-
-
Notifications
You must be signed in to change notification settings - Fork 12
Expose internal API handler and server adapter types to support custom handler and adapter implementations #413
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Expose internal API handler and server adapter types to support custom handler and adapter implementations #413
Conversation
merge dev to main
merge dev to main (3.0.0-alpha.4)
merge dev to main
merge dev to main (v3.0.0-alpha.6)
merge dev to main
merge dev to main
merge dev to main
merge dev to main
merge dev to main
merge dev to main
merge dev to main
merge dev to main
merge dev to main (v3.0.0-alpha.13)
merge dev to main (v3.0.0-alpha.14)
merge dev to main (v3.0.0-alpha.15)
merge dev to main (v3.0.0-alpha.16)
merge dev to main (v3.0.0-alpha.17)
merge dev to main (v3.0.0-alpha.18)
merge dev to main (v3.0.0-alpha.19)
merge dev to main
merge dev to main (v3.0.0-alpha.21)
merge dev to main (v3.0.0-alpha.22)
merge dev to main (v3.0.0-alpha.23)
merge dev to main (v3.0.0-alpha.24)
merge dev to main (v3.0.0-alpha.25)
merge dev to main (v3.0.0-alpha.26)
merge dev to main (v3.0.0-alpha.27)
merge dev to main
merge dev to main (v3.0.0-alpha.29)
merge dev to main
merge dev to main (v3.0.0-beta.3)
merge dev to main (v3.0.0-beta.4)
merge dev to main
merge dev to main (v3.0.0-beta.6)
merge dev to main (v3.0.0-beta.7)
merge dev to main (v3.0.0-beta.8)
merge dev to main (v3.0.0-beta.9)
merge dev to main (v3.0.0-beta.10)
merge dev to main (v3.0.0-beta.11)
merge dev to main (v3.0.0-beta.12)
merge dev to main (v3.0.0-beta.13)
merge dev to main (v3.0.0-beta.14)
merge dev to main (v3.0.0-beta.15)
merge dev to main (v3.0.0-beta.16)
merge dev to main (v3.0.0-beta.17)
merge dev to main (v3.0.0-beta.18)
merge dev to main (v3.0.0-beta.19)
merge dev to main (v3.0.0-beta.20)
merge dev to main (v3.0.0-beta.21)
merge dev to main (v3.0.0-beta.22)
merge dev to main (v3.0.0-beta.23)
Expose internal handler types and adapter interfaces. Improve visibility of handler internals required for overrides. Add shared entry point for common server utilities.
WalkthroughThis pull request expands the public API surface of the server package by adding new exports ( Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example instruction:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR exposes internal APIs to enable custom handler and adapter implementations by changing visibility modifiers and adding new package exports.
- Changes visibility of RPC and REST handler methods/fields from
privatetoprotectedto support inheritance - Adds new package.json exports for
types,common, andapimodules - Includes comprehensive test coverage demonstrating custom handler and adapter implementations
Reviewed Changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| packages/server/tsup.config.ts | Adds build entry points for types, common, and api modules to support new exports |
| packages/server/package.json | Exposes new package entry points ./types and ./common for custom implementations |
| packages/server/src/api/index.ts | Exports utility functions from ./utils for use by custom handlers |
| packages/server/src/api/rpc/index.ts | Changes visibility of constructor options and internal methods from private to protected to enable handler extension |
| packages/server/src/api/rest/index.ts | Changes visibility of internal fields, methods, and configuration from private to protected for customization |
| packages/server/test/api/rpc.test.ts | Adds test demonstrating custom RPC handler extending RPCApiHandler to customize query unmarshalling |
| packages/server/test/api/rest.test.ts | Adds test demonstrating custom REST handler extending RestApiHandler to customize filter building |
| packages/server/test/api/custom.test.ts | Adds test for implementing a completely custom API handler using exposed types and utilities |
| packages/server/test/adapter/custom.test.ts | Adds test for implementing a custom server adapter using exposed adapter utilities and types |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
packages/server/src/api/index.ts (1)
3-3: Consider re‑exporting specific utils instead ofexport *Re‑exporting everything from
./utilsmakes any future helper added there part of the public API by default. If the goal is mainly to surface a stable subset (e.g., logging and serializer registration helpers), consider explicitly exporting those symbols instead to keep internal utilities free to evolve.packages/server/test/api/rest.test.ts (1)
3167-3240: Handler‑extension test nicely exercisesbuildFilter, consider aligning call shapeThe custom
RestApiHandlersubclass and its test are a solid proof thatbuildFilteris now a usable extension point: you preserve the base filter/error and layer ontitle: 'second', then assert both the recorded call and the filtered result set. One minor consistency tweak to consider is callinghandleRequestvia the same wrapper pattern used elsewhere in this file (i.e., adding aurlfield) so the test mirrors how adapters actually invoke the REST handler.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
packages/server/package.json(2 hunks)packages/server/src/api/index.ts(1 hunks)packages/server/src/api/rest/index.ts(41 hunks)packages/server/src/api/rpc/index.ts(6 hunks)packages/server/test/adapter/custom.test.ts(1 hunks)packages/server/test/api/custom.test.ts(1 hunks)packages/server/test/api/rest.test.ts(1 hunks)packages/server/test/api/rpc.test.ts(1 hunks)packages/server/tsup.config.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-21T16:09:31.218Z
Learnt from: ymc9
Repo: zenstackhq/zenstack-v3 PR: 319
File: packages/runtime/src/client/executor/zenstack-query-executor.ts:63-72
Timestamp: 2025-10-21T16:09:31.218Z
Learning: In ZenStack, TypeDefs can be inherited by models. When a TypeDef contains fields with `map` attributes, those mapped field names need to be processed by the QueryNameMapper since they become part of the inheriting model's schema. Therefore, when checking if a schema has mapped names (e.g., in `schemaHasMappedNames`), both `schema.models` and `schema.typeDefs` must be inspected for `@map` and `map` attributes.
Applied to files:
packages/server/src/api/rest/index.ts
🧬 Code graph analysis (6)
packages/server/test/api/rest.test.ts (1)
packages/server/src/api/rest/index.ts (1)
RestApiHandler(119-2075)
packages/server/src/api/rpc/index.ts (3)
packages/orm/src/client/contract.ts (1)
ClientContract(52-172)packages/common-helpers/src/lower-case-first.ts (1)
lowerCaseFirst(1-3)packages/orm/src/client/errors.ts (1)
ORMError(66-104)
packages/server/test/api/custom.test.ts (3)
packages/server/src/types.ts (4)
ApiHandler(67-82)RequestContext(22-47)LogConfig(17-17)Response(52-62)packages/schema/src/schema.ts (1)
SchemaDef(11-19)packages/server/src/api/utils.ts (1)
registerCustomSerializers(32-53)
packages/server/test/api/rpc.test.ts (2)
packages/server/src/api/rpc/index.ts (1)
RPCApiHandler(29-259)packages/schema/src/schema.ts (1)
SchemaDef(11-19)
packages/server/test/adapter/custom.test.ts (4)
packages/schema/src/schema.ts (1)
SchemaDef(11-19)packages/orm/src/client/contract.ts (1)
ClientContract(52-172)packages/server/src/types.ts (3)
ApiHandler(67-82)Response(52-62)RequestContext(22-47)packages/server/src/adapter/common.ts (2)
CommonAdapterOptions(8-13)logInternalError(15-21)
packages/server/src/api/rest/index.ts (5)
packages/server/src/types.ts (1)
Response(52-62)packages/orm/src/client/contract.ts (1)
ClientContract(52-172)packages/schema/src/schema.ts (2)
ModelDef(21-38)FieldDef(62-77)packages/common-helpers/src/lower-case-first.ts (1)
lowerCaseFirst(1-3)packages/orm/src/client/errors.ts (1)
ORMError(66-104)
⏰ 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). (1)
- GitHub Check: Agent
🔇 Additional comments (19)
packages/server/tsup.config.ts (1)
5-7: Newtypesandcommontsup entries align with package exportsAdding
typesandcommonto theentrymap matches the new./typesand./commonexports pattern and keeps the build config consistent with existing adapters. Just ensure the server package build actually emits the correspondingdist/types*anddist/common*bundles and declarations before publishing.packages/server/test/api/custom.test.ts (1)
1-62: Custom handler tests correctly exercise the new public API surfaceThe
CustomApiHandlerimplementation and its tests validate exactly the intended extension points: implementingApiHandler, usingLogConfigwith the sharedloghelper, inspecting capturedRequestContexts, and round‑tripping a custom‑serialized numeric value. This looks coherent and gives good coverage of the new customization hooks.packages/server/package.json (2)
42-51:./commonexport is consistent with existing adapter entrypointsThe new
./commonexport follows the same import/require + types/default structure as the other adapters and lines up with the addedcommontsup entry. No issues from an exports/paths perspective; just make sure the correspondingdist/common.*artifacts exist in CI builds.
131-140:./typesexport cleanly surfaces shared handler/adaptor typesExposing
./typeswith both ESM and CJS type/runtime entries makes type‑only imports ergonomic (e.g.@zenstackhq/server/types) and is aligned with the rest of the export map. Keep in mind thatsrc/types.tsis now part of the public API, so future breaking changes there will be observable by consumers.packages/server/src/api/rpc/index.ts (1)
30-30: Protected options and helpers support subclassing without changing behaviorMaking
optionsand the internal helpers (isValidModel, the error response builders,processRequestPayload, andunmarshalQ)protectedlines up well with the newCustomHandlertests and allows targeted overrides without altering the existing request flow. The added debug logging around error responses is also reasonable, reusing the centralloghelper andsafeJSONStringifyso observability improves without changing response shapes.Also applies to: 166-258
packages/server/test/api/rpc.test.ts (1)
511-567: Subclassing test correctly validatesunmarshalQextensibilityThis test is a good demonstration of the new
protectedsurface: theCustomHandleroverride ofunmarshalQrecords calls, preserves the base result, and successfully narrows the query totitle: 'second'. Callinghandler.handleRequestdirectly is fine here; if you ever add extra context fields (like aurl) to RPC requests, you might want to mirror the adapter wrapper pattern for consistency, but the current test accurately exercises the intended hook.packages/server/test/adapter/custom.test.ts (5)
1-6: LGTM!The imports properly utilize the newly exposed public API surface, including types from
./typesand utilities from./commonentry points.
7-36: LGTM!The
AdapterRequesttype andRecordingHandlertest double are well-designed. The handler correctly implements theApiHandlerinterface and captures requests for verification.
38-52: LGTM!The
ThrowingHandlertest double appropriately simulates adapter failures for error handling verification.
54-73: LGTM!The adapter correctly transforms
AdapterRequesttoRequestContextand delegates to the handler. Error handling properly logs vialogInternalErrorbefore rethrowing. This serves as a good minimal example of custom adapter implementation.
75-119: LGTM!The test suite thoroughly validates:
- Correct mapping from
AdapterRequesttoRequestContext- Response pass-through from handler
- Error logging via
logInternalErrorThese tests effectively demonstrate the intended usage pattern for custom adapters.
packages/server/src/api/rest/index.ts (8)
121-201: LGTM!Exposing
serializersanderrorsas protected enables subclasses to customize serialization behavior and error responses. The addition of thedetailfield to theunsupportedModelerror provides clearer error messages.
203-253: LGTM!Exposing internal patterns, schemas, and mappings as protected allows subclasses to customize:
- Request payload validation
- URL pattern matching
- Model name mappings
- Filter query parsing
This provides the necessary hooks for extending handler behavior.
255-330: LGTM!Making the constructor options
protected readonlyand utility methods protected provides appropriate extension points while preventing unintended modification of configuration.
472-1202: LGTM!Exposing CRUD operation handlers (
processSingleRead,processCreate,processUpdate, etc.) as protected enables subclasses to override or enhance specific operations with custom logic like authorization, audit logging, or tenant filtering.
788-2016: LGTM!Exposing query building methods (
buildFilter,buildSort,buildPartialSelect, etc.) as protected enables powerful customization capabilities, such as implementing custom query syntax, filtering rules, or relationship handling logic.
1206-1487: LGTM!Exposing internal utilities as protected provides subclasses with the building blocks needed for deep customization, including schema introspection, URL generation, and serialization logic.
1489-1977: LGTM!Exposing ID handling and filter construction methods as protected enables subclasses to customize type coercion, ID representation, and filter logic—essential for supporting custom field types or filter operators.
1017-2072: LGTM!Exposing the remaining utility and error handling methods as protected completes the extensibility surface, allowing subclasses to customize error responses, pagination logic, and URL construction.
This change expands the server package to allow developers to build custom API handlers and server adapters. Several internal types, interfaces, and utilities are now exported so that custom implementations can follow the same patterns used by the built in REST and RPC handlers.
Key improvements include:
These updates make it possible to adjust handler behavior for specific needs, write entirely new handlers that behave consistently with existing ones, and implement new adapters for other server environments.
Summary by CodeRabbit
New Features
./commonand./typesmodules, expanding the package's public API surface.Tests