next-openapi-gen 1.1.1 → 1.2.0
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 +22 -0
- package/dist/cli.js +97 -4
- package/dist/index.js +97 -4
- package/dist/next/index.js +97 -4
- package/dist/react-router/index.js +97 -4
- package/dist/vite/index.js +97 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -162,6 +162,28 @@ For more adoption patterns, see
|
|
|
162
162
|
|
|
163
163
|
When you target modern OpenAPI output, the Zod path can also split request and response component refs when a supported Zod 4 schema emits different input and output JSON Schema shapes, while the TypeScript path can use selective checker fallback for mapped, conditional, template-literal, and import-based named types.
|
|
164
164
|
|
|
165
|
+
### Add OpenAPI metadata directly in Zod schemas
|
|
166
|
+
|
|
167
|
+
Use `.describe()` for a quick description, or Zod v4's `.meta()` to attach `description`, `examples`, `example`, `deprecated`, `title`, and custom `x-*` extensions without any JSDoc:
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
// .describe() → description field
|
|
171
|
+
z.string().describe("ISO 639-1 language code");
|
|
172
|
+
// → { type: "string", description: "ISO 639-1 language code" }
|
|
173
|
+
|
|
174
|
+
// .meta() → description + examples (and any other OpenAPI key)
|
|
175
|
+
z.number()
|
|
176
|
+
.int()
|
|
177
|
+
.positive()
|
|
178
|
+
.meta({
|
|
179
|
+
description: "PIM ID of the slider",
|
|
180
|
+
examples: [42, 1337],
|
|
181
|
+
});
|
|
182
|
+
// → { type: "integer", exclusiveMinimum: 0, description: "PIM ID of the slider", examples: [42, 1337] }
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Both work inside `z.object({...})` properties, in drizzle-zod override callbacks, and at the top level of named schemas. See [docs/zod4-support-matrix.md](./docs/zod4-support-matrix.md) for the full supported metadata surface.
|
|
186
|
+
|
|
165
187
|
### Generate docs from Drizzle schemas
|
|
166
188
|
|
|
167
189
|
`next-openapi-gen` works well with `drizzle-zod`, so your database schema, validation, and API docs can share the same source of truth.
|
package/dist/cli.js
CHANGED
|
@@ -3154,7 +3154,7 @@ var SymbolResolver = class {
|
|
|
3154
3154
|
|
|
3155
3155
|
// ../openapi-core/dist/schema/zod/drizzle-zod-processor.js
|
|
3156
3156
|
import * as t4 from "@babel/types";
|
|
3157
|
-
var DrizzleZodProcessor = class {
|
|
3157
|
+
var DrizzleZodProcessor = class _DrizzleZodProcessor {
|
|
3158
3158
|
/**
|
|
3159
3159
|
* Known drizzle-zod helper function names
|
|
3160
3160
|
*/
|
|
@@ -3580,6 +3580,16 @@ var DrizzleZodProcessor = class {
|
|
|
3580
3580
|
result.description = args[0].value;
|
|
3581
3581
|
}
|
|
3582
3582
|
break;
|
|
3583
|
+
case "meta": {
|
|
3584
|
+
const firstArg = args[0];
|
|
3585
|
+
if (firstArg && !t4.isSpreadElement(firstArg) && !t4.isArgumentPlaceholder(firstArg)) {
|
|
3586
|
+
const metadata = _DrizzleZodProcessor.extractStaticObject(firstArg);
|
|
3587
|
+
if (metadata) {
|
|
3588
|
+
Object.assign(result, metadata);
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
break;
|
|
3592
|
+
}
|
|
3583
3593
|
case "default":
|
|
3584
3594
|
if (args.length > 0) {
|
|
3585
3595
|
if (t4.isStringLiteral(args[0])) {
|
|
@@ -3600,6 +3610,49 @@ var DrizzleZodProcessor = class {
|
|
|
3600
3610
|
static isDrizzleZodHelper(name) {
|
|
3601
3611
|
return this.DRIZZLE_ZOD_HELPERS.includes(name);
|
|
3602
3612
|
}
|
|
3613
|
+
static extractStaticObject(node) {
|
|
3614
|
+
if (!t4.isObjectExpression(node))
|
|
3615
|
+
return null;
|
|
3616
|
+
const out = {};
|
|
3617
|
+
for (const prop of node.properties) {
|
|
3618
|
+
if (!t4.isObjectProperty(prop))
|
|
3619
|
+
return null;
|
|
3620
|
+
const key = t4.isIdentifier(prop.key) ? prop.key.name : t4.isStringLiteral(prop.key) ? prop.key.value : null;
|
|
3621
|
+
if (!key)
|
|
3622
|
+
return null;
|
|
3623
|
+
const val = _DrizzleZodProcessor.extractStaticValue(prop.value);
|
|
3624
|
+
if (typeof val === "undefined")
|
|
3625
|
+
return null;
|
|
3626
|
+
out[key] = val;
|
|
3627
|
+
}
|
|
3628
|
+
return out;
|
|
3629
|
+
}
|
|
3630
|
+
static extractStaticValue(node) {
|
|
3631
|
+
if (t4.isStringLiteral(node))
|
|
3632
|
+
return node.value;
|
|
3633
|
+
if (t4.isNumericLiteral(node))
|
|
3634
|
+
return node.value;
|
|
3635
|
+
if (t4.isBooleanLiteral(node))
|
|
3636
|
+
return node.value;
|
|
3637
|
+
if (t4.isNullLiteral(node))
|
|
3638
|
+
return null;
|
|
3639
|
+
if (t4.isArrayExpression(node)) {
|
|
3640
|
+
const values = [];
|
|
3641
|
+
for (const el of node.elements) {
|
|
3642
|
+
if (!el || t4.isSpreadElement(el) || t4.isArgumentPlaceholder(el))
|
|
3643
|
+
return void 0;
|
|
3644
|
+
const v = _DrizzleZodProcessor.extractStaticValue(el);
|
|
3645
|
+
if (typeof v === "undefined")
|
|
3646
|
+
return void 0;
|
|
3647
|
+
values.push(v);
|
|
3648
|
+
}
|
|
3649
|
+
return values;
|
|
3650
|
+
}
|
|
3651
|
+
if (t4.isObjectExpression(node)) {
|
|
3652
|
+
return _DrizzleZodProcessor.extractStaticObject(node);
|
|
3653
|
+
}
|
|
3654
|
+
return void 0;
|
|
3655
|
+
}
|
|
3603
3656
|
};
|
|
3604
3657
|
|
|
3605
3658
|
// ../openapi-core/dist/schema/zod/converter-runtime.js
|
|
@@ -4570,8 +4623,12 @@ function processZodPrimitiveNode(node, context) {
|
|
|
4570
4623
|
};
|
|
4571
4624
|
break;
|
|
4572
4625
|
}
|
|
4626
|
+
case "strictObject":
|
|
4573
4627
|
case "object":
|
|
4574
4628
|
schema = node.arguments.length > 0 ? context.processObject(node) : { type: "object" };
|
|
4629
|
+
if (zodType === "strictObject") {
|
|
4630
|
+
schema.additionalProperties = false;
|
|
4631
|
+
}
|
|
4575
4632
|
break;
|
|
4576
4633
|
case "templateLiteral":
|
|
4577
4634
|
schema = { type: "string" };
|
|
@@ -11638,6 +11695,10 @@ var ZodRuntimeExporter = class {
|
|
|
11638
11695
|
return this.buildEnum(node);
|
|
11639
11696
|
case "array":
|
|
11640
11697
|
return node.arguments[0] && isProcessableNode(node.arguments[0]) ? array(this.buildSchema(node.arguments[0]) ?? unknown()) : array(unknown());
|
|
11698
|
+
case "strictObject": {
|
|
11699
|
+
const base = this.buildObject(node);
|
|
11700
|
+
return base && typeof base.strict === "function" ? base.strict() : base;
|
|
11701
|
+
}
|
|
11641
11702
|
case "object":
|
|
11642
11703
|
return this.buildObject(node);
|
|
11643
11704
|
case "record":
|
|
@@ -12657,8 +12718,12 @@ var ZodSchemaConverter = class {
|
|
|
12657
12718
|
}
|
|
12658
12719
|
if (t10.isCallExpression(node) && t10.isMemberExpression(node.callee) && t10.isIdentifier(node.callee.object) && this.isZodLocalName(node.callee.object.name) && t10.isIdentifier(node.callee.property)) {
|
|
12659
12720
|
const methodName = node.callee.property.name;
|
|
12660
|
-
if (methodName === "object" && node.arguments.length > 0) {
|
|
12661
|
-
|
|
12721
|
+
if ((methodName === "object" || methodName === "strictObject") && node.arguments.length > 0) {
|
|
12722
|
+
const schema = this.processZodObject(node);
|
|
12723
|
+
if (methodName === "strictObject") {
|
|
12724
|
+
schema.additionalProperties = false;
|
|
12725
|
+
}
|
|
12726
|
+
return schema;
|
|
12662
12727
|
} else if (methodName === "union" && node.arguments.length > 0) {
|
|
12663
12728
|
return this.processZodUnion(node);
|
|
12664
12729
|
} else if (methodName === "intersection" && node.arguments.length > 0) {
|
|
@@ -14816,6 +14881,8 @@ var SchemaProcessor = class {
|
|
|
14816
14881
|
// Track imports per file for resolving ReturnType<typeof func>
|
|
14817
14882
|
importMap = {};
|
|
14818
14883
|
// { filePath: { importName: importPath } }
|
|
14884
|
+
// Inverted index: typeName → first filePath that imports it (O(1) lookup for findFileImportingType)
|
|
14885
|
+
typeToFileIndex = /* @__PURE__ */ new Map();
|
|
14819
14886
|
currentFilePath = "";
|
|
14820
14887
|
// Track the file being processed
|
|
14821
14888
|
constructor(schemaDir, schemaType = "typescript", schemaFiles, apiDir, fileAccess = defaultFileAccess2, runtime) {
|
|
@@ -14969,6 +15036,13 @@ var SchemaProcessor = class {
|
|
|
14969
15036
|
}
|
|
14970
15037
|
collectImports(ast, filePath) {
|
|
14971
15038
|
collectImports(ast, filePath, this.importMap);
|
|
15039
|
+
const normalizedPath = path14.normalize(filePath);
|
|
15040
|
+
const entries = this.importMap[normalizedPath] ?? {};
|
|
15041
|
+
for (const typeName of Object.keys(entries)) {
|
|
15042
|
+
if (!this.typeToFileIndex.has(typeName)) {
|
|
15043
|
+
this.typeToFileIndex.set(typeName, normalizedPath);
|
|
15044
|
+
}
|
|
15045
|
+
}
|
|
14972
15046
|
}
|
|
14973
15047
|
/**
|
|
14974
15048
|
* Resolve an import path relative to the current file
|
|
@@ -15007,6 +15081,15 @@ var SchemaProcessor = class {
|
|
|
15007
15081
|
}
|
|
15008
15082
|
const typeDefEntry = this.typeDefinitions[typeName.toString()];
|
|
15009
15083
|
if (!typeDefEntry) {
|
|
15084
|
+
const contextFile = this.findFileImportingType(typeName);
|
|
15085
|
+
if (contextFile) {
|
|
15086
|
+
logger.debug(`resolveType: "${typeName}" not in schema dirs; attempting TypeScript checker fallback via ${contextFile}`);
|
|
15087
|
+
const checkerSchema = this.resolveTypeWithTypeScriptChecker(typeName, contextFile);
|
|
15088
|
+
if (checkerSchema && Object.keys(checkerSchema).length > 0) {
|
|
15089
|
+
this.openapiDefinitions[typeName] = checkerSchema;
|
|
15090
|
+
return checkerSchema;
|
|
15091
|
+
}
|
|
15092
|
+
}
|
|
15010
15093
|
logger.debug(`resolveType: no TypeScript definition found for "${typeName}" in ${this.currentFilePath}; returning empty schema`);
|
|
15011
15094
|
return {};
|
|
15012
15095
|
}
|
|
@@ -15218,6 +15301,14 @@ var SchemaProcessor = class {
|
|
|
15218
15301
|
}
|
|
15219
15302
|
return null;
|
|
15220
15303
|
}
|
|
15304
|
+
/**
|
|
15305
|
+
* Return the path of the first scanned file that imports `typeName`, or `null` when none is
|
|
15306
|
+
* found. Used as a fallback context for {@link resolveTypeWithTypeScriptChecker} when the type
|
|
15307
|
+
* is not defined in any schema-dir file (e.g. comes from node_modules or a shared package).
|
|
15308
|
+
*/
|
|
15309
|
+
findFileImportingType(typeName) {
|
|
15310
|
+
return this.typeToFileIndex.get(typeName) ?? null;
|
|
15311
|
+
}
|
|
15221
15312
|
shouldUseTypeScriptChecker(node) {
|
|
15222
15313
|
return t15.isTSConditionalType(node) || t15.isTSMappedType(node) || t15.isTSTemplateLiteralType(node) || t15.isTSImportType(node) || t15.isTSTypeOperator(node) && node.operator === "keyof";
|
|
15223
15314
|
}
|
|
@@ -15281,7 +15372,9 @@ var SchemaProcessor = class {
|
|
|
15281
15372
|
if (seen.has(seenKey)) {
|
|
15282
15373
|
return { type: "object" };
|
|
15283
15374
|
}
|
|
15284
|
-
|
|
15375
|
+
if (!(type.flags & (primitiveLikeFlags | ts2.TypeFlags.Any | ts2.TypeFlags.Never | ts2.TypeFlags.Unknown | ts2.TypeFlags.Void))) {
|
|
15376
|
+
seen.add(seenKey);
|
|
15377
|
+
}
|
|
15285
15378
|
if (type.isStringLiteral()) {
|
|
15286
15379
|
return { type: "string", enum: [type.value] };
|
|
15287
15380
|
}
|
package/dist/index.js
CHANGED
|
@@ -2703,7 +2703,7 @@ var SymbolResolver = class {
|
|
|
2703
2703
|
|
|
2704
2704
|
// ../openapi-core/dist/schema/zod/drizzle-zod-processor.js
|
|
2705
2705
|
import * as t4 from "@babel/types";
|
|
2706
|
-
var DrizzleZodProcessor = class {
|
|
2706
|
+
var DrizzleZodProcessor = class _DrizzleZodProcessor {
|
|
2707
2707
|
/**
|
|
2708
2708
|
* Known drizzle-zod helper function names
|
|
2709
2709
|
*/
|
|
@@ -3129,6 +3129,16 @@ var DrizzleZodProcessor = class {
|
|
|
3129
3129
|
result.description = args[0].value;
|
|
3130
3130
|
}
|
|
3131
3131
|
break;
|
|
3132
|
+
case "meta": {
|
|
3133
|
+
const firstArg = args[0];
|
|
3134
|
+
if (firstArg && !t4.isSpreadElement(firstArg) && !t4.isArgumentPlaceholder(firstArg)) {
|
|
3135
|
+
const metadata = _DrizzleZodProcessor.extractStaticObject(firstArg);
|
|
3136
|
+
if (metadata) {
|
|
3137
|
+
Object.assign(result, metadata);
|
|
3138
|
+
}
|
|
3139
|
+
}
|
|
3140
|
+
break;
|
|
3141
|
+
}
|
|
3132
3142
|
case "default":
|
|
3133
3143
|
if (args.length > 0) {
|
|
3134
3144
|
if (t4.isStringLiteral(args[0])) {
|
|
@@ -3149,6 +3159,49 @@ var DrizzleZodProcessor = class {
|
|
|
3149
3159
|
static isDrizzleZodHelper(name) {
|
|
3150
3160
|
return this.DRIZZLE_ZOD_HELPERS.includes(name);
|
|
3151
3161
|
}
|
|
3162
|
+
static extractStaticObject(node) {
|
|
3163
|
+
if (!t4.isObjectExpression(node))
|
|
3164
|
+
return null;
|
|
3165
|
+
const out = {};
|
|
3166
|
+
for (const prop of node.properties) {
|
|
3167
|
+
if (!t4.isObjectProperty(prop))
|
|
3168
|
+
return null;
|
|
3169
|
+
const key = t4.isIdentifier(prop.key) ? prop.key.name : t4.isStringLiteral(prop.key) ? prop.key.value : null;
|
|
3170
|
+
if (!key)
|
|
3171
|
+
return null;
|
|
3172
|
+
const val = _DrizzleZodProcessor.extractStaticValue(prop.value);
|
|
3173
|
+
if (typeof val === "undefined")
|
|
3174
|
+
return null;
|
|
3175
|
+
out[key] = val;
|
|
3176
|
+
}
|
|
3177
|
+
return out;
|
|
3178
|
+
}
|
|
3179
|
+
static extractStaticValue(node) {
|
|
3180
|
+
if (t4.isStringLiteral(node))
|
|
3181
|
+
return node.value;
|
|
3182
|
+
if (t4.isNumericLiteral(node))
|
|
3183
|
+
return node.value;
|
|
3184
|
+
if (t4.isBooleanLiteral(node))
|
|
3185
|
+
return node.value;
|
|
3186
|
+
if (t4.isNullLiteral(node))
|
|
3187
|
+
return null;
|
|
3188
|
+
if (t4.isArrayExpression(node)) {
|
|
3189
|
+
const values = [];
|
|
3190
|
+
for (const el of node.elements) {
|
|
3191
|
+
if (!el || t4.isSpreadElement(el) || t4.isArgumentPlaceholder(el))
|
|
3192
|
+
return void 0;
|
|
3193
|
+
const v = _DrizzleZodProcessor.extractStaticValue(el);
|
|
3194
|
+
if (typeof v === "undefined")
|
|
3195
|
+
return void 0;
|
|
3196
|
+
values.push(v);
|
|
3197
|
+
}
|
|
3198
|
+
return values;
|
|
3199
|
+
}
|
|
3200
|
+
if (t4.isObjectExpression(node)) {
|
|
3201
|
+
return _DrizzleZodProcessor.extractStaticObject(node);
|
|
3202
|
+
}
|
|
3203
|
+
return void 0;
|
|
3204
|
+
}
|
|
3152
3205
|
};
|
|
3153
3206
|
|
|
3154
3207
|
// ../openapi-core/dist/schema/zod/converter-runtime.js
|
|
@@ -4119,8 +4172,12 @@ function processZodPrimitiveNode(node, context) {
|
|
|
4119
4172
|
};
|
|
4120
4173
|
break;
|
|
4121
4174
|
}
|
|
4175
|
+
case "strictObject":
|
|
4122
4176
|
case "object":
|
|
4123
4177
|
schema = node.arguments.length > 0 ? context.processObject(node) : { type: "object" };
|
|
4178
|
+
if (zodType === "strictObject") {
|
|
4179
|
+
schema.additionalProperties = false;
|
|
4180
|
+
}
|
|
4124
4181
|
break;
|
|
4125
4182
|
case "templateLiteral":
|
|
4126
4183
|
schema = { type: "string" };
|
|
@@ -11187,6 +11244,10 @@ var ZodRuntimeExporter = class {
|
|
|
11187
11244
|
return this.buildEnum(node);
|
|
11188
11245
|
case "array":
|
|
11189
11246
|
return node.arguments[0] && isProcessableNode(node.arguments[0]) ? array(this.buildSchema(node.arguments[0]) ?? unknown()) : array(unknown());
|
|
11247
|
+
case "strictObject": {
|
|
11248
|
+
const base = this.buildObject(node);
|
|
11249
|
+
return base && typeof base.strict === "function" ? base.strict() : base;
|
|
11250
|
+
}
|
|
11190
11251
|
case "object":
|
|
11191
11252
|
return this.buildObject(node);
|
|
11192
11253
|
case "record":
|
|
@@ -12206,8 +12267,12 @@ var ZodSchemaConverter = class {
|
|
|
12206
12267
|
}
|
|
12207
12268
|
if (t10.isCallExpression(node) && t10.isMemberExpression(node.callee) && t10.isIdentifier(node.callee.object) && this.isZodLocalName(node.callee.object.name) && t10.isIdentifier(node.callee.property)) {
|
|
12208
12269
|
const methodName = node.callee.property.name;
|
|
12209
|
-
if (methodName === "object" && node.arguments.length > 0) {
|
|
12210
|
-
|
|
12270
|
+
if ((methodName === "object" || methodName === "strictObject") && node.arguments.length > 0) {
|
|
12271
|
+
const schema = this.processZodObject(node);
|
|
12272
|
+
if (methodName === "strictObject") {
|
|
12273
|
+
schema.additionalProperties = false;
|
|
12274
|
+
}
|
|
12275
|
+
return schema;
|
|
12211
12276
|
} else if (methodName === "union" && node.arguments.length > 0) {
|
|
12212
12277
|
return this.processZodUnion(node);
|
|
12213
12278
|
} else if (methodName === "intersection" && node.arguments.length > 0) {
|
|
@@ -14365,6 +14430,8 @@ var SchemaProcessor = class {
|
|
|
14365
14430
|
// Track imports per file for resolving ReturnType<typeof func>
|
|
14366
14431
|
importMap = {};
|
|
14367
14432
|
// { filePath: { importName: importPath } }
|
|
14433
|
+
// Inverted index: typeName → first filePath that imports it (O(1) lookup for findFileImportingType)
|
|
14434
|
+
typeToFileIndex = /* @__PURE__ */ new Map();
|
|
14368
14435
|
currentFilePath = "";
|
|
14369
14436
|
// Track the file being processed
|
|
14370
14437
|
constructor(schemaDir, schemaType = "typescript", schemaFiles, apiDir, fileAccess = defaultFileAccess2, runtime) {
|
|
@@ -14518,6 +14585,13 @@ var SchemaProcessor = class {
|
|
|
14518
14585
|
}
|
|
14519
14586
|
collectImports(ast, filePath) {
|
|
14520
14587
|
collectImports(ast, filePath, this.importMap);
|
|
14588
|
+
const normalizedPath = path9.normalize(filePath);
|
|
14589
|
+
const entries = this.importMap[normalizedPath] ?? {};
|
|
14590
|
+
for (const typeName of Object.keys(entries)) {
|
|
14591
|
+
if (!this.typeToFileIndex.has(typeName)) {
|
|
14592
|
+
this.typeToFileIndex.set(typeName, normalizedPath);
|
|
14593
|
+
}
|
|
14594
|
+
}
|
|
14521
14595
|
}
|
|
14522
14596
|
/**
|
|
14523
14597
|
* Resolve an import path relative to the current file
|
|
@@ -14556,6 +14630,15 @@ var SchemaProcessor = class {
|
|
|
14556
14630
|
}
|
|
14557
14631
|
const typeDefEntry = this.typeDefinitions[typeName.toString()];
|
|
14558
14632
|
if (!typeDefEntry) {
|
|
14633
|
+
const contextFile = this.findFileImportingType(typeName);
|
|
14634
|
+
if (contextFile) {
|
|
14635
|
+
logger.debug(`resolveType: "${typeName}" not in schema dirs; attempting TypeScript checker fallback via ${contextFile}`);
|
|
14636
|
+
const checkerSchema = this.resolveTypeWithTypeScriptChecker(typeName, contextFile);
|
|
14637
|
+
if (checkerSchema && Object.keys(checkerSchema).length > 0) {
|
|
14638
|
+
this.openapiDefinitions[typeName] = checkerSchema;
|
|
14639
|
+
return checkerSchema;
|
|
14640
|
+
}
|
|
14641
|
+
}
|
|
14559
14642
|
logger.debug(`resolveType: no TypeScript definition found for "${typeName}" in ${this.currentFilePath}; returning empty schema`);
|
|
14560
14643
|
return {};
|
|
14561
14644
|
}
|
|
@@ -14767,6 +14850,14 @@ var SchemaProcessor = class {
|
|
|
14767
14850
|
}
|
|
14768
14851
|
return null;
|
|
14769
14852
|
}
|
|
14853
|
+
/**
|
|
14854
|
+
* Return the path of the first scanned file that imports `typeName`, or `null` when none is
|
|
14855
|
+
* found. Used as a fallback context for {@link resolveTypeWithTypeScriptChecker} when the type
|
|
14856
|
+
* is not defined in any schema-dir file (e.g. comes from node_modules or a shared package).
|
|
14857
|
+
*/
|
|
14858
|
+
findFileImportingType(typeName) {
|
|
14859
|
+
return this.typeToFileIndex.get(typeName) ?? null;
|
|
14860
|
+
}
|
|
14770
14861
|
shouldUseTypeScriptChecker(node) {
|
|
14771
14862
|
return t15.isTSConditionalType(node) || t15.isTSMappedType(node) || t15.isTSTemplateLiteralType(node) || t15.isTSImportType(node) || t15.isTSTypeOperator(node) && node.operator === "keyof";
|
|
14772
14863
|
}
|
|
@@ -14830,7 +14921,9 @@ var SchemaProcessor = class {
|
|
|
14830
14921
|
if (seen.has(seenKey)) {
|
|
14831
14922
|
return { type: "object" };
|
|
14832
14923
|
}
|
|
14833
|
-
|
|
14924
|
+
if (!(type.flags & (primitiveLikeFlags | ts2.TypeFlags.Any | ts2.TypeFlags.Never | ts2.TypeFlags.Unknown | ts2.TypeFlags.Void))) {
|
|
14925
|
+
seen.add(seenKey);
|
|
14926
|
+
}
|
|
14834
14927
|
if (type.isStringLiteral()) {
|
|
14835
14928
|
return { type: "string", enum: [type.value] };
|
|
14836
14929
|
}
|
package/dist/next/index.js
CHANGED
|
@@ -3737,7 +3737,7 @@ var SymbolResolver = class {
|
|
|
3737
3737
|
|
|
3738
3738
|
// ../openapi-core/dist/schema/zod/drizzle-zod-processor.js
|
|
3739
3739
|
import * as t5 from "@babel/types";
|
|
3740
|
-
var DrizzleZodProcessor = class {
|
|
3740
|
+
var DrizzleZodProcessor = class _DrizzleZodProcessor {
|
|
3741
3741
|
/**
|
|
3742
3742
|
* Known drizzle-zod helper function names
|
|
3743
3743
|
*/
|
|
@@ -4163,6 +4163,16 @@ var DrizzleZodProcessor = class {
|
|
|
4163
4163
|
result.description = args[0].value;
|
|
4164
4164
|
}
|
|
4165
4165
|
break;
|
|
4166
|
+
case "meta": {
|
|
4167
|
+
const firstArg = args[0];
|
|
4168
|
+
if (firstArg && !t5.isSpreadElement(firstArg) && !t5.isArgumentPlaceholder(firstArg)) {
|
|
4169
|
+
const metadata = _DrizzleZodProcessor.extractStaticObject(firstArg);
|
|
4170
|
+
if (metadata) {
|
|
4171
|
+
Object.assign(result, metadata);
|
|
4172
|
+
}
|
|
4173
|
+
}
|
|
4174
|
+
break;
|
|
4175
|
+
}
|
|
4166
4176
|
case "default":
|
|
4167
4177
|
if (args.length > 0) {
|
|
4168
4178
|
if (t5.isStringLiteral(args[0])) {
|
|
@@ -4183,6 +4193,49 @@ var DrizzleZodProcessor = class {
|
|
|
4183
4193
|
static isDrizzleZodHelper(name) {
|
|
4184
4194
|
return this.DRIZZLE_ZOD_HELPERS.includes(name);
|
|
4185
4195
|
}
|
|
4196
|
+
static extractStaticObject(node) {
|
|
4197
|
+
if (!t5.isObjectExpression(node))
|
|
4198
|
+
return null;
|
|
4199
|
+
const out = {};
|
|
4200
|
+
for (const prop of node.properties) {
|
|
4201
|
+
if (!t5.isObjectProperty(prop))
|
|
4202
|
+
return null;
|
|
4203
|
+
const key = t5.isIdentifier(prop.key) ? prop.key.name : t5.isStringLiteral(prop.key) ? prop.key.value : null;
|
|
4204
|
+
if (!key)
|
|
4205
|
+
return null;
|
|
4206
|
+
const val = _DrizzleZodProcessor.extractStaticValue(prop.value);
|
|
4207
|
+
if (typeof val === "undefined")
|
|
4208
|
+
return null;
|
|
4209
|
+
out[key] = val;
|
|
4210
|
+
}
|
|
4211
|
+
return out;
|
|
4212
|
+
}
|
|
4213
|
+
static extractStaticValue(node) {
|
|
4214
|
+
if (t5.isStringLiteral(node))
|
|
4215
|
+
return node.value;
|
|
4216
|
+
if (t5.isNumericLiteral(node))
|
|
4217
|
+
return node.value;
|
|
4218
|
+
if (t5.isBooleanLiteral(node))
|
|
4219
|
+
return node.value;
|
|
4220
|
+
if (t5.isNullLiteral(node))
|
|
4221
|
+
return null;
|
|
4222
|
+
if (t5.isArrayExpression(node)) {
|
|
4223
|
+
const values = [];
|
|
4224
|
+
for (const el of node.elements) {
|
|
4225
|
+
if (!el || t5.isSpreadElement(el) || t5.isArgumentPlaceholder(el))
|
|
4226
|
+
return void 0;
|
|
4227
|
+
const v = _DrizzleZodProcessor.extractStaticValue(el);
|
|
4228
|
+
if (typeof v === "undefined")
|
|
4229
|
+
return void 0;
|
|
4230
|
+
values.push(v);
|
|
4231
|
+
}
|
|
4232
|
+
return values;
|
|
4233
|
+
}
|
|
4234
|
+
if (t5.isObjectExpression(node)) {
|
|
4235
|
+
return _DrizzleZodProcessor.extractStaticObject(node);
|
|
4236
|
+
}
|
|
4237
|
+
return void 0;
|
|
4238
|
+
}
|
|
4186
4239
|
};
|
|
4187
4240
|
|
|
4188
4241
|
// ../openapi-core/dist/schema/zod/converter-runtime.js
|
|
@@ -5153,8 +5206,12 @@ function processZodPrimitiveNode(node, context) {
|
|
|
5153
5206
|
};
|
|
5154
5207
|
break;
|
|
5155
5208
|
}
|
|
5209
|
+
case "strictObject":
|
|
5156
5210
|
case "object":
|
|
5157
5211
|
schema = node.arguments.length > 0 ? context.processObject(node) : { type: "object" };
|
|
5212
|
+
if (zodType === "strictObject") {
|
|
5213
|
+
schema.additionalProperties = false;
|
|
5214
|
+
}
|
|
5158
5215
|
break;
|
|
5159
5216
|
case "templateLiteral":
|
|
5160
5217
|
schema = { type: "string" };
|
|
@@ -12221,6 +12278,10 @@ var ZodRuntimeExporter = class {
|
|
|
12221
12278
|
return this.buildEnum(node);
|
|
12222
12279
|
case "array":
|
|
12223
12280
|
return node.arguments[0] && isProcessableNode(node.arguments[0]) ? array(this.buildSchema(node.arguments[0]) ?? unknown()) : array(unknown());
|
|
12281
|
+
case "strictObject": {
|
|
12282
|
+
const base = this.buildObject(node);
|
|
12283
|
+
return base && typeof base.strict === "function" ? base.strict() : base;
|
|
12284
|
+
}
|
|
12224
12285
|
case "object":
|
|
12225
12286
|
return this.buildObject(node);
|
|
12226
12287
|
case "record":
|
|
@@ -13240,8 +13301,12 @@ var ZodSchemaConverter = class {
|
|
|
13240
13301
|
}
|
|
13241
13302
|
if (t11.isCallExpression(node) && t11.isMemberExpression(node.callee) && t11.isIdentifier(node.callee.object) && this.isZodLocalName(node.callee.object.name) && t11.isIdentifier(node.callee.property)) {
|
|
13242
13303
|
const methodName = node.callee.property.name;
|
|
13243
|
-
if (methodName === "object" && node.arguments.length > 0) {
|
|
13244
|
-
|
|
13304
|
+
if ((methodName === "object" || methodName === "strictObject") && node.arguments.length > 0) {
|
|
13305
|
+
const schema = this.processZodObject(node);
|
|
13306
|
+
if (methodName === "strictObject") {
|
|
13307
|
+
schema.additionalProperties = false;
|
|
13308
|
+
}
|
|
13309
|
+
return schema;
|
|
13245
13310
|
} else if (methodName === "union" && node.arguments.length > 0) {
|
|
13246
13311
|
return this.processZodUnion(node);
|
|
13247
13312
|
} else if (methodName === "intersection" && node.arguments.length > 0) {
|
|
@@ -15399,6 +15464,8 @@ var SchemaProcessor = class {
|
|
|
15399
15464
|
// Track imports per file for resolving ReturnType<typeof func>
|
|
15400
15465
|
importMap = {};
|
|
15401
15466
|
// { filePath: { importName: importPath } }
|
|
15467
|
+
// Inverted index: typeName → first filePath that imports it (O(1) lookup for findFileImportingType)
|
|
15468
|
+
typeToFileIndex = /* @__PURE__ */ new Map();
|
|
15402
15469
|
currentFilePath = "";
|
|
15403
15470
|
// Track the file being processed
|
|
15404
15471
|
constructor(schemaDir, schemaType = "typescript", schemaFiles, apiDir, fileAccess = defaultFileAccess2, runtime) {
|
|
@@ -15552,6 +15619,13 @@ var SchemaProcessor = class {
|
|
|
15552
15619
|
}
|
|
15553
15620
|
collectImports(ast, filePath) {
|
|
15554
15621
|
collectImports(ast, filePath, this.importMap);
|
|
15622
|
+
const normalizedPath = path12.normalize(filePath);
|
|
15623
|
+
const entries = this.importMap[normalizedPath] ?? {};
|
|
15624
|
+
for (const typeName of Object.keys(entries)) {
|
|
15625
|
+
if (!this.typeToFileIndex.has(typeName)) {
|
|
15626
|
+
this.typeToFileIndex.set(typeName, normalizedPath);
|
|
15627
|
+
}
|
|
15628
|
+
}
|
|
15555
15629
|
}
|
|
15556
15630
|
/**
|
|
15557
15631
|
* Resolve an import path relative to the current file
|
|
@@ -15590,6 +15664,15 @@ var SchemaProcessor = class {
|
|
|
15590
15664
|
}
|
|
15591
15665
|
const typeDefEntry = this.typeDefinitions[typeName.toString()];
|
|
15592
15666
|
if (!typeDefEntry) {
|
|
15667
|
+
const contextFile = this.findFileImportingType(typeName);
|
|
15668
|
+
if (contextFile) {
|
|
15669
|
+
logger.debug(`resolveType: "${typeName}" not in schema dirs; attempting TypeScript checker fallback via ${contextFile}`);
|
|
15670
|
+
const checkerSchema = this.resolveTypeWithTypeScriptChecker(typeName, contextFile);
|
|
15671
|
+
if (checkerSchema && Object.keys(checkerSchema).length > 0) {
|
|
15672
|
+
this.openapiDefinitions[typeName] = checkerSchema;
|
|
15673
|
+
return checkerSchema;
|
|
15674
|
+
}
|
|
15675
|
+
}
|
|
15593
15676
|
logger.debug(`resolveType: no TypeScript definition found for "${typeName}" in ${this.currentFilePath}; returning empty schema`);
|
|
15594
15677
|
return {};
|
|
15595
15678
|
}
|
|
@@ -15801,6 +15884,14 @@ var SchemaProcessor = class {
|
|
|
15801
15884
|
}
|
|
15802
15885
|
return null;
|
|
15803
15886
|
}
|
|
15887
|
+
/**
|
|
15888
|
+
* Return the path of the first scanned file that imports `typeName`, or `null` when none is
|
|
15889
|
+
* found. Used as a fallback context for {@link resolveTypeWithTypeScriptChecker} when the type
|
|
15890
|
+
* is not defined in any schema-dir file (e.g. comes from node_modules or a shared package).
|
|
15891
|
+
*/
|
|
15892
|
+
findFileImportingType(typeName) {
|
|
15893
|
+
return this.typeToFileIndex.get(typeName) ?? null;
|
|
15894
|
+
}
|
|
15804
15895
|
shouldUseTypeScriptChecker(node) {
|
|
15805
15896
|
return t16.isTSConditionalType(node) || t16.isTSMappedType(node) || t16.isTSTemplateLiteralType(node) || t16.isTSImportType(node) || t16.isTSTypeOperator(node) && node.operator === "keyof";
|
|
15806
15897
|
}
|
|
@@ -15864,7 +15955,9 @@ var SchemaProcessor = class {
|
|
|
15864
15955
|
if (seen.has(seenKey)) {
|
|
15865
15956
|
return { type: "object" };
|
|
15866
15957
|
}
|
|
15867
|
-
|
|
15958
|
+
if (!(type.flags & (primitiveLikeFlags | ts3.TypeFlags.Any | ts3.TypeFlags.Never | ts3.TypeFlags.Unknown | ts3.TypeFlags.Void))) {
|
|
15959
|
+
seen.add(seenKey);
|
|
15960
|
+
}
|
|
15868
15961
|
if (type.isStringLiteral()) {
|
|
15869
15962
|
return { type: "string", enum: [type.value] };
|
|
15870
15963
|
}
|
|
@@ -2741,7 +2741,7 @@ var SymbolResolver = class {
|
|
|
2741
2741
|
|
|
2742
2742
|
// ../openapi-core/dist/schema/zod/drizzle-zod-processor.js
|
|
2743
2743
|
import * as t4 from "@babel/types";
|
|
2744
|
-
var DrizzleZodProcessor = class {
|
|
2744
|
+
var DrizzleZodProcessor = class _DrizzleZodProcessor {
|
|
2745
2745
|
/**
|
|
2746
2746
|
* Known drizzle-zod helper function names
|
|
2747
2747
|
*/
|
|
@@ -3167,6 +3167,16 @@ var DrizzleZodProcessor = class {
|
|
|
3167
3167
|
result.description = args[0].value;
|
|
3168
3168
|
}
|
|
3169
3169
|
break;
|
|
3170
|
+
case "meta": {
|
|
3171
|
+
const firstArg = args[0];
|
|
3172
|
+
if (firstArg && !t4.isSpreadElement(firstArg) && !t4.isArgumentPlaceholder(firstArg)) {
|
|
3173
|
+
const metadata = _DrizzleZodProcessor.extractStaticObject(firstArg);
|
|
3174
|
+
if (metadata) {
|
|
3175
|
+
Object.assign(result, metadata);
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
break;
|
|
3179
|
+
}
|
|
3170
3180
|
case "default":
|
|
3171
3181
|
if (args.length > 0) {
|
|
3172
3182
|
if (t4.isStringLiteral(args[0])) {
|
|
@@ -3187,6 +3197,49 @@ var DrizzleZodProcessor = class {
|
|
|
3187
3197
|
static isDrizzleZodHelper(name) {
|
|
3188
3198
|
return this.DRIZZLE_ZOD_HELPERS.includes(name);
|
|
3189
3199
|
}
|
|
3200
|
+
static extractStaticObject(node) {
|
|
3201
|
+
if (!t4.isObjectExpression(node))
|
|
3202
|
+
return null;
|
|
3203
|
+
const out = {};
|
|
3204
|
+
for (const prop of node.properties) {
|
|
3205
|
+
if (!t4.isObjectProperty(prop))
|
|
3206
|
+
return null;
|
|
3207
|
+
const key = t4.isIdentifier(prop.key) ? prop.key.name : t4.isStringLiteral(prop.key) ? prop.key.value : null;
|
|
3208
|
+
if (!key)
|
|
3209
|
+
return null;
|
|
3210
|
+
const val = _DrizzleZodProcessor.extractStaticValue(prop.value);
|
|
3211
|
+
if (typeof val === "undefined")
|
|
3212
|
+
return null;
|
|
3213
|
+
out[key] = val;
|
|
3214
|
+
}
|
|
3215
|
+
return out;
|
|
3216
|
+
}
|
|
3217
|
+
static extractStaticValue(node) {
|
|
3218
|
+
if (t4.isStringLiteral(node))
|
|
3219
|
+
return node.value;
|
|
3220
|
+
if (t4.isNumericLiteral(node))
|
|
3221
|
+
return node.value;
|
|
3222
|
+
if (t4.isBooleanLiteral(node))
|
|
3223
|
+
return node.value;
|
|
3224
|
+
if (t4.isNullLiteral(node))
|
|
3225
|
+
return null;
|
|
3226
|
+
if (t4.isArrayExpression(node)) {
|
|
3227
|
+
const values = [];
|
|
3228
|
+
for (const el of node.elements) {
|
|
3229
|
+
if (!el || t4.isSpreadElement(el) || t4.isArgumentPlaceholder(el))
|
|
3230
|
+
return void 0;
|
|
3231
|
+
const v = _DrizzleZodProcessor.extractStaticValue(el);
|
|
3232
|
+
if (typeof v === "undefined")
|
|
3233
|
+
return void 0;
|
|
3234
|
+
values.push(v);
|
|
3235
|
+
}
|
|
3236
|
+
return values;
|
|
3237
|
+
}
|
|
3238
|
+
if (t4.isObjectExpression(node)) {
|
|
3239
|
+
return _DrizzleZodProcessor.extractStaticObject(node);
|
|
3240
|
+
}
|
|
3241
|
+
return void 0;
|
|
3242
|
+
}
|
|
3190
3243
|
};
|
|
3191
3244
|
|
|
3192
3245
|
// ../openapi-core/dist/schema/zod/converter-runtime.js
|
|
@@ -4157,8 +4210,12 @@ function processZodPrimitiveNode(node, context) {
|
|
|
4157
4210
|
};
|
|
4158
4211
|
break;
|
|
4159
4212
|
}
|
|
4213
|
+
case "strictObject":
|
|
4160
4214
|
case "object":
|
|
4161
4215
|
schema = node.arguments.length > 0 ? context.processObject(node) : { type: "object" };
|
|
4216
|
+
if (zodType === "strictObject") {
|
|
4217
|
+
schema.additionalProperties = false;
|
|
4218
|
+
}
|
|
4162
4219
|
break;
|
|
4163
4220
|
case "templateLiteral":
|
|
4164
4221
|
schema = { type: "string" };
|
|
@@ -11225,6 +11282,10 @@ var ZodRuntimeExporter = class {
|
|
|
11225
11282
|
return this.buildEnum(node);
|
|
11226
11283
|
case "array":
|
|
11227
11284
|
return node.arguments[0] && isProcessableNode(node.arguments[0]) ? array(this.buildSchema(node.arguments[0]) ?? unknown()) : array(unknown());
|
|
11285
|
+
case "strictObject": {
|
|
11286
|
+
const base = this.buildObject(node);
|
|
11287
|
+
return base && typeof base.strict === "function" ? base.strict() : base;
|
|
11288
|
+
}
|
|
11228
11289
|
case "object":
|
|
11229
11290
|
return this.buildObject(node);
|
|
11230
11291
|
case "record":
|
|
@@ -12244,8 +12305,12 @@ var ZodSchemaConverter = class {
|
|
|
12244
12305
|
}
|
|
12245
12306
|
if (t10.isCallExpression(node) && t10.isMemberExpression(node.callee) && t10.isIdentifier(node.callee.object) && this.isZodLocalName(node.callee.object.name) && t10.isIdentifier(node.callee.property)) {
|
|
12246
12307
|
const methodName = node.callee.property.name;
|
|
12247
|
-
if (methodName === "object" && node.arguments.length > 0) {
|
|
12248
|
-
|
|
12308
|
+
if ((methodName === "object" || methodName === "strictObject") && node.arguments.length > 0) {
|
|
12309
|
+
const schema = this.processZodObject(node);
|
|
12310
|
+
if (methodName === "strictObject") {
|
|
12311
|
+
schema.additionalProperties = false;
|
|
12312
|
+
}
|
|
12313
|
+
return schema;
|
|
12249
12314
|
} else if (methodName === "union" && node.arguments.length > 0) {
|
|
12250
12315
|
return this.processZodUnion(node);
|
|
12251
12316
|
} else if (methodName === "intersection" && node.arguments.length > 0) {
|
|
@@ -14403,6 +14468,8 @@ var SchemaProcessor = class {
|
|
|
14403
14468
|
// Track imports per file for resolving ReturnType<typeof func>
|
|
14404
14469
|
importMap = {};
|
|
14405
14470
|
// { filePath: { importName: importPath } }
|
|
14471
|
+
// Inverted index: typeName → first filePath that imports it (O(1) lookup for findFileImportingType)
|
|
14472
|
+
typeToFileIndex = /* @__PURE__ */ new Map();
|
|
14406
14473
|
currentFilePath = "";
|
|
14407
14474
|
// Track the file being processed
|
|
14408
14475
|
constructor(schemaDir, schemaType = "typescript", schemaFiles, apiDir, fileAccess = defaultFileAccess2, runtime) {
|
|
@@ -14556,6 +14623,13 @@ var SchemaProcessor = class {
|
|
|
14556
14623
|
}
|
|
14557
14624
|
collectImports(ast, filePath) {
|
|
14558
14625
|
collectImports(ast, filePath, this.importMap);
|
|
14626
|
+
const normalizedPath = path9.normalize(filePath);
|
|
14627
|
+
const entries = this.importMap[normalizedPath] ?? {};
|
|
14628
|
+
for (const typeName of Object.keys(entries)) {
|
|
14629
|
+
if (!this.typeToFileIndex.has(typeName)) {
|
|
14630
|
+
this.typeToFileIndex.set(typeName, normalizedPath);
|
|
14631
|
+
}
|
|
14632
|
+
}
|
|
14559
14633
|
}
|
|
14560
14634
|
/**
|
|
14561
14635
|
* Resolve an import path relative to the current file
|
|
@@ -14594,6 +14668,15 @@ var SchemaProcessor = class {
|
|
|
14594
14668
|
}
|
|
14595
14669
|
const typeDefEntry = this.typeDefinitions[typeName.toString()];
|
|
14596
14670
|
if (!typeDefEntry) {
|
|
14671
|
+
const contextFile = this.findFileImportingType(typeName);
|
|
14672
|
+
if (contextFile) {
|
|
14673
|
+
logger.debug(`resolveType: "${typeName}" not in schema dirs; attempting TypeScript checker fallback via ${contextFile}`);
|
|
14674
|
+
const checkerSchema = this.resolveTypeWithTypeScriptChecker(typeName, contextFile);
|
|
14675
|
+
if (checkerSchema && Object.keys(checkerSchema).length > 0) {
|
|
14676
|
+
this.openapiDefinitions[typeName] = checkerSchema;
|
|
14677
|
+
return checkerSchema;
|
|
14678
|
+
}
|
|
14679
|
+
}
|
|
14597
14680
|
logger.debug(`resolveType: no TypeScript definition found for "${typeName}" in ${this.currentFilePath}; returning empty schema`);
|
|
14598
14681
|
return {};
|
|
14599
14682
|
}
|
|
@@ -14805,6 +14888,14 @@ var SchemaProcessor = class {
|
|
|
14805
14888
|
}
|
|
14806
14889
|
return null;
|
|
14807
14890
|
}
|
|
14891
|
+
/**
|
|
14892
|
+
* Return the path of the first scanned file that imports `typeName`, or `null` when none is
|
|
14893
|
+
* found. Used as a fallback context for {@link resolveTypeWithTypeScriptChecker} when the type
|
|
14894
|
+
* is not defined in any schema-dir file (e.g. comes from node_modules or a shared package).
|
|
14895
|
+
*/
|
|
14896
|
+
findFileImportingType(typeName) {
|
|
14897
|
+
return this.typeToFileIndex.get(typeName) ?? null;
|
|
14898
|
+
}
|
|
14808
14899
|
shouldUseTypeScriptChecker(node) {
|
|
14809
14900
|
return t15.isTSConditionalType(node) || t15.isTSMappedType(node) || t15.isTSTemplateLiteralType(node) || t15.isTSImportType(node) || t15.isTSTypeOperator(node) && node.operator === "keyof";
|
|
14810
14901
|
}
|
|
@@ -14868,7 +14959,9 @@ var SchemaProcessor = class {
|
|
|
14868
14959
|
if (seen.has(seenKey)) {
|
|
14869
14960
|
return { type: "object" };
|
|
14870
14961
|
}
|
|
14871
|
-
|
|
14962
|
+
if (!(type.flags & (primitiveLikeFlags | ts2.TypeFlags.Any | ts2.TypeFlags.Never | ts2.TypeFlags.Unknown | ts2.TypeFlags.Void))) {
|
|
14963
|
+
seen.add(seenKey);
|
|
14964
|
+
}
|
|
14872
14965
|
if (type.isStringLiteral()) {
|
|
14873
14966
|
return { type: "string", enum: [type.value] };
|
|
14874
14967
|
}
|
package/dist/vite/index.js
CHANGED
|
@@ -2741,7 +2741,7 @@ var SymbolResolver = class {
|
|
|
2741
2741
|
|
|
2742
2742
|
// ../openapi-core/dist/schema/zod/drizzle-zod-processor.js
|
|
2743
2743
|
import * as t4 from "@babel/types";
|
|
2744
|
-
var DrizzleZodProcessor = class {
|
|
2744
|
+
var DrizzleZodProcessor = class _DrizzleZodProcessor {
|
|
2745
2745
|
/**
|
|
2746
2746
|
* Known drizzle-zod helper function names
|
|
2747
2747
|
*/
|
|
@@ -3167,6 +3167,16 @@ var DrizzleZodProcessor = class {
|
|
|
3167
3167
|
result.description = args[0].value;
|
|
3168
3168
|
}
|
|
3169
3169
|
break;
|
|
3170
|
+
case "meta": {
|
|
3171
|
+
const firstArg = args[0];
|
|
3172
|
+
if (firstArg && !t4.isSpreadElement(firstArg) && !t4.isArgumentPlaceholder(firstArg)) {
|
|
3173
|
+
const metadata = _DrizzleZodProcessor.extractStaticObject(firstArg);
|
|
3174
|
+
if (metadata) {
|
|
3175
|
+
Object.assign(result, metadata);
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
break;
|
|
3179
|
+
}
|
|
3170
3180
|
case "default":
|
|
3171
3181
|
if (args.length > 0) {
|
|
3172
3182
|
if (t4.isStringLiteral(args[0])) {
|
|
@@ -3187,6 +3197,49 @@ var DrizzleZodProcessor = class {
|
|
|
3187
3197
|
static isDrizzleZodHelper(name) {
|
|
3188
3198
|
return this.DRIZZLE_ZOD_HELPERS.includes(name);
|
|
3189
3199
|
}
|
|
3200
|
+
static extractStaticObject(node) {
|
|
3201
|
+
if (!t4.isObjectExpression(node))
|
|
3202
|
+
return null;
|
|
3203
|
+
const out = {};
|
|
3204
|
+
for (const prop of node.properties) {
|
|
3205
|
+
if (!t4.isObjectProperty(prop))
|
|
3206
|
+
return null;
|
|
3207
|
+
const key = t4.isIdentifier(prop.key) ? prop.key.name : t4.isStringLiteral(prop.key) ? prop.key.value : null;
|
|
3208
|
+
if (!key)
|
|
3209
|
+
return null;
|
|
3210
|
+
const val = _DrizzleZodProcessor.extractStaticValue(prop.value);
|
|
3211
|
+
if (typeof val === "undefined")
|
|
3212
|
+
return null;
|
|
3213
|
+
out[key] = val;
|
|
3214
|
+
}
|
|
3215
|
+
return out;
|
|
3216
|
+
}
|
|
3217
|
+
static extractStaticValue(node) {
|
|
3218
|
+
if (t4.isStringLiteral(node))
|
|
3219
|
+
return node.value;
|
|
3220
|
+
if (t4.isNumericLiteral(node))
|
|
3221
|
+
return node.value;
|
|
3222
|
+
if (t4.isBooleanLiteral(node))
|
|
3223
|
+
return node.value;
|
|
3224
|
+
if (t4.isNullLiteral(node))
|
|
3225
|
+
return null;
|
|
3226
|
+
if (t4.isArrayExpression(node)) {
|
|
3227
|
+
const values = [];
|
|
3228
|
+
for (const el of node.elements) {
|
|
3229
|
+
if (!el || t4.isSpreadElement(el) || t4.isArgumentPlaceholder(el))
|
|
3230
|
+
return void 0;
|
|
3231
|
+
const v = _DrizzleZodProcessor.extractStaticValue(el);
|
|
3232
|
+
if (typeof v === "undefined")
|
|
3233
|
+
return void 0;
|
|
3234
|
+
values.push(v);
|
|
3235
|
+
}
|
|
3236
|
+
return values;
|
|
3237
|
+
}
|
|
3238
|
+
if (t4.isObjectExpression(node)) {
|
|
3239
|
+
return _DrizzleZodProcessor.extractStaticObject(node);
|
|
3240
|
+
}
|
|
3241
|
+
return void 0;
|
|
3242
|
+
}
|
|
3190
3243
|
};
|
|
3191
3244
|
|
|
3192
3245
|
// ../openapi-core/dist/schema/zod/converter-runtime.js
|
|
@@ -4157,8 +4210,12 @@ function processZodPrimitiveNode(node, context) {
|
|
|
4157
4210
|
};
|
|
4158
4211
|
break;
|
|
4159
4212
|
}
|
|
4213
|
+
case "strictObject":
|
|
4160
4214
|
case "object":
|
|
4161
4215
|
schema = node.arguments.length > 0 ? context.processObject(node) : { type: "object" };
|
|
4216
|
+
if (zodType === "strictObject") {
|
|
4217
|
+
schema.additionalProperties = false;
|
|
4218
|
+
}
|
|
4162
4219
|
break;
|
|
4163
4220
|
case "templateLiteral":
|
|
4164
4221
|
schema = { type: "string" };
|
|
@@ -11225,6 +11282,10 @@ var ZodRuntimeExporter = class {
|
|
|
11225
11282
|
return this.buildEnum(node);
|
|
11226
11283
|
case "array":
|
|
11227
11284
|
return node.arguments[0] && isProcessableNode(node.arguments[0]) ? array(this.buildSchema(node.arguments[0]) ?? unknown()) : array(unknown());
|
|
11285
|
+
case "strictObject": {
|
|
11286
|
+
const base = this.buildObject(node);
|
|
11287
|
+
return base && typeof base.strict === "function" ? base.strict() : base;
|
|
11288
|
+
}
|
|
11228
11289
|
case "object":
|
|
11229
11290
|
return this.buildObject(node);
|
|
11230
11291
|
case "record":
|
|
@@ -12244,8 +12305,12 @@ var ZodSchemaConverter = class {
|
|
|
12244
12305
|
}
|
|
12245
12306
|
if (t10.isCallExpression(node) && t10.isMemberExpression(node.callee) && t10.isIdentifier(node.callee.object) && this.isZodLocalName(node.callee.object.name) && t10.isIdentifier(node.callee.property)) {
|
|
12246
12307
|
const methodName = node.callee.property.name;
|
|
12247
|
-
if (methodName === "object" && node.arguments.length > 0) {
|
|
12248
|
-
|
|
12308
|
+
if ((methodName === "object" || methodName === "strictObject") && node.arguments.length > 0) {
|
|
12309
|
+
const schema = this.processZodObject(node);
|
|
12310
|
+
if (methodName === "strictObject") {
|
|
12311
|
+
schema.additionalProperties = false;
|
|
12312
|
+
}
|
|
12313
|
+
return schema;
|
|
12249
12314
|
} else if (methodName === "union" && node.arguments.length > 0) {
|
|
12250
12315
|
return this.processZodUnion(node);
|
|
12251
12316
|
} else if (methodName === "intersection" && node.arguments.length > 0) {
|
|
@@ -14403,6 +14468,8 @@ var SchemaProcessor = class {
|
|
|
14403
14468
|
// Track imports per file for resolving ReturnType<typeof func>
|
|
14404
14469
|
importMap = {};
|
|
14405
14470
|
// { filePath: { importName: importPath } }
|
|
14471
|
+
// Inverted index: typeName → first filePath that imports it (O(1) lookup for findFileImportingType)
|
|
14472
|
+
typeToFileIndex = /* @__PURE__ */ new Map();
|
|
14406
14473
|
currentFilePath = "";
|
|
14407
14474
|
// Track the file being processed
|
|
14408
14475
|
constructor(schemaDir, schemaType = "typescript", schemaFiles, apiDir, fileAccess = defaultFileAccess2, runtime) {
|
|
@@ -14556,6 +14623,13 @@ var SchemaProcessor = class {
|
|
|
14556
14623
|
}
|
|
14557
14624
|
collectImports(ast, filePath) {
|
|
14558
14625
|
collectImports(ast, filePath, this.importMap);
|
|
14626
|
+
const normalizedPath = path9.normalize(filePath);
|
|
14627
|
+
const entries = this.importMap[normalizedPath] ?? {};
|
|
14628
|
+
for (const typeName of Object.keys(entries)) {
|
|
14629
|
+
if (!this.typeToFileIndex.has(typeName)) {
|
|
14630
|
+
this.typeToFileIndex.set(typeName, normalizedPath);
|
|
14631
|
+
}
|
|
14632
|
+
}
|
|
14559
14633
|
}
|
|
14560
14634
|
/**
|
|
14561
14635
|
* Resolve an import path relative to the current file
|
|
@@ -14594,6 +14668,15 @@ var SchemaProcessor = class {
|
|
|
14594
14668
|
}
|
|
14595
14669
|
const typeDefEntry = this.typeDefinitions[typeName.toString()];
|
|
14596
14670
|
if (!typeDefEntry) {
|
|
14671
|
+
const contextFile = this.findFileImportingType(typeName);
|
|
14672
|
+
if (contextFile) {
|
|
14673
|
+
logger.debug(`resolveType: "${typeName}" not in schema dirs; attempting TypeScript checker fallback via ${contextFile}`);
|
|
14674
|
+
const checkerSchema = this.resolveTypeWithTypeScriptChecker(typeName, contextFile);
|
|
14675
|
+
if (checkerSchema && Object.keys(checkerSchema).length > 0) {
|
|
14676
|
+
this.openapiDefinitions[typeName] = checkerSchema;
|
|
14677
|
+
return checkerSchema;
|
|
14678
|
+
}
|
|
14679
|
+
}
|
|
14597
14680
|
logger.debug(`resolveType: no TypeScript definition found for "${typeName}" in ${this.currentFilePath}; returning empty schema`);
|
|
14598
14681
|
return {};
|
|
14599
14682
|
}
|
|
@@ -14805,6 +14888,14 @@ var SchemaProcessor = class {
|
|
|
14805
14888
|
}
|
|
14806
14889
|
return null;
|
|
14807
14890
|
}
|
|
14891
|
+
/**
|
|
14892
|
+
* Return the path of the first scanned file that imports `typeName`, or `null` when none is
|
|
14893
|
+
* found. Used as a fallback context for {@link resolveTypeWithTypeScriptChecker} when the type
|
|
14894
|
+
* is not defined in any schema-dir file (e.g. comes from node_modules or a shared package).
|
|
14895
|
+
*/
|
|
14896
|
+
findFileImportingType(typeName) {
|
|
14897
|
+
return this.typeToFileIndex.get(typeName) ?? null;
|
|
14898
|
+
}
|
|
14808
14899
|
shouldUseTypeScriptChecker(node) {
|
|
14809
14900
|
return t15.isTSConditionalType(node) || t15.isTSMappedType(node) || t15.isTSTemplateLiteralType(node) || t15.isTSImportType(node) || t15.isTSTypeOperator(node) && node.operator === "keyof";
|
|
14810
14901
|
}
|
|
@@ -14868,7 +14959,9 @@ var SchemaProcessor = class {
|
|
|
14868
14959
|
if (seen.has(seenKey)) {
|
|
14869
14960
|
return { type: "object" };
|
|
14870
14961
|
}
|
|
14871
|
-
|
|
14962
|
+
if (!(type.flags & (primitiveLikeFlags | ts2.TypeFlags.Any | ts2.TypeFlags.Never | ts2.TypeFlags.Unknown | ts2.TypeFlags.Void))) {
|
|
14963
|
+
seen.add(seenKey);
|
|
14964
|
+
}
|
|
14872
14965
|
if (type.isStringLiteral()) {
|
|
14873
14966
|
return { type: "string", enum: [type.value] };
|
|
14874
14967
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-openapi-gen",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Automatically generate OpenAPI 3.0, 3.1, and 3.2 documentation from Next.js projects, with support for Zod schemas, TypeScript types, and reusable OpenAPI fragments.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|