Repository: samchungy/zod-openapi
Pull request #348 (2024-10-28 07:23:01)

Support changing the components path in `createSchema`


Patch:
diff --git a/README.md b/README.md
index b6ad16d..6089aef 100644
--- a/README.md
+++ b/README.md
@@ -276,6 +276,7 @@ const { schema, components } = createSchema(job, {
   schemaType: 'input'; // This controls whether this should be rendered as a request (`input`) or response (`output`). Defaults to `output`
   openapi: '3.0.0'; // OpenAPI version to use, defaults to `'3.1.0'`
   components: { jobId: z.string() } // Additional components to use and create while rendering the schema
+  componentRefPath: '#/definitions/' // Defaults to #/components/schemas/
 })
 ```
 
diff --git a/src/create/components.ts b/src/create/components.ts
index f42542c..91306bc 100644
--- a/src/create/components.ts
+++ b/src/create/components.ts
@@ -385,8 +385,10 @@ const getCallbacks = (
   });
 };
 
-export const createComponentSchemaRef = (schemaRef: string) =>
-  `#/components/schemas/${schemaRef}`;
+export const createComponentSchemaRef = (
+  schemaRef: string,
+  componentPath?: string,
+) => `${componentPath ?? '#/components/schemas/'}${schemaRef}`;
 
 export const createComponentResponseRef = (responseRef: string) =>
   `#/components/responses/${responseRef}`;
diff --git a/src/create/schema/index.ts b/src/create/schema/index.ts
index 8e021a1..e9abb7f 100644
--- a/src/create/schema/index.ts
+++ b/src/create/schema/index.ts
@@ -8,11 +8,11 @@ import {
   type SchemaComponent,
   createComponentSchemaRef,
 } from '../components';
-import type { CreateDocumentOptions } from '../document';
 
 import { enhanceWithMetadata } from './metadata';
 import { createSchemaSwitch } from './parsers';
 import { verifyEffects } from './parsers/transform';
+import type { CreateSchemaOptions } from './single';
 
 export type LazyMap = Map<ZodType, true>;
 
@@ -21,7 +21,7 @@ export interface SchemaState {
   type: CreationType;
   path: string[];
   visited: Set<ZodType>;
-  documentOptions?: CreateDocumentOptions;
+  documentOptions?: CreateSchemaOptions;
 }
 
 const isDescriptionEqual = (schema: Schema, zodSchema: ZodType): boolean =>
@@ -95,7 +95,12 @@ export const createNewRef = <
 
   return {
     type: 'ref',
-    schema: { $ref: createComponentSchemaRef(ref) },
+    schema: {
+      $ref: createComponentSchemaRef(
+        ref,
+        state.documentOptions?.componentRefPath,
+      ),
+    },
     effects: newSchema.effects
       ? [
           {
@@ -121,7 +126,12 @@ export const createExistingRef = <
   if (component && component.type === 'complete') {
     return {
       type: 'ref',
-      schema: { $ref: createComponentSchemaRef(component.ref) },
+      schema: {
+        $ref: createComponentSchemaRef(
+          component.ref,
+          state.documentOptions?.componentRefPath,
+        ),
+      },
       effects: component.effects
         ? [
             {
@@ -138,7 +148,12 @@ export const createExistingRef = <
   if (component && component.type === 'in-progress') {
     return {
       type: 'ref',
-      schema: { $ref: createComponentSchemaRef(component.ref) },
+      schema: {
+        $ref: createComponentSchemaRef(
+          component.ref,
+          state.documentOptions?.componentRefPath,
+        ),
+      },
       effects: [
         {
           type: 'component',
diff --git a/src/create/schema/parsers/object.ts b/src/create/schema/parsers/object.ts
index 523caec..30ad5d8 100644
--- a/src/create/schema/parsers/object.ts
+++ b/src/create/schema/parsers/object.ts
@@ -107,7 +107,14 @@ export const createExtendedSchema = <
   return {
     type: 'schema',
     schema: {
-      allOf: [{ $ref: createComponentSchemaRef(completeComponent.ref) }],
+      allOf: [
+        {
+          $ref: createComponentSchemaRef(
+            completeComponent.ref,
+            state.documentOptions?.componentRefPath,
+          ),
+        },
+      ],
       ...extendedSchema.schema,
     },
     effects: flattenEffects([
diff --git a/src/create/schema/single.ts b/src/create/schema/single.ts
index 193b136..6cde6e3 100644
--- a/src/create/schema/single.ts
+++ b/src/create/schema/single.ts
@@ -34,6 +34,10 @@ export interface CreateSchemaOptions extends CreateDocumentOptions {
    * Additional components to use and create while rendering the schema
    */
   components?: Record<string, ZodType>;
+  /**
+   * The $ref path to use for the component. Defaults to `#/components/schemas/`
+   */
+  componentRefPath?: string;
 }
 
 export const createSchema = (


Test patch:
diff --git a/src/create/schema/single.test.ts b/src/create/schema/single.test.ts
index bae5893..c344bca 100644
--- a/src/create/schema/single.test.ts
+++ b/src/create/schema/single.test.ts
@@ -58,4 +58,25 @@ describe('createSchema', () => {
       },
     });
   });
+
+  it('should support componentRefPath', () => {
+    const schema = createSchema(
+      z.string().openapi({ description: 'foo', ref: 'String' }),
+      {
+        componentRefPath: '#/definitions/',
+      },
+    );
+
+    expect(schema).toEqual<SchemaResult>({
+      schema: {
+        $ref: '#/definitions/String',
+      },
+      components: {
+        String: {
+          type: 'string',
+          description: 'foo',
+        },
+      },
+    });
+  });
 });