Skip to content

feat: extract @trpc/observable into standalone package#7175

Open
since-2017-hub wants to merge 10 commits intotrpc:mainfrom
since-2017-hub:feat-server-link-issue
Open

feat: extract @trpc/observable into standalone package#7175
since-2017-hub wants to merge 10 commits intotrpc:mainfrom
since-2017-hub:feat-server-link-issue

Conversation

@since-2017-hub
Copy link
Copy Markdown

@since-2017-hub since-2017-hub commented Feb 20, 2026

Closes: #7112

🎯 Changes

Extracts the observable module from @trpc/server into a standalone @trpc/observable package, so client-side apps can build custom links using observables without pulling in the entire @trpc/server dependency.

New package: @trpc/observable

  • Lightweight (~8 KB bundled) standalone package under packages/observable/
  • Exports: observable, isObservable, observableToPromise, observableToAsyncIterable, operators (map, share, tap, distinctUntilChanged, distinctUntilDeepChanged), behaviorSubject, and all related types

Backward compatibility

  • @trpc/server/observable re-exports everything from @trpc/observable — existing imports continue to work
  • @trpc/server lists @trpc/observable as a direct dependency

Import updates

  • All internal imports across @trpc/client, @trpc/next, @trpc/react-query, @trpc/tanstack-react-query, @trpc/tests, and 6 examples now import from @trpc/observable directly
  • Removed 4 dead source files from packages/server/src/observable/ (replaced by re-exports)

Documentation

  • Added README.md for the new @trpc/observable package with usage examples
  • Updated www/docs/client/links/overview.md and www/docs/server/adapters/fastify.md to reference @trpc/observable

✅ Checklist

  • I have followed the steps listed in the Contributing guide.
  • If necessary, I have added documentation related to the changes made.
  • I have added or updated the tests related to the changes made.

Summary by CodeRabbit

  • New Features

    • Observable utilities consolidated into a standalone observable package and exposed via a centralized public API.
  • Chores

    • Multiple projects updated to consume the new observable package; dependency declarations added where needed.
  • Refactor

    • Import paths adjusted across packages and examples to use the new observable entry point.
  • Documentation

    • Added README for the observable package with usage examples and export details.

@since-2017-hub since-2017-hub requested review from a team as code owners February 20, 2026 05:06
@vercel
Copy link
Copy Markdown

vercel bot commented Feb 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
next-prisma-starter Error Error Mar 5, 2026 1:42am
og-image Ready Ready Preview, Comment Mar 5, 2026 1:42am

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

A new standalone @trpc/observable package was added and the repository was migrated to import observable utilities and types from @trpc/observable instead of @trpc/server/observable. TypeScript path aliases and package manifests were updated accordingly.

Changes

