Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds first-class Fastify support and documentation: new @orpc/standard-server-fastify package (request/response adapters), Fastify handler and RPCHandler in @orpc/server, OpenAPI Fastify adapter, docs/examples updated, Nest integration adjusted, tests and package export entries added. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client
participant Fastify
participant FastifyHandler
participant Interceptor
participant StandardHandler
participant ResponseSender as sendStandardResponse
Client->>Fastify: HTTP request
Fastify->>FastifyHandler: handle(req, reply, { prefix, ... })
FastifyHandler->>Interceptor: intercept({ request, reply, sendStandardResponseOptions }, next)
Interceptor->>FastifyHandler: next()
FastifyHandler->>StandardHandler: handle(standardRequest, options)
alt matched
StandardHandler-->>FastifyHandler: { matched: true, response }
FastifyHandler->>ResponseSender: sendStandardResponse(reply, response, opts)
ResponseSender->>Fastify: set headers + send(body)
else not matched
StandardHandler-->>FastifyHandler: { matched: false }
FastifyHandler-->>Fastify: ({ matched: false })
end
Fastify-->Client: HTTP response
sequenceDiagram
autonumber
participant FastifyReq as FastifyRequest
participant toStandardLazyRequest
participant BodyResolver
FastifyReq->>toStandardLazyRequest: (req, reply)
toStandardLazyRequest->>BodyResolver: create lazy body getter (signal)
alt req.body present
BodyResolver-->>toStandardLazyRequest: return req.body
else no parsed body
BodyResolver->>BodyResolver: call toStandardBody(req.raw, { signal })
BodyResolver-->>toStandardLazyRequest: parsed body
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Areas to focus review on:
Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
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 |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
More templates
@orpc/arktype
@orpc/client
@orpc/contract
@orpc/experimental-durable-iterator
@orpc/hey-api
@orpc/interop
@orpc/json-schema
@orpc/nest
@orpc/openapi
@orpc/openapi-client
@orpc/otel
@orpc/experimental-publisher
@orpc/react
@orpc/react-query
@orpc/experimental-react-swr
@orpc/server
@orpc/shared
@orpc/solid-query
@orpc/standard-server
@orpc/standard-server-aws-lambda
@orpc/standard-server-fastify
@orpc/standard-server-fetch
@orpc/standard-server-node
@orpc/standard-server-peer
@orpc/svelte-query
@orpc/tanstack-query
@orpc/trpc
@orpc/valibot
@orpc/vue-colada
@orpc/vue-query
@orpc/zod
commit: |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (16)
packages/standard-server-fastify/src/index.test.ts (1)
1-3: Consider adding functional tests beyond export verification.This test only verifies that
toStandardLazyRequestis exported, but doesn't validate its behavior, edge cases, or integration with Fastify request/reply objects.Consider adding tests that:
- Verify request method, URL, and headers are correctly mapped
- Test body resolution with both parsed and raw bodies
- Validate abort signal propagation
- Check error handling in body parsing
packages/openapi/src/adapters/fastify/index.test.ts (1)
1-3: Consider adding functional tests for OpenAPIHandler.Similar to the standard-server-fastify tests, this only verifies the export exists without testing actual OpenAPIHandler functionality for Fastify.
Consider adding integration tests that verify:
- OpenAPI request handling with Fastify request/reply objects
- Response serialization and status code handling
- Error responses and validation failures
packages/server/src/adapters/fastify/index.test.ts (1)
1-3: Consider adding functional tests for RPCHandler.This test only verifies the
RPCHandlerexport without testing its integration with Fastify's request/reply handling or RPC protocol implementation.Consider adding tests that verify:
- RPC request handling with Fastify-specific features
- Proper context propagation from Fastify request/reply
- Error handling and response serialization
- Integration with Fastify plugins and middleware
packages/openapi/src/adapters/fastify/openapi-handler.test.ts (1)
6-21: Consider expanding test coverage.The test validates basic functionality, but the OpenAPI handler likely supports additional features worth testing:
- Error handling and validation failures
- Different HTTP methods and content types
- OpenAPI-specific behaviors (schema validation, serialization)
- Prefix edge cases (empty prefix, trailing slashes)
- Non-matching routes
packages/server/src/adapters/fastify/rpc-handler.test.ts (1)
6-38: Consider expanding test coverage.While the current tests validate core functionality, additional test cases would strengthen confidence:
- POST requests to demonstrate non-GET method handling
- Error scenarios (invalid routes, malformed requests)
- Plugin configuration options (disabling StrictGetMethodPlugin)
- Multiple prefix configurations
- Content-type handling
packages/standard-server-fastify/README.md (5)
5-5: Remove empty H1 or give it a title.Empty
<h1></h1>hurts accessibility/SEO.-<h1></h1> +<!-- Removed: empty heading -->
46-49: Make the docs link descriptive (MD059).Avoid “here” link text; use “oRPC Documentation”.
-You can find the full documentation [here](https://orpc.unnoq.com). +See the [oRPC Documentation](https://orpc.unnoq.com).
73-76: Add alt text to the sponsors image (MD045).- <img src='https://cdn.jsdelivr.net/gh/unnoq/unnoq/sponsors.svg'/> + <img src='https://cdn.jsdelivr.net/gh/unnoq/unnoq/sponsors.svg' alt="oRPC sponsors"/>
44-44: Wording nit: “Extensibility” reads better than “Extendability”.-- **🔌 Extendability**: Easily extend functionality with plugins, middleware, and interceptors. +- **🔌 Extensibility**: Easily extend functionality with plugins, middleware, and interceptors.
25-25: Style nit: “Type‑safe” is more standard than “Typesafe”.-<h3 align="center">Typesafe APIs Made Simple 🪄</h3> +<h3 align="center">Type‑safe APIs Made Simple 🪄</h3>packages/nest/src/implement.ts (1)
123-126: Compute framework once and use a consistent branch.Branching on
'raw' in reqand later'raw' in rescan diverge. Determine Fastify once and reuse to avoid mismatches and tighten the guard.- const standardRequest = 'raw' in req - ? StandardServerFastify.toStandardLazyRequest(req, res as FastifyReply) - : StandardServerNode.toStandardLazyRequest(req, res as Response) + const isFastify = typeof (req as any)?.raw?.method === 'string' && typeof (res as any)?.raw?.setHeader === 'function' + const standardRequest = isFastify + ? StandardServerFastify.toStandardLazyRequest(req as FastifyRequest, res as FastifyReply) + : StandardServerNode.toStandardLazyRequest(req as Request, res as Response) @@ - if ('raw' in res) { + if (isFastify) { await StandardServerFastify.sendStandardResponse(res, standardResponse, this.config) } else { await StandardServerNode.sendStandardResponse(res, standardResponse, this.config) }Also applies to: 156-161
packages/standard-server-fastify/src/request.test.ts (2)
40-41: Avoid relying on raw.headers identity; assert Fastify headers instead.
req.headersis what the adapter returns; identity withraw.headersisn’t guaranteed.- expect(standardRequest.headers).toBe(fastifyReq.raw.headers) + expect(standardRequest.headers).toBe(fastifyReq.headers) + // or toStrictEqual if identity is not guaranteed by Fastify: + // expect(standardRequest.headers).toStrictEqual(fastifyReq.headers)
72-78: FormData deep equality is brittle; compare entries and assert fallback parser ran.Strengthen the assertion and verify
toStandardBodywas used.- const expectedBody = new FormData() - expectedBody.append('foo', 'bar') - expect(standardBody).toEqual(expectedBody) + // ensure fallback parser was used + expect(toStandardBodySpy).toHaveBeenCalledTimes(1) + // compare entries to avoid implementation-specific equality issues + const entries = Array.from((standardBody as FormData).entries()) + expect(entries).toEqual([['foo', 'bar']])packages/standard-server-fastify/src/response.ts (1)
24-32: Consider simplifying the conditional body sending logic.The
else ifbranch for strings (lines 27-29) and the finalelsebranch (lines 30-32) perform identical operations since Fastify'sreply.send()handles both strings and Readable streams. This can be simplified for better maintainability.Apply this diff to simplify:
if (resBody === undefined) { reply.send() } - else if (typeof resBody === 'string') { - reply.send(resBody) - } else { reply.send(resBody) }apps/content/docs/adapters/fastify.md (1)
10-12: Clarify the warning about content-type parsing.The warning states that "oRPC will use the parsed body when available," but the example immediately below (lines 31-35) shows disabling Fastify's parsing by returning
undefined. This creates potential confusion about when and why developers should disable parsing versus letting Fastify handle it.Consider expanding the warning to clarify the tradeoff:
::: warning -Fastify parses common request content types by default. oRPC will use the parsed body when available. +Fastify parses common request content types by default. To fully utilize oRPC features (such as streaming inputs), you can disable Fastify's content parsing for oRPC routes by using a wildcard content-type parser that returns `undefined`, allowing oRPC to handle the raw request body. See the example below. :::packages/server/src/adapters/fastify/rpc-handler.ts (1)
25-32: Avoid mutating the input options object.The constructor directly mutates the
optionsparameter (lines 27-28), which can lead to unexpected behavior if the user reuses the same options object for multiple handler instances or keeps a reference to it.Apply this diff to avoid mutation:
constructor(router: Router<any, T>, options: NoInfer<RPCHandlerOptions<T>> = {}) { - if (options.strictGetMethodPluginEnabled ?? true) { - options.plugins ??= [] - options.plugins.push(new StrictGetMethodPlugin()) - } - - super(new StandardRPCHandler(router, options), options) + const handlerOptions = { + ...options, + plugins: options.strictGetMethodPluginEnabled ?? true + ? [...(options.plugins ?? []), new StrictGetMethodPlugin()] + : options.plugins, + } + + super(new StandardRPCHandler(router, handlerOptions), handlerOptions) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (30)
apps/content/docs/adapters/fastify.md(1 hunks)apps/content/docs/adapters/http.md(2 hunks)apps/content/docs/openapi/integrations/implement-contract-in-nest.md(0 hunks)apps/content/learn-and-contribute/overview.md(1 hunks)packages/nest/package.json(1 hunks)packages/nest/src/implement.test.ts(2 hunks)packages/nest/src/implement.ts(3 hunks)packages/openapi/package.json(3 hunks)packages/openapi/src/adapters/fastify/index.test.ts(1 hunks)packages/openapi/src/adapters/fastify/index.ts(1 hunks)packages/openapi/src/adapters/fastify/openapi-handler.test.ts(1 hunks)packages/openapi/src/adapters/fastify/openapi-handler.ts(1 hunks)packages/server/package.json(4 hunks)packages/server/src/adapters/fastify/handler.test-d.ts(1 hunks)packages/server/src/adapters/fastify/handler.test.ts(1 hunks)packages/server/src/adapters/fastify/handler.ts(1 hunks)packages/server/src/adapters/fastify/index.test.ts(1 hunks)packages/server/src/adapters/fastify/index.ts(1 hunks)packages/server/src/adapters/fastify/rpc-handler.test.ts(1 hunks)packages/server/src/adapters/fastify/rpc-handler.ts(1 hunks)packages/standard-server-fastify/.gitignore(1 hunks)packages/standard-server-fastify/README.md(1 hunks)packages/standard-server-fastify/package.json(1 hunks)packages/standard-server-fastify/src/index.test.ts(1 hunks)packages/standard-server-fastify/src/index.ts(1 hunks)packages/standard-server-fastify/src/request.test.ts(1 hunks)packages/standard-server-fastify/src/request.ts(1 hunks)packages/standard-server-fastify/src/response.test.ts(1 hunks)packages/standard-server-fastify/src/response.ts(1 hunks)packages/standard-server-fastify/tsconfig.json(1 hunks)
💤 Files with no reviewable changes (1)
- apps/content/docs/openapi/integrations/implement-contract-in-nest.md
🧰 Additional context used
🧬 Code graph analysis (12)
packages/standard-server-fastify/src/request.ts (3)
packages/standard-server/src/types.ts (1)
StandardLazyRequest(26-32)packages/standard-server-node/src/method.ts (1)
toStandardMethod(1-3)packages/shared/src/function.ts (1)
once(3-16)
packages/openapi/src/adapters/fastify/openapi-handler.test.ts (2)
packages/server/src/builder.ts (2)
handler(273-280)os(336-352)packages/openapi/src/adapters/fastify/openapi-handler.ts (1)
OpenAPIHandler(16-20)
packages/openapi/src/adapters/fastify/openapi-handler.ts (4)
packages/server/src/context.ts (1)
Context(1-1)packages/server/src/adapters/fastify/handler.ts (2)
FastifyHandlerOptions(18-20)FastifyHandler(22-62)packages/openapi/src/adapters/standard/openapi-handler.ts (2)
StandardOpenAPIHandlerOptions(10-12)StandardOpenAPIHandler(14-24)packages/server/src/router.ts (1)
Router(12-17)
packages/server/src/adapters/fastify/rpc-handler.ts (5)
packages/server/src/context.ts (1)
Context(1-1)packages/server/src/adapters/fastify/handler.ts (2)
FastifyHandlerOptions(18-20)FastifyHandler(22-62)packages/server/src/adapters/standard/rpc-handler.ts (2)
StandardRPCHandlerOptions(11-13)StandardRPCHandler(15-24)packages/server/src/router.ts (1)
Router(12-17)packages/server/src/plugins/strict-get-method.ts (1)
StrictGetMethodPlugin(24-66)
packages/server/src/adapters/fastify/handler.test-d.ts (1)
packages/server/src/adapters/fastify/handler.ts (1)
FastifyHandler(22-62)
packages/standard-server-fastify/src/response.test.ts (1)
packages/standard-server-fastify/src/response.ts (1)
sendStandardResponse(8-34)
packages/server/src/adapters/fastify/handler.ts (7)
packages/server/src/context.ts (1)
Context(1-1)packages/server/src/adapters/standard/handler.ts (2)
StandardHandleOptions(16-19)StandardHandler(50-183)packages/standard-server-fastify/src/response.ts (2)
SendStandardResponseOptions(6-6)sendStandardResponse(8-34)packages/shared/src/interceptor.ts (1)
Interceptor(13-16)packages/shared/src/array.ts (1)
toArray(1-3)packages/shared/src/args.ts (2)
MaybeOptionalOptions(1-3)resolveMaybeOptionalOptions(5-7)packages/server/src/adapters/standard/utils.ts (2)
FriendlyStandardHandleOptions(4-6)resolveFriendlyStandardHandleOptions(8-13)
packages/standard-server-fastify/src/response.ts (2)
packages/standard-server-node/src/body.ts (2)
ToNodeHttpBodyOptions(53-53)toNodeHttpBody(60-104)packages/standard-server/src/types.ts (2)
StandardResponse(34-41)StandardHeaders(1-3)
packages/server/src/adapters/fastify/rpc-handler.test.ts (2)
packages/server/src/builder.ts (2)
handler(273-280)os(336-352)packages/server/src/adapters/fastify/rpc-handler.ts (1)
RPCHandler(24-33)
packages/nest/src/implement.test.ts (1)
packages/standard-server-fastify/src/index.ts (1)
FastifyReply(4-4)
packages/server/src/adapters/fastify/handler.test.ts (2)
packages/server/src/adapters/fastify/handler.ts (2)
handle(34-61)FastifyHandler(22-62)packages/standard-server-fastify/src/response.ts (1)
sendStandardResponse(8-34)
packages/standard-server-fastify/src/request.test.ts (2)
packages/standard-server-fastify/src/request.ts (1)
toStandardLazyRequest(6-26)packages/standard-server/src/types.ts (1)
StandardLazyRequest(26-32)
🪛 LanguageTool
packages/standard-server-fastify/README.md
[style] ~54-~54: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... your API or implement API contract. - [@orpc/client](https://www.npmjs.com/package/@...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~55-~55: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... API on the client with type-safety. - [@orpc/openapi](https://www.npmjs.com/package/...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~56-~56: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...I specs and handle OpenAPI requests. - [@orpc/otel](https://www.npmjs.com/package/@or...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~57-~57: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ....io/) integration for observability. - [@orpc/nest](https://www.npmjs.com/package/@or...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~58-~58: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... with NestJS. - [@orpc/react](https://www.npmjs.com/package/@o...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~59-~59: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...with React and React Server Actions. - [@orpc/tanstack-query](https://www.npmjs.com/p...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~60-~60: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...stack.com/query/latest) integration. - [@orpc/experimental-react-swr](https://www.npm...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~61-~61: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ttps://swr.vercel.app/) integration. - [@orpc/vue-colada](https://www.npmjs.com/packa...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~62-~62: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ada](https://pinia-colada.esm.dev/). - [@orpc/hey-api](https://www.npmjs.com/package/...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~63-~63: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...I](https://heyapi.dev/) integration. - [@orpc/zod](https://www.npmjs.com/package/@orp...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~64-~64: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...tps://zod.dev/) doesn't support yet. - [@orpc/valibot](https://www.npmjs.com/package/...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~65-~65: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...rom Valibot. - [@orpc/arktype](https://www.npmjs.com/package/...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🪛 markdownlint-cli2 (0.18.1)
packages/standard-server-fastify/README.md
48-48: Link text should be descriptive
(MD059, descriptive-link-text)
75-75: Images should have alternate text (alt text)
(MD045, no-alt-text)
🔇 Additional comments (35)
packages/standard-server-fastify/.gitignore (1)
1-26: ✓ Standard.gitignoreconfiguration looks good.The file follows common Node.js
.gitignorepatterns and provides comprehensive coverage for generated artifacts (build outputs, node_modules, logs, TypeScript metadata, test temps, etc.). The explicit exceptions for.gitignoreand.*.examplefiles are appropriate.packages/standard-server-fastify/tsconfig.json (1)
1-19: TypeScript configuration structure is sound.The configuration properly extends the base library configuration, targets ES2022 for a modern library, includes appropriate excludes for test/mock files, and restricts compilation to the src directory. The setup aligns with standard monorepo practices.
packages/standard-server-fastify/src/request.ts (2)
13-15: Verify the inconsistency betweenreq.rawand directreqproperty access.Lines 13-14 access
req.raw.methodandreq.rawfor URL conversion, but line 15 usesreq.headersdirectly instead ofreq.raw.headers. This inconsistency may lead to unexpected behavior if Fastify normalizes or transforms headers differently from the raw Node.js request.Please verify whether this is intentional. If headers should match the raw request for consistency, apply this diff:
return { method: toStandardMethod(req.raw.method), url: toStandardUrl(req.raw), - headers: req.headers, + headers: req.raw.headers, body: once(async () => {
16-23: Consider edge cases in body resolution logic.The condition
req.body !== undefined(line 18) prefers Fastify's parsed body when defined. However, if Fastify explicitly setsreq.body = undefinedin some edge cases (e.g., after certain content-type handling or errors), this could unintentionally skip the parsed body and fall back to raw parsing.Please verify that Fastify never explicitly assigns
undefinedtoreq.bodyin scenarios where body parsing was attempted. If this is a concern, consider checking for the presence of the property using'body' in reqor relying on Fastify's content-type handling flags.packages/server/package.json (1)
58-62: LGTM! Fastify adapter exports and dependencies are properly configured.The new Fastify adapter export structure follows the established pattern for other adapters (node, fetch, aws-lambda), with appropriate workspace dependency on
@orpc/standard-server-fastifyand devDependency onfastifyfor testing.Also applies to: 104-104, 139-139, 149-149
packages/standard-server-fastify/package.json (1)
36-42: Verify whetherfastifyshould be a required peer dependency.The
fastifypeer dependency is marked as optional (lines 40-42), butpackages/standard-server-fastify/src/request.tsdirectly importsFastifyRequestandFastifyReplytypes from thefastifypackage. This creates a mismatch: TypeScript compilation will fail iffastifyis not installed, making the "optional" designation potentially misleading.Please verify whether consumers can realistically use this package without
fastifyinstalled. If not, consider removing theoptional: trueflag to make it a required peer dependency:"peerDependenciesMeta": { "fastify": { - "optional": true } },packages/nest/package.json (1)
60-60: LGTM! Nest package dependencies updated for Fastify integration.The additions of
@orpc/standard-server-fastifyand@fastify/cookiealign with the PR's objective to provide native Fastify support for NestJS integration. The dependency structure is appropriate given thatfastifyis already an optional peer dependency.Also applies to: 64-64
apps/content/learn-and-contribute/overview.md (1)
40-40: LGTM! Documentation updated to include the new Fastify adapter.The addition of the
standard-server-fastifylink follows the established documentation pattern and is correctly placed within the Standard Server section.packages/openapi/src/adapters/fastify/index.ts (1)
1-1: LGTM!The re-export pattern follows standard module consolidation practices and provides a clean public API surface for the Fastify OpenAPI adapter.
packages/server/src/adapters/fastify/handler.test-d.ts (1)
1-17: LGTM!The TypeScript declaration tests properly validate the context type behavior, ensuring that optional contexts don't require the context parameter while required contexts do. The use of
@ts-expect-erroron Line 14 correctly documents the expected type error.packages/server/src/adapters/fastify/index.ts (1)
1-2: LGTM!The re-exports consolidate the Fastify adapter's public API surface, following the standard pattern used across the codebase.
packages/standard-server-fastify/src/index.ts (1)
1-4: LGTM!The exports properly consolidate the package's public API. The use of type-only exports on Line 4 for Fastify types is correct and prevents unnecessary runtime imports.
apps/content/docs/adapters/http.md (2)
139-147: LGTM! Clear integration pattern.The route handler and 404 fallback follow the standard pattern used across other adapters. The prefix handling and matched flag check are consistent with the existing examples.
133-137: This pattern is intentional and correctly recommended for full oRPC feature support.The content-type parser pattern is deliberately designed to allow oRPC to handle all body parsing directly, enabling advanced features like Bracket Notation and proper File handling that wouldn't work with framework-level parsing conflicts. This is validated by the test demonstrating the trade-off explicitly.
The original review's concern about differing from other adapters needs context: Express and Next.js use middleware architectures and recommend different integration patterns for that reason, not because the Fastify approach is wrong. Documentation already acknowledges this in
fastify.md(warning about default content-type parsing).Suggested improvements (not critical issues):
- Add similar context to the HTTP.md example explaining why the parser is configured this way and how oRPC handles body validation internally
- Reference the "Extend Body Parser" guide for handling large payloads if needed
packages/nest/src/implement.test.ts (2)
468-503: Good coverage of Fastify cookie integration.The test validates that:
- Fastify cookie plugin integrates with oRPC handlers
- The @res decorator with passthrough mode works correctly
- Response headers include both oRPC-set headers and Fastify-set cookies
This effectively demonstrates the native Fastify integration benefits mentioned in the PR objectives.
483-483: Theas anycast addresses a documented version incompatibility, not a code defect.The @nestjs/platform-fastify package depends on Fastify version 4.28.1, while newer versions of @fastify/cookie require Fastify ^5.0.0. This causes a TypeScript error: "Argument of type 'FastifyCookie' is not assignable to parameter of type 'FastifyPluginCallback...'" The cast is a known workaround; upgrading all NestJS packages resolves the underlying type incompatibility. If dependencies are already aligned to compatible versions in this codebase, the cast can be removed. Otherwise, it remains necessary and should be retained until the version mismatch is resolved.
packages/server/src/adapters/fastify/rpc-handler.test.ts (2)
7-10: LGTM!The handler setup demonstrates both explicit route configuration (ping with GET method) and implicit handler configuration (pong without method specification), which is useful for testing different handler patterns.
26-37: Good validation of default plugin behavior.The test correctly validates that StrictGetMethodPlugin is enabled by default, ensuring GET requests to procedures without explicit method configuration are rejected with 405. This enforces proper HTTP method semantics.
packages/openapi/package.json (1)
43-47: Export configuration verified; confirm dist files after build.The fastify export is correctly configured:
- Export points to existing source file:
./src/adapters/fastify/index.ts✅- publishConfig exports properly mapped to dist paths ✅
- Source and test files present ✅
Dist files (
./dist/adapters/fastify/index.mjsand./dist/adapters/fastify/index.d.mts) can only be verified after runningpnpm -w build. Ensure the build completes successfully and produces these output files.packages/standard-server-fastify/src/response.ts (3)
1-6: LGTM!The imports and interface definition are well-structured. The empty extension of
ToNodeHttpBodyOptionscreates a semantic alias that allows future extensibility without breaking changes.
13-15: LGTM!The Promise wrapper with
reply.rawevent handlers is the correct pattern for handling Fastify response lifecycle events, ensuring proper resolution on successful completion and rejection on transmission errors.
17-22: LGTM!The header cloning and body conversion logic is correct. The shallow clone protects the original
standardResponse.headersfrom mutation, whiletoNodeHttpBodyappropriately mutates the cloned headers to set the correctcontent-typeandcontent-dispositionbased on body type.apps/content/docs/adapters/fastify.md (1)
37-46: LGTM!The route handler example correctly demonstrates the integration pattern, including prefix stripping, context provision, and 404 handling for unmatched routes.
packages/server/src/adapters/fastify/rpc-handler.ts (1)
1-16: LGTM!The interface definition correctly composes options from both the Fastify adapter layer and the standard RPC handler layer, with clear documentation for the plugin enablement flag.
packages/server/src/adapters/fastify/handler.test.ts (3)
1-18: LGTM!The mock setup is well-structured with proper isolation and cleanup. The use of
vi.clearAllMocks()inbeforeEachensures test independence.
20-52: LGTM!The test setup cleverly uses an actual Fastify instance to capture real
FastifyRequestandFastifyReplyobjects, which is more robust than mocking these complex Fastify types. The pattern of usingfastify.ready()followed by a test request to populate fixtures is appropriate for this use case.
54-99: LGTM!The 'on match' test case provides comprehensive coverage, validating all interactions including the standard handler call, request conversion, response sending, and interceptor execution with correct context propagation.
packages/standard-server-fastify/src/response.test.ts (6)
1-13: LGTM!The test setup correctly uses spies on the actual implementation rather than full mocks, allowing validation of both the function calls and the actual behavior. The
beforeEachcleanup ensures test isolation.
15-51: LGTM!The test thoroughly validates the empty body scenario, including proper cleanup, correct function calls, and expected HTTP response characteristics.
53-136: LGTM!Both the JSON body and file streaming tests comprehensively validate their respective scenarios, including correct content-type headers, body serialization, and streaming behavior.
138-184: LGTM!The async generator streaming test thoroughly validates server-sent events (SSE) formatting, including correct event types, data serialization, and content-type headers.
186-251: LGTM!The edge case tests provide excellent coverage for error conditions and resource cleanup, including stream error propagation and proper cancellation handling when requests are aborted.
253-280: LGTM!The cookie integration test is valuable for validating compatibility with Fastify's plugin ecosystem, ensuring that
sendStandardResponsedoesn't interfere with other Fastify plugins like@fastify/cookie.packages/server/src/adapters/fastify/handler.ts (2)
1-20: LGTM!The type definitions are well-structured and correctly model the Fastify adapter layer's concerns. The
FastifyHandleResultappropriately simplifies the response model since responses are sent directly through Fastify rather than returned.
34-61: LGTM!The
handlemethod implementation correctly orchestrates the request flow, properly converting between Fastify and standard representations, delegating to the standard handler, and handling both matched and unmatched cases appropriately.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
packages/server/src/adapters/fastify/handler.ts (1)
22-22: Note: The self-referential implements clause has been correctly removed.A previous review comment flagged this issue and it appears to have been addressed. The class declaration is now correct.
🧹 Nitpick comments (1)
packages/standard-server-fastify/src/response.ts (1)
13-24: Consider wrapping response operations in try-catch.If
toNodeHttpBody,reply.status(),reply.headers(), orreply.send()throw synchronously, the promise will reject but the event listeners may not be properly cleaned up, depending on timing.Wrap the operations in a try-catch to ensure proper error handling:
reply.raw.once('error', onError) reply.raw.once('close', onClose) + try { const resHeaders: StandardHeaders = { ...standardResponse.headers } const resBody = toNodeHttpBody(standardResponse.body, resHeaders, options) reply.status(standardResponse.status) reply.headers(resHeaders) reply.send(resBody) + } catch (err) { + reply.raw.off('error', onError) + reply.raw.off('close', onClose) + reject(err) + } }) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
packages/server/src/adapters/fastify/handler.test.ts(1 hunks)packages/server/src/adapters/fastify/handler.ts(1 hunks)packages/server/src/adapters/node/handler.test.ts(1 hunks)packages/server/src/adapters/node/handler.ts(1 hunks)packages/standard-server-fastify/src/response.test.ts(1 hunks)packages/standard-server-fastify/src/response.ts(1 hunks)packages/standard-server-node/src/response.test.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/standard-server-fastify/src/response.test.ts
- packages/server/src/adapters/fastify/handler.test.ts
🧰 Additional context used
🧬 Code graph analysis (4)
packages/server/src/adapters/node/handler.ts (1)
packages/server/src/context.ts (1)
Context(1-1)
packages/server/src/adapters/node/handler.test.ts (2)
packages/server/src/adapters/node/handler.ts (1)
handle(42-69)packages/server/src/adapters/standard/handler.ts (1)
handle(72-182)
packages/standard-server-fastify/src/response.ts (2)
packages/standard-server-node/src/body.ts (2)
ToNodeHttpBodyOptions(53-53)toNodeHttpBody(60-104)packages/standard-server/src/types.ts (2)
StandardResponse(34-41)StandardHeaders(1-3)
packages/server/src/adapters/fastify/handler.ts (7)
packages/server/src/context.ts (1)
Context(1-1)packages/server/src/adapters/standard/handler.ts (2)
StandardHandleOptions(16-19)StandardHandler(50-183)packages/standard-server-fastify/src/response.ts (2)
SendStandardResponseOptions(6-6)sendStandardResponse(8-25)packages/shared/src/interceptor.ts (1)
Interceptor(13-16)packages/shared/src/array.ts (1)
toArray(1-3)packages/shared/src/args.ts (2)
MaybeOptionalOptions(1-3)resolveMaybeOptionalOptions(5-7)packages/server/src/adapters/standard/utils.ts (2)
FriendlyStandardHandleOptions(4-6)resolveFriendlyStandardHandleOptions(8-13)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: publish-commit
- GitHub Check: lint
- GitHub Check: test
🔇 Additional comments (4)
packages/standard-server-node/src/response.test.ts (1)
41-42: LGTM! Test precision improved.The explicit assertions correctly verify that
content-typeis not set when the body is undefined, while custom headers are still propagated. This is more precise than a permissivetoMatchObjectmatch and aligns with the stricter header handling introduced across the Fastify and Node adapters in this PR.packages/server/src/adapters/node/handler.test.ts (1)
97-128: LGTM! Test correctly aligns with the return type.The test now correctly expects
{ matched: false }without theresponsefield, which matches theNodeHttpHandleResulttype definition. The Node handler transforms the internalStandardHandleResult(which includesresponse: undefined) to its own simpler result type.packages/server/src/adapters/node/handler.ts (1)
26-26: LGTM! Removed meaningless self-referential implements clause.The class no longer implements itself, which was semantically incorrect. This is a good cleanup.
packages/server/src/adapters/fastify/handler.ts (1)
34-61: LGTM! Handler implementation follows the established adapter pattern.The
handlemethod correctly:
- Applies adapter interceptors
- Converts Fastify request/reply to standard request
- Delegates to the standard handler
- Sends the response on match
- Returns the appropriate result type
The implementation is consistent with the Node handler and integrates properly with the standard server infrastructure.
|
@unnoq I spent the last day using this release and it worked wonders. Thank you soo much. Can't wait to have this in main. |
This PR adds a native oRPC adapter for Fastify. Previously, oRPC in Fastify used the Node adapter, which didn't integrate well with Fastify's ecosystem (e.g., cookies, helpers, middleware). This native adapter supports Fastify's request/reply APIs directly, enabling full access to Fastify features within oRPC.
Closes: #998, #992
Summary by CodeRabbit
New Features
Documentation
Tests
Chores