@kubb/plugin-swr 5.0.0-beta.95 → 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.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as __name } from "./rolldown-runtime-C0LytTxp.js";
2
+ import path from "node:path";
2
3
  import { Resolver, ast, createResolver, defineGenerator, definePlugin } from "kubb/kit";
3
4
  import { createFunctionParameter, createFunctionParameters, createObjectBindingPattern, createTypeLiteral, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
4
- import path from "node:path";
5
5
  import { File, Function, Type, jsxRenderer } from "kubb/jsx";
6
6
  import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
7
7
  //#region ../../internals/utils/src/casing.ts
@@ -161,33 +161,17 @@ function isIdentifier(name) {
161
161
  }
162
162
  //#endregion
163
163
  //#region ../../internals/utils/src/url.ts
164
- function transformParam(raw, casing) {
165
- const param = isValidVarName(raw) ? raw : camelCase(raw);
166
- return casing === "camelcase" ? camelCase(param) : param;
167
- }
168
- function toParamsObject(path, { replacer, casing } = {}) {
169
- const params = {};
170
- for (const match of path.matchAll(/\{([^}]+)\}/g)) {
171
- const param = transformParam(match[1], casing);
172
- const key = replacer ? replacer(param) : param;
173
- params[key] = key;
174
- }
175
- return Object.keys(params).length > 0 ? params : null;
164
+ /**
165
+ * Keeps the OpenAPI parameter name as-is when it is already a valid JS identifier, and
166
+ * camelCases it only enough to become one otherwise (for example a hyphenated path segment).
167
+ */
168
+ function transformParam(raw) {
169
+ return isValidVarName(raw) ? raw : camelCase(raw);
176
170
  }
177
171
  /**
178
- * Helpers for OpenAPI/Swagger paths, plus a thin wrapper over the native `URL`.
172
+ * Helpers for OpenAPI/Swagger paths.
179
173
  */
180
174
  var Url = class Url {
181
- /**
182
- * Reports whether `url` is a parseable absolute URL. Delegates to the native `URL.canParse`.
183
- *
184
- * @example
185
- * Url.canParse('https://petstore.swagger.io/v2') // true
186
- * Url.canParse('/pet/{petId}') // false
187
- */
188
- static canParse(url, base) {
189
- return URL.canParse(url, base);
190
- }
191
175
  /**
192
176
  * Converts an OpenAPI/Swagger path to Express-style colon syntax.
193
177
  *
@@ -203,15 +187,14 @@ var Url = class Url {
203
187
  * key.
204
188
  *
205
189
  * @example
206
- * Url.toCasedTemplate('/projects/{project_id}', { casing: 'camelcase' }) // '/projects/{projectId}'
190
+ * Url.toSafeTemplate('/user/{monetary-account-id}') // '/user/{monetaryAccountId}'
207
191
  */
208
- static toCasedTemplate(path, { casing } = {}) {
209
- return path.replace(/\{([^}]+)\}/g, (_, name) => `{${transformParam(name, casing)}}`);
192
+ static toSafeTemplate(path) {
193
+ return path.replace(/\{([^}]+)\}/g, (_, name) => `{${transformParam(name)}}`);
210
194
  }
211
195
  /**
212
196
  * Converts an OpenAPI/Swagger path to a TypeScript template literal string.
213
- * `prefix` is prepended inside the literal, `replacer` transforms each parameter name,
214
- * and `casing` controls parameter identifier casing.
197
+ * `prefix` is prepended inside the literal, and `replacer` transforms each parameter name.
215
198
  *
216
199
  * @example
217
200
  * Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'
@@ -219,10 +202,10 @@ var Url = class Url {
219
202
  * @example
220
203
  * Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'
221
204
  */
222
- static toTemplateString(path, { prefix, replacer, casing } = {}) {
205
+ static toTemplateString(path, { prefix, replacer } = {}) {
223
206
  const result = path.split(/\{([^}]+)\}/).map((part, i) => {
224
207
  if (i % 2 === 0) return part;
225
- const param = transformParam(part, casing);
208
+ const param = transformParam(part);
226
209
  return `\${${replacer ? replacer(param) : param}}`;
227
210
  }).join("");
228
211
  return `\`${prefix ?? ""}${result}\``;
@@ -230,8 +213,8 @@ var Url = class Url {
230
213
  /**
231
214
  * Converts an OpenAPI/Swagger path to a template literal that reads each parameter off the
232
215
  * grouped `path` request option, e.g. `/pet/{petId}` becomes `` `/pet/${path.petId}` ``. Parameter
233
- * names are camelCased to match the generated `path` type, and `prefix` is prepended inside the
234
- * literal. Shared by the client and cypress generators that pass a grouped `path` object.
216
+ * names match the generated `path` type, and `prefix` is prepended inside the literal. Shared by
217
+ * the client and cypress generators that pass a grouped `path` object.
235
218
  *
236
219
  * @example
237
220
  * Url.toGroupedTemplateString('/pet/{petId}') // '`/pet/${path.petId}`'
@@ -239,72 +222,25 @@ var Url = class Url {
239
222
  static toGroupedTemplateString(path, { prefix } = {}) {
240
223
  return Url.toTemplateString(path, {
241
224
  prefix,
242
- casing: "camelcase",
243
225
  replacer: (name) => `path.${name}`
244
226
  });
245
227
  }
246
- /**
247
- * Returns the path and its extracted params as a structured `URLObject`, or as a stringified
248
- * expression when `stringify` is set.
249
- *
250
- * @example
251
- * Url.toObject('/pet/{petId}')
252
- * // { url: '/pet/:petId', params: { petId: 'petId' } }
253
- */
254
- static toObject(path, { type = "path", replacer, stringify, casing } = {}) {
255
- const object = {
256
- url: type === "path" ? Url.toPath(path) : Url.toTemplateString(path, {
257
- replacer,
258
- casing
259
- }),
260
- params: toParamsObject(path, {
261
- replacer,
262
- casing
263
- })
264
- };
265
- if (stringify) {
266
- if (type === "template") return JSON.stringify(object).replaceAll("'", "").replaceAll(`"`, "");
267
- if (object.params) return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll("'", "").replaceAll(`"`, "")} }`;
268
- return `{ url: '${object.url}' }`;
269
- }
270
- return object;
271
- }
272
228
  };
273
229
  //#endregion
274
230
  //#region ../../internals/shared/src/params.ts
275
- const caseParamsCache = /* @__PURE__ */ new WeakMap();
276
231
  /**
277
- * Applies camelCase to parameter names and returns a new array without mutating the input.
232
+ * Drops parameters that share the same name, keeping the first.
278
233
  *
279
- * Run it before handing parameters to schema builders so output property keys get the right casing
280
- * while `OperationNode.parameters` stays intact for other consumers. When `casing` is unset, the
281
- * original array is returned unchanged. Results are cached per input array.
234
+ * A malformed spec can declare the same parameter name twice within one `in` location. Both would
235
+ * resolve to the same output property, so emitting both would yield an object type with a duplicate
236
+ * member, which TypeScript rejects. This is a defensive guard against that case, not a casing guard:
237
+ * parameter names flow through unchanged, so no two distinct names ever collide here anymore.
282
238
  */
283
- function caseParams(params, casing) {
284
- if (!casing) return params;
285
- const cached = caseParamsCache.get(params);
286
- if (cached) return cached;
287
- const result = params.map((param) => ({
288
- ...param,
289
- name: camelCase(param.name)
290
- }));
291
- caseParamsCache.set(params, result);
292
- return result;
293
- }
294
- /**
295
- * Drops parameters that collapse to the same property identity once camelCased, keeping the first.
296
- *
297
- * Some specs declare the same parameter twice under different casings (for example AWS S3 lists both
298
- * `max-uploads` and `MaxUploads`). Both resolve to one output property, so emitting both would yield
299
- * an object type with a duplicate member, which TypeScript rejects. De-duplicate by the camelCased
300
- * identity so the resulting group is collision-free regardless of the names each caller carries.
301
- */
302
- function dedupeByCasedName(params) {
239
+ function dedupeParams(params) {
303
240
  const seen = /* @__PURE__ */ new Set();
304
241
  return params.filter((param) => {
305
- const key = camelCase(param.name);
306
- if (seen.has(key)) return false;
307
- seen.add(key);
242
+ if (seen.has(param.name)) return false;
243
+ seen.add(param.name);
308
244
  return true;
309
245
  });
310
246
  }
@@ -423,13 +359,15 @@ function buildOperationComments(node, options = {}) {
423
359
  if (!splitLines) return filteredComments;
424
360
  return filteredComments.flatMap((text) => text.split(/\r?\n/).map((line) => line.trim())).filter((comment) => Boolean(comment));
425
361
  }
426
- function getOperationParameters(node, options = {}) {
427
- const params = caseParams(node.parameters, options.paramsCasing === "original" ? void 0 : "camelcase");
362
+ function getOperationParameters(node) {
428
363
  return {
429
- path: dedupeByCasedName(params.filter((param) => param.in === "path")),
430
- query: dedupeByCasedName(params.filter((param) => param.in === "query")),
431
- header: dedupeByCasedName(params.filter((param) => param.in === "header")),
432
- cookie: dedupeByCasedName(params.filter((param) => param.in === "cookie"))
364
+ path: dedupeParams(node.parameters.filter((param) => param.in === "path").map((param) => isValidVarName(param.name) ? param : {
365
+ ...param,
366
+ name: camelCase(param.name)
367
+ })),
368
+ query: dedupeParams(node.parameters.filter((param) => param.in === "query")),
369
+ header: dedupeParams(node.parameters.filter((param) => param.in === "header")),
370
+ cookie: dedupeParams(node.parameters.filter((param) => param.in === "cookie"))
433
371
  };
434
372
  }
435
373
  function getStatusCodeNumber(statusCode) {
@@ -461,7 +399,7 @@ function resolveStatusCodeNames(node, resolver) {
461
399
  }
462
400
  const typeNamesByResolver = /* @__PURE__ */ new WeakMap();
463
401
  function resolveOperationTypeNames(node, resolver, options = {}) {
464
- const cacheKey = `${node.operationId}\0${options.paramsCasing ?? ""}\0${options.order ?? ""}\0${options.responseStatusNames ?? ""}\0${options.includeParams === false ? "noparams" : ""}\0${(options.exclude ?? []).join(",")}`;
402
+ const cacheKey = `${node.operationId}\0${options.order ?? ""}\0${options.responseStatusNames ?? ""}\0${options.includeParams === false ? "noparams" : ""}\0${(options.exclude ?? []).join(",")}`;
465
403
  let byResolver = typeNamesByResolver.get(resolver);
466
404
  if (byResolver) {
467
405
  const cached = byResolver.get(cacheKey);
@@ -470,7 +408,7 @@ function resolveOperationTypeNames(node, resolver, options = {}) {
470
408
  byResolver = /* @__PURE__ */ new Map();
471
409
  typeNamesByResolver.set(resolver, byResolver);
472
410
  }
473
- const { path, query, header } = getOperationParameters(node, { paramsCasing: options.paramsCasing });
411
+ const { path, query, header } = getOperationParameters(node);
474
412
  const responseStatusNames = options.responseStatusNames === "error" ? resolveErrorNames(node, resolver) : options.responseStatusNames === false ? [] : resolveStatusCodeNames(node, resolver);
475
413
  const exclude = new Set(options.exclude ?? []);
476
414
  const paramNames = options.includeParams === false ? [] : [
@@ -630,87 +568,6 @@ function resolveClientOperation(options) {
630
568
  };
631
569
  }
632
570
  //#endregion
633
- //#region ../../internals/tanstack-query/src/components/MutationKey.tsx
634
- const declarationPrinter$4 = functionPrinter({ mode: "declaration" });
635
- const mutationKeyTransformer = ({ node }) => {
636
- if (!node.path) return [];
637
- return [`{ url: '${Url.toPath(node.path)}' }`];
638
- };
639
- function MutationKey$1({ name, node, transformer }) {
640
- const paramsNode = createFunctionParameters({ params: [] });
641
- const paramsSignature = declarationPrinter$4.print(paramsNode) ?? "";
642
- const keys = (transformer ?? mutationKeyTransformer)({
643
- node,
644
- casing: "camelcase"
645
- });
646
- return /* @__PURE__ */ jsx(File.Source, {
647
- name,
648
- isExportable: true,
649
- isIndexable: true,
650
- children: /* @__PURE__ */ jsx(Function.Arrow, {
651
- name,
652
- export: true,
653
- params: paramsSignature,
654
- singleLine: true,
655
- children: `[${keys.join(", ")}] as const`
656
- })
657
- });
658
- }
659
- __name(MutationKey$1, "MutationKey");
660
- //#endregion
661
- //#region ../../internals/tanstack-query/src/resolver.ts
662
- /**
663
- * Builds the shared query namespace for a variant. Spread the result into
664
- * `createResolver` once per variant the plugin supports.
665
- *
666
- * @example
667
- * ```ts
668
- * createResolver<PluginReactQuery>({
669
- * query: createQueryResolver(),
670
- * suspenseQuery: createQueryResolver('Suspense'),
671
- * })
672
- * ```
673
- */
674
- function createQueryResolver(variant = "") {
675
- return {
676
- name(node) {
677
- return `use${capitalize(this.name(node.operationId))}${variant}`;
678
- },
679
- optionsName(node) {
680
- return `${this.name(node.operationId)}${variant}QueryOptions`;
681
- },
682
- keyName(node) {
683
- return `${this.name(node.operationId)}${variant}QueryKey`;
684
- },
685
- keyTypeName(node) {
686
- return `${capitalize(this.name(node.operationId))}${variant}QueryKey`;
687
- },
688
- clientName(node) {
689
- return `${this.name(node.operationId)}${variant}`;
690
- }
691
- };
692
- }
693
- /**
694
- * Builds the shared mutation namespace. Spread the result into
695
- * `createResolver` and add plugin-specific methods (`optionsName`,
696
- * `typeName`, `argTypeName`) next to it.
697
- *
698
- * @example
699
- * ```ts
700
- * createResolver<PluginSwr>({ mutation: { ...createMutationResolver(), argTypeName(node) {...} } })
701
- * ```
702
- */
703
- function createMutationResolver() {
704
- return {
705
- name(node) {
706
- return `use${capitalize(this.name(node.operationId))}`;
707
- },
708
- keyName(node) {
709
- return `${this.name(node.operationId)}MutationKey`;
710
- }
711
- };
712
- }
713
- //#endregion
714
571
  //#region ../../internals/tanstack-query/src/utils.ts
715
572
  /**
716
573
  * The grouped request options, ordered for both the destructured signature and the
@@ -858,6 +715,87 @@ function buildQueryKeyParams(node, options) {
858
715
  return createFunctionParameters({ params: groupedParam ? [groupedParam] : [] });
859
716
  }
860
717
  //#endregion
718
+ //#region ../../internals/tanstack-query/src/components/MutationKey.tsx
719
+ const declarationPrinter$4 = functionPrinter({ mode: "declaration" });
720
+ const mutationKeyTransformer = ({ node }) => {
721
+ if (!node.path) return [];
722
+ return [`{ url: '${Url.toPath(node.path)}' }`];
723
+ };
724
+ function MutationKey$1({ name, node, transformer }) {
725
+ const paramsNode = createFunctionParameters({ params: [] });
726
+ const paramsSignature = declarationPrinter$4.print(paramsNode) ?? "";
727
+ const keys = (transformer ?? mutationKeyTransformer)({
728
+ node,
729
+ casing: "camelcase"
730
+ });
731
+ return /* @__PURE__ */ jsx(File.Source, {
732
+ name,
733
+ isExportable: true,
734
+ isIndexable: true,
735
+ children: /* @__PURE__ */ jsx(Function.Arrow, {
736
+ name,
737
+ export: true,
738
+ params: paramsSignature,
739
+ singleLine: true,
740
+ children: `[${keys.join(", ")}] as const`
741
+ })
742
+ });
743
+ }
744
+ __name(MutationKey$1, "MutationKey");
745
+ //#endregion
746
+ //#region ../../internals/tanstack-query/src/resolver.ts
747
+ /**
748
+ * Builds the shared query namespace for a variant. Spread the result into
749
+ * `createResolver` once per variant the plugin supports.
750
+ *
751
+ * @example
752
+ * ```ts
753
+ * createResolver<PluginReactQuery>({
754
+ * query: createQueryResolver(),
755
+ * suspenseQuery: createQueryResolver('Suspense'),
756
+ * })
757
+ * ```
758
+ */
759
+ function createQueryResolver(variant = "") {
760
+ return {
761
+ name(node) {
762
+ return `use${capitalize(this.name(node.operationId))}${variant}`;
763
+ },
764
+ optionsName(node) {
765
+ return `${this.name(node.operationId)}${variant}QueryOptions`;
766
+ },
767
+ keyName(node) {
768
+ return `${this.name(node.operationId)}${variant}QueryKey`;
769
+ },
770
+ keyTypeName(node) {
771
+ return `${capitalize(this.name(node.operationId))}${variant}QueryKey`;
772
+ },
773
+ clientName(node) {
774
+ return `${this.name(node.operationId)}${variant}`;
775
+ }
776
+ };
777
+ }
778
+ /**
779
+ * Builds the shared mutation namespace. Spread the result into
780
+ * `createResolver` and add plugin-specific methods (`optionsName`,
781
+ * `typeName`, `argTypeName`) next to it.
782
+ *
783
+ * @example
784
+ * ```ts
785
+ * createResolver<PluginSwr>({ mutation: { ...createMutationResolver(), argTypeName(node) {...} } })
786
+ * ```
787
+ */
788
+ function createMutationResolver() {
789
+ return {
790
+ name(node) {
791
+ return `use${capitalize(this.name(node.operationId))}`;
792
+ },
793
+ keyName(node) {
794
+ return `${this.name(node.operationId)}MutationKey`;
795
+ }
796
+ };
797
+ }
798
+ //#endregion
861
799
  //#region ../../internals/tanstack-query/src/components/QueryKey.tsx
862
800
  const declarationPrinter$3 = functionPrinter({ mode: "declaration" });
863
801
  const queryKeyTransformer = ({ node }) => {