Skip to content

Conversation

@RobinTail
Copy link
Owner

@RobinTail RobinTail commented Sep 28, 2025

module: node20 introduced in Typescript 5.9 as a stable replacement for nodenext:
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-9.html#support-for---module-node20

The recommended combination is with moduleResolution: node16:
microsoft/TypeScript#61805

That change implies relative imports to have extensions, however, it's possible to change them directly to .ts, which will also reiterate and resolve #2289 . It will enable running typescript natively by Node.js without tsx. It may also come handy if I decide to publish to JSR.

Summary by CodeRabbit

  • Chores
    • Project build and compiler settings standardized; JSON imports made explicit and some tooling switched to static JSON imports.
  • Refactor
    • Internal module references normalized to explicit TypeScript entries; some runtime identifiers now derive from environment-provided build metadata.
  • Tests
    • Test imports updated for explicit module resolution; migration tests expanded with additional valid cases.
  • Style
    • New lint rules encourage .ts extensions for local imports and discourage direct package.json imports.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 28, 2025

Walkthrough

Repository-wide normalization: convert many local import specifiers to explicit .ts extensions, remove per-package tsconfig compilerOptions in favor of root settings, replace dynamic JSON reads with ESM JSON imports, and switch some global Symbol keys to use Symbol.for(process.env.TSDOWN_SELF!).

Changes

