feat(v27): Zod Plugin v4: Moving brand to inheritable metadata#3162
feat(v27): Zod Plugin v4: Moving brand to inheritable metadata#3162
Conversation
📝 WalkthroughWalkthroughBumps zod requirement to ^4.3.4, removes the custom pack/unpack mechanism, and migrates schema branding to use Zod metadata and globalRegistry (brand stored as Changes
Sequence Diagram(s)(omitted) Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
express-zod-api/tests/env.spec.tsexpress-zod-api/tests/integration.spec.tspnpm-workspace.yamlzod-plugin/CHANGELOG.mdzod-plugin/README.mdzod-plugin/package.jsonzod-plugin/src/brand.tszod-plugin/src/index.tszod-plugin/src/packer.tszod-plugin/tests/brand.spec.tszod-plugin/tests/index.spec.tszod-plugin/tests/packer.spec.ts
💤 Files with no reviewable changes (4)
- zod-plugin/src/index.ts
- zod-plugin/src/packer.ts
- zod-plugin/tests/packer.spec.ts
- zod-plugin/tests/index.spec.ts
🧰 Additional context used
🧠 Learnings (26)
📓 Common learnings
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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.
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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.
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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.
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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.
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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.
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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
Repo: RobinTail/express-zod-api PR: 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.
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2869
File: zod-plugin/package.json:42-44
Timestamp: 2025-08-05T14:43:24.702Z
Learning: Zod version 4 has been officially released and is stable. As of August 2025, the latest published version is 4.0.14 (published July 30, 2025). Zod v4 is available on npm and can be used in peer dependencies with version constraints like "^4.0.0".
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2546
File: express-zod-api/src/metadata.ts:5-13
Timestamp: 2025-05-27T20:08:50.699Z
Learning: The `_zod` property in Zod v4 schemas is officially documented and recommended for library authors to differentiate between Zod 3 and Zod 4 schemas at runtime, despite the underscore prefix. This is explicitly mentioned in Zod's library authors documentation and is not a private internal property.
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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.
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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.
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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.
📚 Learning: 2025-08-05T14:43:24.702Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2869
File: zod-plugin/package.json:42-44
Timestamp: 2025-08-05T14:43:24.702Z
Learning: Zod version 4 has been officially released and is stable. As of August 2025, the latest published version is 4.0.14 (published July 30, 2025). Zod v4 is available on npm and can be used in peer dependencies with version constraints like "^4.0.0".
Applied to files:
zod-plugin/package.jsonzod-plugin/README.mdpnpm-workspace.yamlzod-plugin/CHANGELOG.md
📚 Learning: 2025-05-27T19:27:13.492Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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/package.jsonzod-plugin/README.mdpnpm-workspace.yamlexpress-zod-api/tests/integration.spec.tszod-plugin/CHANGELOG.mdzod-plugin/src/brand.ts
📚 Learning: 2025-06-02T21:11:20.768Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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:
zod-plugin/package.jsonpnpm-workspace.yaml
📚 Learning: 2025-08-01T09:48:13.742Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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:
zod-plugin/package.jsonzod-plugin/README.mdpnpm-workspace.yamlexpress-zod-api/tests/integration.spec.tszod-plugin/tests/brand.spec.tszod-plugin/CHANGELOG.mdexpress-zod-api/tests/env.spec.tszod-plugin/src/brand.ts
📚 Learning: 2025-05-27T20:08:50.699Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2546
File: express-zod-api/src/metadata.ts:5-13
Timestamp: 2025-05-27T20:08:50.699Z
Learning: The `_zod` property in Zod v4 schemas is officially documented and recommended for library authors to differentiate between Zod 3 and Zod 4 schemas at runtime, despite the underscore prefix. This is explicitly mentioned in Zod's library authors documentation and is not a private internal property.
Applied to files:
zod-plugin/package.jsonzod-plugin/README.mdexpress-zod-api/tests/integration.spec.tszod-plugin/CHANGELOG.mdzod-plugin/src/brand.ts
📚 Learning: 2025-09-29T06:00:16.488Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2974
File: express-zod-api/src/documentation-helpers.ts:48-48
Timestamp: 2025-09-29T06:00:16.488Z
Learning: In the express-zod-api repository, the project uses pnpm workspaces with autoInstallPeers: false, meaning peerDependencies are not installed. The actual TypeScript version used for development comes from devDependencies which references "catalog:dev" in pnpm-workspace.yaml where it's set to a recent version (^5.9.2), not the peerDependency version which is just the minimum consumer requirement.
Applied to files:
zod-plugin/package.jsonpnpm-workspace.yamlexpress-zod-api/tests/integration.spec.ts
📚 Learning: 2025-08-08T16:45:20.527Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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:
zod-plugin/package.jsonzod-plugin/README.mdexpress-zod-api/tests/integration.spec.tszod-plugin/tests/brand.spec.tszod-plugin/src/brand.ts
📚 Learning: 2025-09-29T03:35:55.561Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 0
File: :0-0
Timestamp: 2025-09-29T03:35:55.561Z
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.
Applied to files:
zod-plugin/package.jsonpnpm-workspace.yamlexpress-zod-api/tests/integration.spec.ts
📚 Learning: 2025-05-27T20:03:34.213Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2546
File: example/factories.ts:35-42
Timestamp: 2025-05-27T20:03:34.213Z
Learning: The `./example` directory in the express-zod-api repository contains demonstration code for educational purposes only, not intended for production use. Example code can make simplified assumptions for brevity and clarity, and should not be flagged for missing production-level error handling, security measures, or edge case handling.
Applied to files:
zod-plugin/package.json
📚 Learning: 2025-10-02T17:42:48.840Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 0
File: :0-0
Timestamp: 2025-10-02T17:42:48.840Z
Learning: In express-zod-api v25 (ESM-only), the `.example()` method error occurs when user code runs as CommonJS. Express Zod API patches Zod's ESM bundle with `.example()`, but CommonJS code requires a separate CJS bundle instance that lacks this patch. Users must run their code as ESM by: (1) setting `"type": "module"` in package.json, (2) using `.mts` or `.mjs` file extensions, or (3) using tools like `tsx` or `vite-node` that provide their own ESM-compatible compilation.
Applied to files:
zod-plugin/package.jsonexpress-zod-api/tests/integration.spec.tszod-plugin/tests/brand.spec.ts
📚 Learning: 2025-05-27T20:27:17.015Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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:
zod-plugin/package.jsonpnpm-workspace.yaml
📚 Learning: 2025-08-08T16:45:20.527Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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:
zod-plugin/README.mdexpress-zod-api/tests/integration.spec.tszod-plugin/tests/brand.spec.tszod-plugin/CHANGELOG.mdzod-plugin/src/brand.ts
📚 Learning: 2025-08-08T11:59:04.814Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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:
zod-plugin/README.mdexpress-zod-api/tests/integration.spec.tszod-plugin/tests/brand.spec.tszod-plugin/src/brand.ts
📚 Learning: 2025-08-08T16:45:20.527Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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:
zod-plugin/README.mdexpress-zod-api/tests/integration.spec.tszod-plugin/tests/brand.spec.tszod-plugin/CHANGELOG.mdzod-plugin/src/brand.ts
📚 Learning: 2025-08-08T16:45:20.527Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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:
zod-plugin/README.mdexpress-zod-api/tests/integration.spec.tszod-plugin/tests/brand.spec.tszod-plugin/CHANGELOG.mdzod-plugin/src/brand.ts
📚 Learning: 2025-05-28T07:58:09.853Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2546
File: express-zod-api/src/documentation-helpers.ts:508-512
Timestamp: 2025-05-28T07:58:09.853Z
Learning: In express-zod-api, when working with Zod's JSON schema override callbacks, using `delete` to mutate `ctx.jsonSchema` is the recommended approach per Zod's official documentation, even if it triggers performance linting warnings. This is preferable to creating copies with `undefined` values, especially for snapshot testing.
Applied to files:
zod-plugin/README.mdexpress-zod-api/tests/integration.spec.ts
📚 Learning: 2025-05-28T19:19:27.727Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 0
File: :0-0
Timestamp: 2025-05-28T19:19:27.727Z
Learning: In pnpm workspaces, most configuration can now be done directly in pnpm-workspace.yaml using the `settings` section instead of requiring .npmrc files. This includes workspace linking, dependency resolution, and performance settings.
Applied to files:
pnpm-workspace.yaml
📚 Learning: 2025-12-18T13:42:39.225Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 3054
File: pnpm-workspace.yaml:68-68
Timestamp: 2025-12-18T13:42:39.225Z
Learning: In the express-zod-api repository, Vite is overridden to v8 beta in pnpm-workspace.yaml specifically to ensure vitest (which depends on Vite) uses the same rolldown bundler as tsdown and unrun. This override is intentional for toolchain consistency, as Vite is only used for testing purposes (not production).
Applied to files:
pnpm-workspace.yaml
📚 Learning: 2025-06-02T21:08:56.475Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2697
File: CHANGELOG.md:5-5
Timestamp: 2025-06-02T21:08:56.475Z
Learning: The `cjs-test` directory in the express-zod-api repository is a test workspace and should be excluded when checking for main project version consistency with changelog entries.
Applied to files:
pnpm-workspace.yamlexpress-zod-api/tests/integration.spec.tsexpress-zod-api/tests/env.spec.ts
📚 Learning: 2025-05-27T20:27:17.015Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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:
pnpm-workspace.yamlexpress-zod-api/tests/integration.spec.tszod-plugin/tests/brand.spec.tszod-plugin/CHANGELOG.mdzod-plugin/src/brand.ts
📚 Learning: 2025-05-27T19:35:57.357Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2546
File: express-zod-api/tests/buffer-schema.spec.ts:32-37
Timestamp: 2025-05-27T19:35:57.357Z
Learning: In the express-zod-api project, tests are run from the `express-zod-api` workspace directory, and the project uses an ESM-first environment without `__dirname`. Relative paths like `../logo.svg` in test files correctly resolve to the repository root due to this test execution context.
Applied to files:
express-zod-api/tests/integration.spec.tszod-plugin/tests/brand.spec.tsexpress-zod-api/tests/env.spec.ts
📚 Learning: 2025-06-14T16:42:52.972Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2736
File: express-zod-api/tsup.config.ts:12-26
Timestamp: 2025-06-14T16:42:52.972Z
Learning: In express-zod-api tsup configurations, the direct mutation of `options.supported` in the `esbuildOptions` callback is intentional behavior and should not be flagged as a side effect issue.
Applied to files:
express-zod-api/tests/integration.spec.tsexpress-zod-api/tests/env.spec.ts
📚 Learning: 2025-05-28T18:58:10.064Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2428
File: express-zod-api/src/index.ts:44-44
Timestamp: 2025-05-28T18:58:10.064Z
Learning: The type-only import `import type {} from "qs";` in express-zod-api/src/index.ts is necessary to avoid TS2742 errors for exported functions like attachRouting, makeRequestMock, testEndpoint, and testMiddleware that have types depending on types/qs. This import provides the reference TypeScript needs to infer portable type names.
Applied to files:
express-zod-api/tests/integration.spec.ts
📚 Learning: 2025-05-27T20:22:30.428Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 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:
zod-plugin/tests/brand.spec.tsexpress-zod-api/tests/env.spec.ts
📚 Learning: 2025-09-08T09:24:05.821Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2922
File: example/endpoints/list-users.ts:4-4
Timestamp: 2025-09-08T09:24:05.821Z
Learning: In Zod v4, z.literal() accepts arrays and supports multiple values in a single schema (e.g., z.literal(["manager", "operator", "admin"]) is valid), unlike previous versions where it only accepted single literal values. The .value property was replaced with .values which is a Set.
Applied to files:
zod-plugin/CHANGELOG.md
🧬 Code graph analysis (2)
express-zod-api/tests/integration.spec.ts (1)
express-zod-api/src/middleware.ts (1)
schema(82-84)
zod-plugin/tests/brand.spec.ts (2)
zod-plugin/src/brand.ts (3)
brandProperty(4-4)setBrand(7-9)getBrand(15-24)zod-plugin/src/index.ts (1)
getBrand(2-2)
🔇 Additional comments (13)
pnpm-workspace.yaml (1)
53-53: LGTM!The Zod version bump to
^4.3.4is consistent across bothpeeranddevcatalogs, properly aligning with the PR's goal of utilizing inheritable metadata introduced in Zod 4.3.0.Also applies to: 68-68
zod-plugin/package.json (1)
3-3: LGTM!The major version bump to
4.0.0-beta.1is appropriate given the breaking changes (removal ofpack()andunpack()APIs). The beta designation allows for user feedback before stable release.express-zod-api/tests/env.spec.ts (1)
132-136: LGTM!This test correctly validates Zod 4.3's metadata inheritance feature, which is the foundation for this PR's changes. The test demonstrates that metadata from a parent schema propagates through schema transformations like
.min(1).zod-plugin/CHANGELOG.md (1)
3-10: LGTM!The changelog entry accurately documents the breaking changes:
- Zod version requirement bump to
^4.3.4- Removal of
pack()andunpack()(with clear migration path to.meta())- Brand metadata storage change
zod-plugin/tests/brand.spec.ts (3)
1-1: LGTM!Import correctly adds
globalRegistryfrom zod to support the new metadata retrieval mechanism.
12-16: LGTM!The test correctly verifies that
setBrandstores the brand under the"x-brand"key via the schema's.meta()method.
20-27: LGTM!The parameterized test comprehensively covers all edge cases for
getBrand:
- Metadata with brand present → returns the brand value
- Empty metadata object → returns
undefined- No metadata registered → returns
undefinedThe conditional
if (metadata)correctly skips registry manipulation for theundefinedcase.express-zod-api/tests/integration.spec.ts (2)
2-2: LGTM!Import correctly adds
globalRegistryfrom zod to support the registry-based brand clearing mechanism.
136-136: Verify:globalRegistry.remove()clears all metadata, not just the brand.The previous implementation (
schema._zod.bag.brand = undefined) only cleared the brand property. The new approach usingglobalRegistry.remove(schema)removes the entire schema from the registry, clearing all metadata (examples, descriptions, etc.), not just the brand.If this behavioral difference is intentional for this test case, this is fine. However, if the intent is to only clear the brand while preserving other metadata, consider using a more targeted approach.
zod-plugin/src/brand.ts (4)
3-4: LGTM! OpenAPI-compliant naming.The rename to
"x-brand"correctly follows the OpenAPI convention of prefixing vendor extensions with"x-".
7-9: The implementation is correct. The test at line 12-16 ofbrand.spec.tsconfirms that.meta()preserves immutability:const subject = setBrand.call(parent, "test")returns a new schema instance with the metadata properly set, verified byexpect(subject.meta()).toHaveProperty(brandProperty, "test"). The migration frompack()to Zod's native.meta()API is sound and working as expected.
1-1: TheglobalRegistryAPI is officially available and stable in Zod 4.3.4. It is a documented global registry for schema metadata with core methods includingget(),has(),remove(), andclear(), plus convenience methods like.meta(). The import from the main"zod"package is correct, and the API is part of Zod's official interface.
15-24: Remove the verification request—the implementation is correct.The
getBrandfunction properly retrieves brand metadata fromglobalRegistrywith a safe fallback and type guards. The codebase pattern intentionally applies.brand()at the terminal point of schema chains, after transformations (seedate-in-schema.tsanddate-out-schema.ts), rather than expecting brands to be inherited through transforms. Tests confirm brand metadata is preserved through refinements and schema description, which validates the design.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
<img width="1200" height="630" alt="image" src="https://github.com/user-attachments/assets/5af2b247-bd39-4481-98a4-0ab6586afe49" /> Nikki Kuhnhausen was 17 years young transgender woman. She was murdered by David Bogdanov in 2019. Her body was identified from decayed remains on December 7th, in the Larch Mountain area near Vancouver, Washington. Authorities were able to identify the body from personal effects; subsequent examination showed she died from strangulation. Nikki had previously been missing since June 5th when she left with David Bogdanov, a 25-year-old male she met in Snapchat, who has since been charged with second degree murder. Authorities believe that Bogdanov, looking for a sexual encounter, became enraged upon learning of Nikki's transgender origins. https://katu.com/news/local/missing-vancouver-teen-nikki-kuhnhausen-found-dead-in-remote-clark-county-location-suspect-arrested Transgender women suffer too frequently from transphobic violence and cruelty, being the less protected social group. I'd like to raise an awareness of this problem. Humans should be creators — not killers. But most importantly, I want every transgender girl to have an opportunity to create applications quickly and, in general, learn to write code easily in order to receive job offers and leave dangerously transphobic territories for more favorable and civilized ones, and live happily there. Protect transgender women. ------------------ Version 27 makes `typescript` an optional peer dependency with explicit injection of the manually imported module into the `Integration` class constructor (`new Integration({ typescript, ... })`), or by calling the new async `Integration.create()` factory method for automatic loading. The Zod Plugin now leverages Zod 4.3's inheritable metadata feature, removing the need for `pack()` and `unpack()` helpers while simplifying brand handling by storing brands in standard metadata under `x-brand` property. - #3149 - #3162 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Async Integration.create() factory and optional TypeScript injection for client generation * Zod metadata is inheritable (requires Zod ^4.3.4) * **Breaking Changes** * pack/unpack/setBrand removed; branding exposed as "x-brand" via schema.meta() * Integration constructor now accepts a typescript option and usage may require async create() * **Documentation** * Examples updated for TypeScript injection and async create() usage * **Chores** * Version bumps to v27 beta and updated CI branch targets <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Thanks to #3156 storing the runtime distinguishable brand in the
bagis no longer required, since metadata became inheritable between zod schemas inglobalRegistrystarting from Zod v4.3.0.See https://github.com/colinhacks/zod/pull/5578/changes for implementation.
Breaking changes to the Zod Plugin:
pack()andunpack()removed (no longer needed)Summary by CodeRabbit
New Features
Breaking Changes
Chores
✏️ Tip: You can customize this high-level summary in your review settings.