@alt-stack/zod-openapi 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +331 -0
- package/bin/zod-openapi.js +28 -0
- package/dist/index.d.mts +120 -0
- package/dist/index.d.ts +120 -0
- package/dist/index.js +860 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +825 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +35 -0
- package/src/cli.ts +105 -0
- package/src/dependencies.spec.ts +440 -0
- package/src/dependencies.ts +176 -0
- package/src/index.ts +27 -0
- package/src/registry.spec.ts +308 -0
- package/src/registry.ts +227 -0
- package/src/routes.ts +231 -0
- package/src/to-typescript.spec.ts +474 -0
- package/src/to-typescript.ts +289 -0
- package/src/to-zod.spec.ts +480 -0
- package/src/to-zod.ts +112 -0
- package/src/types/array.spec.ts +222 -0
- package/src/types/array.ts +29 -0
- package/src/types/boolean.spec.ts +18 -0
- package/src/types/boolean.ts +6 -0
- package/src/types/intersection.spec.ts +108 -0
- package/src/types/intersection.ts +14 -0
- package/src/types/number.spec.ts +127 -0
- package/src/types/number.ts +20 -0
- package/src/types/object.spec.ts +302 -0
- package/src/types/object.ts +41 -0
- package/src/types/string.spec.ts +431 -0
- package/src/types/string.ts +75 -0
- package/src/types/types.ts +10 -0
- package/src/types/union.spec.ts +135 -0
- package/src/types/union.ts +10 -0
- package/tsconfig.json +12 -0
- package/tsup.config.ts +11 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import {
|
|
4
|
+
registerZodSchemaToOpenApiSchema,
|
|
5
|
+
getSchemaExportedVariableNameForStringFormat,
|
|
6
|
+
clearZodSchemaToOpenApiSchemaRegistry,
|
|
7
|
+
schemaRegistry,
|
|
8
|
+
} from "./registry";
|
|
9
|
+
|
|
10
|
+
describe("ZodSchemaRegistry", () => {
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
clearZodSchemaToOpenApiSchemaRegistry();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe("registerZodSchemaToOpenApiSchema", () => {
|
|
16
|
+
describe("string format registration", () => {
|
|
17
|
+
it("should register schema with single string format", () => {
|
|
18
|
+
const schema = z.string().email();
|
|
19
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
20
|
+
schemaExportedVariableName: "emailSchema",
|
|
21
|
+
type: "string",
|
|
22
|
+
format: "email",
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const result = getSchemaExportedVariableNameForStringFormat("email");
|
|
26
|
+
expect(result).toBe("emailSchema");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("should register schema with multiple string formats", () => {
|
|
30
|
+
const schema = z.string();
|
|
31
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
32
|
+
schemaExportedVariableName: "dateSchema",
|
|
33
|
+
type: "string",
|
|
34
|
+
formats: ["date", "iso-date"],
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
expect(getSchemaExportedVariableNameForStringFormat("date")).toBe(
|
|
38
|
+
"dateSchema",
|
|
39
|
+
);
|
|
40
|
+
expect(getSchemaExportedVariableNameForStringFormat("iso-date")).toBe(
|
|
41
|
+
"dateSchema",
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("should throw error when registering duplicate format", () => {
|
|
46
|
+
const schema1 = z.string().email();
|
|
47
|
+
const schema2 = z.string().email();
|
|
48
|
+
|
|
49
|
+
registerZodSchemaToOpenApiSchema(schema1, {
|
|
50
|
+
schemaExportedVariableName: "emailSchema1",
|
|
51
|
+
type: "string",
|
|
52
|
+
format: "email",
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
expect(() => {
|
|
56
|
+
registerZodSchemaToOpenApiSchema(schema2, {
|
|
57
|
+
schemaExportedVariableName: "emailSchema2",
|
|
58
|
+
type: "string",
|
|
59
|
+
format: "email",
|
|
60
|
+
});
|
|
61
|
+
}).toThrow("duplicate Zod OpenAPI registration");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("should allow same schema to be registered multiple times", () => {
|
|
65
|
+
const schema = z.string().email();
|
|
66
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
67
|
+
schemaExportedVariableName: "emailSchema",
|
|
68
|
+
type: "string",
|
|
69
|
+
format: "email",
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
expect(() => {
|
|
73
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
74
|
+
schemaExportedVariableName: "emailSchema",
|
|
75
|
+
type: "string",
|
|
76
|
+
format: "email",
|
|
77
|
+
});
|
|
78
|
+
}).not.toThrow();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe("primitive type registration", () => {
|
|
83
|
+
it("should register number schema", () => {
|
|
84
|
+
const schema = z.number();
|
|
85
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
86
|
+
schemaExportedVariableName: "numberSchema",
|
|
87
|
+
type: "number",
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
expect(schemaRegistry.isRegistered(schema)).toBe(true);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("should register integer schema", () => {
|
|
94
|
+
const schema = z.number().int();
|
|
95
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
96
|
+
schemaExportedVariableName: "integerSchema",
|
|
97
|
+
type: "integer",
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
expect(schemaRegistry.isRegistered(schema)).toBe(true);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("should register boolean schema", () => {
|
|
104
|
+
const schema = z.boolean();
|
|
105
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
106
|
+
schemaExportedVariableName: "booleanSchema",
|
|
107
|
+
type: "boolean",
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
expect(schemaRegistry.isRegistered(schema)).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe("multiple registrations", () => {
|
|
115
|
+
it("should register multiple schemas with different formats", () => {
|
|
116
|
+
const emailSchema = z.string().email();
|
|
117
|
+
const uuidSchema = z.string().uuid();
|
|
118
|
+
const dateSchema = z.string();
|
|
119
|
+
|
|
120
|
+
registerZodSchemaToOpenApiSchema(emailSchema, {
|
|
121
|
+
schemaExportedVariableName: "emailSchema",
|
|
122
|
+
type: "string",
|
|
123
|
+
format: "email",
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
registerZodSchemaToOpenApiSchema(uuidSchema, {
|
|
127
|
+
schemaExportedVariableName: "uuidSchema",
|
|
128
|
+
type: "string",
|
|
129
|
+
format: "uuid",
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
registerZodSchemaToOpenApiSchema(dateSchema, {
|
|
133
|
+
schemaExportedVariableName: "dateSchema",
|
|
134
|
+
type: "string",
|
|
135
|
+
formats: ["date", "date-time"],
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
expect(getSchemaExportedVariableNameForStringFormat("email")).toBe(
|
|
139
|
+
"emailSchema",
|
|
140
|
+
);
|
|
141
|
+
expect(getSchemaExportedVariableNameForStringFormat("uuid")).toBe(
|
|
142
|
+
"uuidSchema",
|
|
143
|
+
);
|
|
144
|
+
expect(getSchemaExportedVariableNameForStringFormat("date")).toBe(
|
|
145
|
+
"dateSchema",
|
|
146
|
+
);
|
|
147
|
+
expect(getSchemaExportedVariableNameForStringFormat("date-time")).toBe(
|
|
148
|
+
"dateSchema",
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe("getSchemaExportedVariableNameForStringFormat", () => {
|
|
155
|
+
it("should return undefined for unregistered format", () => {
|
|
156
|
+
const result = getSchemaExportedVariableNameForStringFormat("email");
|
|
157
|
+
expect(result).toBeUndefined();
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("should return variable name for registered single format", () => {
|
|
161
|
+
const schema = z.string().email();
|
|
162
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
163
|
+
schemaExportedVariableName: "customEmail",
|
|
164
|
+
type: "string",
|
|
165
|
+
format: "email",
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const result = getSchemaExportedVariableNameForStringFormat("email");
|
|
169
|
+
expect(result).toBe("customEmail");
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("should return variable name for registered format in formats array", () => {
|
|
173
|
+
const schema = z.string();
|
|
174
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
175
|
+
schemaExportedVariableName: "customDate",
|
|
176
|
+
type: "string",
|
|
177
|
+
formats: ["date", "iso-date"],
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
expect(getSchemaExportedVariableNameForStringFormat("date")).toBe(
|
|
181
|
+
"customDate",
|
|
182
|
+
);
|
|
183
|
+
expect(getSchemaExportedVariableNameForStringFormat("iso-date")).toBe(
|
|
184
|
+
"customDate",
|
|
185
|
+
);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("should not return variable name for unregistered format in same schema", () => {
|
|
189
|
+
const schema = z.string();
|
|
190
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
191
|
+
schemaExportedVariableName: "customDate",
|
|
192
|
+
type: "string",
|
|
193
|
+
formats: ["date"],
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const result = getSchemaExportedVariableNameForStringFormat("email");
|
|
197
|
+
expect(result).toBeUndefined();
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
describe("schemaRegistry methods", () => {
|
|
202
|
+
describe("getOpenApiSchema", () => {
|
|
203
|
+
it("should return registration for registered schema", () => {
|
|
204
|
+
const schema = z.string().email();
|
|
205
|
+
const registration = {
|
|
206
|
+
schemaExportedVariableName: "emailSchema",
|
|
207
|
+
type: "string" as const,
|
|
208
|
+
format: "email" as const,
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
registerZodSchemaToOpenApiSchema(schema, registration);
|
|
212
|
+
const result = schemaRegistry.getOpenApiSchema(schema);
|
|
213
|
+
|
|
214
|
+
expect(result).toEqual(registration);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it("should return undefined for unregistered schema", () => {
|
|
218
|
+
const schema = z.string();
|
|
219
|
+
const result = schemaRegistry.getOpenApiSchema(schema);
|
|
220
|
+
expect(result).toBeUndefined();
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
describe("isRegistered", () => {
|
|
225
|
+
it("should return true for registered schema", () => {
|
|
226
|
+
const schema = z.string().email();
|
|
227
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
228
|
+
schemaExportedVariableName: "emailSchema",
|
|
229
|
+
type: "string",
|
|
230
|
+
format: "email",
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
expect(schemaRegistry.isRegistered(schema)).toBe(true);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it("should return false for unregistered schema", () => {
|
|
237
|
+
const schema = z.string();
|
|
238
|
+
expect(schemaRegistry.isRegistered(schema)).toBe(false);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
describe("clear", () => {
|
|
243
|
+
it("should clear all registered schemas", () => {
|
|
244
|
+
const schema = z.string().email();
|
|
245
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
246
|
+
schemaExportedVariableName: "emailSchema",
|
|
247
|
+
type: "string",
|
|
248
|
+
format: "email",
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
expect(schemaRegistry.isRegistered(schema)).toBe(true);
|
|
252
|
+
|
|
253
|
+
clearZodSchemaToOpenApiSchemaRegistry();
|
|
254
|
+
|
|
255
|
+
expect(schemaRegistry.isRegistered(schema)).toBe(false);
|
|
256
|
+
expect(
|
|
257
|
+
getSchemaExportedVariableNameForStringFormat("email"),
|
|
258
|
+
).toBeUndefined();
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
describe("edge cases", () => {
|
|
264
|
+
it("should handle registration with description", () => {
|
|
265
|
+
const schema = z.string().email();
|
|
266
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
267
|
+
schemaExportedVariableName: "emailSchema",
|
|
268
|
+
type: "string",
|
|
269
|
+
format: "email",
|
|
270
|
+
description: "Custom email schema",
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
const result = schemaRegistry.getOpenApiSchema(schema);
|
|
274
|
+
expect(result?.description).toBe("Custom email schema");
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it("should handle all supported string formats", () => {
|
|
278
|
+
const formats = [
|
|
279
|
+
"color-hex",
|
|
280
|
+
"date",
|
|
281
|
+
"date-time",
|
|
282
|
+
"email",
|
|
283
|
+
"iso-date",
|
|
284
|
+
"iso-date-time",
|
|
285
|
+
"objectid",
|
|
286
|
+
"uri",
|
|
287
|
+
"url",
|
|
288
|
+
"uuid",
|
|
289
|
+
];
|
|
290
|
+
|
|
291
|
+
for (const format of formats) {
|
|
292
|
+
const schema = z.string();
|
|
293
|
+
registerZodSchemaToOpenApiSchema(schema, {
|
|
294
|
+
schemaExportedVariableName: `${format}Schema`,
|
|
295
|
+
type: "string",
|
|
296
|
+
format: format as any,
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
const result = getSchemaExportedVariableNameForStringFormat(
|
|
300
|
+
format as any,
|
|
301
|
+
);
|
|
302
|
+
expect(result).toBe(`${format}Schema`);
|
|
303
|
+
|
|
304
|
+
clearZodSchemaToOpenApiSchemaRegistry();
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
});
|
package/src/registry.ts
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Constants
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
const SUPPORTED_STRING_FORMATS_MAP = {
|
|
8
|
+
"color-hex": 1,
|
|
9
|
+
date: 1,
|
|
10
|
+
"date-time": 1,
|
|
11
|
+
email: 1,
|
|
12
|
+
"iso-date": 1,
|
|
13
|
+
"iso-date-time": 1,
|
|
14
|
+
objectid: 1,
|
|
15
|
+
uri: 1,
|
|
16
|
+
url: 1,
|
|
17
|
+
uuid: 1,
|
|
18
|
+
} as const;
|
|
19
|
+
|
|
20
|
+
export const SUPPORTED_STRING_FORMATS = Object.keys(
|
|
21
|
+
SUPPORTED_STRING_FORMATS_MAP,
|
|
22
|
+
) as unknown as keyof typeof SUPPORTED_STRING_FORMATS_MAP;
|
|
23
|
+
|
|
24
|
+
type SupportedStringFormat = typeof SUPPORTED_STRING_FORMATS;
|
|
25
|
+
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Types
|
|
28
|
+
// ============================================================================
|
|
29
|
+
|
|
30
|
+
export type ZodOpenApiRegistrationString<
|
|
31
|
+
F extends SupportedStringFormat = SupportedStringFormat,
|
|
32
|
+
> = {
|
|
33
|
+
/** The name of the schema variable, IMPORTANT: must be named the same as the variable name */
|
|
34
|
+
schemaExportedVariableName: string;
|
|
35
|
+
type: "string";
|
|
36
|
+
description?: string;
|
|
37
|
+
format: F;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type ZodOpenApiRegistrationStrings<
|
|
41
|
+
Fs extends
|
|
42
|
+
readonly SupportedStringFormat[] = readonly SupportedStringFormat[],
|
|
43
|
+
> = {
|
|
44
|
+
/** The name of the schema variable, IMPORTANT: must be named the same as the variable name */
|
|
45
|
+
schemaExportedVariableName: string;
|
|
46
|
+
type: "string";
|
|
47
|
+
description?: string;
|
|
48
|
+
formats: Fs;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type ZodOpenApiRegistrationPrimitive = {
|
|
52
|
+
/** The name of the schema variable, IMPORTANT: must be named the same as the variable name */
|
|
53
|
+
schemaExportedVariableName: string;
|
|
54
|
+
description?: string;
|
|
55
|
+
type: "number" | "integer" | "boolean";
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export type ZodOpenApiRegistration =
|
|
59
|
+
| ZodOpenApiRegistrationString
|
|
60
|
+
| ZodOpenApiRegistrationStrings
|
|
61
|
+
| ZodOpenApiRegistrationPrimitive;
|
|
62
|
+
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// Type Guards
|
|
65
|
+
// ============================================================================
|
|
66
|
+
|
|
67
|
+
function isStringRegistration(
|
|
68
|
+
reg: ZodOpenApiRegistration,
|
|
69
|
+
): reg is ZodOpenApiRegistrationString {
|
|
70
|
+
return reg.type === "string" && "format" in reg;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function isStringsRegistration(
|
|
74
|
+
reg: ZodOpenApiRegistration,
|
|
75
|
+
): reg is ZodOpenApiRegistrationStrings {
|
|
76
|
+
return reg.type === "string" && "formats" in reg;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ============================================================================
|
|
80
|
+
// Helper Functions
|
|
81
|
+
// ============================================================================
|
|
82
|
+
|
|
83
|
+
type TypeFormatPair = { type: string; format: string | undefined };
|
|
84
|
+
|
|
85
|
+
function getTypeFormatPairs(reg: ZodOpenApiRegistration): TypeFormatPair[] {
|
|
86
|
+
if (isStringRegistration(reg)) {
|
|
87
|
+
return [{ type: "string", format: reg.format }];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (isStringsRegistration(reg)) {
|
|
91
|
+
return reg.formats.map((f) => ({ type: "string", format: f }));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ============================================================================
|
|
98
|
+
// Registry Class
|
|
99
|
+
// ============================================================================
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Global registry for mapping Zod schemas to OpenAPI schema representations
|
|
103
|
+
*/
|
|
104
|
+
class ZodSchemaRegistry {
|
|
105
|
+
private readonly map = new Map<z.ZodTypeAny, ZodOpenApiRegistration>();
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Register a Zod schema with its OpenAPI representation
|
|
109
|
+
*/
|
|
110
|
+
register<F extends SupportedStringFormat>(
|
|
111
|
+
schema: z.ZodTypeAny,
|
|
112
|
+
registration: ZodOpenApiRegistrationString<F>,
|
|
113
|
+
): void;
|
|
114
|
+
register<Fs extends readonly SupportedStringFormat[]>(
|
|
115
|
+
schema: z.ZodTypeAny,
|
|
116
|
+
registration: ZodOpenApiRegistrationStrings<Fs>,
|
|
117
|
+
): void;
|
|
118
|
+
register(
|
|
119
|
+
schema: z.ZodTypeAny,
|
|
120
|
+
registration: ZodOpenApiRegistrationPrimitive,
|
|
121
|
+
): void;
|
|
122
|
+
register(schema: z.ZodTypeAny, registration: ZodOpenApiRegistration): void {
|
|
123
|
+
const newPairs = getTypeFormatPairs(registration);
|
|
124
|
+
|
|
125
|
+
if (newPairs.length > 0) {
|
|
126
|
+
for (const [existingSchema, existingRegistration] of this.map.entries()) {
|
|
127
|
+
if (existingSchema === schema) continue;
|
|
128
|
+
|
|
129
|
+
const existingPairs = getTypeFormatPairs(existingRegistration);
|
|
130
|
+
for (const { type, format } of newPairs) {
|
|
131
|
+
if (
|
|
132
|
+
existingPairs.some((p) => p.type === type && p.format === format)
|
|
133
|
+
) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
`duplicate Zod OpenAPI registration for (type, format)=('${type}', '${format as string}')`,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
this.map.set(schema, registration);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Get the OpenAPI schema for a given Zod schema
|
|
147
|
+
*/
|
|
148
|
+
getOpenApiSchema(schema: z.ZodTypeAny): ZodOpenApiRegistration | undefined {
|
|
149
|
+
return this.map.get(schema);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Check if a Zod schema is registered
|
|
154
|
+
*/
|
|
155
|
+
isRegistered(schema: z.ZodTypeAny): boolean {
|
|
156
|
+
return this.map.has(schema);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Clear all registered schemas
|
|
161
|
+
*/
|
|
162
|
+
clear(): void {
|
|
163
|
+
this.map.clear();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Reverse-lookup helper: given a string format, return the registered schema's exported variable name
|
|
168
|
+
*/
|
|
169
|
+
getSchemaExportedVariableNameForStringFormat(
|
|
170
|
+
format: SupportedStringFormat,
|
|
171
|
+
): string | undefined {
|
|
172
|
+
for (const registration of this.map.values()) {
|
|
173
|
+
if (registration.type !== "string") continue;
|
|
174
|
+
|
|
175
|
+
if (
|
|
176
|
+
isStringRegistration(registration) &&
|
|
177
|
+
registration.format === format
|
|
178
|
+
) {
|
|
179
|
+
return registration.schemaExportedVariableName;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (
|
|
183
|
+
isStringsRegistration(registration) &&
|
|
184
|
+
registration.formats.includes(format)
|
|
185
|
+
) {
|
|
186
|
+
return registration.schemaExportedVariableName;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ============================================================================
|
|
194
|
+
// Global Registry Instance
|
|
195
|
+
// ============================================================================
|
|
196
|
+
|
|
197
|
+
export const schemaRegistry = new ZodSchemaRegistry();
|
|
198
|
+
|
|
199
|
+
// ============================================================================
|
|
200
|
+
// Public API
|
|
201
|
+
// ============================================================================
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Helper function to register a Zod schema with its OpenAPI representation
|
|
205
|
+
*/
|
|
206
|
+
export function registerZodSchemaToOpenApiSchema(
|
|
207
|
+
schema: z.ZodTypeAny,
|
|
208
|
+
openApiSchema: ZodOpenApiRegistration,
|
|
209
|
+
): void {
|
|
210
|
+
schemaRegistry.register(schema, openApiSchema as any);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Convenience helper to get an exported schema variable name for a given string format
|
|
215
|
+
*/
|
|
216
|
+
export function getSchemaExportedVariableNameForStringFormat(
|
|
217
|
+
format: SupportedStringFormat,
|
|
218
|
+
): string | undefined {
|
|
219
|
+
return schemaRegistry.getSchemaExportedVariableNameForStringFormat(format);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Clear all registered schemas in the global registry
|
|
224
|
+
*/
|
|
225
|
+
export function clearZodSchemaToOpenApiSchemaRegistry(): void {
|
|
226
|
+
schemaRegistry.clear();
|
|
227
|
+
}
|