@kubb/core 5.0.0-beta.87 → 5.0.0-beta.89

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.
@@ -496,23 +496,14 @@ type ResolverDefault = {
496
496
  */
497
497
  name(name: string): string;
498
498
  options<TOptions>(node: Node, context: ResolveOptionsContext<TOptions>): TOptions | null;
499
- path(params: ResolverPathParams, context: ResolverContext): string;
500
- file(params: ResolverFileParams, context: ResolverContext): FileNode;
499
+ path(options: ResolvePathOptions): string;
500
+ file(options: ResolveFileOptions): FileNode;
501
501
  banner(meta: InputMeta | undefined, context: ResolveBannerContext): string | null;
502
502
  footer(meta: InputMeta | undefined, context: ResolveBannerContext): string | null;
503
503
  };
504
504
  /**
505
- * File-specific parameters for `resolver.default.path`.
506
- * Provide `tag` for tag-based grouping or `path` for path-based grouping.
507
- *
508
- * @example
509
- * ```ts
510
- * resolver.default.path(
511
- * { baseName: 'petTypes.ts', tag: 'pets' },
512
- * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },
513
- * )
514
- * // → '/src/types/pets/petTypes.ts'
515
- * ```
505
+ * The name request for `resolver.default.path`: a `baseName` plus the optional `tag`/`path` that
506
+ * grouping keys off.
516
507
  */
517
508
  type ResolverPathParams = {
518
509
  baseName: FileNode['baseName'];
@@ -526,27 +517,32 @@ type ResolverPathParams = {
526
517
  path?: string;
527
518
  };
528
519
  /**
529
- * Shared context passed as the second argument to `resolver.default.path` and
530
- * `resolver.default.file`: where output is rooted, which output config is active,
531
- * and the optional grouping strategy.
520
+ * Options for `resolver.default.path`: the name request (`baseName`, `tag`, `path`) plus where the
521
+ * output goes (`root`, `output`, `group`).
522
+ *
523
+ * @example
524
+ * ```ts
525
+ * resolver.default.path({ baseName: 'petTypes.ts', tag: 'pets', root: '/src', output: { path: 'types' }, group: { type: 'tag' } })
526
+ * // → '/src/types/pets/petTypes.ts'
527
+ * ```
532
528
  */
533
- type ResolverContext = {
529
+ type ResolvePathOptions = ResolverPathParams & {
530
+ /**
531
+ * Absolute project root that the output path is resolved against.
532
+ */
534
533
  root: string;
534
+ /**
535
+ * Active output config; `output.path` is the base directory.
536
+ */
535
537
  output: Output;
538
+ /**
539
+ * Optional grouping strategy applied to `tag` (tag grouping) or `path` (path grouping).
540
+ */
536
541
  group?: Group;
537
542
  };
538
543
  /**
539
- * File-specific parameters for `resolver.default.file`.
540
- * `tag` and `path` are used only when a matching `group` is present in the context.
541
- *
542
- * @example
543
- * ```ts
544
- * resolver.default.file(
545
- * { name: 'listPets', extname: '.ts', tag: 'pets' },
546
- * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },
547
- * )
548
- * // → { baseName: 'listPets.ts', path: '/src/types/pets/listPets.ts', ... }
549
- * ```
544
+ * The file request for `resolver.file` and `resolver.default.file`: the `name` and `extname` plus
545
+ * the optional `tag`/`path` that grouping keys off.
550
546
  */
551
547
  type ResolverFileParams = {
552
548
  name: string;
@@ -559,13 +555,68 @@ type ResolverFileParams = {
559
555
  * Path value used when `group.type === 'path'`.
560
556
  */
561
557
  path?: string;
558
+ };
559
+ /**
560
+ * Options for `resolver.file` and `resolver.default.file`: the file request (`name`, `extname`,
561
+ * `tag`, `path`) plus where the output goes (`root`, `output`, `group`).
562
+ *
563
+ * @example
564
+ * ```ts
565
+ * resolver.default.file({ name: 'listPets', extname: '.ts', tag: 'pets', root: '/src', output: { path: 'types' }, group: { type: 'tag' } })
566
+ * // → { baseName: 'listPets.ts', path: '/src/types/pets/listPets.ts', ... }
567
+ * ```
568
+ */
569
+ type ResolveFileOptions = ResolverFileParams & {
570
+ root: string;
571
+ output: Output;
572
+ group?: Group;
573
+ };
574
+ /**
575
+ * The `file` field of a resolver: decides what a generated file is called and, optionally, where
576
+ * it lives. This is how a resolver renames or relocates its files, replacing the older per-call
577
+ * `resolveName` hook.
578
+ *
579
+ * @example Suffix every generated file
580
+ * ```ts
581
+ * file: {
582
+ * baseName({ name, extname }) {
583
+ * return `${name}Faker${extname}`
584
+ * },
585
+ * }
586
+ * ```
587
+ *
588
+ * @example Own the full path
589
+ * ```ts
590
+ * file: {
591
+ * path({ baseName, output }) {
592
+ * return `${output.path}/mocks/${baseName}`
593
+ * },
594
+ * }
595
+ * ```
596
+ */
597
+ type ResolverFile = {
562
598
  /**
563
- * Casing applied to `name` to build the file base name. A plugin's `file` override
564
- * threads its own caser here to change file naming without reimplementing the builder.
565
- *
566
- * @default toFilePath
599
+ * Builds the file's complete base name, extension included, from the identifier and the target
600
+ * `extname`. Defaults to `toFilePath(name)` with `extname` appended. Reaches sibling resolver
601
+ * helpers through `this`.
567
602
  */
568
- resolveName?: (name: string) => string;
603
+ baseName?(params: Pick<ResolverFileParams, 'name' | 'extname'>): FileNode['baseName'];
604
+ /**
605
+ * Returns the file's complete path, resolved against the project `root`. Bypasses `output.path`
606
+ * and `group`, so the resolver owns the layout. The returned path may not escape `root`. Reaches
607
+ * sibling resolver helpers through `this`.
608
+ */
609
+ path?(params: ResolverFilePathParams): string;
610
+ };
611
+ /**
612
+ * The argument to a resolver's `file.path`: the resolved `baseName` (what `file.baseName` produced,
613
+ * with the extension already appended) and the active `output`. `tag`, `path`, and `group` are
614
+ * omitted because `file.path` owns the whole path and bypasses grouping, and `root` because the
615
+ * returned path is resolved against it.
616
+ */
617
+ type ResolverFilePathParams = {
618
+ baseName: FileNode['baseName'];
619
+ output: Output;
569
620
  };
570
621
  /**
571
622
  * Per-file context describing the file a banner/footer is being resolved for, so a
@@ -631,18 +682,27 @@ type ResolveBannerContext = {
631
682
  type ResolverBuildOptions = {
632
683
  pluginName: string;
633
684
  name?: (name: string) => string;
634
- file?: (params: ResolverFileParams, context: ResolverContext) => FileNode;
685
+ file?: ResolverFile;
635
686
  [key: string]: unknown;
636
687
  };
637
688
  /**
638
689
  * Partial resolver fields accepted by `Resolver.merge` and `setResolver`. Parameterize with a
639
- * concrete resolver type (e.g. `ResolverPatch<ResolverTs>`) to type-check namespace overrides
640
- * and bind `this` to the full resolver. The bare form accepts any resolver's fields.
690
+ * concrete resolver type (e.g. `ResolverPatch<ResolverTs>`) to type-check overrides and bind
691
+ * `this` to the full resolver. Namespaces are partial, so a patch may override a single method
692
+ * (`query.name`) and the rest keep the plugin defaults. Overriding a whole resolver is not the
693
+ * job of this patch, that is what a custom plugin is for.
641
694
  */
642
- type ResolverPatch<T extends Resolver = Resolver> = Partial<Omit<T, keyof Resolver>> & {
695
+ type ResolverPatch<T extends Resolver = Resolver> = { [K in keyof Omit<T, keyof Resolver>]?: T[K] extends ((...args: Array<never>) => unknown) ? T[K] : Partial<T[K]> } & {
643
696
  name?: T['name'];
644
- file?: T['file'];
697
+ file?: ResolverFile;
645
698
  } & ThisType<T>;
699
+ /**
700
+ * Shared brand for reaching a resolver's build options. `Resolver.merge` reads this instead of
701
+ * relying on `instanceof`, which fails when a CommonJS config and the ESM CLI each load their own
702
+ * copy of `@kubb/core`. `Symbol.for` resolves to one key across those copies, so the options stay
703
+ * reachable and a `file` override is never dropped.
704
+ */
705
+ declare const resolverOptions: unique symbol;
646
706
  /**
647
707
  * Base constraint for all plugin resolver objects.
648
708
  *
@@ -671,16 +731,21 @@ declare class Resolver {
671
731
  #private;
672
732
  readonly pluginName: string;
673
733
  constructor(options: ResolverBuildOptions);
734
+ /** Exposes the raw build options so `Resolver.merge` can read them across `@kubb/core` copies. */
735
+ get [resolverOptions](): ResolverBuildOptions;
674
736
  /**
675
737
  * The built-in resolution machinery. Always reaches the untouched defaults, even when a
676
738
  * plugin overrides the top-level `name` or `file`.
677
739
  */
678
740
  get default(): ResolverDefault;
679
741
  name(name: string): string;
680
- file(params: ResolverFileParams, context: ResolverContext): FileNode;
742
+ file(options: ResolveFileOptions): FileNode;
681
743
  /**
682
- * Merges `override` over `base` and returns a new resolver with helpers re-bound.
683
- * Each key is replaced wholesale. Used when applying `setResolver` partial overrides.
744
+ * Merges `override` over `base` and returns a new resolver with helpers re-bound. Top-level
745
+ * keys replace, and a namespace (or `file`) merges per method, so overriding `query.name`
746
+ * keeps the base `query.keyName`. Used when applying `setResolver` partial overrides. Reads a
747
+ * resolver's options through the shared brand rather than `instanceof`, so a `file` override
748
+ * survives even when `base` and `override` come from different `@kubb/core` copies.
684
749
  */
685
750
  static merge<T extends Resolver>(base: T, override: ResolverPatch<T> | Resolver): T;
686
751
  }
@@ -1377,11 +1442,7 @@ declare class KubbDriver {
1377
1442
  * the failure as a {@link Diagnostic} instead of propagating. Each plugin also
1378
1443
  * contributes a `timing` diagnostic for the run summary.
1379
1444
  */
1380
- run({
1381
- storage
1382
- }: {
1383
- storage: Storage;
1384
- }): Promise<{
1445
+ run(): Promise<{
1385
1446
  diagnostics: Array<Diagnostic>;
1386
1447
  }>;
1387
1448
  /**
@@ -1499,7 +1560,7 @@ type GeneratorContext<TOptions extends PluginFactoryOptions = PluginFactoryOptio
1499
1560
  * `ctx.resolver.name('pet') // 'pet'`
1500
1561
  *
1501
1562
  * @example Resolve an output file
1502
- * `ctx.resolver.file({ name: 'pet', extname: '.ts' }, { root, output })`
1563
+ * `ctx.resolver.file({ name: 'pet', extname: '.ts', root, output })`
1503
1564
  */
1504
1565
  resolver: TOptions['resolver'];
1505
1566
  /**
@@ -2789,5 +2850,5 @@ declare class Diagnostics {
2789
2850
  static formatLines(diagnostic: Diagnostic): Array<string>;
2790
2851
  }
2791
2852
  //#endregion
2792
- export { Include as $, KubbHookStartContext as A, UserReporter as At, Kubb$1 as B, KubbFilesProcessingEndContext as C, createRenderer as Ct, KubbGenerationStartContext as D, Reporter as Dt, KubbGenerationEndContext as E, GenerationResult as Et, KubbSuccessContext as F, AdapterSource as Ft, KubbDriver as G, Generator as H, KubbWarnContext as I, createAdapter as It, Parser as J, FileManagerHooks as K, PossibleConfig as L, KubbInfoContext as M, logLevel as Mt, KubbLifecycleStartContext as N, Adapter as Nt, KubbHookEndContext as O, ReporterContext as Ot, KubbPluginsEndContext as P, AdapterFactoryOptions as Pt, Group as Q, UserConfig as R, KubbFileProcessingUpdate as S, RendererFactory as St, KubbFilesProcessingUpdateContext as T, createStorage as Tt, GeneratorContext as U, createKubb as V, defineGenerator as W, Exclude$1 as X, defineParser as Y, Filter as Z, InputPath as _, ResolverDefault as _t, DiagnosticLocation as a, OutputMode as at, KubbDiagnosticContext as b, ResolverPathParams as bt, PerformanceDiagnostic as c, Plugin as ct, SerializedDiagnostic as d, BannerMeta as dt, KubbPluginEndContext as et, UpdateDiagnostic as f, ResolveBannerContext as ft, InputData as g, ResolverContext as gt, Config as h, Resolver as ht, DiagnosticKind as i, Output as it, KubbHooks as j, createReporter as jt, KubbHookLineContext as k, ReporterName as kt, ProblemCode as l, PluginFactoryOptions as lt, CLIOptions as m, ResolveOptionsContext as mt, DiagnosticByCode as n, KubbPluginStartContext as nt, DiagnosticSeverity as o, OutputOptions as ot, BuildOutput as p, ResolveBannerFile as pt, Hookable as q, DiagnosticDoc as r, NormalizedPlugin as rt, Diagnostics as s, Override as st, Diagnostic as t, KubbPluginSetupContext as tt, ProblemDiagnostic as u, definePlugin as ut, KubbBuildEndContext as v, ResolverFileParams as vt, KubbFilesProcessingStartContext as w, Storage as wt, KubbErrorContext as x, Renderer as xt, KubbBuildStartContext as y, ResolverPatch as yt, CreateKubbOptions as z };
2793
- //# sourceMappingURL=Diagnostics-aWJg-H2d.d.ts.map
2853
+ export { Include as $, KubbHookStartContext as A, Reporter as At, Kubb$1 as B, KubbFilesProcessingEndContext as C, ResolverPathParams as Ct, KubbGenerationStartContext as D, Storage as Dt, KubbGenerationEndContext as E, createRenderer as Et, KubbSuccessContext as F, logLevel as Ft, KubbDriver as G, Generator as H, KubbWarnContext as I, Adapter as It, Parser as J, FileManagerHooks as K, PossibleConfig as L, AdapterFactoryOptions as Lt, KubbInfoContext as M, ReporterName as Mt, KubbLifecycleStartContext as N, UserReporter as Nt, KubbHookEndContext as O, createStorage as Ot, KubbPluginsEndContext as P, createReporter as Pt, Group as Q, UserConfig as R, AdapterSource as Rt, KubbFileProcessingUpdate as S, ResolverPatch as St, KubbFilesProcessingUpdateContext as T, RendererFactory as Tt, GeneratorContext as U, createKubb as V, defineGenerator as W, Exclude$1 as X, defineParser as Y, Filter as Z, InputPath as _, Resolver as _t, DiagnosticLocation as a, OutputMode as at, KubbDiagnosticContext as b, ResolverFileParams as bt, PerformanceDiagnostic as c, Plugin as ct, SerializedDiagnostic as d, BannerMeta as dt, KubbPluginEndContext as et, UpdateDiagnostic as f, ResolveBannerContext as ft, InputData as g, ResolvePathOptions as gt, Config as h, ResolveOptionsContext as ht, DiagnosticKind as i, Output as it, KubbHooks as j, ReporterContext as jt, KubbHookLineContext as k, GenerationResult as kt, ProblemCode as l, PluginFactoryOptions as lt, CLIOptions as m, ResolveFileOptions as mt, DiagnosticByCode as n, KubbPluginStartContext as nt, DiagnosticSeverity as o, OutputOptions as ot, BuildOutput as p, ResolveBannerFile as pt, Hookable as q, DiagnosticDoc as r, NormalizedPlugin as rt, Diagnostics as s, Override as st, Diagnostic as t, KubbPluginSetupContext as tt, ProblemDiagnostic as u, definePlugin as ut, KubbBuildEndContext as v, ResolverDefault as vt, KubbFilesProcessingStartContext as w, Renderer as wt, KubbErrorContext as x, ResolverFilePathParams as xt, KubbBuildStartContext as y, ResolverFile as yt, CreateKubbOptions as z, createAdapter as zt };
2854
+ //# sourceMappingURL=Diagnostics-CM0-Ae30.d.ts.map
package/dist/index.cjs CHANGED
@@ -172,7 +172,7 @@ function memoize(store, factory) {
172
172
  }
173
173
  //#endregion
174
174
  //#region package.json
175
- var version = "5.0.0-beta.87";
175
+ var version = "5.0.0-beta.89";
176
176
  //#endregion
177
177
  //#region src/constants.ts
178
178
  /**
@@ -747,6 +747,19 @@ function isNamespace(value) {
747
747
  return typeof value === "object" && value !== null && !Array.isArray(value);
748
748
  }
749
749
  /**
750
+ * Shared brand for reaching a resolver's build options. `Resolver.merge` reads this instead of
751
+ * relying on `instanceof`, which fails when a CommonJS config and the ESM CLI each load their own
752
+ * copy of `@kubb/core`. `Symbol.for` resolves to one key across those copies, so the options stay
753
+ * reachable and a `file` override is never dropped.
754
+ */
755
+ const resolverOptions = Symbol.for("@kubb/core/resolver/options");
756
+ /**
757
+ * Built-in `file.baseName`: casts the identifier with `toFilePath` and appends the extension.
758
+ */
759
+ function toBaseName({ name, extname }) {
760
+ return `${require_usingCtx.toFilePath(name)}${extname}`;
761
+ }
762
+ /**
750
763
  * Base constraint for all plugin resolver objects.
751
764
  *
752
765
  * The built-in machinery lives under `default`. Generators call the top-level `name` and
@@ -775,11 +788,19 @@ var Resolver = class Resolver {
775
788
  static #optionsCache = /* @__PURE__ */ new WeakMap();
776
789
  pluginName;
777
790
  #options;
791
+ #baseName;
792
+ #filePath;
778
793
  constructor(options) {
779
794
  this.pluginName = options.pluginName;
780
795
  this.#options = options;
796
+ this.#baseName = options.file?.baseName ? options.file.baseName.bind(this) : toBaseName;
797
+ this.#filePath = options.file?.path ? options.file.path.bind(this) : void 0;
781
798
  this.#apply(options);
782
799
  }
800
+ /** Exposes the raw build options so `Resolver.merge` can read them across `@kubb/core` copies. */
801
+ get [resolverOptions]() {
802
+ return this.#options;
803
+ }
783
804
  /**
784
805
  * The built-in resolution machinery. Always reaches the untouched defaults, even when a
785
806
  * plugin overrides the top-level `name` or `file`.
@@ -797,19 +818,28 @@ var Resolver = class Resolver {
797
818
  name(name) {
798
819
  return this.default.name(name);
799
820
  }
800
- file(params, context) {
801
- return this.default.file(params, context);
821
+ file(options) {
822
+ return this.#resolveFile(options);
802
823
  }
803
824
  /**
804
- * Merges `override` over `base` and returns a new resolver with helpers re-bound.
805
- * Each key is replaced wholesale. Used when applying `setResolver` partial overrides.
825
+ * Merges `override` over `base` and returns a new resolver with helpers re-bound. Top-level
826
+ * keys replace, and a namespace (or `file`) merges per method, so overriding `query.name`
827
+ * keeps the base `query.keyName`. Used when applying `setResolver` partial overrides. Reads a
828
+ * resolver's options through the shared brand rather than `instanceof`, so a `file` override
829
+ * survives even when `base` and `override` come from different `@kubb/core` copies.
806
830
  */
807
831
  static merge(base, override) {
808
- const patch = override instanceof Resolver ? override.#options : override;
809
- return new Resolver({
810
- ...base.#options,
811
- ...patch
812
- });
832
+ const patch = resolverOptions in override ? override[resolverOptions] : override;
833
+ const merged = { ...base[resolverOptions] };
834
+ for (const [key, value] of Object.entries(patch)) {
835
+ if (value === void 0) continue;
836
+ const current = merged[key];
837
+ merged[key] = isNamespace(value) && isNamespace(current) ? {
838
+ ...current,
839
+ ...value
840
+ } : value;
841
+ }
842
+ return new Resolver(merged);
813
843
  }
814
844
  /**
815
845
  * Binds each entry of `options` onto the resolver, so `this.name`, `this.default`, and
@@ -820,7 +850,7 @@ var Resolver = class Resolver {
820
850
  const root = this;
821
851
  const bind = (value) => typeof value === "function" ? value.bind(root) : value;
822
852
  for (const [key, value] of Object.entries(options)) {
823
- if (key === "pluginName" || key === "default" || value === void 0) continue;
853
+ if (key === "pluginName" || key === "default" || key === "file" || value === void 0) continue;
824
854
  root[key] = isNamespace(value) ? Object.fromEntries(Object.entries(value).map(([method, member]) => [method, bind(member)])) : bind(value);
825
855
  }
826
856
  }
@@ -905,7 +935,7 @@ var Resolver = class Resolver {
905
935
  * to `output.path/{baseName}`, or into a subdirectory when `group` and a `tag`/`path` value
906
936
  * are provided.
907
937
  */
908
- #resolvePath({ baseName, tag, path: groupPath }, { root, output, group }) {
938
+ #resolvePath({ baseName, tag, path: groupPath, root, output, group }) {
909
939
  if (output.mode === "file") return node_path.default.resolve(root, output.path);
910
940
  const outputDir = node_path.default.resolve(root, output.path);
911
941
  const result = group && (groupPath || tag) ? node_path.default.resolve(outputDir, Resolver.#resolveGroupDir(group, group.type === "path" ? groupPath : tag), baseName) : node_path.default.resolve(outputDir, baseName);
@@ -920,17 +950,45 @@ var Resolver = class Resolver {
920
950
  return result;
921
951
  }
922
952
  /**
923
- * Builds a `FileNode` by combining file-name casing (`params.resolveName`) with path
924
- * resolution. The resolved file starts with empty `sources`, `imports`, and `exports`,
925
- * which consumers populate separately.
953
+ * Resolves a resolver-supplied full path (`file.path`) against `root`, bypassing `output.path`
954
+ * and `group`. The path may not escape `root`, which keeps a `file.path` that interpolates
955
+ * spec-derived values from writing outside the project.
956
+ */
957
+ #resolveOverridePath(filePath, root) {
958
+ const resolved = node_path.default.resolve(root, filePath);
959
+ const rootWithSep = root.endsWith(node_path.default.sep) ? root : `${root}${node_path.default.sep}`;
960
+ if (resolved !== root && !resolved.startsWith(rootWithSep)) throw new Diagnostics.Error({
961
+ code: Diagnostics.code.pathTraversal,
962
+ severity: "error",
963
+ message: `Resolved path "${resolved}" is outside the project root "${root}".`,
964
+ help: "A resolver `file.path` must return a path inside the project root.",
965
+ location: { kind: "config" }
966
+ });
967
+ return resolved;
968
+ }
969
+ /**
970
+ * Builds a `FileNode`. When `#filePath` (the resolver's `file.path`) is set it owns the whole
971
+ * path; otherwise the base name (from `#baseName`, the resolver's `file.baseName` or the
972
+ * built-in `toBaseName`) is placed by the `output.path`/`group` layout. The resolved file starts
973
+ * with empty `sources`, `imports`, and `exports`, which consumers populate separately.
926
974
  */
927
- #resolveFile({ name, extname, tag, path: groupPath, resolveName = require_usingCtx.toFilePath }, context) {
928
- const resolvedName = context.output.mode === "file" ? "" : resolveName(name);
929
- const filePath = this.#resolvePath({
930
- baseName: `${resolvedName}${extname}`,
975
+ #resolveFile(options) {
976
+ const { name, extname, tag, path: groupPath, root, output, group } = options;
977
+ const baseName = this.#baseName({
978
+ name,
979
+ extname
980
+ });
981
+ const filePath = this.#filePath ? this.#resolveOverridePath(this.#filePath({
982
+ baseName,
983
+ output
984
+ }), root) : this.#resolvePath({
985
+ baseName,
931
986
  tag,
932
- path: groupPath
933
- }, context);
987
+ path: groupPath,
988
+ root,
989
+ output,
990
+ group
991
+ });
934
992
  return _kubb_ast.ast.factory.createFile({
935
993
  path: filePath,
936
994
  baseName: node_path.default.basename(filePath),
@@ -1007,15 +1065,39 @@ var Resolver = class Resolver {
1007
1065
  * (`query`, `schema`, …). Every method reaches sibling helpers and the built-in machinery
1008
1066
  * through `this.name`, `this.file`, and `this.default`.
1009
1067
  *
1010
- * @example Custom identifier and file casing
1068
+ * @example Custom identifier casing
1011
1069
  * ```ts
1012
1070
  * export const resolverTs = createResolver<PluginTs>({
1013
1071
  * pluginName: 'plugin-ts',
1014
1072
  * name(name) {
1015
1073
  * return ensureValidVarName(pascalCase(name))
1016
1074
  * },
1017
- * file(params, context) {
1018
- * return this.default.file({ ...params, resolveName: (name) => toFilePath(name, pascalCase) }, context)
1075
+ * })
1076
+ * ```
1077
+ *
1078
+ * @example Rename generated files with `file.baseName`
1079
+ * ```ts
1080
+ * export const resolverFaker = createResolver<PluginFaker>({
1081
+ * pluginName: 'plugin-faker',
1082
+ * name(name) {
1083
+ * return camelCase(name, { prefix: 'create' })
1084
+ * },
1085
+ * file: {
1086
+ * baseName({ name, extname }) {
1087
+ * return `${camelCase(name, { prefix: 'create' })}${extname}`
1088
+ * },
1089
+ * },
1090
+ * })
1091
+ * ```
1092
+ *
1093
+ * @example Own the full path with `file.path`
1094
+ * ```ts
1095
+ * export const resolverFaker = createResolver<PluginFaker>({
1096
+ * pluginName: 'plugin-faker',
1097
+ * file: {
1098
+ * path({ baseName, output }) {
1099
+ * return `${output.path}/mocks/${baseName}`
1100
+ * },
1019
1101
  * },
1020
1102
  * })
1021
1103
  * ```
@@ -1326,7 +1408,7 @@ var KubbDriver = class {
1326
1408
  * the failure as a {@link Diagnostic} instead of propagating. Each plugin also
1327
1409
  * contributes a `timing` diagnostic for the run summary.
1328
1410
  */
1329
- async run({ storage }) {
1411
+ async run() {
1330
1412
  const { hooks, config, fileManager } = this;
1331
1413
  const diagnostics = [];
1332
1414
  const parsersMap = /* @__PURE__ */ new Map();
@@ -1408,7 +1490,7 @@ var KubbDriver = class {
1408
1490
  diagnostics.push(...await this.#runGenerators(generatorPlugins));
1409
1491
  await hooks.callHook("kubb:plugins:end", Object.assign({ config }, this.#filesPayload()));
1410
1492
  await fileManager.write(fileManager.files, {
1411
- storage,
1493
+ storage: config.storage,
1412
1494
  parsers: parsersMap,
1413
1495
  extension: config.output.extension
1414
1496
  });
@@ -1976,7 +2058,7 @@ var Kubb = class {
1976
2058
  const self = _usingCtx$1.u(this);
1977
2059
  const driver = self.driver;
1978
2060
  const storage = self.storage;
1979
- const { diagnostics } = await driver.run({ storage });
2061
+ const { diagnostics } = await driver.run();
1980
2062
  return {
1981
2063
  diagnostics,
1982
2064
  files: driver.fileManager.files,