next-openapi-gen 1.4.2 → 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/cli.js CHANGED
@@ -904,7 +904,6 @@ function parseJSDocBlock(commentValue, filePath) {
904
904
  result.summary = explicitSummary;
905
905
  }
906
906
  result.description = extractLineValue(normalizedComment, "@description");
907
- result.tag = extractLineValue(normalizedComment, "@tag");
908
907
  result.tagSummary = extractLineValue(normalizedComment, "@tagSummary");
909
908
  result.tagKind = extractLineValue(normalizedComment, "@tagKind");
910
909
  result.tagParent = extractLineValue(normalizedComment, "@tagParent");
@@ -938,17 +937,28 @@ function parseJSDocBlock(commentValue, filePath) {
938
937
  if (Array.isArray(responsePrefixEncoding)) {
939
938
  result.responsePrefixEncoding = responsePrefixEncoding;
940
939
  }
941
- const parsedResponse = parseResponseTag(normalizedComment);
942
- if (parsedResponse) {
943
- result.successCode = parsedResponse.successCode;
944
- result.responseType = parsedResponse.responseType;
945
- if (!result.responseDescription && parsedResponse.responseDescription) {
946
- result.responseDescription = parsedResponse.responseDescription;
940
+ const responseMatches = [...normalizedComment.matchAll(/@response\s+([^\n\r@]+)/g)];
941
+ if (responseMatches.length > 0) {
942
+ const firstRaw = responseMatches[0]?.[1]?.trim();
943
+ if (firstRaw) {
944
+ const parsedResponse = parseResponseRawValue(firstRaw);
945
+ result.successCode = parsedResponse.successCode;
946
+ result.responseType = parsedResponse.responseType;
947
+ if (!result.responseDescription && parsedResponse.responseDescription) {
948
+ result.responseDescription = parsedResponse.responseDescription;
949
+ }
950
+ }
951
+ const extraResponses = responseMatches.slice(1).map((m) => m[1]?.trim()).filter((t17) => Boolean(t17));
952
+ if (extraResponses.length > 0) {
953
+ result.addResponses = extraResponses.join(",");
947
954
  }
948
955
  }
949
956
  const addMatches = [...normalizedComment.matchAll(/@add\s+([^\n\r@]*)/g)];
950
957
  if (addMatches.length > 0) {
951
- result.addResponses = addMatches.map((match) => match[1]?.trim() || "").filter(Boolean).join(",");
958
+ const addEntries = addMatches.map((match) => match[1]?.trim() || "").filter(Boolean).join(",");
959
+ if (addEntries) {
960
+ result.addResponses = result.addResponses ? `${result.addResponses},${addEntries}` : addEntries;
961
+ }
952
962
  }
953
963
  const examples = collectExampleDefinitions(normalizedComment, "@examples", filePath);
954
964
  result.requestExamples = buildExampleMap(examples.definitions, "request");
@@ -961,6 +971,17 @@ function parseJSDocBlock(commentValue, filePath) {
961
971
  if (additionalTags.length > 0) {
962
972
  result.tags = additionalTags;
963
973
  }
974
+ const tagMatches = [...normalizedComment.matchAll(/@tag\s+([^\n\r@]*)/g)];
975
+ if (tagMatches.length > 0) {
976
+ const primaryTag = tagMatches[0]?.[1]?.trim();
977
+ if (primaryTag) {
978
+ result.tag = primaryTag;
979
+ }
980
+ const extraTags = tagMatches.slice(1).map((m) => m[1]?.trim()).filter((t17) => Boolean(t17));
981
+ if (extraTags.length > 0) {
982
+ result.tags = [...result.tags ?? [], ...extraTags];
983
+ }
984
+ }
964
985
  const servers = parseServersTag(normalizedComment);
965
986
  if (servers.length > 0) {
966
987
  result.servers = servers;
@@ -1163,11 +1184,7 @@ function parseOpenApiOverrideTag(commentValue) {
1163
1184
  function extractTypeFromComment(commentValue, tag) {
1164
1185
  return commentValue.match(new RegExp(`^\\s*\\*?\\s*${tag}\\s+([\\w<>,\\s[\\]]+)`, "m"))?.[1]?.trim() || "";
1165
1186
  }
1166
- function parseResponseTag(commentValue) {
1167
- const rawValue = commentValue.match(/@response\s+([^\n\r@]+)/)?.[1]?.trim();
1168
- if (!rawValue) {
1169
- return null;
1170
- }
1187
+ function parseResponseRawValue(rawValue) {
1171
1188
  if (isStatusCodeToken(rawValue)) {
1172
1189
  return {
1173
1190
  responseDescription: "",
@@ -1616,6 +1633,18 @@ function getOperationId(routePath, method) {
1616
1633
  const operation = routePath.replaceAll(/\//g, "-").replace(/^-/, "");
1617
1634
  return `${method}-${operation}`;
1618
1635
  }
1636
+ function deepMerge(target, source) {
1637
+ for (const key of Object.keys(source)) {
1638
+ const sourceVal = source[key];
1639
+ const targetVal = target[key];
1640
+ if (sourceVal !== null && typeof sourceVal === "object" && !Array.isArray(sourceVal) && targetVal !== null && typeof targetVal === "object" && !Array.isArray(targetVal)) {
1641
+ deepMerge(targetVal, sourceVal);
1642
+ } else {
1643
+ target[key] = sourceVal;
1644
+ }
1645
+ }
1646
+ return target;
1647
+ }
1619
1648
  var DEFAULT_PARSER_OPTIONS = {
1620
1649
  sourceType: "module",
1621
1650
  plugins: ["typescript", "jsx", "decorators-legacy"]
@@ -17046,7 +17075,7 @@ var OperationProcessor = class {
17046
17075
  this.applyResponseHeaders(definition, responseHeaders);
17047
17076
  this.applyResponseLinks(definition, responseLinks);
17048
17077
  if (openapiOverride) {
17049
- Object.assign(definition, structuredClone(openapiOverride));
17078
+ deepMerge(definition, structuredClone(openapiOverride));
17050
17079
  }
17051
17080
  return {
17052
17081
  routePath,
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"]
@@ -16595,7 +16624,7 @@ var OperationProcessor = class {
16595
16624
  this.applyResponseHeaders(definition, responseHeaders);
16596
16625
  this.applyResponseLinks(definition, responseLinks);
16597
16626
  if (openapiOverride) {
16598
- Object.assign(definition, structuredClone(openapiOverride));
16627
+ deepMerge(definition, structuredClone(openapiOverride));
16599
16628
  }
16600
16629
  return {
16601
16630
  routePath,
@@ -923,7 +923,6 @@ function parseJSDocBlock(commentValue, filePath) {
923
923
  result.summary = explicitSummary;
924
924
  }
925
925
  result.description = extractLineValue(normalizedComment, "@description");
926
- result.tag = extractLineValue(normalizedComment, "@tag");
927
926
  result.tagSummary = extractLineValue(normalizedComment, "@tagSummary");
928
927
  result.tagKind = extractLineValue(normalizedComment, "@tagKind");
929
928
  result.tagParent = extractLineValue(normalizedComment, "@tagParent");
@@ -957,17 +956,28 @@ function parseJSDocBlock(commentValue, filePath) {
957
956
  if (Array.isArray(responsePrefixEncoding)) {
958
957
  result.responsePrefixEncoding = responsePrefixEncoding;
959
958
  }
960
- const parsedResponse = parseResponseTag(normalizedComment);
961
- if (parsedResponse) {
962
- result.successCode = parsedResponse.successCode;
963
- result.responseType = parsedResponse.responseType;
964
- if (!result.responseDescription && parsedResponse.responseDescription) {
965
- result.responseDescription = parsedResponse.responseDescription;
959
+ const responseMatches = [...normalizedComment.matchAll(/@response\s+([^\n\r@]+)/g)];
960
+ if (responseMatches.length > 0) {
961
+ const firstRaw = responseMatches[0]?.[1]?.trim();
962
+ if (firstRaw) {
963
+ const parsedResponse = parseResponseRawValue(firstRaw);
964
+ result.successCode = parsedResponse.successCode;
965
+ result.responseType = parsedResponse.responseType;
966
+ if (!result.responseDescription && parsedResponse.responseDescription) {
967
+ result.responseDescription = parsedResponse.responseDescription;
968
+ }
969
+ }
970
+ const extraResponses = responseMatches.slice(1).map((m) => m[1]?.trim()).filter((t17) => Boolean(t17));
971
+ if (extraResponses.length > 0) {
972
+ result.addResponses = extraResponses.join(",");
966
973
  }
967
974
  }
968
975
  const addMatches = [...normalizedComment.matchAll(/@add\s+([^\n\r@]*)/g)];
969
976
  if (addMatches.length > 0) {
970
- result.addResponses = addMatches.map((match) => match[1]?.trim() || "").filter(Boolean).join(",");
977
+ const addEntries = addMatches.map((match) => match[1]?.trim() || "").filter(Boolean).join(",");
978
+ if (addEntries) {
979
+ result.addResponses = result.addResponses ? `${result.addResponses},${addEntries}` : addEntries;
980
+ }
971
981
  }
972
982
  const examples = collectExampleDefinitions(normalizedComment, "@examples", filePath);
973
983
  result.requestExamples = buildExampleMap(examples.definitions, "request");
@@ -980,6 +990,17 @@ function parseJSDocBlock(commentValue, filePath) {
980
990
  if (additionalTags.length > 0) {
981
991
  result.tags = additionalTags;
982
992
  }
993
+ const tagMatches = [...normalizedComment.matchAll(/@tag\s+([^\n\r@]*)/g)];
994
+ if (tagMatches.length > 0) {
995
+ const primaryTag = tagMatches[0]?.[1]?.trim();
996
+ if (primaryTag) {
997
+ result.tag = primaryTag;
998
+ }
999
+ const extraTags = tagMatches.slice(1).map((m) => m[1]?.trim()).filter((t17) => Boolean(t17));
1000
+ if (extraTags.length > 0) {
1001
+ result.tags = [...result.tags ?? [], ...extraTags];
1002
+ }
1003
+ }
983
1004
  const servers = parseServersTag(normalizedComment);
984
1005
  if (servers.length > 0) {
985
1006
  result.servers = servers;
@@ -1182,11 +1203,7 @@ function parseOpenApiOverrideTag(commentValue) {
1182
1203
  function extractTypeFromComment(commentValue, tag) {
1183
1204
  return commentValue.match(new RegExp(`^\\s*\\*?\\s*${tag}\\s+([\\w<>,\\s[\\]]+)`, "m"))?.[1]?.trim() || "";
1184
1205
  }
1185
- function parseResponseTag(commentValue) {
1186
- const rawValue = commentValue.match(/@response\s+([^\n\r@]+)/)?.[1]?.trim();
1187
- if (!rawValue) {
1188
- return null;
1189
- }
1206
+ function parseResponseRawValue(rawValue) {
1190
1207
  if (isStatusCodeToken(rawValue)) {
1191
1208
  return {
1192
1209
  responseDescription: "",
@@ -1635,6 +1652,18 @@ function getOperationId(routePath, method) {
1635
1652
  const operation = routePath.replaceAll(/\//g, "-").replace(/^-/, "");
1636
1653
  return `${method}-${operation}`;
1637
1654
  }
1655
+ function deepMerge(target, source) {
1656
+ for (const key of Object.keys(source)) {
1657
+ const sourceVal = source[key];
1658
+ const targetVal = target[key];
1659
+ if (sourceVal !== null && typeof sourceVal === "object" && !Array.isArray(sourceVal) && targetVal !== null && typeof targetVal === "object" && !Array.isArray(targetVal)) {
1660
+ deepMerge(targetVal, sourceVal);
1661
+ } else {
1662
+ target[key] = sourceVal;
1663
+ }
1664
+ }
1665
+ return target;
1666
+ }
1638
1667
  var DEFAULT_PARSER_OPTIONS = {
1639
1668
  sourceType: "module",
1640
1669
  plugins: ["typescript", "jsx", "decorators-legacy"]
@@ -17633,7 +17662,7 @@ var OperationProcessor = class {
17633
17662
  this.applyResponseHeaders(definition, responseHeaders);
17634
17663
  this.applyResponseLinks(definition, responseLinks);
17635
17664
  if (openapiOverride) {
17636
- Object.assign(definition, structuredClone(openapiOverride));
17665
+ deepMerge(definition, structuredClone(openapiOverride));
17637
17666
  }
17638
17667
  return {
17639
17668
  routePath,
@@ -369,7 +369,6 @@ function parseJSDocBlock(commentValue, filePath) {
369
369
  result.summary = explicitSummary;
370
370
  }
371
371
  result.description = extractLineValue(normalizedComment, "@description");
372
- result.tag = extractLineValue(normalizedComment, "@tag");
373
372
  result.tagSummary = extractLineValue(normalizedComment, "@tagSummary");
374
373
  result.tagKind = extractLineValue(normalizedComment, "@tagKind");
375
374
  result.tagParent = extractLineValue(normalizedComment, "@tagParent");
@@ -403,17 +402,28 @@ function parseJSDocBlock(commentValue, filePath) {
403
402
  if (Array.isArray(responsePrefixEncoding)) {
404
403
  result.responsePrefixEncoding = responsePrefixEncoding;
405
404
  }
406
- const parsedResponse = parseResponseTag(normalizedComment);
407
- if (parsedResponse) {
408
- result.successCode = parsedResponse.successCode;
409
- result.responseType = parsedResponse.responseType;
410
- if (!result.responseDescription && parsedResponse.responseDescription) {
411
- result.responseDescription = parsedResponse.responseDescription;
405
+ const responseMatches = [...normalizedComment.matchAll(/@response\s+([^\n\r@]+)/g)];
406
+ if (responseMatches.length > 0) {
407
+ const firstRaw = responseMatches[0]?.[1]?.trim();
408
+ if (firstRaw) {
409
+ const parsedResponse = parseResponseRawValue(firstRaw);
410
+ result.successCode = parsedResponse.successCode;
411
+ result.responseType = parsedResponse.responseType;
412
+ if (!result.responseDescription && parsedResponse.responseDescription) {
413
+ result.responseDescription = parsedResponse.responseDescription;
414
+ }
415
+ }
416
+ const extraResponses = responseMatches.slice(1).map((m) => m[1]?.trim()).filter((t16) => Boolean(t16));
417
+ if (extraResponses.length > 0) {
418
+ result.addResponses = extraResponses.join(",");
412
419
  }
413
420
  }
414
421
  const addMatches = [...normalizedComment.matchAll(/@add\s+([^\n\r@]*)/g)];
415
422
  if (addMatches.length > 0) {
416
- result.addResponses = addMatches.map((match) => match[1]?.trim() || "").filter(Boolean).join(",");
423
+ const addEntries = addMatches.map((match) => match[1]?.trim() || "").filter(Boolean).join(",");
424
+ if (addEntries) {
425
+ result.addResponses = result.addResponses ? `${result.addResponses},${addEntries}` : addEntries;
426
+ }
417
427
  }
418
428
  const examples = collectExampleDefinitions(normalizedComment, "@examples", filePath);
419
429
  result.requestExamples = buildExampleMap(examples.definitions, "request");
@@ -426,6 +436,17 @@ function parseJSDocBlock(commentValue, filePath) {
426
436
  if (additionalTags.length > 0) {
427
437
  result.tags = additionalTags;
428
438
  }
439
+ const tagMatches = [...normalizedComment.matchAll(/@tag\s+([^\n\r@]*)/g)];
440
+ if (tagMatches.length > 0) {
441
+ const primaryTag = tagMatches[0]?.[1]?.trim();
442
+ if (primaryTag) {
443
+ result.tag = primaryTag;
444
+ }
445
+ const extraTags = tagMatches.slice(1).map((m) => m[1]?.trim()).filter((t16) => Boolean(t16));
446
+ if (extraTags.length > 0) {
447
+ result.tags = [...result.tags ?? [], ...extraTags];
448
+ }
449
+ }
429
450
  const servers = parseServersTag(normalizedComment);
430
451
  if (servers.length > 0) {
431
452
  result.servers = servers;
@@ -628,11 +649,7 @@ function parseOpenApiOverrideTag(commentValue) {
628
649
  function extractTypeFromComment(commentValue, tag) {
629
650
  return commentValue.match(new RegExp(`^\\s*\\*?\\s*${tag}\\s+([\\w<>,\\s[\\]]+)`, "m"))?.[1]?.trim() || "";
630
651
  }
631
- function parseResponseTag(commentValue) {
632
- const rawValue = commentValue.match(/@response\s+([^\n\r@]+)/)?.[1]?.trim();
633
- if (!rawValue) {
634
- return null;
635
- }
652
+ function parseResponseRawValue(rawValue) {
636
653
  if (isStatusCodeToken(rawValue)) {
637
654
  return {
638
655
  responseDescription: "",
@@ -1081,6 +1098,18 @@ function getOperationId(routePath, method) {
1081
1098
  const operation = routePath.replaceAll(/\//g, "-").replace(/^-/, "");
1082
1099
  return `${method}-${operation}`;
1083
1100
  }
1101
+ function deepMerge(target, source) {
1102
+ for (const key of Object.keys(source)) {
1103
+ const sourceVal = source[key];
1104
+ const targetVal = target[key];
1105
+ if (sourceVal !== null && typeof sourceVal === "object" && !Array.isArray(sourceVal) && targetVal !== null && typeof targetVal === "object" && !Array.isArray(targetVal)) {
1106
+ deepMerge(targetVal, sourceVal);
1107
+ } else {
1108
+ target[key] = sourceVal;
1109
+ }
1110
+ }
1111
+ return target;
1112
+ }
1084
1113
  var DEFAULT_PARSER_OPTIONS = {
1085
1114
  sourceType: "module",
1086
1115
  plugins: ["typescript", "jsx", "decorators-legacy"]
@@ -16633,7 +16662,7 @@ var OperationProcessor = class {
16633
16662
  this.applyResponseHeaders(definition, responseHeaders);
16634
16663
  this.applyResponseLinks(definition, responseLinks);
16635
16664
  if (openapiOverride) {
16636
- Object.assign(definition, structuredClone(openapiOverride));
16665
+ deepMerge(definition, structuredClone(openapiOverride));
16637
16666
  }
16638
16667
  return {
16639
16668
  routePath,
@@ -369,7 +369,6 @@ function parseJSDocBlock(commentValue, filePath) {
369
369
  result.summary = explicitSummary;
370
370
  }
371
371
  result.description = extractLineValue(normalizedComment, "@description");
372
- result.tag = extractLineValue(normalizedComment, "@tag");
373
372
  result.tagSummary = extractLineValue(normalizedComment, "@tagSummary");
374
373
  result.tagKind = extractLineValue(normalizedComment, "@tagKind");
375
374
  result.tagParent = extractLineValue(normalizedComment, "@tagParent");
@@ -403,17 +402,28 @@ function parseJSDocBlock(commentValue, filePath) {
403
402
  if (Array.isArray(responsePrefixEncoding)) {
404
403
  result.responsePrefixEncoding = responsePrefixEncoding;
405
404
  }
406
- const parsedResponse = parseResponseTag(normalizedComment);
407
- if (parsedResponse) {
408
- result.successCode = parsedResponse.successCode;
409
- result.responseType = parsedResponse.responseType;
410
- if (!result.responseDescription && parsedResponse.responseDescription) {
411
- result.responseDescription = parsedResponse.responseDescription;
405
+ const responseMatches = [...normalizedComment.matchAll(/@response\s+([^\n\r@]+)/g)];
406
+ if (responseMatches.length > 0) {
407
+ const firstRaw = responseMatches[0]?.[1]?.trim();
408
+ if (firstRaw) {
409
+ const parsedResponse = parseResponseRawValue(firstRaw);
410
+ result.successCode = parsedResponse.successCode;
411
+ result.responseType = parsedResponse.responseType;
412
+ if (!result.responseDescription && parsedResponse.responseDescription) {
413
+ result.responseDescription = parsedResponse.responseDescription;
414
+ }
415
+ }
416
+ const extraResponses = responseMatches.slice(1).map((m) => m[1]?.trim()).filter((t16) => Boolean(t16));
417
+ if (extraResponses.length > 0) {
418
+ result.addResponses = extraResponses.join(",");
412
419
  }
413
420
  }
414
421
  const addMatches = [...normalizedComment.matchAll(/@add\s+([^\n\r@]*)/g)];
415
422
  if (addMatches.length > 0) {
416
- result.addResponses = addMatches.map((match) => match[1]?.trim() || "").filter(Boolean).join(",");
423
+ const addEntries = addMatches.map((match) => match[1]?.trim() || "").filter(Boolean).join(",");
424
+ if (addEntries) {
425
+ result.addResponses = result.addResponses ? `${result.addResponses},${addEntries}` : addEntries;
426
+ }
417
427
  }
418
428
  const examples = collectExampleDefinitions(normalizedComment, "@examples", filePath);
419
429
  result.requestExamples = buildExampleMap(examples.definitions, "request");
@@ -426,6 +436,17 @@ function parseJSDocBlock(commentValue, filePath) {
426
436
  if (additionalTags.length > 0) {
427
437
  result.tags = additionalTags;
428
438
  }
439
+ const tagMatches = [...normalizedComment.matchAll(/@tag\s+([^\n\r@]*)/g)];
440
+ if (tagMatches.length > 0) {
441
+ const primaryTag = tagMatches[0]?.[1]?.trim();
442
+ if (primaryTag) {
443
+ result.tag = primaryTag;
444
+ }
445
+ const extraTags = tagMatches.slice(1).map((m) => m[1]?.trim()).filter((t16) => Boolean(t16));
446
+ if (extraTags.length > 0) {
447
+ result.tags = [...result.tags ?? [], ...extraTags];
448
+ }
449
+ }
429
450
  const servers = parseServersTag(normalizedComment);
430
451
  if (servers.length > 0) {
431
452
  result.servers = servers;
@@ -628,11 +649,7 @@ function parseOpenApiOverrideTag(commentValue) {
628
649
  function extractTypeFromComment(commentValue, tag) {
629
650
  return commentValue.match(new RegExp(`^\\s*\\*?\\s*${tag}\\s+([\\w<>,\\s[\\]]+)`, "m"))?.[1]?.trim() || "";
630
651
  }
631
- function parseResponseTag(commentValue) {
632
- const rawValue = commentValue.match(/@response\s+([^\n\r@]+)/)?.[1]?.trim();
633
- if (!rawValue) {
634
- return null;
635
- }
652
+ function parseResponseRawValue(rawValue) {
636
653
  if (isStatusCodeToken(rawValue)) {
637
654
  return {
638
655
  responseDescription: "",
@@ -1081,6 +1098,18 @@ function getOperationId(routePath, method) {
1081
1098
  const operation = routePath.replaceAll(/\//g, "-").replace(/^-/, "");
1082
1099
  return `${method}-${operation}`;
1083
1100
  }
1101
+ function deepMerge(target, source) {
1102
+ for (const key of Object.keys(source)) {
1103
+ const sourceVal = source[key];
1104
+ const targetVal = target[key];
1105
+ if (sourceVal !== null && typeof sourceVal === "object" && !Array.isArray(sourceVal) && targetVal !== null && typeof targetVal === "object" && !Array.isArray(targetVal)) {
1106
+ deepMerge(targetVal, sourceVal);
1107
+ } else {
1108
+ target[key] = sourceVal;
1109
+ }
1110
+ }
1111
+ return target;
1112
+ }
1084
1113
  var DEFAULT_PARSER_OPTIONS = {
1085
1114
  sourceType: "module",
1086
1115
  plugins: ["typescript", "jsx", "decorators-legacy"]
@@ -16633,7 +16662,7 @@ var OperationProcessor = class {
16633
16662
  this.applyResponseHeaders(definition, responseHeaders);
16634
16663
  this.applyResponseLinks(definition, responseLinks);
16635
16664
  if (openapiOverride) {
16636
- Object.assign(definition, structuredClone(openapiOverride));
16665
+ deepMerge(definition, structuredClone(openapiOverride));
16637
16666
  }
16638
16667
  return {
16639
16668
  routePath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-openapi-gen",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
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",