Cohort / File(s) Summary
Import specifier updates
express-zod-api/src/*, zod-plugin/src/*, example/*, tools/*, migration/*, compat-test/*, esm-test/*, **/tests/*
Replaced many local/bare imports with explicit .ts specifiers (including type-only imports); tests updated to import index.ts or explicit .ts modules.
tsconfig consolidation
tsconfig.json, express-zod-api/tsconfig.json, example/tsconfig.json, esm-test/tsconfig.json, migration/tsconfig.json, tools/tsconfig.json
Root tsconfig.json now contains module/target/allowImportingTsExtensions/resolveJsonModule; package-level tsconfigs had their compilerOptions removed and now extend the root.
JSON / manifest imports
tools/license.ts, express-zod-api/tsdown.config.ts, zod-plugin/tsdown.config.ts, migration/index.spec.ts, other tools/tests
Replaced dynamic fs+JSON.parse or ambiguous imports with static ESM JSON imports using with { type: "json" }; code now reads manifest.version/manifest.name.
Env-driven Symbol keys
express-zod-api/src/server-helpers.ts, zod-plugin/src/runtime.ts, zod-plugin/tsdown.config.ts, express-zod-api/tsdown.config.ts
Global Symbols and plugin flags now use Symbol.for(process.env.TSDOWN_SELF!) (env injected via tsdown configs) instead of prior module-local identifiers.
Build / lint & generators
eslint.config.js, tools/make-tests.ts, tools/license.ts, example/generate-client.ts, example/generate-documentation.ts
Added ESLint rules nudging .ts extensions and package.json import concerns; updated generators/tools to emit/use explicit .ts imports and typed JSON imports.
Minor runtime change
express-zod-api/src/server-helpers.ts
localsID initialization changed to Symbol.for(process.env.TSDOWN_SELF!) replacing the previous self-based key.

Sequence Diagram(s)

sequenceDiagram
  participant TSDown as tsdown build
  participant Env as process.env
  participant Module as runtime module (zod-plugin / server-helpers)
  Note over TSDown: tsdown.config.ts imports package.json\nand defines TSDOWN_SELF = manifest.name
  TSDown->>Env: set process.env.TSDOWN_SELF
  Env->>Module: Module reads process.env.TSDOWN_SELF
  Module->>Module: pluginFlag = Symbol.for(process.env.TSDOWN_SELF!)
  alt pluginFlag not present on globalThis
    Module->>Global: attach augmentations (e.g., Zod prototypes)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

breaking

Poem

I nibbled imports neat and small,
Added .ts to one and all.
Manifest snug, env set right,
Symbols hop into the night —
A tidy burrow, build takes flight! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The migration test updates in migration/index.spec.ts introduce dynamic rule name logic and additional test cases that are unrelated to the import-extension and tsconfig changes defined in the linked issue, indicating an out-of-scope feature change. Please isolate the migration rule name updates and expanded test cases into a separate pull request to maintain focus on tsconfig and import extension refactoring.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly describes the main changes by indicating the tsconfig update to module: node20 and the adoption of import extensions, clearly reflecting the core refactoring in this pull request.
Linked Issues Check ✅ Passed The pull request fully implements the import extension standardization by updating all relative import specifiers to include .ts and updates the TypeScript configuration to module: node20 with appropriate compiler flags, satisfying the primary goals of issue #2289.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch strict-module-node20

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 791bca5 and 5434de3.

📒 Files selected for processing (1)
  • migration/index.spec.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2974
File: express-zod-api/src/zts-helpers.ts:2-3
Timestamp: 2025-09-29T06:00:10.793Z
Learning: tsdown handles module resolution and bundling independently of TypeScript's native compilation settings like rewriteRelativeImportExtensions, making such TypeScript emit-related configuration unnecessary when using tsdown for builds.
📚 Learning: 2025-06-02T21:11:20.768Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2697
File: CHANGELOG.md:5-5
Timestamp: 2025-06-02T21:11:20.768Z
Learning: In the express-zod-api repository, RobinTail follows a release workflow where package.json version is only updated on the master branch after merging all planned release changes. Changelog entries may show future version numbers while package.json remains at the previous version during feature development, and this is intentional workflow, not a version inconsistency that needs to be flagged.

Applied to files:

  • migration/index.spec.ts
🔇 Additional comments (4)
migration/index.spec.ts (4)

2-4: LGTM! Import changes align with PR objectives.

The explicit .ts extension and modern ESM JSON import syntax (using with { type: "json" }) are consistent with the PR's goal to adopt TypeScript 5.9's module: node20 configuration and explicit import extensions. Based on learnings, tsdown handles module resolution during builds, so these source-level .ts extensions won't affect published packages.


14-15: LGTM! Dynamic rule name derivation is correctly implemented.

Extracting the major version from manifest.version and using it to dynamically reference the migration rule eliminates the hard-coded version issue flagged in previous reviews. The type assertion on line 15 is safe because the property existence is validated by the test on line 19.


19-23: LGTM! Test assertions now use the dynamic rule name.

Both the property check and the tester.run call correctly use the derived ruleName and theRule, ensuring tests stay synchronized with the package version on future major bumps.


27-28: LGTM! Additional valid test cases enhance coverage.

The new test cases for ez.dateOut with examples and schema.meta()?.examples follow the existing pattern and appropriately expand the valid-usage test coverage.


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.

@coveralls-official
Copy link

coveralls-official bot commented Sep 28, 2025

Coverage Status

coverage: 100.0%. remained the same
when pulling 5434de3 on strict-module-node20
into a99cbf4 on master.

@RobinTail RobinTail added the refactoring The better way to achieve the same result label Sep 28, 2025
@RobinTail RobinTail changed the title Switching to stable module node20 Switching to stablemodule: node20 Sep 28, 2025
@RobinTail RobinTail changed the title Switching to stablemodule: node20 Switching to stable module: node20 Sep 28, 2025
@RobinTail RobinTail marked this pull request as ready for review September 28, 2025 20:23
Copy link
Contributor

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

Caution

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

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

141-145: Bug: Object.freeze called on possibly undefined

this.#def.methods is optional; Object.freeze(undefined) throws. Return undefined when not set, otherwise freeze the array.

-  public override get methods() {
-    return Object.freeze(this.#def.methods);
-  }
+  public override get methods() {
+    const m = this.#def.methods;
+    return m ? Object.freeze(m) : undefined;
+  }
express-zod-api/tests/server-helpers.spec.ts (1)

106-108: Use the imported fail() in server-helpers.spec.ts
Replace the two assert.fail calls with the already-imported fail:

-      () => assert.fail("I am faulty"),
-      async () => assert.fail("I am faulty"),
+      () => fail("I am faulty"),
+      async () => fail("I am faulty"),

To verify there are no additional assert.fail calls in this file:

rg -nP '\bassert\.fail\s*\(' express-zod-api/tests/server-helpers.spec.ts
🧹 Nitpick comments (35)
express-zod-api/tests/startup-logo.spec.ts (1)

1-2: Convert the TTY import to a type-only import
The project’s tsconfig.json already has "module": "node20" and "allowImportingTsExtensions": true, so the .ts specifier is supported and no runtime change is needed. Marking WriteStream as a type-only import prevents an unnecessary ESM load:

-import { WriteStream } from "node:tty";
+import type { WriteStream } from "node:tty";
express-zod-api/tests/logger-helpers.spec.ts (2)

2-2: Make this a type‑only import

BuiltinLoggerConfig is used only as a type in this file. Switching to import type avoids an unnecessary runtime binding and future-proofs for stricter verbatim module semantics.

-import { BuiltinLoggerConfig } from "../src/builtin-logger.ts";
+import type { BuiltinLoggerConfig } from "../src/builtin-logger.ts";

3-10: Split type from value imports to avoid runtime named import of a type

AbstractLogger appears to be used purely as a type parameter here. Keep value imports as-is, but import the type separately to prevent a runtime named import that may not exist if/when verbatim module syntax is enabled or when running TS natively.

-import {
-  AbstractLogger,
-  isLoggerInstance,
-  isSeverity,
-  isHidden,
-  makeNumberFormat,
-  formatDuration,
-} from "../src/logger-helpers.ts";
+import type { AbstractLogger } from "../src/logger-helpers.ts";
+import {
+  isLoggerInstance,
+  isSeverity,
+  isHidden,
+  makeNumberFormat,
+  formatDuration,
+} from "../src/logger-helpers.ts";
express-zod-api/src/routing-walker.ts (2)

1-6: Imports updated to .ts: good; split type-only imports for cleaner emits under node20.

To avoid unnecessary runtime loads with module: node20 + erasableSyntaxOnly/verbatimModuleSyntax, split type-only symbols from value imports and keep .ts specifiers.

-import { ClientMethod, isMethod, Method } from "./method.ts";
-import { Routing } from "./routing.ts";
+import { isMethod } from "./method.ts";
+import type { ClientMethod, Method } from "./method.ts";
+import type { Routing } from "./routing.ts";

Also ensure allowImportingTsExtensions: true is set in the root tsconfig so these specifiers compile cleanly.


83-85: Minor perf nit: avoid shift() in hot loops.

shift() is O(n); switch to an index pointer or treat stack as LIFO with pop() for linear behavior.

-while (stack.length) {
-  const [path, element, explicitMethod] = stack.shift()!;
+for (let i = 0; i < stack.length; i++) {
+  const [path, element, explicitMethod] = stack[i]!;
tools/license.ts (1)

2-2: JSON import attribute compatibility + author shape guard

  • Node 20.10.0 introduced import-attributes with { type: "json" } without flags and TypeScript 5.9 (--module node20) follows that form; if your engines.node range is below 20.10.0, switch to assert { type: "json" } or bump the engine requirement.
  • manifest.author may be a string or an object—guard its shape:
-import manifest from "../express-zod-api/package.json" with { type: "json" };
+import manifest from "../express-zod-api/package.json" assert { type: "json" }; // or keep `with { type: "json" }` if engines.node ≥20.10.0-const text = `
+const author =
+  typeof manifest.author === "string"
+    ? manifest.author
+    : manifest.author?.name ?? "";
+const text = `
 MIT License
 Copyright (c) ${new Date().getFullYear()} ${author}
 …
 `;
express-zod-api/src/diagnostics.ts (2)

8-8: Use type-only imports to avoid unnecessary runtime loads under verbatim module syntax.

ActualLogger is used only for typing in the ctor and should be a type-only import. Also split FlatObject (type) from getRoutePathParams (value) to keep emitted imports minimal.

-import { FlatObject, getRoutePathParams } from "./common-helpers.ts";
-import { ActualLogger } from "./logger-helpers.ts";
+import { getRoutePathParams } from "./common-helpers.ts";
+import type { FlatObject } from "./common-helpers.ts";
+import type { ActualLogger } from "./logger-helpers.ts";

Also applies to: 17-17


36-39: Prefer non-mutating context enrichment in logs.

Object.assign(ctx, ...) mutates the caller-provided ctx; use spread to avoid side effects.

-          Object.assign(ctx, { reason }),
+          { ...ctx, reason },

and

-            Object.assign(ctx, { reason }),
+            { ...ctx, reason },

and

-        Object.assign(ctx, { path, param }),
+        { ...ctx, path, param },

Also applies to: 47-50, 77-79

express-zod-api/src/zts-helpers.ts (1)

2-3: Prefer type‑only imports for purely type usage

Both FlatObject and SchemaHandler are used only in types here. Mark them as type imports to avoid unintended runtime bindings under verbatimModuleSyntax.

-import { FlatObject } from "./common-helpers.ts";
-import { SchemaHandler } from "./schema-walker.ts";
+import type { FlatObject } from "./common-helpers.ts";
+import type { SchemaHandler } from "./schema-walker.ts";

This aligns with TS guidance on verbatimModuleSyntax and type‑only imports. (typescriptlang.org)

express-zod-api/src/middleware.ts (1)

3-8: Split value vs type imports to avoid runtime bindings

Only emptySchema and InputValidationError are used at runtime here. Mark the rest as type imports to keep emitted JS clean with verbatimModuleSyntax.

-import { emptySchema, FlatObject } from "./common-helpers.ts";
-import { InputValidationError } from "./errors.ts";
-import { IOSchema } from "./io-schema.ts";
-import { LogicalContainer } from "./logical-container.ts";
-import { Security } from "./security.ts";
-import { ActualLogger } from "./logger-helpers.ts";
+import { emptySchema, type FlatObject } from "./common-helpers.ts";
+import { InputValidationError } from "./errors.ts";
+import type { IOSchema } from "./io-schema.ts";
+import type { LogicalContainer } from "./logical-container.ts";
+import type { Security } from "./security.ts";
+import type { ActualLogger } from "./logger-helpers.ts";

This follows TS 5.x guidance on verbatimModuleSyntax/type imports. (typescriptlang.org)

express-zod-api/src/result-handler.ts (2)

11-11: Mark ActualLogger as a type-only import to avoid emitting a runtime import

It’s used purely in types; switch to import type to keep JS clean under verbatim/erasable settings.

Apply:

-import { ActualLogger } from "./logger-helpers.ts";
+import type { ActualLogger } from "./logger-helpers.ts";

Based on learnings.


10-10: Also mark IOSchema as type-only

It’s used only in type positions; this avoids an extra runtime import of ./io-schema.ts.

-import { IOSchema } from "./io-schema.ts";
+import type { IOSchema } from "./io-schema.ts";
express-zod-api/src/sse.ts (1)

1-1: Prefer type-only imports where the symbol is types-only (TS-native friendly).

To reduce unnecessary runtime imports under node20 and TS-native scenarios, make Response and FlatObject type-only. Keep other imports as values.

-import { Response } from "express";
+import type { Response } from "express";
@@
-import { FlatObject } from "./common-helpers.ts";
+import type { FlatObject } from "./common-helpers.ts";

Also applies to: 3-7

example/tsconfig.json (1)

2-2: Explicitly target the example tsconfig in pretest
In example/package.json, update the pretest script to

"pretest": "tsc -p example/tsconfig.json --noEmit"

to avoid accidentally picking up the root tsconfig when invoking tsc from the repo root.

example/generate-documentation.ts (1)

3-5: Update JSON import assertion for Node 20 compatibility
Node.js 20.0–20.9 only supports import … assert { type: "json" }, whereas Node.js 20.10+ supports import … with { type: "json" }. To target all Node 20 LTS minors, either bump your minimum Node.js version to ≥ 20.10 or replace:

-import manifest from "./package.json" with { type: "json" };
+import manifest from "./package.json" assert { type: "json" };
tools/make-tests.ts (1)

3-3: No extension-less imports detected—extension normalization helper remains an optional future enhancement.

express-zod-api/tests/common-helpers.spec.ts (1)

15-15: Prefer type‑only imports for types to keep runtime clean

EmptySchema, EmptyObject, CommonConfig, and InputSources are types in usage here. Import them via import type to avoid emitting (or preserving) unnecessary runtime imports under node20/verbatim/erasable settings.

-import {
+import {
   combinations,
   defaultInputSources,
   getInput,
   getMessageFromError,
   makeCleanId,
   ensureError,
   getRoutePathParams,
   shouldHaveContent,
   getInputSources,
   emptySchema,
-  EmptySchema,
-  EmptyObject,
 } from "../src/common-helpers.ts";
+import type { EmptySchema, EmptyObject } from "../src/common-helpers.ts";

-import { CommonConfig, InputSources } from "../src/config-type.ts";
+import type { CommonConfig, InputSources } from "../src/config-type.ts";

Also applies to: 17-17, 19-19

express-zod-api/src/routable.ts (1)

1-1: Use a type-only import for Routing

  • Switch to
    import type { Routing } from "./routing.ts";
    since Routing is an interface and should not emit a runtime import.
  • Your express-zod-api/tsconfig.json doesn’t declare Node20 module mode or erasure flags—please verify your root TS config enables type-only import erasure (e.g. importsNotUsedAsValues: "remove", verbatimModuleSyntax/erasableSyntaxOnly, or equivalent).
express-zod-api/src/endpoints-factory.ts (1)

1-1: Confirm repo-wide compiler settings for Node 20 mode

To avoid surprises with the new specifier rules and JSON handling:

  • Prefer moduleResolution: "node16" with module: "node20".
  • Ensure allowImportingTsExtensions: true; TS will rewrite .ts.js on emit.
  • If targeting TS-native runtimes later, keep erasableSyntaxOnly: true (instead of verbatimModuleSyntax) as per your issue notes.

Add to root tsconfig if missing:

 {
   "compilerOptions": {
     "module": "node20",
+    "moduleResolution": "node16",
+    "allowImportingTsExtensions": true,
+    "resolveJsonModule": true,
+    "erasableSyntaxOnly": true
   }
 }
express-zod-api/src/integration.ts (1)

4-6: Split value vs type imports for cleaner ESM output.

Use import type for ResponseVariant, Routing, OnEndpoint, HandlingRules, ZTSContext, ClientMethod while keeping runtime values as value imports. This trims emitted JS and avoids accidental side‑effects under node20.

Example:

-import { ResponseVariant, responseVariants } from "./api-response.ts";
+import { responseVariants } from "./api-response.ts";
+import type { ResponseVariant } from "./api-response.ts";

-import { IntegrationBase } from "./integration-base.ts";
+import { IntegrationBase } from "./integration-base.ts";

...
-import { Routing } from "./routing.ts";
-import { OnEndpoint, walkRouting, withHead } from "./routing-walker.ts";
-import { HandlingRules } from "./schema-walker.ts";
+import type { Routing } from "./routing.ts";
+import { walkRouting, withHead } from "./routing-walker.ts";
+import type { OnEndpoint } from "./routing-walker.ts";
+import type { HandlingRules } from "./schema-walker.ts";

...
-import { ZTSContext } from "./zts-helpers.ts";
+import type { ZTSContext } from "./zts-helpers.ts";

...
-import { ClientMethod } from "./method.ts";
+import type { ClientMethod } from "./method.ts";

Also applies to: 16-26

express-zod-api/tests/last-resort.spec.ts (1)

2-4: Make HttpError a type‑only import to avoid named CJS import at runtime.

s/http-errors doesn’t expose a runtime HttpError binding; it’s a type. Import it with import type to prevent runtime lookup.

Use:

import createHttpError from "http-errors";
import type { HttpError } from "http-errors";
express-zod-api/tests/index.spec.ts (1)

4-4: Use import type for named types to keep tests emission clean.

Prevents unnecessary runtime imports under verbatimModuleSyntax and aligns with prior repo practice for type‑only imports. Based on learnings.

-import * as entrypoint from "../src/index.ts";
+import * as entrypoint from "../src/index.ts";
@@
-import {
+import type {
   ApiResponse,
   AppConfig,
   BasicSecurity,
   BearerSecurity,
   CommonConfig,
   CookieSecurity,
   HeaderSecurity,
   Depicter,
   FlatObject,
   IOSchema,
   InputSecurity,
   LoggerOverrides,
   Method,
   OAuth2Security,
   OpenIdSecurity,
   Producer,
   Routing,
   ServerConfig,
-} from "../src/index.ts";
+} from "../src/index.ts";

Also applies to: 24-24

express-zod-api/tests/documentation-helpers.spec.ts (1)

4-4: Switch to explicit .ts specifiers — looks good.

Tests targeting source with .ts specifiers align with node20 mode.

Optionally, add a minimal suite importing from the package entry (bare import) to catch regressions in published “exports” mapping, while keeping current tests for internal behavior.

Also applies to: 28-28

express-zod-api/src/peer-helpers.ts (1)

7-11: Don’t swallow non-not-found errors; also guard missing export

Empty catch masks real import-time failures (e.g., syntax/runtime errors inside the peer), rethrowing MissingPeerError and hiding root cause. Also, if the requested export is absent, the current code returns undefined as T. Prefer precise handling.

Apply this diff:

 export const loadPeer = async <T>(
   moduleName: string,
   moduleExport: string = "default",
 ): Promise<T> => {
   try {
-    return (await import(moduleName))[moduleExport];
-  } catch {}
-  throw new MissingPeerError(moduleName);
+    const mod = await import(moduleName);
+    if (!(moduleExport in mod)) {
+      // export missing: surface a clear error
+      throw new MissingPeerError(moduleName);
+    }
+    return mod[moduleExport] as T;
+  } catch (err) {
+    const e = err as any;
+    const code = e?.code ?? e?.cause?.code;
+    if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") {
+      throw new MissingPeerError(moduleName);
+    }
+    // Different failure (e.g., peer threw during init) — propagate
+    throw e instanceof Error ? e : new Error(String(e));
+  }
 };
express-zod-api/tests/builtin-logger.spec.ts (1)

141-141: Avoid busy-wait in tests

The spin loop can be flaky/CPU-heavy in CI. Prefer advancing timers or stubbing performance.now().

express-zod-api/tests/result-handler.spec.ts (2)

1-1: Avoid importing types as values under Node20/TS “verbatim module” semantics.

Split type-only names to import type to prevent runtime named-import mismatches and reduce unnecessary runtime deps in tests.

Apply:

- import { Response } from "express";
+ import type { Response } from "express";
@@
- } from "../src/index.ts";
+ } from "../src/index.ts";
- import { AbstractResultHandler, Result } from "../src/result-handler.ts";
+ import { AbstractResultHandler } from "../src/result-handler.ts";
+ import type { Result } from "../src/result-handler.ts";
@@
- } from "../src/testing.ts";
+ } from "../src/testing.ts";

Note: AbstractResultHandler is used at runtime (instanceof), so keep it as a value import; Result is types-only.

Also applies to: 9-11, 16-16


9-11: TS config validated: allowImportingTsExtensions is already set to true in tsconfig.json. Optional: enable verbatimModuleSyntax or erasableSyntaxOnly to future-proof Node-24/JSR import handling.

express-zod-api/src/server.ts (1)

5-5: Split type-only imports from value imports to be Node20/TS-runtime friendly.

AppConfig | CommonConfig | HttpConfig | ServerConfig | Parsers | Routing are used as types only. Import them with import type and keep initRouting as a value import.

Apply:

-import { BuiltinLogger } from "./builtin-logger.ts";
+import { BuiltinLogger } from "./builtin-logger.ts";
@@
-import {
-  AppConfig,
-  CommonConfig,
-  HttpConfig,
-  ServerConfig,
-} from "./config-type.ts";
+import type {
+  AppConfig,
+  CommonConfig,
+  HttpConfig,
+  ServerConfig,
+} from "./config-type.ts";
@@
-import { isLoggerInstance } from "./logger-helpers.ts";
+import { isLoggerInstance } from "./logger-helpers.ts";
@@
-import { loadPeer } from "./peer-helpers.ts";
+import { loadPeer } from "./peer-helpers.ts";
@@
-import { defaultResultHandler } from "./result-handler.ts";
+import { defaultResultHandler } from "./result-handler.ts";
@@
-import { Parsers, Routing, initRouting } from "./routing.ts";
+import type { Parsers, Routing } from "./routing.ts";
+import { initRouting } from "./routing.ts";
@@
-import {
+import {
   createLoggingMiddleware,
   createNotFoundHandler,
   createCatcher,
   createUploadParsers,
   makeGetLogger,
   installDeprecationListener,
   moveRaw,
   installTerminationListener,
 } from "./server-helpers.ts";
-import { printStartupLogo } from "./startup-logo.ts";
+import { printStartupLogo } from "./startup-logo.ts";

This prevents accidental runtime named-import of type-only exports and keeps output clean under verbatimModuleSyntax or Node’s TS-native stripping.

Also applies to: 11-15, 25-26

express-zod-api/src/errors.ts (1)

2-4: Use type‑only import for OpenAPIContext

It’s only used for typing; mark it as import type to avoid emitting runtime imports with node20 + verbatim/erasable settings.

-import { OpenAPIContext } from "./documentation-helpers.ts";
+import type { OpenAPIContext } from "./documentation-helpers.ts";
express-zod-api/src/testing.ts (1)

2-4: Split value vs type imports for cleaner ESM under node20

Mark type‑only symbols with import type; keep runtime values as normal imports.

-import { ensureError, FlatObject, getInput } from "./common-helpers.ts";
+import { ensureError, getInput } from "./common-helpers.ts";
+import type { FlatObject } from "./common-helpers.ts";

-import { CommonConfig } from "./config-type.ts";
+import type { CommonConfig } from "./config-type.ts";

-import { AbstractEndpoint } from "./endpoint.ts";
+import type { AbstractEndpoint } from "./endpoint.ts";

-import {
-  AbstractLogger,
-  ActualLogger,
-  isSeverity,
-  Severity,
-} from "./logger-helpers.ts";
+import { isSeverity } from "./logger-helpers.ts";
+import type { AbstractLogger, ActualLogger, Severity } from "./logger-helpers.ts";

-import { AbstractMiddleware } from "./middleware.ts";
+import type { AbstractMiddleware } from "./middleware.ts";

Also applies to: 10-11, 18-19

express-zod-api/src/endpoint.ts (1)

4-6: Use import type for pure type imports
Update express-zod-api/src/endpoint.ts so that all type-only symbols are imported with import type, leaving value imports untouched:

-import { NormalizedResponse, ResponseVariant } from "./api-response.ts";
+import type { NormalizedResponse, ResponseVariant } from "./api-response.ts";

-import {
-  FlatObject,
-  getActualMethod,
-  getInput,
-  ensureError,
-  isSchema,
-} from "./common-helpers.ts";
+import { getActualMethod, getInput, ensureError, isSchema } from "./common-helpers.ts";
+import type { FlatObject } from "./common-helpers.ts";

-import { CommonConfig } from "./config-type.ts";
+import type { CommonConfig } from "./config-type.ts";

-import { IOSchema } from "./io-schema.ts";
+import type { IOSchema } from "./io-schema.ts";

-import { ActualLogger } from "./logger-helpers.ts";
+import type { ActualLogger } from "./logger-helpers.ts";

-import { LogicalContainer } from "./logical-container.ts";
+import type { LogicalContainer } from "./logical-container.ts";

-import { ClientMethod, CORSMethod, Method } from "./method.ts";
+import type { ClientMethod, CORSMethod, Method } from "./method.ts";

-import { AbstractMiddleware, ExpressMiddleware } from "./middleware.ts";
+import { ExpressMiddleware } from "./middleware.ts";
+import type { AbstractMiddleware } from "./middleware.ts";

-import { ContentType } from "./content-type.ts";
+import type { ContentType } from "./content-type.ts";

-import { DiscriminatedResult, pullResponseExamples } from "./result-helpers.ts";
+import { pullResponseExamples } from "./result-helpers.ts";
+import type { DiscriminatedResult } from "./result-helpers.ts";

-import { AbstractResultHandler } from "./result-handler.ts";
+import type { AbstractResultHandler } from "./result-handler.ts";

-import { Security } from "./security.ts";
+import type { Security } from "./security.ts";

Ensure your root tsconfig.json is configured for TypeScript 5.9 targeting Node.js 20 ESM, for example:

{
  "compilerOptions": {
    "module": "node20",
    "moduleResolution": "node20",
    "target": "es2023",
    "allowImportingTsExtensions": true,
    "rewriteRelativeImportExtensions": true
  }
}

Rebuild and confirm the emitted JavaScript uses .js import specifiers and contains no runtime imports for types.

express-zod-api/src/documentation-helpers.ts (1)

1-1: Prefer import type for type‑only symbols (future‑proof w/ verbatimModuleSyntax)

Under module: node20, if verbatimModuleSyntax is ever enabled, plain imports that are used only as types will become runtime imports. Mark them as type now to be safe and clearer.

Suggested diff:

- import {
-   ExamplesObject,
-   isReferenceObject,
-   isSchemaObject,
-   MediaTypeObject,
-   OAuthFlowObject,
-   ParameterObject,
-   ReferenceObject,
-   RequestBodyObject,
-   ResponseObject,
-   SchemaObject,
-   SchemaObjectType,
-   SecurityRequirementObject,
-   SecuritySchemeObject,
-   TagObject,
- } from "openapi3-ts/oas31";
+ import type {
+   ExamplesObject,
+   MediaTypeObject,
+   OAuthFlowObject,
+   ParameterObject,
+   ReferenceObject,
+   RequestBodyObject,
+   ResponseObject,
+   SchemaObject,
+   SchemaObjectType,
+   SecurityRequirementObject,
+   SecuritySchemeObject,
+   TagObject,
+ } from "openapi3-ts/oas31";
+ import { isReferenceObject, isSchemaObject } from "openapi3-ts/oas31";
- import { NormalizedResponse, ResponseVariant } from "./api-response.ts";
+ import type { NormalizedResponse, ResponseVariant } from "./api-response.ts";
- } from "./common-helpers.ts";
+   type FlatObject,
+   type Tag,
+ } from "./common-helpers.ts";
- import { InputSource } from "./config-type.ts";
+ import type { InputSource } from "./config-type.ts";
- import { IOSchema } from "./io-schema.ts";
+ import type { IOSchema } from "./io-schema.ts";
- import { Alternatives } from "./logical-container.ts";
+ import type { Alternatives } from "./logical-container.ts";
- import { ClientMethod } from "./method.ts";
+ import type { ClientMethod } from "./method.ts";
- import { ProprietaryBrand } from "./proprietary-schemas.ts";
+ import type { ProprietaryBrand } from "./proprietary-schemas.ts";
- import { FirstPartyKind } from "./schema-walker.ts";
+ import type { FirstPartyKind } from "./schema-walker.ts";
- import { Security } from "./security.ts";
+ import type { Security } from "./security.ts";

This keeps value imports (e.g., brands, helpers, contentTypes) intact while making type usage explicit.

If you prefer not to change imports, confirm tsconfig keeps "erasableSyntaxOnly": true (and does not enable verbatimModuleSyntax).

Also applies to: 19-19, 33-33, 34-34, 39-39, 41-41, 43-43, 44-44, 46-46, 47-47

express-zod-api/src/result-helpers.ts (1)

5-5: Make these imports type-only to avoid unnecessary runtime edges.

They’re only used in types here; switch to import type to prevent loading api-response.ts at runtime.

-import { NormalizedResponse, ResponseVariant } from "./api-response.ts";
+import type { NormalizedResponse, ResponseVariant } from "./api-response.ts";
express-zod-api/src/integration-base.ts (1)

3-3: Use a type-only import for ResponseVariant.

It’s only a type here; avoid a value import to keep runtime clean.

-import { ResponseVariant } from "./api-response.ts";
+import type { ResponseVariant } from "./api-response.ts";
express-zod-api/src/server-helpers.ts (1)

14-14: Harden localsID against missing manifest.name.

If package.json name is undefined during tests/build, Symbol.for(undefined) throws. Add a safe fallback.

-export const localsID = Symbol.for(manifest.name);
+const manifestName = manifest?.name ?? "express-zod-api";
+export const localsID = Symbol.for(manifestName);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb4a82c and 1dd79b8.

📒 Files selected for processing (107)
  • compat-test/quick-start.spec.ts (1 hunks)
  • esm-test/quick-start.spec.ts (1 hunks)
  • esm-test/tsconfig.json (0 hunks)
  • example/config.ts (1 hunks)
  • example/endpoints/create-user.ts (1 hunks)
  • example/endpoints/delete-user.ts (1 hunks)
  • example/endpoints/list-users.ts (1 hunks)
  • example/endpoints/retrieve-user.ts (1 hunks)
  • example/endpoints/send-avatar.ts (1 hunks)
  • example/endpoints/stream-avatar.ts (1 hunks)
  • example/endpoints/time-subscription.ts (1 hunks)
  • example/endpoints/update-user.ts (1 hunks)
  • example/factories.ts (1 hunks)
  • example/generate-client.ts (1 hunks)
  • example/generate-documentation.ts (1 hunks)
  • example/index.spec.ts (1 hunks)
  • example/index.ts (1 hunks)
  • example/routing.ts (1 hunks)
  • example/tsconfig.json (1 hunks)
  • express-zod-api/src/builtin-logger.ts (1 hunks)
  • express-zod-api/src/common-helpers.ts (1 hunks)
  • express-zod-api/src/config-type.ts (1 hunks)
  • express-zod-api/src/deep-checks.ts (1 hunks)
  • express-zod-api/src/depends-on-method.ts (1 hunks)
  • express-zod-api/src/diagnostics.ts (1 hunks)
  • express-zod-api/src/documentation-helpers.ts (2 hunks)
  • express-zod-api/src/documentation.ts (2 hunks)
  • express-zod-api/src/endpoint.ts (1 hunks)
  • express-zod-api/src/endpoints-factory.ts (1 hunks)
  • express-zod-api/src/errors.ts (1 hunks)
  • express-zod-api/src/graceful-shutdown.ts (1 hunks)
  • express-zod-api/src/index.ts (2 hunks)
  • express-zod-api/src/integration-base.ts (2 hunks)
  • express-zod-api/src/integration.ts (2 hunks)
  • express-zod-api/src/json-schema-helpers.ts (1 hunks)
  • express-zod-api/src/last-resort.ts (1 hunks)
  • express-zod-api/src/logger-helpers.ts (1 hunks)
  • express-zod-api/src/logical-container.ts (1 hunks)
  • express-zod-api/src/middleware.ts (1 hunks)
  • express-zod-api/src/peer-helpers.ts (1 hunks)
  • express-zod-api/src/proprietary-schemas.ts (1 hunks)
  • express-zod-api/src/raw-schema.ts (1 hunks)
  • express-zod-api/src/result-handler.ts (1 hunks)
  • express-zod-api/src/result-helpers.ts (1 hunks)
  • express-zod-api/src/routable.ts (1 hunks)
  • express-zod-api/src/routing-walker.ts (1 hunks)
  • express-zod-api/src/routing.ts (1 hunks)
  • express-zod-api/src/schema-walker.ts (1 hunks)
  • express-zod-api/src/server-helpers.ts (1 hunks)
  • express-zod-api/src/server.ts (2 hunks)
  • express-zod-api/src/sse.ts (1 hunks)
  • express-zod-api/src/testing.ts (1 hunks)
  • express-zod-api/src/zts-helpers.ts (1 hunks)
  • express-zod-api/src/zts.ts (1 hunks)
  • express-zod-api/tests/api-response.spec.ts (1 hunks)
  • express-zod-api/tests/buffer-schema.spec.ts (1 hunks)
  • express-zod-api/tests/builtin-logger.spec.ts (1 hunks)
  • express-zod-api/tests/common-helpers.spec.ts (1 hunks)
  • express-zod-api/tests/config-type.spec.ts (1 hunks)
  • express-zod-api/tests/content-type.spec.ts (1 hunks)
  • express-zod-api/tests/date-in-schema.spec.ts (1 hunks)
  • express-zod-api/tests/date-out-schema.spec.ts (1 hunks)
  • express-zod-api/tests/deep-checks.spec.ts (1 hunks)
  • express-zod-api/tests/depends-on-method.spec.ts (1 hunks)
  • express-zod-api/tests/documentation-helpers.spec.ts (2 hunks)
  • express-zod-api/tests/documentation.spec.ts (1 hunks)
  • express-zod-api/tests/endpoint.spec.ts (1 hunks)
  • express-zod-api/tests/endpoints-factory.spec.ts (1 hunks)
  • express-zod-api/tests/errors.spec.ts (1 hunks)
  • express-zod-api/tests/form-schema.spec.ts (1 hunks)
  • express-zod-api/tests/graceful-helpers.spec.ts (1 hunks)
  • express-zod-api/tests/graceful-shutdown.spec.ts (1 hunks)
  • express-zod-api/tests/index.spec.ts (2 hunks)
  • express-zod-api/tests/integration.spec.ts (1 hunks)
  • express-zod-api/tests/io-schema.spec.ts (1 hunks)
  • express-zod-api/tests/json-schema-helpers.spec.ts (1 hunks)
  • express-zod-api/tests/last-resort.spec.ts (1 hunks)
  • express-zod-api/tests/logger-helpers.spec.ts (1 hunks)
  • express-zod-api/tests/logical-container.spec.ts (1 hunks)
  • express-zod-api/tests/method.spec.ts (1 hunks)
  • express-zod-api/tests/middleware.spec.ts (1 hunks)
  • express-zod-api/tests/peer-helpers.spec.ts (1 hunks)
  • express-zod-api/tests/raw-schema.spec.ts (1 hunks)
  • express-zod-api/tests/result-handler.spec.ts (1 hunks)
  • express-zod-api/tests/result-helpers.spec.ts (1 hunks)
  • express-zod-api/tests/routable.spec.ts (1 hunks)
  • express-zod-api/tests/routing.spec.ts (2 hunks)
  • express-zod-api/tests/serve-static.spec.ts (1 hunks)
  • express-zod-api/tests/server-helpers.spec.ts (2 hunks)
  • express-zod-api/tests/server.spec.ts (2 hunks)
  • express-zod-api/tests/sse.spec.ts (1 hunks)
  • express-zod-api/tests/startup-logo.spec.ts (1 hunks)
  • express-zod-api/tests/system.spec.ts (1 hunks)
  • express-zod-api/tests/testing.spec.ts (1 hunks)
  • express-zod-api/tests/upload-schema.spec.ts (1 hunks)
  • express-zod-api/tests/zts.spec.ts (1 hunks)
  • express-zod-api/tsconfig.json (0 hunks)
  • express-zod-api/vitest.setup.ts (1 hunks)
  • migration/index.spec.ts (2 hunks)
  • migration/tsconfig.json (1 hunks)
  • tools/license.ts (1 hunks)
  • tools/make-tests.ts (2 hunks)
  • tools/tsconfig.json (1 hunks)
  • tsconfig.json (1 hunks)
  • zod-plugin/src/augmentation.ts (1 hunks)
  • zod-plugin/src/brand.ts (1 hunks)
  • zod-plugin/src/index.ts (1 hunks)
⛔ Files not processed due to max files limit (7)
  • zod-plugin/src/runtime.ts
  • zod-plugin/tests/brand.spec.ts
  • zod-plugin/tests/index.spec.ts
  • zod-plugin/tests/packer.spec.ts
  • zod-plugin/tests/runtime.spec.ts
  • zod-plugin/tsconfig.json
  • zod-plugin/vitest.setup.ts
💤 Files with no reviewable changes (2)
  • express-zod-api/tsconfig.json
  • esm-test/tsconfig.json
🧰 Additional context used
🧠 Learnings (24)
📚 Learning: 2025-05-28T18:58:10.064Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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/tests/common-helpers.spec.ts
  • compat-test/quick-start.spec.ts
  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/src/sse.ts
  • express-zod-api/vitest.setup.ts
  • express-zod-api/tests/sse.spec.ts
  • express-zod-api/tests/testing.spec.ts
  • express-zod-api/tests/documentation.spec.ts
  • express-zod-api/src/testing.ts
  • tools/license.ts
  • tools/make-tests.ts
  • express-zod-api/src/config-type.ts
  • express-zod-api/tests/form-schema.spec.ts
  • express-zod-api/tests/peer-helpers.spec.ts
  • express-zod-api/tests/buffer-schema.spec.ts
  • express-zod-api/tests/startup-logo.spec.ts
  • example/index.ts
  • express-zod-api/src/deep-checks.ts
  • express-zod-api/src/integration-base.ts
  • zod-plugin/src/augmentation.ts
  • example/factories.ts
  • express-zod-api/tests/errors.spec.ts
  • express-zod-api/tests/api-response.spec.ts
  • express-zod-api/tests/result-helpers.spec.ts
  • express-zod-api/tests/graceful-shutdown.spec.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/proprietary-schemas.ts
  • express-zod-api/src/routing-walker.ts
  • express-zod-api/tests/index.spec.ts
  • express-zod-api/tests/deep-checks.spec.ts
  • express-zod-api/tests/integration.spec.ts
  • example/routing.ts
  • express-zod-api/src/server-helpers.ts
  • express-zod-api/tests/server-helpers.spec.ts
  • express-zod-api/src/builtin-logger.ts
  • express-zod-api/src/graceful-shutdown.ts
  • express-zod-api/src/middleware.ts
  • express-zod-api/src/last-resort.ts
  • express-zod-api/src/diagnostics.ts
  • example/index.spec.ts
  • express-zod-api/tests/documentation-helpers.spec.ts
  • express-zod-api/tests/server.spec.ts
  • express-zod-api/src/zts.ts
  • express-zod-api/src/zts-helpers.ts
  • express-zod-api/tests/result-handler.spec.ts
  • express-zod-api/tests/io-schema.spec.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/tests/system.spec.ts
  • express-zod-api/src/errors.ts
  • example/endpoints/retrieve-user.ts
  • express-zod-api/src/result-handler.ts
  • express-zod-api/tests/last-resort.spec.ts
  • express-zod-api/tests/routing.spec.ts
  • express-zod-api/tests/method.spec.ts
  • express-zod-api/tests/serve-static.spec.ts
  • express-zod-api/tests/content-type.spec.ts
  • express-zod-api/src/schema-walker.ts
  • express-zod-api/tests/json-schema-helpers.spec.ts
  • express-zod-api/src/integration.ts
  • express-zod-api/tests/date-out-schema.spec.ts
  • express-zod-api/tests/zts.spec.ts
  • express-zod-api/tests/routable.spec.ts
  • express-zod-api/src/endpoints-factory.ts
  • express-zod-api/src/documentation-helpers.ts
  • express-zod-api/src/depends-on-method.ts
  • express-zod-api/tests/config-type.spec.ts
  • zod-plugin/src/brand.ts
  • express-zod-api/tests/graceful-helpers.spec.ts
  • express-zod-api/src/routing.ts
  • express-zod-api/src/routable.ts
  • express-zod-api/tests/middleware.spec.ts
  • express-zod-api/src/common-helpers.ts
  • express-zod-api/src/server.ts
  • express-zod-api/tests/logical-container.spec.ts
  • express-zod-api/src/raw-schema.ts
  • express-zod-api/src/documentation.ts
  • express-zod-api/src/peer-helpers.ts
  • esm-test/quick-start.spec.ts
  • express-zod-api/src/index.ts
  • express-zod-api/tests/upload-schema.spec.ts
  • express-zod-api/tests/depends-on-method.spec.ts
  • express-zod-api/src/result-helpers.ts
  • example/config.ts
  • express-zod-api/tests/endpoints-factory.spec.ts
  • example/generate-documentation.ts
  • express-zod-api/src/endpoint.ts
  • express-zod-api/tests/endpoint.spec.ts
📚 Learning: 2025-05-27T19:35:57.357Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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/common-helpers.spec.ts
  • express-zod-api/vitest.setup.ts
  • express-zod-api/tests/sse.spec.ts
  • express-zod-api/tests/testing.spec.ts
  • express-zod-api/tests/documentation.spec.ts
  • express-zod-api/src/testing.ts
  • express-zod-api/tests/form-schema.spec.ts
  • express-zod-api/tests/buffer-schema.spec.ts
  • express-zod-api/tests/startup-logo.spec.ts
  • express-zod-api/tests/errors.spec.ts
  • express-zod-api/tests/api-response.spec.ts
  • express-zod-api/tests/result-helpers.spec.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/tests/index.spec.ts
  • express-zod-api/tests/deep-checks.spec.ts
  • express-zod-api/tests/integration.spec.ts
  • express-zod-api/tests/server-helpers.spec.ts
  • express-zod-api/tests/documentation-helpers.spec.ts
  • express-zod-api/tests/server.spec.ts
  • express-zod-api/src/zts.ts
  • express-zod-api/tests/result-handler.spec.ts
  • express-zod-api/tests/io-schema.spec.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/tests/system.spec.ts
  • express-zod-api/tests/last-resort.spec.ts
  • express-zod-api/tests/routing.spec.ts
  • express-zod-api/tests/method.spec.ts
  • express-zod-api/tests/builtin-logger.spec.ts
  • express-zod-api/tests/serve-static.spec.ts
  • express-zod-api/tests/content-type.spec.ts
  • express-zod-api/tests/json-schema-helpers.spec.ts
  • express-zod-api/src/integration.ts
  • express-zod-api/tests/zts.spec.ts
  • express-zod-api/tests/routable.spec.ts
  • express-zod-api/tests/config-type.spec.ts
  • express-zod-api/tests/logger-helpers.spec.ts
  • express-zod-api/tests/graceful-helpers.spec.ts
  • express-zod-api/tests/middleware.spec.ts
  • express-zod-api/src/server.ts
  • express-zod-api/tests/logical-container.spec.ts
  • express-zod-api/tests/upload-schema.spec.ts
  • express-zod-api/tests/depends-on-method.spec.ts
  • express-zod-api/tests/endpoints-factory.spec.ts
  • express-zod-api/tests/endpoint.spec.ts
📚 Learning: 2025-06-14T16:42:52.972Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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/tests/common-helpers.spec.ts
  • express-zod-api/src/sse.ts
  • express-zod-api/tests/sse.spec.ts
  • express-zod-api/tests/testing.spec.ts
  • express-zod-api/tests/documentation.spec.ts
  • express-zod-api/src/testing.ts
  • express-zod-api/src/config-type.ts
  • express-zod-api/tests/buffer-schema.spec.ts
  • express-zod-api/src/deep-checks.ts
  • express-zod-api/src/integration-base.ts
  • express-zod-api/tests/graceful-shutdown.spec.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/proprietary-schemas.ts
  • express-zod-api/src/routing-walker.ts
  • express-zod-api/tests/index.spec.ts
  • express-zod-api/tests/deep-checks.spec.ts
  • express-zod-api/tests/server-helpers.spec.ts
  • express-zod-api/src/graceful-shutdown.ts
  • express-zod-api/src/middleware.ts
  • express-zod-api/src/last-resort.ts
  • express-zod-api/src/diagnostics.ts
  • express-zod-api/src/zts.ts
  • express-zod-api/src/zts-helpers.ts
  • express-zod-api/tests/io-schema.spec.ts
  • express-zod-api/src/errors.ts
  • express-zod-api/src/result-handler.ts
  • express-zod-api/tests/last-resort.spec.ts
  • example/tsconfig.json
  • express-zod-api/tests/content-type.spec.ts
  • express-zod-api/tests/json-schema-helpers.spec.ts
  • express-zod-api/src/integration.ts
  • express-zod-api/tests/zts.spec.ts
  • express-zod-api/src/documentation-helpers.ts
  • express-zod-api/src/depends-on-method.ts
  • express-zod-api/tests/graceful-helpers.spec.ts
  • express-zod-api/src/routing.ts
  • express-zod-api/src/common-helpers.ts
  • express-zod-api/src/server.ts
  • express-zod-api/src/raw-schema.ts
  • express-zod-api/src/documentation.ts
  • express-zod-api/src/index.ts
📚 Learning: 2025-06-02T21:08:56.475Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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/common-helpers.spec.ts
  • express-zod-api/tests/sse.spec.ts
  • express-zod-api/tests/testing.spec.ts
  • express-zod-api/tests/documentation.spec.ts
  • express-zod-api/src/testing.ts
  • express-zod-api/tests/buffer-schema.spec.ts
  • express-zod-api/tests/startup-logo.spec.ts
  • express-zod-api/tests/api-response.spec.ts
  • express-zod-api/tests/graceful-shutdown.spec.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/tests/index.spec.ts
  • express-zod-api/tests/deep-checks.spec.ts
  • express-zod-api/tests/integration.spec.ts
  • express-zod-api/tests/documentation-helpers.spec.ts
  • express-zod-api/tests/server.spec.ts
  • express-zod-api/src/zts.ts
  • express-zod-api/tests/io-schema.spec.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/tests/system.spec.ts
  • express-zod-api/tests/last-resort.spec.ts
  • express-zod-api/tests/routing.spec.ts
  • express-zod-api/tests/method.spec.ts
  • express-zod-api/tests/serve-static.spec.ts
  • express-zod-api/tests/content-type.spec.ts
  • express-zod-api/tests/json-schema-helpers.spec.ts
  • express-zod-api/tests/zts.spec.ts
  • express-zod-api/tests/config-type.spec.ts
  • express-zod-api/tests/middleware.spec.ts
  • express-zod-api/tests/logical-container.spec.ts
  • express-zod-api/tests/depends-on-method.spec.ts
📚 Learning: 2025-08-01T09:48:13.742Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-08-01T09:48:13.742Z
Learning: In express-zod-api, when migrating from Zod v3 to v4, the correct approach for internal type imports is to change from `import type { $ZodType } from "zod/v4/core"` to `import { z } from "zod"` and then use `z.core.$ZodType`. The zod/v4/core module is reexported as z.core by the main zod package, making this a valid and working approach.

Applied to files:

  • express-zod-api/tests/common-helpers.spec.ts
  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/src/sse.ts
  • express-zod-api/vitest.setup.ts
  • express-zod-api/tests/testing.spec.ts
  • express-zod-api/tests/documentation.spec.ts
  • express-zod-api/src/testing.ts
  • tools/license.ts
  • express-zod-api/src/config-type.ts
  • express-zod-api/tests/form-schema.spec.ts
  • express-zod-api/tests/buffer-schema.spec.ts
  • express-zod-api/src/deep-checks.ts
  • express-zod-api/src/integration-base.ts
  • zod-plugin/src/augmentation.ts
  • express-zod-api/tests/errors.spec.ts
  • express-zod-api/tests/api-response.spec.ts
  • express-zod-api/tests/result-helpers.spec.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/proprietary-schemas.ts
  • express-zod-api/src/logical-container.ts
  • express-zod-api/tests/index.spec.ts
  • express-zod-api/tests/deep-checks.spec.ts
  • express-zod-api/tests/integration.spec.ts
  • express-zod-api/src/server-helpers.ts
  • express-zod-api/src/graceful-shutdown.ts
  • express-zod-api/src/middleware.ts
  • express-zod-api/src/last-resort.ts
  • express-zod-api/tests/documentation-helpers.spec.ts
  • express-zod-api/tests/server.spec.ts
  • express-zod-api/src/zts.ts
  • express-zod-api/src/zts-helpers.ts
  • express-zod-api/tests/result-handler.spec.ts
  • express-zod-api/tests/io-schema.spec.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/tests/system.spec.ts
  • express-zod-api/src/errors.ts
  • express-zod-api/src/result-handler.ts
  • express-zod-api/tests/last-resort.spec.ts
  • express-zod-api/tests/method.spec.ts
  • express-zod-api/tests/content-type.spec.ts
  • express-zod-api/src/schema-walker.ts
  • express-zod-api/tests/json-schema-helpers.spec.ts
  • express-zod-api/src/integration.ts
  • express-zod-api/tests/date-out-schema.spec.ts
  • express-zod-api/tests/zts.spec.ts
  • express-zod-api/tests/routable.spec.ts
  • express-zod-api/src/endpoints-factory.ts
  • express-zod-api/src/documentation-helpers.ts
  • express-zod-api/src/depends-on-method.ts
  • express-zod-api/tests/config-type.spec.ts
  • zod-plugin/src/brand.ts
  • express-zod-api/src/routing.ts
  • express-zod-api/src/routable.ts
  • express-zod-api/tests/middleware.spec.ts
  • express-zod-api/src/common-helpers.ts
  • express-zod-api/src/server.ts
  • express-zod-api/src/raw-schema.ts
  • express-zod-api/src/documentation.ts
  • express-zod-api/src/index.ts
  • express-zod-api/tests/depends-on-method.spec.ts
  • express-zod-api/src/result-helpers.ts
  • zod-plugin/src/index.ts
  • express-zod-api/src/endpoint.ts
📚 Learning: 2025-05-27T20:27:17.015Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: express-zod-api/src/json-schema-helpers.ts:1-3
Timestamp: 2025-05-27T20:27:17.015Z
Learning: The JSONSchema type is not exported from the main "zod" module and must be imported from "zod/v4/core" when using Zod v4. This is acceptable for type-only imports as they don't create runtime dependencies.

Applied to files:

  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/src/deep-checks.ts
  • zod-plugin/src/augmentation.ts
  • express-zod-api/tests/io-schema.spec.ts
  • zod-plugin/src/brand.ts
  • express-zod-api/src/raw-schema.ts
📚 Learning: 2025-05-27T20:40:19.548Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: express-zod-api/src/json-schema-helpers.ts:75-87
Timestamp: 2025-05-27T20:40:19.548Z
Learning: In express-zod-api's `flattenIO` function in json-schema-helpers.ts, the `additionalProperties` field is used as a template to generate property schemas for literal property names extracted from `propertyNames.const` and `propertyNames.enum`. Converting boolean `additionalProperties` values to empty objects `{}` via `Object(entry.additionalProperties)` is intentional behavior, as the function only needs property schema templates, not the boolean semantics of `additionalProperties`.

Applied to files:

  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/tests/json-schema-helpers.spec.ts
📚 Learning: 2025-08-08T11:59:04.814Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2878
File: zod-plugin/runtime.ts:39-42
Timestamp: 2025-08-08T11:59:04.814Z
Learning: express-zod-api/zod-plugin/runtime.ts (TypeScript): Do not memoize the ZodType.prototype.brand getter. The current design returning setBrand.bind(this) on each access is intentional/preferred; avoid redefining "brand" as a data property per instance.

Applied to files:

  • express-zod-api/vitest.setup.ts
  • express-zod-api/src/config-type.ts
  • express-zod-api/tests/form-schema.spec.ts
  • express-zod-api/src/deep-checks.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/proprietary-schemas.ts
  • express-zod-api/src/zts.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/src/schema-walker.ts
  • express-zod-api/tests/date-out-schema.spec.ts
  • zod-plugin/src/brand.ts
  • express-zod-api/src/raw-schema.ts
  • express-zod-api/tests/upload-schema.spec.ts
  • zod-plugin/src/index.ts
📚 Learning: 2025-08-08T16:45:20.527Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-08-08T16:45:20.527Z
Learning: express-zod-api/zod-plugin: The brand setter must be immutable and always invoke pack→.check() via the getter-bound setBrand. Including brandProperty with an explicit undefined enables unbranding and should not be optimized away.

Applied to files:

  • express-zod-api/vitest.setup.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/src/schema-walker.ts
  • zod-plugin/src/brand.ts
  • express-zod-api/src/raw-schema.ts
  • express-zod-api/tests/upload-schema.spec.ts
  • zod-plugin/src/index.ts
📚 Learning: 2025-08-08T16:45:20.527Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-08-08T16:45:20.527Z
Learning: express-zod-api/zod-plugin: The ZodType.prototype.brand getter returns setBrand.bind(this) each time (no memoization). setBrand must always call pack() and include { brand: undefined } when unbranding so that pack → .check() runs and prior brand is overwritten; do not suggest removing the explicit undefined entry.

Applied to files:

  • express-zod-api/vitest.setup.ts
  • express-zod-api/tests/form-schema.spec.ts
  • express-zod-api/src/deep-checks.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/src/schema-walker.ts
  • express-zod-api/tests/date-out-schema.spec.ts
  • zod-plugin/src/brand.ts
  • express-zod-api/src/raw-schema.ts
  • express-zod-api/tests/upload-schema.spec.ts
  • zod-plugin/src/index.ts
📚 Learning: 2025-08-08T16:45:20.527Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-08-08T16:45:20.527Z
Learning: In express-zod-api zod-plugin, the brand setter must be immutable and always call `.check()` (packer’s onattach). Therefore, writing an explicit undefined entry in the bag for brand is intentional and should not be suggested for removal.

Applied to files:

  • express-zod-api/vitest.setup.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/schema-walker.ts
  • zod-plugin/src/brand.ts
  • express-zod-api/src/raw-schema.ts
  • zod-plugin/src/index.ts
📚 Learning: 2025-08-08T16:45:20.527Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-08-08T16:45:20.527Z
Learning: express-zod-api zod-plugin: The brand setter must stay immutable and always invoke pack→.check() (onattach). Including brandProperty with an explicit undefined enables “unbranding” (overwriting a previous brand) and should not be optimized away.

Applied to files:

  • express-zod-api/vitest.setup.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/schema-walker.ts
  • zod-plugin/src/brand.ts
  • zod-plugin/src/index.ts
📚 Learning: 2025-05-27T20:27:17.015Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: express-zod-api/src/json-schema-helpers.ts:1-3
Timestamp: 2025-05-27T20:27:17.015Z
Learning: Ramda is correctly listed as a dependency in express-zod-api/package.json, so imports of ramda utilities are properly supported.

Applied to files:

  • tools/license.ts
  • express-zod-api/src/deep-checks.ts
  • express-zod-api/src/common-helpers.ts
📚 Learning: 2025-06-02T21:11:20.768Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2697
File: CHANGELOG.md:5-5
Timestamp: 2025-06-02T21:11:20.768Z
Learning: In the express-zod-api repository, RobinTail follows a release workflow where package.json version is only updated on the master branch after merging all planned release changes. Changelog entries may show future version numbers while package.json remains at the previous version during feature development, and this is intentional workflow, not a version inconsistency that needs to be flagged.

Applied to files:

  • tools/license.ts
📚 Learning: 2025-05-27T20:03:34.213Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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:

  • tools/license.ts
  • example/factories.ts
  • express-zod-api/tests/errors.spec.ts
  • example/routing.ts
  • example/endpoints/retrieve-user.ts
  • express-zod-api/tests/routable.spec.ts
  • example/generate-client.ts
  • example/generate-documentation.ts
📚 Learning: 2025-05-27T19:30:51.885Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: compat-test/sample.ts:1-1
Timestamp: 2025-05-27T19:30:51.885Z
Learning: Files in compat-test/ directories, especially those named sample.ts or similar, are often test fixtures for migration scripts and may intentionally contain deprecated or "incorrect" code that the migration tooling is designed to fix. These should not be flagged as issues.

Applied to files:

  • tools/make-tests.ts
  • express-zod-api/tests/last-resort.spec.ts
  • express-zod-api/tests/zts.spec.ts
  • migration/index.spec.ts
📚 Learning: 2025-05-27T19:27:13.492Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: express-zod-api/tests/form-schema.spec.ts:31-31
Timestamp: 2025-05-27T19:27:13.492Z
Learning: Zod version 3.25.0 and later expose the Zod v4 API through the special import paths "zod/v4" and "zod/v4/core", allowing v4 features like .loose() to be used even when the package.json dependency shows a 3.x version.

Applied to files:

  • zod-plugin/src/augmentation.ts
📚 Learning: 2025-05-28T05:49:36.540Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: express-zod-api/src/common-helpers.ts:64-69
Timestamp: 2025-05-28T05:49:36.540Z
Learning: ZodError does not extend Error, but ZodRealError does extend Error. This is why in ensureError functions, you need to check for ZodError separately and wrap it in ZodRealError to convert it to a proper Error instance.

Applied to files:

  • express-zod-api/tests/errors.spec.ts
📚 Learning: 2025-05-28T05:04:40.327Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: express-zod-api/src/io-schema.ts:5-8
Timestamp: 2025-05-28T05:04:40.327Z
Learning: The Base type `object & { [Symbol.iterator]?: never }` in express-zod-api correctly excludes arrays and other iterables from IOSchema. Arrays are properly rejected because they have a defined Symbol.iterator method which conflicts with the never constraint, as demonstrated by TypeScript compiler errors when attempting to assign z.array() to IOSchema.

Applied to files:

  • express-zod-api/tests/io-schema.spec.ts
  • example/endpoints/retrieve-user.ts
  • express-zod-api/tests/json-schema-helpers.spec.ts
📚 Learning: 2025-09-28T10:09:35.674Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-09-28T10:09:35.674Z
Learning: In TypeScript configuration, when `strict: true` is set (including through extended configurations like tsconfig/node20), it automatically enables strictNullChecks along with other strict type-checking options, making explicit `strictNullChecks: true` redundant.

Applied to files:

  • example/tsconfig.json
📚 Learning: 2025-07-20T11:09:58.980Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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/tests/method.spec.ts
📚 Learning: 2025-05-27T20:22:30.428Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: express-zod-api/tests/zts.spec.ts:160-162
Timestamp: 2025-05-27T20:22:30.428Z
Learning: In express-zod-api/tests/zts.spec.ts, the `Fruits` enum intentionally contains both string and numeric members (Apple = "apple", Banana = "banana", Cantaloupe = "cantaloupe", A = 5) and is used with `z.enum(Fruits)` to test how the system handles mixed enum types. This is by design for testing purposes.

Applied to files:

  • express-zod-api/tests/zts.spec.ts
📚 Learning: 2025-09-26T09:00:24.416Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2965
File: express-zod-api/src/sse.ts:0-0
Timestamp: 2025-09-26T09:00:24.416Z
Learning: In express-zod-api SSE implementation, the ensureStream function checks response.headersSent before calling response.writeHead, which prevents writing to closed responses even if setTimeout fires after client disconnect. No cleanup of the headers timeout is needed.

Applied to files:

  • example/endpoints/time-subscription.ts
📚 Learning: 2025-08-25T17:43:34.491Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2904
File: express-zod-api/src/routing.ts:74-79
Timestamp: 2025-08-25T17:43:34.491Z
Learning: In express-zod-api, OPTIONS (CORS preflight) requests intentionally go through the same middleware and parser chain as other HTTP methods. This was specifically implemented to fix Issue #514 where middlewares were not running for OPTIONS requests. The framework seeds "options" with the same [parsers, endpoint] pair as other methods to ensure consistent middleware execution for CORS preflight requests.

Applied to files:

  • express-zod-api/src/endpoint.ts

Copy link
Contributor

@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

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/documentation.ts (1)

11-34: Blocking: publishing with .ts specifiers will break consumers

With module: "node20" + moduleResolution: "node16", TypeScript preserves the exact text of your import specifiers. After this change the emitted ESM files (and the .d.ts declarations) will still reference "./api-response.ts", "./common-helpers.ts", etc. Our published package only ships compiled .js files (+ declarations), so Node will try to load .ts files that do not exist, and downstream TypeScript users without allowImportingTsExtensions will get resolution failures.

Please keep the source specifiers pointed at the runtime extension (.js) and let the compiler map them back to the .ts sources, or introduce a build step that rewrites these paths before publishing. For example:

-import { responseVariants } from "./api-response.ts";
+import { responseVariants } from "./api-response.js";

Apply the same fix to every internal import introduced in this PR (unless we change the packaging strategy to ship the raw .ts files).

🧹 Nitpick comments (1)
tools/tsconfig.json (1)

2-2: Override test globals in tools tsconfig
tools/tsconfig.json currently inherits "vitest/globals" from the root, causing test globals to bleed into tooling code. Prevent this by adding a local override:

 {
   "extends": "../tsconfig.json",
+  "compilerOptions": {
+    "types": []
+  }
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb4a82c and c21d5e2.

📒 Files selected for processing (107)
  • compat-test/quick-start.spec.ts (1 hunks)
  • esm-test/quick-start.spec.ts (1 hunks)
  • esm-test/tsconfig.json (0 hunks)
  • example/config.ts (1 hunks)
  • example/endpoints/create-user.ts (1 hunks)
  • example/endpoints/delete-user.ts (1 hunks)
  • example/endpoints/list-users.ts (1 hunks)
  • example/endpoints/retrieve-user.ts (1 hunks)
  • example/endpoints/send-avatar.ts (1 hunks)
  • example/endpoints/stream-avatar.ts (1 hunks)
  • example/endpoints/time-subscription.ts (1 hunks)
  • example/endpoints/update-user.ts (1 hunks)
  • example/factories.ts (1 hunks)
  • example/generate-client.ts (1 hunks)
  • example/generate-documentation.ts (1 hunks)
  • example/index.spec.ts (1 hunks)
  • example/index.ts (1 hunks)
  • example/routing.ts (1 hunks)
  • example/tsconfig.json (1 hunks)
  • express-zod-api/src/builtin-logger.ts (1 hunks)
  • express-zod-api/src/common-helpers.ts (1 hunks)
  • express-zod-api/src/config-type.ts (1 hunks)
  • express-zod-api/src/deep-checks.ts (1 hunks)
  • express-zod-api/src/depends-on-method.ts (1 hunks)
  • express-zod-api/src/diagnostics.ts (1 hunks)
  • express-zod-api/src/documentation-helpers.ts (2 hunks)
  • express-zod-api/src/documentation.ts (2 hunks)
  • express-zod-api/src/endpoint.ts (1 hunks)
  • express-zod-api/src/endpoints-factory.ts (1 hunks)
  • express-zod-api/src/errors.ts (1 hunks)
  • express-zod-api/src/graceful-shutdown.ts (1 hunks)
  • express-zod-api/src/index.ts (2 hunks)
  • express-zod-api/src/integration-base.ts (2 hunks)
  • express-zod-api/src/integration.ts (2 hunks)
  • express-zod-api/src/json-schema-helpers.ts (1 hunks)
  • express-zod-api/src/last-resort.ts (1 hunks)
  • express-zod-api/src/logger-helpers.ts (1 hunks)
  • express-zod-api/src/logical-container.ts (1 hunks)
  • express-zod-api/src/middleware.ts (1 hunks)
  • express-zod-api/src/peer-helpers.ts (1 hunks)
  • express-zod-api/src/proprietary-schemas.ts (1 hunks)
  • express-zod-api/src/raw-schema.ts (1 hunks)
  • express-zod-api/src/result-handler.ts (1 hunks)
  • express-zod-api/src/result-helpers.ts (1 hunks)
  • express-zod-api/src/routable.ts (1 hunks)
  • express-zod-api/src/routing-walker.ts (1 hunks)
  • express-zod-api/src/routing.ts (1 hunks)
  • express-zod-api/src/schema-walker.ts (1 hunks)
  • express-zod-api/src/server-helpers.ts (1 hunks)
  • express-zod-api/src/server.ts (2 hunks)
  • express-zod-api/src/sse.ts (1 hunks)
  • express-zod-api/src/testing.ts (1 hunks)
  • express-zod-api/src/zts-helpers.ts (1 hunks)
  • express-zod-api/src/zts.ts (1 hunks)
  • express-zod-api/tests/api-response.spec.ts (1 hunks)
  • express-zod-api/tests/buffer-schema.spec.ts (1 hunks)
  • express-zod-api/tests/builtin-logger.spec.ts (1 hunks)
  • express-zod-api/tests/common-helpers.spec.ts (1 hunks)
  • express-zod-api/tests/config-type.spec.ts (1 hunks)
  • express-zod-api/tests/content-type.spec.ts (1 hunks)
  • express-zod-api/tests/date-in-schema.spec.ts (1 hunks)
  • express-zod-api/tests/date-out-schema.spec.ts (1 hunks)
  • express-zod-api/tests/deep-checks.spec.ts (1 hunks)
  • express-zod-api/tests/depends-on-method.spec.ts (1 hunks)
  • express-zod-api/tests/documentation-helpers.spec.ts (2 hunks)
  • express-zod-api/tests/documentation.spec.ts (1 hunks)
  • express-zod-api/tests/endpoint.spec.ts (1 hunks)
  • express-zod-api/tests/endpoints-factory.spec.ts (1 hunks)
  • express-zod-api/tests/errors.spec.ts (1 hunks)
  • express-zod-api/tests/form-schema.spec.ts (1 hunks)
  • express-zod-api/tests/graceful-helpers.spec.ts (1 hunks)
  • express-zod-api/tests/graceful-shutdown.spec.ts (1 hunks)
  • express-zod-api/tests/index.spec.ts (2 hunks)
  • express-zod-api/tests/integration.spec.ts (1 hunks)
  • express-zod-api/tests/io-schema.spec.ts (1 hunks)
  • express-zod-api/tests/json-schema-helpers.spec.ts (1 hunks)
  • express-zod-api/tests/last-resort.spec.ts (1 hunks)
  • express-zod-api/tests/logger-helpers.spec.ts (1 hunks)
  • express-zod-api/tests/logical-container.spec.ts (1 hunks)
  • express-zod-api/tests/method.spec.ts (1 hunks)
  • express-zod-api/tests/middleware.spec.ts (1 hunks)
  • express-zod-api/tests/peer-helpers.spec.ts (1 hunks)
  • express-zod-api/tests/raw-schema.spec.ts (1 hunks)
  • express-zod-api/tests/result-handler.spec.ts (1 hunks)
  • express-zod-api/tests/result-helpers.spec.ts (1 hunks)
  • express-zod-api/tests/routable.spec.ts (1 hunks)
  • express-zod-api/tests/routing.spec.ts (2 hunks)
  • express-zod-api/tests/serve-static.spec.ts (1 hunks)
  • express-zod-api/tests/server-helpers.spec.ts (2 hunks)
  • express-zod-api/tests/server.spec.ts (2 hunks)
  • express-zod-api/tests/sse.spec.ts (1 hunks)
  • express-zod-api/tests/startup-logo.spec.ts (1 hunks)
  • express-zod-api/tests/system.spec.ts (1 hunks)
  • express-zod-api/tests/testing.spec.ts (1 hunks)
  • express-zod-api/tests/upload-schema.spec.ts (1 hunks)
  • express-zod-api/tests/zts.spec.ts (1 hunks)
  • express-zod-api/tsconfig.json (0 hunks)
  • express-zod-api/tsdown.config.ts (1 hunks)
  • express-zod-api/vitest.setup.ts (1 hunks)
  • migration/index.spec.ts (2 hunks)
  • migration/tsconfig.json (1 hunks)
  • tools/license.ts (1 hunks)
  • tools/make-tests.ts (2 hunks)
  • tools/tsconfig.json (1 hunks)
  • tsconfig.json (1 hunks)
  • zod-plugin/src/augmentation.ts (1 hunks)
  • zod-plugin/src/brand.ts (1 hunks)
⛔ Files not processed due to max files limit (8)
  • zod-plugin/src/index.ts
  • zod-plugin/src/runtime.ts
  • zod-plugin/tests/brand.spec.ts
  • zod-plugin/tests/index.spec.ts
  • zod-plugin/tests/packer.spec.ts
  • zod-plugin/tests/runtime.spec.ts
  • zod-plugin/tsconfig.json
  • zod-plugin/vitest.setup.ts
💤 Files with no reviewable changes (2)
  • express-zod-api/tsconfig.json
  • esm-test/tsconfig.json
🧰 Additional context used
🧠 Learnings (23)
📓 Common learnings
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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.
📚 Learning: 2025-05-27T19:35:57.357Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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/builtin-logger.spec.ts
  • express-zod-api/src/sse.ts
  • express-zod-api/tests/documentation-helpers.spec.ts
  • express-zod-api/tests/common-helpers.spec.ts
  • express-zod-api/tests/logical-container.spec.ts
  • express-zod-api/tests/peer-helpers.spec.ts
  • express-zod-api/tests/testing.spec.ts
  • express-zod-api/tests/method.spec.ts
  • express-zod-api/tests/documentation.spec.ts
  • express-zod-api/tests/integration.spec.ts
  • express-zod-api/tests/sse.spec.ts
  • express-zod-api/tests/logger-helpers.spec.ts
  • express-zod-api/tests/result-handler.spec.ts
  • express-zod-api/tests/routing.spec.ts
  • express-zod-api/tests/middleware.spec.ts
  • express-zod-api/tests/zts.spec.ts
  • express-zod-api/tests/server.spec.ts
  • express-zod-api/tests/deep-checks.spec.ts
  • express-zod-api/tests/depends-on-method.spec.ts
  • express-zod-api/tests/date-out-schema.spec.ts
  • express-zod-api/tests/upload-schema.spec.ts
  • express-zod-api/tests/system.spec.ts
  • express-zod-api/tests/io-schema.spec.ts
  • express-zod-api/tests/json-schema-helpers.spec.ts
  • express-zod-api/tests/endpoints-factory.spec.ts
  • express-zod-api/src/testing.ts
  • express-zod-api/tests/api-response.spec.ts
  • express-zod-api/src/integration.ts
  • express-zod-api/tests/serve-static.spec.ts
  • express-zod-api/tests/config-type.spec.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/tests/index.spec.ts
  • express-zod-api/tests/server-helpers.spec.ts
  • express-zod-api/tests/routable.spec.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/vitest.setup.ts
  • express-zod-api/tests/endpoint.spec.ts
  • express-zod-api/tests/result-helpers.spec.ts
  • express-zod-api/tests/content-type.spec.ts
  • express-zod-api/tests/errors.spec.ts
  • express-zod-api/tests/startup-logo.spec.ts
  • express-zod-api/tests/form-schema.spec.ts
  • express-zod-api/tests/buffer-schema.spec.ts
📚 Learning: 2025-09-26T09:00:24.416Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2965
File: express-zod-api/src/sse.ts:0-0
Timestamp: 2025-09-26T09:00:24.416Z
Learning: In express-zod-api SSE implementation, the ensureStream function checks response.headersSent before calling response.writeHead, which prevents writing to closed responses even if setTimeout fires after client disconnect. No cleanup of the headers timeout is needed.

Applied to files:

  • example/endpoints/time-subscription.ts
📚 Learning: 2025-05-28T18:58:10.064Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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/sse.ts
  • express-zod-api/tests/documentation-helpers.spec.ts
  • example/factories.ts
  • express-zod-api/tests/common-helpers.spec.ts
  • express-zod-api/src/routable.ts
  • express-zod-api/src/proprietary-schemas.ts
  • express-zod-api/tests/peer-helpers.spec.ts
  • express-zod-api/tests/testing.spec.ts
  • express-zod-api/tests/method.spec.ts
  • express-zod-api/src/config-type.ts
  • express-zod-api/tests/documentation.spec.ts
  • tools/make-tests.ts
  • express-zod-api/tests/integration.spec.ts
  • express-zod-api/tests/last-resort.spec.ts
  • express-zod-api/tests/sse.spec.ts
  • express-zod-api/src/diagnostics.ts
  • express-zod-api/tests/result-handler.spec.ts
  • express-zod-api/tests/routing.spec.ts
  • express-zod-api/src/peer-helpers.ts
  • express-zod-api/src/middleware.ts
  • express-zod-api/src/routing.ts
  • express-zod-api/tests/middleware.spec.ts
  • express-zod-api/src/depends-on-method.ts
  • express-zod-api/src/endpoint.ts
  • express-zod-api/tests/zts.spec.ts
  • express-zod-api/tests/server.spec.ts
  • express-zod-api/tests/deep-checks.spec.ts
  • express-zod-api/tests/graceful-helpers.spec.ts
  • express-zod-api/tests/graceful-shutdown.spec.ts
  • express-zod-api/tests/depends-on-method.spec.ts
  • express-zod-api/tests/date-out-schema.spec.ts
  • express-zod-api/tests/upload-schema.spec.ts
  • express-zod-api/src/server.ts
  • express-zod-api/tests/system.spec.ts
  • express-zod-api/tests/io-schema.spec.ts
  • express-zod-api/tests/json-schema-helpers.spec.ts
  • express-zod-api/src/documentation.ts
  • express-zod-api/src/zts-helpers.ts
  • compat-test/quick-start.spec.ts
  • express-zod-api/tests/endpoints-factory.spec.ts
  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/src/testing.ts
  • express-zod-api/src/documentation-helpers.ts
  • express-zod-api/src/last-resort.ts
  • express-zod-api/tests/api-response.spec.ts
  • express-zod-api/src/common-helpers.ts
  • esm-test/quick-start.spec.ts
  • express-zod-api/src/integration.ts
  • express-zod-api/src/result-helpers.ts
  • express-zod-api/src/schema-walker.ts
  • express-zod-api/tests/serve-static.spec.ts
  • express-zod-api/tests/config-type.spec.ts
  • express-zod-api/src/integration-base.ts
  • express-zod-api/src/result-handler.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/zts.ts
  • express-zod-api/src/graceful-shutdown.ts
  • express-zod-api/tests/index.spec.ts
  • express-zod-api/tests/server-helpers.spec.ts
  • express-zod-api/src/raw-schema.ts
  • express-zod-api/tests/routable.spec.ts
  • example/index.spec.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/src/logical-container.ts
  • example/routing.ts
  • express-zod-api/vitest.setup.ts
  • express-zod-api/tests/endpoint.spec.ts
  • express-zod-api/src/routing-walker.ts
  • example/endpoints/retrieve-user.ts
  • express-zod-api/tests/result-helpers.spec.ts
  • express-zod-api/src/errors.ts
  • express-zod-api/src/endpoints-factory.ts
  • express-zod-api/tsdown.config.ts
  • express-zod-api/tests/content-type.spec.ts
  • express-zod-api/src/deep-checks.ts
  • zod-plugin/src/augmentation.ts
  • express-zod-api/tests/errors.spec.ts
  • express-zod-api/tests/form-schema.spec.ts
  • express-zod-api/src/server-helpers.ts
  • express-zod-api/tests/buffer-schema.spec.ts
  • express-zod-api/src/index.ts
📚 Learning: 2025-06-14T16:42:52.972Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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/sse.ts
  • express-zod-api/tests/documentation-helpers.spec.ts
  • express-zod-api/tests/common-helpers.spec.ts
  • express-zod-api/src/proprietary-schemas.ts
  • express-zod-api/src/config-type.ts
  • express-zod-api/tests/documentation.spec.ts
  • express-zod-api/tests/integration.spec.ts
  • express-zod-api/tests/last-resort.spec.ts
  • express-zod-api/src/diagnostics.ts
  • express-zod-api/src/middleware.ts
  • express-zod-api/src/routing.ts
  • express-zod-api/src/endpoint.ts
  • express-zod-api/tests/zts.spec.ts
  • express-zod-api/tests/server.spec.ts
  • express-zod-api/tests/deep-checks.spec.ts
  • express-zod-api/tests/graceful-helpers.spec.ts
  • express-zod-api/tests/graceful-shutdown.spec.ts
  • express-zod-api/src/server.ts
  • express-zod-api/tests/system.spec.ts
  • express-zod-api/src/documentation.ts
  • express-zod-api/src/zts-helpers.ts
  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/src/testing.ts
  • express-zod-api/src/documentation-helpers.ts
  • express-zod-api/src/last-resort.ts
  • express-zod-api/src/common-helpers.ts
  • express-zod-api/src/integration.ts
  • express-zod-api/src/result-helpers.ts
  • express-zod-api/tests/serve-static.spec.ts
  • express-zod-api/tests/config-type.spec.ts
  • express-zod-api/src/integration-base.ts
  • express-zod-api/src/result-handler.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/zts.ts
  • express-zod-api/src/graceful-shutdown.ts
  • express-zod-api/tests/index.spec.ts
  • express-zod-api/tests/server-helpers.spec.ts
  • express-zod-api/src/raw-schema.ts
  • express-zod-api/src/routing-walker.ts
  • express-zod-api/src/errors.ts
  • express-zod-api/tsdown.config.ts
  • express-zod-api/src/deep-checks.ts
  • express-zod-api/src/server-helpers.ts
  • express-zod-api/tests/buffer-schema.spec.ts
  • express-zod-api/src/index.ts
📚 Learning: 2025-08-01T09:48:13.742Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-08-01T09:48:13.742Z
Learning: In express-zod-api, when migrating from Zod v3 to v4, the correct approach for internal type imports is to change from `import type { $ZodType } from "zod/v4/core"` to `import { z } from "zod"` and then use `z.core.$ZodType`. The zod/v4/core module is reexported as z.core by the main zod package, making this a valid and working approach.

Applied to files:

  • express-zod-api/src/sse.ts
  • express-zod-api/tests/documentation-helpers.spec.ts
  • express-zod-api/tests/common-helpers.spec.ts
  • express-zod-api/src/routable.ts
  • express-zod-api/src/proprietary-schemas.ts
  • express-zod-api/tests/testing.spec.ts
  • express-zod-api/tests/method.spec.ts
  • express-zod-api/src/config-type.ts
  • express-zod-api/tests/documentation.spec.ts
  • express-zod-api/tests/integration.spec.ts
  • express-zod-api/src/diagnostics.ts
  • express-zod-api/src/peer-helpers.ts
  • express-zod-api/src/middleware.ts
  • express-zod-api/src/routing.ts
  • express-zod-api/src/depends-on-method.ts
  • express-zod-api/src/endpoint.ts
  • express-zod-api/tests/zts.spec.ts
  • express-zod-api/tests/server.spec.ts
  • express-zod-api/tests/deep-checks.spec.ts
  • express-zod-api/tests/depends-on-method.spec.ts
  • express-zod-api/src/server.ts
  • express-zod-api/tests/system.spec.ts
  • express-zod-api/tests/io-schema.spec.ts
  • express-zod-api/tests/json-schema-helpers.spec.ts
  • express-zod-api/src/documentation.ts
  • express-zod-api/src/zts-helpers.ts
  • express-zod-api/tests/endpoints-factory.spec.ts
  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/src/testing.ts
  • express-zod-api/src/documentation-helpers.ts
  • express-zod-api/src/last-resort.ts
  • express-zod-api/src/common-helpers.ts
  • express-zod-api/src/integration.ts
  • express-zod-api/src/result-helpers.ts
  • express-zod-api/src/schema-walker.ts
  • express-zod-api/tests/config-type.spec.ts
  • express-zod-api/src/integration-base.ts
  • express-zod-api/src/result-handler.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/zts.ts
  • express-zod-api/src/graceful-shutdown.ts
  • express-zod-api/tests/index.spec.ts
  • express-zod-api/tests/server-helpers.spec.ts
  • express-zod-api/src/raw-schema.ts
  • express-zod-api/tests/routable.spec.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/src/logical-container.ts
  • express-zod-api/vitest.setup.ts
  • zod-plugin/src/brand.ts
  • express-zod-api/src/logger-helpers.ts
  • express-zod-api/tests/endpoint.spec.ts
  • express-zod-api/src/routing-walker.ts
  • express-zod-api/tests/result-helpers.spec.ts
  • express-zod-api/src/errors.ts
  • express-zod-api/src/endpoints-factory.ts
  • express-zod-api/tsdown.config.ts
  • express-zod-api/tests/content-type.spec.ts
  • express-zod-api/src/deep-checks.ts
  • zod-plugin/src/augmentation.ts
  • express-zod-api/tests/errors.spec.ts
  • express-zod-api/tests/form-schema.spec.ts
  • express-zod-api/src/server-helpers.ts
  • express-zod-api/tests/buffer-schema.spec.ts
  • express-zod-api/src/index.ts
📚 Learning: 2025-06-02T21:08:56.475Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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/documentation-helpers.spec.ts
  • express-zod-api/tests/common-helpers.spec.ts
  • express-zod-api/tests/testing.spec.ts
  • express-zod-api/tests/method.spec.ts
  • express-zod-api/tests/documentation.spec.ts
  • express-zod-api/tests/integration.spec.ts
  • express-zod-api/tests/result-handler.spec.ts
  • express-zod-api/tests/routing.spec.ts
  • express-zod-api/tests/zts.spec.ts
  • express-zod-api/tests/server.spec.ts
  • express-zod-api/tests/deep-checks.spec.ts
  • express-zod-api/tests/depends-on-method.spec.ts
  • express-zod-api/tests/date-out-schema.spec.ts
  • express-zod-api/tests/upload-schema.spec.ts
  • express-zod-api/tests/system.spec.ts
  • express-zod-api/tests/io-schema.spec.ts
  • express-zod-api/tests/json-schema-helpers.spec.ts
  • express-zod-api/tests/endpoints-factory.spec.ts
  • express-zod-api/src/testing.ts
  • express-zod-api/tests/api-response.spec.ts
  • express-zod-api/tests/serve-static.spec.ts
  • express-zod-api/tests/config-type.spec.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/zts.ts
  • express-zod-api/tests/index.spec.ts
  • express-zod-api/tests/server-helpers.spec.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/tests/endpoint.spec.ts
  • express-zod-api/tests/errors.spec.ts
  • express-zod-api/tests/startup-logo.spec.ts
  • express-zod-api/tests/form-schema.spec.ts
  • express-zod-api/tests/buffer-schema.spec.ts
📚 Learning: 2025-05-27T20:03:34.213Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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:

  • example/factories.ts
  • example/generate-documentation.ts
  • tools/license.ts
  • example/generate-client.ts
  • express-zod-api/tests/routable.spec.ts
  • example/routing.ts
  • example/endpoints/retrieve-user.ts
  • express-zod-api/tests/errors.spec.ts
📚 Learning: 2025-05-27T20:40:19.548Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: express-zod-api/src/json-schema-helpers.ts:75-87
Timestamp: 2025-05-27T20:40:19.548Z
Learning: In express-zod-api's `flattenIO` function in json-schema-helpers.ts, the `additionalProperties` field is used as a template to generate property schemas for literal property names extracted from `propertyNames.const` and `propertyNames.enum`. Converting boolean `additionalProperties` values to empty objects `{}` via `Object(entry.additionalProperties)` is intentional behavior, as the function only needs property schema templates, not the boolean semantics of `additionalProperties`.

Applied to files:

  • express-zod-api/src/proprietary-schemas.ts
  • express-zod-api/tests/json-schema-helpers.spec.ts
  • express-zod-api/src/zts-helpers.ts
  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/src/schema-walker.ts
📚 Learning: 2025-08-08T11:59:04.814Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2878
File: zod-plugin/runtime.ts:39-42
Timestamp: 2025-08-08T11:59:04.814Z
Learning: express-zod-api/zod-plugin/runtime.ts (TypeScript): Do not memoize the ZodType.prototype.brand getter. The current design returning setBrand.bind(this) on each access is intentional/preferred; avoid redefining "brand" as a data property per instance.

Applied to files:

  • express-zod-api/src/proprietary-schemas.ts
  • express-zod-api/tests/date-out-schema.spec.ts
  • express-zod-api/tests/upload-schema.spec.ts
  • express-zod-api/src/zts-helpers.ts
  • express-zod-api/src/schema-walker.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/zts.ts
  • express-zod-api/src/raw-schema.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/vitest.setup.ts
  • zod-plugin/src/brand.ts
  • express-zod-api/src/deep-checks.ts
  • express-zod-api/tests/form-schema.spec.ts
📚 Learning: 2025-07-20T11:09:58.980Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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/tests/method.spec.ts
📚 Learning: 2025-09-28T10:09:35.674Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-09-28T10:09:35.674Z
Learning: In TypeScript configuration, when `strict: true` is set (including through extended configurations like tsconfig/node20), it automatically enables strictNullChecks along with other strict type-checking options, making explicit `strictNullChecks: true` redundant.

Applied to files:

  • tsconfig.json
📚 Learning: 2025-05-27T19:30:51.885Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: compat-test/sample.ts:1-1
Timestamp: 2025-05-27T19:30:51.885Z
Learning: Files in compat-test/ directories, especially those named sample.ts or similar, are often test fixtures for migration scripts and may intentionally contain deprecated or "incorrect" code that the migration tooling is designed to fix. These should not be flagged as issues.

Applied to files:

  • tools/make-tests.ts
  • migration/index.spec.ts
  • compat-test/quick-start.spec.ts
📚 Learning: 2025-05-27T20:27:17.015Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: express-zod-api/src/json-schema-helpers.ts:1-3
Timestamp: 2025-05-27T20:27:17.015Z
Learning: Ramda is correctly listed as a dependency in express-zod-api/package.json, so imports of ramda utilities are properly supported.

Applied to files:

  • express-zod-api/src/routing.ts
  • express-zod-api/src/depends-on-method.ts
  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/src/common-helpers.ts
  • express-zod-api/src/integration.ts
  • express-zod-api/src/deep-checks.ts
📚 Learning: 2025-08-25T17:43:34.491Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2904
File: express-zod-api/src/routing.ts:74-79
Timestamp: 2025-08-25T17:43:34.491Z
Learning: In express-zod-api, OPTIONS (CORS preflight) requests intentionally go through the same middleware and parser chain as other HTTP methods. This was specifically implemented to fix Issue #514 where middlewares were not running for OPTIONS requests. The framework seeds "options" with the same [parsers, endpoint] pair as other methods to ensure consistent middleware execution for CORS preflight requests.

Applied to files:

  • express-zod-api/src/endpoint.ts
📚 Learning: 2025-05-27T19:27:13.492Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: express-zod-api/tests/form-schema.spec.ts:31-31
Timestamp: 2025-05-27T19:27:13.492Z
Learning: Zod version 3.25.0 and later expose the Zod v4 API through the special import paths "zod/v4" and "zod/v4/core", allowing v4 features like .loose() to be used even when the package.json dependency shows a 3.x version.

Applied to files:

  • express-zod-api/tests/zts.spec.ts
  • zod-plugin/src/augmentation.ts
📚 Learning: 2025-08-08T16:45:20.527Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-08-08T16:45:20.527Z
Learning: express-zod-api/zod-plugin: The ZodType.prototype.brand getter returns setBrand.bind(this) each time (no memoization). setBrand must always call pack() and include { brand: undefined } when unbranding so that pack → .check() runs and prior brand is overwritten; do not suggest removing the explicit undefined entry.

Applied to files:

  • express-zod-api/tests/date-out-schema.spec.ts
  • express-zod-api/tests/upload-schema.spec.ts
  • express-zod-api/src/schema-walker.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/raw-schema.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/vitest.setup.ts
  • zod-plugin/src/brand.ts
  • express-zod-api/src/deep-checks.ts
  • express-zod-api/tests/form-schema.spec.ts
📚 Learning: 2025-08-08T16:45:20.527Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-08-08T16:45:20.527Z
Learning: express-zod-api/zod-plugin: The brand setter must be immutable and always invoke pack→.check() via the getter-bound setBrand. Including brandProperty with an explicit undefined enables unbranding and should not be optimized away.

Applied to files:

  • express-zod-api/tests/upload-schema.spec.ts
  • express-zod-api/src/schema-walker.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/raw-schema.ts
  • express-zod-api/tests/date-in-schema.spec.ts
  • express-zod-api/vitest.setup.ts
  • zod-plugin/src/brand.ts
📚 Learning: 2025-05-28T05:04:40.327Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: express-zod-api/src/io-schema.ts:5-8
Timestamp: 2025-05-28T05:04:40.327Z
Learning: The Base type `object & { [Symbol.iterator]?: never }` in express-zod-api correctly excludes arrays and other iterables from IOSchema. Arrays are properly rejected because they have a defined Symbol.iterator method which conflicts with the never constraint, as demonstrated by TypeScript compiler errors when attempting to assign z.array() to IOSchema.

Applied to files:

  • express-zod-api/tests/io-schema.spec.ts
  • express-zod-api/tests/json-schema-helpers.spec.ts
  • example/endpoints/retrieve-user.ts
📚 Learning: 2025-05-27T20:27:17.015Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: express-zod-api/src/json-schema-helpers.ts:1-3
Timestamp: 2025-05-27T20:27:17.015Z
Learning: The JSONSchema type is not exported from the main "zod" module and must be imported from "zod/v4/core" when using Zod v4. This is acceptable for type-only imports as they don't create runtime dependencies.

Applied to files:

  • express-zod-api/tests/io-schema.spec.ts
  • express-zod-api/src/json-schema-helpers.ts
  • express-zod-api/src/raw-schema.ts
  • zod-plugin/src/brand.ts
  • express-zod-api/src/deep-checks.ts
  • zod-plugin/src/augmentation.ts
📚 Learning: 2025-08-08T16:45:20.527Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-08-08T16:45:20.527Z
Learning: express-zod-api zod-plugin: The brand setter must stay immutable and always invoke pack→.check() (onattach). Including brandProperty with an explicit undefined enables “unbranding” (overwriting a previous brand) and should not be optimized away.

Applied to files:

  • express-zod-api/src/schema-walker.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/vitest.setup.ts
  • zod-plugin/src/brand.ts
📚 Learning: 2025-08-08T16:45:20.527Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-08-08T16:45:20.527Z
Learning: In express-zod-api zod-plugin, the brand setter must be immutable and always call `.check()` (packer’s onattach). Therefore, writing an explicit undefined entry in the bag for brand is intentional and should not be suggested for removal.

Applied to files:

  • express-zod-api/src/schema-walker.ts
  • express-zod-api/tests/raw-schema.spec.ts
  • express-zod-api/src/raw-schema.ts
  • express-zod-api/vitest.setup.ts
  • zod-plugin/src/brand.ts
📚 Learning: 2025-05-28T05:49:36.540Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2546
File: express-zod-api/src/common-helpers.ts:64-69
Timestamp: 2025-05-28T05:49:36.540Z
Learning: ZodError does not extend Error, but ZodRealError does extend Error. This is why in ensureError functions, you need to check for ZodError separately and wrap it in ZodRealError to convert it to a proper Error instance.

Applied to files:

  • express-zod-api/tests/errors.spec.ts
🔇 Additional comments (71)
example/endpoints/retrieve-user.ts (1)

5-5: Import extension update looks correct.

Explicit .ts extension matches the new module: node20 requirements and resolves to example/middlewares.ts without changing runtime behavior.

zod-plugin/src/augmentation.ts (1)

2-2: Extension update aligns with Node20 module mode.

Explicit .ts specifier keeps the compiler happy under module: "node20"/allowImportingTsExtensions, and since this is a type-only import it won’t leak into emitted JS. 👍

tools/make-tests.ts (1)

3-20: Explicit .ts specifier aligns with node20 expectations.

Thanks for updating both the tool import and the generated template to reference ports.ts explicitly. That keeps the script and emitted fixtures consistent with the new module: node20 + allowImportingTsExtensions setup and prevents drift when these tests are regenerated.

compat-test/quick-start.spec.ts (1)

11-11: Good: explicit .ts specifier under node20.

Import path update aligns with the new module strategy and tsx runner.

express-zod-api/src/proprietary-schemas.ts (1)

1-6: Build output not found; please run a production build and verify no “.ts” extensions remain in emitted code.
Once you’ve generated your JS and .d.ts artifacts (e.g. in dist, build, or lib), search them for ".ts" to confirm all import specifiers have been rewritten to extension-less or .js paths.

tsconfig.json (1)

4-6: Couldn’t retrieve the effective TS compilerOptions in this environment—please run locally:

npx typescript@latest tsc --showConfig -p tsconfig.json \
  | jq '.compilerOptions | {module, moduleResolution, target, allowImportingTsExtensions, resolveJsonModule, verbatimModuleSyntax, erasableSyntaxOnly}'

and confirm that moduleResolution and the chosen emit mode (verbatimModuleSyntax or erasableSyntaxOnly) are set as expected.

migration/tsconfig.json (1)

2-2: Confirm effective tsconfig options for the migration package

Ensure it inherits the following from the root config and that no overrides have changed them:

  • module: "node20"
  • allowImportingTsExtensions: true
  • resolveJsonModule: true
  • moduleResolution: "node16"

Please verify these effective compilerOptions manually.

example/config.ts (1)

4-4: Explicit .ts import keeps module resolution predictable.

The switch to ../tools/ports.ts is exactly what module: "node20" expects when allowImportingTsExtensions is enabled. Looks good.

example/routing.ts (1)

2-12: Consistent .ts specifiers across endpoints.

Updating every local endpoint import to a .ts suffix matches the new compiler settings and keeps the example routing tree working without side effects.

express-zod-api/tests/startup-logo.spec.ts (1)

2-2: Test import updated for Node 20 module mode.

Pointing directly to startup-logo.ts keeps vitest aligned with the repo-wide extension policy—no other adjustments needed.

express-zod-api/tests/server.spec.ts (1)

1-27: Server-spec imports follow the new explicit-extension rule.

All updated paths (server-helpers.ts, ports.ts, mocks, and index.ts) reflect the Node 20 ESM expectations while keeping the test harness unchanged.

example/index.ts (1)

2-3: Example entrypoint now matches explicit extension policy.

Importing ./config.ts and ./routing.ts keeps the example app consistent with the new module settings. All good.

express-zod-api/src/server-helpers.ts (1)

12-15: Manifest-based locals symbol aligns multi-package scenarios

Tying the locals key to manifest.name keeps the shared symbol stable across multiple copies of the package while staying future-proof with Node 20 JSON imports. Nicely done.

express-zod-api/tests/graceful-shutdown.spec.ts (1)

6-8: Import extensions updated for Node 20

The .ts specifiers line up with the new module: node20 expectations and keep the test harness working. Looks good.

example/generate-client.ts (1)

3-4: Example import updates stay consistent

Explicit .ts imports keep the example aligned with the new compiler settings without affecting runtime behavior.

express-zod-api/tests/middleware.spec.ts (1)

2-8: Test suite imports match the tightened module resolution

The switch to explicit .ts paths ensures the tests continue to compile under module: node20 while leaving behavior untouched.

example/generate-documentation.ts (1)

3-5: Typed JSON and explicit extensions keep the doc generator compliant

Bringing in the manifest with { type: "json" } and updating the local imports keeps this script compatible with the new TS/Node settings.

esm-test/quick-start.spec.ts (1)

2-2: Explicit .ts import keeps the ESM test aligned with node20 resolution

Switching to ../tools/ports.ts matches the new module settings and avoids implicit extension lookups. Looks good.

express-zod-api/tsdown.config.ts (1)

2-9: JSON manifest import is a nice cleanup

Pulling the version via a typed JSON import removes the async file read and keeps the define block intact. 👍

express-zod-api/tests/upload-schema.spec.ts (1)

2-4: Test imports now point directly at the TS sources

The explicit .ts specifiers ensure vitest/tsx resolve the modules without relying on directory indexes. All good here.

express-zod-api/tests/form-schema.spec.ts (1)

2-3: Consistent .ts imports for form schema tests

This keeps the test suite in lockstep with the repo-wide module settings. No issues found.

tools/license.ts (1)

2-8: JSON import matches the new tooling expectations

Using the import attribute keeps the license script simple under the new TypeScript/Node setup. Looks great.

express-zod-api/src/testing.ts (1)

2-4: Consistent .ts specifiers in testing utilities — LGTM.

Tests typically run under tsx/vitest where .ts specifiers are fine. Just ensure the library build step won’t emit JS that still references .ts here (tsup bundling is fine; plain tsc preserveModules is not).

If you plan to execute this file under Node without a TS runner, confirm Node 24+ type‑stripping is enabled in your CI matrix and that package.json “type”/exports don’t conflict.

Also applies to: 10-11, 18-19

express-zod-api/tests/graceful-helpers.spec.ts (1)

7-7: Test imports updated to explicit .ts — looks good.

No behavioral changes. Keep using makeRequestMock from src/testing.ts; matches the new import‑extension convention.

Also applies to: 9-9

express-zod-api/src/zts.ts (1)

4-12: Confirm tsconfig and bundler for .ts imports

  • Root tsconfig.json sets "allowImportingTsExtensions": true but omits "moduleResolution" (should be "node20") and neither "verbatimModuleSyntax" nor "erasableSyntaxOnly" is enabled. Add:
    "moduleResolution": "node20" to match "module": "node20"
    "erasableSyntaxOnly": true if relying on Node 24+ TS stripping, or
    "verbatimModuleSyntax": true if bundling with esbuild/tsup to rewrite extensions
  • I don’t see a tsup.config.ts in express-zod-api; ensure your build pipeline rewrites .ts imports to .js before publishing, or switch to a TS‐at‐runtime setup with the flags above.
migration/index.spec.ts (1)

2-18: Explicit .ts/JSON imports look correct.

The .ts specifier and the JSON with { type: "json" } import both align with Node 20 module semantics, and the major-version assertion preserves the prior behavior.

express-zod-api/src/documentation-helpers.ts (1)

19-48: Consistent .ts specifiers across internal deps.

Every updated import now resolves via an explicit .ts suffix (plus the JSON with { type: "json" }), matching the new module: "node20" + allowImportingTsExtensions setup without altering runtime behavior.

express-zod-api/src/sse.ts (1)

3-12: SSE helpers now use explicit .ts paths.

The updated imports map one-to-one to existing modules, so the SSE factory continues to compile under the stricter resolver.

express-zod-api/src/peer-helpers.ts (1)

1-1: Peer error import matches new specifier rules.

Pointing at ./errors.ts keeps dynamic peer loading intact under Node 20 module resolution.

express-zod-api/src/routable.ts (1)

1-1: Routing import aligned with .ts suffix policy.

The explicit extension keeps Routable compatible with the updated resolver without changing behavior.

example/endpoints/delete-user.ts (1)

4-4: Import extension aligns with module: node20 expectations.

The .ts specifier keeps this example aligned with the new compiler settings while still resolving to the intended factory module. No further action needed.

express-zod-api/tests/testing.spec.ts (1)

9-9: Test import updated to explicit entrypoint.

Confirming the switch to ../src/index.ts keeps the tests targeting the published surface while satisfying the new explicit-extension rule. Looks good.

example/factories.ts (1)

10-10: Example middleware import stays consistent.

The .ts suffix mirrors the adjacent endpoint updates and keeps the demo code runnable under the new resolver. All set.

express-zod-api/tests/integration.spec.ts (1)

9-9: Integration test import matches explicit-export policy.

Using ../src/index.ts retains access to the public exports while satisfying the stricter resolver—no further adjustments needed.

express-zod-api/tests/config-type.spec.ts (1)

2-2: Config-type test import remains correct.

The explicit .ts keeps the test pointed at the public createConfig export under the new module configuration. Looks good.

express-zod-api/tests/buffer-schema.spec.ts (1)

3-3: Explicit .ts specifier keeps ez buffer tests compatible

The updated import complies with the new module: node20 requirement while preserving existing test behavior.

express-zod-api/vitest.setup.ts (1)

4-4: Serializer import aligns with node20 module rules

Adding the .ts extension matches the revised compiler settings and doesn’t affect the serializer logic.

express-zod-api/tests/method.spec.ts (1)

10-10: Method test import tracks new extension policy

Appending .ts keeps the test suite consistent with the repository-wide module resolution update.

example/endpoints/stream-avatar.ts (1)

2-2: Factory import updated for explicit extensions

The .ts suffix matches the new TypeScript module configuration with no functional fallout.

express-zod-api/tests/api-response.spec.ts (1)

1-1: API response test import follows .ts convention

The explicit extension satisfies the stricter module resolution while leaving test logic untouched.

express-zod-api/tests/logical-container.spec.ts (1)

1-1: Import extension update looks good.

The .ts specifier aligns the test import with the node20 module settings introduced in this PR.

express-zod-api/tests/raw-schema.spec.ts (1)

2-4: Imports match the new module resolution strategy.

Switching to explicit .ts paths keeps these tests compatible with the node20 configuration and verbatim module syntax workflow.

express-zod-api/tests/routable.spec.ts (1)

2-2: Extension-qualified import looks correct.

The update ensures the spec stays in sync with the rest of the codebase under node20 semantics.

express-zod-api/tests/builtin-logger.spec.ts (1)

2-2: Explicit .ts import confirmed.

The logger test now references the resolved TypeScript module directly, matching the project-wide convention.

express-zod-api/src/routing-walker.ts (1)

1-6: Module specifiers updated appropriately.

All internal imports now include .ts extensions, which is required for the node20 module target without altering routing logic.

express-zod-api/src/logical-container.ts (1)

2-2: Import extension update looks good

Switching to the explicit .ts suffix keeps this module consistent with the Node 20 resolver requirements introduced in the PR. No further action needed.

example/endpoints/create-user.ts (1)

4-4: Consistent .ts specifier

Thanks for updating this factory import to the explicit .ts specifier—matches the rest of the example endpoints and the new compiler settings.

express-zod-api/tests/endpoint.spec.ts (1)

10-11: Tests aligned with explicit entrypoints

Good call re-pointing the test imports at index.ts and endpoint.ts; keeps the suite aligned with the updated module resolution rules.

express-zod-api/src/depends-on-method.ts (1)

2-4: Internal wiring matches the new resolution settings

The explicit .ts imports for AbstractEndpoint, Method, and Routable keep this module in step with the rest of the source tree. Looks great.

express-zod-api/tests/system.spec.ts (1)

16-17: System test imports updated correctly

Repointing to ../src/index.ts and ../../tools/ports.ts fits the new Node 20 module rules; the rest of the test body remains unaffected.

express-zod-api/tests/serve-static.spec.ts (1)

1-2: LGTM on explicit test imports

Switching the spec file to explicit extensions keeps it aligned with the new module settings; no issues spotted here.

express-zod-api/src/builtin-logger.ts (1)

4-11: Same .ts import concern as flagged elsewhere

Please see my blocking note on express-zod-api/src/documentation.ts (Lines 11-34); the same reasoning applies to these .ts specifiers.

express-zod-api/tests/index.spec.ts (1)

4-24: Tests keep matching the public barrel

Pointing the snapshot tests at the explicit index.ts entrypoint fits the new resolution rules; everything still lines up.

express-zod-api/src/result-helpers.ts (1)

5-14: Same .ts specifier issue as documentation.ts

This file shares the runtime/declaration breakage described in my comment on express-zod-api/src/documentation.ts (Lines 11-34); please address it here as well.

express-zod-api/tests/date-out-schema.spec.ts (1)

2-3: Import specifiers updated appropriately.

Switching these test imports to explicit .ts is the right move for the module: "node20" / moduleResolution: "node16" combo—everything keeps pointing at the same source entry points with no extra churn. Nicely done.

express-zod-api/tests/documentation-helpers.spec.ts (1)

4-28: Import updates look good.

Explicit .ts specifiers line up with the new module: node20 setup and keep tests in sync with runtime resolution.

express-zod-api/tests/json-schema-helpers.spec.ts (1)

2-2: Consistent extension usage.

The explicit .ts import ensures compatibility with the new Node20 module configuration; no further action needed.

express-zod-api/tests/result-handler.spec.ts (1)

9-16: Clear, extension-aware imports.

Splitting the barrel import into explicit .ts paths keeps type access predictable under module: node20 while preserving test behavior.

express-zod-api/src/integration-base.ts (1)

3-42: Imports updated correctly for node20 module mode.

Explicit .ts specifiers keep this module in step with the new compiler settings; nothing else to flag.

express-zod-api/src/deep-checks.ts (1)

3-12: Import specifiers look good.

The .ts extensions match the node20 transition without touching runtime behavior.

express-zod-api/tests/date-in-schema.spec.ts (1)

2-3: Test import updates are consistent.

Pointing directly at the .ts modules matches the new resolution strategy; assertions remain intact.

express-zod-api/tests/endpoints-factory.spec.ts (1)

10-12: Good swap to explicit .ts imports.

Direct module targets will play nicely with the new compiler module settings.

express-zod-api/tests/common-helpers.spec.ts (1)

15-20: Helper imports updated appropriately.

Explicit .ts specifiers keep the test suite aligned with the node20 configuration.

express-zod-api/tests/errors.spec.ts (1)

2-10: Imports align with node20 specifier requirements

Thanks for updating the test imports to the explicit .ts paths—this keeps the suite in step with the module/node20 switch without altering behavior.

express-zod-api/src/integration.ts (1)

4-26: Core integration imports updated consistently

The import block now targets the .ts sources directly, matching the repo-wide module setting change while keeping the integration surface untouched. Looks good.

express-zod-api/src/server.ts (1)

5-27: Server wiring stays stable under explicit extensions

These .ts specifiers keep server wiring compatible with the node20 resolver with no other behavior shifts. All good here.

express-zod-api/src/zts-helpers.ts (1)

2-4: Helper imports kept in sync

Explicit .ts paths for the helper dependencies look correct and maintain the existing typing surface.

express-zod-api/tests/zts.spec.ts (1)

3-6: zts tests align with new specifiers

The test harness now points at the .ts entry points, matching the rest of the refactor without affecting coverage.

express-zod-api/tests/server-helpers.spec.ts (1)

2-26: Explicit .ts imports align with the Node 20 module target.

The updated specifiers fit the new module: node20 + relative-extension policy without affecting test behavior. Looks good.

express-zod-api/tests/result-helpers.spec.ts (1)

3-12: Consistent .ts specifiers for direct TS execution.

Nice job keeping these result-helper tests in sync with the new import-extension requirements while leaving logic untouched.

express-zod-api/tests/logger-helpers.spec.ts (1)

1-11: Logger helper test imports updated correctly.

The .ts extensions ensure compatibility with the strict Node 20 resolution setup and match the source re-exports. All good here.

@RobinTail
Copy link
Owner Author

11-34: Blocking: publishing with .ts specifiers will break consumers

@coderabbitai, there are 3 packages in this repo at the moment that are published, they are located in express-zod-api, zod-plugin and migration dirs. Each contains tsdown.config.ts file because they are built by tsdown into JS bundle and declaration file before publishing.
The source code currently is not published so it's not going to break anything. Moreover, I'm considering publishing it to JSR registry, and there it's required exactly to have .ts extensions in imports within source code.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 29, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@RobinTail, thank you for the clarification! Let me verify the build configuration to better understand the publishing workflow.


🏁 Script executed:

#!/bin/bash
# Check the tsdown configuration files in the 3 package directories
echo "=== express-zod-api tsdown config ==="
cat express-zod-api/tsdown.config.ts

echo -e "\n=== zod-plugin tsdown config ==="  
cat zod-plugin/tsdown.config.ts

echo -e "\n=== migration tsdown config ==="
cat migration/tsdown.config.ts

# Check package.json files to understand what gets published
echo -e "\n=== express-zod-api package.json (files field) ==="
jq '.files // "no files field"' express-zod-api/package.json

echo -e "\n=== zod-plugin package.json (files field) ==="
jq '.files // "no files field"' zod-plugin/package.json

echo -e "\n=== migration package.json (files field) ==="
jq '.files // "no files field"' migration/package.json

Length of output: 1224


@RobinTail, perfect! Thank you for the detailed explanation. I can see from the configuration that:

  1. tsdown builds the packages: Each package uses tsdown to compile TypeScript source into JavaScript bundles and declaration files in the dist/ directory
  2. Only built artifacts are published: The package.json files specify "files": ["dist", "*.md"], meaning only the compiled output gets published, not the source code
  3. Source stays internal: The .ts extensions in imports are only in the source code, which consumers never see

This completely resolves my concern about breaking consumers. Since the source code with .ts extensions isn't published and gets compiled to standard JS, there's no compatibility issue for npm consumers.

The approach also positions you well for JSR publishing, which does indeed require explicit .ts extensions in source imports.

I withdraw my blocking concern - this change is safe and follows a proper build-then-publish workflow.


✏️ Learnings added
Learnt from: RobinTail
URL: https://github.com/RobinTail/express-zod-api/pull/2974

Timestamp: 2025-09-29T03:35:55.530Z
Learning: In the express-zod-api repository, packages are built using tsdown before publishing. Source code with .ts extensions is not published - only the built JavaScript bundles and declaration files in the dist/ directory are published to npm. This means .ts extensions in source imports don't affect consumers.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2697
File: CHANGELOG.md:5-5
Timestamp: 2025-06-02T21:11:20.768Z
Learning: In the express-zod-api repository, RobinTail follows a release workflow where package.json version is only updated on the master branch after merging all planned release changes. Changelog entries may show future version numbers while package.json remains at the previous version during feature development, and this is intentional workflow, not a version inconsistency that needs to be flagged.

Learnt from: RobinTail
PR: RobinTail/express-zod-api#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.

Learnt from: RobinTail
PR: RobinTail/express-zod-api#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.

Copy link
Contributor

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

🧹 Nitpick comments (1)
eslint.config.js (1)

209-209: Broaden TS file globs so package‑scoped rules hit subfolders

Current globs only match direct children of src/. Use recursive patterns to cover nested modules.

-    files: ["express-zod-api/src/*.ts"],
+    files: ["express-zod-api/src/**/*.ts"],
-    files: ["zod-plugin/src/*.ts"],
+    files: ["zod-plugin/src/**/*.ts"],

Also applies to: 222-222

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 10d4dfe and d893552.

📒 Files selected for processing (1)
  • eslint.config.js (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-09-29T03:35:55.530Z
Learning: In the express-zod-api repository, packages are built using tsdown before publishing. Source code with .ts extensions is not published - only the built JavaScript bundles and declaration files in the dist/ directory are published to npm. This means .ts extensions in source imports don't affect consumers.
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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.

Copy link
Owner Author

@RobinTail RobinTail left a comment

Choose a reason for hiding this comment

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

☑️ reviewed

@RobinTail RobinTail force-pushed the strict-module-node20 branch from 035815d to 4d1debb Compare October 1, 2025 13:49
Copy link
Owner Author

@RobinTail RobinTail left a comment

Choose a reason for hiding this comment

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

🏁 kinda ready

Copy link
Contributor

@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)
eslint.config.js (2)

27-30: Tighten the regex to match only relative imports and optionally cover dynamic imports.

The current regex /\.js$/ matches any import ending in .js. Anchor it to explicitly target relative imports:

   {
-    selector: "ImportDeclaration[source.value=/\\.js$/]",
+    selector: "ImportDeclaration[source.value=/^\\..*\\.js$/]",
     message: "use .ts extension for relative imports",
   },

If you also want to catch dynamic imports like import('./foo.js'), extend the selector:

-    selector: "ImportDeclaration[source.value=/^\\..*\\.js$/]",
+    selector: "ImportDeclaration[source.value=/^\\..*\\.js$/], ImportExpression[source.value=/^\\..*\\.js$/]",

71-74: Good addition for tree-shaking awareness.

This rule correctly flags a performance concern. Importing package.json prevents tree-shaking and the suggestion to use tsdown and process.env aligns with the build setup.

Optional: Consider fixing the grammar in the message:

-    message: "it can not be tree shaken, use tsdown and process.env instead",
+    message: "it cannot be tree-shaken; use tsdown and process.env instead",
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a08c1dd and 5fd70d4.

📒 Files selected for processing (1)
  • eslint.config.js (2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: RobinTail
PR: RobinTail/express-zod-api#0
File: :0-0
Timestamp: 2025-09-29T03:35:55.530Z
Learning: In the express-zod-api repository, packages are built using tsdown before publishing. Source code with .ts extensions is not published - only the built JavaScript bundles and declaration files in the dist/ directory are published to npm. This means .ts extensions in source imports don't affect consumers.
📚 Learning: 2025-09-25T14:04:50.830Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#2965
File: express-zod-api/src/sse.ts:0-0
Timestamp: 2025-09-25T14:04:50.830Z
Learning: [monologue]
[task analyze_typescript_behavior_1/1]
The user RobinTail is correcting my understanding of TypeScript's type inference for the `return setTimeout(...) && { ... }` expression.
[observations]
- I previously stated that `return setTimeout(...) && { ... }` would have type `NodeJS.Timeout | Emitter<E>`
- RobinTail is claiming the type is actually `Emitter<E>` because the `&&` operator evaluates to its right side when the left side (setTimeout return value) is truthy
- The setTimeout function returns a NodeJS.Timeout which is indeed truthy
- In TypeScript, the `&&` operator has specific type inference rules
- I need to verify the actual TypeScript behavior for this pattern
[analysis]
Let me think through TypeScript's `&&` operator type inference:
1. `setTimeout()` returns `NodeJS.Timeout` which is truthy
2. In `A && B`, if A is always truthy, TypeScript should infer the type as B
3. However, there's also the possibility that TypeScript might still consider the union type `A | B`...

Applied to files:

  • eslint.config.js
📚 Learning: 2025-06-14T16:42:52.972Z
Learnt from: RobinTail
PR: RobinTail/express-zod-api#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:

  • eslint.config.js
⏰ 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: report

@RobinTail
Copy link
Owner Author

RobinTail commented Oct 2, 2025

File extensions are also required to run typescript natively by node

@RobinTail
Copy link
Owner Author

RobinTail commented Oct 4, 2025

dynamic migration rule name might be required for #2980

but I probably would do it in another PR

Copy link
Owner Author

@RobinTail RobinTail left a comment

Choose a reason for hiding this comment

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

🏁 ready now

@RobinTail RobinTail changed the title Switching to stable module: node20 chores: module: node20 and import extensions Oct 4, 2025
@RobinTail RobinTail changed the title chores: module: node20 and import extensions chores: tsconfig module: node20 and import extensions Oct 4, 2025
@RobinTail RobinTail merged commit e5da940 into master Oct 4, 2025
13 checks passed
@RobinTail RobinTail deleted the strict-module-node20 branch October 4, 2025 07:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI/CD refactoring The better way to achieve the same result

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants