next-openapi-gen 1.4.0 → 1.4.2

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.
@@ -737,96 +737,100 @@ function typeToOpenApiSchema(type, checker, seen) {
737
737
  return { type: "object" };
738
738
  }
739
739
  seen.add(seenKey);
740
- if (type.isStringLiteral()) {
741
- return { type: "string", enum: [type.value] };
742
- }
743
- if (type.isNumberLiteral()) {
744
- return { type: "number", enum: [type.value] };
745
- }
746
- if (type.flags & ts2.TypeFlags.BooleanLiteral) {
747
- return {
748
- type: "boolean",
749
- enum: [checker.typeToString(type) === "true"]
750
- };
751
- }
752
- if (type.flags & ts2.TypeFlags.TemplateLiteral) {
753
- return { type: "string" };
754
- }
755
- if (type.flags & ts2.TypeFlags.StringLike) {
756
- return { type: "string" };
757
- }
758
- if (type.flags & ts2.TypeFlags.NumberLike) {
759
- return { type: "number" };
760
- }
761
- if (type.flags & ts2.TypeFlags.BooleanLike) {
762
- return { type: "boolean" };
763
- }
764
- if (type.flags & ts2.TypeFlags.Null) {
765
- return { type: "null" };
766
- }
767
- if (type.isUnion()) {
768
- const nullable2 = type.types.some((member) => member.flags & ts2.TypeFlags.Null);
769
- const nonNullTypes = type.types.filter((member) => !(member.flags & ts2.TypeFlags.Null));
770
- const soleNonNullType = nonNullTypes[0];
771
- if (nullable2 && soleNonNullType && nonNullTypes.length === 1) {
740
+ try {
741
+ if (type.isStringLiteral()) {
742
+ return { type: "string", enum: [type.value] };
743
+ }
744
+ if (type.isNumberLiteral()) {
745
+ return { type: "number", enum: [type.value] };
746
+ }
747
+ if (type.flags & ts2.TypeFlags.BooleanLiteral) {
772
748
  return {
773
- ...typeToOpenApiSchema(soleNonNullType, checker, seen),
774
- nullable: true
749
+ type: "boolean",
750
+ enum: [checker.typeToString(type) === "true"]
775
751
  };
776
752
  }
777
- return {
778
- oneOf: nonNullTypes.map((member) => typeToOpenApiSchema(member, checker, seen))
779
- };
780
- }
781
- if (checker.isTupleType(type)) {
782
- const itemTypes = checker.getTypeArguments(type);
783
- return {
784
- type: "array",
785
- prefixItems: itemTypes.map((itemType) => typeToOpenApiSchema(itemType, checker, seen)),
786
- items: false,
787
- minItems: itemTypes.length,
788
- maxItems: itemTypes.length
789
- };
790
- }
791
- if (checker.isArrayType(type)) {
792
- const elementType = checker.getTypeArguments(type)[0];
793
- return {
794
- type: "array",
795
- items: elementType ? typeToOpenApiSchema(elementType, checker, seen) : { type: "object" }
796
- };
797
- }
798
- const properties = checker.getPropertiesOfType(type);
799
- if (properties.length > 0) {
800
- const schemaProperties = {};
801
- const required2 = [];
802
- properties.forEach((property) => {
803
- const propertyDeclaration = property.valueDeclaration || property.declarations?.[0];
804
- if (!propertyDeclaration) {
805
- return;
806
- }
807
- const propertyType = checker.getTypeOfSymbolAtLocation(property, propertyDeclaration);
808
- schemaProperties[property.getName()] = typeToOpenApiSchema(propertyType, checker, seen);
809
- if (!(property.flags & ts2.SymbolFlags.Optional)) {
810
- required2.push(property.getName());
753
+ if (type.flags & ts2.TypeFlags.TemplateLiteral) {
754
+ return { type: "string" };
755
+ }
756
+ if (type.flags & ts2.TypeFlags.StringLike) {
757
+ return { type: "string" };
758
+ }
759
+ if (type.flags & ts2.TypeFlags.NumberLike) {
760
+ return { type: "number" };
761
+ }
762
+ if (type.flags & ts2.TypeFlags.BooleanLike) {
763
+ return { type: "boolean" };
764
+ }
765
+ if (type.flags & ts2.TypeFlags.Null) {
766
+ return { type: "null" };
767
+ }
768
+ if (type.isUnion()) {
769
+ const nullable2 = type.types.some((member) => member.flags & ts2.TypeFlags.Null);
770
+ const nonNullTypes = type.types.filter((member) => !(member.flags & ts2.TypeFlags.Null));
771
+ const soleNonNullType = nonNullTypes[0];
772
+ if (nullable2 && soleNonNullType && nonNullTypes.length === 1) {
773
+ return {
774
+ ...typeToOpenApiSchema(soleNonNullType, checker, seen),
775
+ nullable: true
776
+ };
811
777
  }
812
- });
813
- return required2.length > 0 ? {
814
- type: "object",
815
- properties: schemaProperties,
816
- required: required2
817
- } : {
818
- type: "object",
819
- properties: schemaProperties
820
- };
821
- }
822
- const stringIndexType = type.getStringIndexType();
823
- if (stringIndexType) {
824
- return {
825
- type: "object",
826
- additionalProperties: typeToOpenApiSchema(stringIndexType, checker, seen)
827
- };
778
+ return {
779
+ oneOf: nonNullTypes.map((member) => typeToOpenApiSchema(member, checker, seen))
780
+ };
781
+ }
782
+ if (checker.isTupleType(type)) {
783
+ const itemTypes = checker.getTypeArguments(type);
784
+ return {
785
+ type: "array",
786
+ prefixItems: itemTypes.map((itemType) => typeToOpenApiSchema(itemType, checker, seen)),
787
+ items: false,
788
+ minItems: itemTypes.length,
789
+ maxItems: itemTypes.length
790
+ };
791
+ }
792
+ if (checker.isArrayType(type)) {
793
+ const elementType = checker.getTypeArguments(type)[0];
794
+ return {
795
+ type: "array",
796
+ items: elementType ? typeToOpenApiSchema(elementType, checker, seen) : { type: "object" }
797
+ };
798
+ }
799
+ const properties = checker.getPropertiesOfType(type);
800
+ if (properties.length > 0) {
801
+ const schemaProperties = {};
802
+ const required2 = [];
803
+ properties.forEach((property) => {
804
+ const propertyDeclaration = property.valueDeclaration || property.declarations?.[0];
805
+ if (!propertyDeclaration) {
806
+ return;
807
+ }
808
+ const propertyType = checker.getTypeOfSymbolAtLocation(property, propertyDeclaration);
809
+ schemaProperties[property.getName()] = typeToOpenApiSchema(propertyType, checker, seen);
810
+ if (!(property.flags & ts2.SymbolFlags.Optional)) {
811
+ required2.push(property.getName());
812
+ }
813
+ });
814
+ return required2.length > 0 ? {
815
+ type: "object",
816
+ properties: schemaProperties,
817
+ required: required2
818
+ } : {
819
+ type: "object",
820
+ properties: schemaProperties
821
+ };
822
+ }
823
+ const stringIndexType = type.getStringIndexType();
824
+ if (stringIndexType) {
825
+ return {
826
+ type: "object",
827
+ additionalProperties: typeToOpenApiSchema(stringIndexType, checker, seen)
828
+ };
829
+ }
830
+ return { type: "object" };
831
+ } finally {
832
+ seen.delete(seenKey);
828
833
  }
829
- return { type: "object" };
830
834
  }
831
835
  function unwrapPromiseType(type, checker) {
832
836
  const symbolName = type.getSymbol()?.getName();
@@ -3451,23 +3455,58 @@ var SymbolResolver = class {
3451
3455
  }
3452
3456
  /**
3453
3457
  * Returns a simple literal value (string/number/boolean/null) for a `const` declarator,
3454
- * or `null` if no such declarator exists.
3458
+ * following imports and re-exports when the name is not declared locally.
3455
3459
  */
3456
3460
  resolveLiteral(filePath, name) {
3461
+ const visited = /* @__PURE__ */ new Set();
3462
+ return this.resolveLiteralInternal(filePath, name, visited);
3463
+ }
3464
+ resolveLiteralInternal(filePath, name, visited) {
3465
+ if (visited.has(filePath))
3466
+ return void 0;
3467
+ visited.add(filePath);
3457
3468
  const index = this.getIndex(filePath);
3458
3469
  if (!index)
3459
3470
  return void 0;
3460
3471
  const literal2 = index.constLiterals.get(name);
3461
- if (!literal2)
3462
- return void 0;
3463
- if (t4.isStringLiteral(literal2))
3464
- return literal2.value;
3465
- if (t4.isNumericLiteral(literal2))
3466
- return literal2.value;
3467
- if (t4.isBooleanLiteral(literal2))
3468
- return literal2.value;
3469
- if (t4.isNullLiteral(literal2))
3470
- return null;
3472
+ if (literal2) {
3473
+ if (t4.isStringLiteral(literal2))
3474
+ return literal2.value;
3475
+ if (t4.isNumericLiteral(literal2))
3476
+ return literal2.value;
3477
+ if (t4.isBooleanLiteral(literal2))
3478
+ return literal2.value;
3479
+ if (t4.isNullLiteral(literal2))
3480
+ return null;
3481
+ }
3482
+ const imports = this.getImports(filePath);
3483
+ const importInfo = imports?.get(name);
3484
+ if (importInfo) {
3485
+ const resolved = this.resolveImportPath(filePath, importInfo.source);
3486
+ if (resolved) {
3487
+ const targetName = importInfo.importedName === "default" ? name : importInfo.importedName;
3488
+ const result = this.resolveLiteralInternal(resolved, targetName, visited);
3489
+ if (result !== void 0)
3490
+ return result;
3491
+ }
3492
+ }
3493
+ const reExport = index.namedReExports.get(name);
3494
+ if (reExport) {
3495
+ const resolved = this.resolveImportPath(filePath, reExport.source);
3496
+ if (resolved) {
3497
+ const result = this.resolveLiteralInternal(resolved, reExport.importedName, visited);
3498
+ if (result !== void 0)
3499
+ return result;
3500
+ }
3501
+ }
3502
+ for (const starSrc of index.exportsStar) {
3503
+ const resolved = this.resolveImportPath(filePath, starSrc);
3504
+ if (!resolved)
3505
+ continue;
3506
+ const result = this.resolveLiteralInternal(resolved, name, visited);
3507
+ if (result !== void 0)
3508
+ return result;
3509
+ }
3471
3510
  return void 0;
3472
3511
  }
3473
3512
  /**
@@ -13790,6 +13829,58 @@ var ZodSchemaConverter = class {
13790
13829
  this.symbolResolver.primeAST(this.currentFilePath, this.currentAST);
13791
13830
  return this.symbolResolver.resolveLiteral(this.currentFilePath, name);
13792
13831
  }
13832
+ /**
13833
+ * Unwrap a possible `TSAsExpression` / `TSSatisfiesExpression` to get the
13834
+ * underlying expression node. Returns the node itself when no wrapper is
13835
+ * present.
13836
+ */
13837
+ unwrapTypeAssertion(node) {
13838
+ if (!node)
13839
+ return void 0;
13840
+ if (t11.isTSAsExpression(node) || t11.isTSSatisfiesExpression(node)) {
13841
+ return node.expression;
13842
+ }
13843
+ return node;
13844
+ }
13845
+ /**
13846
+ * Resolve a numeric value from a call-expression argument.
13847
+ * Handles: numeric literals, identifier references to const numbers,
13848
+ * and `x as number` / `x satisfies number` wrappers around either.
13849
+ */
13850
+ resolveNumericArg(arg) {
13851
+ if (!arg)
13852
+ return void 0;
13853
+ const node = this.unwrapTypeAssertion(arg);
13854
+ if (t11.isNumericLiteral(node))
13855
+ return node.value;
13856
+ if (t11.isUnaryExpression(node) && node.operator === "-" && t11.isNumericLiteral(node.argument)) {
13857
+ return -node.argument.value;
13858
+ }
13859
+ if (t11.isIdentifier(node)) {
13860
+ const val = this.resolveLiteralValue(node.name);
13861
+ if (typeof val === "number")
13862
+ return val;
13863
+ }
13864
+ return void 0;
13865
+ }
13866
+ /**
13867
+ * Resolve a string value from a call-expression argument.
13868
+ * Handles: string literals, identifier references to const strings,
13869
+ * and `x as string` / `x satisfies string` wrappers around either.
13870
+ */
13871
+ resolveStringArg(arg) {
13872
+ if (!arg)
13873
+ return void 0;
13874
+ const node = this.unwrapTypeAssertion(arg);
13875
+ if (t11.isStringLiteral(node))
13876
+ return node.value;
13877
+ if (t11.isIdentifier(node)) {
13878
+ const val = this.resolveLiteralValue(node.name);
13879
+ if (typeof val === "string")
13880
+ return val;
13881
+ }
13882
+ return void 0;
13883
+ }
13793
13884
  /**
13794
13885
  * Resolve an identifier referring to a `z.object({...})` (or similar) call expression.
13795
13886
  * This lets callers inline the referenced object's shape.
@@ -13858,6 +13949,14 @@ var ZodSchemaConverter = class {
13858
13949
  if (t11.isNullLiteral(node)) {
13859
13950
  return null;
13860
13951
  }
13952
+ if (t11.isIdentifier(node)) {
13953
+ const val = this.resolveLiteralValue(node.name);
13954
+ if (val !== void 0)
13955
+ return val;
13956
+ }
13957
+ if (t11.isTSAsExpression(node) || t11.isTSSatisfiesExpression(node)) {
13958
+ return this.extractStaticJsonValue(node.expression);
13959
+ }
13861
13960
  if (t11.isArrayExpression(node)) {
13862
13961
  const values = [];
13863
13962
  for (const element of node.elements) {
@@ -13920,7 +14019,7 @@ var ZodSchemaConverter = class {
13920
14019
  return helperName.startsWith("coerce.") || helperName === "templateLiteral" || helperName === "stringbool";
13921
14020
  }
13922
14021
  if (t11.isMemberExpression(node.callee) && t11.isIdentifier(node.callee.property)) {
13923
- const runtimeMethods = /* @__PURE__ */ new Set(["pipe", "meta"]);
14022
+ const runtimeMethods = /* @__PURE__ */ new Set(["pipe"]);
13924
14023
  if (runtimeMethods.has(node.callee.property.name)) {
13925
14024
  return true;
13926
14025
  }
@@ -13956,53 +14055,60 @@ var ZodSchemaConverter = class {
13956
14055
  schema.nullable = true;
13957
14056
  }
13958
14057
  break;
13959
- case "describe":
13960
- if (node.arguments.length > 0 && t11.isStringLiteral(node.arguments[0])) {
13961
- const description = node.arguments[0].value;
13962
- if (description.startsWith("@deprecated")) {
14058
+ case "describe": {
14059
+ const descVal = this.resolveStringArg(node.arguments[0]);
14060
+ if (descVal !== void 0) {
14061
+ if (descVal.startsWith("@deprecated")) {
13963
14062
  schema.deprecated = true;
13964
- schema.description = description.replace("@deprecated", "").trim();
14063
+ schema.description = descVal.replace("@deprecated", "").trim();
13965
14064
  } else {
13966
- schema.description = description;
14065
+ schema.description = descVal;
13967
14066
  }
13968
14067
  }
13969
14068
  break;
14069
+ }
13970
14070
  case "deprecated":
13971
14071
  schema.deprecated = true;
13972
14072
  break;
13973
- case "min":
13974
- if (node.arguments.length > 0 && t11.isNumericLiteral(node.arguments[0])) {
14073
+ case "min": {
14074
+ const minVal = this.resolveNumericArg(node.arguments[0]);
14075
+ if (minVal !== void 0) {
13975
14076
  if (schema.type === "string") {
13976
- schema.minLength = node.arguments[0].value;
14077
+ schema.minLength = minVal;
13977
14078
  } else if (schema.type === "number" || schema.type === "integer") {
13978
- schema.minimum = node.arguments[0].value;
14079
+ schema.minimum = minVal;
13979
14080
  } else if (schema.type === "array") {
13980
- schema.minItems = node.arguments[0].value;
14081
+ schema.minItems = minVal;
13981
14082
  }
13982
14083
  }
13983
14084
  break;
13984
- case "max":
13985
- if (node.arguments.length > 0 && t11.isNumericLiteral(node.arguments[0])) {
14085
+ }
14086
+ case "max": {
14087
+ const maxVal = this.resolveNumericArg(node.arguments[0]);
14088
+ if (maxVal !== void 0) {
13986
14089
  if (schema.type === "string") {
13987
- schema.maxLength = node.arguments[0].value;
14090
+ schema.maxLength = maxVal;
13988
14091
  } else if (schema.type === "number" || schema.type === "integer") {
13989
- schema.maximum = node.arguments[0].value;
14092
+ schema.maximum = maxVal;
13990
14093
  } else if (schema.type === "array") {
13991
- schema.maxItems = node.arguments[0].value;
14094
+ schema.maxItems = maxVal;
13992
14095
  }
13993
14096
  }
13994
14097
  break;
13995
- case "length":
13996
- if (node.arguments.length > 0 && t11.isNumericLiteral(node.arguments[0])) {
14098
+ }
14099
+ case "length": {
14100
+ const lenVal = this.resolveNumericArg(node.arguments[0]);
14101
+ if (lenVal !== void 0) {
13997
14102
  if (schema.type === "string") {
13998
- schema.minLength = node.arguments[0].value;
13999
- schema.maxLength = node.arguments[0].value;
14103
+ schema.minLength = lenVal;
14104
+ schema.maxLength = lenVal;
14000
14105
  } else if (schema.type === "array") {
14001
- schema.minItems = node.arguments[0].value;
14002
- schema.maxItems = node.arguments[0].value;
14106
+ schema.minItems = lenVal;
14107
+ schema.maxItems = lenVal;
14003
14108
  }
14004
14109
  }
14005
14110
  break;
14111
+ }
14006
14112
  case "nonempty":
14007
14113
  if (schema.type === "array") {
14008
14114
  schema.minItems = Math.max(schema.minItems ?? 0, 1);
@@ -14078,34 +14184,38 @@ var ZodSchemaConverter = class {
14078
14184
  schema.pattern = node.arguments[0].pattern;
14079
14185
  }
14080
14186
  break;
14081
- case "startsWith":
14082
- if (node.arguments.length > 0 && t11.isStringLiteral(node.arguments[0])) {
14083
- schema.pattern = `^${this.escapeRegExp(node.arguments[0].value)}`;
14187
+ case "startsWith": {
14188
+ const swVal = this.resolveStringArg(node.arguments[0]);
14189
+ if (swVal !== void 0) {
14190
+ schema.pattern = `^${this.escapeRegExp(swVal)}`;
14084
14191
  }
14085
14192
  break;
14086
- case "endsWith":
14087
- if (node.arguments.length > 0 && t11.isStringLiteral(node.arguments[0])) {
14088
- schema.pattern = `${this.escapeRegExp(node.arguments[0].value)}$`;
14193
+ }
14194
+ case "endsWith": {
14195
+ const ewVal = this.resolveStringArg(node.arguments[0]);
14196
+ if (ewVal !== void 0) {
14197
+ schema.pattern = `${this.escapeRegExp(ewVal)}$`;
14089
14198
  }
14090
14199
  break;
14091
- case "includes":
14092
- if (node.arguments.length > 0 && t11.isStringLiteral(node.arguments[0])) {
14093
- schema.pattern = this.escapeRegExp(node.arguments[0].value);
14200
+ }
14201
+ case "includes": {
14202
+ const incVal = this.resolveStringArg(node.arguments[0]);
14203
+ if (incVal !== void 0) {
14204
+ schema.pattern = this.escapeRegExp(incVal);
14094
14205
  }
14095
14206
  break;
14207
+ }
14096
14208
  case "int":
14097
14209
  schema.type = "integer";
14098
14210
  break;
14099
14211
  case "positive":
14100
- schema.minimum = 0;
14101
- schema.exclusiveMinimum = true;
14212
+ schema.exclusiveMinimum = 0;
14102
14213
  break;
14103
14214
  case "nonnegative":
14104
14215
  schema.minimum = 0;
14105
14216
  break;
14106
14217
  case "negative":
14107
- schema.maximum = 0;
14108
- schema.exclusiveMaximum = true;
14218
+ schema.exclusiveMaximum = 0;
14109
14219
  break;
14110
14220
  case "nonpositive":
14111
14221
  schema.maximum = 0;
@@ -14118,17 +14228,22 @@ var ZodSchemaConverter = class {
14118
14228
  break;
14119
14229
  case "default":
14120
14230
  if (node.arguments.length > 0) {
14121
- if (t11.isStringLiteral(node.arguments[0])) {
14122
- schema.default = node.arguments[0].value;
14123
- } else if (t11.isNumericLiteral(node.arguments[0])) {
14124
- schema.default = node.arguments[0].value;
14125
- } else if (t11.isBooleanLiteral(node.arguments[0])) {
14126
- schema.default = node.arguments[0].value;
14127
- } else if (t11.isNullLiteral(node.arguments[0])) {
14231
+ const defaultArg = this.unwrapTypeAssertion(node.arguments[0]);
14232
+ if (t11.isStringLiteral(defaultArg)) {
14233
+ schema.default = defaultArg.value;
14234
+ } else if (t11.isNumericLiteral(defaultArg)) {
14235
+ schema.default = defaultArg.value;
14236
+ } else if (t11.isBooleanLiteral(defaultArg)) {
14237
+ schema.default = defaultArg.value;
14238
+ } else if (t11.isNullLiteral(defaultArg)) {
14128
14239
  schema.default = null;
14129
- } else if (t11.isObjectExpression(node.arguments[0])) {
14240
+ } else if (t11.isIdentifier(defaultArg)) {
14241
+ const val = this.resolveLiteralValue(defaultArg.name);
14242
+ if (val !== void 0)
14243
+ schema.default = val;
14244
+ } else if (t11.isObjectExpression(defaultArg)) {
14130
14245
  const defaultObj = {};
14131
- node.arguments[0].properties.forEach((prop) => {
14246
+ defaultArg.properties.forEach((prop) => {
14132
14247
  if (t11.isObjectProperty(prop) && (t11.isIdentifier(prop.key) || t11.isStringLiteral(prop.key)) && (t11.isStringLiteral(prop.value) || t11.isNumericLiteral(prop.value) || t11.isBooleanLiteral(prop.value))) {
14133
14248
  const key = t11.isIdentifier(prop.key) ? prop.key.name : prop.key.value;
14134
14249
  const value = t11.isStringLiteral(prop.value) ? prop.value.value : t11.isNumericLiteral(prop.value) ? prop.value.value : t11.isBooleanLiteral(prop.value) ? prop.value.value : null;
@@ -17961,6 +18076,7 @@ function applyExcludeSchemas(document, mergedSchemas, excludedSchemas) {
17961
18076
  if (excludedNames.size === 0)
17962
18077
  return;
17963
18078
  walkAndInline(document, excludedSchemas, excludedNames, /* @__PURE__ */ new Set());
18079
+ walkAndInline(mergedSchemas, excludedSchemas, excludedNames, /* @__PURE__ */ new Set());
17964
18080
  for (const name of excludedNames) {
17965
18081
  delete mergedSchemas[name];
17966
18082
  }