@sdk-it/spec 0.25.0 → 0.26.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 (50) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +3 -0
  4. package/dist/index.js.map +2 -2
  5. package/dist/lib/create-operation.d.ts +28 -0
  6. package/dist/lib/create-operation.d.ts.map +1 -0
  7. package/dist/lib/create-operation.js +62 -0
  8. package/dist/lib/create-operation.js.map +7 -0
  9. package/dist/lib/for-each-operation.d.ts.map +1 -1
  10. package/dist/lib/for-each-operation.js +0 -3
  11. package/dist/lib/for-each-operation.js.map +2 -2
  12. package/dist/lib/guess/guess-resource.d.ts +7 -0
  13. package/dist/lib/guess/guess-resource.d.ts.map +1 -0
  14. package/dist/lib/guess/guess-resource.js +76 -0
  15. package/dist/lib/guess/guess-resource.js.map +7 -0
  16. package/dist/lib/metadata.test.js +359 -0
  17. package/dist/lib/metadata.test.js.map +7 -0
  18. package/dist/lib/operation.d.ts +1 -32
  19. package/dist/lib/operation.d.ts.map +1 -1
  20. package/dist/lib/operation.js +32 -312
  21. package/dist/lib/operation.js.map +2 -2
  22. package/dist/lib/options.d.ts +42 -1
  23. package/dist/lib/options.d.ts.map +1 -1
  24. package/dist/lib/options.js +23 -8
  25. package/dist/lib/options.js.map +2 -2
  26. package/dist/lib/pagination/guess-pagination.d.ts +50 -0
  27. package/dist/lib/pagination/guess-pagination.d.ts.map +1 -0
  28. package/dist/lib/pagination/guess-pagination.js +222 -0
  29. package/dist/lib/pagination/guess-pagination.js.map +7 -0
  30. package/dist/lib/pagination/pagination.d.ts +2 -49
  31. package/dist/lib/pagination/pagination.d.ts.map +1 -1
  32. package/dist/lib/pagination/pagination.js +43 -209
  33. package/dist/lib/pagination/pagination.js.map +2 -2
  34. package/dist/lib/pagination/pagination.test.js +2 -1
  35. package/dist/lib/pagination/pagination.test.js.map +2 -2
  36. package/dist/lib/sidebar.d.ts +4 -23
  37. package/dist/lib/sidebar.d.ts.map +1 -1
  38. package/dist/lib/sidebar.js +22 -65
  39. package/dist/lib/sidebar.js.map +3 -3
  40. package/dist/lib/tune-request-body.d.ts +5 -0
  41. package/dist/lib/tune-request-body.d.ts.map +1 -0
  42. package/dist/lib/tune-request-body.js +88 -0
  43. package/dist/lib/tune-request-body.js.map +7 -0
  44. package/dist/lib/tune-response.d.ts +5 -0
  45. package/dist/lib/tune-response.d.ts.map +1 -0
  46. package/dist/lib/tune-response.js +102 -0
  47. package/dist/lib/tune-response.js.map +7 -0
  48. package/dist/lib/types.d.ts +8 -3
  49. package/dist/lib/types.d.ts.map +1 -1
  50. package/package.json +2 -2
@@ -1,21 +1,12 @@
1
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";
2
+ import { resolveRef } from "@sdk-it/core/ref.js";
3
+ import { snakecase } from "@sdk-it/core/utils.js";
4
+ import { toResource } from "./guess/guess-resource.js";
5
+ import { coeraceConfig } from "./options.js";
14
6
  import { extractOverviewDocs } from "./overview-docs.js";
15
- import {
16
- guessPagination
17
- } from "./pagination/pagination.js";
18
- import { securityToOptions } from "./security.js";
7
+ import { toPagination } from "./pagination/pagination.js";
8
+ import { tuneRequestBody } from "./tune-request-body.js";
9
+ import { resolveResponses } from "./tune-response.js";
19
10
  import { expandSpec, fixSpec } from "./tune.js";
