@kubb/plugin-faker 5.0.0-beta.103 → 5.0.0-beta.106

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
@@ -576,8 +576,9 @@ function Faker({ node, description, name, typeName, printer, seed, canOverride }
576
576
  })();
577
577
  const { dataType, returnType: resolvedReturnType } = resolveFakerTypeUsage(node, typeName, canOverride);
578
578
  if (!useGenericOverride) {
579
+ const dataParamName = /\bdata\b/.test(fakerTextWithOverride) ? "data" : "_data";
579
580
  const params = createFunctionParameters({ params: [createFunctionParameter({
580
- name: /\bdata\b/.test(fakerTextWithOverride) ? "data" : "_data",
581
+ name: dataParamName,
581
582
  type: dataType,
582
583
  optional: true
583
584
  })] });
@@ -647,6 +648,45 @@ function dedupeParams(params) {
647
648
  //#endregion
648
649
  //#region ../../internals/shared/src/operation.ts
649
650
  /**
651
+ * Builds the `ResolverFileParams` every operation generator passes to
652
+ * `resolver.file`: a file named `name`, tagged by the operation's first
653
+ * tag (or `'default'`), at the operation's path. Centralizes the entry object
654
+ * that was repeated at dozens of call sites across the client and query plugins.
655
+ *
656
+ * @example
657
+ * ```ts
658
+ * resolver.file(operationFileEntry(node, node.operationId), { root, output, group })
659
+ * ```
660
+ */
661
+ function operationFileEntry(node, name, extname = ".ts") {
662
+ return {
663
+ name,
664
+ extname,
665
+ tag: node.tags[0] ?? "default",
666
+ path: node.path
667
+ };
668
+ }
669
+ /**
670
+ * Resolves a dependency plugin's generated file for `node.operationId`, cached in `cache` (the
671
+ * current node's `ctx.cache`) under the resolver's own plugin name. Several dependents reading the
672
+ * same dependency for the same operation in one pass (a query plugin's several hook generators, the
673
+ * MCP handler, ...) share one computed name and path instead of each calling `resolver.file` again.
674
+ *
675
+ * @example Cache `plugin-ts`'s file for the current operation
676
+ * ```ts
677
+ * const fileTs = resolveDependencyOperationFile({ cache: ctx.cache, node, resolver: tsResolver, root, output })
678
+ * ```
679
+ */
680
+ function resolveDependencyOperationFile(options) {
681
+ const { cache, node, resolver, root, output, group } = options;
682
+ return cache.getOrSet(`${resolver.pluginName}:operationFile`, () => resolver.file({
683
+ ...operationFileEntry(node, node.operationId),
684
+ root,
685
+ output,
686
+ group: group ?? void 0
687
+ }));
688
+ }
689
+ /**
650
690
  * Maps a content type to the PascalCase suffix used to name per-content-type variants
651
691
  * (e.g. `application/json` → `Json`, `application/xml` → `Xml`, `multipart/form-data` → `FormData`).
652
692
  */
@@ -694,13 +734,24 @@ function resolveContentTypeVariants(entries, baseName) {
694
734
  };
695
735
  });
696
736
  }
737
+ const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
738
+ /**
739
+ * Groups an operation's parameters by location (`path`/`query`/`header`/`cookie`), deduping each
740
+ * group by name. Every plugin generator visiting the same `OperationNode` shares one AST instance
741
+ * (see `KubbDriver`), so the result is cached per node to avoid re-filtering and re-deduping the
742
+ * same parameters once per plugin.
743
+ */
697
744
  function getOperationParameters(node) {
698
- return {
745
+ const cached = operationParameterGroupsByNode.get(node);
746
+ if (cached) return cached;
747
+ const groups = {
699
748
  path: dedupeParams(node.parameters.filter((param) => param.in === "path")),
700
749
  query: dedupeParams(node.parameters.filter((param) => param.in === "query")),
701
750
  header: dedupeParams(node.parameters.filter((param) => param.in === "header")),
702
751
  cookie: dedupeParams(node.parameters.filter((param) => param.in === "cookie"))
703
752
  };
753
+ operationParameterGroupsByNode.set(node, groups);
754
+ return groups;
704
755
  }
705
756
  //#endregion
706
757
  //#region ../../internals/shared/src/resolver.ts
@@ -832,6 +883,18 @@ function mapSchemaItems(node, transform) {
832
883
  }
833
884
  //#endregion
834
885
  //#region src/printers/printerFaker.ts
886
+ /**
887
+ * Formats that put a whole number inside a `type: 'string'` schema, the way ProtoJSON encodes
888
+ * 64-bit integers, so the mock has to be digits rather than letters.
889
+ *
890
+ * @see https://protobuf.dev/programming-guides/json/#int64-strings
891
+ */
892
+ const integerFormats = /* @__PURE__ */ new Set([
893
+ "int32",
894
+ "int64",
895
+ "uint64"
896
+ ]);
897
+ const maxInt32 = 2147483647;
835
898
  const fakerKeywordMapper = {
836
899
  any: () => "undefined",
837
900
  unknown: () => "undefined",
@@ -849,6 +912,10 @@ const fakerKeywordMapper = {
849
912
  return "faker.number.int()";
850
913
  },
851
914
  bigint: () => "faker.number.bigInt()",
915
+ integerString: (format) => {
916
+ if (format === "int32") return `faker.number.int({ max: ${maxInt32} }).toString()`;
917
+ return "faker.number.bigInt().toString()";
918
+ },
852
919
  string: (min, max) => {
853
920
  if (max !== void 0 && min !== void 0) return `faker.string.alpha({ length: { min: ${min}, max: ${max} } })`;
854
921
  if (max !== void 0) return `faker.string.alpha({ length: ${max} })`;
@@ -948,6 +1015,7 @@ const printerFaker = ast.createPrinter((options) => {
948
1015
  null: () => fakerKeywordMapper.null(),
949
1016
  string(node) {
950
1017
  if (node.pattern) return fakerKeywordMapper.matches(node.pattern, this.options.regexGenerator);
1018
+ if (node.format && integerFormats.has(node.format)) return fakerKeywordMapper.integerString(node.format);
951
1019
  return fakerKeywordMapper.string(node.min, node.max);
952
1020
  },
953
1021
  email: () => fakerKeywordMapper.email(),
@@ -1253,14 +1321,13 @@ const fakerGenerator = defineGenerator({
1253
1321
  output,
1254
1322
  group: group ?? void 0
1255
1323
  }),
1256
- typeFile: tsResolver.file({
1257
- name: node.operationId,
1258
- extname: ".ts",
1259
- tag: node.tags[0] ?? "default",
1260
- path: node.path,
1324
+ typeFile: resolveDependencyOperationFile({
1325
+ cache: ctx.cache,
1326
+ node,
1327
+ resolver: tsResolver,
1261
1328
  root,
1262
1329
  output: pluginTs.options?.output ?? output,
1263
- group: pluginTs.options?.group ?? void 0
1330
+ group: pluginTs.options?.group
1264
1331
  })
1265
1332
  };
1266
1333
  function resolveMockImports(schema) {