@kubb/plugin-fetch 5.0.0-beta.98 → 5.0.0-beta.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +36 -160
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +36 -160
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -202,33 +202,17 @@ function buildJSDoc(comments, options = {}) {
|
|
|
202
202
|
}
|
|
203
203
|
//#endregion
|
|
204
204
|
//#region ../../internals/utils/src/url.ts
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
function
|
|
210
|
-
|
|
211
|
-
for (const match of path.matchAll(/\{([^}]+)\}/g)) {
|
|
212
|
-
const param = transformParam(match[1], casing);
|
|
213
|
-
const key = replacer ? replacer(param) : param;
|
|
214
|
-
params[key] = key;
|
|
215
|
-
}
|
|
216
|
-
return Object.keys(params).length > 0 ? params : null;
|
|
205
|
+
/**
|
|
206
|
+
* Keeps the OpenAPI parameter name as-is when it is already a valid JS identifier, and
|
|
207
|
+
* camelCases it only enough to become one otherwise (for example a hyphenated path segment).
|
|
208
|
+
*/
|
|
209
|
+
function transformParam(raw) {
|
|
210
|
+
return isValidVarName(raw) ? raw : camelCase(raw);
|
|
217
211
|
}
|
|
218
212
|
/**
|
|
219
|
-
* Helpers for OpenAPI/Swagger paths
|
|
213
|
+
* Helpers for OpenAPI/Swagger paths.
|
|
220
214
|
*/
|
|
221
215
|
var Url = class Url {
|
|
222
|
-
/**
|
|
223
|
-
* Reports whether `url` is a parseable absolute URL. Delegates to the native `URL.canParse`.
|
|
224
|
-
*
|
|
225
|
-
* @example
|
|
226
|
-
* Url.canParse('https://petstore.swagger.io/v2') // true
|
|
227
|
-
* Url.canParse('/pet/{petId}') // false
|
|
228
|
-
*/
|
|
229
|
-
static canParse(url, base) {
|
|
230
|
-
return URL.canParse(url, base);
|
|
231
|
-
}
|
|
232
216
|
/**
|
|
233
217
|
* Converts an OpenAPI/Swagger path to Express-style colon syntax.
|
|
234
218
|
*
|
|
@@ -244,15 +228,14 @@ var Url = class Url {
|
|
|
244
228
|
* key.
|
|
245
229
|
*
|
|
246
230
|
* @example
|
|
247
|
-
* Url.
|
|
231
|
+
* Url.toSafeTemplate('/user/{monetary-account-id}') // '/user/{monetaryAccountId}'
|
|
248
232
|
*/
|
|
249
|
-
static
|
|
250
|
-
return path.replace(/\{([^}]+)\}/g, (_, name) => `{${transformParam(name
|
|
233
|
+
static toSafeTemplate(path) {
|
|
234
|
+
return path.replace(/\{([^}]+)\}/g, (_, name) => `{${transformParam(name)}}`);
|
|
251
235
|
}
|
|
252
236
|
/**
|
|
253
237
|
* Converts an OpenAPI/Swagger path to a TypeScript template literal string.
|
|
254
|
-
* `prefix` is prepended inside the literal, `replacer` transforms each parameter name
|
|
255
|
-
* and `casing` controls parameter identifier casing.
|
|
238
|
+
* `prefix` is prepended inside the literal, and `replacer` transforms each parameter name.
|
|
256
239
|
*
|
|
257
240
|
* @example
|
|
258
241
|
* Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'
|
|
@@ -260,10 +243,10 @@ var Url = class Url {
|
|
|
260
243
|
* @example
|
|
261
244
|
* Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'
|
|
262
245
|
*/
|
|
263
|
-
static toTemplateString(path, { prefix, replacer
|
|
246
|
+
static toTemplateString(path, { prefix, replacer } = {}) {
|
|
264
247
|
const result = path.split(/\{([^}]+)\}/).map((part, i) => {
|
|
265
248
|
if (i % 2 === 0) return part;
|
|
266
|
-
const param = transformParam(part
|
|
249
|
+
const param = transformParam(part);
|
|
267
250
|
return `\${${replacer ? replacer(param) : param}}`;
|
|
268
251
|
}).join("");
|
|
269
252
|
return `\`${prefix ?? ""}${result}\``;
|
|
@@ -271,8 +254,8 @@ var Url = class Url {
|
|
|
271
254
|
/**
|
|
272
255
|
* Converts an OpenAPI/Swagger path to a template literal that reads each parameter off the
|
|
273
256
|
* grouped `path` request option, e.g. `/pet/{petId}` becomes `` `/pet/${path.petId}` ``. Parameter
|
|
274
|
-
* names
|
|
275
|
-
*
|
|
257
|
+
* names match the generated `path` type, and `prefix` is prepended inside the literal. Shared by
|
|
258
|
+
* the client and cypress generators that pass a grouped `path` object.
|
|
276
259
|
*
|
|
277
260
|
* @example
|
|
278
261
|
* Url.toGroupedTemplateString('/pet/{petId}') // '`/pet/${path.petId}`'
|
|
@@ -280,103 +263,28 @@ var Url = class Url {
|
|
|
280
263
|
static toGroupedTemplateString(path, { prefix } = {}) {
|
|
281
264
|
return Url.toTemplateString(path, {
|
|
282
265
|
prefix,
|
|
283
|
-
casing: "camelcase",
|
|
284
266
|
replacer: (name) => `path.${name}`
|
|
285
267
|
});
|
|
286
268
|
}
|
|
287
|
-
/**
|
|
288
|
-
* Returns the path and its extracted params as a structured `URLObject`, or as a stringified
|
|
289
|
-
* expression when `stringify` is set.
|
|
290
|
-
*
|
|
291
|
-
* @example
|
|
292
|
-
* Url.toObject('/pet/{petId}')
|
|
293
|
-
* // { url: '/pet/:petId', params: { petId: 'petId' } }
|
|
294
|
-
*/
|
|
295
|
-
static toObject(path, { type = "path", replacer, stringify, casing } = {}) {
|
|
296
|
-
const object = {
|
|
297
|
-
url: type === "path" ? Url.toPath(path) : Url.toTemplateString(path, {
|
|
298
|
-
replacer,
|
|
299
|
-
casing
|
|
300
|
-
}),
|
|
301
|
-
params: toParamsObject(path, {
|
|
302
|
-
replacer,
|
|
303
|
-
casing
|
|
304
|
-
})
|
|
305
|
-
};
|
|
306
|
-
if (stringify) {
|
|
307
|
-
if (type === "template") return JSON.stringify(object).replaceAll("'", "").replaceAll(`"`, "");
|
|
308
|
-
if (object.params) return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll("'", "").replaceAll(`"`, "")} }`;
|
|
309
|
-
return `{ url: '${object.url}' }`;
|
|
310
|
-
}
|
|
311
|
-
return object;
|
|
312
|
-
}
|
|
313
269
|
};
|
|
314
270
|
//#endregion
|
|
315
271
|
//#region ../../internals/shared/src/params.ts
|
|
316
|
-
const caseParamsCache = /* @__PURE__ */ new WeakMap();
|
|
317
|
-
/**
|
|
318
|
-
* Applies camelCase to parameter names and returns a new array without mutating the input.
|
|
319
|
-
*
|
|
320
|
-
* Run it before handing parameters to schema builders so output property keys get the right casing
|
|
321
|
-
* while `OperationNode.parameters` stays intact for other consumers. When `casing` is unset, the
|
|
322
|
-
* original array is returned unchanged. Results are cached per input array.
|
|
323
|
-
*/
|
|
324
|
-
function caseParams(params, casing) {
|
|
325
|
-
if (!casing) return params;
|
|
326
|
-
const cached = caseParamsCache.get(params);
|
|
327
|
-
if (cached) return cached;
|
|
328
|
-
const result = params.map((param) => ({
|
|
329
|
-
...param,
|
|
330
|
-
name: camelCase(param.name)
|
|
331
|
-
}));
|
|
332
|
-
caseParamsCache.set(params, result);
|
|
333
|
-
return result;
|
|
334
|
-
}
|
|
335
272
|
/**
|
|
336
|
-
* Drops parameters that
|
|
273
|
+
* Drops parameters that share the same name, keeping the first.
|
|
337
274
|
*
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
275
|
+
* A malformed spec can declare the same parameter name twice within one `in` location. Both would
|
|
276
|
+
* resolve to the same output property, so emitting both would yield an object type with a duplicate
|
|
277
|
+
* member, which TypeScript rejects. This is a defensive guard against that case, not a casing guard:
|
|
278
|
+
* parameter names flow through unchanged, so no two distinct names ever collide here anymore.
|
|
342
279
|
*/
|
|
343
|
-
function
|
|
280
|
+
function dedupeParams(params) {
|
|
344
281
|
const seen = /* @__PURE__ */ new Set();
|
|
345
282
|
return params.filter((param) => {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
seen.add(key);
|
|
283
|
+
if (seen.has(param.name)) return false;
|
|
284
|
+
seen.add(param.name);
|
|
349
285
|
return true;
|
|
350
286
|
});
|
|
351
287
|
}
|
|
352
|
-
function buildParamsMapping(originalParams, mappedParams) {
|
|
353
|
-
const mapping = {};
|
|
354
|
-
let hasChanged = false;
|
|
355
|
-
originalParams.forEach((param, i) => {
|
|
356
|
-
const mappedName = mappedParams[i]?.name ?? param.name;
|
|
357
|
-
mapping[param.name] = mappedName;
|
|
358
|
-
if (param.name !== mappedName) hasChanged = true;
|
|
359
|
-
});
|
|
360
|
-
return hasChanged ? mapping : null;
|
|
361
|
-
}
|
|
362
|
-
function toAccess(object, name) {
|
|
363
|
-
return isValidVarName(name) ? `${object}.${name}` : `${object}[${JSON.stringify(name)}]`;
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* Renders the object-literal expression that renames the camelCased keys of a grouped request
|
|
367
|
-
* option back to the names the OpenAPI document declares, guarded so an omitted optional group
|
|
368
|
-
* stays omitted. Shared by the client and cypress generators, which pass a `buildParamsMapping`
|
|
369
|
-
* result and the source expression to read the keys from.
|
|
370
|
-
*
|
|
371
|
-
* @example
|
|
372
|
-
* ```ts
|
|
373
|
-
* buildParamsRemapExpression({ source: 'config.query', mapping: { include_deleted: 'includeDeleted' } })
|
|
374
|
-
* // 'config.query ? { "include_deleted": config.query.includeDeleted } : config.query'
|
|
375
|
-
* ```
|
|
376
|
-
*/
|
|
377
|
-
function buildParamsRemapExpression({ source, mapping }) {
|
|
378
|
-
return `${source} ? { ${Object.entries(mapping).map(([originalName, casedName]) => `${JSON.stringify(originalName)}: ${toAccess(source, casedName)}`).join(", ")} } : ${source}`;
|
|
379
|
-
}
|
|
380
288
|
//#endregion
|
|
381
289
|
//#region ../../internals/shared/src/operation.ts
|
|
382
290
|
/**
|
|
@@ -510,13 +418,15 @@ function buildOperationComments(node, options = {}) {
|
|
|
510
418
|
if (!splitLines) return filteredComments;
|
|
511
419
|
return filteredComments.flatMap((text) => text.split(/\r?\n/).map((line) => line.trim())).filter((comment) => Boolean(comment));
|
|
512
420
|
}
|
|
513
|
-
function getOperationParameters(node
|
|
514
|
-
const params = caseParams(node.parameters, options.paramsCasing === "original" ? void 0 : "camelcase");
|
|
421
|
+
function getOperationParameters(node) {
|
|
515
422
|
return {
|
|
516
|
-
path:
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
423
|
+
path: dedupeParams(node.parameters.filter((param) => param.in === "path").map((param) => isValidVarName(param.name) ? param : {
|
|
424
|
+
...param,
|
|
425
|
+
name: camelCase(param.name)
|
|
426
|
+
})),
|
|
427
|
+
query: dedupeParams(node.parameters.filter((param) => param.in === "query")),
|
|
428
|
+
header: dedupeParams(node.parameters.filter((param) => param.in === "header")),
|
|
429
|
+
cookie: dedupeParams(node.parameters.filter((param) => param.in === "cookie"))
|
|
520
430
|
};
|
|
521
431
|
}
|
|
522
432
|
function getStatusCodeNumber(statusCode) {
|
|
@@ -568,38 +478,6 @@ function createGroupConfig(group) {
|
|
|
568
478
|
};
|
|
569
479
|
}
|
|
570
480
|
//#endregion
|
|
571
|
-
//#region ../../internals/client/src/builders/paramsRemap.ts
|
|
572
|
-
/**
|
|
573
|
-
* Builds the call-config entries that rename the camelCased `query` and `headers` keys back to the
|
|
574
|
-
* names the OpenAPI document declares, so the wire format follows the spec while the generated
|
|
575
|
-
* types keep camelCase keys. Returns an empty array when no name changes. Path parameters need no
|
|
576
|
-
* remap because the URL template placeholders are renamed in sync with the `path` keys. Emit the
|
|
577
|
-
* entries after the `...config` spread so they override the camelCased groups the caller passes in.
|
|
578
|
-
*
|
|
579
|
-
* @example
|
|
580
|
-
* ```ts
|
|
581
|
-
* // a query param named include_deleted in the spec
|
|
582
|
-
* buildParamsRemap({ node }) // ['query: config.query ? { "include_deleted": config.query.includeDeleted } : config.query']
|
|
583
|
-
* ```
|
|
584
|
-
*/
|
|
585
|
-
function buildParamsRemap({ node }) {
|
|
586
|
-
if (!ast.isHttpOperationNode(node)) return [];
|
|
587
|
-
const original = getOperationParameters(node, { paramsCasing: "original" });
|
|
588
|
-
const cased = getOperationParameters(node);
|
|
589
|
-
const queryMapping = buildParamsMapping(original.query, cased.query);
|
|
590
|
-
const headerMapping = buildParamsMapping(original.header, cased.header);
|
|
591
|
-
const entries = [];
|
|
592
|
-
if (queryMapping) entries.push(`query: ${buildParamsRemapExpression({
|
|
593
|
-
source: "config.query",
|
|
594
|
-
mapping: queryMapping
|
|
595
|
-
})}`);
|
|
596
|
-
if (headerMapping) entries.push(`headers: ${buildParamsRemapExpression({
|
|
597
|
-
source: "config.headers",
|
|
598
|
-
mapping: headerMapping
|
|
599
|
-
})}`);
|
|
600
|
-
return entries;
|
|
601
|
-
}
|
|
602
|
-
//#endregion
|
|
603
481
|
//#region ../../internals/client/src/builders/generics.ts
|
|
604
482
|
/**
|
|
605
483
|
* Builds the `RequestResult` generic arguments for one operation: the plugin-ts per-status responses
|
|
@@ -831,11 +709,10 @@ function buildCallConfig({ node, validator, zodResolver, security }) {
|
|
|
831
709
|
const securityLiteral = buildSecurityMetadata({ security });
|
|
832
710
|
return `{ ${[
|
|
833
711
|
`method: '${node.method.toUpperCase()}'`,
|
|
834
|
-
`url: '${Url.
|
|
712
|
+
`url: '${Url.toSafeTemplate(node.path)}'`,
|
|
835
713
|
securityLiteral ? `security: ${securityLiteral}` : null,
|
|
836
714
|
validatorLiteral,
|
|
837
|
-
"...config"
|
|
838
|
-
...buildParamsRemap({ node })
|
|
715
|
+
"...config"
|
|
839
716
|
].filter(Boolean).join(", ")} }`;
|
|
840
717
|
}
|
|
841
718
|
/**
|
|
@@ -961,14 +838,13 @@ function Operation({ name, node, tsResolver, zodResolver, validator, security, i
|
|
|
961
838
|
const validatorLiteral = validatorEntries.length ? `validator: { ${validatorEntries.join(", ")} }` : null;
|
|
962
839
|
const callConfig = `{ ${[
|
|
963
840
|
`method: '${node.method.toUpperCase()}'`,
|
|
964
|
-
`url: '${Url.
|
|
841
|
+
`url: '${Url.toSafeTemplate(node.path)}'`,
|
|
965
842
|
securityLiteral ? `security: ${securityLiteral}` : null,
|
|
966
843
|
stylesLiteral ? `styles: ${stylesLiteral}` : null,
|
|
967
844
|
validatorLiteral,
|
|
968
845
|
contentTypeLiteral,
|
|
969
846
|
responseTypeLiteral,
|
|
970
|
-
"...config"
|
|
971
|
-
...buildParamsRemap({ node })
|
|
847
|
+
"...config"
|
|
972
848
|
].filter(Boolean).join(", ")} }`;
|
|
973
849
|
const eventType = `SuccessOf<${tsResolver.response.responses(node)}>`;
|
|
974
850
|
const returnType = eventStream ? `Promise<EventStreamResult<${eventType}>>` : signature.returnType;
|
|
@@ -1061,7 +937,7 @@ function resolveTypeImportNames(node, tsResolver) {
|
|
|
1061
937
|
return [tsResolver.response.options(node), tsResolver.response.responses(node)];
|
|
1062
938
|
}
|
|
1063
939
|
function resolveZodImportNames(node, zodResolver, validator) {
|
|
1064
|
-
const { query: queryParams } = getOperationParameters(node
|
|
940
|
+
const { query: queryParams } = getOperationParameters(node);
|
|
1065
941
|
return [
|
|
1066
942
|
resolveResponseValidator(validator) === "zod" ? zodResolver.response.response(node) : null,
|
|
1067
943
|
resolveResponseValidator(validator) === "zod" ? buildZodErrorParse(node, zodResolver)?.expression ?? null : null,
|