20
11
  function findUniqueOperationId(usedOperationIds, initialId, choices, formatter) {
21
12
  let counter = 1;
@@ -41,24 +32,15 @@ function augmentSpec(config, verbose = false) {
41
32
  if ("x-sdk-augmented" in config.spec) {
42
33
  return config.spec;
43
34
  }
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
35
  const paths = {};
55
36
  const usedOperationIds = /* @__PURE__ */ new Set();
56
- for (const [path, pathItem] of Object.entries(spec.paths)) {
37
+ for (const [path, pathItem] of Object.entries(coearcedConfig.spec.paths)) {
57
38
  const fixedPath = path.replace(/:([^/]+)/g, "{$1}");
58
39
  for (const [method, operation] of Object.entries(pathItem)) {
59
40
  if (!methods.includes(method)) {
60
41
  continue;
61
42
  }
43
+ const { name } = toResource(operation, fixedPath, method);
62
44
  const operationTag = coearcedConfig.tag(operation, fixedPath);
63
45
  const operationId = findUniqueOperationId(
64
46
  usedOperationIds,
@@ -74,21 +56,24 @@ function augmentSpec(config, verbose = false) {
74
56
  const parameters = [
75
57
  ...pathItem.parameters ?? [],
76
58
  ...operation.parameters ?? []
77
- ].map((it) => resolveRef(spec, it));
59
+ ].map((it) => resolveRef(coearcedConfig.spec, it));
78
60
  const tunedOperation = {
79
61
  ...operation,
80
62
  parameters,
63
+ "x-fn-name": name,
64
+ "x-fn-group": operationTag,
81
65
  tags: [snakecase(operationTag)],
82
66
  operationId,
83
67
  responses: resolveResponses(
84
- spec,
68
+ coearcedConfig.spec,
85
69
  operationId,
86
70
  operation,
87
- config.responses
71
+ coearcedConfig.responses
88
72
  ),
89
73
  requestBody: tuneRequestBody(
90
- spec,
74
+ coearcedConfig.spec,
91
75
  operationId,
76
+ // camelcase(`${name} ${operationTag}`),
92
77
  operation,
93
78
  parameters,
94
79
  operation.security ?? []
@@ -96,7 +81,10 @@ function augmentSpec(config, verbose = false) {
96
81
  };
97
82
  if (coearcedConfig.pagination.enabled) {
98
83
  if (coearcedConfig.pagination.guess) {
99
- tunedOperation["x-pagination"] = toPagination(spec, tunedOperation);
84
+ tunedOperation["x-pagination"] = toPagination(
85
+ coearcedConfig.spec,
86
+ tunedOperation
87
+ );
100
88
  }
101
89
  } else {
102
90
  delete tunedOperation["x-pagination"];
@@ -109,294 +97,26 @@ function augmentSpec(config, verbose = false) {
109
97
  });
110
98
  }
111
99
  }
112
- fixSpec(spec, Object.values(spec.components.schemas));
100
+ fixSpec(
101
+ coearcedConfig.spec,
102
+ Object.values(coearcedConfig.spec.components.schemas)
103
+ );
113
104
  if (verbose) {
114
105
  const newRefs = [];
115
- expandSpec(spec, spec.components.schemas, newRefs);
106
+ expandSpec(
107
+ coearcedConfig.spec,
108
+ coearcedConfig.spec.components.schemas,
109
+ newRefs
110
+ );
116
111
  }
117
112
  return {
118
- ...spec,
113
+ ...coearcedConfig.spec,
119
114
  paths,
120
- "x-docs": extractOverviewDocs(spec),
115
+ "x-docs": extractOverviewDocs(coearcedConfig.spec),
121
116
  "x-sdk-augmented": true
122
117
  };
123
118
  }
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
119
  export {
398
- augmentSpec,
399
- createOperation,
400
- patchParameters
120
+ augmentSpec
401
121
  };
402
122
  //# sourceMappingURL=operation.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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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",
4
+ "sourcesContent": ["import type {\n OperationObject,\n ParameterObject,\n PathsObject,\n SchemaObject,\n} from 'openapi3-ts/oas31';\n\nimport { type Method, methods } from '@sdk-it/core/paths.js';\nimport { resolveRef } from '@sdk-it/core/ref.js';\nimport { snakecase } from '@sdk-it/core/utils.js';\n\nimport { toResource } from './guess/guess-resource.js';\nimport { type GenerateSdkConfig, coeraceConfig } from './options.js';\nimport { extractOverviewDocs } from './overview-docs.js';\nimport { toPagination } from './pagination/pagination.js';\nimport { tuneRequestBody } from './tune-request-body.js';\nimport { resolveResponses } from './tune-response.js';\nimport { expandSpec, fixSpec } from './tune.js';\nimport type { OurOpenAPIObject, TunedOperationObject } 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\n const paths: PathsObject = {};\n const usedOperationIds = new Set<string>();\n\n for (const [path, pathItem] of Object.entries(coearcedConfig.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 { name } = toResource(operation, fixedPath, method);\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>(coearcedConfig.spec, it));\n\n const tunedOperation: TunedOperationObject = {\n ...operation,\n parameters,\n 'x-fn-name': name,\n 'x-fn-group': operationTag,\n tags: [snakecase(operationTag)],\n operationId: operationId,\n responses: resolveResponses(\n coearcedConfig.spec,\n operationId,\n operation,\n coearcedConfig.responses,\n ),\n requestBody: tuneRequestBody(\n coearcedConfig.spec,\n operationId,\n // camelcase(`${name} ${operationTag}`),\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(\n coearcedConfig.spec,\n tunedOperation,\n );\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(\n coearcedConfig.spec,\n Object.values(coearcedConfig.spec.components.schemas),\n );\n\n if (verbose) {\n const newRefs: { name: string; value: SchemaObject }[] = [];\n expandSpec(\n coearcedConfig.spec,\n coearcedConfig.spec.components.schemas,\n newRefs,\n );\n }\n\n return {\n ...coearcedConfig.spec,\n paths,\n 'x-docs': extractOverviewDocs(coearcedConfig.spec),\n 'x-sdk-augmented': true,\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -12,6 +12,7 @@ export interface ResponsesConfig {
12
12
  export type PaginationConfig = {
13
13
  guess?: boolean;
14
14
  };
15
+ export declare function cleanOperationId(operationId: string): string;
15
16
  export declare const defaults: Partial<GenerateSdkConfig> & Required<Pick<GenerateSdkConfig, 'operationId' | 'tag'>>;
16
17
  export declare function coeraceConfig(config: GenerateSdkConfig): {
17
18
  pagination: {
@@ -19,7 +20,47 @@ export declare function coeraceConfig(config: GenerateSdkConfig): {
19
20
  enabled: boolean;
20
21
  };
21
22
  responses: ResponsesConfig;
22
- spec: OpenAPIObject;
23
+ spec: {
24
+ components: {
25
+ schemas: {
26
+ [schema: string]: import("openapi3-ts/oas31").SchemaObject | import("openapi3-ts/oas31").ReferenceObject;
27
+ };
28
+ securitySchemes: {
29
+ [securityScheme: string]: import("openapi3-ts/oas31").ReferenceObject | import("openapi3-ts/oas31").SecuritySchemeObject;
30
+ };
31
+ responses?: {
32
+ [response: string]: import("openapi3-ts/oas31").ResponseObject | import("openapi3-ts/oas31").ReferenceObject;
33
+ };
34
+ parameters?: {
35
+ [parameter: string]: import("openapi3-ts/oas31").ParameterObject | import("openapi3-ts/oas31").ReferenceObject;
36
+ };
37
+ examples?: {
38
+ [example: string]: import("openapi3-ts/oas31").ExampleObject | import("openapi3-ts/oas31").ReferenceObject;
39
+ };
40
+ requestBodies?: {
41
+ [request: string]: import("openapi3-ts/oas31").RequestBodyObject | import("openapi3-ts/oas31").ReferenceObject;
42
+ };
43
+ headers?: {
44
+ [header: string]: import("openapi3-ts/oas31").HeaderObject | import("openapi3-ts/oas31").ReferenceObject;
45
+ };
46
+ links?: {
47
+ [link: string]: import("openapi3-ts/oas31").LinkObject | import("openapi3-ts/oas31").ReferenceObject;
48
+ };
49
+ callbacks?: {
50
+ [callback: string]: import("openapi3-ts/oas31").CallbackObject | import("openapi3-ts/oas31").ReferenceObject;
51
+ };
52
+ };
53
+ paths: import("openapi3-ts/oas31").PathsObject;
54
+ 'x-docs': never[];
55
+ 'x-tagGroups': any;
56
+ openapi: string;
57
+ info: import("openapi3-ts/oas31").InfoObject;
58
+ servers?: import("openapi3-ts/oas31").ServerObject[];
59
+ security?: import("openapi3-ts/oas31").SecurityRequirementObject[];
60
+ tags?: import("openapi3-ts/oas31").TagObject[];
61
+ externalDocs?: import("openapi3-ts/oas31").ExternalDocumentationObject;
62
+ webhooks?: import("openapi3-ts/oas31").PathsObject;
63
+ };
23
64
  operationId: (operation: OperationObject, path: string, method: string) => string;
24
65
  tag: (operation: OperationObject, path: string) => string;
25
66
  };
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/lib/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAKxE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,UAAU,CAAC,EAAE,gBAAgB,GAAG,KAAK,CAAC;IACtC,WAAW,CAAC,EAAE,CACZ,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,KACX,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC5D;AACD,MAAM,WAAW,eAAe;IAC9B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAC/C,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,aAAa,GAAG,KAAK,CAAC,CA0BxD,CAAC;AAEF,wBAAgB,aAAa,CAAC,MAAM,EAAE,iBAAiB;;;;;;;6BA3CxC,eAAe,QACpB,MAAM,UACJ,MAAM,KACX,MAAM;qBACO,eAAe,QAAQ,MAAM,KAAK,MAAM;EA+C3D;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,gBAAgB,GAAG,SAAS,GAAG,KAAK;;;EAmB9C"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/lib/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAMxE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,UAAU,CAAC,EAAE,gBAAgB,GAAG,KAAK,CAAC;IACtC,WAAW,CAAC,EAAE,CACZ,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,KACX,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC5D;AACD,MAAM,WAAW,eAAe;IAC9B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,UAOnD;AAED,eAAO,MAAM,QAAQ,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAC/C,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,aAAa,GAAG,KAAK,CAAC,CAkBxD,CAAC;AAEF,wBAAgB,aAAa,CAAC,MAAM,EAAE,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BA5CxC,eAAe,QACpB,MAAM,UACJ,MAAM,KACX,MAAM;qBACO,eAAe,QAAQ,MAAM,KAAK,MAAM;EA+D3D;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,gBAAgB,GAAG,SAAS,GAAG,KAAK;;;EAmB9C"}
@@ -1,15 +1,14 @@
1
1
  import { camelcase } from "stringcase";
2
2
  import { determineGenericTag, sanitizeTag } from "./tag.js";
3
+ function cleanOperationId(operationId) {
4
+ return camelcase(
5
+ operationId.split("#").pop().replace(/-(?=\d)/g, "")
6
+ );
7
+ }
3
8
  const defaults = {
4
9
  operationId: (operation, path, method) => {
5
10
  if (operation.operationId) {
6
- return camelcase(
7
- operation.operationId.split("#").pop().replace(/-(?=\d)/g, "")
8
- );
9
- }
10
- const metadata = operation["x-oaiMeta"];
11
- if (metadata && metadata.name) {
12
- return camelcase(metadata.name);
11
+ return cleanOperationId(operation.operationId);
13
12
  }
14
13
  return camelcase(
15
14
  [method, ...path.replace(/[\\/\\{\\}]/g, " ").split(" ")].filter(Boolean).join(" ").trim()
@@ -23,7 +22,22 @@ function coeraceConfig(config) {
23
22
  return {
24
23
  pagination: coearcePaginationConfig(config.pagination),
25
24
  responses: config.responses ?? {},
26
- spec: config.spec,
25
+ spec: {
26
+ ...config.spec,
27
+ components: {
28
+ ...config.spec.components,
29
+ schemas: config.spec.components?.schemas ?? {},
30
+ securitySchemes: config.spec.components?.securitySchemes ?? {}
31
+ },
32
+ paths: config.spec.paths ?? {},
33
+ "x-docs": [],
34
+ "x-tagGroups": config.spec["x-tagGroups"] ?? [
35
+ {
36
+ name: "API",
37
+ tags: config.spec.tags?.map((tag) => tag.name) ?? []
38
+ }
39
+ ]
40
+ },
27
41
  operationId: config.operationId ?? defaults.operationId,
28
42
  tag: config.tag ?? defaults.tag
29
43
  };
@@ -47,6 +61,7 @@ function coearcePaginationConfig(options) {
47
61
  };
48
62
  }
49
63
  export {
64
+ cleanOperationId,
50
65
  coearcePaginationConfig,
51
66
  coeraceConfig,
52
67
  defaults
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/options.ts"],
4
- "sourcesContent": ["import type { OpenAPIObject, OperationObject } from 'openapi3-ts/oas31';\nimport { camelcase } from 'stringcase';\n\nimport { determineGenericTag, sanitizeTag } from './tag.js';\n\nexport interface GenerateSdkConfig {\n spec: OpenAPIObject;\n responses?: ResponsesConfig;\n pagination?: PaginationConfig | false;\n operationId?: (\n operation: OperationObject,\n path: string,\n method: string,\n ) => string;\n tag?: (operation: OperationObject, path: string) => string;\n}\nexport interface ResponsesConfig {\n flattenErrorResponses?: boolean;\n}\n\nexport type PaginationConfig = {\n guess?: boolean;\n};\n\nexport const defaults: Partial<GenerateSdkConfig> &\n Required<Pick<GenerateSdkConfig, 'operationId' | 'tag'>> = {\n operationId: (operation, path, method) => {\n if (operation.operationId) {\n return camelcase(\n operation.operationId\n .split('#')\n .pop()!\n .replace(/-(?=\\d)/g, ''),\n );\n }\n const metadata = operation['x-oaiMeta'];\n if (metadata && metadata.name) {\n return camelcase(metadata.name);\n }\n return camelcase(\n [method, ...path.replace(/[\\\\/\\\\{\\\\}]/g, ' ').split(' ')]\n .filter(Boolean)\n .join(' ')\n .trim(),\n );\n },\n tag: (operation, path) => {\n return operation.tags?.[0]\n ? sanitizeTag(operation.tags?.[0])\n : determineGenericTag(path, operation);\n },\n};\n\nexport function coeraceConfig(config: GenerateSdkConfig) {\n return {\n pagination: coearcePaginationConfig(config.pagination),\n responses: config.responses ?? {},\n spec: config.spec,\n operationId: config.operationId ?? defaults.operationId,\n tag: config.tag ?? defaults.tag,\n };\n}\n\nexport function coearcePaginationConfig(\n options: PaginationConfig | undefined | false,\n) {\n if (options === undefined) {\n return {\n guess: true,\n enabled: true,\n };\n }\n if (options === false) {\n return {\n enabled: false,\n guess: false,\n };\n }\n // If options is true, we assume pagination is enabled with guessing\n return {\n guess: options.guess ?? true,\n enabled: true,\n };\n}\n"],
5
- "mappings": "AACA,SAAS,iBAAiB;AAE1B,SAAS,qBAAqB,mBAAmB;AAqB1C,MAAM,WACgD;AAAA,EAC3D,aAAa,CAAC,WAAW,MAAM,WAAW;AACxC,QAAI,UAAU,aAAa;AACzB,aAAO;AAAA,QACL,UAAU,YACP,MAAM,GAAG,EACT,IAAI,EACJ,QAAQ,YAAY,EAAE;AAAA,MAC3B;AAAA,IACF;AACA,UAAM,WAAW,UAAU,WAAW;AACtC,QAAI,YAAY,SAAS,MAAM;AAC7B,aAAO,UAAU,SAAS,IAAI;AAAA,IAChC;AACA,WAAO;AAAA,MACL,CAAC,QAAQ,GAAG,KAAK,QAAQ,gBAAgB,GAAG,EAAE,MAAM,GAAG,CAAC,EACrD,OAAO,OAAO,EACd,KAAK,GAAG,EACR,KAAK;AAAA,IACV;AAAA,EACF;AAAA,EACA,KAAK,CAAC,WAAW,SAAS;AACxB,WAAO,UAAU,OAAO,CAAC,IACrB,YAAY,UAAU,OAAO,CAAC,CAAC,IAC/B,oBAAoB,MAAM,SAAS;AAAA,EACzC;AACF;AAEO,SAAS,cAAc,QAA2B;AACvD,SAAO;AAAA,IACL,YAAY,wBAAwB,OAAO,UAAU;AAAA,IACrD,WAAW,OAAO,aAAa,CAAC;AAAA,IAChC,MAAM,OAAO;AAAA,IACb,aAAa,OAAO,eAAe,SAAS;AAAA,IAC5C,KAAK,OAAO,OAAO,SAAS;AAAA,EAC9B;AACF;AAEO,SAAS,wBACd,SACA;AACA,MAAI,YAAY,QAAW;AACzB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,EACF;AACA,MAAI,YAAY,OAAO;AACrB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,QAAQ,SAAS;AAAA,IACxB,SAAS;AAAA,EACX;AACF;",
4
+ "sourcesContent": ["import type { OpenAPIObject, OperationObject } from 'openapi3-ts/oas31';\nimport { camelcase } from 'stringcase';\n\nimport { determineGenericTag, sanitizeTag } from './tag.js';\nimport type { OurOpenAPIObject } from './types.js';\n\nexport interface GenerateSdkConfig {\n spec: OpenAPIObject;\n responses?: ResponsesConfig;\n pagination?: PaginationConfig | false;\n operationId?: (\n operation: OperationObject,\n path: string,\n method: string,\n ) => string;\n tag?: (operation: OperationObject, path: string) => string;\n}\nexport interface ResponsesConfig {\n flattenErrorResponses?: boolean;\n}\n\nexport type PaginationConfig = {\n guess?: boolean;\n};\n\nexport function cleanOperationId(operationId: string) {\n return camelcase(\n operationId\n .split('#')\n .pop()!\n .replace(/-(?=\\d)/g, ''),\n );\n}\n\nexport const defaults: Partial<GenerateSdkConfig> &\n Required<Pick<GenerateSdkConfig, 'operationId' | 'tag'>> = {\n operationId: (operation, path, method) => {\n if (operation.operationId) {\n return cleanOperationId(operation.operationId);\n }\n\n return camelcase(\n [method, ...path.replace(/[\\\\/\\\\{\\\\}]/g, ' ').split(' ')]\n .filter(Boolean)\n .join(' ')\n .trim(),\n );\n },\n tag: (operation, path) => {\n return operation.tags?.[0]\n ? sanitizeTag(operation.tags?.[0])\n : determineGenericTag(path, operation);\n },\n};\n\nexport function coeraceConfig(config: GenerateSdkConfig) {\n return {\n pagination: coearcePaginationConfig(config.pagination),\n responses: config.responses ?? {},\n spec: {\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 'x-tagGroups': config.spec['x-tagGroups'] ?? [\n {\n name: 'API',\n tags: config.spec.tags?.map((tag) => tag.name) ?? [],\n },\n ],\n } satisfies OurOpenAPIObject,\n operationId: config.operationId ?? defaults.operationId,\n tag: config.tag ?? defaults.tag,\n };\n}\n\nexport function coearcePaginationConfig(\n options: PaginationConfig | undefined | false,\n) {\n if (options === undefined) {\n return {\n guess: true,\n enabled: true,\n };\n }\n if (options === false) {\n return {\n enabled: false,\n guess: false,\n };\n }\n // If options is true, we assume pagination is enabled with guessing\n return {\n guess: options.guess ?? true,\n enabled: true,\n };\n}\n"],
5
+ "mappings": "AACA,SAAS,iBAAiB;AAE1B,SAAS,qBAAqB,mBAAmB;AAsB1C,SAAS,iBAAiB,aAAqB;AACpD,SAAO;AAAA,IACL,YACG,MAAM,GAAG,EACT,IAAI,EACJ,QAAQ,YAAY,EAAE;AAAA,EAC3B;AACF;AAEO,MAAM,WACgD;AAAA,EAC3D,aAAa,CAAC,WAAW,MAAM,WAAW;AACxC,QAAI,UAAU,aAAa;AACzB,aAAO,iBAAiB,UAAU,WAAW;AAAA,IAC/C;AAEA,WAAO;AAAA,MACL,CAAC,QAAQ,GAAG,KAAK,QAAQ,gBAAgB,GAAG,EAAE,MAAM,GAAG,CAAC,EACrD,OAAO,OAAO,EACd,KAAK,GAAG,EACR,KAAK;AAAA,IACV;AAAA,EACF;AAAA,EACA,KAAK,CAAC,WAAW,SAAS;AACxB,WAAO,UAAU,OAAO,CAAC,IACrB,YAAY,UAAU,OAAO,CAAC,CAAC,IAC/B,oBAAoB,MAAM,SAAS;AAAA,EACzC;AACF;AAEO,SAAS,cAAc,QAA2B;AACvD,SAAO;AAAA,IACL,YAAY,wBAAwB,OAAO,UAAU;AAAA,IACrD,WAAW,OAAO,aAAa,CAAC;AAAA,IAChC,MAAM;AAAA,MACJ,GAAG,OAAO;AAAA,MACV,YAAY;AAAA,QACV,GAAG,OAAO,KAAK;AAAA,QACf,SAAS,OAAO,KAAK,YAAY,WAAW,CAAC;AAAA,QAC7C,iBAAiB,OAAO,KAAK,YAAY,mBAAmB,CAAC;AAAA,MAC/D;AAAA,MACA,OAAO,OAAO,KAAK,SAAS,CAAC;AAAA,MAC7B,UAAU,CAAC;AAAA,MACX,eAAe,OAAO,KAAK,aAAa,KAAK;AAAA,QAC3C;AAAA,UACE,MAAM;AAAA,UACN,MAAM,OAAO,KAAK,MAAM,IAAI,CAAC,QAAQ,IAAI,IAAI,KAAK,CAAC;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAAA,IACA,aAAa,OAAO,eAAe,SAAS;AAAA,IAC5C,KAAK,OAAO,OAAO,SAAS;AAAA,EAC9B;AACF;AAEO,SAAS,wBACd,SACA;AACA,MAAI,YAAY,QAAW;AACzB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,EACF;AACA,MAAI,YAAY,OAAO;AACrB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,QAAQ,SAAS;AAAA,IACxB,SAAS;AAAA,EACX;AACF;",
6
6
  "names": []
7
7
  }