Repository: samchungy/zod-openapi
Pull request #370 (2024-11-25 01:59:18)

Bump @redocly/cli from 1.25.11 to 1.25.13
Bumps [@redocly/cli](https://github.com/Redocly/redocly-cli) from 1.25.11 to 1.25.13.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/Redocly/redocly-cli/releases"><code>@​redocly/cli</code>'s releases</a>.</em></p>
<blockquote>
<h2><code>@​redocly/cli</code><a href="https://github.com/1"><code>@​1</code></a>.25.13</h2>
<h3>Patch Changes</h3>
<ul>
<li>Added the possibility to skip configurable rules using the <code>--skip-rule</code> option.</li>
<li>Updated <code>@​redocly/openapi-core</code> to v1.25.13.</li>
</ul>
<h2><code>@​redocly/cli</code><a href="https://github.com/1"><code>@​1</code></a>.25.12</h2>
<h3>Patch Changes</h3>
<ul>
<li>Fixed an issue where valid Redocly tokens were not recognized.</li>
<li>Updated <code>@​redocly/openapi-core</code> to v1.25.12.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/Redocly/redocly-cli/blob/main/docs/changelog.md"><code>@​redocly/cli</code>'s changelog</a>.</em></p>
<blockquote>
<h2>1.25.13 (2024-11-21)</h2>
<h3>Patch Changes</h3>
<ul>
<li>Added the possibility to skip configurable rules using the <code>--skip-rule</code> option.</li>
<li>Updated <code>@​redocly/openapi-core</code> to v1.25.13.</li>
</ul>
<h2>1.25.12 (2024-11-20)</h2>
<h3>Patch Changes</h3>
<ul>
<li>Fixed an issue where valid Redocly tokens were not recognized.</li>
<li>Updated <code>@​redocly/openapi-core</code> to v1.25.12.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/Redocly/redocly-cli/commit/0b265e12d0c0858e4ade96d85399579c11e31e98"><code>0b265e1</code></a> chore: 🔖 release new versions (<a href="https://redirect.github.com/Redocly/redocly-cli/issues/1810">#1810</a>)</li>
<li><a href="https://github.com/Redocly/redocly-cli/commit/f55be3f554fc3195576127bca7442df979a4c0d1"><code>f55be3f</code></a> fix: add the possibility to skip configurable rules (<a href="https://redirect.github.com/Redocly/redocly-cli/issues/1809">#1809</a>)</li>
<li><a href="https://github.com/Redocly/redocly-cli/commit/18bb9b6773829cee712605496c7ebdf4de036cfb"><code>18bb9b6</code></a> chore: 🔖 release new versions (<a href="https://redirect.github.com/Redocly/redocly-cli/issues/1808">#1808</a>)</li>
<li><a href="https://github.com/Redocly/redocly-cli/commit/884ca34ae52d44363949324efc55582a443f4484"><code>884ca34</code></a> fix: make isAuthorizedWithRedocly recognize valid Redocly tokens (<a href="https://redirect.github.com/Redocly/redocly-cli/issues/1807">#1807</a>)</li>
<li>See full diff in <a href="https://github.com/Redocly/redocly-cli/compare/@redocly/cli@1.25.11...@redocly/cli@1.25.13">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@redocly/cli&package-manager=npm_and_yarn&previous-version=1.25.11&new-version=1.25.13)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/README.md b/README.md
index d265caa..cabaa97 100644
--- a/README.md
+++ b/README.md
@@ -206,6 +206,7 @@ const document = createDocument({
 const document = createDocument(details, {
   defaultDateSchema: { type: 'string', format: 'date-time' }, // defaults to { type: 'string' }
   unionOneOf: true, // defaults to false. Forces all ZodUnions to output oneOf instead of anyOf. An `.openapi()` `unionOneOf` value takes precedence over this one.
+  enforceDiscriminatedUnionComponents: true, // defaults to false. Throws an error if a Discriminated Union member is not registered as a component.
 });
 ```
 
diff --git a/package.json b/package.json
index 13238f1..8f7bf49 100644
--- a/package.json
+++ b/package.json
@@ -74,12 +74,12 @@
   "devDependencies": {
     "@arethetypeswrong/cli": "0.17.0",
     "@crackle/cli": "0.15.5",
-    "@redocly/cli": "1.25.11",
+    "@redocly/cli": "1.25.13",
     "@types/node": "^20.3.0",
     "eslint-plugin-zod-openapi": "^1.0.0-beta.0",
     "openapi3-ts": "4.4.0",
     "skuba": "9.1.0",
-    "yaml": "2.6.0",
+    "yaml": "2.6.1",
     "zod": "3.23.8"
   },
   "peerDependencies": {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4115c99..610e929 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -15,8 +15,8 @@ importers:
         specifier: 0.15.5
         version: 0.15.5(@types/node@20.12.13)(terser@5.31.1)(typescript@5.6.2)(webpack@5.92.0(@swc/core@1.6.1)(esbuild@0.24.0))
       '@redocly/cli':
-        specifier: 1.25.11
-        version: 1.25.11(encoding@0.1.13)(enzyme@3.11.0)
+        specifier: 1.25.13
+        version: 1.25.13(encoding@0.1.13)(enzyme@3.11.0)
       '@types/node':
         specifier: ^20.3.0
         version: 20.12.13
@@ -30,8 +30,8 @@ importers:
         specifier: 9.1.0
         version: 9.1.0(@babel/core@7.24.6)(@jest/transform@29.7.0)(@swc/core@1.6.1)(@typescript-eslint/eslint-plugin@8.7.0(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@1.21.6))(typescript@5.6.2))(eslint@9.11.1(jiti@1.21.6))(typescript@5.6.2))(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@1.21.6))(typescript@5.6.2))(babel-jest@29.7.0(@babel/core@7.24.6))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@1.21.6))(typescript@5.6.2))(eslint@9.11.1(jiti@1.21.6)))(jiti@1.21.6)
       yaml:
-        specifier: 2.6.0
-        version: 2.6.0
+        specifier: 2.6.1
+        version: 2.6.1
       zod:
         specifier: 3.23.8
         version: 3.23.8
@@ -1181,16 +1181,16 @@ packages:
   '@redocly/ajv@8.11.2':
     resolution: {integrity: sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==}
 
-  '@redocly/cli@1.25.11':
-    resolution: {integrity: sha512-dttBsmLnnbTlJCTa+s7Sy+qtXDq692n7Ru3nUUIHp9XdCbhXIHWhpc8uAl+GmR4MGbVe8ohATl3J+zX3aFy82A==}
+  '@redocly/cli@1.25.13':
+    resolution: {integrity: sha512-bdt9dj6jTu68N3p4+oHc8uYXNKc2kEIZ70G6u627H9oZWUHHH3jxdOH1KiKacjgjB1/0WBxp8scVz0ktLEP7sQ==}
     engines: {node: '>=14.19.0', npm: '>=7.0.0'}
     hasBin: true
 
   '@redocly/config@0.16.0':
     resolution: {integrity: sha512-t9jnODbUcuANRSl/K4L9nb12V+U5acIHnVSl26NWrtSdDZVtoqUXk2yGFPZzohYf62cCfEQUT8ouJ3bhPfpnJg==}
 
-  '@redocly/openapi-core@1.25.11':
-    resolution: {integrity: sha512-bH+a8izQz4fnKROKoX3bEU8sQ9rjvEIZOqU6qTmxlhOJ0NsKa5e+LmU18SV0oFeg5YhWQhhEDihXkvKJ1wMMNQ==}
+  '@redocly/openapi-core@1.25.13':
+    resolution: {integrity: sha512-8O2IdHCHU1EaGc74/Z5nTItfPrakvPEwZ6sf16c/u5ZJJBo3SKbqM2vOLk4spY4Tn0eaAwUxw2b0kXueemp+iw==}
     engines: {node: '>=14.19.0', npm: '>=7.0.0'}
 
   '@remix-run/router@1.16.1':
@@ -5565,8 +5565,8 @@ packages:
     resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
     engines: {node: '>= 6'}
 
-  yaml@2.6.0:
-    resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==}
+  yaml@2.6.1:
+    resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==}
     engines: {node: '>= 14'}
     hasBin: true
 
@@ -6731,9 +6731,9 @@ snapshots:
       require-from-string: 2.0.2
       uri-js-replace: 1.0.1
 
-  '@redocly/cli@1.25.11(encoding@0.1.13)(enzyme@3.11.0)':
+  '@redocly/cli@1.25.13(encoding@0.1.13)(enzyme@3.11.0)':
     dependencies:
-      '@redocly/openapi-core': 1.25.11(encoding@0.1.13)
+      '@redocly/openapi-core': 1.25.13(encoding@0.1.13)
       abort-controller: 3.0.0
       chokidar: 3.6.0
       colorette: 1.4.0
@@ -6762,7 +6762,7 @@ snapshots:
 
   '@redocly/config@0.16.0': {}
 
-  '@redocly/openapi-core@1.25.11(encoding@0.1.13)':
+  '@redocly/openapi-core@1.25.13(encoding@0.1.13)':
     dependencies:
       '@redocly/ajv': 8.11.2
       '@redocly/config': 0.16.0
@@ -10382,7 +10382,7 @@ snapshots:
 
   openapi3-ts@4.4.0:
     dependencies:
-      yaml: 2.6.0
+      yaml: 2.6.1
 
   optionator@0.9.4:
     dependencies:
@@ -10766,7 +10766,7 @@ snapshots:
   redoc@2.2.0(core-js@3.37.1)(encoding@0.1.13)(enzyme@3.11.0)(mobx@6.12.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)):
     dependencies:
       '@cfaester/enzyme-adapter-react-18': 0.8.0(enzyme@3.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@redocly/openapi-core': 1.25.11(encoding@0.1.13)
+      '@redocly/openapi-core': 1.25.13(encoding@0.1.13)
       classnames: 2.5.1
       core-js: 3.37.1
       decko: 1.2.0
@@ -11976,11 +11976,11 @@ snapshots:
     dependencies:
       eslint-visitor-keys: 3.4.3
       lodash: 4.17.21
-      yaml: 2.6.0
+      yaml: 2.6.1
 
   yaml@1.10.2: {}
 
-  yaml@2.6.0: {}
+  yaml@2.6.1: {}
 
   yargs-parser@20.2.9: {}
 
diff --git a/src/create/document.ts b/src/create/document.ts
index 33fbafc..d316815 100644
--- a/src/create/document.ts
+++ b/src/create/document.ts
@@ -155,6 +155,10 @@ export type ZodObjectInputType<
 > = ZodType<Output, Def, Input>;
 
 export interface CreateDocumentOptions {
+  /**
+   * Used to throw an error if a Discriminated Union member is not registered as a component
+   */
+  enforceDiscriminatedUnionComponents?: boolean;
   /**
    * Used to change the default Zod Date schema
    */
diff --git a/src/create/schema/parsers/discriminatedUnion.ts b/src/create/schema/parsers/discriminatedUnion.ts
index 6861dfc..1f928ba 100644
--- a/src/create/schema/parsers/discriminatedUnion.ts
+++ b/src/create/schema/parsers/discriminatedUnion.ts
@@ -36,6 +36,7 @@ export const createDiscriminatedUnionSchema = <
     zodDiscriminatedUnion.discriminator,
     state,
   );
+
   return {
     type: 'schema',
     schema: {
@@ -98,6 +99,11 @@ export const mapDiscriminator = (
     const schema = schemas[index] as oas31.SchemaObject | oas31.ReferenceObject;
     const componentSchemaRef = '$ref' in schema ? schema?.$ref : undefined;
     if (!componentSchemaRef) {
+      if (state.documentOptions?.enforceDiscriminatedUnionComponents) {
+        throw new Error(
+          `Discriminated Union member ${index} at ${state.path.join(' > ')} is not registered as a component`,
+        );
+      }
       return undefined;
     }
 


Test patch:
diff --git a/src/create/schema/parsers/discriminatedUnion.test.ts b/src/create/schema/parsers/discriminatedUnion.test.ts
index 7c77470..69c2f7f 100644
--- a/src/create/schema/parsers/discriminatedUnion.test.ts
+++ b/src/create/schema/parsers/discriminatedUnion.test.ts
@@ -486,4 +486,26 @@ describe('createDiscriminatedUnionSchema', () => {
       ],
     });
   });
+
+  it('throws an error if enforceDiscriminatedUnionComponents is specified and a schema is not registered', () => {
+    const schema = z.discriminatedUnion('type', [
+      z.object({
+        type: z.literal('a'),
+      }),
+      z
+        .object({
+          type: z.literal('b'),
+        })
+        .openapi({ ref: 'b' }),
+    ]);
+
+    expect(() =>
+      createDiscriminatedUnionSchema(schema, {
+        ...createOutputState({}, { enforceDiscriminatedUnionComponents: true }),
+        path: ['some', 'path'],
+      }),
+    ).toThrowErrorMatchingInlineSnapshot(
+      `"Discriminated Union member 0 at some > path is not registered as a component"`,
+    );
+  });
 });