Cohort / File(s) Summary
New package
packages/observable/...
Adds standalone @trpc/observable package: source, tests, README, package.json, tsconfigs, tsdown/turbo config, and build/test infra.
TS alias
tsconfig.json
Adds path aliases mapping @trpc/observable./packages/observable/src (and wildcard).
Package manifests
packages/*/package.json, examples/*/package.json, packages/tests/package.json
Adds @trpc/observable dependency entries across multiple packages and example projects.
Client code & links
packages/client/src/..., packages/next/src/..., packages/react-query/src/..., packages/tanstack-react-query/src/...
Updated imports of observable utilities/types (e.g., observable, tap, Unsubscribable, behaviorSubject, share) to @trpc/observable.
Server exports & core
packages/server/src/observable/index.ts, packages/server/src/...unstable-core-do-not-import...
Reworked server observable re-exports to delegate several types/utilities to @trpc/observable; updated internal imports to use the new package.
Tests
packages/tests/server/**, packages/client/src/__tests__/**, packages/react-query/test/**, packages/observable/*.{test,vitest.config.ts}
Updated numerous test imports to @trpc/observable; adds observable package tests and vitest config re-export.
Examples
examples/.../src/...
Example source files updated to import observables from @trpc/observable; example package.json entries updated.
Implementation tweak
packages/observable/src/observable.ts
Internalized a Result discriminated-union type (removed external import); observable implementation surfaced via new package.
Docs
packages/observable/README.md, www/docs/...
Adds README for @trpc/observable; updates docs snippets to import from new package; removes an unused import in a Fastify example.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Suggested labels

♻️ autoupdate

Suggested reviewers

  • KATT
  • Nick-Lucas

Poem

🐰 A rabbit hops through code with glee,

Split the observables, set them free,
A tiny package, tidy and bright,
Imports aligned, everything right,
Hooray for clean hops — and a carrot tonight! 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: extract @trpc/observable into standalone package' clearly and concisely describes the main objective: extracting the observable module into a new standalone package.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The PR description follows the template structure with all required sections completed: issue reference, clear description of changes, checklist items marked as complete.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
www/docs/server/adapters/fastify.md (1)

199-213: ⚠️ Potential issue | 🟡 Minor

Remove unused observable import from the code snippet.

The import on line 201 is dead — the subscription uses the async function* generator pattern and never calls observable(...). Leaving it in the snippet misleads readers into thinking @trpc/observable must be imported for async-generator subscriptions, and implies an unnecessary install step.

📝 Proposed fix
 ```ts title='router.ts'
 import { initTRPC } from '@trpc/server';
-import { observable } from '@trpc/observable';
 
 const t = initTRPC.create();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@www/docs/server/adapters/fastify.md` around lines 199 - 213, The snippet
imports observable from '@trpc/observable' but never uses it; remove the unused
import statement (the "observable" import) from the router.ts example so the top
of the file only imports initTRPC, leaving the existing t = initTRPC.create()
and the appRouter/randomNumber async generator subscription unchanged.
www/docs/client/links/overview.md (1)

47-47: ⚠️ Potential issue | 🟡 Minor

Stale @trpc/server attribution in prose — update to @trpc/observable.

Line 47 still says "the observable function provided by @trpc/server" while the adjacent code snippet on line 53 was just updated to import from @trpc/observable. The description should be updated to match.

📝 Proposed fix
-3. The function in step 2 returns a final function that returns the `observable` function provided by `@trpc/server`. The `observable` accepts a function...
+3. The function in step 2 returns a final function that returns the `observable` function provided by `@trpc/observable`. The `observable` accepts a function...
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@www/docs/client/links/overview.md` at line 47, The prose incorrectly
attributes the observable function to `@trpc/server`; update the sentence to
reference `@trpc/observable` instead. Edit the paragraph mentioning "the
observable function provided by `@trpc/server`" to read "the observable function
provided by `@trpc/observable`", keeping the rest of the explanation (including
the discussion of the observable callback that receives an observer and the
example use of next(op)) unchanged so it matches the adjacent code snippet and
imports.
🧹 Nitpick comments (7)
packages/server/src/observable/behaviorSubject.test.ts (1)

1-1: Move this test to packages/observable/ to co-locate it with its source.

The behaviorSubject.ts source was extracted to packages/observable/src/, but this test remains in packages/server/src/observable/. The test has no server-specific dependencies and tests only observable functionality—it should be placed alongside its source in the observable package for clarity of ownership and easier maintenance.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/server/src/observable/behaviorSubject.test.ts` at line 1, The test
file behaviorSubject.test.ts lives outside the observable package; move
behaviorSubject.test.ts into the packages/observable test folder so it’s
co-located with the source that exports behaviorSubject, update any import paths
if they become relative (the import of behaviorSubject should still reference
the module that exports it), and ensure the observable package test
runner/config (jest/tsconfig or workspace test globs) includes the new file and
no longer expects it under packages/server so CI still picks it up.
packages/observable/src/index.ts (1)

1-7: Separate type re-exports from value re-exports in both mixed export {} blocks.

Two export blocks inline type alongside values — this is the export-side equivalent of the "Separate type imports from value imports" guideline.

♻️ Proposed fix
-export {
-  isObservable,
-  observable,
-  observableToAsyncIterable,
-  observableToPromise,
-  type inferObservableValue,
-} from './observable';
+export {
+  isObservable,
+  observable,
+  observableToAsyncIterable,
+  observableToPromise,
+} from './observable';
+export type { inferObservableValue } from './observable';
-export {
-  behaviorSubject,
-  type BehaviorSubject,
-  type ReadonlyBehaviorSubject,
-} from './behaviorSubject';
+export { behaviorSubject } from './behaviorSubject';
+export type { BehaviorSubject, ReadonlyBehaviorSubject } from './behaviorSubject';

As per coding guidelines: "Separate type imports from value imports" — the same convention applies to re-exports.

Also applies to: 25-29

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/observable/src/index.ts` around lines 1 - 7, The current export
block mixes value exports (isObservable, observable, observableToAsyncIterable,
observableToPromise) with a type export (inferObservableValue); split them into
separate re-exports by leaving the value exports in the existing export { ... }
from './observable' and adding a separate type-only re-export using export type
{ inferObservableValue } from './observable'; apply the same pattern wherever
other mixed export blocks occur (the other mixed block mentioned in the review)
to ensure all type re-exports are separated from value re-exports.
packages/client/src/links/wsLink/wsClient/requestManager.ts (1)

1-6: Nit: group the new @trpc/observable import with its sibling tRPC imports

@trpc/observable is currently interleaved between two @trpc/server import statements. Consider consolidating:

♻️ Suggested reorder
 import type { AnyTRPCRouter, inferRouterError } from '@trpc/server';
+import type { Observer } from '@trpc/observable';
 import type {
   TRPCClientOutgoingMessage,
   TRPCResponseMessage,
 } from '@trpc/server/unstable-core-do-not-import';
-import type { Observer } from '@trpc/observable';
 import type { TRPCClientError } from '../../../TRPCClientError';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/client/src/links/wsLink/wsClient/requestManager.ts` around lines 1 -
6, The imports are misordered: the Observer import from '@trpc/observable' is
interleaved between two '@trpc/server' imports; consolidate related tRPC imports
by grouping AnyTRPCRouter and inferRouterError together with Observer, and keep
TRPCClientOutgoingMessage and TRPCResponseMessage (from
'@trpc/server/unstable-core-do-not-import') separate; reorder the import
statements so the '@trpc/server' and '@trpc/observable' symbols (AnyTRPCRouter,
inferRouterError, Observer) appear together to improve consistency and
readability.
packages/tests/server/smoke.test.ts (1)

8-10: Nit: @trpc/observable imports split the @trpc/server import block.

The new imports on lines 8–9 are inserted between two @trpc/server imports (lines 7 and 10), splitting what was a consecutive group. Consider moving the @trpc/observable pair adjacent to the other third-party tRPC imports or after the @trpc/server/unstable-core-do-not-import import for cleaner grouping.

♻️ Suggested ordering
 import type { inferProcedureOutput } from '@trpc/server';
 import { initTRPC } from '@trpc/server';
+import { lazy } from '@trpc/server/unstable-core-do-not-import';
 import type { Unsubscribable } from '@trpc/observable';
 import { observable } from '@trpc/observable';
-import { lazy } from '@trpc/server/unstable-core-do-not-import';
 import { z } from 'zod';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/tests/server/smoke.test.ts` around lines 8 - 10, The three imports
Unsubscribable and observable from '@trpc/observable' and lazy from
'@trpc/server/unstable-core-do-not-import' are splitting the existing
'@trpc/server' import group; reorder imports so all `@trpc/`* imports are
contiguous (e.g., move the '@trpc/observable' import block adjacent to the other
`@trpc/server` imports or place it directly after the lazy import) to keep
third-party tRPC imports grouped together.
tsconfig.json (1)

12-12: Missing "@trpc/observable/*" wildcard path alias for consistency.

Every other @trpc/* package has both a direct alias and a wildcard alias. @trpc/observable only has the direct mapping. While no subpath imports are used today, the inconsistency could silently break subpath resolution during development if any are added.

🔧 Suggested addition
       "@trpc/observable": ["./packages/observable/src"],
+      "@trpc/observable/*": ["./packages/observable/src/*"],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tsconfig.json` at line 12, The paths mapping for the "@trpc/observable"
package is missing a wildcard alias which makes it inconsistent with other
"@trpc/*" entries and could break subpath imports; update the tsconfig "paths"
to add the wildcard entry "@trpc/observable/*" pointing to the source directory
(e.g., map "@trpc/observable/*" to "./packages/observable/src/*") so both direct
("@trpc/observable") and wildcard ("@trpc/observable/*") resolutions work for
functions/modules that import subpaths.
packages/server/src/observable/observable.test.ts (1)

2-7: Consider moving these tests to packages/observable/ or testing through the backward-compat re-export.

This test file lives at packages/server/src/observable/observable.test.ts but now imports directly from @trpc/observable. With observable extracted into its own package, tests for the observable primitives logically belong in packages/observable/. Alternatively, if the intent is to validate the backward-compat re-export, these tests should import from @trpc/server/observable instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/server/src/observable/observable.test.ts` around lines 2 - 7, Tests
import observable primitives (observable, observableToAsyncIterable, share, tap)
directly from `@trpc/observable` but live in packages/server; either move this
test file into packages/observable/ to colocate tests with the extracted package
and keep the current imports, or if you intend to verify the backward-compat
re-export, change the imports to come from `@trpc/server/observable` so the test
validates the server package’s re-export; update the test module location or
imports accordingly and run the test suite to ensure imports resolve.
packages/client/src/links/wsLink/wsClient/wsClient.ts (1)

2-3: Optional: group value imports after all type imports.

The value import on line 3 is currently sandwiched between type imports (lines 1–2 and lines 4–10), violating the "Separate type imports from value imports" coding guideline.

♻️ Suggested reordering
 import type { AnyTRPCRouter } from '@trpc/server';
 import type { BehaviorSubject } from '@trpc/observable';
-import { behaviorSubject, observable } from '@trpc/observable';
 import type {
   CombinedDataTransformer,
   TRPCClientIncomingMessage,
   TRPCClientIncomingRequest,
   TRPCClientOutgoingMessage,
   TRPCResponseMessage,
 } from '@trpc/server/unstable-core-do-not-import';
+import { behaviorSubject, observable } from '@trpc/observable';
 import {
   run,
   sleep,
   transformResult,
 } from '@trpc/server/unstable-core-do-not-import';

As per coding guidelines: "Separate type imports from value imports."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/client/src/links/wsLink/wsClient/wsClient.ts` around lines 2 - 3,
The import order mixes type and value imports: move the value imports
(behaviorSubject, observable) so all type-only imports (e.g., BehaviorSubject
and any other "import type" lines) appear first and then import the values;
adjust the import statements in wsClient.ts to group "import type {
BehaviorSubject } from '@trpc/observable';" with other type imports and place
"import { behaviorSubject, observable } from '@trpc/observable';" after them to
comply with the "Separate type imports from value imports" guideline.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/observable/README.md`:
- Around line 33-38: The README exports list omits the public API function
inferObservableValue declared in src/index.ts; update the Exports section to
include `inferObservableValue` alongside the other entries (e.g., after
`observableToAsyncIterable` or wherever alphabetically appropriate) so the
documented public API matches the actual exports in src/index.ts and users can
discover inferObservableValue.

---

Outside diff comments:
In `@www/docs/client/links/overview.md`:
- Line 47: The prose incorrectly attributes the observable function to
`@trpc/server`; update the sentence to reference `@trpc/observable` instead. Edit
the paragraph mentioning "the observable function provided by `@trpc/server`" to
read "the observable function provided by `@trpc/observable`", keeping the rest of
the explanation (including the discussion of the observable callback that
receives an observer and the example use of next(op)) unchanged so it matches
the adjacent code snippet and imports.

In `@www/docs/server/adapters/fastify.md`:
- Around line 199-213: The snippet imports observable from '@trpc/observable'
but never uses it; remove the unused import statement (the "observable" import)
from the router.ts example so the top of the file only imports initTRPC, leaving
the existing t = initTRPC.create() and the appRouter/randomNumber async
generator subscription unchanged.

---

Nitpick comments:
In `@packages/client/src/links/wsLink/wsClient/requestManager.ts`:
- Around line 1-6: The imports are misordered: the Observer import from
'@trpc/observable' is interleaved between two '@trpc/server' imports;
consolidate related tRPC imports by grouping AnyTRPCRouter and inferRouterError
together with Observer, and keep TRPCClientOutgoingMessage and
TRPCResponseMessage (from '@trpc/server/unstable-core-do-not-import') separate;
reorder the import statements so the '@trpc/server' and '@trpc/observable'
symbols (AnyTRPCRouter, inferRouterError, Observer) appear together to improve
consistency and readability.

In `@packages/client/src/links/wsLink/wsClient/wsClient.ts`:
- Around line 2-3: The import order mixes type and value imports: move the value
imports (behaviorSubject, observable) so all type-only imports (e.g.,
BehaviorSubject and any other "import type" lines) appear first and then import
the values; adjust the import statements in wsClient.ts to group "import type {
BehaviorSubject } from '@trpc/observable';" with other type imports and place
"import { behaviorSubject, observable } from '@trpc/observable';" after them to
comply with the "Separate type imports from value imports" guideline.

In `@packages/observable/src/index.ts`:
- Around line 1-7: The current export block mixes value exports (isObservable,
observable, observableToAsyncIterable, observableToPromise) with a type export
(inferObservableValue); split them into separate re-exports by leaving the value
exports in the existing export { ... } from './observable' and adding a separate
type-only re-export using export type { inferObservableValue } from
'./observable'; apply the same pattern wherever other mixed export blocks occur
(the other mixed block mentioned in the review) to ensure all type re-exports
are separated from value re-exports.

In `@packages/server/src/observable/behaviorSubject.test.ts`:
- Line 1: The test file behaviorSubject.test.ts lives outside the observable
package; move behaviorSubject.test.ts into the packages/observable test folder
so it’s co-located with the source that exports behaviorSubject, update any
import paths if they become relative (the import of behaviorSubject should still
reference the module that exports it), and ensure the observable package test
runner/config (jest/tsconfig or workspace test globs) includes the new file and
no longer expects it under packages/server so CI still picks it up.

In `@packages/server/src/observable/observable.test.ts`:
- Around line 2-7: Tests import observable primitives (observable,
observableToAsyncIterable, share, tap) directly from `@trpc/observable` but live
in packages/server; either move this test file into packages/observable/ to
colocate tests with the extracted package and keep the current imports, or if
you intend to verify the backward-compat re-export, change the imports to come
from `@trpc/server/observable` so the test validates the server package’s
re-export; update the test module location or imports accordingly and run the
test suite to ensure imports resolve.

In `@packages/tests/server/smoke.test.ts`:
- Around line 8-10: The three imports Unsubscribable and observable from
'@trpc/observable' and lazy from '@trpc/server/unstable-core-do-not-import' are
splitting the existing '@trpc/server' import group; reorder imports so all
`@trpc/`* imports are contiguous (e.g., move the '@trpc/observable' import block
adjacent to the other `@trpc/server` imports or place it directly after the lazy
import) to keep third-party tRPC imports grouped together.

In `@tsconfig.json`:
- Line 12: The paths mapping for the "@trpc/observable" package is missing a
wildcard alias which makes it inconsistent with other "@trpc/*" entries and
could break subpath imports; update the tsconfig "paths" to add the wildcard
entry "@trpc/observable/*" pointing to the source directory (e.g., map
"@trpc/observable/*" to "./packages/observable/src/*") so both direct
("@trpc/observable") and wildcard ("@trpc/observable/*") resolutions work for
functions/modules that import subpaths.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Feb 20, 2026

Open in StackBlitz

@trpc/client

npm i https://pkg.pr.new/trpc/trpc/@trpc/client@7175

@trpc/next

npm i https://pkg.pr.new/trpc/trpc/@trpc/next@7175

@trpc/observable

npm i https://pkg.pr.new/trpc/trpc/@trpc/observable@7175

@trpc/react-query

npm i https://pkg.pr.new/trpc/trpc/@trpc/react-query@7175

@trpc/server

npm i https://pkg.pr.new/trpc/trpc/@trpc/server@7175

@trpc/tanstack-react-query

npm i https://pkg.pr.new/trpc/trpc/@trpc/tanstack-react-query@7175

@trpc/upgrade

npm i https://pkg.pr.new/trpc/trpc/@trpc/upgrade@7175

commit: 15f8cb1

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/react-query/test/useSubscription.test.tsx (1)

8-8: Move @trpc/observable and other tRPC imports before third-party imports to comply with import order guidelines.

Lines 8–10 import from @trpc/* packages but are placed after @testing-library/react (third-party, line 7). Per the coding guidelines, the order must be: test helpers → tRPC imports → third-party → relative. Consolidate all tRPC imports together before the third-party imports.

♻️ Suggested reorder
 import { getServerAndReactClient } from './__reactHelpers';
 import { IterableEventEmitter } from '@trpc/server/__tests__/iterableEventEmitter';
 import {
   ignoreErrors,
   suppressLogsUntil,
 } from '@trpc/server/__tests__/suppressLogs';
+import { observable } from '@trpc/observable';
+import type { TRPCSubscriptionResult } from '@trpc/react-query/shared';
+import { initTRPC } from '@trpc/server';
 import { fireEvent, render } from '@testing-library/react';
-import { observable } from '@trpc/observable';
-import type { TRPCSubscriptionResult } from '@trpc/react-query/shared';
-import { initTRPC } from '@trpc/server';
 import { konn } from 'konn';
 import React, { useState } from 'react';
 import { z } from 'zod';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-query/test/useSubscription.test.tsx` at line 8, Move the tRPC
imports (e.g., the observable import from '@trpc/observable' and any other
'@trpc/*' imports) so they appear before third-party imports like
'@testing-library/react' to match the required import order (test helpers → tRPC
imports → third-party → relative); locate the current import statement for
observable and any other '@trpc' imports in useSubscription.test.tsx and reorder
them to be grouped together immediately after test helper imports and before
other third-party imports.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/react-query/test/useSubscription.test.tsx`:
- Line 8: Move the tRPC imports (e.g., the observable import from
'@trpc/observable' and any other '@trpc/*' imports) so they appear before
third-party imports like '@testing-library/react' to match the required import
order (test helpers → tRPC imports → third-party → relative); locate the current
import statement for observable and any other '@trpc' imports in
useSubscription.test.tsx and reorder them to be grouped together immediately
after test helper imports and before other third-party imports.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
packages/observable/src/observable.test.ts (1)

1-1: Prefer node:events over stream as the source for EventEmitter.

Node.js offers the events module, which provides the EventEmitter class. The stream module is for stream-related APIs; while TypeScript's @types/node may re-export EventEmitter transitively through stream, the canonical and idiomatic import is from 'node:events' (or 'events'), as shown in the official docs.

🔧 Suggested fix
-import { EventEmitter } from 'stream';
+import { EventEmitter } from 'node:events';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/observable/src/observable.test.ts` at line 1, Replace the
non-idiomatic import of EventEmitter from 'stream' with the canonical source
('node:events' or 'events'); locate the import statement that reads "import {
EventEmitter } from 'stream'" in observable.test.ts and change it to import
EventEmitter from 'node:events' (or 'events') so tests use the proper
EventEmitter symbol.
packages/observable/src/operators.test.ts (1)

110-111: Avoid var + eslint-disable; hoist let declarations instead.

var is used solely so subscription1/subscription2 are visible outside their respective {} blocks at lines 138–139. The inner blocks and their eslint-disable comments can be eliminated by hoisting declarations with let at the top of the test, or by dropping the artificial block scoping and using distinct local variable names:

♻️ Suggested refactor
-  {
-    const next = vi.fn();
-    const error = vi.fn();
-    const complete = vi.fn();
-
-    // eslint-disable-next-line no-var
-    var subscription1 = obs.subscribe({
-      next,
-      error,
-      complete,
-    });
-    expect(next.mock.calls).toHaveLength(1);
-    expect(complete.mock.calls).toHaveLength(0);
-    expect(error.mock.calls).toHaveLength(0);
-    expect(next.mock.calls[0]![0]).toBe(1);
-  }
-
-  {
-    // subscribe again - it's shared so should not propagate any results
-    const next = vi.fn();
-    const error = vi.fn();
-    const complete = vi.fn();
-    // eslint-disable-next-line no-var
-    var subscription2 = obs.subscribe({
-      next,
-      error,
-      complete,
-    });
-    expect(next.mock.calls).toHaveLength(0);
-    expect(complete.mock.calls).toHaveLength(0);
-    expect(error.mock.calls).toHaveLength(0);
-  }
+  const next1 = vi.fn();
+  const error1 = vi.fn();
+  const complete1 = vi.fn();
+  const subscription1 = obs.subscribe({ next: next1, error: error1, complete: complete1 });
+  expect(next1.mock.calls).toHaveLength(1);
+  expect(complete1.mock.calls).toHaveLength(0);
+  expect(error1.mock.calls).toHaveLength(0);
+  expect(next1.mock.calls[0]![0]).toBe(1);
+
+  // subscribe again - it's shared so should not propagate any results
+  const next2 = vi.fn();
+  const error2 = vi.fn();
+  const complete2 = vi.fn();
+  const subscription2 = obs.subscribe({ next: next2, error: error2, complete: complete2 });
+  expect(next2.mock.calls).toHaveLength(0);
+  expect(complete2.mock.calls).toHaveLength(0);
+  expect(error2.mock.calls).toHaveLength(0);

Also applies to: 127-128

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/observable/src/operators.test.ts` around lines 110 - 111, Replace
the use of "var" and the eslint-disable comments by hoisting subscription1 and
subscription2 as let declarations at the top of the test scope (before any inner
blocks), then remove the artificial inner blocks and their eslint-disable lines
so the calls to obs.subscribe(...) can assign into those hoisted lets; locate
the occurrences around the obs.subscribe calls referencing subscription1 and
subscription2 and change their declarations from var to let and eliminate the
block scoping.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/observable/src/observable.test.ts`:
- Line 1: Replace the non-idiomatic import of EventEmitter from 'stream' with
the canonical source ('node:events' or 'events'); locate the import statement
that reads "import { EventEmitter } from 'stream'" in observable.test.ts and
change it to import EventEmitter from 'node:events' (or 'events') so tests use
the proper EventEmitter symbol.

In `@packages/observable/src/operators.test.ts`:
- Around line 110-111: Replace the use of "var" and the eslint-disable comments
by hoisting subscription1 and subscription2 as let declarations at the top of
the test scope (before any inner blocks), then remove the artificial inner
blocks and their eslint-disable lines so the calls to obs.subscribe(...) can
assign into those hoisted lets; locate the occurrences around the obs.subscribe
calls referencing subscription1 and subscription2 and change their declarations
from var to let and eliminate the block scoping.

@Nick-Lucas
Copy link
Copy Markdown
Contributor

Sorry for the delay, has been a busy week and Alex is also detained with life stuff!

I've left a comment on the issue: #7112 (comment)

This is a nice idea, but we probably don't want to encourage use of this outside of tRPC, and I'm not convinced that the current approach actually inflates bundle sizes at all

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: sever link to @trpc/server in @trpc/client

3 participants