feat: extract @trpc/observable into standalone package#7175
feat: extract @trpc/observable into standalone package#7175since-2017-hub wants to merge 10 commits intotrpc:mainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughA new standalone Changes
Sequence Diagram(s)(omitted) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). 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. Comment |
There was a problem hiding this comment.
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 | 🟡 MinorRemove unused
observableimport from the code snippet.The import on line 201 is dead — the subscription uses the
async function*generator pattern and never callsobservable(...). Leaving it in the snippet misleads readers into thinking@trpc/observablemust 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 | 🟡 MinorStale
@trpc/serverattribution 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 topackages/observable/to co-locate it with its source.The
behaviorSubject.tssource was extracted topackages/observable/src/, but this test remains inpackages/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 mixedexport {}blocks.Two export blocks inline
typealongside 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/observableimport with its sibling tRPC imports
@trpc/observableis currently interleaved between two@trpc/serverimport 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/observableimports split the@trpc/serverimport block.The new imports on lines 8–9 are inserted between two
@trpc/serverimports (lines 7 and 10), splitting what was a consecutive group. Consider moving the@trpc/observablepair adjacent to the other third-party tRPC imports or after the@trpc/server/unstable-core-do-not-importimport 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/observableonly 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 topackages/observable/or testing through the backward-compat re-export.This test file lives at
packages/server/src/observable/observable.test.tsbut now imports directly from@trpc/observable. With observable extracted into its own package, tests for the observable primitives logically belong inpackages/observable/. Alternatively, if the intent is to validate the backward-compat re-export, these tests should import from@trpc/server/observableinstead.🤖 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.
@trpc/client
@trpc/next
@trpc/observable
@trpc/react-query
@trpc/server
@trpc/tanstack-react-query
@trpc/upgrade
commit: |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/react-query/test/useSubscription.test.tsx (1)
8-8: Move@trpc/observableand 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.
There was a problem hiding this comment.
🧹 Nitpick comments (2)
packages/observable/src/observable.test.ts (1)
1-1: Prefernode:eventsoverstreamas the source forEventEmitter.Node.js offers the
eventsmodule, which provides theEventEmitterclass. Thestreammodule is for stream-related APIs; while TypeScript's@types/nodemay re-exportEventEmittertransitively throughstream, 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: Avoidvar+eslint-disable; hoistletdeclarations instead.
varis used solely sosubscription1/subscription2are visible outside their respective{}blocks at lines 138–139. The inner blocks and theireslint-disablecomments can be eliminated by hoisting declarations withletat 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.
…ve subscription handling
|
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 |
Closes: #7112
🎯 Changes
Extracts the observable module from
@trpc/serverinto a standalone@trpc/observablepackage, so client-side apps can build custom links using observables without pulling in the entire@trpc/serverdependency.New package:
@trpc/observablepackages/observable/observable,isObservable,observableToPromise,observableToAsyncIterable, operators (map,share,tap,distinctUntilChanged,distinctUntilDeepChanged),behaviorSubject, and all related typesBackward compatibility
@trpc/server/observablere-exports everything from@trpc/observable— existing imports continue to work@trpc/serverlists@trpc/observableas a direct dependencyImport updates
@trpc/client,@trpc/next,@trpc/react-query,@trpc/tanstack-react-query,@trpc/tests, and 6 examples now import from@trpc/observabledirectlypackages/server/src/observable/(replaced by re-exports)Documentation
README.mdfor the new@trpc/observablepackage with usage exampleswww/docs/client/links/overview.mdandwww/docs/server/adapters/fastify.mdto reference@trpc/observable✅ Checklist
Summary by CodeRabbit
New Features
Chores
Refactor
Documentation