@sdk-it/spec 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/index.d.ts +7 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +19 -2629
  4. package/dist/index.js.map +4 -4
  5. package/dist/lib/find-polymorphic-varients.d.ts +1 -1
  6. package/dist/lib/find-polymorphic-varients.d.ts.map +1 -1
  7. package/dist/lib/find-polymorphic-varients.js +291 -0
  8. package/dist/lib/find-polymorphic-varients.js.map +7 -0
  9. package/dist/lib/find-polymorphic-varients.test.js +615 -0
  10. package/dist/lib/find-polymorphic-varients.test.js.map +7 -0
  11. package/dist/lib/find-unique-schema-name.js +16 -0
  12. package/dist/lib/find-unique-schema-name.js.map +7 -0
  13. package/dist/lib/for-each-operation.d.ts +3 -0
  14. package/dist/lib/for-each-operation.d.ts.map +1 -0
  15. package/dist/lib/for-each-operation.js +30 -0
  16. package/dist/lib/for-each-operation.js.map +7 -0
  17. package/dist/lib/format-name.js +86 -0
  18. package/dist/lib/format-name.js.map +7 -0
  19. package/dist/lib/get-ref-usage.d.ts +1 -1
  20. package/dist/lib/get-ref-usage.d.ts.map +1 -1
  21. package/dist/lib/get-ref-usage.js +52 -0
  22. package/dist/lib/get-ref-usage.js.map +7 -0
  23. package/dist/lib/is-primitive-schema.js +12 -0
  24. package/dist/lib/is-primitive-schema.js.map +7 -0
  25. package/dist/lib/is.d.ts +14 -0
  26. package/dist/lib/is.d.ts.map +1 -0
  27. package/dist/lib/is.js +71 -0
  28. package/dist/lib/is.js.map +7 -0
  29. package/dist/lib/loaders/load-spec.js +25 -0
  30. package/dist/lib/loaders/load-spec.js.map +7 -0
  31. package/dist/lib/loaders/local-loader.js +20 -0
  32. package/dist/lib/loaders/local-loader.js.map +7 -0
  33. package/dist/lib/loaders/postman/postman-converter.js +483 -0
  34. package/dist/lib/loaders/postman/postman-converter.js.map +7 -0
  35. package/dist/lib/loaders/postman/spec-types.js +1 -0
  36. package/dist/lib/loaders/postman/spec-types.js.map +7 -0
  37. package/dist/lib/loaders/remote-loader.js +29 -0
  38. package/dist/lib/loaders/remote-loader.js.map +7 -0
  39. package/dist/lib/metadata.js +51 -0
  40. package/dist/lib/metadata.js.map +7 -0
  41. package/dist/lib/operation.d.ts +4 -75
  42. package/dist/lib/operation.d.ts.map +1 -1
  43. package/dist/lib/operation.js +402 -0
  44. package/dist/lib/operation.js.map +7 -0
  45. package/dist/lib/operation.test.js +261 -0
  46. package/dist/lib/operation.test.js.map +7 -0
  47. package/dist/lib/options.d.ts +30 -0
  48. package/dist/lib/options.d.ts.map +1 -0
  49. package/dist/lib/options.js +54 -0
  50. package/dist/lib/options.js.map +7 -0
  51. package/dist/lib/overview-docs.d.ts +4 -0
  52. package/dist/lib/overview-docs.d.ts.map +1 -0
  53. package/dist/lib/overview-docs.js +276 -0
  54. package/dist/lib/overview-docs.js.map +7 -0
  55. package/dist/lib/pagination/pagination-result.js +235 -0
  56. package/dist/lib/pagination/pagination-result.js.map +7 -0
  57. package/dist/lib/pagination/pagination-result.test.js +548 -0
  58. package/dist/lib/pagination/pagination-result.test.js.map +7 -0
  59. package/dist/lib/pagination/pagination.d.ts +1 -1
  60. package/dist/lib/pagination/pagination.d.ts.map +1 -1
  61. package/dist/lib/pagination/pagination.js +222 -0
  62. package/dist/lib/pagination/pagination.js.map +7 -0
  63. package/dist/lib/pagination/pagination.test.js +378 -0
  64. package/dist/lib/pagination/pagination.test.js.map +7 -0
  65. package/dist/lib/reserved-keywords.d.ts +6 -0
  66. package/dist/lib/reserved-keywords.d.ts.map +1 -0
  67. package/dist/lib/reserved-keywords.js +71 -0
  68. package/dist/lib/reserved-keywords.js.map +7 -0
  69. package/dist/lib/security.d.ts +6 -4
  70. package/dist/lib/security.d.ts.map +1 -1
  71. package/dist/lib/security.js +75 -0
  72. package/dist/lib/security.js.map +7 -0
  73. package/dist/lib/sidebar.d.ts +5 -3
  74. package/dist/lib/sidebar.d.ts.map +1 -1
  75. package/dist/lib/sidebar.js +79 -0
  76. package/dist/lib/sidebar.js.map +7 -0
  77. package/dist/lib/tag.d.ts +19 -0
  78. package/dist/lib/tag.d.ts.map +1 -0
  79. package/dist/lib/tag.js +132 -0
  80. package/dist/lib/tag.js.map +7 -0
  81. package/dist/lib/tune.d.ts +1 -1
  82. package/dist/lib/tune.d.ts.map +1 -1
  83. package/dist/lib/tune.js +291 -0
  84. package/dist/lib/tune.js.map +7 -0
  85. package/dist/lib/tune.test.js +60 -0
  86. package/dist/lib/tune.test.js.map +7 -0
  87. package/dist/lib/types.d.ts +37 -0
  88. package/dist/lib/types.d.ts.map +1 -0
  89. package/dist/lib/types.js +1 -0
  90. package/dist/lib/types.js.map +7 -0
  91. package/package.json +4 -3
@@ -1,68 +1,11 @@
1
- import type { ComponentsObject, MediaTypeObject, OpenAPIObject, OperationObject, ParameterObject, PathsObject, ReferenceObject, RequestBodyObject, ResponseObject, SchemaObject, SecurityRequirementObject, SecuritySchemeObject } from 'openapi3-ts/oas31';
2
- import { type PaginationGuess } from './pagination/pagination.ts';
1
+ import type { ParameterObject, ReferenceObject, SchemaObject, SecurityRequirementObject } from 'openapi3-ts/oas31';
2
+ import { type GenerateSdkConfig } from './options.js';
3
+ import { type PaginationGuess } from './pagination/pagination.js';
4
+ import type { OurOpenAPIObject, TunedOperationObject } from './types.js';
3
5
  export declare function augmentSpec(config: GenerateSdkConfig, verbose?: boolean): OurOpenAPIObject;
4
6
  export type OperationPagination = PaginationGuess & {
5
7
  items: string;
6
8
  };
7
- export declare const defaults: Partial<GenerateSdkConfig> & Required<Pick<GenerateSdkConfig, 'operationId' | 'tag'>>;
8
- export type TunedOperationObject = Omit<OperationObject, 'operationId' | 'tags' | 'parameters' | 'responses' | 'requestBody'> & {
9
- tags: string[];
10
- operationId: string;
11
- parameters: ParameterObject[];
12
- responses: Record<string, ResponseObject>;
13
- requestBody: OurRequestBodyObject;
14
- };
15
- export interface OperationEntry {
16
- name?: string;
17
- method: string;
18
- path: string;
19
- groupName: string;
20
- tag: string;
21
- }
22
- export type Operation = {
23
- entry: OperationEntry;
24
- operation: TunedOperationObject;
25
- };
26
- export declare function forEachOperation<T>(spec: OurOpenAPIObject, callback: (entry: OperationEntry, operation: TunedOperationObject) => T): T[];
27
- interface ResponsesConfig {
28
- flattenErrorResponses?: boolean;
29
- }
30
- export interface GenerateSdkConfig {
31
- spec: OpenAPIObject;
32
- responses?: ResponsesConfig;
33
- operationId?: (operation: OperationObject, path: string, method: string) => string;
34
- tag?: (operation: OperationObject, path: string) => string;
35
- }
36
- /**
37
- * Sanitizes a potential tag name (assumed to be already camelCased)
38
- * to avoid conflicts with reserved keywords or invalid starting characters (numbers).
39
- * Appends an underscore if the tag matches a reserved keyword.
40
- * Prepends an underscore if the tag starts with a number.
41
- * @param tag The potential tag name, already camelCased.
42
- * @returns The sanitized tag name.
43
- */
44
- export declare function sanitizeTag(tag: string): string;
45
- /**
46
- * Attempts to determine a generic tag for an OpenAPI operation based on path and operationId.
47
- * Rules and fallbacks are documented within the code.
48
- * @param pathString The path string.
49
- * @param operation The OpenAPI Operation Object.
50
- * @returns A sanitized, camelCased tag name string.
51
- */
52
- export declare function determineGenericTag(pathString: string, operation: OperationObject): string;
53
- export declare function parseJsonContentType(contentType: string | null | undefined): string | null;
54
- export declare function isTextContentType(contentType: string | null | undefined): boolean;
55
- /**
56
- * Checks if a given content type string represents Server-Sent Events (SSE).
57
- * Handles case-insensitivity, parameters (like charset), and leading/trailing whitespace.
58
- *
59
- * @param contentType The content type string to check (e.g., from a Content-Type header).
60
- * @returns True if the content type is 'text/event-stream', false otherwise.
61
- */
62
- export declare function isSseContentType(contentType: string | null | undefined): boolean;
63
- export declare function isStreamingContentType(contentType: string | null | undefined): boolean;
64
- export declare function isSuccessStatusCode(statusCode: number | string): boolean;
65
- export declare function isErrorStatusCode(statusCode: number | string): boolean;
66
9
  export declare function patchParameters(spec: OurOpenAPIObject, schema: SchemaObject, parameters: ParameterObject[], security: SecurityRequirementObject[]): void;
67
10
  export declare function createOperation(options: {
68
11
  name: string;
@@ -89,18 +32,4 @@ export declare function createOperation(options: {
89
32
  response: Record<string, SchemaObject | Record<string, SchemaObject>>;
90
33
  request?: Record<string, ReferenceObject>;
91
34
  }): TunedOperationObject;
92
- export interface OurOpenAPIObject extends OpenAPIObject {
93
- 'x-sdk-augmented'?: boolean;
94
- components: Omit<ComponentsObject, 'schemas'> & {
95
- schemas: Record<string, SchemaObject | ReferenceObject>;
96
- securitySchemes: Record<string, SecuritySchemeObject | ReferenceObject>;
97
- };
98
- paths: PathsObject;
99
- }
100
- export interface OurRequestBodyObject extends RequestBodyObject {
101
- content: Record<string, Omit<MediaTypeObject, 'schema'> & {
102
- schema: ReferenceObject;
103
- }>;
104
- }
105
- export {};
106
35
  //# sourceMappingURL=operation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"operation.d.ts","sourceRoot":"","sources":["../../src/lib/operation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"operation.d.ts","sourceRoot":"","sources":["../../src/lib/operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,eAAe,EAEf,eAAe,EAIf,YAAY,EACZ,yBAAyB,EAC1B,MAAM,mBAAmB,CAAC;AAa3B,OAAO,EACL,KAAK,iBAAiB,EAGvB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,KAAK,EACV,gBAAgB,EAEhB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAiCpB,wBAAgB,WAAW,CACzB,MAAM,EAAE,iBAAiB,EACzB,OAAO,UAAQ,GACd,gBAAgB,CAkGlB;AAED,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAAG;IAClD,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAqMF,wBAAgB,eAAe,CAC7B,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,eAAe,EAAE,EAC7B,QAAQ,EAAE,yBAAyB,EAAE,QA4BtC;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE;QACX,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,MAAM,EAAE,YAAY,CAAC;YAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;QACrE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,MAAM,EAAE,YAAY,CAAC;YAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;QACpE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,MAAM,EAAE,YAAY,CAAC;YAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;QACtE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,MAAM,EAAE,YAAY,CAAC;YAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;KACvE,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC3C,GAAG,oBAAoB,CA4DvB"}
@@ -0,0 +1,402 @@
1
+ import { methods } from "@sdk-it/core/paths.js";
2
+ import { followRef, isRef, parseRef, resolveRef } from "@sdk-it/core/ref.js";
3
+ import { isEmpty, pascalcase, snakecase } from "@sdk-it/core/utils.js";
4
+ import { findUniqueSchemaName } from "./find-unique-schema-name.js";
5
+ import {
6
+ isSseContentType,
7
+ isSuccessStatusCode,
8
+ isTextContentType,
9
+ parseJsonContentType
10
+ } from "./is.js";
11
+ import {
12
+ coeraceConfig
13
+ } from "./options.js";
14
+ import { extractOverviewDocs } from "./overview-docs.js";
15
+ import {
16
+ guessPagination
17
+ } from "./pagination/pagination.js";
18
+ import { securityToOptions } from "./security.js";
19
+ import { expandSpec, fixSpec } from "./tune.js";
20
+ function findUniqueOperationId(usedOperationIds, initialId, choices, formatter) {
21
+ let counter = 1;
22
+ let uniqueOperationId = formatter(initialId);
23
+ while (usedOperationIds.has(uniqueOperationId)) {
24
+ const prependIndex = Math.min(counter - 1, choices.length - 1);
25
+ const prefix = choices[prependIndex];
26
+ if (prependIndex < choices.length - 1) {
27
+ uniqueOperationId = formatter(
28
+ `${prefix}${initialId.charAt(0).toUpperCase() + initialId.slice(1)}`
29
+ );
30
+ } else {
31
+ uniqueOperationId = formatter(
32
+ `${prefix}${initialId.charAt(0).toUpperCase() + initialId.slice(1)}${counter - choices.length + 1}`
33
+ );
34
+ }
35
+ counter++;
36
+ }
37
+ return uniqueOperationId;
38
+ }
39
+ function augmentSpec(config, verbose = false) {
40
+ const coearcedConfig = coeraceConfig(config);
41
+ if ("x-sdk-augmented" in config.spec) {
42
+ return config.spec;
43
+ }
44
+ const spec = {
45
+ ...config.spec,
46
+ components: {
47
+ ...config.spec.components,
48
+ schemas: config.spec.components?.schemas ?? {},
49
+ securitySchemes: config.spec.components?.securitySchemes ?? {}
50
+ },
51
+ paths: config.spec.paths ?? {},
52
+ "x-docs": []
53
+ };
54
+ const paths = {};
55
+ const usedOperationIds = /* @__PURE__ */ new Set();
56
+ for (const [path, pathItem] of Object.entries(spec.paths)) {
57
+ const fixedPath = path.replace(/:([^/]+)/g, "{$1}");
58
+ for (const [method, operation] of Object.entries(pathItem)) {
59
+ if (!methods.includes(method)) {
60
+ continue;
61
+ }
62
+ const operationTag = coearcedConfig.tag(operation, fixedPath);
63
+ const operationId = findUniqueOperationId(
64
+ usedOperationIds,
65
+ coearcedConfig.operationId(operation, fixedPath, method),
66
+ [operationTag, method, fixedPath.split("/").filter(Boolean).join("")],
67
+ (id) => coearcedConfig.operationId(
68
+ { ...operation, operationId: id },
69
+ fixedPath,
70
+ method
71
+ )
72
+ );
73
+ usedOperationIds.add(operationId);
74
+ const parameters = [
75
+ ...pathItem.parameters ?? [],
76
+ ...operation.parameters ?? []
77
+ ].map((it) => resolveRef(spec, it));
78
+ const tunedOperation = {
79
+ ...operation,
80
+ parameters,
81
+ tags: [snakecase(operationTag)],
82
+ operationId,
83
+ responses: resolveResponses(
84
+ spec,
85
+ operationId,
86
+ operation,
87
+ config.responses
88
+ ),
89
+ requestBody: tuneRequestBody(
90
+ spec,
91
+ operationId,
92
+ operation,
93
+ parameters,
94
+ operation.security ?? []
95
+ )
96
+ };
97
+ if (coearcedConfig.pagination.enabled) {
98
+ if (coearcedConfig.pagination.guess) {
99
+ tunedOperation["x-pagination"] = toPagination(spec, tunedOperation);
100
+ }
101
+ } else {
102
+ delete tunedOperation["x-pagination"];
103
+ }
104
+ Object.assign(paths, {
105
+ [fixedPath]: {
106
+ ...paths[fixedPath],
107
+ [method]: tunedOperation
108
+ }
109
+ });
110
+ }
111
+ }
112
+ fixSpec(spec, Object.values(spec.components.schemas));
113
+ if (verbose) {
114
+ const newRefs = [];
115
+ expandSpec(spec, spec.components.schemas, newRefs);
116
+ }
117
+ return {
118
+ ...spec,
119
+ paths,
120
+ "x-docs": extractOverviewDocs(spec),
121
+ "x-sdk-augmented": true
122
+ };
123
+ }
124
+ function toPagination(spec, tunedOperation) {
125
+ if (tunedOperation["x-pagination"]) {
126
+ return tunedOperation["x-pagination"];
127
+ }
128
+ const schema = getResponseContentSchema(
129
+ spec,
130
+ tunedOperation.responses["200"],
131
+ "application/json"
132
+ );
133
+ const pagination = guessPagination(
134
+ tunedOperation,
135
+ tunedOperation.requestBody ? getRequestContentSchema(
136
+ spec,
137
+ tunedOperation.requestBody,
138
+ "application/json"
139
+ ) : void 0,
140
+ schema
141
+ );
142
+ if (pagination && pagination.type !== "none" && schema) {
143
+ return pagination;
144
+ }
145
+ return void 0;
146
+ }
147
+ function getResponseContentSchema(spec, response, type) {
148
+ if (!response) {
149
+ return void 0;
150
+ }
151
+ const content = response.content;
152
+ if (!content) {
153
+ return void 0;
154
+ }
155
+ for (const contentType in content) {
156
+ if (contentType.toLowerCase() === type.toLowerCase()) {
157
+ return isRef(content[contentType].schema) ? followRef(spec, content[contentType].schema.$ref) : content[contentType].schema;
158
+ }
159
+ }
160
+ return void 0;
161
+ }
162
+ function getRequestContentSchema(spec, requestBody, type) {
163
+ const content = requestBody.content;
164
+ if (!content) {
165
+ return void 0;
166
+ }
167
+ for (const contentType in content) {
168
+ if (contentType.toLowerCase() === type.toLowerCase()) {
169
+ return isRef(content[contentType].schema) ? followRef(spec, content[contentType].schema.$ref) : content[contentType].schema;
170
+ }
171
+ }
172
+ return void 0;
173
+ }
174
+ function resolveResponses(spec, operationId, operation, responsesConfig) {
175
+ const responses = operation.responses ?? {};
176
+ operation.responses ??= {};
177
+ let foundSuccessResponse = false;
178
+ for (const status in responses) {
179
+ if (status === "default") {
180
+ delete responses[status];
181
+ continue;
182
+ }
183
+ operation.responses[status] = structuredClone(
184
+ resolveRef(spec, responses[status])
185
+ );
186
+ if (isSuccessStatusCode(status)) {
187
+ foundSuccessResponse = true;
188
+ }
189
+ }
190
+ if (!foundSuccessResponse) {
191
+ operation.responses["200"] = {
192
+ description: "OK",
193
+ content: {
194
+ "application/json": {
195
+ schema: {}
196
+ }
197
+ }
198
+ };
199
+ }
200
+ for (const status in operation.responses) {
201
+ const response = operation.responses[status];
202
+ const statusCode = +status;
203
+ const outputName = statusCode !== 200 ? pascalcase(operationId) + status : findUniqueSchemaName(spec, operationId, [
204
+ "output",
205
+ "payload",
206
+ "result"
207
+ ]);
208
+ if (!responsesConfig?.flattenErrorResponses) {
209
+ if (!isSuccessStatusCode(status)) {
210
+ continue;
211
+ }
212
+ }
213
+ if (isEmpty(response.content)) {
214
+ response.content = {
215
+ "application/octet-stream": {}
216
+ };
217
+ }
218
+ response["x-response-name"] = outputName;
219
+ for (const [contentType, mediaType] of Object.entries(
220
+ response.content
221
+ )) {
222
+ if (isRef(mediaType.schema)) {
223
+ const { model } = parseRef(mediaType.schema.$ref);
224
+ Object.assign(spec.components.schemas[model], {
225
+ "x-responsebody": true
226
+ // do not assign response ref to a group
227
+ // because they are supposed to be in a separate file only inlined
228
+ // schemas are grouped by operationId
229
+ });
230
+ response["x-response-name"] = model;
231
+ continue;
232
+ }
233
+ if (isSseContentType(contentType)) {
234
+ continue;
235
+ }
236
+ if (parseJsonContentType(contentType)) {
237
+ if (isEmpty(mediaType.schema)) {
238
+ spec.components.schemas[outputName] = {
239
+ type: "object",
240
+ additionalProperties: true
241
+ };
242
+ }
243
+ } else {
244
+ spec.components.schemas[outputName] = {
245
+ ...spec.components.schemas[outputName],
246
+ "x-stream": !isTextContentType(contentType)
247
+ };
248
+ }
249
+ spec.components.schemas[outputName] = {
250
+ ...spec.components.schemas[outputName],
251
+ ...mediaType.schema,
252
+ "x-responsebody": true,
253
+ "x-response-group": operationId
254
+ };
255
+ operation.responses[status].content[contentType].schema = {
256
+ $ref: `#/components/schemas/${outputName}`
257
+ };
258
+ }
259
+ }
260
+ return operation.responses;
261
+ }
262
+ function patchParameters(spec, schema, parameters, security) {
263
+ const securitySchemes = spec.components?.securitySchemes ?? {};
264
+ const securityOptions = securityToOptions(spec, security, securitySchemes);
265
+ let required = Array.isArray(schema.required) ? schema.required : [];
266
+ schema["x-properties"] ??= {};
267
+ for (const param of parameters) {
268
+ if (param.required) {
269
+ required.push(param.name);
270
+ }
271
+ schema["x-properties"][param.name] = {
272
+ "x-in": param.in,
273
+ ...isRef(param.schema) ? followRef(spec, param.schema.$ref) : param.schema ?? { type: "string" }
274
+ };
275
+ }
276
+ for (const param of securityOptions) {
277
+ required = required.filter((name) => name !== param.name);
278
+ schema["x-properties"][param.name] = {
279
+ "x-in": "header",
280
+ ...isRef(param.schema) ? followRef(spec, param.schema.$ref) : param.schema ?? { type: "string" }
281
+ };
282
+ }
283
+ schema["x-required"] = required;
284
+ }
285
+ function createOperation(options) {
286
+ const parameters = [];
287
+ if (!isEmpty(options.parameters)) {
288
+ const locations = ["query", "path", "header", "cookie"];
289
+ for (const location of locations) {
290
+ const locationParams = options.parameters[location];
291
+ if (locationParams) {
292
+ for (const [name, param] of Object.entries(locationParams)) {
293
+ parameters.push({
294
+ name,
295
+ in: location,
296
+ required: param.required ?? false,
297
+ schema: param.schema
298
+ });
299
+ }
300
+ }
301
+ }
302
+ }
303
+ const responses = {};
304
+ for (const [key, schema] of Object.entries(options.response)) {
305
+ const [statusCode, contentType] = key.split(/-(.*)/);
306
+ if (!contentType) {
307
+ throw new Error(
308
+ `Response key "${key}" must be in the format "statusCode-contentType"`
309
+ );
310
+ }
311
+ responses[statusCode] ??= {
312
+ description: `Response for ${statusCode}`,
313
+ content: {}
314
+ };
315
+ if (contentType === "headers") {
316
+ responses[statusCode].headers = schema;
317
+ } else {
318
+ responses[statusCode].content[contentType] = {
319
+ schema
320
+ };
321
+ }
322
+ }
323
+ let requestBody = void 0;
324
+ if (options.request) {
325
+ requestBody = { description: "Request body", content: {} };
326
+ for (const [contentType, schema] of Object.entries(options.request)) {
327
+ requestBody.content[contentType] = { schema };
328
+ }
329
+ }
330
+ return {
331
+ security: (options.security ?? []).map((name) => ({
332
+ [name]: []
333
+ })),
334
+ operationId: options.name,
335
+ tags: [options.group],
336
+ parameters,
337
+ responses,
338
+ requestBody
339
+ };
340
+ }
341
+ function tuneRequestBody(spec, operationId, operation, parameters, security) {
342
+ const inputName = findUniqueSchemaName(spec, operationId, [
343
+ "input",
344
+ "payload",
345
+ "request"
346
+ ]);
347
+ const requestBody = isRef(operation.requestBody) ? followRef(spec, operation.requestBody.$ref) : operation.requestBody ?? {
348
+ content: {},
349
+ required: false
350
+ };
351
+ if (isEmpty(requestBody.content)) {
352
+ const schema = {
353
+ "x-inputname": inputName,
354
+ "x-requestbody": true
355
+ };
356
+ patchParameters(spec, schema, parameters, security);
357
+ const tuned = {
358
+ ...requestBody,
359
+ content: {
360
+ "application/empty": {
361
+ schema: { $ref: `#/components/schemas/${inputName}` }
362
+ }
363
+ }
364
+ };
365
+ spec.components.schemas[inputName] = schema;
366
+ return tuned;
367
+ }
368
+ for (const contentType in requestBody.content) {
369
+ const mediaType = requestBody.content[contentType];
370
+ let schema;
371
+ switch (true) {
372
+ case isRef(mediaType.schema):
373
+ schema = followRef(spec, mediaType.schema.$ref);
374
+ break;
375
+ case isEmpty(mediaType.schema):
376
+ schema ??= {};
377
+ console.warn(
378
+ `Request body schema for content type "${contentType}" is empty.`
379
+ );
380
+ break;
381
+ default:
382
+ schema = mediaType.schema;
383
+ break;
384
+ }
385
+ patchParameters(spec, schema, parameters, security);
386
+ spec.components.schemas[inputName] = {
387
+ ...schema,
388
+ "x-requestbody": true,
389
+ "x-inputname": inputName
390
+ };
391
+ requestBody.content[contentType].schema = {
392
+ $ref: `#/components/schemas/${inputName}`
393
+ };
394
+ }
395
+ return requestBody;
396
+ }
397
+ export {
398
+ augmentSpec,
399
+ createOperation,
400
+ patchParameters
401
+ };
402
+ //# sourceMappingURL=operation.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/operation.ts"],
4
+ "sourcesContent": ["import type {\n MediaTypeObject,\n OperationObject,\n ParameterObject,\n PathsObject,\n ReferenceObject,\n RequestBodyObject,\n ResponseObject,\n ResponsesObject,\n SchemaObject,\n SecurityRequirementObject,\n} from 'openapi3-ts/oas31';\n\nimport { type Method, methods } from '@sdk-it/core/paths.js';\nimport { followRef, isRef, parseRef, resolveRef } from '@sdk-it/core/ref.js';\nimport { isEmpty, pascalcase, snakecase } from '@sdk-it/core/utils.js';\n\nimport { findUniqueSchemaName } from './find-unique-schema-name.js';\nimport {\n isSseContentType,\n isSuccessStatusCode,\n isTextContentType,\n parseJsonContentType,\n} from './is.js';\nimport {\n type GenerateSdkConfig,\n type ResponsesConfig,\n coeraceConfig,\n} from './options.js';\nimport { extractOverviewDocs } from './overview-docs.js';\nimport {\n type PaginationGuess,\n guessPagination,\n} from './pagination/pagination.js';\nimport { securityToOptions } from './security.js';\nimport { expandSpec, fixSpec } from './tune.js';\nimport type {\n OurOpenAPIObject,\n OurRequestBodyObject,\n TunedOperationObject,\n} from './types.js';\n\nfunction findUniqueOperationId(\n usedOperationIds: Set<string>,\n initialId: string,\n choices: string[],\n formatter: (id: string) => string,\n) {\n let counter = 1;\n let uniqueOperationId = formatter(initialId);\n\n while (usedOperationIds.has(uniqueOperationId)) {\n // Try each prepend option\n const prependIndex = Math.min(counter - 1, choices.length - 1);\n const prefix = choices[prependIndex];\n\n if (prependIndex < choices.length - 1) {\n // Using one of the prepend options\n uniqueOperationId = formatter(\n `${prefix}${initialId.charAt(0).toUpperCase() + initialId.slice(1)}`,\n );\n } else {\n // If we've exhausted all prepend options, start adding numbers\n uniqueOperationId = formatter(\n `${prefix}${initialId.charAt(0).toUpperCase() + initialId.slice(1)}${counter - choices.length + 1}`,\n );\n }\n counter++;\n }\n\n return uniqueOperationId;\n}\n\nexport function augmentSpec(\n config: GenerateSdkConfig,\n verbose = false,\n): OurOpenAPIObject {\n const coearcedConfig = coeraceConfig(config);\n if ('x-sdk-augmented' in config.spec) {\n return config.spec as OurOpenAPIObject; // Already augmented\n }\n const spec: OurOpenAPIObject = {\n ...config.spec,\n components: {\n ...config.spec.components,\n schemas: config.spec.components?.schemas ?? {},\n securitySchemes: config.spec.components?.securitySchemes ?? {},\n },\n paths: config.spec.paths ?? {},\n 'x-docs': [],\n };\n\n const paths: PathsObject = {};\n const usedOperationIds = new Set<string>();\n\n for (const [path, pathItem] of Object.entries(spec.paths)) {\n // Convert Express-style routes (:param) to OpenAPI-style routes ({param})\n const fixedPath = path.replace(/:([^/]+)/g, '{$1}');\n for (const [method, operation] of Object.entries(pathItem) as [\n Method,\n OperationObject,\n ][]) {\n if (!methods.includes(method)) {\n continue;\n }\n const operationTag = coearcedConfig.tag(operation, fixedPath);\n const operationId = findUniqueOperationId(\n usedOperationIds,\n coearcedConfig.operationId(operation, fixedPath, method),\n [operationTag, method, fixedPath.split('/').filter(Boolean).join('')],\n (id) =>\n coearcedConfig.operationId(\n { ...operation, operationId: id },\n fixedPath,\n method,\n ),\n );\n usedOperationIds.add(operationId);\n\n const parameters = [\n ...(pathItem.parameters ?? []),\n ...(operation.parameters ?? []),\n ].map((it) => resolveRef<ParameterObject>(spec, it));\n\n const tunedOperation: TunedOperationObject = {\n ...operation,\n parameters,\n tags: [snakecase(operationTag)],\n operationId: operationId,\n responses: resolveResponses(\n spec,\n operationId,\n operation,\n config.responses,\n ),\n requestBody: tuneRequestBody(\n spec,\n operationId,\n operation,\n parameters,\n operation.security ?? [],\n ),\n };\n\n if (coearcedConfig.pagination.enabled) {\n if (coearcedConfig.pagination.guess) {\n tunedOperation['x-pagination'] = toPagination(spec, tunedOperation);\n }\n } else {\n delete tunedOperation['x-pagination'];\n }\n\n Object.assign(paths, {\n [fixedPath]: {\n ...paths[fixedPath],\n [method]: tunedOperation,\n },\n });\n }\n }\n\n fixSpec(spec, Object.values(spec.components.schemas));\n\n if (verbose) {\n const newRefs: { name: string; value: SchemaObject }[] = [];\n expandSpec(spec, spec.components.schemas, newRefs);\n }\n\n return {\n ...(spec as OurOpenAPIObject),\n paths,\n 'x-docs': extractOverviewDocs(spec),\n 'x-sdk-augmented': true,\n };\n}\n\nexport type OperationPagination = PaginationGuess & {\n items: string;\n};\n\nfunction toPagination(\n spec: OurOpenAPIObject,\n tunedOperation: TunedOperationObject,\n) {\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;\n }\n return undefined;\n}\n\nfunction getResponseContentSchema(\n spec: OurOpenAPIObject,\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: OurOpenAPIObject,\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\nfunction resolveResponses(\n spec: OurOpenAPIObject,\n operationId: string,\n operation: OperationObject,\n responsesConfig?: ResponsesConfig,\n) {\n const responses = operation.responses ?? {};\n operation.responses ??= {};\n let foundSuccessResponse = false;\n for (const status in responses) {\n if (status === 'default') {\n delete responses[status]; // Skip default response\n continue;\n }\n // use structuredClone to avoid mutating a response object\n // that is referenced by multiple operations\n operation.responses[status] = structuredClone(\n resolveRef<ResponseObject>(spec, responses[status]),\n );\n\n if (isSuccessStatusCode(status)) {\n foundSuccessResponse = true;\n }\n }\n\n if (!foundSuccessResponse) {\n operation.responses['200'] = {\n description: 'OK',\n content: {\n 'application/json': {\n schema: {},\n },\n },\n };\n }\n\n for (const status in operation.responses) {\n const response = operation.responses[status] as ResponseObject;\n const statusCode = +status;\n\n const outputName =\n statusCode !== 200\n ? pascalcase(operationId) + status\n : findUniqueSchemaName(spec, operationId, [\n 'output',\n 'payload',\n 'result',\n ]);\n\n if (!responsesConfig?.flattenErrorResponses) {\n if (!isSuccessStatusCode(status)) {\n continue;\n }\n }\n\n if (isEmpty(response.content)) {\n response.content = {\n 'application/octet-stream': {},\n };\n }\n\n response['x-response-name'] = outputName;\n\n // if (isErrorStatusCode(status)) {\n // const mediaType = response.content?.['application/json'];\n // if (mediaType && isRef(mediaType.schema)) {\n // const { model } = parseRef(mediaType.schema.$ref);\n // Object.assign(config.spec.components.schemas[model], {\n // 'x-responsebody': true,\n // // do not assign response ref to a group\n // // because they are supposed to be in a separate file only inlined\n // // schemas are grouped by operationId\n // });\n // response['x-response-name'] = model;\n // }\n // continue;\n // }\n\n for (const [contentType, mediaType] of Object.entries(\n response.content as Record<string, MediaTypeObject>,\n )) {\n if (isRef(mediaType.schema)) {\n const { model } = parseRef(mediaType.schema.$ref);\n Object.assign(spec.components.schemas[model], {\n 'x-responsebody': true,\n // do not assign response ref to a group\n // because they are supposed to be in a separate file only inlined\n // schemas are grouped by operationId\n });\n response['x-response-name'] = model;\n continue;\n }\n if (isSseContentType(contentType)) {\n continue; // Skip SSE content types\n }\n if (parseJsonContentType(contentType)) {\n if (isEmpty(mediaType.schema)) {\n // add \"additionalProperties\" because we're certain this is a response body is of json type\n spec.components.schemas[outputName] = {\n type: 'object',\n additionalProperties: true,\n };\n }\n } else {\n spec.components.schemas[outputName] = {\n ...spec.components.schemas[outputName],\n 'x-stream': !isTextContentType(contentType),\n };\n }\n\n spec.components.schemas[outputName] = {\n ...spec.components.schemas[outputName],\n ...mediaType.schema,\n 'x-responsebody': true,\n 'x-response-group': operationId,\n };\n operation.responses[status].content[contentType].schema = {\n $ref: `#/components/schemas/${outputName}`,\n };\n }\n }\n\n return operation.responses;\n}\n\nexport function patchParameters(\n spec: OurOpenAPIObject,\n schema: SchemaObject,\n parameters: ParameterObject[],\n security: SecurityRequirementObject[],\n) {\n const securitySchemes = spec.components?.securitySchemes ?? {};\n const securityOptions = securityToOptions(spec, security, securitySchemes);\n\n let required = Array.isArray(schema.required) ? schema.required : [];\n schema['x-properties'] ??= {};\n for (const param of parameters) {\n if (param.required) {\n required.push(param.name);\n }\n schema['x-properties'][param.name] = {\n 'x-in': param.in,\n ...(isRef(param.schema)\n ? followRef<SchemaObject>(spec, param.schema.$ref)\n : (param.schema ?? { type: 'string' })),\n };\n }\n for (const param of securityOptions) {\n required = required.filter((name) => name !== param.name);\n schema['x-properties'][param.name] = {\n 'x-in': 'header',\n ...(isRef(param.schema)\n ? followRef<SchemaObject>(spec, param.schema.$ref)\n : (param.schema ?? { type: 'string' })),\n };\n }\n schema['x-required'] = required;\n}\n\nexport function createOperation(options: {\n name: string;\n group: string;\n security?: string[];\n parameters?: {\n query?: Record<string, { schema: SchemaObject; required?: boolean }>;\n path?: Record<string, { schema: SchemaObject; required?: boolean }>;\n header?: Record<string, { schema: SchemaObject; required?: boolean }>;\n cookie?: Record<string, { schema: SchemaObject; required?: boolean }>;\n };\n response: Record<string, SchemaObject | Record<string, SchemaObject>>; // Key is statusCode-contentType\n request?: Record<string, ReferenceObject>;\n}): TunedOperationObject {\n const parameters: ParameterObject[] = [];\n if (!isEmpty(options.parameters)) {\n const locations = ['query', 'path', 'header', 'cookie'] as const;\n for (const location of locations) {\n const locationParams = options.parameters[location];\n if (locationParams) {\n for (const [name, param] of Object.entries(locationParams)) {\n parameters.push({\n name,\n in: location,\n required: param.required ?? false,\n schema: param.schema,\n });\n }\n }\n }\n }\n const responses: ResponsesObject = {};\n\n for (const [key, schema] of Object.entries(options.response)) {\n const [statusCode, contentType] = key.split(/-(.*)/); // Split on the first dash\n if (!contentType) {\n throw new Error(\n `Response key \"${key}\" must be in the format \"statusCode-contentType\"`,\n );\n }\n responses[statusCode] ??= {\n description: `Response for ${statusCode}`,\n content: {},\n };\n\n if (contentType === 'headers') {\n responses[statusCode].headers = schema;\n } else {\n responses[statusCode].content[contentType] = {\n schema: schema,\n };\n }\n }\n\n let requestBody: OurRequestBodyObject | undefined = undefined;\n\n if (options.request) {\n requestBody = { description: 'Request body', content: {} };\n\n for (const [contentType, schema] of Object.entries(options.request)) {\n requestBody.content[contentType] = { schema: schema };\n }\n }\n return {\n security: (options.security ?? []).map((name) => ({\n [name]: [],\n })),\n operationId: options.name,\n tags: [options.group],\n parameters,\n responses,\n requestBody: requestBody as any,\n };\n}\n\nfunction tuneRequestBody(\n spec: OurOpenAPIObject,\n operationId: string,\n operation: OperationObject,\n parameters: ParameterObject[],\n security: SecurityRequirementObject[],\n): OurRequestBodyObject {\n const inputName = findUniqueSchemaName(spec, operationId, [\n 'input',\n 'payload',\n 'request',\n ]);\n const requestBody = isRef(operation.requestBody)\n ? followRef<RequestBodyObject>(spec, operation.requestBody.$ref)\n : (operation.requestBody ?? {\n content: {},\n required: false,\n });\n if (isEmpty(requestBody.content)) {\n const schema: SchemaObject = {\n 'x-inputname': inputName,\n 'x-requestbody': true,\n };\n patchParameters(spec, schema, parameters, security);\n const tuned: OurRequestBodyObject = {\n ...requestBody,\n content: {\n 'application/empty': {\n schema: { $ref: `#/components/schemas/${inputName}` },\n },\n },\n };\n\n spec.components.schemas[inputName] = schema;\n return tuned;\n }\n for (const contentType in requestBody.content) {\n const mediaType = requestBody.content[contentType];\n let schema: SchemaObject | undefined;\n\n switch (true) {\n case isRef(mediaType.schema):\n schema = followRef<SchemaObject>(spec, mediaType.schema.$ref);\n // we cannot use the model name as inputName as it might be used in other places that are not request bodies\n // inputName = parseRef(mediaType.schema.$ref).model;\n break;\n case isEmpty(mediaType.schema):\n schema ??= {}; // default to empty schema if not defined\n console.warn(\n `Request body schema for content type \"${contentType}\" is empty.`,\n );\n break;\n default:\n schema = mediaType.schema;\n break;\n }\n\n patchParameters(spec, schema, parameters, security);\n spec.components.schemas[inputName] = {\n ...schema,\n 'x-requestbody': true,\n 'x-inputname': inputName,\n };\n\n requestBody.content[contentType].schema = {\n $ref: `#/components/schemas/${inputName}`,\n };\n }\n return requestBody as OurRequestBodyObject;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }