Skip to content

Conversation

@RobinTail
Copy link
Owner

@RobinTail RobinTail commented Sep 21, 2025

A user reported that they're having troubles with module augmentation in their environment, but they aren't even using the example() method. It's found to be used in the framework itself and this PR should fix it, so that the framework would be usable for them even without the plugin features.

Summary by CodeRabbit

  • Bug Fixes

    • Resolved a runtime TypeError occurring in environments where a plugin wasn’t loaded, ensuring consistent behavior across setups.
    • Standardized negative response schemas in result handlers to improve reliability without changing external behavior.
  • Chores

    • Added an internal lint rule to flag unsafe example() usage and enforce safer patterns.
  • Documentation

    • Updated the changelog for v24.7.4 describing the patch and its impact.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 21, 2025

Important

Review skipped

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

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

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

Walkthrough

Introduces global example registration for negative schemas to avoid using ZodType.example(), updates result handlers to consume shared schemas, adds an ESLint compatibility rule to flag example() usage, and records the change in the changelog.

Changes

Cohort / File(s) Summary
Changelog update
CHANGELOG.md
Adds v24.7.4 entry noting replacement of ZodType::example() with globalRegistry.add() to fix TypeError in environments without the Zod plugin.
ESLint compatibility rules
eslint.config.js
Adds and integrates a compatibility rule set flagging example() usage on Zod types; merges into existing no-restricted-syntax concerns.
Result handler schema refactor
express-zod-api/src/result-handler.ts
Introduces defaultNegativeSchema and arrayNegativeSchema; registers examples via globalRegistry; updates defaultResultHandler and arrayResultHandler to use shared schemas instead of inline .example() calls.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant Server
  participant ResultHandler
  participant GlobalRegistry as GlobalRegistry

  Note over Server,ResultHandler: Startup / Module load
  Server->>GlobalRegistry: add(defaultNegativeSchema, examples)
  Server->>GlobalRegistry: add(arrayNegativeSchema, examples)

  Note over Client,ResultHandler: Request handling
  Client->>Server: HTTP Request
  Server->>ResultHandler: Process result
  alt Positive path
    ResultHandler-->>Client: Positive response (unchanged)
  else Negative path
    ResultHandler->>ResultHandler: Select shared negative schema
    ResultHandler-->>Client: Negative response using registered schema
  end

  Note right of GlobalRegistry: Used for example metadata<br/>instead of ZodType.example()
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested labels

refactoring

Poem

A bunny taps keys with twitching nose,
Swaps .example() where the error grows.
Registry shelves the samples neat,
Handlers nibble a structured treat.
ESLint thumps a warning beat—
Hop, hop, tidy code complete! 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "v24: Replacing usage of example() method in framework sources" accurately and concisely captures the PR's primary intent—removing internal uses of Zod's example() across framework files (as reflected in result-handler.ts, eslint.config.js, and the changelog)—and is specific enough for a teammate scanning history to understand the main change.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

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 21, 2025

Coverage Status

coverage: 100.0%. remained the same
when pulling 122157b on fix-failsafe-example-method-usage
into 1d25423 on v24.

@RobinTail RobinTail marked this pull request as ready for review September 21, 2025 15:43
@RobinTail
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 21, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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)

36-42: Typo in variable name and broaden selector to catch more .example() calls.

Rename compatibilityConernscompatibilityConcerns. Also, current selector misses optional chaining and computed property calls. Consider the following tweaks.

Apply this diff:

-const compatibilityConerns = [
-  {
-    selector: "CallExpression > MemberExpression[property.name='example']",
-    message: "avoid using example() method to operate without zod plugin",
-  },
-];
+const compatibilityConcerns = [
+  // schema.example()
+  {
+    selector:
+      "CallExpression[callee.type='MemberExpression'][callee.property.name='example']",
+    message: "avoid using example() method to operate without zod plugin",
+  },
+  // schema?.example()
+  {
+    selector:
+      "ChainExpression > CallExpression[callee.type='MemberExpression'][callee.property.name='example']",
+    message: "avoid using example() method to operate without zod plugin",
+  },
+  // schema['example']()
+  {
+    selector:
+      "CallExpression[callee.type='MemberExpression'][callee.computed=true][callee.property.value='example']",
+    message: "avoid using example() method to operate without zod plugin",
+  },
+];

220-220: Update spread usage after rename.

Adjust reference to the corrected variable.

-        ...compatibilityConerns,
+        ...compatibilityConcerns,
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d25423 and c50e58f.

📒 Files selected for processing (3)
  • CHANGELOG.md (1 hunks)
  • eslint.config.js (2 hunks)
  • express-zod-api/src/result-handler.ts (4 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 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/src/result-handler.ts
🔇 Additional comments (5)
CHANGELOG.md (1)

5-11: Changelog entry reads well; scope and rationale are clear.

No API breakage implied and the mitigation is explicit. LGTM.

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

98-107: Good: static negative schema + registry examples (no per-call allocations).

Typed examples via satisfies is a nice safety net. This addresses prior memory concerns about re-adding examples.


125-125: Swapping inline negative schema for a shared constant is correct.

Keeps the error shape consistent and avoids duplicate registry entries.


144-150: Array negative schema registered once with a canonical example.

Matches the handler’s text/plain behavior.


181-181: Negative response now declares text/plain explicitly — LGTM.

Docs generation should reflect this. .example() appears only in express-zod-api/src/zod-plugin.ts; globalRegistry is imported from "zod/v4" in express-zod-api/src/zts.ts, express-zod-api/src/metadata.ts, and express-zod-api/src/result-handler.ts.

@RobinTail
Copy link
Owner Author

✅ QA passed

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

@RobinTail RobinTail merged commit 3aacc05 into v24 Sep 21, 2025
14 checks passed
@RobinTail RobinTail deleted the fix-failsafe-example-method-usage branch September 21, 2025 16:55
RobinTail added a commit that referenced this pull request Sep 21, 2025
Cherry-picked 3aacc05 , #2954 

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- New Features
- Standardized error handling with reusable default and array error
schemas, including documented examples.
- arrayResultHandler now uses a structured negative configuration
(schema + mimeType).

- Bug Fixes
- Resolved a TypeError occurring in some environments related to
generating examples.

- Documentation
  - Added v25.4.1 changelog entry with details and attribution.
  - Updated README with additional contributor avatars.

- Chores
- Introduced an ESLint rule to flag incompatible example() usage,
improving cross-environment compatibility.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants