Skip to content

feat(v29): Supporting QUERY method#3479

Merged
RobinTail merged 24 commits into
make-v29from
add-query-method
Jun 21, 2026
Merged

feat(v29): Supporting QUERY method#3479
RobinTail merged 24 commits into
make-v29from
add-query-method

Conversation

@RobinTail

@RobinTail RobinTail commented Jun 20, 2026

Copy link
Copy Markdown
Owner

Supporting HTTP QUERY Method in express-zod-api

Background: What Is HTTP QUERY?

The HTTP QUERY method is defined in RFC 10008 (published June 2026, Standards Track). In essence, QUERY is like GET but with a body. It is a safe and idempotent request method that can carry request content — a combination of properties that no existing standard HTTP method fully satisfies.

QUERY requests that the target resource process the enclosed content (the query) and respond with the result, without changing resource state. The server uses the Content-Type to determine how to interpret the body, and clients can discover QUERY support via the Accept-Query response header.

Key properties:

Property QUERY GET POST
Safe Yes Yes No
Idempotent Yes Yes No
Can have body Yes No Yes
Cacheable Yes Yes With care
Request content in URI Not required Required Not required

Why Use QUERY When GET and POST Already Exist?

Problems with GET for queries

GET encodes the entire query in the URI. This has several drawbacks:

  • URI size limits — many implementations (servers, proxies, CDNs) cap URIs at ~8 KB, making complex queries impossible.
  • Encoding overhead — binary data, complex filters, or structured query languages must be URI-encoded, inflating size and reducing readability.
  • Exposure — URIs are more likely to be logged by intermediaries and bookmarked by users, potentially leaking query details.

Problems with POST for queries

POST is neither safe nor idempotent. Using it for queries means:

  • No safe retries — intermediaries and clients cannot automatically retry a POST on network failure, because the request might have mutated state.
  • No caching — POST responses are not cacheable by default, so repeated identical queries cannot be served from a cache.
  • Semantic mismatch — POST implies creation or mutation; using it for read-only queries confuses tooling, monitoring, and human readers.

How QUERY bridges the gap

QUERY is semantically a read operation (safe, idempotent, cacheable) but with body support like POST. This makes it the natural choice for:

  • Complex search/filter APIs (GraphQL, Elasticsearch, SQL-over-HTTP)
  • APIs with large or structured query payloads
  • Any read operation where the query exceeds URI size limits
  • Safe operations that need content negotiation via Content-Type

What Would It Take to Add QUERY Support?

Current state

  • Node.js (22.19+, 24.x, 26.x) already has QUERY in http.METHODS — the parser accepts it.
  • Express 5.1.x at runtime handles QUERY correctly via its Layer-based routing — Express does not restrict which methods can be routed.
  • Express types (@types/express-serve-static-core) do not list query on IRouter. This is a deliberate policy: Express adds type entries only when the IETF method reaches sufficient maturity. (For reference, Express also does not type "query" despite it being the ?key=val part of a URL — the name collision is coincidental.)

Summary by CodeRabbit

  • New Features
    • Added support for the HTTP QUERY method (RFC 10008), including typed client/endpoints and default input handling (query, body, and path params).
    • Documentation improvements for OpenAPI 3.2.0 (including SSE schema handling) and enhanced security depiction (OAuth2 device authorization).
  • Bug Fixes
    • Improved routing initialization to validate QUERY registration and raise clearer errors when unsupported.
  • Documentation
    • Updated generated docs/snapshots and example payload structure (valuedataValue), and adjusted documentation constructor inputs to info + server.
  • Tests
    • Expanded coverage for QUERY routing, extraction, typing, and documentation output.
  • Chores
    • Updated server startup lifecycle to treat hooks as synchronous, and removed the deprecated Integration.create() factory.

@RobinTail RobinTail added the enhancement New feature or request label Jun 20, 2026
@coveralls-official

coveralls-official Bot commented Jun 20, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 100.0%. remained the same — add-query-method into make-v29

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 294cdbc5-fbcf-4059-9ee4-aea11fe810b4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds HTTP QUERY method support (RFC 10008) with comprehensive type system integration and a runtime guard in route registration. Concurrently removes async patterns from server lifecycle: createServer becomes synchronous, ServerHook callbacks return void only, and Integration.create() static factory is removed. Refactors Documentation constructor from flat parameters (title/version/serverUrl) to nested info/server structure. Upgrades OpenAPI schemas from 3.1 to 3.2 with type migration from SchemaObject to SchemaObjectValue. Adds OAuth2 device flow support and security deprecation flags. Updates ESLint migration rule for v29 breaking changes and CI/packaging for new constraints.

Changes

HTTP QUERY Method Support

Layer / File(s) Summary
QUERY type definitions and input sources
express-zod-api/src/method.ts, express-zod-api/src/common-helpers.ts
"query" added to FamiliarMethod type (excluding "all") and methods array with JSDoc update; defaultInputSources gains query: ["query", "body", "params"] entry.
QUERY route registration with runtime safety check
express-zod-api/src/routing.ts
initRouting imports IRouterMatcher, resolves method-specific matcher from Express app, validates at runtime that QUERY matcher is a function, and registers routes via bound matcher instead of direct app[method] invocation.
RoutingError type safety migration to CORSMethod
express-zod-api/src/errors.ts
RoutingError constructor and cause.method field switch from Method to CORSMethod type for CORS-aware method representation.
QUERY tests, examples, and snapshots
express-zod-api/tests/method.spec.ts, express-zod-api/tests/routing.spec.ts, express-zod-api/tests/common-helpers.spec.ts, express-zod-api/tests/env.spec.ts, express-zod-api/tests/endpoint.spec.ts, express-zod-api/tests/express-mock.ts, express-zod-api/tests/integration.spec.ts, example/example.client.ts, example/endpoints/list-users.ts, example/index.spec.ts, CHANGELOG.md
Type assertions extended for Method/ClientMethod/CORSMethod; routing test verifies QUERY endpoint registration with CORS OPTIONS; input-source and extraction tests confirm default behavior; Node.js METHODS membership tested; endpoint .methods includes "query"; express mock gains query handler; examples and snapshots updated; v28.8.0 changelog entry documents QUERY with generators and behavior.

Synchronous Server and Integration Lifecycle

Layer / File(s) Summary
Synchronous createServer and ServerHook contract
express-zod-api/src/server.ts, express-zod-api/src/config-type.ts
createServer function becomes synchronous; beforeRouting and afterRouting hooks invoked directly without await; ServerHook type returns void only instead of allowing Promise<void>.
Remove Integration.create() static factory
express-zod-api/src/integration.ts
Public static async factory Integration.create() removed; users instantiate new Integration() directly.
Server/integration synchronous tests and examples
express-zod-api/tests/server.spec.ts, express-zod-api/tests/system.spec.ts, example/index.ts, express-zod-api/tests/integration.spec.ts
Test suite converts async/await patterns to synchronous; createServer calls no longer awaited; integration test uses direct constructor; system test reorganizes deprecation warning assertion into beforeAll hook.

Documentation Constructor Refactor and OpenAPI 3.2 Migration

Layer / File(s) Summary
Documentation constructor parameters: info and server
express-zod-api/src/documentation.ts
DocumentationParams changes to accept info: InfoObject (replacing title/version) and flexible server parameter (string, ServerObject, or tuple variants) replacing serverUrl; #addMetadata and #makeRef updated for new shapes.
OpenAPI 3.2 schema type migration from OAS31
express-zod-api/src/documentation-helpers.ts, express-zod-api/src/json-schema-helpers.ts, express-zod-api/tests/documentation-helpers.spec.ts
Type imports switch from openapi3-ts/oas31 SchemaObject to openapi3-ts/oas32 SchemaObjectValue across documentation pipeline; Depicter return type, makeRef/makeSample parameters, and mergeableKeys constraints updated.
Refactored response depiction with per-media examples and itemSchema support
express-zod-api/src/documentation-helpers.ts
depictResponse refactored to iterate over mime types, compute single schemaOrRef, use itemSchema for SSE vs schema for others, attach per-media enumerated examples; example payloads changed from value to dataValue keys.
OAuth2 device flow and security deprecation support
express-zod-api/src/security.ts, express-zod-api/tests/documentation-helpers.spec.ts
Adds DeviceAuthFlow<S> and DeviceAuthUrl for OAuth2 device authorization; extends OAuth2Security with deviceAuthorization field; adds optional deprecated?: boolean to Security<K,S> intersection; depictSecurity preserves deprecated flag per scheme.
Tag depiction with external docs URL shorthand
express-zod-api/src/documentation-helpers.ts, express-zod-api/tests/documentation-helpers.spec.ts
TagDetails interface introduces optional url and parent fields; depictTags converts url shorthand to externalDocs.url in tag objects; test coverage added for tag objects with external docs override.
Documentation tests, examples, and snapshots
express-zod-api/tests/documentation.spec.ts, example/generate-documentation.ts, issue952-test/tags.ts
Test suite refactored to share info/server variables; endpoint method switched to query in "Intersection and And types" test; Documentation example code and test code updated to info/server structure; test coverage added for OAuth2 device flow and deprecated security schemes.
Generated OpenAPI 3.2.0 specification updates
example/example.documentation.yaml
Document version bumped to 3.2.0; /v1/user/list switches from get to query with requestBody added; head operation removed; example payloads use dataValue keys; /v1/events/stream SSE response uses itemSchema.

Migration Rule Updates for v29 Breaking Changes

Layer / File(s) Summary
ESLint migration rule for v29 patterns
migration/index.ts
Query selectors target Integration.create(), createServer(), async lifecycle hooks, and Documentation config literals; handlers transform awaited Integration.create to constructor, remove createServer await, strip async from hooks, and rebuild Documentation objects with info/server mapping.
Migration rule test cases for v29 transformations
migration/index.spec.ts
Test suite validates v29 patterns (Integration/createServer/hooks/Documentation) and asserts migrations for Integration.create removal, createServer await removal, async hook conversion, and Documentation parameter reshaping.

Infrastructure, Workflows, Packaging, and Documentation

Layer / File(s) Summary
GitHub Workflows and OpenAPI validation
.github/workflows/codeql-analysis.yml, .github/workflows/node.js.yml, .github/workflows/oas.yml
CI branch filters include make-v29; Node.js matrix upgraded to 24.11.0; new OpenAPI 3.2 validation workflow added for example/example.documentation.yaml.
Package versions and Node engine constraints
express-zod-api/package.json, migration/package.json, zod-plugin/package.json, .pnpmfile.mjs
express-zod-api upgrades openapi3-ts to ^4.6.0 and Node to ^24.11.0; migration version to 29.0.0-beta.0 with Node tightened; zod-plugin Node to ^24.11.0; Babel compatibility patch removed.
ESLint import restrictions and compatibility test updates
eslint.config.js, compat-test/eslint.config.js, compat-test/migration.spec.ts, compat-test/package.json
ESLint config restricts openapi3-ts/oas3 and SchemaObject imports with guidance to use OAS32 equivalents; compat-test updates migration version to v29 and modifies sample code expectations.
CHANGELOG and README documentation of v29 changes
CHANGELOG.md, README.md
CHANGELOG documents v29.0.0 with Node version, API/lifecycle, and generator updates; v28.8.0 entry describes QUERY support; README examples remove await from createServer and refactor Documentation constructor.
Example application updates for v29 patterns
example/index.ts, example/index.spec.ts, example/generate-documentation.ts, issue952-test/tags.ts
Example removes await from createServer; test skips OpenAPI Documentation test with TODO; example and test code update to info/server structure.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • RobinTail/express-zod-api#3465: Both PRs refactor async-to-sync patterns in express-zod-api/src/integration.ts and express-zod-api/src/server.ts, including Integration.create() factory changes and createServer lifecycle modifications.
  • RobinTail/express-zod-api#3472: Both PRs make createServer() synchronous and update ServerHook to return void only, directly overlapping in express-zod-api/src/server.ts and lifecycle hook handling.
  • RobinTail/express-zod-api#3453: Both PRs refactor the Documentation constructor API from flat parameters to nested info/server structure in express-zod-api/src/documentation.ts.

Poem

🐇 Hippity-hop, a v29 release,
QUERY joins HTTP, giving peace!
Sync'd up the server, deprecated old ways,
Documentation reborn in modern days.
OAuth2 devices and schemas evolve—
The rabbit's grand refactor? Completely resolved! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(v29): Supporting QUERY method' clearly and specifically describes the main change—adding support for the QUERY HTTP method—which aligns with the comprehensive changeset across the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-query-method

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.

@RobinTail RobinTail changed the title feat: Add QUERY method support feat: Supporting QUERY method Jun 20, 2026
@RobinTail

RobinTail commented Jun 20, 2026

Copy link
Copy Markdown
Owner Author
  • needs an update to dataflow diagram

@RobinTail RobinTail marked this pull request as ready for review June 20, 2026 09:21

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ One minor issue — import convention fix needed.

Reviewed changes — adds HTTP QUERY method support (RFC 10008), making "query" a first-class method on EndpointsFactory, with appropriate default input sources and full test coverage.

  • Add "query" to FamiliarMethod, methods, and clientMethods — forces the method name into the type system despite Express types not yet including it, with @todo markers for future cleanup.
  • Add "query" to defaultInputSources["query", "body", "params"] with query params at lowest priority, body in the middle, and route params highest.
  • Add runtime safety check in initRouting — casts app to include the query method and throws RoutingError if the Express runtime doesn't support it.
  • Change RoutingError.cause from Method to CORSMethod — needed because options can also flow through routing paths.
  • Update tests, snapshots, and client generation — comprehensive test coverage for method registration, input sources, type assertions, and environment checks.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

Comment thread express-zod-api/src/routing.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@express-zod-api/src/routing.ts`:
- Line 13: The import statement for RoutingError from "./errors.ts" includes a
`.ts` extension in the relative import path, which violates the compiled code
guideline that requires imports without file extensions. Remove the `.ts`
extension from the import path so it reads "./errors" instead, ensuring
compliance with the coding guidelines for compiled workspace code.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9da551c1-8068-49a0-be96-3bdf80c81944

📥 Commits

Reviewing files that changed from the base of the PR and between 9fbd272 and 8b1c803.

⛔ Files ignored due to path filters (3)
  • express-zod-api/tests/__snapshots__/common-helpers.spec.ts.snap is excluded by !**/*.snap
  • express-zod-api/tests/__snapshots__/documentation.spec.ts.snap is excluded by !**/*.snap
  • express-zod-api/tests/__snapshots__/integration.spec.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (14)
  • CHANGELOG.md
  • example/example.client.ts
  • express-zod-api/src/common-helpers.ts
  • express-zod-api/src/errors.ts
  • express-zod-api/src/method.ts
  • express-zod-api/src/routing.ts
  • express-zod-api/tests/common-helpers.spec.ts
  • express-zod-api/tests/documentation.spec.ts
  • express-zod-api/tests/endpoint.spec.ts
  • express-zod-api/tests/env.spec.ts
  • express-zod-api/tests/express-mock.ts
  • express-zod-api/tests/integration.spec.ts
  • express-zod-api/tests/method.spec.ts
  • express-zod-api/tests/routing.spec.ts

Comment thread express-zod-api/src/routing.ts Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — since the prior pullfrog review, excluded "all" from FamiliarMethod so Express's app.all() is correctly filtered out of the supported HTTP method type union.

  • Exclude "all" from FamiliarMethodIRouter["all"] registers handlers for all HTTP methods, not a real method itself, so it doesn't belong in FamiliarMethod.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — since the prior pullfrog review, the example listUsersEndpoint was converted from GET to QUERY to demonstrate the new method, and all generated artifacts (client types, OpenAPI docs, test) were updated accordingly.

  • Switch example endpoint to QUERYlistUsersEndpoint now uses method: "query" instead of "get", with the client types, example.documentation.yaml, and example test regenerated to match.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@RobinTail

RobinTail commented Jun 20, 2026

Copy link
Copy Markdown
Owner Author

@RobinTail RobinTail added this to the v29 milestone Jun 20, 2026
@RobinTail RobinTail changed the title feat: Supporting QUERY method feat(blocked): Supporting QUERY method Jun 20, 2026
RobinTail added a commit that referenced this pull request Jun 20, 2026
@RobinTail RobinTail changed the title feat(blocked): Supporting QUERY method feat: Supporting QUERY method Jun 20, 2026
@RobinTail RobinTail changed the title feat: Supporting QUERY method feat(v29): Supporting QUERY method Jun 20, 2026
@RobinTail RobinTail changed the base branch from master to make-v29 June 20, 2026 15:38
@RobinTail

Copy link
Copy Markdown
Owner Author

rebased against #3469

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — adds HTTP QUERY method support (RFC 10008) across the type system, routing, input resolution, integration, and documentation layers, with comprehensive test coverage.

  • Add "query" to FamiliarMethod and method arrays — with @todo markers for cleanup when Express types catch up, and exclusion of "all" from the familiar set.
  • Add "query" to defaultInputSources["query", "body", "params"] giving body priority over query params for QUERY requests.
  • Broaden RoutingError.cause from Method to CORSMethod — needed because options can flow through routing.
  • Add runtime safety check in initRouting — casts app and throws RoutingError if Express runtime lacks query support, using .bind(app) for correct this context.
  • Convert example listUsersEndpoint from GET to QUERY — regenerated client types, OpenAPI docs, and tests.
  • Update tests and snapshots — method type tests, routing registration tests, environment check for http.METHODS, input source resolution, and integration/documentation snapshot matches.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
express-zod-api/src/server.ts (1)

83-93: ⚠️ Potential issue | 🟠 Major

Guard against Promise-returning lifecycle hooks.

Lines 83 and 93 currently ignore returned values. In TypeScript, async callbacks can still be assignable to void-return hook types, so rejected Promises can become unhandled and hook side effects can race startup/routing.

💡 Proposed fix
+const assertSyncHook = (
+  hook: "beforeRouting" | "afterRouting",
+  result: unknown,
+) => {
+  if (result && typeof (result as PromiseLike<unknown>).then === "function") {
+    throw new Error(
+      `${hook} must be synchronous in v29. Move async initialization before createServer().`,
+    );
+  }
+};
+
 export const createServer = (config: ServerConfig, routing: Routing) => {
@@
-  config.beforeRouting?.({ app, getLogger });
+  assertSyncHook("beforeRouting", config.beforeRouting?.({ app, getLogger }));
@@
-  config.afterRouting?.({ app, getLogger });
+  assertSyncHook("afterRouting", config.afterRouting?.({ app, getLogger }));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@express-zod-api/src/server.ts` around lines 83 - 93, The lifecycle hooks
config.beforeRouting and config.afterRouting at lines 83 and 93 may return
Promises, but their return values are currently ignored, which can lead to
unhandled Promise rejections and race conditions with side effects. Capture the
return values from both config.beforeRouting and config.afterRouting hook
invocations and await them to ensure they complete before proceeding with the
next operations, using Promise.resolve to safely handle both synchronous and
asynchronous return values.
🧹 Nitpick comments (1)
express-zod-api/src/security.ts (1)

77-80: ⚡ Quick win

Use an interface for the new object-shaped flow type

Line 77 introduces an object-shaped type alias. Please switch it to an interface to match the TypeScript guideline used in this repo.

Proposed fix
-type DeviceAuthFlow<S extends string> = DeviceAuthUrl &
-  TokenUrl &
-  RefreshUrl &
-  Scopes<S>;
+interface DeviceAuthFlow<S extends string>
+  extends DeviceAuthUrl,
+    TokenUrl,
+    RefreshUrl,
+    Scopes<S> {}

As per coding guidelines, **/*.ts: “Declare object-based types as interfaces, not type aliases.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@express-zod-api/src/security.ts` around lines 77 - 80, The DeviceAuthFlow
type alias on lines 77-80 uses a type alias to define an object-shaped type, but
the repository guidelines require using interfaces instead of type aliases for
object-based types. Convert the DeviceAuthFlow type alias to an interface by
replacing the type keyword and equals sign with the interface keyword, and
adjust the body to list the constituent types as interface extensions using the
extends keyword instead of the intersection operator.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/oas.yml:
- Around line 3-6: The workflow trigger configuration in the push and
pull_request sections is missing the v29 branch. Add v29 to the branches array
in both the push trigger block and the pull_request trigger block so that the
workflow executes for pushes and pull requests targeting the new v29 branch in
addition to the existing master, v25, v26, and v27 branches.
- Around line 16-19: Replace the mutable version tags in both the
actions/checkout and swaggerexpert/apidom-validate actions with specific commit
SHAs for improved supply chain security. For the actions/checkout action, also
add the persist-credentials parameter set to false since this workflow is
read-only and does not require writable credentials. Look up the latest stable
commit SHAs for each action and substitute them in place of the version tag
references.

In `@example/index.spec.ts`:
- Around line 609-610: The OpenAPI Documentation test suite (describe.skip block
at line 609-610 in example/index.spec.ts) is disabled locally with the
expectation that validation is handled by the .github/workflows/oas.yml
workflow. However, that workflow currently does not run on the make-v29 branch,
leaving the branch without OpenAPI validation coverage. Before keeping the
describe.skip directive in place, update the .github/workflows/oas.yml file to
ensure it runs on the make-v29 branch by adding make-v29 to the branch
configuration or trigger conditions in the workflow file.

In `@express-zod-api/src/documentation.ts`:
- Around line 67-71: Make the `server` property optional in the type definition
by adding a question mark (making it `server?:`) around line 67, and then add a
guard check in the code that registers metadata (around line 179) to verify that
`server` exists before attempting to use it. This ensures the Documentation
class can be instantiated without providing a `server` property and prevents
runtime errors when `addServer` or similar metadata registration methods receive
undefined values from JavaScript consumers.

In `@express-zod-api/src/security.ts`:
- Around line 87-91: The optional OAuth2 fields oauth2MetadataUrl and
deviceAuthorization are missing the required `@default` JSDoc tag in their
documentation blocks. Add `@default` tags to the JSDoc comments for both
oauth2MetadataUrl? (around line 87-91) and deviceAuthorization? (around line
101-105) to indicate their default values, following the coding guidelines that
require all public properties in express-zod-api/src/*.ts files to have `@desc`,
`@default` for optional properties, and `@example` directives.

In `@migration/index.ts`:
- Around line 124-147: The documentationConfig handler silently drops title and
version properties when an info property already exists in the config. When the
info property is encountered, infoItems is set to undefined, and then when title
or version properties are subsequently processed, the optional chaining
infoItems?.push() silently does nothing without adding these properties to
parts. To fix this, modify the logic for handling title and version properties
to check whether infoItems is undefined (indicating info already exists) and
either add them to parts to preserve the legacy properties in the output, or
throw an error or log a warning to explicitly inform the user that both info and
legacy title/version properties cannot coexist in the same config.

---

Outside diff comments:
In `@express-zod-api/src/server.ts`:
- Around line 83-93: The lifecycle hooks config.beforeRouting and
config.afterRouting at lines 83 and 93 may return Promises, but their return
values are currently ignored, which can lead to unhandled Promise rejections and
race conditions with side effects. Capture the return values from both
config.beforeRouting and config.afterRouting hook invocations and await them to
ensure they complete before proceeding with the next operations, using
Promise.resolve to safely handle both synchronous and asynchronous return
values.

---

Nitpick comments:
In `@express-zod-api/src/security.ts`:
- Around line 77-80: The DeviceAuthFlow type alias on lines 77-80 uses a type
alias to define an object-shaped type, but the repository guidelines require
using interfaces instead of type aliases for object-based types. Convert the
DeviceAuthFlow type alias to an interface by replacing the type keyword and
equals sign with the interface keyword, and adjust the body to list the
constituent types as interface extensions using the extends keyword instead of
the intersection operator.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c8a35ca1-dea2-46e5-810d-9e8031382c7c

📥 Commits

Reviewing files that changed from the base of the PR and between 67fce61 and 81204da.

⛔ Files ignored due to path filters (6)
  • express-zod-api/tests/__snapshots__/common-helpers.spec.ts.snap is excluded by !**/*.snap
  • express-zod-api/tests/__snapshots__/documentation-helpers.spec.ts.snap is excluded by !**/*.snap
  • express-zod-api/tests/__snapshots__/documentation.spec.ts.snap is excluded by !**/*.snap
  • express-zod-api/tests/__snapshots__/integration.spec.ts.snap is excluded by !**/*.snap
  • migration/__snapshots__/index.spec.ts.snap is excluded by !**/*.snap
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (44)
  • .github/workflows/codeql-analysis.yml
  • .github/workflows/node.js.yml
  • .github/workflows/oas.yml
  • .pnpmfile.mjs
  • CHANGELOG.md
  • README.md
  • compat-test/eslint.config.js
  • compat-test/migration.spec.ts
  • compat-test/package.json
  • eslint.config.js
  • example/endpoints/list-users.ts
  • example/example.client.ts
  • example/example.documentation.yaml
  • example/generate-documentation.ts
  • example/index.spec.ts
  • example/index.ts
  • express-zod-api/package.json
  • express-zod-api/src/common-helpers.ts
  • express-zod-api/src/config-type.ts
  • express-zod-api/src/documentation-helpers.ts
  • express-zod-api/src/documentation.ts
  • express-zod-api/src/errors.ts
  • express-zod-api/src/integration.ts
  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/src/method.ts
  • express-zod-api/src/routing.ts
  • express-zod-api/src/security.ts
  • express-zod-api/src/server.ts
  • express-zod-api/tests/common-helpers.spec.ts
  • express-zod-api/tests/documentation-helpers.spec.ts
  • express-zod-api/tests/documentation.spec.ts
  • express-zod-api/tests/endpoint.spec.ts
  • express-zod-api/tests/env.spec.ts
  • express-zod-api/tests/express-mock.ts
  • express-zod-api/tests/integration.spec.ts
  • express-zod-api/tests/method.spec.ts
  • express-zod-api/tests/routing.spec.ts
  • express-zod-api/tests/server.spec.ts
  • express-zod-api/tests/system.spec.ts
  • issue952-test/tags.ts
  • migration/index.spec.ts
  • migration/index.ts
  • migration/package.json
  • zod-plugin/package.json
💤 Files with no reviewable changes (2)
  • .pnpmfile.mjs
  • express-zod-api/src/integration.ts
✅ Files skipped from review due to trivial changes (8)
  • example/index.ts
  • compat-test/migration.spec.ts
  • zod-plugin/package.json
  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/tests/express-mock.ts
  • README.md
  • express-zod-api/tests/endpoint.spec.ts
  • CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (10)
  • express-zod-api/src/common-helpers.ts
  • express-zod-api/src/errors.ts
  • example/endpoints/list-users.ts
  • express-zod-api/tests/env.spec.ts
  • express-zod-api/tests/common-helpers.spec.ts
  • express-zod-api/tests/routing.spec.ts
  • express-zod-api/src/method.ts
  • express-zod-api/tests/method.spec.ts
  • express-zod-api/src/routing.ts
  • example/example.client.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
express-zod-api/src/server.ts (1)

83-93: ⚠️ Potential issue | 🟠 Major

Guard against Promise-returning lifecycle hooks.

Lines 83 and 93 currently ignore returned values. In TypeScript, async callbacks can still be assignable to void-return hook types, so rejected Promises can become unhandled and hook side effects can race startup/routing.

💡 Proposed fix
+const assertSyncHook = (
+  hook: "beforeRouting" | "afterRouting",
+  result: unknown,
+) => {
+  if (result && typeof (result as PromiseLike<unknown>).then === "function") {
+    throw new Error(
+      `${hook} must be synchronous in v29. Move async initialization before createServer().`,
+    );
+  }
+};
+
 export const createServer = (config: ServerConfig, routing: Routing) => {
@@
-  config.beforeRouting?.({ app, getLogger });
+  assertSyncHook("beforeRouting", config.beforeRouting?.({ app, getLogger }));
@@
-  config.afterRouting?.({ app, getLogger });
+  assertSyncHook("afterRouting", config.afterRouting?.({ app, getLogger }));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@express-zod-api/src/server.ts` around lines 83 - 93, The lifecycle hooks
config.beforeRouting and config.afterRouting at lines 83 and 93 may return
Promises, but their return values are currently ignored, which can lead to
unhandled Promise rejections and race conditions with side effects. Capture the
return values from both config.beforeRouting and config.afterRouting hook
invocations and await them to ensure they complete before proceeding with the
next operations, using Promise.resolve to safely handle both synchronous and
asynchronous return values.
🧹 Nitpick comments (1)
express-zod-api/src/security.ts (1)

77-80: ⚡ Quick win

Use an interface for the new object-shaped flow type

Line 77 introduces an object-shaped type alias. Please switch it to an interface to match the TypeScript guideline used in this repo.

Proposed fix
-type DeviceAuthFlow<S extends string> = DeviceAuthUrl &
-  TokenUrl &
-  RefreshUrl &
-  Scopes<S>;
+interface DeviceAuthFlow<S extends string>
+  extends DeviceAuthUrl,
+    TokenUrl,
+    RefreshUrl,
+    Scopes<S> {}

As per coding guidelines, **/*.ts: “Declare object-based types as interfaces, not type aliases.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@express-zod-api/src/security.ts` around lines 77 - 80, The DeviceAuthFlow
type alias on lines 77-80 uses a type alias to define an object-shaped type, but
the repository guidelines require using interfaces instead of type aliases for
object-based types. Convert the DeviceAuthFlow type alias to an interface by
replacing the type keyword and equals sign with the interface keyword, and
adjust the body to list the constituent types as interface extensions using the
extends keyword instead of the intersection operator.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/oas.yml:
- Around line 3-6: The workflow trigger configuration in the push and
pull_request sections is missing the v29 branch. Add v29 to the branches array
in both the push trigger block and the pull_request trigger block so that the
workflow executes for pushes and pull requests targeting the new v29 branch in
addition to the existing master, v25, v26, and v27 branches.
- Around line 16-19: Replace the mutable version tags in both the
actions/checkout and swaggerexpert/apidom-validate actions with specific commit
SHAs for improved supply chain security. For the actions/checkout action, also
add the persist-credentials parameter set to false since this workflow is
read-only and does not require writable credentials. Look up the latest stable
commit SHAs for each action and substitute them in place of the version tag
references.

In `@example/index.spec.ts`:
- Around line 609-610: The OpenAPI Documentation test suite (describe.skip block
at line 609-610 in example/index.spec.ts) is disabled locally with the
expectation that validation is handled by the .github/workflows/oas.yml
workflow. However, that workflow currently does not run on the make-v29 branch,
leaving the branch without OpenAPI validation coverage. Before keeping the
describe.skip directive in place, update the .github/workflows/oas.yml file to
ensure it runs on the make-v29 branch by adding make-v29 to the branch
configuration or trigger conditions in the workflow file.

In `@express-zod-api/src/documentation.ts`:
- Around line 67-71: Make the `server` property optional in the type definition
by adding a question mark (making it `server?:`) around line 67, and then add a
guard check in the code that registers metadata (around line 179) to verify that
`server` exists before attempting to use it. This ensures the Documentation
class can be instantiated without providing a `server` property and prevents
runtime errors when `addServer` or similar metadata registration methods receive
undefined values from JavaScript consumers.

In `@express-zod-api/src/security.ts`:
- Around line 87-91: The optional OAuth2 fields oauth2MetadataUrl and
deviceAuthorization are missing the required `@default` JSDoc tag in their
documentation blocks. Add `@default` tags to the JSDoc comments for both
oauth2MetadataUrl? (around line 87-91) and deviceAuthorization? (around line
101-105) to indicate their default values, following the coding guidelines that
require all public properties in express-zod-api/src/*.ts files to have `@desc`,
`@default` for optional properties, and `@example` directives.

In `@migration/index.ts`:
- Around line 124-147: The documentationConfig handler silently drops title and
version properties when an info property already exists in the config. When the
info property is encountered, infoItems is set to undefined, and then when title
or version properties are subsequently processed, the optional chaining
infoItems?.push() silently does nothing without adding these properties to
parts. To fix this, modify the logic for handling title and version properties
to check whether infoItems is undefined (indicating info already exists) and
either add them to parts to preserve the legacy properties in the output, or
throw an error or log a warning to explicitly inform the user that both info and
legacy title/version properties cannot coexist in the same config.

---

Outside diff comments:
In `@express-zod-api/src/server.ts`:
- Around line 83-93: The lifecycle hooks config.beforeRouting and
config.afterRouting at lines 83 and 93 may return Promises, but their return
values are currently ignored, which can lead to unhandled Promise rejections and
race conditions with side effects. Capture the return values from both
config.beforeRouting and config.afterRouting hook invocations and await them to
ensure they complete before proceeding with the next operations, using
Promise.resolve to safely handle both synchronous and asynchronous return
values.

---

Nitpick comments:
In `@express-zod-api/src/security.ts`:
- Around line 77-80: The DeviceAuthFlow type alias on lines 77-80 uses a type
alias to define an object-shaped type, but the repository guidelines require
using interfaces instead of type aliases for object-based types. Convert the
DeviceAuthFlow type alias to an interface by replacing the type keyword and
equals sign with the interface keyword, and adjust the body to list the
constituent types as interface extensions using the extends keyword instead of
the intersection operator.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c8a35ca1-dea2-46e5-810d-9e8031382c7c

📥 Commits

Reviewing files that changed from the base of the PR and between 67fce61 and 81204da.

⛔ Files ignored due to path filters (6)
  • express-zod-api/tests/__snapshots__/common-helpers.spec.ts.snap is excluded by !**/*.snap
  • express-zod-api/tests/__snapshots__/documentation-helpers.spec.ts.snap is excluded by !**/*.snap
  • express-zod-api/tests/__snapshots__/documentation.spec.ts.snap is excluded by !**/*.snap
  • express-zod-api/tests/__snapshots__/integration.spec.ts.snap is excluded by !**/*.snap
  • migration/__snapshots__/index.spec.ts.snap is excluded by !**/*.snap
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (44)
  • .github/workflows/codeql-analysis.yml
  • .github/workflows/node.js.yml
  • .github/workflows/oas.yml
  • .pnpmfile.mjs
  • CHANGELOG.md
  • README.md
  • compat-test/eslint.config.js
  • compat-test/migration.spec.ts
  • compat-test/package.json
  • eslint.config.js
  • example/endpoints/list-users.ts
  • example/example.client.ts
  • example/example.documentation.yaml
  • example/generate-documentation.ts
  • example/index.spec.ts
  • example/index.ts
  • express-zod-api/package.json
  • express-zod-api/src/common-helpers.ts
  • express-zod-api/src/config-type.ts
  • express-zod-api/src/documentation-helpers.ts
  • express-zod-api/src/documentation.ts
  • express-zod-api/src/errors.ts
  • express-zod-api/src/integration.ts
  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/src/method.ts
  • express-zod-api/src/routing.ts
  • express-zod-api/src/security.ts
  • express-zod-api/src/server.ts
  • express-zod-api/tests/common-helpers.spec.ts
  • express-zod-api/tests/documentation-helpers.spec.ts
  • express-zod-api/tests/documentation.spec.ts
  • express-zod-api/tests/endpoint.spec.ts
  • express-zod-api/tests/env.spec.ts
  • express-zod-api/tests/express-mock.ts
  • express-zod-api/tests/integration.spec.ts
  • express-zod-api/tests/method.spec.ts
  • express-zod-api/tests/routing.spec.ts
  • express-zod-api/tests/server.spec.ts
  • express-zod-api/tests/system.spec.ts
  • issue952-test/tags.ts
  • migration/index.spec.ts
  • migration/index.ts
  • migration/package.json
  • zod-plugin/package.json
💤 Files with no reviewable changes (2)
  • .pnpmfile.mjs
  • express-zod-api/src/integration.ts
✅ Files skipped from review due to trivial changes (8)
  • example/index.ts
  • compat-test/migration.spec.ts
  • zod-plugin/package.json
  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/tests/express-mock.ts
  • README.md
  • express-zod-api/tests/endpoint.spec.ts
  • CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (10)
  • express-zod-api/src/common-helpers.ts
  • express-zod-api/src/errors.ts
  • example/endpoints/list-users.ts
  • express-zod-api/tests/env.spec.ts
  • express-zod-api/tests/common-helpers.spec.ts
  • express-zod-api/tests/routing.spec.ts
  • express-zod-api/src/method.ts
  • express-zod-api/tests/method.spec.ts
  • express-zod-api/src/routing.ts
  • example/example.client.ts
🛑 Comments failed to post (6)
.github/workflows/oas.yml (2)

3-6: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Include the v29 branch in the workflow trigger.

This workflow still only runs for master/v25/v26/v27, so it will miss pushes and PRs for the new v29 line this PR is meant to validate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/oas.yml around lines 3 - 6, The workflow trigger
configuration in the push and pull_request sections is missing the v29 branch.
Add v29 to the branches array in both the push trigger block and the
pull_request trigger block so that the workflow executes for pushes and pull
requests targeting the new v29 branch in addition to the existing master, v25,
v26, and v27 branches.

16-19: ⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/oas.yml

Repository: RobinTail/express-zod-api

Length of output: 664


🏁 Script executed:

find .github/workflows -name "*.yml" -o -name "*.yaml" | head -20

Repository: RobinTail/express-zod-api

Length of output: 285


🏁 Script executed:

head -30 .github/workflows/bump.yml

Repository: RobinTail/express-zod-api

Length of output: 655


🏁 Script executed:

head -30 .github/workflows/node.js.yml

Repository: RobinTail/express-zod-api

Length of output: 973


🏁 Script executed:

head -30 .github/workflows/npm-publish.yml

Repository: RobinTail/express-zod-api

Length of output: 738


🏁 Script executed:

grep -r "uses:" .github/workflows/*.yml | head -30

Repository: RobinTail/express-zod-api

Length of output: 1785


🏁 Script executed:

grep -r "persist-credentials" .github/workflows/

Repository: RobinTail/express-zod-api

Length of output: 51


🏁 Script executed:

cat .github/workflows/codeql-analysis.yml | grep -A 5 "checkout"

Repository: RobinTail/express-zod-api

Length of output: 234


🏁 Script executed:

cat .github/workflows/npm-publish.yml | grep -A 5 "permissions"

Repository: RobinTail/express-zod-api

Length of output: 224


Pin the actions to commit SHAs and disable persisted checkout credentials.

actions/checkout@v6 and swaggerexpert/apidom-validate@v1 use mutable version tags; pin both to commit SHAs for supply chain security. Also set persist-credentials: false on checkout since this job is read-only and does not need writable credentials.

🧰 Tools
🪛 zizmor (1.25.2)

[warning] 16-17: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 17-17: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 19-19: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/oas.yml around lines 16 - 19, Replace the mutable version
tags in both the actions/checkout and swaggerexpert/apidom-validate actions with
specific commit SHAs for improved supply chain security. For the
actions/checkout action, also add the persist-credentials parameter set to false
since this workflow is read-only and does not require writable credentials. Look
up the latest stable commit SHAs for each action and substitute them in place of
the version tag references.

Source: Linters/SAST tools

example/index.spec.ts (1)

609-610: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Restore OpenAPI validation coverage for make-v29 before skipping this suite.

Line 609 disables the local docs test, but the replacement workflow (.github/workflows/oas.yml) currently does not run on
make-v29. That leaves this branch without OpenAPI validation.

Suggested fix (`.github/workflows/oas.yml`)
 on:
   push:
-    branches: [ master, v25, v26, v27 ]
+    branches: [ master, v25, v26, v27, make-v29 ]
   pull_request:
-    branches: [ master, v25, v26, v27 ]
+    branches: [ master, v25, v26, v27, make-v29 ]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@example/index.spec.ts` around lines 609 - 610, The OpenAPI Documentation test
suite (describe.skip block at line 609-610 in example/index.spec.ts) is disabled
locally with the expectation that validation is handled by the
.github/workflows/oas.yml workflow. However, that workflow currently does not
run on the make-v29 branch, leaving the branch without OpenAPI validation
coverage. Before keeping the describe.skip directive in place, update the
.github/workflows/oas.yml file to ensure it runs on the make-v29 branch by
adding make-v29 to the branch configuration or trigger conditions in the
workflow file.
express-zod-api/src/documentation.ts (1)

67-71: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make server optional and guard metadata registration.

Line 67 currently requires server, and Line 179 assumes it always exists. That conflicts with the migrated constructor shape that may omit server (new Documentation({ info, routing, config })), and can pass undefined to addServer at runtime in JS consumers.

Suggested fix
 interface DocumentationParams {
   /** `@desc` At least title and version properties are required */
   info: InfoObject;
   /** `@desc` Server URL(s) or their complete definitions */
-  server:
+  server?:
     | string
     | [string, ...string[]]
     | ServerObject
     | [ServerObject, ...ServerObject[]];
@@
   `#addMetadata`({ tags, info, server }: DocumentationParams) {
     this.addInfo(info);
     if (tags) this.rootDoc.tags = depictTags(tags);
-    for (const one of Array.isArray(server) ? server : [server])
-      this.addServer(typeof one === "string" ? { url: one } : one);
+    if (server) {
+      for (const one of Array.isArray(server) ? server : [server]) {
+        this.addServer(typeof one === "string" ? { url: one } : one);
+      }
+    }
   }

Also applies to: 176-180

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@express-zod-api/src/documentation.ts` around lines 67 - 71, Make the `server`
property optional in the type definition by adding a question mark (making it
`server?:`) around line 67, and then add a guard check in the code that
registers metadata (around line 179) to verify that `server` exists before
attempting to use it. This ensures the Documentation class can be instantiated
without providing a `server` property and prevents runtime errors when
`addServer` or similar metadata registration methods receive undefined values
from JavaScript consumers.
express-zod-api/src/security.ts (1)

87-91: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add missing @default tags for optional OAuth2 fields

Line 91 (oauth2MetadataUrl?) and Line 105 (deviceAuthorization?) are optional, but their JSDoc blocks miss @default, which is required for public properties in express-zod-api/src/*.ts.

Proposed fix
   /**
    * `@desc` URL to OAuth 2.0 Authorization Server metadata document
+   * `@default` undefined
    * `@link` https://www.rfc-editor.org/rfc/rfc8414
    * */
   oauth2MetadataUrl?: string;
@@
     /**
      * `@desc` Device Authorization flow (OAuth 2.0 Device Authorization Grant)
+     * `@default` undefined
      * `@link` https://oauth.net/2/device-flow/
      * */
     deviceAuthorization?: DeviceAuthFlow<S>;

As per coding guidelines, express-zod-api/src/*.ts: “All properties of publicly available entities (exported via index.ts) must have JSDoc documentation with @desc, @default (for optional properties), and @example (for literal types) directives.”

Also applies to: 101-105

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@express-zod-api/src/security.ts` around lines 87 - 91, The optional OAuth2
fields oauth2MetadataUrl and deviceAuthorization are missing the required
`@default` JSDoc tag in their documentation blocks. Add `@default` tags to the JSDoc
comments for both oauth2MetadataUrl? (around line 87-91) and
deviceAuthorization? (around line 101-105) to indicate their default values,
following the coding guidelines that require all public properties in
express-zod-api/src/*.ts files to have `@desc`, `@default` for optional properties,
and `@example` directives.

Source: Coding guidelines

migration/index.ts (1)

124-147: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Edge case: title/version props are silently dropped when info already exists.

If a user's config contains both an info property and legacy title/version properties (e.g., partially migrated code), this handler will:

  1. Add the info prop to parts and set infoItems = undefined (line 137)
  2. Skip adding title/version to either parts or infoItems (line 140 does nothing via optional chaining)
  3. Still report a change because changelog has an entry

Result: The title/version properties are silently lost in the output.

Consider either preserving the legacy props in parts when info already exists, or explicitly warning when both forms are present.

Suggested fix
          } else if (propName === "title" || propName === "version") {
-           changelog["title, version"] = infoItems ? "info" : "";
-           infoItems?.push(ctx.sourceCode.getText(prop));
+           if (infoItems) {
+             changelog["title, version"] = "info";
+             infoItems.push(ctx.sourceCode.getText(prop));
+           } else {
+             // info already exists; preserve legacy props to avoid data loss
+             parts.push(ctx.sourceCode.getText(prop));
+           }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@migration/index.ts` around lines 124 - 147, The documentationConfig handler
silently drops title and version properties when an info property already exists
in the config. When the info property is encountered, infoItems is set to
undefined, and then when title or version properties are subsequently processed,
the optional chaining infoItems?.push() silently does nothing without adding
these properties to parts. To fix this, modify the logic for handling title and
version properties to check whether infoItems is undefined (indicating info
already exists) and either add them to parts to preserve the legacy properties
in the output, or throw an error or log a warning to explicitly inform the user
that both info and legacy title/version properties cannot coexist in the same
config.

Comment thread express-zod-api/src/routing.ts Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — since the prior pullfrog review, the CHANGELOG entry for QUERY was moved into the v29 section, and the routing registration was refactored from .bind(app)(...) to .call(app, ...) with a simpler type annotation.

  • Move QUERY CHANGELOG entry to v29 — relocated from v28.8.0 section to sit alongside other v29 features.
  • Refactor routing registration from bind to call — replaced .bind(app)(path, ...handlers) with .call(app, path, ...handlers) and simplified the register type from IRouterMatcher<IRouter> to a plain function type, avoiding an unnecessary intermediate bound function.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — since the prior pullfrog review, removed the runtime safety check for the QUERY method and switched to .call(app, ...) for more direct invocation.

  • Removed QUERY runtime safety check — the engines restriction (^22.19.0) ensures Node.js 22.19+ which includes QUERY in http.METHODS, so the guard is dead code. This also let errors.ts revert to its pre-PR state, removing the unnecessary CORSMethod broadening.
  • Switched .bind(app) to .call(app, path, ...handlers) — invokes the register function directly with the correct this context in one shot, avoiding an intermediate bound function.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@RobinTail

Copy link
Copy Markdown
Owner Author

@pullfrog let me know if I forget something

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — adds HTTP QUERY method (RFC 10008) support, a safe+idempotent method with body semantics, integrated across the full framework surface.

  • Add "query" to FamiliarMethod type and methods array — also excludes "all" (not a real HTTP method) from the type pool.
  • Wire routing for QUERY — uses a type assertion + .call() bridge to work around Express types not yet listing "query" on IRouter.
  • Define default input sources for QUERY["query", "body", "params"] giving body higher priority than query params.
  • Update example, tests, and snapshotslist-users endpoint switches from GET to QUERY; integration, documentation, routing, method, endpoint, and common-helpers tests all cover the new method.
  • Update Integration and Documentation generators — client code types use Query prefix, generated Method union includes "query", hasBody correctly evaluates to true for QUERY.
  • Environment checkenv.spec.ts asserts Node.js http.METHODS includes QUERY.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — since the prior pullfrog review, QUERY method endpoints now correctly keep isQueryEnabled input properties in the request body, since the body IS the semantic query for the QUERY method.

  • Exclude "query" from query-param rendering in depictRequestParamsgetLocation now skips isQueryEnabled inputs when method === "query", so those properties stay in the request body rather than being redundantly shown as URL query parameters.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@RobinTail RobinTail merged commit b0bce41 into make-v29 Jun 21, 2026
14 checks passed
@RobinTail RobinTail deleted the add-query-method branch June 21, 2026 08:05
RobinTail added a commit that referenced this pull request Jul 2, 2026
1. Related to #3479 
2. Restores #1733 
3. Partially reverts #1741 to support both JSON and more conventional
URL-encoded body types for QUERY method
4. Splits CORS to maintain handling for the issue #2706 
5. Changes the type of the `cors` config option (breaking) to support
RequestHandler, such as a middleware provided by the well-known `cors`
library
6. Featuring `beforeParsers` hook, while `beforeRouting` remains exactly
before calling `initRouting()`

---------

Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant