Skip to content

Conversation

@mwillbanks
Copy link

@mwillbanks mwillbanks commented Nov 17, 2025

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:

  • New exports that allow extension of REST and RPC API handlers and the creation of additional handler types
  • Additional exported types and interfaces that support custom server adapters
  • Updated visibility of internal fields so custom handlers can override behavior such as query parsing or serialization
  • New entry points in package.json to expose common api and types.

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

    • Added public exports for ./common and ./types modules, expanding the package's public API surface.
    • Enhanced extensibility of REST and RPC API handlers to support custom implementations through inheritance.
  • Tests

    • Added test coverage for custom adapter and handler implementations demonstrating new extension capabilities.

ymc9 added 30 commits June 17, 2025 13:08
merge dev to main (3.0.0-alpha.4)
merge dev to main (v3.0.0-alpha.6)
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 (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 (v3.0.0-alpha.29)
ymc9 and others added 22 commits September 4, 2025 12:37
merge dev to main (v3.0.0-beta.3)
merge dev to main (v3.0.0-beta.4)
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.
Copilot AI review requested due to automatic review settings November 17, 2025 20:39
@coderabbitai
Copy link

coderabbitai bot commented Nov 17, 2025

Walkthrough

This pull request expands the public API surface of the server package by adding new exports (./common and ./types), re-exporting utility functions, widening many private members to protected in API handler classes to enable subclassing, updating build configuration, and adding test files demonstrating handler extensibility.

Changes

Cohort / File(s) Summary
Package & Build Configuration
packages/server/package.json, packages/server/tsup.config.ts
Adds new public exports ./common and ./types with dual ESM/CommonJS mappings; adds corresponding build entry points in tsup config.
API Module Exports
packages/server/src/api/index.ts
Re-exports all utilities from ./utils module, expanding public API surface.
REST API Handler Extensibility
packages/server/src/api/rest/index.ts
Widens constructor and ~40 private members (properties and methods) to protected, enabling subclassing and customization of RestApiHandler internal behavior.
RPC API Handler Extensibility
packages/server/src/api/rpc/index.ts
Widens constructor and 6 private methods to protected; adds debug logging in error response helpers.
Test Suites for Extensibility
packages/server/test/api/rest.test.ts, packages/server/test/api/rpc.test.ts
Introduces test cases demonstrating subclassing of RestApiHandler and RPCApiHandler with method overrides (buildFilter, unmarshalQ).
Test Infrastructure
packages/server/test/adapter/custom.test.ts, packages/server/test/api/custom.test.ts
Adds new test files with custom handler implementations and context/logging verification.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Visibility changes: Verify that ~46 private→protected transitions in RestApiHandler and RPCApiHandler don't inadvertently expose internal state or break encapsulation contracts.
  • Export mappings: Confirm all dual ESM/CommonJS entry points in package.json reference correct dist files and type declarations.
  • Build entries: Validate tsup.config entries correctly reference source files and generate expected outputs.
  • Test coverage: Review new test subclasses to ensure they correctly exercise the protected members and validate intended extensibility patterns.

Possibly related PRs

Poem

🐰 Hops through code with glee,
Protected now for all to see!
Subclass magic, extend with care,
New exports float through the air! 🌟

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly summarizes the main change: exposing internal API handler and server adapter types to support custom implementations.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining why this PR is needed, why this solution was chosen, and what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

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.

❤️ Share

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

Copilot finished reviewing on behalf of mwillbanks November 17, 2025 20:42
Copy link
Contributor

Copilot AI left a 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 private to protected to support inheritance
  • Adds new package.json exports for types, common, and api modules
  • 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.

Copy link

@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: 0

🧹 Nitpick comments (2)
packages/server/src/api/index.ts (1)

3-3: Consider re‑exporting specific utils instead of export *

Re‑exporting everything from ./utils makes 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 exercises buildFilter, consider aligning call shape

The custom RestApiHandler subclass and its test are a solid proof that buildFilter is now a usable extension point: you preserve the base filter/error and layer on title: 'second', then assert both the recorded call and the filtered result set. One minor consistency tweak to consider is calling handleRequest via the same wrapper pattern used elsewhere in this file (i.e., adding a url field) so the test mirrors how adapters actually invoke the REST handler.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 778526d and c356683.

📒 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: New types and common tsup entries align with package exports

Adding types and common to the entry map matches the new ./types and ./common exports pattern and keeps the build config consistent with existing adapters. Just ensure the server package build actually emits the corresponding dist/types* and dist/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 surface

The CustomApiHandler implementation and its tests validate exactly the intended extension points: implementing ApiHandler, using LogConfig with the shared log helper, inspecting captured RequestContexts, 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: ./common export is consistent with existing adapter entrypoints

The new ./common export follows the same import/require + types/default structure as the other adapters and lines up with the added common tsup entry. No issues from an exports/paths perspective; just make sure the corresponding dist/common.* artifacts exist in CI builds.


131-140: ./types export cleanly surfaces shared handler/adaptor types

Exposing ./types with 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 that src/types.ts is 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 behavior

Making options and the internal helpers (isValidModel, the error response builders, processRequestPayload, and unmarshalQ) protected lines up well with the new CustomHandler tests and allows targeted overrides without altering the existing request flow. The added debug logging around error responses is also reasonable, reusing the central log helper and safeJSONStringify so observability improves without changing response shapes.

Also applies to: 166-258

packages/server/test/api/rpc.test.ts (1)

511-567: Subclassing test correctly validates unmarshalQ extensibility

This test is a good demonstration of the new protected surface: the CustomHandler override of unmarshalQ records calls, preserves the base result, and successfully narrows the query to title: 'second'. Calling handler.handleRequest directly is fine here; if you ever add extra context fields (like a url) 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 ./types and utilities from ./common entry points.


7-36: LGTM!

The AdapterRequest type and RecordingHandler test double are well-designed. The handler correctly implements the ApiHandler interface and captures requests for verification.


38-52: LGTM!

The ThrowingHandler test double appropriately simulates adapter failures for error handling verification.


54-73: LGTM!

The adapter correctly transforms AdapterRequest to RequestContext and delegates to the handler. Error handling properly logs via logInternalError before rethrowing. This serves as a good minimal example of custom adapter implementation.


75-119: LGTM!

The test suite thoroughly validates:

  • Correct mapping from AdapterRequest to RequestContext
  • Response pass-through from handler
  • Error logging via logInternalError

These tests effectively demonstrate the intended usage pattern for custom adapters.

packages/server/src/api/rest/index.ts (8)

121-201: LGTM!

Exposing serializers and errors as protected enables subclasses to customize serialization behavior and error responses. The addition of the detail field to the unsupportedModel error 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 readonly and 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.

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.

2 participants