-
-
Notifications
You must be signed in to change notification settings - Fork 35
feat(v26): method only routes #3049
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
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThis PR adds configuration-driven routing behavior to the framework. A new Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
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 |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
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: 1
🧹 Nitpick comments (9)
example/routing.ts (1)
22-23: Clarify the comment to reflect method-only routing.The comment states "methods are defined within the route," but with the new
patchsyntax, the method name is the route key itself (method-only routing), not a combined string like"patch /". Consider updating the comment to clarify this distinction, for example:- // syntax 2: methods are defined within the route + // syntax 2: method-only routing (requires methodLikeRouteBehavior config) patch: updateUserEndpoint, // demonstrates authenticationThis helps readers understand that
patchis interpreted as an HTTP method, not a path segment likeretrieveorremove.CHANGELOG.md (2)
7-12: Clarify which keys are recognized as “method-like”.Suggest listing supported lowercase HTTP methods (get, post, put, patch, delete, head, options) and noting case-sensitivity to avoid ambiguity.
21-31: Make it explicit that “create” is a nested path segment.To prevent confusion with HTTP methods, consider annotating the example or using a more obviously non-method key:
-+ "/v1/users": { -+ get: getUserEndpoint, -+ create: makeUserEndpoint -+ }, ++ "/v1/users": { ++ get: getUserEndpoint, // method ++ create: makeUserEndpoint // nested path segment ++ },example/generate-client.ts (1)
8-13: Guard serverUrl when listen is an object.config.http.listen can be number|string|ListenOptions. If it’s ListenOptions, template string will yield “[object Object]”. Optionally normalize:
- serverUrl: `http://localhost:${config.http!.listen}`, + serverUrl: `http://localhost:${ + typeof config.http?.listen === "object" + ? (config.http.listen as { port?: number|string }).port ?? 80 + : config.http?.listen + }`,express-zod-api/tests/integration.spec.ts (1)
24-24: Add a focused test for methodLikeRouteBehavior="path".Current tests pass config but don’t assert the “method-like key as path segment” mode. Add one snapshot where a key like “get” under a path object is forced to be treated as a nested segment via config.methodLikeRouteBehavior="path". This hardens the new behavior.
Also applies to: 29-47, 52-70, 75-89, 112-126, 138-163
express-zod-api/src/config-type.ts (1)
49-57: New config option looks good; document recognized methods.Consider specifying recognized lowercase method names (get, post, put, patch, delete, head, options) in the JSDoc for clarity. Ensure routing-walker applies a default of "method" when unset.
express-zod-api/src/routing.ts (1)
19-21: Update example to match “DependsOnMethod removed”.Replace the stale “dependsOnMethod” example with method-key routing:
- * @example { dependsOnMethod: { get: retrieveEndpoint, post: createEndpoint } } + * @example { users: { get: retrieveEndpoint, post: createEndpoint } } // methods as keys on an objectREADME.md (2)
308-314: Consider documenting method-only routing conditions.The method-based routing example clearly shows the new syntax. To help users avoid confusion, consider adding a note that method-only routing (where keys like
get,postare treated as methods rather than path segments) only applies when:
- The key is a valid HTTP method name
- The value is an
Endpoint(not nested routing)methodLikeRouteBehavioris set to"method"(which is the default)For nested routing under method keys, users should either use explicit syntax like
"get /path"or setmethodLikeRouteBehavior: "path".
1088-1092: Clarify whetherconfigparameter is required.The documentation shows that
configis now a parameter for theIntegrationconstructor, and the PR description mentions "Integration now requires aconfigparameter" as a breaking change. Consider making this explicit in the documentation by:
- Adding a comment indicating it's required, or
- Showing both the old usage (deprecated) and new usage with a migration note
This will help users understand the breaking change when upgrading.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
CHANGELOG.md(1 hunks)README.md(2 hunks)example/generate-client.ts(1 hunks)example/routing.ts(1 hunks)express-zod-api/src/config-type.ts(1 hunks)express-zod-api/src/documentation.ts(2 hunks)express-zod-api/src/integration.ts(4 hunks)express-zod-api/src/routing-walker.ts(5 hunks)express-zod-api/src/routing.ts(2 hunks)express-zod-api/tests/integration.spec.ts(5 hunks)express-zod-api/tests/routing.spec.ts(5 hunks)
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-07-20T11:09:58.980Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2833
File: express-zod-api/src/method.ts:3-3
Timestamp: 2025-07-20T11:09:58.980Z
Learning: In express-zod-api, the `SomeMethod` type (defined as `Lowercase<string>`) is intentionally broad to represent raw, unvalidated HTTP methods from requests. The narrower `Method` type is used after validation with `isMethod()`. This defensive programming pattern separates raw external input types from validated types, allowing graceful handling of unknown methods.
Applied to files:
express-zod-api/src/config-type.tsexpress-zod-api/src/routing-walker.ts
📚 Learning: 2025-05-28T18:58:10.064Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2428
File: express-zod-api/src/index.ts:44-44
Timestamp: 2025-05-28T18:58:10.064Z
Learning: The type-only import `import type {} from "qs";` in express-zod-api/src/index.ts is necessary to avoid TS2742 errors for exported functions like attachRouting, makeRequestMock, testEndpoint, and testMiddleware that have types depending on types/qs. This import provides the reference TypeScript needs to infer portable type names.
Applied to files:
express-zod-api/src/config-type.tsexpress-zod-api/src/integration.tsexpress-zod-api/tests/integration.spec.tsexpress-zod-api/src/routing.tsexpress-zod-api/tests/routing.spec.ts
📚 Learning: 2025-06-14T16:42:52.972Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2736
File: express-zod-api/tsup.config.ts:12-26
Timestamp: 2025-06-14T16:42:52.972Z
Learning: In express-zod-api tsup configurations, the direct mutation of `options.supported` in the `esbuildOptions` callback is intentional behavior and should not be flagged as a side effect issue.
Applied to files:
express-zod-api/src/config-type.tsexpress-zod-api/src/documentation.tsexpress-zod-api/src/routing.tsexpress-zod-api/tests/routing.spec.ts
📚 Learning: 2025-06-02T21:08:56.475Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2697
File: CHANGELOG.md:5-5
Timestamp: 2025-06-02T21:08:56.475Z
Learning: The `cjs-test` directory in the express-zod-api repository is a test workspace and should be excluded when checking for main project version consistency with changelog entries.
Applied to files:
express-zod-api/tests/integration.spec.ts
📚 Learning: 2025-10-02T17:42:48.840Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 0
File: :0-0
Timestamp: 2025-10-02T17:42:48.840Z
Learning: In express-zod-api v25 (ESM-only), the `.example()` method error occurs when user code runs as CommonJS. Express Zod API patches Zod's ESM bundle with `.example()`, but CommonJS code requires a separate CJS bundle instance that lacks this patch. Users must run their code as ESM by: (1) setting `"type": "module"` in package.json, (2) using `.mts` or `.mjs` file extensions, or (3) using tools like `tsx` or `vite-node` that provide their own ESM-compatible compilation.
Applied to files:
express-zod-api/src/routing.ts
📚 Learning: 2025-05-27T20:03:34.213Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2546
File: example/factories.ts:35-42
Timestamp: 2025-05-27T20:03:34.213Z
Learning: The `./example` directory in the express-zod-api repository contains demonstration code for educational purposes only, not intended for production use. Example code can make simplified assumptions for brevity and clarity, and should not be flagged for missing production-level error handling, security measures, or edge case handling.
Applied to files:
express-zod-api/src/routing.ts
📚 Learning: 2025-05-27T19:35:57.357Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2546
File: express-zod-api/tests/buffer-schema.spec.ts:32-37
Timestamp: 2025-05-27T19:35:57.357Z
Learning: In the express-zod-api project, tests are run from the `express-zod-api` workspace directory, and the project uses an ESM-first environment without `__dirname`. Relative paths like `../logo.svg` in test files correctly resolve to the repository root due to this test execution context.
Applied to files:
express-zod-api/tests/routing.spec.ts
🔇 Additional comments (10)
express-zod-api/src/routing.ts (1)
81-82: Passing config into walkRouting — looks good.express-zod-api/src/documentation.ts (1)
48-54: Config plumbed into Documentation — verified.The required config and forwarding to walkRouting are correct. Verified that routing-walker properly defaults
methodLikeRouteBehaviorto"method"via destructuring default inrouting-walker.ts:41.express-zod-api/src/integration.ts (1)
28-31: Config now required in Integration — implementation verified complete.Verification confirms all Integration instantiations in production code and tests supply the required
configparameter. No call sites missing the property.express-zod-api/tests/routing.spec.ts (3)
34-94: LGTM! Test correctly validates path-based interpretation.The test properly validates that when
methodLikeRouteBehavior: "path"is set, method-like keys (e.g.,get,post) are treated as path segments rather than HTTP methods. The expectations correctly verify that thegetkey results in the path/v1/user/get.Note: This test uses the non-default behavior. The default (
methodLikeRouteBehavior: "method") is tested in subsequent tests where method keys route to the parent path without adding a segment.
112-155: LGTM! Test validates the new method-only routing feature.This test correctly validates the default behavior (
methodLikeRouteBehavior: "method") where method-like keys (get,post,put,patch) are interpreted as HTTP methods rather than path segments. The expectations confirm that all methods route to the parent path/v1/userinstead of creating nested paths like/v1/user/get.This is the core feature introduced by this PR and the test coverage is appropriate.
157-182: LGTM! Proper validation of method support.The test correctly validates that when using method-only routing, the framework verifies that the endpoint actually supports the assigned method. The intentional assignment to
post(line 169) of an endpoint that only supportsputandpatchproperly triggers an error, ensuring type safety at runtime.express-zod-api/src/routing-walker.ts (4)
22-27: LGTM! Type signature updated to support config-driven routing.The addition of
config: CommonConfigtoRoutingWalkerParamsenables the routing walker to accessmethodLikeRouteBehaviorconfiguration. This is a necessary change for the method-only routing feature.Note: This is part of the breaking change mentioned in the PR description, as all call sites of
walkRoutingmust now provide aconfigparameter.
40-56: LGTM! Core logic correctly implements method-only routing.The implementation properly handles both routing modes:
Method mode (default,
methodLikeRouteBehavior: "method"): When a method-like key (e.g.,get) is assigned to anAbstractEndpoint, the key is interpreted as the HTTP method and the segment is"/", resulting in routing to the parent path.Path mode (
methodLikeRouteBehavior: "path"): Method-like keys are treated as path segments, falling through todetachMethodwhich returns them as regular path components.The three-part condition on lines 49-50 ensures method-only routing only activates when:
- The key is a valid HTTP method
- The config enables method interpretation
- The value is an actual endpoint (not nested routing)
This prevents confusion when method-like keys are used with nested routing structures.
40-42: Verify: Default value is breaking change.The default
methodLikeRouteBehavior = "method"enables the new method-only routing behavior. This means that existing route definitions using method names as path segments (e.g.,{ get: { nested: endpoint } }intending/get/nested) will now be interpreted differently.Ensure this breaking change is:
- ✅ Documented in the PR description
- ✅ Mentioned in CHANGELOG/migration guide
- Communicated in release notes
Users upgrading will need to either:
- Set
methodLikeRouteBehavior: "path"to restore old behavior, or- Rename their routes to avoid method names
86-116: LGTM! Config properly propagated through routing traversal.The
walkRoutingfunction correctly threads theconfigparameter through both the initialprocessEntriescall (line 92) and the recursive call when expanding nested routing structures (line 113). This ensures thatmethodLikeRouteBehavioris consistently applied at all nesting levels.The function maintains all existing validation logic (duplicate checking, method support checking) while integrating the new config-driven behavior seamlessly.
b77e2f1 to
6825c71
Compare
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
RobinTail
left a 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.
I like it
Due to #2938
This will set us free from the requirement to write slash to the keys when we imply method depending routing.
Breaking change:
Integrationrequiresconfigparameter.Summary by CodeRabbit
New Features
methodLikeRouteBehaviorconfiguration option to control interpretation of method-like routing keys ("method" or "path")hasHeadMethodoption for endpoint documentation configurationRefactor
configparameter during initialization