next-openapi-gen 1.4.1 → 1.4.3

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/dist/index.js CHANGED
@@ -448,7 +448,6 @@ function parseJSDocBlock(commentValue, filePath) {
448
448
  result.summary = explicitSummary;
449
449
  }
450
450
  result.description = extractLineValue(normalizedComment, "@description");
451
- result.tag = extractLineValue(normalizedComment, "@tag");
452
451
  result.tagSummary = extractLineValue(normalizedComment, "@tagSummary");
453
452
  result.tagKind = extractLineValue(normalizedComment, "@tagKind");
454
453
  result.tagParent = extractLineValue(normalizedComment, "@tagParent");
@@ -482,17 +481,28 @@ function parseJSDocBlock(commentValue, filePath) {
482
481
  if (Array.isArray(responsePrefixEncoding)) {
483
482
  result.responsePrefixEncoding = responsePrefixEncoding;
484
483
  }
485
- const parsedResponse = parseResponseTag(normalizedComment);
486
- if (parsedResponse) {
487
- result.successCode = parsedResponse.successCode;
488
- result.responseType = parsedResponse.responseType;
489
- if (!result.responseDescription && parsedResponse.responseDescription) {
490
- result.responseDescription = parsedResponse.responseDescription;
484
+ const responseMatches = [...normalizedComment.matchAll(/@response\s+([^\n\r@]+)/g)];
485
+ if (responseMatches.length > 0) {
486
+ const firstRaw = responseMatches[0]?.[1]?.trim();
487
+ if (firstRaw) {
488
+ const parsedResponse = parseResponseRawValue(firstRaw);
489
+ result.successCode = parsedResponse.successCode;
490
+ result.responseType = parsedResponse.responseType;
491
+ if (!result.responseDescription && parsedResponse.responseDescription) {
492
+ result.responseDescription = parsedResponse.responseDescription;
493
+ }
494
+ }
495
+ const extraResponses = responseMatches.slice(1).map((m) => m[1]?.trim()).filter((t17) => Boolean(t17));
496
+ if (extraResponses.length > 0) {
497
+ result.addResponses = extraResponses.join(",");
491
498
  }
492
499
  }
493
500
  const addMatches = [...normalizedComment.matchAll(/@add\s+([^\n\r@]*)/g)];
494
501
  if (addMatches.length > 0) {
495
- result.addResponses = addMatches.map((match) => match[1]?.trim() || "").filter(Boolean).join(",");
502
+ const addEntries = addMatches.map((match) => match[1]?.trim() || "").filter(Boolean).join(",");
503
+ if (addEntries) {
504
+ result.addResponses = result.addResponses ? `${result.addResponses},${addEntries}` : addEntries;
505
+ }
496
506
  }
497
507
  const examples = collectExampleDefinitions(normalizedComment, "@examples", filePath);
498
508
  result.requestExamples = buildExampleMap(examples.definitions, "request");
@@ -505,6 +515,17 @@ function parseJSDocBlock(commentValue, filePath) {
505
515
  if (additionalTags.length > 0) {
506
516
  result.tags = additionalTags;
507
517
  }
518
+ const tagMatches = [...normalizedComment.matchAll(/@tag\s+([^\n\r@]*)/g)];
519
+ if (tagMatches.length > 0) {
520
+ const primaryTag = tagMatches[0]?.[1]?.trim();
521
+ if (primaryTag) {
522
+ result.tag = primaryTag;
523
+ }
524
+ const extraTags = tagMatches.slice(1).map((m) => m[1]?.trim()).filter((t17) => Boolean(t17));
525
+ if (extraTags.length > 0) {
526
+ result.tags = [...result.tags ?? [], ...extraTags];
527
+ }
528
+ }
508
529
  const servers = parseServersTag(normalizedComment);
509
530
  if (servers.length > 0) {
510
531
  result.servers = servers;
@@ -707,11 +728,7 @@ function parseOpenApiOverrideTag(commentValue) {
707
728
  function extractTypeFromComment(commentValue, tag) {
708
729
  return commentValue.match(new RegExp(`^\\s*\\*?\\s*${tag}\\s+([\\w<>,\\s[\\]]+)`, "m"))?.[1]?.trim() || "";
709
730
  }
710
- function parseResponseTag(commentValue) {
711
- const rawValue = commentValue.match(/@response\s+([^\n\r@]+)/)?.[1]?.trim();
712
- if (!rawValue) {
713
- return null;
714
- }
731
+ function parseResponseRawValue(rawValue) {
715
732
  if (isStatusCodeToken(rawValue)) {
716
733
  return {
717
734
  responseDescription: "",
@@ -1160,6 +1177,18 @@ function getOperationId(routePath, method) {
1160
1177
  const operation = routePath.replaceAll(/\//g, "-").replace(/^-/, "");
1161
1178
  return `${method}-${operation}`;
1162
1179
  }
1180
+ function deepMerge(target, source) {
1181
+ for (const key of Object.keys(source)) {
1182
+ const sourceVal = source[key];
1183
+ const targetVal = target[key];
1184
+ if (sourceVal !== null && typeof sourceVal === "object" && !Array.isArray(sourceVal) && targetVal !== null && typeof targetVal === "object" && !Array.isArray(targetVal)) {
1185
+ deepMerge(targetVal, sourceVal);
1186
+ } else {
1187
+ target[key] = sourceVal;
1188
+ }
1189
+ }
1190
+ return target;
1191
+ }
1163
1192
  var DEFAULT_PARSER_OPTIONS = {
1164
1193
  sourceType: "module",
1165
1194
  plugins: ["typescript", "jsx", "decorators-legacy"]
@@ -2417,23 +2446,58 @@ var SymbolResolver = class {
2417
2446
  }
2418
2447
  /**
2419
2448
  * Returns a simple literal value (string/number/boolean/null) for a `const` declarator,
2420
- * or `null` if no such declarator exists.
2449
+ * following imports and re-exports when the name is not declared locally.
2421
2450
  */
2422
2451
  resolveLiteral(filePath, name) {
2452
+ const visited = /* @__PURE__ */ new Set();
2453
+ return this.resolveLiteralInternal(filePath, name, visited);
2454
+ }
2455
+ resolveLiteralInternal(filePath, name, visited) {
2456
+ if (visited.has(filePath))
2457
+ return void 0;
2458
+ visited.add(filePath);
2423
2459
  const index = this.getIndex(filePath);
2424
2460
  if (!index)
2425
2461
  return void 0;
2426
2462
  const literal2 = index.constLiterals.get(name);
2427
- if (!literal2)
2428
- return void 0;
2429
- if (t3.isStringLiteral(literal2))
2430
- return literal2.value;
2431
- if (t3.isNumericLiteral(literal2))
2432
- return literal2.value;
2433
- if (t3.isBooleanLiteral(literal2))
2434
- return literal2.value;
2435
- if (t3.isNullLiteral(literal2))
2436
- return null;
2463
+ if (literal2) {
2464
+ if (t3.isStringLiteral(literal2))
2465
+ return literal2.value;
2466
+ if (t3.isNumericLiteral(literal2))
2467
+ return literal2.value;
2468
+ if (t3.isBooleanLiteral(literal2))
2469
+ return literal2.value;
2470
+ if (t3.isNullLiteral(literal2))
2471
+ return null;
2472
+ }
2473
+ const imports = this.getImports(filePath);
2474
+ const importInfo = imports?.get(name);
2475
+ if (importInfo) {
2476
+ const resolved = this.resolveImportPath(filePath, importInfo.source);
2477
+ if (resolved) {
2478
+ const targetName = importInfo.importedName === "default" ? name : importInfo.importedName;
2479
+ const result = this.resolveLiteralInternal(resolved, targetName, visited);
2480
+ if (result !== void 0)
2481
+ return result;
2482
+ }
2483
+ }
2484
+ const reExport = index.namedReExports.get(name);
2485
+ if (reExport) {
2486
+ const resolved = this.resolveImportPath(filePath, reExport.source);
2487
+ if (resolved) {
2488
+ const result = this.resolveLiteralInternal(resolved, reExport.importedName, visited);
2489
+ if (result !== void 0)
2490
+ return result;
2491
+ }
2492
+ }
2493
+ for (const starSrc of index.exportsStar) {
2494
+ const resolved = this.resolveImportPath(filePath, starSrc);
2495
+ if (!resolved)
2496
+ continue;
2497
+ const result = this.resolveLiteralInternal(resolved, name, visited);
2498
+ if (result !== void 0)
2499
+ return result;
2500
+ }
2437
2501
  return void 0;
2438
2502
  }
2439
2503
  /**
@@ -12756,6 +12820,58 @@ var ZodSchemaConverter = class {
12756
12820
  this.symbolResolver.primeAST(this.currentFilePath, this.currentAST);
12757
12821
  return this.symbolResolver.resolveLiteral(this.currentFilePath, name);
12758
12822
  }
12823
+ /**
12824
+ * Unwrap a possible `TSAsExpression` / `TSSatisfiesExpression` to get the
12825
+ * underlying expression node. Returns the node itself when no wrapper is
12826
+ * present.
12827
+ */
12828
+ unwrapTypeAssertion(node) {
12829
+ if (!node)
12830
+ return void 0;
12831
+ if (t10.isTSAsExpression(node) || t10.isTSSatisfiesExpression(node)) {
12832
+ return node.expression;
12833
+ }
12834
+ return node;
12835
+ }
12836
+ /**
12837
+ * Resolve a numeric value from a call-expression argument.
12838
+ * Handles: numeric literals, identifier references to const numbers,
12839
+ * and `x as number` / `x satisfies number` wrappers around either.
12840
+ */
12841
+ resolveNumericArg(arg) {
12842
+ if (!arg)
12843
+ return void 0;
12844
+ const node = this.unwrapTypeAssertion(arg);
12845
+ if (t10.isNumericLiteral(node))
12846
+ return node.value;
12847
+ if (t10.isUnaryExpression(node) && node.operator === "-" && t10.isNumericLiteral(node.argument)) {
12848
+ return -node.argument.value;
12849
+ }
12850
+ if (t10.isIdentifier(node)) {
12851
+ const val = this.resolveLiteralValue(node.name);
12852
+ if (typeof val === "number")
12853
+ return val;
12854
+ }
12855
+ return void 0;
12856
+ }
12857
+ /**
12858
+ * Resolve a string value from a call-expression argument.
12859
+ * Handles: string literals, identifier references to const strings,
12860
+ * and `x as string` / `x satisfies string` wrappers around either.
12861
+ */
12862
+ resolveStringArg(arg) {
12863
+ if (!arg)
12864
+ return void 0;
12865
+ const node = this.unwrapTypeAssertion(arg);
12866
+ if (t10.isStringLiteral(node))
12867
+ return node.value;
12868
+ if (t10.isIdentifier(node)) {
12869
+ const val = this.resolveLiteralValue(node.name);
12870
+ if (typeof val === "string")
12871
+ return val;
12872
+ }
12873
+ return void 0;
12874
+ }
12759
12875
  /**
12760
12876
  * Resolve an identifier referring to a `z.object({...})` (or similar) call expression.
12761
12877
  * This lets callers inline the referenced object's shape.
@@ -12824,6 +12940,14 @@ var ZodSchemaConverter = class {
12824
12940
  if (t10.isNullLiteral(node)) {
12825
12941
  return null;
12826
12942
  }
12943
+ if (t10.isIdentifier(node)) {
12944
+ const val = this.resolveLiteralValue(node.name);
12945
+ if (val !== void 0)
12946
+ return val;
12947
+ }
12948
+ if (t10.isTSAsExpression(node) || t10.isTSSatisfiesExpression(node)) {
12949
+ return this.extractStaticJsonValue(node.expression);
12950
+ }
12827
12951
  if (t10.isArrayExpression(node)) {
12828
12952
  const values = [];
12829
12953
  for (const element of node.elements) {
@@ -12922,53 +13046,60 @@ var ZodSchemaConverter = class {
12922
13046
  schema.nullable = true;
12923
13047
  }
12924
13048
  break;
12925
- case "describe":
12926
- if (node.arguments.length > 0 && t10.isStringLiteral(node.arguments[0])) {
12927
- const description = node.arguments[0].value;
12928
- if (description.startsWith("@deprecated")) {
13049
+ case "describe": {
13050
+ const descVal = this.resolveStringArg(node.arguments[0]);
13051
+ if (descVal !== void 0) {
13052
+ if (descVal.startsWith("@deprecated")) {
12929
13053
  schema.deprecated = true;
12930
- schema.description = description.replace("@deprecated", "").trim();
13054
+ schema.description = descVal.replace("@deprecated", "").trim();
12931
13055
  } else {
12932
- schema.description = description;
13056
+ schema.description = descVal;
12933
13057
  }
12934
13058
  }
12935
13059
  break;
13060
+ }
12936
13061
  case "deprecated":
12937
13062
  schema.deprecated = true;
12938
13063
  break;
12939
- case "min":
12940
- if (node.arguments.length > 0 && t10.isNumericLiteral(node.arguments[0])) {
13064
+ case "min": {
13065
+ const minVal = this.resolveNumericArg(node.arguments[0]);
13066
+ if (minVal !== void 0) {
12941
13067
  if (schema.type === "string") {
12942
- schema.minLength = node.arguments[0].value;
13068
+ schema.minLength = minVal;
12943
13069
  } else if (schema.type === "number" || schema.type === "integer") {
12944
- schema.minimum = node.arguments[0].value;
13070
+ schema.minimum = minVal;
12945
13071
  } else if (schema.type === "array") {
12946
- schema.minItems = node.arguments[0].value;
13072
+ schema.minItems = minVal;
12947
13073
  }
12948
13074
  }
12949
13075
  break;
12950
- case "max":
12951
- if (node.arguments.length > 0 && t10.isNumericLiteral(node.arguments[0])) {
13076
+ }
13077
+ case "max": {
13078
+ const maxVal = this.resolveNumericArg(node.arguments[0]);
13079
+ if (maxVal !== void 0) {
12952
13080
  if (schema.type === "string") {
12953
- schema.maxLength = node.arguments[0].value;
13081
+ schema.maxLength = maxVal;
12954
13082
  } else if (schema.type === "number" || schema.type === "integer") {
12955
- schema.maximum = node.arguments[0].value;
13083
+ schema.maximum = maxVal;
12956
13084
  } else if (schema.type === "array") {
12957
- schema.maxItems = node.arguments[0].value;
13085
+ schema.maxItems = maxVal;
12958
13086
  }
12959
13087
  }
12960
13088
  break;
12961
- case "length":
12962
- if (node.arguments.length > 0 && t10.isNumericLiteral(node.arguments[0])) {
13089
+ }
13090
+ case "length": {
13091
+ const lenVal = this.resolveNumericArg(node.arguments[0]);
13092
+ if (lenVal !== void 0) {
12963
13093
  if (schema.type === "string") {
12964
- schema.minLength = node.arguments[0].value;
12965
- schema.maxLength = node.arguments[0].value;
13094
+ schema.minLength = lenVal;
13095
+ schema.maxLength = lenVal;
12966
13096
  } else if (schema.type === "array") {
12967
- schema.minItems = node.arguments[0].value;
12968
- schema.maxItems = node.arguments[0].value;
13097
+ schema.minItems = lenVal;
13098
+ schema.maxItems = lenVal;
12969
13099
  }
12970
13100
  }
12971
13101
  break;
13102
+ }
12972
13103
  case "nonempty":
12973
13104
  if (schema.type === "array") {
12974
13105
  schema.minItems = Math.max(schema.minItems ?? 0, 1);
@@ -13044,21 +13175,27 @@ var ZodSchemaConverter = class {
13044
13175
  schema.pattern = node.arguments[0].pattern;
13045
13176
  }
13046
13177
  break;
13047
- case "startsWith":
13048
- if (node.arguments.length > 0 && t10.isStringLiteral(node.arguments[0])) {
13049
- schema.pattern = `^${this.escapeRegExp(node.arguments[0].value)}`;
13178
+ case "startsWith": {
13179
+ const swVal = this.resolveStringArg(node.arguments[0]);
13180
+ if (swVal !== void 0) {
13181
+ schema.pattern = `^${this.escapeRegExp(swVal)}`;
13050
13182
  }
13051
13183
  break;
13052
- case "endsWith":
13053
- if (node.arguments.length > 0 && t10.isStringLiteral(node.arguments[0])) {
13054
- schema.pattern = `${this.escapeRegExp(node.arguments[0].value)}$`;
13184
+ }
13185
+ case "endsWith": {
13186
+ const ewVal = this.resolveStringArg(node.arguments[0]);
13187
+ if (ewVal !== void 0) {
13188
+ schema.pattern = `${this.escapeRegExp(ewVal)}$`;
13055
13189
  }
13056
13190
  break;
13057
- case "includes":
13058
- if (node.arguments.length > 0 && t10.isStringLiteral(node.arguments[0])) {
13059
- schema.pattern = this.escapeRegExp(node.arguments[0].value);
13191
+ }
13192
+ case "includes": {
13193
+ const incVal = this.resolveStringArg(node.arguments[0]);
13194
+ if (incVal !== void 0) {
13195
+ schema.pattern = this.escapeRegExp(incVal);
13060
13196
  }
13061
13197
  break;
13198
+ }
13062
13199
  case "int":
13063
13200
  schema.type = "integer";
13064
13201
  break;
@@ -13082,17 +13219,22 @@ var ZodSchemaConverter = class {
13082
13219
  break;
13083
13220
  case "default":
13084
13221
  if (node.arguments.length > 0) {
13085
- if (t10.isStringLiteral(node.arguments[0])) {
13086
- schema.default = node.arguments[0].value;
13087
- } else if (t10.isNumericLiteral(node.arguments[0])) {
13088
- schema.default = node.arguments[0].value;
13089
- } else if (t10.isBooleanLiteral(node.arguments[0])) {
13090
- schema.default = node.arguments[0].value;
13091
- } else if (t10.isNullLiteral(node.arguments[0])) {
13222
+ const defaultArg = this.unwrapTypeAssertion(node.arguments[0]);
13223
+ if (t10.isStringLiteral(defaultArg)) {
13224
+ schema.default = defaultArg.value;
13225
+ } else if (t10.isNumericLiteral(defaultArg)) {
13226
+ schema.default = defaultArg.value;
13227
+ } else if (t10.isBooleanLiteral(defaultArg)) {
13228
+ schema.default = defaultArg.value;
13229
+ } else if (t10.isNullLiteral(defaultArg)) {
13092
13230
  schema.default = null;
13093
- } else if (t10.isObjectExpression(node.arguments[0])) {
13231
+ } else if (t10.isIdentifier(defaultArg)) {
13232
+ const val = this.resolveLiteralValue(defaultArg.name);
13233
+ if (val !== void 0)
13234
+ schema.default = val;
13235
+ } else if (t10.isObjectExpression(defaultArg)) {
13094
13236
  const defaultObj = {};
13095
- node.arguments[0].properties.forEach((prop) => {
13237
+ defaultArg.properties.forEach((prop) => {
13096
13238
  if (t10.isObjectProperty(prop) && (t10.isIdentifier(prop.key) || t10.isStringLiteral(prop.key)) && (t10.isStringLiteral(prop.value) || t10.isNumericLiteral(prop.value) || t10.isBooleanLiteral(prop.value))) {
13097
13239
  const key = t10.isIdentifier(prop.key) ? prop.key.name : prop.key.value;
13098
13240
  const value = t10.isStringLiteral(prop.value) ? prop.value.value : t10.isNumericLiteral(prop.value) ? prop.value.value : t10.isBooleanLiteral(prop.value) ? prop.value.value : null;
@@ -16482,7 +16624,7 @@ var OperationProcessor = class {
16482
16624
  this.applyResponseHeaders(definition, responseHeaders);
16483
16625
  this.applyResponseLinks(definition, responseLinks);
16484
16626
  if (openapiOverride) {
16485
- Object.assign(definition, structuredClone(openapiOverride));
16627
+ deepMerge(definition, structuredClone(openapiOverride));
16486
16628
  }
16487
16629
  return {
16488
16630
  routePath,