@sdk-it/spec 0.45.0 → 0.46.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/README.md +65 -0
  2. package/dist/index.d.ts +3 -3
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +3 -3
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/find-polymorphic-varients.d.ts.map +1 -1
  7. package/dist/lib/find-polymorphic-varients.js +6 -11
  8. package/dist/lib/find-polymorphic-varients.js.map +2 -2
  9. package/dist/lib/for-each-operation.d.ts +11 -3
  10. package/dist/lib/for-each-operation.d.ts.map +1 -1
  11. package/dist/lib/for-each-operation.js +23 -15
  12. package/dist/lib/for-each-operation.js.map +2 -2
  13. package/dist/lib/format-name.d.ts.map +1 -1
  14. package/dist/lib/format-name.js +0 -1
  15. package/dist/lib/format-name.js.map +2 -2
  16. package/dist/lib/ir.d.ts +2 -2
  17. package/dist/lib/ir.d.ts.map +1 -1
  18. package/dist/lib/ir.js +6 -120
  19. package/dist/lib/ir.js.map +2 -2
  20. package/dist/lib/is-primitive-schema.js +1 -1
  21. package/dist/lib/is-primitive-schema.js.map +1 -1
  22. package/dist/lib/is.d.ts +2 -0
  23. package/dist/lib/is.d.ts.map +1 -1
  24. package/dist/lib/is.js +6 -3
  25. package/dist/lib/is.js.map +2 -2
  26. package/dist/lib/loaders/postman/postman-converter.d.ts.map +1 -1
  27. package/dist/lib/loaders/postman/postman-converter.js +1 -11
  28. package/dist/lib/loaders/postman/postman-converter.js.map +2 -2
  29. package/dist/lib/options.d.ts +7 -45
  30. package/dist/lib/options.d.ts.map +1 -1
  31. package/dist/lib/options.js +26 -28
  32. package/dist/lib/options.js.map +2 -2
  33. package/dist/lib/overview-docs/overview-pagination.d.ts +1 -1
  34. package/dist/lib/overview-docs/overview-pagination.d.ts.map +1 -1
  35. package/dist/lib/overview-docs/overview-pagination.js +1 -1
  36. package/dist/lib/overview-docs/overview-pagination.js.map +2 -2
  37. package/dist/lib/pagination/guess-pagination.d.ts.map +1 -1
  38. package/dist/lib/pagination/guess-pagination.js +1 -1
  39. package/dist/lib/pagination/guess-pagination.js.map +2 -2
  40. package/dist/lib/pagination/pagination-result.d.ts.map +1 -1
  41. package/dist/lib/pagination/pagination-result.js +15 -5
  42. package/dist/lib/pagination/pagination-result.js.map +2 -2
  43. package/dist/lib/pagination/pagination.d.ts.map +1 -1
  44. package/dist/lib/pagination/pagination.js +7 -6
  45. package/dist/lib/pagination/pagination.js.map +2 -2
  46. package/dist/lib/processing-plugins/canonicalize-spec.d.ts +3 -0
  47. package/dist/lib/processing-plugins/canonicalize-spec.d.ts.map +1 -0
  48. package/dist/lib/processing-plugins/canonicalize-spec.js +29 -0
  49. package/dist/lib/processing-plugins/canonicalize-spec.js.map +7 -0
  50. package/dist/lib/processing-plugins/create-default-processing-plugins.d.ts +5 -0
  51. package/dist/lib/processing-plugins/create-default-processing-plugins.d.ts.map +1 -0
  52. package/dist/lib/processing-plugins/create-default-processing-plugins.js +30 -0
  53. package/dist/lib/processing-plugins/create-default-processing-plugins.js.map +7 -0
  54. package/dist/lib/processing-plugins/enrich-examples.d.ts +25 -0
  55. package/dist/lib/processing-plugins/enrich-examples.d.ts.map +1 -0
  56. package/dist/lib/processing-plugins/enrich-examples.js +93 -0
  57. package/dist/lib/processing-plugins/enrich-examples.js.map +7 -0
  58. package/dist/lib/processing-plugins/extract-inline-schemas.d.ts +3 -0
  59. package/dist/lib/processing-plugins/extract-inline-schemas.d.ts.map +1 -0
  60. package/dist/lib/processing-plugins/extract-inline-schemas.js +165 -0
  61. package/dist/lib/processing-plugins/extract-inline-schemas.js.map +7 -0
  62. package/dist/lib/processing-plugins/extract-overview-docs.d.ts +3 -0
  63. package/dist/lib/processing-plugins/extract-overview-docs.d.ts.map +1 -0
  64. package/dist/lib/processing-plugins/extract-overview-docs.js +13 -0
  65. package/dist/lib/processing-plugins/extract-overview-docs.js.map +7 -0
  66. package/dist/lib/processing-plugins/index.d.ts +14 -0
  67. package/dist/lib/processing-plugins/index.d.ts.map +1 -0
  68. package/dist/lib/processing-plugins/index.js +14 -0
  69. package/dist/lib/processing-plugins/index.js.map +7 -0
  70. package/dist/lib/processing-plugins/infer-pagination.d.ts +3 -0
  71. package/dist/lib/processing-plugins/infer-pagination.d.ts.map +1 -0
  72. package/dist/lib/processing-plugins/infer-pagination.js +21 -0
  73. package/dist/lib/processing-plugins/infer-pagination.js.map +7 -0
  74. package/dist/lib/processing-plugins/normalize-operation-ids.d.ts +3 -0
  75. package/dist/lib/processing-plugins/normalize-operation-ids.d.ts.map +1 -0
  76. package/dist/lib/processing-plugins/normalize-operation-ids.js +74 -0
  77. package/dist/lib/processing-plugins/normalize-operation-ids.js.map +7 -0
  78. package/dist/lib/processing-plugins/normalize-parameters.d.ts +3 -0
  79. package/dist/lib/processing-plugins/normalize-parameters.d.ts.map +1 -0
  80. package/dist/lib/processing-plugins/normalize-parameters.js +29 -0
  81. package/dist/lib/processing-plugins/normalize-parameters.js.map +7 -0
  82. package/dist/lib/processing-plugins/normalize-paths.d.ts +3 -0
  83. package/dist/lib/processing-plugins/normalize-paths.d.ts.map +1 -0
  84. package/dist/lib/processing-plugins/normalize-paths.js +67 -0
  85. package/dist/lib/processing-plugins/normalize-paths.js.map +7 -0
  86. package/dist/lib/processing-plugins/normalize-request-bodies.d.ts +6 -0
  87. package/dist/lib/processing-plugins/normalize-request-bodies.d.ts.map +1 -0
  88. package/dist/lib/processing-plugins/normalize-request-bodies.js +139 -0
  89. package/dist/lib/processing-plugins/normalize-request-bodies.js.map +7 -0
  90. package/dist/lib/processing-plugins/normalize-responses.d.ts +3 -0
  91. package/dist/lib/processing-plugins/normalize-responses.d.ts.map +1 -0
  92. package/dist/lib/{tune-response.js → processing-plugins/normalize-responses.js} +55 -25
  93. package/dist/lib/processing-plugins/normalize-responses.js.map +7 -0
  94. package/dist/lib/processing-plugins/normalize-schemas.d.ts +3 -0
  95. package/dist/lib/processing-plugins/normalize-schemas.d.ts.map +1 -0
  96. package/dist/lib/processing-plugins/normalize-schemas.js +170 -0
  97. package/dist/lib/processing-plugins/normalize-schemas.js.map +7 -0
  98. package/dist/lib/processing-plugins/normalize-tags.d.ts +3 -0
  99. package/dist/lib/processing-plugins/normalize-tags.d.ts.map +1 -0
  100. package/dist/lib/processing-plugins/normalize-tags.js +18 -0
  101. package/dist/lib/processing-plugins/normalize-tags.js.map +7 -0
  102. package/dist/lib/processing.d.ts +33 -0
  103. package/dist/lib/processing.d.ts.map +1 -0
  104. package/dist/lib/processing.js +41 -0
  105. package/dist/lib/processing.js.map +7 -0
  106. package/dist/lib/reserved-keywords.d.ts.map +1 -1
  107. package/dist/lib/reserved-keywords.js +18 -1
  108. package/dist/lib/reserved-keywords.js.map +2 -2
  109. package/dist/lib/tag.js +2 -2
  110. package/dist/lib/tag.js.map +2 -2
  111. package/dist/lib/types.d.ts +4 -1
  112. package/dist/lib/types.d.ts.map +1 -1
  113. package/dist/lib/walk-schemas.d.ts +8 -0
  114. package/dist/lib/walk-schemas.d.ts.map +1 -0
  115. package/dist/lib/walk-schemas.js +51 -0
  116. package/dist/lib/walk-schemas.js.map +7 -0
  117. package/package.json +2 -2
  118. package/dist/lib/tune-request-body.d.ts +0 -5
  119. package/dist/lib/tune-request-body.d.ts.map +0 -1
  120. package/dist/lib/tune-request-body.js +0 -91
  121. package/dist/lib/tune-request-body.js.map +0 -7
  122. package/dist/lib/tune-response.d.ts +0 -5
  123. package/dist/lib/tune-response.d.ts.map +0 -1
  124. package/dist/lib/tune-response.js.map +0 -7
  125. package/dist/lib/tune.d.ts +0 -11
  126. package/dist/lib/tune.d.ts.map +0 -1
  127. package/dist/lib/tune.js +0 -291
  128. package/dist/lib/tune.js.map +0 -7
@@ -22,6 +22,12 @@ const PRIMARY_OTHER_KEYWORDS = [
22
22
  "events"
23
23
  ];
24
24
  const SECONDARY_KEYWORDS = ["entries", "rows", "elements"];
25
+ function lastWord(propName) {
26
+ return propName.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean).at(-1) ?? "";
27
+ }
28
+ function hasKeyword(propName, keywords) {
29
+ return keywords.includes(lastWord(propName));
30
+ }
25
31
  const PLURAL_DEPRIORITIZE_LIST = [
26
32
  "status",
27
33
  "success",
@@ -46,6 +52,7 @@ const PLURAL_DEPRIORITIZE_LIST = [
46
52
  "actions",
47
53
  "attributes",
48
54
  "categories",
55
+ "configurations",
49
56
  "features",
50
57
  "includes",
51
58
  "tags"
@@ -131,23 +138,26 @@ function getItemsName(properties) {
131
138
  };
132
139
  for (const propName of arrayPropertyNames) {
133
140
  const lowerPropName = propName.toLowerCase();
134
- if (PRIMARY_TOP_TIER_KEYWORDS.includes(lowerPropName)) {
141
+ const finalWord = lastWord(propName);
142
+ const isDeprioritized = PLURAL_DEPRIORITIZE_LIST.includes(lowerPropName);
143
+ const isCompoundMetadata = finalWord !== lowerPropName && PLURAL_DEPRIORITIZE_LIST.includes(finalWord);
144
+ if (hasKeyword(propName, PRIMARY_TOP_TIER_KEYWORDS)) {
135
145
  updateCandidate(propName, 2);
136
146
  continue;
137
147
  }
138
- if (candidateRank > 3 && PRIMARY_OTHER_KEYWORDS.includes(lowerPropName)) {
148
+ if (candidateRank > 3 && hasKeyword(propName, PRIMARY_OTHER_KEYWORDS)) {
139
149
  updateCandidate(propName, 3);
140
150
  continue;
141
151
  }
142
- if (candidateRank > 4 && SECONDARY_KEYWORDS.includes(lowerPropName)) {
152
+ if (candidateRank > 4 && hasKeyword(propName, SECONDARY_KEYWORDS)) {
143
153
  updateCandidate(propName, 4);
144
154
  continue;
145
155
  }
146
- if (candidateRank > 5 && pluralize.isPlural(propName) && !PLURAL_DEPRIORITIZE_LIST.includes(lowerPropName)) {
156
+ if (candidateRank > 5 && pluralize.isPlural(propName) && !isDeprioritized && !isCompoundMetadata) {
147
157
  updateCandidate(propName, 5);
148
158
  continue;
149
159
  }
150
- if (candidateRank > 6 && pluralize.isPlural(propName) && PLURAL_DEPRIORITIZE_LIST.includes(lowerPropName)) {
160
+ if (candidateRank > 6 && pluralize.isPlural(propName) && isDeprioritized) {
151
161
  updateCandidate(propName, 6);
152
162
  continue;
153
163
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/pagination/pagination-result.ts"],
4
- "sourcesContent": ["import type { SchemaObject, SchemasObject } from 'openapi3-ts/oas31';\nimport pluralize from 'pluralize';\n\nconst PRIMARY_TOP_TIER_KEYWORDS: string[] = [\n 'data',\n 'items',\n 'results',\n 'value',\n];\nconst PRIMARY_OTHER_KEYWORDS: string[] = [\n 'records',\n 'content',\n 'list',\n 'payload',\n 'entities',\n 'collection',\n 'users',\n 'products',\n 'orders',\n 'bookings',\n 'articles',\n 'posts',\n 'documents',\n 'events',\n];\nconst SECONDARY_KEYWORDS: string[] = ['entries', 'rows', 'elements'];\n\nconst PLURAL_DEPRIORITIZE_LIST: string[] = [\n 'status',\n 'success',\n 'address',\n 'details',\n 'properties',\n 'params',\n 'headers',\n 'cookies',\n 'series',\n 'links',\n 'meta',\n 'metadata',\n 'statistics',\n 'settings',\n 'options',\n 'permissions',\n 'credentials',\n 'diagnostics',\n 'warnings',\n 'errors',\n 'actions',\n 'attributes',\n 'categories',\n 'features',\n 'includes',\n 'tags',\n];\n\n// For exact matches (normalized: lowercase, no underscores/hyphens)\nconst HAS_MORE_PRIMARY_POSITIVE_EXACT: string[] = [\n 'hasmore',\n 'hasnext',\n 'hasnextpage',\n 'moreitems',\n 'moreitemsavailable',\n 'nextpage',\n 'nextpageexists',\n 'nextpageavailable',\n 'hasadditionalresults',\n 'moreresultsavailable',\n 'canloadmore',\n 'hasadditional',\n 'additionalitems',\n 'fetchmore',\n];\n\nconst HAS_MORE_SECONDARY_POSITIVE_EXACT: string[] = ['more', 'next'];\n\nconst HAS_MORE_PRIMARY_INVERTED_EXACT: string[] = [\n 'islast',\n 'lastpage',\n 'endofresults',\n 'endoflist',\n 'nomoreitems',\n 'nomoredata',\n 'allitemsloaded',\n 'iscomplete',\n 'completed',\n];\n\n// For regex-based sub-phrase matching (tested against original propName, case-insensitive)\n// These regexes look for meaningful phrases, often using word boundaries (\\b)\n// and allowing for optional underscores.\nconst HAS_MORE_POSITIVE_REGEX_PATTERNS: string[] = [\n '\\\\bhas_?more\\\\b',\n '\\\\bhas_?next\\\\b', // e.g., itemsHasNext, items_has_next\n '\\\\bmore_?items\\\\b',\n '\\\\bnext_?page\\\\b', // e.g., userNextPageFlag\n '\\\\badditional\\\\b', // e.g., hasAdditionalData, additional_results_exist\n '\\\\bcontinuation\\\\b', // e.g., continuationAvailable, has_continuation_token\n '\\\\bmore_?results\\\\b',\n '\\\\bpage_?available\\\\b',\n '\\\\bnext(?:_?(page|marker))?\\\\b',\n];\nconst COMPILED_HAS_MORE_POSITIVE_REGEXES: RegExp[] =\n HAS_MORE_POSITIVE_REGEX_PATTERNS.map((p) => new RegExp(p, 'i'));\n\nconst HAS_MORE_INVERTED_REGEX_PATTERNS: string[] = [\n '\\\\bis_?last\\\\b', // e.g., pageIsLast\n '\\\\blast_?page\\\\b', // e.g., resultsAreLastPage\n '\\\\bend_?of_?(data|results|list|items|stream)\\\\b',\n '\\\\bno_?more_?(items|data|results)?\\\\b',\n '\\\\ball_?(items_?)?loaded\\\\b',\n '\\\\bis_?complete\\\\b',\n];\nconst COMPILED_HAS_MORE_INVERTED_REGEXES: RegExp[] =\n HAS_MORE_INVERTED_REGEX_PATTERNS.map((p) => new RegExp(p, 'i'));\n\n/**\n * Tries to guess the name of the property that holds the main list of items\n * within an object schema using a series of heuristics.\n *\n * @param schema The OpenAPI SchemaObject, expected to be of type 'object'.\n * @returns The name of the most likely property containing the items array,\n * or null if no array properties are found in the schema.\n */\nexport function getItemsName(\n properties: Record<string, SchemaObject>,\n): string | null {\n const arrayPropertyNames: string[] = [];\n for (const propName in properties) {\n if (propName in properties) {\n const propSchema = properties[propName] as SchemaObject;\n if (propSchema && propSchema.type === 'array') {\n arrayPropertyNames.push(propName);\n }\n }\n }\n\n // Heuristic 0: No array properties at all.\n if (arrayPropertyNames.length === 0) {\n return null;\n }\n\n // Heuristic 1: Exactly one array property. This is the strongest signal.\n if (arrayPropertyNames.length === 1) {\n return arrayPropertyNames[0];\n }\n\n // Multiple array properties exist. Apply ranked heuristics:\n let bestCandidate: string | null = null;\n let candidateRank = Infinity; // Lower is better\n\n const updateCandidate = (propName: string, rank: number) => {\n if (rank < candidateRank) {\n bestCandidate = propName;\n candidateRank = rank;\n }\n };\n\n for (const propName of arrayPropertyNames) {\n const lowerPropName = propName.toLowerCase();\n\n // Heuristic 2: Top-tier primary keywords (e.g., \"data\", \"items\")\n if (PRIMARY_TOP_TIER_KEYWORDS.includes(lowerPropName)) {\n updateCandidate(propName, 2);\n continue; // Move to next property, this is a strong match for this prop\n }\n\n // Heuristic 3: Other primary keywords\n if (candidateRank > 3 && PRIMARY_OTHER_KEYWORDS.includes(lowerPropName)) {\n updateCandidate(propName, 3);\n continue;\n }\n\n // Heuristic 4: Secondary keywords\n if (candidateRank > 4 && SECONDARY_KEYWORDS.includes(lowerPropName)) {\n updateCandidate(propName, 4);\n continue;\n }\n\n // Heuristic 5: Pluralized name, not on the deprioritize list\n if (\n candidateRank > 5 &&\n pluralize.isPlural(propName) &&\n !PLURAL_DEPRIORITIZE_LIST.includes(lowerPropName)\n ) {\n updateCandidate(propName, 5);\n continue;\n }\n\n // Heuristic 6: Pluralized name, IS on the deprioritize list (less preferred plural)\n if (\n candidateRank > 6 &&\n pluralize.isPlural(propName) &&\n PLURAL_DEPRIORITIZE_LIST.includes(lowerPropName)\n ) {\n updateCandidate(propName, 6);\n continue;\n }\n }\n\n // If any of the above heuristics found a candidate, return it.\n if (bestCandidate) {\n return bestCandidate;\n }\n\n // Heuristic 7: Fallback - If no keywords or clear plurals,\n // and multiple arrays exist, return the first array property encountered.\n // This ensures we always return a name if arrays are present.\n return arrayPropertyNames[0];\n}\n\nfunction guess(properties: Record<string, SchemaObject>) {\n const booleanPropertyNames: string[] = [];\n for (const propName in properties) {\n const propSchema = properties[propName] as SchemaObject;\n if (\n propSchema.type === 'boolean' ||\n propSchema.type === 'integer' ||\n propSchema.type === 'string'\n ) {\n booleanPropertyNames.push(propName);\n }\n }\n\n if (booleanPropertyNames.length === 0) {\n return null;\n }\n\n if (booleanPropertyNames.length === 1) {\n return booleanPropertyNames[0];\n }\n\n let bestCandidate: string | null = null;\n let candidateRank = Infinity;\n\n const updateCandidate = (propName: string, rank: number) => {\n if (rank < candidateRank) {\n bestCandidate = propName;\n candidateRank = rank;\n }\n };\n\n for (const propName of booleanPropertyNames) {\n const normalizedForExactMatch = propName.toLowerCase().replace(/[-_]/g, '');\n let currentPropRank = Infinity;\n\n // Rank 1: Primary Exact Positive Match\n if (HAS_MORE_PRIMARY_POSITIVE_EXACT.includes(normalizedForExactMatch)) {\n currentPropRank = 1;\n }\n // Rank 2: Secondary Exact Positive Match\n else if (\n HAS_MORE_SECONDARY_POSITIVE_EXACT.includes(normalizedForExactMatch)\n ) {\n currentPropRank = 2;\n }\n // Rank 3: Positive Regex Match (sub-phrase)\n else {\n let foundPositiveRegex = false;\n for (const regex of COMPILED_HAS_MORE_POSITIVE_REGEXES) {\n if (regex.test(propName)) {\n // Test against original propName\n currentPropRank = 3;\n foundPositiveRegex = true;\n break;\n }\n }\n\n // Only proceed to inverted matches if no positive match of any kind (Rank 1, 2, or 3) was found\n if (!foundPositiveRegex) {\n // Rank 4: Primary Exact Inverted Match\n if (HAS_MORE_PRIMARY_INVERTED_EXACT.includes(normalizedForExactMatch)) {\n currentPropRank = 4;\n }\n // Rank 5: Inverted Regex Match (sub-phrase)\n else {\n for (const regex of COMPILED_HAS_MORE_INVERTED_REGEXES) {\n if (regex.test(propName)) {\n // Test against original propName\n currentPropRank = 5;\n break;\n }\n }\n }\n }\n }\n\n updateCandidate(propName, currentPropRank);\n }\n return bestCandidate;\n}\n\n/**\n * Tries to guess the name of a boolean property that indicates if there are more items\n * to fetch (e.g., for pagination).\n *\n * @param schema The OpenAPI SchemaObject, expected to be of type 'object'.\n * @returns The name of the most likely boolean property indicating \"has more\",\n * or null if no suitable boolean property is found.\n */\nexport function getHasMoreName(properties: SchemasObject): string | null {\n const rootGuess = guess(properties);\n if (rootGuess) {\n return rootGuess;\n }\n for (const propName in properties) {\n const propSchema = properties[propName];\n if (propSchema.type === 'object' && propSchema.properties) {\n const nested = getHasMoreName(propSchema.properties as SchemasObject);\n if (nested) {\n return propName + '.' + nested;\n }\n }\n }\n return null;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { SchemaObject, SchemasObject } from 'openapi3-ts/oas31';\nimport pluralize from 'pluralize';\n\nconst PRIMARY_TOP_TIER_KEYWORDS: string[] = [\n 'data',\n 'items',\n 'results',\n 'value',\n];\nconst PRIMARY_OTHER_KEYWORDS: string[] = [\n 'records',\n 'content',\n 'list',\n 'payload',\n 'entities',\n 'collection',\n 'users',\n 'products',\n 'orders',\n 'bookings',\n 'articles',\n 'posts',\n 'documents',\n 'events',\n];\nconst SECONDARY_KEYWORDS: string[] = ['entries', 'rows', 'elements'];\n\nfunction lastWord(propName: string) {\n return (\n propName\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter(Boolean)\n .at(-1) ?? ''\n );\n}\n\nfunction hasKeyword(propName: string, keywords: string[]) {\n return keywords.includes(lastWord(propName));\n}\n\nconst PLURAL_DEPRIORITIZE_LIST: string[] = [\n 'status',\n 'success',\n 'address',\n 'details',\n 'properties',\n 'params',\n 'headers',\n 'cookies',\n 'series',\n 'links',\n 'meta',\n 'metadata',\n 'statistics',\n 'settings',\n 'options',\n 'permissions',\n 'credentials',\n 'diagnostics',\n 'warnings',\n 'errors',\n 'actions',\n 'attributes',\n 'categories',\n 'configurations',\n 'features',\n 'includes',\n 'tags',\n];\n\n// For exact matches (normalized: lowercase, no underscores/hyphens)\nconst HAS_MORE_PRIMARY_POSITIVE_EXACT: string[] = [\n 'hasmore',\n 'hasnext',\n 'hasnextpage',\n 'moreitems',\n 'moreitemsavailable',\n 'nextpage',\n 'nextpageexists',\n 'nextpageavailable',\n 'hasadditionalresults',\n 'moreresultsavailable',\n 'canloadmore',\n 'hasadditional',\n 'additionalitems',\n 'fetchmore',\n];\n\nconst HAS_MORE_SECONDARY_POSITIVE_EXACT: string[] = ['more', 'next'];\n\nconst HAS_MORE_PRIMARY_INVERTED_EXACT: string[] = [\n 'islast',\n 'lastpage',\n 'endofresults',\n 'endoflist',\n 'nomoreitems',\n 'nomoredata',\n 'allitemsloaded',\n 'iscomplete',\n 'completed',\n];\n\n// For regex-based sub-phrase matching (tested against original propName, case-insensitive)\n// These regexes look for meaningful phrases, often using word boundaries (\\b)\n// and allowing for optional underscores.\nconst HAS_MORE_POSITIVE_REGEX_PATTERNS: string[] = [\n '\\\\bhas_?more\\\\b',\n '\\\\bhas_?next\\\\b', // e.g., itemsHasNext, items_has_next\n '\\\\bmore_?items\\\\b',\n '\\\\bnext_?page\\\\b', // e.g., userNextPageFlag\n '\\\\badditional\\\\b', // e.g., hasAdditionalData, additional_results_exist\n '\\\\bcontinuation\\\\b', // e.g., continuationAvailable, has_continuation_token\n '\\\\bmore_?results\\\\b',\n '\\\\bpage_?available\\\\b',\n '\\\\bnext(?:_?(page|marker))?\\\\b',\n];\nconst COMPILED_HAS_MORE_POSITIVE_REGEXES: RegExp[] =\n HAS_MORE_POSITIVE_REGEX_PATTERNS.map((p) => new RegExp(p, 'i'));\n\nconst HAS_MORE_INVERTED_REGEX_PATTERNS: string[] = [\n '\\\\bis_?last\\\\b', // e.g., pageIsLast\n '\\\\blast_?page\\\\b', // e.g., resultsAreLastPage\n '\\\\bend_?of_?(data|results|list|items|stream)\\\\b',\n '\\\\bno_?more_?(items|data|results)?\\\\b',\n '\\\\ball_?(items_?)?loaded\\\\b',\n '\\\\bis_?complete\\\\b',\n];\nconst COMPILED_HAS_MORE_INVERTED_REGEXES: RegExp[] =\n HAS_MORE_INVERTED_REGEX_PATTERNS.map((p) => new RegExp(p, 'i'));\n\n/**\n * Tries to guess the name of the property that holds the main list of items\n * within an object schema using a series of heuristics.\n *\n * @param schema The OpenAPI SchemaObject, expected to be of type 'object'.\n * @returns The name of the most likely property containing the items array,\n * or null if no array properties are found in the schema.\n */\nexport function getItemsName(\n properties: Record<string, SchemaObject>,\n): string | null {\n const arrayPropertyNames: string[] = [];\n for (const propName in properties) {\n if (propName in properties) {\n const propSchema = properties[propName] as SchemaObject;\n if (propSchema && propSchema.type === 'array') {\n arrayPropertyNames.push(propName);\n }\n }\n }\n\n // Heuristic 0: No array properties at all.\n if (arrayPropertyNames.length === 0) {\n return null;\n }\n\n // Heuristic 1: Exactly one array property. This is the strongest signal.\n if (arrayPropertyNames.length === 1) {\n return arrayPropertyNames[0];\n }\n\n // Multiple array properties exist. Apply ranked heuristics:\n let bestCandidate: string | null = null;\n let candidateRank = Infinity; // Lower is better\n\n const updateCandidate = (propName: string, rank: number) => {\n if (rank < candidateRank) {\n bestCandidate = propName;\n candidateRank = rank;\n }\n };\n\n for (const propName of arrayPropertyNames) {\n const lowerPropName = propName.toLowerCase();\n const finalWord = lastWord(propName);\n const isDeprioritized = PLURAL_DEPRIORITIZE_LIST.includes(lowerPropName);\n const isCompoundMetadata =\n finalWord !== lowerPropName &&\n PLURAL_DEPRIORITIZE_LIST.includes(finalWord);\n\n // Heuristic 2: Top-tier primary keywords (e.g., \"data\", \"items\")\n if (hasKeyword(propName, PRIMARY_TOP_TIER_KEYWORDS)) {\n updateCandidate(propName, 2);\n continue; // Move to next property, this is a strong match for this prop\n }\n\n // Heuristic 3: Other primary keywords\n if (candidateRank > 3 && hasKeyword(propName, PRIMARY_OTHER_KEYWORDS)) {\n updateCandidate(propName, 3);\n continue;\n }\n\n // Heuristic 4: Secondary keywords\n if (candidateRank > 4 && hasKeyword(propName, SECONDARY_KEYWORDS)) {\n updateCandidate(propName, 4);\n continue;\n }\n\n // Heuristic 5: Pluralized name, not on the deprioritize list\n if (\n candidateRank > 5 &&\n pluralize.isPlural(propName) &&\n !isDeprioritized &&\n !isCompoundMetadata\n ) {\n updateCandidate(propName, 5);\n continue;\n }\n\n // Heuristic 6: Pluralized name, IS on the deprioritize list (less preferred plural)\n if (candidateRank > 6 && pluralize.isPlural(propName) && isDeprioritized) {\n updateCandidate(propName, 6);\n continue;\n }\n }\n\n // If any of the above heuristics found a candidate, return it.\n if (bestCandidate) {\n return bestCandidate;\n }\n\n // Heuristic 7: Fallback - If no keywords or clear plurals,\n // and multiple arrays exist, return the first array property encountered.\n // This ensures we always return a name if arrays are present.\n return arrayPropertyNames[0];\n}\n\nfunction guess(properties: Record<string, SchemaObject>) {\n const booleanPropertyNames: string[] = [];\n for (const propName in properties) {\n const propSchema = properties[propName] as SchemaObject;\n if (\n propSchema.type === 'boolean' ||\n propSchema.type === 'integer' ||\n propSchema.type === 'string'\n ) {\n booleanPropertyNames.push(propName);\n }\n }\n\n if (booleanPropertyNames.length === 0) {\n return null;\n }\n\n if (booleanPropertyNames.length === 1) {\n return booleanPropertyNames[0];\n }\n\n let bestCandidate: string | null = null;\n let candidateRank = Infinity;\n\n const updateCandidate = (propName: string, rank: number) => {\n if (rank < candidateRank) {\n bestCandidate = propName;\n candidateRank = rank;\n }\n };\n\n for (const propName of booleanPropertyNames) {\n const normalizedForExactMatch = propName.toLowerCase().replace(/[-_]/g, '');\n let currentPropRank = Infinity;\n\n // Rank 1: Primary Exact Positive Match\n if (HAS_MORE_PRIMARY_POSITIVE_EXACT.includes(normalizedForExactMatch)) {\n currentPropRank = 1;\n }\n // Rank 2: Secondary Exact Positive Match\n else if (\n HAS_MORE_SECONDARY_POSITIVE_EXACT.includes(normalizedForExactMatch)\n ) {\n currentPropRank = 2;\n }\n // Rank 3: Positive Regex Match (sub-phrase)\n else {\n let foundPositiveRegex = false;\n for (const regex of COMPILED_HAS_MORE_POSITIVE_REGEXES) {\n if (regex.test(propName)) {\n // Test against original propName\n currentPropRank = 3;\n foundPositiveRegex = true;\n break;\n }\n }\n\n // Only proceed to inverted matches if no positive match of any kind (Rank 1, 2, or 3) was found\n if (!foundPositiveRegex) {\n // Rank 4: Primary Exact Inverted Match\n if (HAS_MORE_PRIMARY_INVERTED_EXACT.includes(normalizedForExactMatch)) {\n currentPropRank = 4;\n }\n // Rank 5: Inverted Regex Match (sub-phrase)\n else {\n for (const regex of COMPILED_HAS_MORE_INVERTED_REGEXES) {\n if (regex.test(propName)) {\n // Test against original propName\n currentPropRank = 5;\n break;\n }\n }\n }\n }\n }\n\n updateCandidate(propName, currentPropRank);\n }\n return bestCandidate;\n}\n\n/**\n * Tries to guess the name of a boolean property that indicates if there are more items\n * to fetch (e.g., for pagination).\n *\n * @param schema The OpenAPI SchemaObject, expected to be of type 'object'.\n * @returns The name of the most likely boolean property indicating \"has more\",\n * or null if no suitable boolean property is found.\n */\nexport function getHasMoreName(properties: SchemasObject): string | null {\n const rootGuess = guess(properties);\n if (rootGuess) {\n return rootGuess;\n }\n for (const propName in properties) {\n const propSchema = properties[propName];\n if (propSchema.type === 'object' && propSchema.properties) {\n const nested = getHasMoreName(propSchema.properties as SchemasObject);\n if (nested) {\n return propName + '.' + nested;\n }\n }\n }\n return null;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../../src/lib/pagination/pagination.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,EAAE,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAG5D,wBAAgB,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,cAAc,EAAE,oBAAoB,OAwB1E"}
1
+ {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../../src/lib/pagination/pagination.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,EAAE,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAG5D,wBAAgB,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,cAAc,EAAE,oBAAoB,OAgC1E"}
@@ -1,14 +1,15 @@
1
1
  import { followRef, isRef } from "@sdk-it/core/ref.js";
2
+ import { isSuccessStatusCode } from "../is.js";
2
3
  import { guessPagination } from "./guess-pagination.js";
3
4
  function toPagination(spec, tunedOperation) {
4
5
  if (tunedOperation["x-pagination"]) {
5
6
  return tunedOperation["x-pagination"];
6
7
  }
7
- const schema = getResponseContentSchema(
8
- spec,
9
- tunedOperation.responses["200"],
10
- "application/json"
8
+ const successResponse = Object.entries(tunedOperation.responses).find(
9
+ ([status]) => isSuccessStatusCode(status) && Number.isInteger(Number(status))
11
10
  );
11
+ const statusCode = successResponse ? Number(successResponse[0]) : void 0;
12
+ const schema = successResponse ? getResponseContentSchema(spec, successResponse[1], "application/json") : void 0;
12
13
  const pagination = guessPagination(
13
14
  tunedOperation,
14
15
  tunedOperation.requestBody ? getRequestContentSchema(
@@ -18,8 +19,8 @@ function toPagination(spec, tunedOperation) {
18
19
  ) : void 0,
19
20
  schema
20
21
  );
21
- if (pagination && pagination.type !== "none" && schema) {
22
- return { ...pagination, statusCode: 200 };
22
+ if (pagination && pagination.type !== "none" && schema && statusCode !== void 0) {
23
+ return { ...pagination, statusCode };
23
24
  }
24
25
  return void 0;
25
26
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/pagination/pagination.ts"],
4
- "sourcesContent": ["import type {\n RequestBodyObject,\n ResponseObject,\n SchemaObject,\n} from 'openapi3-ts/oas31';\n\nimport { followRef, isRef } from '@sdk-it/core/ref.js';\n\nimport type { IR, TunedOperationObject } from '../types.js';\nimport { guessPagination } from './guess-pagination.js';\n\nexport function toPagination(spec: IR, tunedOperation: TunedOperationObject) {\n if (tunedOperation['x-pagination']) {\n return tunedOperation['x-pagination'];\n }\n const schema = getResponseContentSchema(\n spec,\n tunedOperation.responses['200'],\n 'application/json',\n );\n const pagination = guessPagination(\n tunedOperation,\n tunedOperation.requestBody\n ? getRequestContentSchema(\n spec,\n tunedOperation.requestBody,\n 'application/json',\n )\n : undefined,\n schema,\n );\n if (pagination && pagination.type !== 'none' && schema) {\n return { ...pagination, statusCode: 200 };\n }\n return undefined;\n}\n\nfunction getResponseContentSchema(\n spec: IR,\n response: ResponseObject,\n type: string,\n) {\n if (!response) {\n return undefined;\n }\n const content = response.content;\n if (!content) {\n return undefined;\n }\n for (const contentType in content) {\n if (contentType.toLowerCase() === type.toLowerCase()) {\n return isRef(content[contentType].schema)\n ? followRef<SchemaObject>(spec, content[contentType].schema.$ref)\n : content[contentType].schema;\n }\n }\n return undefined;\n}\n\nfunction getRequestContentSchema(\n spec: IR,\n requestBody: RequestBodyObject,\n type: string,\n) {\n const content = requestBody.content;\n if (!content) {\n return undefined;\n }\n for (const contentType in content) {\n if (contentType.toLowerCase() === type.toLowerCase()) {\n return isRef(content[contentType].schema)\n ? followRef<SchemaObject>(spec, content[contentType].schema.$ref)\n : content[contentType].schema;\n }\n }\n return undefined;\n}\n"],
5
- "mappings": "AAMA,SAAS,WAAW,aAAa;AAGjC,SAAS,uBAAuB;AAEzB,SAAS,aAAa,MAAU,gBAAsC;AAC3E,MAAI,eAAe,cAAc,GAAG;AAClC,WAAO,eAAe,cAAc;AAAA,EACtC;AACA,QAAM,SAAS;AAAA,IACb;AAAA,IACA,eAAe,UAAU,KAAK;AAAA,IAC9B;AAAA,EACF;AACA,QAAM,aAAa;AAAA,IACjB;AAAA,IACA,eAAe,cACX;AAAA,MACE;AAAA,MACA,eAAe;AAAA,MACf;AAAA,IACF,IACA;AAAA,IACJ;AAAA,EACF;AACA,MAAI,cAAc,WAAW,SAAS,UAAU,QAAQ;AACtD,WAAO,EAAE,GAAG,YAAY,YAAY,IAAI;AAAA,EAC1C;AACA,SAAO;AACT;AAEA,SAAS,yBACP,MACA,UACA,MACA;AACA,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AACA,QAAM,UAAU,SAAS;AACzB,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,aAAW,eAAe,SAAS;AACjC,QAAI,YAAY,YAAY,MAAM,KAAK,YAAY,GAAG;AACpD,aAAO,MAAM,QAAQ,WAAW,EAAE,MAAM,IACpC,UAAwB,MAAM,QAAQ,WAAW,EAAE,OAAO,IAAI,IAC9D,QAAQ,WAAW,EAAE;AAAA,IAC3B;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,wBACP,MACA,aACA,MACA;AACA,QAAM,UAAU,YAAY;AAC5B,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,aAAW,eAAe,SAAS;AACjC,QAAI,YAAY,YAAY,MAAM,KAAK,YAAY,GAAG;AACpD,aAAO,MAAM,QAAQ,WAAW,EAAE,MAAM,IACpC,UAAwB,MAAM,QAAQ,WAAW,EAAE,OAAO,IAAI,IAC9D,QAAQ,WAAW,EAAE;AAAA,IAC3B;AAAA,EACF;AACA,SAAO;AACT;",
4
+ "sourcesContent": ["import type {\n RequestBodyObject,\n ResponseObject,\n SchemaObject,\n} from 'openapi3-ts/oas31';\n\nimport { followRef, isRef } from '@sdk-it/core/ref.js';\n\nimport { isSuccessStatusCode } from '../is.js';\nimport type { IR, TunedOperationObject } from '../types.js';\nimport { guessPagination } from './guess-pagination.js';\n\nexport function toPagination(spec: IR, tunedOperation: TunedOperationObject) {\n if (tunedOperation['x-pagination']) {\n return tunedOperation['x-pagination'];\n }\n const successResponse = Object.entries(tunedOperation.responses).find(\n ([status]) =>\n isSuccessStatusCode(status) && Number.isInteger(Number(status)),\n );\n const statusCode = successResponse ? Number(successResponse[0]) : undefined;\n const schema = successResponse\n ? getResponseContentSchema(spec, successResponse[1], 'application/json')\n : undefined;\n const pagination = guessPagination(\n tunedOperation,\n tunedOperation.requestBody\n ? getRequestContentSchema(\n spec,\n tunedOperation.requestBody,\n 'application/json',\n )\n : undefined,\n schema,\n );\n if (\n pagination &&\n pagination.type !== 'none' &&\n schema &&\n statusCode !== undefined\n ) {\n return { ...pagination, statusCode };\n }\n return undefined;\n}\n\nfunction getResponseContentSchema(\n spec: IR,\n response: ResponseObject,\n type: string,\n) {\n if (!response) {\n return undefined;\n }\n const content = response.content;\n if (!content) {\n return undefined;\n }\n for (const contentType in content) {\n if (contentType.toLowerCase() === type.toLowerCase()) {\n return isRef(content[contentType].schema)\n ? followRef<SchemaObject>(spec, content[contentType].schema.$ref)\n : content[contentType].schema;\n }\n }\n return undefined;\n}\n\nfunction getRequestContentSchema(\n spec: IR,\n requestBody: RequestBodyObject,\n type: string,\n) {\n const content = requestBody.content;\n if (!content) {\n return undefined;\n }\n for (const contentType in content) {\n if (contentType.toLowerCase() === type.toLowerCase()) {\n return isRef(content[contentType].schema)\n ? followRef<SchemaObject>(spec, content[contentType].schema.$ref)\n : content[contentType].schema;\n }\n }\n return undefined;\n}\n"],
5
+ "mappings": "AAMA,SAAS,WAAW,aAAa;AAEjC,SAAS,2BAA2B;AAEpC,SAAS,uBAAuB;AAEzB,SAAS,aAAa,MAAU,gBAAsC;AAC3E,MAAI,eAAe,cAAc,GAAG;AAClC,WAAO,eAAe,cAAc;AAAA,EACtC;AACA,QAAM,kBAAkB,OAAO,QAAQ,eAAe,SAAS,EAAE;AAAA,IAC/D,CAAC,CAAC,MAAM,MACN,oBAAoB,MAAM,KAAK,OAAO,UAAU,OAAO,MAAM,CAAC;AAAA,EAClE;AACA,QAAM,aAAa,kBAAkB,OAAO,gBAAgB,CAAC,CAAC,IAAI;AAClE,QAAM,SAAS,kBACX,yBAAyB,MAAM,gBAAgB,CAAC,GAAG,kBAAkB,IACrE;AACJ,QAAM,aAAa;AAAA,IACjB;AAAA,IACA,eAAe,cACX;AAAA,MACE;AAAA,MACA,eAAe;AAAA,MACf;AAAA,IACF,IACA;AAAA,IACJ;AAAA,EACF;AACA,MACE,cACA,WAAW,SAAS,UACpB,UACA,eAAe,QACf;AACA,WAAO,EAAE,GAAG,YAAY,WAAW;AAAA,EACrC;AACA,SAAO;AACT;AAEA,SAAS,yBACP,MACA,UACA,MACA;AACA,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AACA,QAAM,UAAU,SAAS;AACzB,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,aAAW,eAAe,SAAS;AACjC,QAAI,YAAY,YAAY,MAAM,KAAK,YAAY,GAAG;AACpD,aAAO,MAAM,QAAQ,WAAW,EAAE,MAAM,IACpC,UAAwB,MAAM,QAAQ,WAAW,EAAE,OAAO,IAAI,IAC9D,QAAQ,WAAW,EAAE;AAAA,IAC3B;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,wBACP,MACA,aACA,MACA;AACA,QAAM,UAAU,YAAY;AAC5B,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,aAAW,eAAe,SAAS;AACjC,QAAI,YAAY,YAAY,MAAM,KAAK,YAAY,GAAG;AACpD,aAAO,MAAM,QAAQ,WAAW,EAAE,MAAM,IACpC,UAAwB,MAAM,QAAQ,WAAW,EAAE,OAAO,IAAI,IAC9D,QAAQ,WAAW,EAAE;AAAA,IAC3B;AAAA,EACF;AACA,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,3 @@
1
+ import type { ProcessingPlugin } from '../processing.js';
2
+ export declare function canonicalizeSpec(): ProcessingPlugin;
3
+ //# sourceMappingURL=canonicalize-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonicalize-spec.d.ts","sourceRoot":"","sources":["../../../src/lib/processing-plugins/canonicalize-spec.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAWzD,wBAAgB,gBAAgB,IAAI,gBAAgB,CAiBnD"}
@@ -0,0 +1,29 @@
1
+ import { walkSchemas } from "../walk-schemas.js";
2
+ function sortRecord(record) {
3
+ return Object.fromEntries(
4
+ Object.entries(record).sort(
5
+ ([left], [right]) => left < right ? -1 : left > right ? 1 : 0
6
+ )
7
+ );
8
+ }
9
+ function canonicalizeSpec() {
10
+ return {
11
+ name: "canonicalize-spec",
12
+ process({ spec }) {
13
+ spec.components.schemas = sortRecord(spec.components.schemas);
14
+ for (const { schema } of walkSchemas(spec)) {
15
+ if (schema.properties) {
16
+ schema.properties = sortRecord(schema.properties);
17
+ }
18
+ const extraProperties = schema["x-properties"];
19
+ if (extraProperties) {
20
+ schema["x-properties"] = sortRecord(extraProperties);
21
+ }
22
+ }
23
+ }
24
+ };
25
+ }
26
+ export {
27
+ canonicalizeSpec
28
+ };
29
+ //# sourceMappingURL=canonicalize-spec.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/lib/processing-plugins/canonicalize-spec.ts"],
4
+ "sourcesContent": ["import type { SchemaObject } from 'openapi3-ts/oas31';\n\nimport type { ProcessingPlugin } from '../processing.js';\nimport { walkSchemas } from '../walk-schemas.js';\n\nfunction sortRecord<T>(record: Record<string, T>): Record<string, T> {\n return Object.fromEntries(\n Object.entries(record).sort(([left], [right]) =>\n left < right ? -1 : left > right ? 1 : 0,\n ),\n );\n}\n\nexport function canonicalizeSpec(): ProcessingPlugin {\n return {\n name: 'canonicalize-spec',\n process({ spec }) {\n spec.components.schemas = sortRecord(spec.components.schemas);\n for (const { schema } of walkSchemas(spec)) {\n if (schema.properties) {\n schema.properties = sortRecord(schema.properties);\n }\n const extraProperties = schema['x-properties'] as\n Record<string, SchemaObject> | undefined;\n if (extraProperties) {\n schema['x-properties'] = sortRecord(extraProperties);\n }\n }\n },\n };\n}\n"],
5
+ "mappings": "AAGA,SAAS,mBAAmB;AAE5B,SAAS,WAAc,QAA8C;AACnE,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQ,MAAM,EAAE;AAAA,MAAK,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,MACzC,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI;AAAA,IACzC;AAAA,EACF;AACF;AAEO,SAAS,mBAAqC;AACnD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,EAAE,KAAK,GAAG;AAChB,WAAK,WAAW,UAAU,WAAW,KAAK,WAAW,OAAO;AAC5D,iBAAW,EAAE,OAAO,KAAK,YAAY,IAAI,GAAG;AAC1C,YAAI,OAAO,YAAY;AACrB,iBAAO,aAAa,WAAW,OAAO,UAAU;AAAA,QAClD;AACA,cAAM,kBAAkB,OAAO,cAAc;AAE7C,YAAI,iBAAiB;AACnB,iBAAO,cAAc,IAAI,WAAW,eAAe;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,5 @@
1
+ import type { ProcessingPlugin } from '../processing.js';
2
+ export declare function createDefaultProcessingPlugins(options?: {
3
+ verbose?: boolean;
4
+ }): ProcessingPlugin[];
5
+ //# sourceMappingURL=create-default-processing-plugins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-default-processing-plugins.d.ts","sourceRoot":"","sources":["../../../src/lib/processing-plugins/create-default-processing-plugins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAazD,wBAAgB,8BAA8B,CAC5C,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAClC,gBAAgB,EAAE,CAcpB"}
@@ -0,0 +1,30 @@
1
+ import { canonicalizeSpec } from "./canonicalize-spec.js";
2
+ import { extractInlineSchemas } from "./extract-inline-schemas.js";
3
+ import { extractOverviewDocsPlugin } from "./extract-overview-docs.js";
4
+ import { inferPagination } from "./infer-pagination.js";
5
+ import { normalizeOperationIds } from "./normalize-operation-ids.js";
6
+ import { normalizeParameters } from "./normalize-parameters.js";
7
+ import { normalizePaths } from "./normalize-paths.js";
8
+ import { normalizeRequestBodies } from "./normalize-request-bodies.js";
9
+ import { normalizeResponses } from "./normalize-responses.js";
10
+ import { normalizeSchemas } from "./normalize-schemas.js";
11
+ import { normalizeTags } from "./normalize-tags.js";
12
+ function createDefaultProcessingPlugins(options = {}) {
13
+ return [
14
+ normalizePaths(),
15
+ normalizeOperationIds(),
16
+ normalizeTags(),
17
+ normalizeParameters(),
18
+ normalizeResponses(),
19
+ normalizeRequestBodies(),
20
+ inferPagination(),
21
+ normalizeSchemas(),
22
+ ...options.verbose ? [extractInlineSchemas()] : [],
23
+ extractOverviewDocsPlugin(),
24
+ canonicalizeSpec()
25
+ ];
26
+ }
27
+ export {
28
+ createDefaultProcessingPlugins
29
+ };
30
+ //# sourceMappingURL=create-default-processing-plugins.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/lib/processing-plugins/create-default-processing-plugins.ts"],
4
+ "sourcesContent": ["import type { ProcessingPlugin } from '../processing.js';\nimport { canonicalizeSpec } from './canonicalize-spec.js';\nimport { extractInlineSchemas } from './extract-inline-schemas.js';\nimport { extractOverviewDocsPlugin } from './extract-overview-docs.js';\nimport { inferPagination } from './infer-pagination.js';\nimport { normalizeOperationIds } from './normalize-operation-ids.js';\nimport { normalizeParameters } from './normalize-parameters.js';\nimport { normalizePaths } from './normalize-paths.js';\nimport { normalizeRequestBodies } from './normalize-request-bodies.js';\nimport { normalizeResponses } from './normalize-responses.js';\nimport { normalizeSchemas } from './normalize-schemas.js';\nimport { normalizeTags } from './normalize-tags.js';\n\nexport function createDefaultProcessingPlugins(\n options: { verbose?: boolean } = {},\n): ProcessingPlugin[] {\n return [\n normalizePaths(),\n normalizeOperationIds(),\n normalizeTags(),\n normalizeParameters(),\n normalizeResponses(),\n normalizeRequestBodies(),\n inferPagination(),\n normalizeSchemas(),\n ...(options.verbose ? [extractInlineSchemas()] : []),\n extractOverviewDocsPlugin(),\n canonicalizeSpec(),\n ];\n}\n"],
5
+ "mappings": "AACA,SAAS,wBAAwB;AACjC,SAAS,4BAA4B;AACrC,SAAS,iCAAiC;AAC1C,SAAS,uBAAuB;AAChC,SAAS,6BAA6B;AACtC,SAAS,2BAA2B;AACpC,SAAS,sBAAsB;AAC/B,SAAS,8BAA8B;AACvC,SAAS,0BAA0B;AACnC,SAAS,wBAAwB;AACjC,SAAS,qBAAqB;AAEvB,SAAS,+BACd,UAAiC,CAAC,GACd;AACpB,SAAO;AAAA,IACL,eAAe;AAAA,IACf,sBAAsB;AAAA,IACtB,cAAc;AAAA,IACd,oBAAoB;AAAA,IACpB,mBAAmB;AAAA,IACnB,uBAAuB;AAAA,IACvB,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,GAAI,QAAQ,UAAU,CAAC,qBAAqB,CAAC,IAAI,CAAC;AAAA,IAClD,0BAA0B;AAAA,IAC1B,iBAAiB;AAAA,EACnB;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,25 @@
1
+ import type { OperationObject, SchemaObject } from 'openapi3-ts/oas31';
2
+ import type { ProcessingPlugin } from '../processing.js';
3
+ import type { IR } from '../types.js';
4
+ export interface ExampleEnrichmentInput {
5
+ spec: IR;
6
+ operation: OperationObject;
7
+ method: string;
8
+ path: string;
9
+ direction: 'request' | 'response';
10
+ mediaType: string;
11
+ schema: SchemaObject;
12
+ statusCode?: string;
13
+ signal?: AbortSignal;
14
+ }
15
+ export interface ExampleValidationInput extends ExampleEnrichmentInput {
16
+ value: unknown;
17
+ }
18
+ export interface ExampleEnrichmentOptions {
19
+ name?: string;
20
+ overwrite?: boolean;
21
+ generate(input: ExampleEnrichmentInput): unknown | Promise<unknown>;
22
+ validate(input: ExampleValidationInput): boolean | Promise<boolean>;
23
+ }
24
+ export declare function enrichExamples(options: ExampleEnrichmentOptions): ProcessingPlugin;
25
+ //# sourceMappingURL=enrich-examples.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrich-examples.d.ts","sourceRoot":"","sources":["../../../src/lib/processing-plugins/enrich-examples.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EAGf,YAAY,EACb,MAAM,mBAAmB,CAAC;AAK3B,OAAO,KAAK,EAAwB,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,EAAE,CAAC;IACT,SAAS,EAAE,eAAe,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,SAAS,GAAG,UAAU,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,sBAAuB,SAAQ,sBAAsB;IACpE,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpE,QAAQ,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACrE;AAgDD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,wBAAwB,GAChC,gBAAgB,CAyDlB"}
@@ -0,0 +1,93 @@
1
+ import { resolveRef } from "@sdk-it/core/ref.js";
2
+ import { iterateOperations } from "../for-each-operation.js";
3
+ function hasAuthoredExample(media) {
4
+ return Object.prototype.hasOwnProperty.call(media, "example") || Object.keys(media.examples ?? {}).length > 0;
5
+ }
6
+ async function enrichMediaType(input, options, report) {
7
+ const { media, ...target } = input;
8
+ if (!media.schema || !options.overwrite && hasAuthoredExample(media)) {
9
+ return;
10
+ }
11
+ target.signal?.throwIfAborted();
12
+ const schema = resolveRef(target.spec, media.schema);
13
+ const enrichmentInput = { ...target, schema };
14
+ const value = await options.generate(enrichmentInput);
15
+ target.signal?.throwIfAborted();
16
+ if (!await options.validate({ ...enrichmentInput, value })) {
17
+ report({
18
+ severity: "warning",
19
+ code: "generated-example-invalid",
20
+ message: `Discarded an invalid generated ${target.direction} example`,
21
+ path: `${target.method.toUpperCase()} ${target.path}`
22
+ });
23
+ return;
24
+ }
25
+ media.example = value;
26
+ report({
27
+ severity: "info",
28
+ code: "example-generated",
29
+ message: `Generated a schema-valid ${target.direction} example`,
30
+ path: `${target.method.toUpperCase()} ${target.path}`
31
+ });
32
+ }
33
+ function enrichExamples(options) {
34
+ return {
35
+ name: options.name ?? "enrich-examples",
36
+ async process({ spec, report, signal }) {
37
+ for (const { entry, operation } of iterateOperations(spec)) {
38
+ if (operation.requestBody) {
39
+ const requestBody = resolveRef(
40
+ spec,
41
+ operation.requestBody
42
+ );
43
+ for (const [mediaType, media] of Object.entries(
44
+ requestBody.content
45
+ )) {
46
+ await enrichMediaType(
47
+ {
48
+ spec,
49
+ operation,
50
+ method: entry.method,
51
+ path: entry.path,
52
+ direction: "request",
53
+ mediaType,
54
+ media,
55
+ signal
56
+ },
57
+ options,
58
+ report
59
+ );
60
+ }
61
+ }
62
+ for (const [statusCode, responseOrRef] of Object.entries(
63
+ operation.responses ?? {}
64
+ )) {
65
+ const response = resolveRef(spec, responseOrRef);
66
+ for (const [mediaType, media] of Object.entries(
67
+ response.content ?? {}
68
+ )) {
69
+ await enrichMediaType(
70
+ {
71
+ spec,
72
+ operation,
73
+ method: entry.method,
74
+ path: entry.path,
75
+ direction: "response",
76
+ statusCode,
77
+ mediaType,
78
+ media,
79
+ signal
80
+ },
81
+ options,
82
+ report
83
+ );
84
+ }
85
+ }
86
+ }
87
+ }
88
+ };
89
+ }
90
+ export {
91
+ enrichExamples
92
+ };
93
+ //# sourceMappingURL=enrich-examples.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/lib/processing-plugins/enrich-examples.ts"],
4
+ "sourcesContent": ["import type {\n MediaTypeObject,\n OperationObject,\n RequestBodyObject,\n ResponseObject,\n SchemaObject,\n} from 'openapi3-ts/oas31';\n\nimport { resolveRef } from '@sdk-it/core/ref.js';\n\nimport { iterateOperations } from '../for-each-operation.js';\nimport type { ProcessingDiagnostic, ProcessingPlugin } from '../processing.js';\nimport type { IR } from '../types.js';\n\nexport interface ExampleEnrichmentInput {\n spec: IR;\n operation: OperationObject;\n method: string;\n path: string;\n direction: 'request' | 'response';\n mediaType: string;\n schema: SchemaObject;\n statusCode?: string;\n signal?: AbortSignal;\n}\n\nexport interface ExampleValidationInput extends ExampleEnrichmentInput {\n value: unknown;\n}\n\nexport interface ExampleEnrichmentOptions {\n name?: string;\n overwrite?: boolean;\n generate(input: ExampleEnrichmentInput): unknown | Promise<unknown>;\n validate(input: ExampleValidationInput): boolean | Promise<boolean>;\n}\n\nfunction hasAuthoredExample(media: MediaTypeObject): boolean {\n return (\n Object.prototype.hasOwnProperty.call(media, 'example') ||\n Object.keys(media.examples ?? {}).length > 0\n );\n}\n\nasync function enrichMediaType(\n input: Omit<ExampleEnrichmentInput, 'schema'> & {\n media: MediaTypeObject;\n },\n options: ExampleEnrichmentOptions,\n report: (\n diagnostic: Omit<ProcessingDiagnostic, 'plugin'>,\n ) => ProcessingDiagnostic,\n) {\n const { media, ...target } = input;\n if (!media.schema || (!options.overwrite && hasAuthoredExample(media))) {\n return;\n }\n\n target.signal?.throwIfAborted();\n const schema = resolveRef<SchemaObject>(target.spec, media.schema);\n const enrichmentInput = { ...target, schema };\n const value = await options.generate(enrichmentInput);\n target.signal?.throwIfAborted();\n\n if (!(await options.validate({ ...enrichmentInput, value }))) {\n report({\n severity: 'warning',\n code: 'generated-example-invalid',\n message: `Discarded an invalid generated ${target.direction} example`,\n path: `${target.method.toUpperCase()} ${target.path}`,\n });\n return;\n }\n\n media.example = value;\n report({\n severity: 'info',\n code: 'example-generated',\n message: `Generated a schema-valid ${target.direction} example`,\n path: `${target.method.toUpperCase()} ${target.path}`,\n });\n}\n\nexport function enrichExamples(\n options: ExampleEnrichmentOptions,\n): ProcessingPlugin {\n return {\n name: options.name ?? 'enrich-examples',\n async process({ spec, report, signal }) {\n for (const { entry, operation } of iterateOperations(spec)) {\n if (operation.requestBody) {\n const requestBody = resolveRef<RequestBodyObject>(\n spec,\n operation.requestBody,\n );\n for (const [mediaType, media] of Object.entries(\n requestBody.content,\n )) {\n await enrichMediaType(\n {\n spec,\n operation,\n method: entry.method,\n path: entry.path,\n direction: 'request',\n mediaType,\n media,\n signal,\n },\n options,\n report,\n );\n }\n }\n\n for (const [statusCode, responseOrRef] of Object.entries(\n operation.responses ?? {},\n )) {\n const response = resolveRef<ResponseObject>(spec, responseOrRef);\n for (const [mediaType, media] of Object.entries(\n response.content ?? {},\n )) {\n await enrichMediaType(\n {\n spec,\n operation,\n method: entry.method,\n path: entry.path,\n direction: 'response',\n statusCode,\n mediaType,\n media,\n signal,\n },\n options,\n report,\n );\n }\n }\n }\n },\n };\n}\n"],
5
+ "mappings": "AAQA,SAAS,kBAAkB;AAE3B,SAAS,yBAAyB;AA2BlC,SAAS,mBAAmB,OAAiC;AAC3D,SACE,OAAO,UAAU,eAAe,KAAK,OAAO,SAAS,KACrD,OAAO,KAAK,MAAM,YAAY,CAAC,CAAC,EAAE,SAAS;AAE/C;AAEA,eAAe,gBACb,OAGA,SACA,QAGA;AACA,QAAM,EAAE,OAAO,GAAG,OAAO,IAAI;AAC7B,MAAI,CAAC,MAAM,UAAW,CAAC,QAAQ,aAAa,mBAAmB,KAAK,GAAI;AACtE;AAAA,EACF;AAEA,SAAO,QAAQ,eAAe;AAC9B,QAAM,SAAS,WAAyB,OAAO,MAAM,MAAM,MAAM;AACjE,QAAM,kBAAkB,EAAE,GAAG,QAAQ,OAAO;AAC5C,QAAM,QAAQ,MAAM,QAAQ,SAAS,eAAe;AACpD,SAAO,QAAQ,eAAe;AAE9B,MAAI,CAAE,MAAM,QAAQ,SAAS,EAAE,GAAG,iBAAiB,MAAM,CAAC,GAAI;AAC5D,WAAO;AAAA,MACL,UAAU;AAAA,MACV,MAAM;AAAA,MACN,SAAS,kCAAkC,OAAO,SAAS;AAAA,MAC3D,MAAM,GAAG,OAAO,OAAO,YAAY,CAAC,IAAI,OAAO,IAAI;AAAA,IACrD,CAAC;AACD;AAAA,EACF;AAEA,QAAM,UAAU;AAChB,SAAO;AAAA,IACL,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS,4BAA4B,OAAO,SAAS;AAAA,IACrD,MAAM,GAAG,OAAO,OAAO,YAAY,CAAC,IAAI,OAAO,IAAI;AAAA,EACrD,CAAC;AACH;AAEO,SAAS,eACd,SACkB;AAClB,SAAO;AAAA,IACL,MAAM,QAAQ,QAAQ;AAAA,IACtB,MAAM,QAAQ,EAAE,MAAM,QAAQ,OAAO,GAAG;AACtC,iBAAW,EAAE,OAAO,UAAU,KAAK,kBAAkB,IAAI,GAAG;AAC1D,YAAI,UAAU,aAAa;AACzB,gBAAM,cAAc;AAAA,YAClB;AAAA,YACA,UAAU;AAAA,UACZ;AACA,qBAAW,CAAC,WAAW,KAAK,KAAK,OAAO;AAAA,YACtC,YAAY;AAAA,UACd,GAAG;AACD,kBAAM;AAAA,cACJ;AAAA,gBACE;AAAA,gBACA;AAAA,gBACA,QAAQ,MAAM;AAAA,gBACd,MAAM,MAAM;AAAA,gBACZ,WAAW;AAAA,gBACX;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,mBAAW,CAAC,YAAY,aAAa,KAAK,OAAO;AAAA,UAC/C,UAAU,aAAa,CAAC;AAAA,QAC1B,GAAG;AACD,gBAAM,WAAW,WAA2B,MAAM,aAAa;AAC/D,qBAAW,CAAC,WAAW,KAAK,KAAK,OAAO;AAAA,YACtC,SAAS,WAAW,CAAC;AAAA,UACvB,GAAG;AACD,kBAAM;AAAA,cACJ;AAAA,gBACE;AAAA,gBACA;AAAA,gBACA,QAAQ,MAAM;AAAA,gBACd,MAAM,MAAM;AAAA,gBACZ,WAAW;AAAA,gBACX;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,3 @@
1
+ import type { ProcessingPlugin } from '../processing.js';
2
+ export declare function extractInlineSchemas(): ProcessingPlugin;
3
+ //# sourceMappingURL=extract-inline-schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-inline-schemas.d.ts","sourceRoot":"","sources":["../../../src/lib/processing-plugins/extract-inline-schemas.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAuLzD,wBAAgB,oBAAoB,IAAI,gBAAgB,CAOvD"}
@@ -0,0 +1,165 @@
1
+ import { isEmpty, isRef, joinSkipDigits, pascalcase } from "@sdk-it/core";
2
+ import { findUniqueSchemaName } from "../find-unique-schema-name.js";
3
+ function extractInlineSchemaComponents(spec, schemas) {
4
+ for (const [name, schema] of Object.entries(schemas)) {
5
+ if (isRef(schema)) continue;
6
+ if (!isEmpty(schema.properties)) {
7
+ if (!isEmpty(schema.oneOf)) {
8
+ for (const oneOfIndex in schema.oneOf) {
9
+ const oneOf = schema.oneOf[oneOfIndex];
10
+ if (isRef(oneOf)) continue;
11
+ for (const key of ["properties", "x-properties"]) {
12
+ if (!isEmpty(oneOf.required) && schema[key]) {
13
+ schema.oneOf[oneOfIndex] = schema[key][oneOf.required[0]];
14
+ }
15
+ }
16
+ }
17
+ delete schema.type;
18
+ extractInlineSchemaComponents(spec, schemas);
19
+ continue;
20
+ }
21
+ if (schema.additionalProperties) {
22
+ continue;
23
+ }
24
+ spec.components.schemas[name] = schema;
25
+ const properties = schema.properties;
26
+ for (const [propertyName, value] of Object.entries(properties)) {
27
+ if (isRef(value)) continue;
28
+ const fixedPropertyName = propertyName.replace("[]", "");
29
+ const refName = findUniqueSchemaName(
30
+ spec,
31
+ pascalcase(joinSkipDigits([name, fixedPropertyName], " ")),
32
+ ["Property", "Field", "Attribute"]
33
+ );
34
+ if (!isEmpty(value.properties)) {
35
+ spec.components.schemas[refName] = value;
36
+ properties[propertyName] = {
37
+ $ref: `#/components/schemas/${refName}`
38
+ };
39
+ extractInlineSchemaComponents(spec, { [refName]: value });
40
+ } else if (!isEmpty(value.oneOf)) {
41
+ extractInlineUnion(spec, name, value, "oneOf");
42
+ spec.components.schemas[refName] = value;
43
+ properties[propertyName] = {
44
+ $ref: `#/components/schemas/${refName}`
45
+ };
46
+ extractInlineSchemaComponents(spec, { [refName]: value });
47
+ } else if (!isEmpty(value.anyOf)) {
48
+ extractInlineUnion(spec, name, value, "anyOf");
49
+ spec.components.schemas[refName] = value;
50
+ properties[propertyName] = {
51
+ $ref: `#/components/schemas/${refName}`
52
+ };
53
+ extractInlineSchemaComponents(spec, { [refName]: value });
54
+ } else {
55
+ extractInlineSchemaComponents(spec, { [refName]: value });
56
+ }
57
+ }
58
+ continue;
59
+ }
60
+ if (!isEmpty(schema["x-properties"])) {
61
+ spec.components.schemas[name] = schema;
62
+ const properties = schema["x-properties"];
63
+ for (const [propertyName, value] of Object.entries(properties)) {
64
+ if (isRef(value)) continue;
65
+ const fixedPropertyName = propertyName.replace("[]", "");
66
+ const refName = findUniqueSchemaName(
67
+ spec,
68
+ pascalcase(joinSkipDigits([name, fixedPropertyName], " ")),
69
+ ["Property", "Field", "Attribute"]
70
+ );
71
+ if (!isEmpty(value.properties)) {
72
+ spec.components.schemas[refName] = value;
73
+ properties[propertyName] = {
74
+ $ref: `#/components/schemas/${refName}`
75
+ };
76
+ extractInlineSchemaComponents(spec, { [refName]: value });
77
+ } else if (!isEmpty(value.oneOf)) {
78
+ extractInlineUnion(spec, name, value, "oneOf");
79
+ spec.components.schemas[refName] = value;
80
+ properties[propertyName] = {
81
+ $ref: `#/components/schemas/${refName}`
82
+ };
83
+ extractInlineSchemaComponents(spec, { [refName]: value });
84
+ } else if (!isEmpty(value.anyOf)) {
85
+ extractInlineUnion(spec, name, value, "anyOf");
86
+ spec.components.schemas[refName] = value;
87
+ properties[propertyName] = {
88
+ $ref: `#/components/schemas/${refName}`
89
+ };
90
+ extractInlineSchemaComponents(spec, { [refName]: value });
91
+ } else {
92
+ extractInlineSchemaComponents(spec, { [refName]: value });
93
+ }
94
+ }
95
+ continue;
96
+ }
97
+ if (schema.type === "array") {
98
+ if (isRef(schema.items) || isEmpty(schema.items)) continue;
99
+ const refName = findUniqueSchemaName(spec, name, ["Item", "Entry"]);
100
+ if (schema.items.type === "object") {
101
+ spec.components.schemas[refName] = schema.items;
102
+ extractInlineSchemaComponents(spec, { [refName]: schema.items });
103
+ schema.items = { $ref: `#/components/schemas/${refName}` };
104
+ continue;
105
+ }
106
+ if (schema.items.type === "array") {
107
+ extractInlineSchemaComponents(spec, { [refName]: schema.items });
108
+ continue;
109
+ }
110
+ if (!isEmpty(schema.items.oneOf)) {
111
+ extractInlineUnion(spec, refName, schema.items, "oneOf");
112
+ continue;
113
+ }
114
+ if (!isEmpty(schema.items.anyOf)) {
115
+ extractInlineUnion(spec, refName, schema.items, "anyOf");
116
+ continue;
117
+ }
118
+ }
119
+ if (!isEmpty(schema.oneOf)) {
120
+ extractInlineUnion(spec, name, schema, "oneOf");
121
+ continue;
122
+ }
123
+ if (!isEmpty(schema.anyOf)) {
124
+ extractInlineUnion(spec, name, schema, "anyOf");
125
+ }
126
+ }
127
+ }
128
+ function extractInlineUnion(spec, name, schema, kind) {
129
+ const varients = schema["x-varients"];
130
+ if (!varients || varients.length === 0) {
131
+ console.warn(
132
+ `No varients found for ${name}. This might be an error in the OpenAPI spec.`
133
+ );
134
+ }
135
+ varients.forEach((varient) => {
136
+ const varientSchema = schema[kind][varient.position];
137
+ if (isRef(varientSchema)) return;
138
+ const refName = findUniqueSchemaName(
139
+ spec,
140
+ pascalcase(`${name} ${varient.name}`),
141
+ ["Varient"]
142
+ );
143
+ if (varientSchema.type === "object") {
144
+ spec.components.schemas[refName] = varientSchema;
145
+ extractInlineSchemaComponents(spec, { [refName]: varientSchema });
146
+ schema[kind][varient.position] = {
147
+ $ref: `#/components/schemas/${refName}`
148
+ };
149
+ } else {
150
+ extractInlineSchemaComponents(spec, { [refName]: varientSchema });
151
+ }
152
+ });
153
+ }
154
+ function extractInlineSchemas() {
155
+ return {
156
+ name: "extract-inline-schemas",
157
+ process({ spec }) {
158
+ extractInlineSchemaComponents(spec, spec.components.schemas);
159
+ }
160
+ };
161
+ }
162
+ export {
163
+ extractInlineSchemas
164
+ };
165
+ //# sourceMappingURL=extract-inline-schemas.js.map