@kubb/core 5.0.0-alpha.47 → 5.0.0-alpha.49
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/README.md +3 -2
- package/dist/{PluginDriver-DGmnXAf5.cjs → PluginDriver-Btusp5ye.cjs} +7 -2
- package/dist/PluginDriver-Btusp5ye.cjs.map +1 -0
- package/dist/{PluginDriver-Cp9dwdYU.js → PluginDriver-CjHpg9MR.js} +7 -2
- package/dist/PluginDriver-CjHpg9MR.js.map +1 -0
- package/dist/index.cjs +2 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/mocks.cjs +1 -1
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.ts +1 -1
- package/dist/mocks.js +1 -1
- package/dist/mocks.js.map +1 -1
- package/dist/{types-B_PnVLGD.d.ts → types-DfEv9d_c.d.ts} +7 -21
- package/package.json +48 -48
- package/src/FileManager.ts +4 -1
- package/src/Kubb.ts +9 -1
- package/src/createKubb.ts +23 -4
- package/src/defineResolver.ts +12 -2
- package/src/mocks.ts +12 -3
- package/src/storages/fsStorage.ts +12 -4
- package/src/types.ts +10 -19
- package/src/utils/getBarrelFiles.ts +0 -1
- package/dist/PluginDriver-Cp9dwdYU.js.map +0 -1
- package/dist/PluginDriver-DGmnXAf5.cjs.map +0 -1
package/dist/mocks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mocks.js","names":[],"sources":["../src/mocks.ts"],"sourcesContent":["import { resolve } from 'node:path'\nimport type { FileNode, OperationNode, SchemaNode, Visitor } from '@kubb/ast'\nimport { transform } from '@kubb/ast'\nimport { FileManager } from './FileManager.ts'\nimport { PluginDriver } from './PluginDriver.ts'\nimport { applyHookResult } from './renderNode.ts'\nimport type { Adapter, AdapterFactoryOptions, Config, Generator, GeneratorContext, NormalizedPlugin, PluginFactoryOptions } from './types.ts'\n\n/**\n * Creates a minimal `PluginDriver` mock suitable for unit tests.\n */\nexport function createMockedPluginDriver(options: { name?: string; plugin?: NormalizedPlugin; config?: Config } = {}): PluginDriver {\n return {\n config: options?.config ?? {\n root: '.',\n output: {\n path: './path',\n },\n },\n getPlugin(_pluginName: string): NormalizedPlugin | undefined {\n return options?.plugin\n },\n getResolver: (_pluginName: string) => options?.plugin?.resolver,\n fileManager: new FileManager(),\n } as unknown as PluginDriver\n}\n\n/**\n * Creates a minimal `Adapter` mock suitable for unit tests.\n *\n * - `parse` returns an empty `InputNode` by default; override via `options.parse`.\n * - `getImports` returns `[]` by default (single-file mode, no cross-file imports).\n */\nexport function createMockedAdapter<TOptions extends AdapterFactoryOptions = AdapterFactoryOptions>(\n options: {\n name?: TOptions['name']\n resolvedOptions?: TOptions['resolvedOptions']\n inputNode?: Adapter<TOptions>['inputNode']\n parse?: Adapter<TOptions>['parse']\n getImports?: Adapter<TOptions>['getImports']\n } = {},\n): Adapter<TOptions> {\n return {\n name: (options.name ?? 'oas') as TOptions['name'],\n options: (options.resolvedOptions ?? {}) as TOptions['resolvedOptions'],\n inputNode: options.inputNode ?? null,\n parse: options.parse ?? (async () => ({ kind: 'Input' as const, schemas: [], operations: [] })),\n getImports: options.getImports ?? ((_node: SchemaNode, _resolve: (schemaName: string) => { name: string; path: string }) => []),\n } as Adapter<TOptions>\n}\n\n/**\n * Creates a minimal plugin mock suitable for unit tests.\n *\n * @example\n * const plugin = createMockedPlugin<PluginTs>({ name: '@kubb/plugin-ts', options })\n */\nexport function createMockedPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>(params: {\n name: TOptions['name']\n options: TOptions['resolvedOptions']\n resolver?: TOptions['resolver']\n transformer?: Visitor\n dependencies?: Array<string>\n}): NormalizedPlugin<TOptions> {\n return {\n name: params.name,\n options: params.options,\n resolver: params.resolver,\n transformer: params.transformer,\n dependencies: params.dependencies,\n hooks: {},\n } as unknown as NormalizedPlugin<TOptions>\n}\n\ntype RenderGeneratorOptions<TOptions extends PluginFactoryOptions> = {\n config: Config\n adapter: Adapter\n driver: PluginDriver\n plugin: NormalizedPlugin<TOptions>\n options: TOptions['resolvedOptions']\n resolver: TOptions['resolver']\n}\n\nfunction createMockedPluginContext<TOptions extends PluginFactoryOptions>(opts: RenderGeneratorOptions<TOptions>): Omit<GeneratorContext<TOptions>, 'options'> {\n const root = resolve(opts.config.root, opts.config.output.path)\n\n return {\n config: opts.config,\n root,\n getMode: (output: { path: string }) => PluginDriver.getMode(resolve(root, output.path)),\n adapter: opts.adapter,\n resolver: opts.resolver,\n plugin: opts.plugin,\n driver: opts.driver,\n getResolver: (name: string) => opts.driver.getResolver(name),\n inputNode: { kind: 'Input', schemas: [], operations: [] },\n addFile: async (...files: Array<FileNode>) => opts.driver.fileManager.add(...files),\n upsertFile: async (...files: Array<FileNode>) => opts.driver.fileManager.upsert(...files),\n hooks: opts.driver.hooks ?? ({} as never),\n warn: (msg: string) => console.warn(msg),\n error: (msg: string) => console.error(msg),\n info: (msg: string) => console.info(msg),\n openInStudio: async () => {},\n } as unknown as Omit<GeneratorContext<TOptions>, 'options'>\n}\n\n/**\n * Renders a generator's `schema` method in a test context.\n *\n * @example\n * await renderGeneratorSchema(typeGenerator, node, { config, adapter, driver, plugin, options, resolver })\n * await matchFiles(driver.fileManager.files)\n */\nexport async function renderGeneratorSchema<TOptions extends PluginFactoryOptions>(\n generator: Generator<TOptions>,\n node: SchemaNode,\n opts: RenderGeneratorOptions<TOptions>,\n): Promise<void> {\n if (!generator.schema) return\n const context = createMockedPluginContext(opts)\n const transformedNode = opts.plugin.transformer ? transform(node, opts.plugin.transformer) : node\n const result = await generator.schema(transformedNode, {
|
|
1
|
+
{"version":3,"file":"mocks.js","names":[],"sources":["../src/mocks.ts"],"sourcesContent":["import { resolve } from 'node:path'\nimport type { FileNode, OperationNode, SchemaNode, Visitor } from '@kubb/ast'\nimport { transform } from '@kubb/ast'\nimport { FileManager } from './FileManager.ts'\nimport { PluginDriver } from './PluginDriver.ts'\nimport { applyHookResult } from './renderNode.ts'\nimport type { Adapter, AdapterFactoryOptions, Config, Generator, GeneratorContext, NormalizedPlugin, PluginFactoryOptions } from './types.ts'\n\n/**\n * Creates a minimal `PluginDriver` mock suitable for unit tests.\n */\nexport function createMockedPluginDriver(options: { name?: string; plugin?: NormalizedPlugin; config?: Config } = {}): PluginDriver {\n return {\n config: options?.config ?? {\n root: '.',\n output: {\n path: './path',\n },\n },\n getPlugin(_pluginName: string): NormalizedPlugin | undefined {\n return options?.plugin\n },\n getResolver: (_pluginName: string) => options?.plugin?.resolver,\n fileManager: new FileManager(),\n } as unknown as PluginDriver\n}\n\n/**\n * Creates a minimal `Adapter` mock suitable for unit tests.\n *\n * - `parse` returns an empty `InputNode` by default; override via `options.parse`.\n * - `getImports` returns `[]` by default (single-file mode, no cross-file imports).\n */\nexport function createMockedAdapter<TOptions extends AdapterFactoryOptions = AdapterFactoryOptions>(\n options: {\n name?: TOptions['name']\n resolvedOptions?: TOptions['resolvedOptions']\n inputNode?: Adapter<TOptions>['inputNode']\n parse?: Adapter<TOptions>['parse']\n getImports?: Adapter<TOptions>['getImports']\n } = {},\n): Adapter<TOptions> {\n return {\n name: (options.name ?? 'oas') as TOptions['name'],\n options: (options.resolvedOptions ?? {}) as TOptions['resolvedOptions'],\n inputNode: options.inputNode ?? null,\n parse: options.parse ?? (async () => ({ kind: 'Input' as const, schemas: [], operations: [] })),\n getImports: options.getImports ?? ((_node: SchemaNode, _resolve: (schemaName: string) => { name: string; path: string }) => []),\n } as Adapter<TOptions>\n}\n\n/**\n * Creates a minimal plugin mock suitable for unit tests.\n *\n * @example\n * const plugin = createMockedPlugin<PluginTs>({ name: '@kubb/plugin-ts', options })\n */\nexport function createMockedPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>(params: {\n name: TOptions['name']\n options: TOptions['resolvedOptions']\n resolver?: TOptions['resolver']\n transformer?: Visitor\n dependencies?: Array<string>\n}): NormalizedPlugin<TOptions> {\n return {\n name: params.name,\n options: params.options,\n resolver: params.resolver,\n transformer: params.transformer,\n dependencies: params.dependencies,\n hooks: {},\n } as unknown as NormalizedPlugin<TOptions>\n}\n\ntype RenderGeneratorOptions<TOptions extends PluginFactoryOptions> = {\n config: Config\n adapter: Adapter\n driver: PluginDriver\n plugin: NormalizedPlugin<TOptions>\n options: TOptions['resolvedOptions']\n resolver: TOptions['resolver']\n}\n\nfunction createMockedPluginContext<TOptions extends PluginFactoryOptions>(opts: RenderGeneratorOptions<TOptions>): Omit<GeneratorContext<TOptions>, 'options'> {\n const root = resolve(opts.config.root, opts.config.output.path)\n\n return {\n config: opts.config,\n root,\n getMode: (output: { path: string }) => PluginDriver.getMode(resolve(root, output.path)),\n adapter: opts.adapter,\n resolver: opts.resolver,\n plugin: opts.plugin,\n driver: opts.driver,\n getResolver: (name: string) => opts.driver.getResolver(name),\n inputNode: { kind: 'Input', schemas: [], operations: [] },\n addFile: async (...files: Array<FileNode>) => opts.driver.fileManager.add(...files),\n upsertFile: async (...files: Array<FileNode>) => opts.driver.fileManager.upsert(...files),\n hooks: opts.driver.hooks ?? ({} as never),\n warn: (msg: string) => console.warn(msg),\n error: (msg: string) => console.error(msg),\n info: (msg: string) => console.info(msg),\n openInStudio: async () => {},\n } as unknown as Omit<GeneratorContext<TOptions>, 'options'>\n}\n\n/**\n * Renders a generator's `schema` method in a test context.\n *\n * @example\n * await renderGeneratorSchema(typeGenerator, node, { config, adapter, driver, plugin, options, resolver })\n * await matchFiles(driver.fileManager.files)\n */\nexport async function renderGeneratorSchema<TOptions extends PluginFactoryOptions>(\n generator: Generator<TOptions>,\n node: SchemaNode,\n opts: RenderGeneratorOptions<TOptions>,\n): Promise<void> {\n if (!generator.schema) return\n const context = createMockedPluginContext(opts)\n const transformedNode = opts.plugin.transformer ? transform(node, opts.plugin.transformer) : node\n const result = await generator.schema(transformedNode, {\n ...context,\n options: opts.options,\n })\n await applyHookResult(result, opts.driver, generator.renderer ?? undefined)\n}\n\n/**\n * Renders a generator's `operation` method in a test context.\n *\n * @example\n * await renderGeneratorOperation(typeGenerator, node, { config, adapter, driver, plugin, options, resolver })\n * await matchFiles(driver.fileManager.files)\n */\nexport async function renderGeneratorOperation<TOptions extends PluginFactoryOptions>(\n generator: Generator<TOptions>,\n node: OperationNode,\n opts: RenderGeneratorOptions<TOptions>,\n): Promise<void> {\n if (!generator.operation) return\n const context = createMockedPluginContext(opts)\n const transformedNode = opts.plugin.transformer ? transform(node, opts.plugin.transformer) : node\n const result = await generator.operation(transformedNode, {\n ...context,\n options: opts.options,\n })\n await applyHookResult(result, opts.driver, generator.renderer ?? undefined)\n}\n\n/**\n * Renders a generator's `operations` method in a test context.\n *\n * @example\n * await renderGeneratorOperations(classClientGenerator, nodes, { config, adapter, driver, plugin, options, resolver })\n * await matchFiles(driver.fileManager.files)\n */\nexport async function renderGeneratorOperations<TOptions extends PluginFactoryOptions>(\n generator: Generator<TOptions>,\n nodes: Array<OperationNode>,\n opts: RenderGeneratorOptions<TOptions>,\n): Promise<void> {\n if (!generator.operations) return\n const context = createMockedPluginContext(opts)\n const transformedNodes = opts.plugin.transformer ? nodes.map((n) => transform(n, opts.plugin.transformer!)) : nodes\n const result = await generator.operations(transformedNodes, {\n ...context,\n options: opts.options,\n })\n await applyHookResult(result, opts.driver, generator.renderer ?? undefined)\n}\n"],"mappings":";;;;;;;;AAWA,SAAgB,yBAAyB,UAAyE,EAAE,EAAgB;AAClI,QAAO;EACL,QAAQ,SAAS,UAAU;GACzB,MAAM;GACN,QAAQ,EACN,MAAM,UACP;GACF;EACD,UAAU,aAAmD;AAC3D,UAAO,SAAS;;EAElB,cAAc,gBAAwB,SAAS,QAAQ;EACvD,aAAa,IAAI,aAAa;EAC/B;;;;;;;;AASH,SAAgB,oBACd,UAMI,EAAE,EACa;AACnB,QAAO;EACL,MAAO,QAAQ,QAAQ;EACvB,SAAU,QAAQ,mBAAmB,EAAE;EACvC,WAAW,QAAQ,aAAa;EAChC,OAAO,QAAQ,UAAU,aAAa;GAAE,MAAM;GAAkB,SAAS,EAAE;GAAE,YAAY,EAAE;GAAE;EAC7F,YAAY,QAAQ,gBAAgB,OAAmB,aAAqE,EAAE;EAC/H;;;;;;;;AASH,SAAgB,mBAAiF,QAMlE;AAC7B,QAAO;EACL,MAAM,OAAO;EACb,SAAS,OAAO;EAChB,UAAU,OAAO;EACjB,aAAa,OAAO;EACpB,cAAc,OAAO;EACrB,OAAO,EAAE;EACV;;AAYH,SAAS,0BAAiE,MAAqF;CAC7J,MAAM,OAAO,QAAQ,KAAK,OAAO,MAAM,KAAK,OAAO,OAAO,KAAK;AAE/D,QAAO;EACL,QAAQ,KAAK;EACb;EACA,UAAU,WAA6B,aAAa,QAAQ,QAAQ,MAAM,OAAO,KAAK,CAAC;EACvF,SAAS,KAAK;EACd,UAAU,KAAK;EACf,QAAQ,KAAK;EACb,QAAQ,KAAK;EACb,cAAc,SAAiB,KAAK,OAAO,YAAY,KAAK;EAC5D,WAAW;GAAE,MAAM;GAAS,SAAS,EAAE;GAAE,YAAY,EAAE;GAAE;EACzD,SAAS,OAAO,GAAG,UAA2B,KAAK,OAAO,YAAY,IAAI,GAAG,MAAM;EACnF,YAAY,OAAO,GAAG,UAA2B,KAAK,OAAO,YAAY,OAAO,GAAG,MAAM;EACzF,OAAO,KAAK,OAAO,SAAU,EAAE;EAC/B,OAAO,QAAgB,QAAQ,KAAK,IAAI;EACxC,QAAQ,QAAgB,QAAQ,MAAM,IAAI;EAC1C,OAAO,QAAgB,QAAQ,KAAK,IAAI;EACxC,cAAc,YAAY;EAC3B;;;;;;;;;AAUH,eAAsB,sBACpB,WACA,MACA,MACe;AACf,KAAI,CAAC,UAAU,OAAQ;CACvB,MAAM,UAAU,0BAA0B,KAAK;CAC/C,MAAM,kBAAkB,KAAK,OAAO,cAAc,UAAU,MAAM,KAAK,OAAO,YAAY,GAAG;AAK7F,OAAM,gBAJS,MAAM,UAAU,OAAO,iBAAiB;EACrD,GAAG;EACH,SAAS,KAAK;EACf,CAAC,EAC4B,KAAK,QAAQ,UAAU,YAAY,KAAA,EAAU;;;;;;;;;AAU7E,eAAsB,yBACpB,WACA,MACA,MACe;AACf,KAAI,CAAC,UAAU,UAAW;CAC1B,MAAM,UAAU,0BAA0B,KAAK;CAC/C,MAAM,kBAAkB,KAAK,OAAO,cAAc,UAAU,MAAM,KAAK,OAAO,YAAY,GAAG;AAK7F,OAAM,gBAJS,MAAM,UAAU,UAAU,iBAAiB;EACxD,GAAG;EACH,SAAS,KAAK;EACf,CAAC,EAC4B,KAAK,QAAQ,UAAU,YAAY,KAAA,EAAU;;;;;;;;;AAU7E,eAAsB,0BACpB,WACA,OACA,MACe;AACf,KAAI,CAAC,UAAU,WAAY;CAC3B,MAAM,UAAU,0BAA0B,KAAK;CAC/C,MAAM,mBAAmB,KAAK,OAAO,cAAc,MAAM,KAAK,MAAM,UAAU,GAAG,KAAK,OAAO,YAAa,CAAC,GAAG;AAK9G,OAAM,gBAJS,MAAM,UAAU,WAAW,kBAAkB;EAC1D,GAAG;EACH,SAAS,KAAK;EACf,CAAC,EAC4B,KAAK,QAAQ,UAAU,YAAY,KAAA,EAAU"}
|
|
@@ -1089,20 +1089,20 @@ type Config<TInput = Input> = {
|
|
|
1089
1089
|
storage?: Storage;
|
|
1090
1090
|
/**
|
|
1091
1091
|
* Specifies the formatting tool to be used.
|
|
1092
|
-
* - 'auto' automatically detects and uses biome or prettier (in that order of preference).
|
|
1092
|
+
* - 'auto' automatically detects and uses oxfmt, biome, or prettier (in that order of preference).
|
|
1093
|
+
* - 'oxfmt' uses Oxfmt for code formatting.
|
|
1093
1094
|
* - 'prettier' uses Prettier for code formatting.
|
|
1094
1095
|
* - 'biome' uses Biome for code formatting.
|
|
1095
|
-
* - 'oxfmt' uses Oxfmt for code formatting.
|
|
1096
1096
|
* - false disables code formatting.
|
|
1097
1097
|
* @default 'prettier'
|
|
1098
1098
|
*/
|
|
1099
1099
|
format?: 'auto' | 'prettier' | 'biome' | 'oxfmt' | false;
|
|
1100
1100
|
/**
|
|
1101
1101
|
* Specifies the linter that should be used to analyze the code.
|
|
1102
|
-
* - 'auto' automatically detects and uses
|
|
1102
|
+
* - 'auto' automatically detects and uses oxlint, biome, or eslint (in that order of preference).
|
|
1103
|
+
* - 'oxlint' uses Oxlint for linting.
|
|
1103
1104
|
* - 'eslint' uses ESLint for linting.
|
|
1104
1105
|
* - 'biome' uses Biome for linting.
|
|
1105
|
-
* - 'oxlint' uses Oxlint for linting.
|
|
1106
1106
|
* - false disables linting.
|
|
1107
1107
|
* @default 'auto'
|
|
1108
1108
|
*/
|
|
@@ -1445,7 +1445,7 @@ type Output<_TOptions = unknown> = {
|
|
|
1445
1445
|
*/
|
|
1446
1446
|
override?: boolean;
|
|
1447
1447
|
};
|
|
1448
|
-
type
|
|
1448
|
+
type Group = {
|
|
1449
1449
|
/**
|
|
1450
1450
|
* Determines how files are grouped into subdirectories.
|
|
1451
1451
|
* - `'tag'` groups files by OpenAPI tags.
|
|
@@ -1460,20 +1460,6 @@ type UserGroup = {
|
|
|
1460
1460
|
group: string;
|
|
1461
1461
|
}) => string;
|
|
1462
1462
|
};
|
|
1463
|
-
type Group = {
|
|
1464
|
-
/**
|
|
1465
|
-
* Determines how files are grouped into subdirectories.
|
|
1466
|
-
* - `'tag'` groups files by OpenAPI tags.
|
|
1467
|
-
* - `'path'` groups files by OpenAPI paths.
|
|
1468
|
-
*/
|
|
1469
|
-
type: 'tag' | 'path';
|
|
1470
|
-
/**
|
|
1471
|
-
* Returns the subdirectory name for a given group value.
|
|
1472
|
-
*/
|
|
1473
|
-
name: (context: {
|
|
1474
|
-
group: string;
|
|
1475
|
-
}) => string;
|
|
1476
|
-
};
|
|
1477
1463
|
type LoggerOptions = {
|
|
1478
1464
|
/**
|
|
1479
1465
|
* @default 3
|
|
@@ -1731,5 +1717,5 @@ type CLIOptions = {
|
|
|
1731
1717
|
*/
|
|
1732
1718
|
type PossibleConfig<TCliOptions = undefined> = PossiblePromise<Config | Config[]> | ((...args: [TCliOptions] extends [undefined] ? [] : [TCliOptions]) => PossiblePromise<Config | Config[]>);
|
|
1733
1719
|
//#endregion
|
|
1734
|
-
export {
|
|
1735
|
-
//# sourceMappingURL=types-
|
|
1720
|
+
export { AsyncEventEmitter as $, ResolverFileParams as A, createKubb as B, PluginFactoryOptions as C, ResolveOptionsContext as D, ResolveNameParams as E, Plugin as F, Generator as G, FileManager as H, definePlugin as I, createStorage as J, defineGenerator as K, Kubb$1 as L, UserConfig as M, UserLogger as N, Resolver as O, FileMetaBase as P, logLevel as Q, KubbHooks as R, Override as S, ResolveBannerContext as T, Parser as U, PluginDriver as V, defineParser as W, RendererFactory as X, Renderer as Y, createRenderer as Z, Logger as _, CLIOptions as a, NormalizedPlugin as b, Exclude$1 as c, Include as d, InputData as f, KubbPluginSetupContext as g, KubbBuildStartContext as h, BarrelType as i, ResolverPathParams as j, ResolverContext as k, GeneratorContext as l, KubbBuildEndContext as m, AdapterFactoryOptions as n, Config as o, InputPath as p, Storage as q, AdapterSource as r, DevtoolsOptions as s, Adapter as t, Group as u, LoggerContext as v, PossibleConfig as w, Output as x, LoggerOptions as y, BuildOutput as z };
|
|
1721
|
+
//# sourceMappingURL=types-DfEv9d_c.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,31 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/core",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.49",
|
|
4
4
|
"description": "Core functionality for Kubb's plugin-based code generation system, providing the foundation for transforming OpenAPI specifications.",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"plugins",
|
|
8
|
-
"plugin-system",
|
|
9
|
-
"plugin-framework",
|
|
6
|
+
"ast",
|
|
10
7
|
"code-generator",
|
|
11
8
|
"codegen",
|
|
12
|
-
"
|
|
9
|
+
"core-library",
|
|
13
10
|
"file-system",
|
|
11
|
+
"kubb",
|
|
12
|
+
"oas",
|
|
14
13
|
"openapi",
|
|
14
|
+
"plugin-framework",
|
|
15
|
+
"plugin-system",
|
|
16
|
+
"plugins",
|
|
15
17
|
"swagger",
|
|
16
|
-
"
|
|
17
|
-
"core-library",
|
|
18
|
-
"kubb"
|
|
18
|
+
"typescript"
|
|
19
19
|
],
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"author": "stijnvanhulle",
|
|
20
22
|
"repository": {
|
|
21
23
|
"type": "git",
|
|
22
24
|
"url": "git+https://github.com/kubb-labs/kubb.git",
|
|
23
25
|
"directory": "packages/core"
|
|
24
26
|
},
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
"files": [
|
|
28
|
+
"src",
|
|
29
|
+
"schemas",
|
|
30
|
+
"dist",
|
|
31
|
+
"*.d.ts",
|
|
32
|
+
"*.d.cts",
|
|
33
|
+
"schema.json",
|
|
34
|
+
"!/**/**.test.**",
|
|
35
|
+
"!/**/__tests__/**",
|
|
36
|
+
"!/**/__snapshots__/**"
|
|
37
|
+
],
|
|
28
38
|
"type": "module",
|
|
39
|
+
"sideEffects": false,
|
|
40
|
+
"main": "./dist/index.cjs",
|
|
41
|
+
"module": "./dist/index.js",
|
|
42
|
+
"types": "./dist/index.d.ts",
|
|
43
|
+
"typesVersions": {
|
|
44
|
+
"*": {
|
|
45
|
+
"mocks": [
|
|
46
|
+
"./dist/mocks.d.ts"
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
},
|
|
29
50
|
"exports": {
|
|
30
51
|
".": {
|
|
31
52
|
"import": "./dist/index.js",
|
|
@@ -37,54 +58,33 @@
|
|
|
37
58
|
},
|
|
38
59
|
"./package.json": "./package.json"
|
|
39
60
|
},
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
"mocks": [
|
|
44
|
-
"./dist/mocks.d.ts"
|
|
45
|
-
]
|
|
46
|
-
}
|
|
61
|
+
"publishConfig": {
|
|
62
|
+
"access": "public",
|
|
63
|
+
"registry": "https://registry.npmjs.org/"
|
|
47
64
|
},
|
|
48
|
-
"files": [
|
|
49
|
-
"src",
|
|
50
|
-
"schemas",
|
|
51
|
-
"dist",
|
|
52
|
-
"*.d.ts",
|
|
53
|
-
"*.d.cts",
|
|
54
|
-
"schema.json",
|
|
55
|
-
"!/**/**.test.**",
|
|
56
|
-
"!/**/__tests__/**",
|
|
57
|
-
"!/**/__snapshots__/**"
|
|
58
|
-
],
|
|
59
|
-
"size-limit": [
|
|
60
|
-
{
|
|
61
|
-
"path": "./dist/*.js",
|
|
62
|
-
"limit": "510 KiB",
|
|
63
|
-
"gzip": true
|
|
64
|
-
}
|
|
65
|
-
],
|
|
66
65
|
"dependencies": {
|
|
67
66
|
"fflate": "^0.8.2",
|
|
68
67
|
"tinyexec": "^1.1.1",
|
|
69
|
-
"@kubb/ast": "5.0.0-alpha.
|
|
68
|
+
"@kubb/ast": "5.0.0-alpha.49"
|
|
70
69
|
},
|
|
71
70
|
"devDependencies": {
|
|
72
71
|
"p-limit": "^7.3.0",
|
|
73
72
|
"@internals/utils": "0.0.0",
|
|
74
|
-
"@kubb/renderer-jsx": "5.0.0-alpha.
|
|
73
|
+
"@kubb/renderer-jsx": "5.0.0-alpha.49"
|
|
75
74
|
},
|
|
76
75
|
"peerDependencies": {
|
|
77
|
-
"@kubb/renderer-jsx": "5.0.0-alpha.
|
|
76
|
+
"@kubb/renderer-jsx": "5.0.0-alpha.49"
|
|
78
77
|
},
|
|
78
|
+
"size-limit": [
|
|
79
|
+
{
|
|
80
|
+
"path": "./dist/*.js",
|
|
81
|
+
"limit": "510 KiB",
|
|
82
|
+
"gzip": true
|
|
83
|
+
}
|
|
84
|
+
],
|
|
79
85
|
"engines": {
|
|
80
86
|
"node": ">=22"
|
|
81
87
|
},
|
|
82
|
-
"publishConfig": {
|
|
83
|
-
"access": "public",
|
|
84
|
-
"registry": "https://registry.npmjs.org/"
|
|
85
|
-
},
|
|
86
|
-
"main": "./dist/index.cjs",
|
|
87
|
-
"module": "./dist/index.js",
|
|
88
88
|
"inlinedDependencies": {
|
|
89
89
|
"p-limit": "7.3.0",
|
|
90
90
|
"yocto-queue": "1.2.2"
|
|
@@ -92,8 +92,8 @@
|
|
|
92
92
|
"scripts": {
|
|
93
93
|
"build": "tsdown && size-limit",
|
|
94
94
|
"clean": "npx rimraf ./dist",
|
|
95
|
-
"lint": "
|
|
96
|
-
"lint:fix": "
|
|
95
|
+
"lint": "oxlint .",
|
|
96
|
+
"lint:fix": "oxlint --fix .",
|
|
97
97
|
"release": "pnpm publish --no-git-check",
|
|
98
98
|
"release:canary": "bash ../../.github/canary.sh && node ../../scripts/build.js canary && pnpm publish --no-git-check",
|
|
99
99
|
"start": "tsdown --watch",
|
package/src/FileManager.ts
CHANGED
|
@@ -106,7 +106,10 @@ export class FileManager {
|
|
|
106
106
|
const keys = [...this.#cache.keys()]
|
|
107
107
|
const meta = new Map<string, { length: number; isIndex: boolean }>()
|
|
108
108
|
for (const key of keys) {
|
|
109
|
-
meta.set(key, {
|
|
109
|
+
meta.set(key, {
|
|
110
|
+
length: key.length,
|
|
111
|
+
isIndex: trimExtName(key).endsWith(BARREL_BASENAME),
|
|
112
|
+
})
|
|
110
113
|
}
|
|
111
114
|
keys.sort((a, b) => {
|
|
112
115
|
const ma = meta.get(a)!
|
package/src/Kubb.ts
CHANGED
|
@@ -149,7 +149,15 @@ export interface KubbHooks {
|
|
|
149
149
|
/**
|
|
150
150
|
* Emitted when a single hook execution completes.
|
|
151
151
|
*/
|
|
152
|
-
'kubb:hook:end': [
|
|
152
|
+
'kubb:hook:end': [
|
|
153
|
+
{
|
|
154
|
+
id?: string
|
|
155
|
+
command: string
|
|
156
|
+
args?: readonly string[]
|
|
157
|
+
success: boolean
|
|
158
|
+
error: Error | null
|
|
159
|
+
},
|
|
160
|
+
]
|
|
153
161
|
|
|
154
162
|
/**
|
|
155
163
|
* Emitted when a new version of Kubb is available.
|
package/src/createKubb.ts
CHANGED
|
@@ -201,7 +201,12 @@ async function runPluginAstHooks(plugin: NormalizedPlugin, context: GeneratorCon
|
|
|
201
201
|
depth: 'shallow',
|
|
202
202
|
async schema(node) {
|
|
203
203
|
const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node
|
|
204
|
-
const options = resolver.resolveOptions(transformedNode, {
|
|
204
|
+
const options = resolver.resolveOptions(transformedNode, {
|
|
205
|
+
options: plugin.options,
|
|
206
|
+
exclude,
|
|
207
|
+
include,
|
|
208
|
+
override,
|
|
209
|
+
})
|
|
205
210
|
if (options === null) return
|
|
206
211
|
|
|
207
212
|
const ctx = { ...generatorContext, options }
|
|
@@ -216,7 +221,12 @@ async function runPluginAstHooks(plugin: NormalizedPlugin, context: GeneratorCon
|
|
|
216
221
|
},
|
|
217
222
|
async operation(node) {
|
|
218
223
|
const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node
|
|
219
|
-
const options = resolver.resolveOptions(transformedNode, {
|
|
224
|
+
const options = resolver.resolveOptions(transformedNode, {
|
|
225
|
+
options: plugin.options,
|
|
226
|
+
exclude,
|
|
227
|
+
include,
|
|
228
|
+
override,
|
|
229
|
+
})
|
|
220
230
|
if (options !== null) {
|
|
221
231
|
collectedOperations.push(transformedNode)
|
|
222
232
|
|
|
@@ -298,7 +308,10 @@ async function safeBuild(setupResult: SetupResult): Promise<BuildOutput> {
|
|
|
298
308
|
const duration = getElapsedMs(hrStart)
|
|
299
309
|
pluginTimings.set(plugin.name, duration)
|
|
300
310
|
|
|
301
|
-
await hooks.emit('kubb:plugin:end', plugin, {
|
|
311
|
+
await hooks.emit('kubb:plugin:end', plugin, {
|
|
312
|
+
duration,
|
|
313
|
+
success: true,
|
|
314
|
+
})
|
|
302
315
|
|
|
303
316
|
await hooks.emit('kubb:debug', {
|
|
304
317
|
date: new Date(),
|
|
@@ -357,7 +370,13 @@ async function safeBuild(setupResult: SetupResult): Promise<BuildOutput> {
|
|
|
357
370
|
const rootFile = createFile<object>({
|
|
358
371
|
path: rootPath,
|
|
359
372
|
baseName: BARREL_FILENAME,
|
|
360
|
-
exports: buildBarrelExports({
|
|
373
|
+
exports: buildBarrelExports({
|
|
374
|
+
barrelFiles,
|
|
375
|
+
rootDir,
|
|
376
|
+
existingExports,
|
|
377
|
+
config,
|
|
378
|
+
driver,
|
|
379
|
+
}).map((e) => createExport(e)),
|
|
361
380
|
sources: [],
|
|
362
381
|
imports: [],
|
|
363
382
|
meta: {},
|
package/src/defineResolver.ts
CHANGED
|
@@ -217,7 +217,13 @@ export function defaultResolvePath({ baseName, pathMode, tag, path: groupPath }:
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
if (group && (groupPath || tag)) {
|
|
220
|
-
|
|
220
|
+
const groupValue = group.type === 'path' ? groupPath! : tag!
|
|
221
|
+
const defaultName =
|
|
222
|
+
group.type === 'tag'
|
|
223
|
+
? ({ group: g }: { group: string }) => `${camelCase(g)}Controller`
|
|
224
|
+
: ({ group: g }: { group: string }) => g.split('/').filter(Boolean)[0] ?? g
|
|
225
|
+
const resolveName = group.name ?? defaultName
|
|
226
|
+
return path.resolve(root, output.path, resolveName({ group: groupValue }), baseName)
|
|
221
227
|
}
|
|
222
228
|
|
|
223
229
|
return path.resolve(root, output.path, baseName)
|
|
@@ -376,7 +382,11 @@ export function defaultResolveBanner(node: InputNode | undefined, { output, conf
|
|
|
376
382
|
return undefined
|
|
377
383
|
}
|
|
378
384
|
|
|
379
|
-
return buildDefaultBanner({
|
|
385
|
+
return buildDefaultBanner({
|
|
386
|
+
title: node?.meta?.title,
|
|
387
|
+
version: node?.meta?.version,
|
|
388
|
+
config,
|
|
389
|
+
})
|
|
380
390
|
}
|
|
381
391
|
|
|
382
392
|
/**
|
package/src/mocks.ts
CHANGED
|
@@ -119,7 +119,10 @@ export async function renderGeneratorSchema<TOptions extends PluginFactoryOption
|
|
|
119
119
|
if (!generator.schema) return
|
|
120
120
|
const context = createMockedPluginContext(opts)
|
|
121
121
|
const transformedNode = opts.plugin.transformer ? transform(node, opts.plugin.transformer) : node
|
|
122
|
-
const result = await generator.schema(transformedNode, {
|
|
122
|
+
const result = await generator.schema(transformedNode, {
|
|
123
|
+
...context,
|
|
124
|
+
options: opts.options,
|
|
125
|
+
})
|
|
123
126
|
await applyHookResult(result, opts.driver, generator.renderer ?? undefined)
|
|
124
127
|
}
|
|
125
128
|
|
|
@@ -138,7 +141,10 @@ export async function renderGeneratorOperation<TOptions extends PluginFactoryOpt
|
|
|
138
141
|
if (!generator.operation) return
|
|
139
142
|
const context = createMockedPluginContext(opts)
|
|
140
143
|
const transformedNode = opts.plugin.transformer ? transform(node, opts.plugin.transformer) : node
|
|
141
|
-
const result = await generator.operation(transformedNode, {
|
|
144
|
+
const result = await generator.operation(transformedNode, {
|
|
145
|
+
...context,
|
|
146
|
+
options: opts.options,
|
|
147
|
+
})
|
|
142
148
|
await applyHookResult(result, opts.driver, generator.renderer ?? undefined)
|
|
143
149
|
}
|
|
144
150
|
|
|
@@ -157,6 +163,9 @@ export async function renderGeneratorOperations<TOptions extends PluginFactoryOp
|
|
|
157
163
|
if (!generator.operations) return
|
|
158
164
|
const context = createMockedPluginContext(opts)
|
|
159
165
|
const transformedNodes = opts.plugin.transformer ? nodes.map((n) => transform(n, opts.plugin.transformer!)) : nodes
|
|
160
|
-
const result = await generator.operations(transformedNodes, {
|
|
166
|
+
const result = await generator.operations(transformedNodes, {
|
|
167
|
+
...context,
|
|
168
|
+
options: opts.options,
|
|
169
|
+
})
|
|
161
170
|
await applyHookResult(result, opts.driver, generator.renderer ?? undefined)
|
|
162
171
|
}
|
|
@@ -46,7 +46,9 @@ export const fsStorage = createStorage(() => ({
|
|
|
46
46
|
return false
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
throw new Error(`Failed to access storage item "${key}"`, {
|
|
49
|
+
throw new Error(`Failed to access storage item "${key}"`, {
|
|
50
|
+
cause: error as Error,
|
|
51
|
+
})
|
|
50
52
|
}
|
|
51
53
|
},
|
|
52
54
|
async getItem(key: string) {
|
|
@@ -57,7 +59,9 @@ export const fsStorage = createStorage(() => ({
|
|
|
57
59
|
return null
|
|
58
60
|
}
|
|
59
61
|
|
|
60
|
-
throw new Error(`Failed to read storage item "${key}"`, {
|
|
62
|
+
throw new Error(`Failed to read storage item "${key}"`, {
|
|
63
|
+
cause: error as Error,
|
|
64
|
+
})
|
|
61
65
|
}
|
|
62
66
|
},
|
|
63
67
|
async setItem(key: string, value: string) {
|
|
@@ -73,13 +77,17 @@ export const fsStorage = createStorage(() => ({
|
|
|
73
77
|
async function walk(dir: string, prefix: string): Promise<void> {
|
|
74
78
|
let entries: Array<Dirent>
|
|
75
79
|
try {
|
|
76
|
-
entries = (await readdir(dir, {
|
|
80
|
+
entries = (await readdir(dir, {
|
|
81
|
+
withFileTypes: true,
|
|
82
|
+
})) as Array<Dirent>
|
|
77
83
|
} catch (error) {
|
|
78
84
|
if (isMissingPathError(error)) {
|
|
79
85
|
return
|
|
80
86
|
}
|
|
81
87
|
|
|
82
|
-
throw new Error(`Failed to list storage keys under "${resolvedBase}"`, {
|
|
88
|
+
throw new Error(`Failed to list storage keys under "${resolvedBase}"`, {
|
|
89
|
+
cause: error as Error,
|
|
90
|
+
})
|
|
83
91
|
}
|
|
84
92
|
for (const entry of entries) {
|
|
85
93
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name
|
package/src/types.ts
CHANGED
|
@@ -202,20 +202,20 @@ export type Config<TInput = Input> = {
|
|
|
202
202
|
storage?: Storage
|
|
203
203
|
/**
|
|
204
204
|
* Specifies the formatting tool to be used.
|
|
205
|
-
* - 'auto' automatically detects and uses biome or prettier (in that order of preference).
|
|
205
|
+
* - 'auto' automatically detects and uses oxfmt, biome, or prettier (in that order of preference).
|
|
206
|
+
* - 'oxfmt' uses Oxfmt for code formatting.
|
|
206
207
|
* - 'prettier' uses Prettier for code formatting.
|
|
207
208
|
* - 'biome' uses Biome for code formatting.
|
|
208
|
-
* - 'oxfmt' uses Oxfmt for code formatting.
|
|
209
209
|
* - false disables code formatting.
|
|
210
210
|
* @default 'prettier'
|
|
211
211
|
*/
|
|
212
212
|
format?: 'auto' | 'prettier' | 'biome' | 'oxfmt' | false
|
|
213
213
|
/**
|
|
214
214
|
* Specifies the linter that should be used to analyze the code.
|
|
215
|
-
* - 'auto' automatically detects and uses
|
|
215
|
+
* - 'auto' automatically detects and uses oxlint, biome, or eslint (in that order of preference).
|
|
216
|
+
* - 'oxlint' uses Oxlint for linting.
|
|
216
217
|
* - 'eslint' uses ESLint for linting.
|
|
217
218
|
* - 'biome' uses Biome for linting.
|
|
218
|
-
* - 'oxlint' uses Oxlint for linting.
|
|
219
219
|
* - false disables linting.
|
|
220
220
|
* @default 'auto'
|
|
221
221
|
*/
|
|
@@ -570,7 +570,7 @@ export type Output<_TOptions = unknown> = {
|
|
|
570
570
|
override?: boolean
|
|
571
571
|
}
|
|
572
572
|
|
|
573
|
-
export type
|
|
573
|
+
export type Group = {
|
|
574
574
|
/**
|
|
575
575
|
* Determines how files are grouped into subdirectories.
|
|
576
576
|
* - `'tag'` groups files by OpenAPI tags.
|
|
@@ -584,19 +584,6 @@ export type UserGroup = {
|
|
|
584
584
|
name?: (context: { group: string }) => string
|
|
585
585
|
}
|
|
586
586
|
|
|
587
|
-
export type Group = {
|
|
588
|
-
/**
|
|
589
|
-
* Determines how files are grouped into subdirectories.
|
|
590
|
-
* - `'tag'` groups files by OpenAPI tags.
|
|
591
|
-
* - `'path'` groups files by OpenAPI paths.
|
|
592
|
-
*/
|
|
593
|
-
type: 'tag' | 'path'
|
|
594
|
-
/**
|
|
595
|
-
* Returns the subdirectory name for a given group value.
|
|
596
|
-
*/
|
|
597
|
-
name: (context: { group: string }) => string
|
|
598
|
-
}
|
|
599
|
-
|
|
600
587
|
export type LoggerOptions = {
|
|
601
588
|
/**
|
|
602
589
|
* @default 3
|
|
@@ -661,7 +648,11 @@ export type KubbPluginSetupContext<TFactory extends PluginFactoryOptions = Plugi
|
|
|
661
648
|
/**
|
|
662
649
|
* Inject a raw file into the build output, bypassing the normal generation pipeline.
|
|
663
650
|
*/
|
|
664
|
-
injectFile(
|
|
651
|
+
injectFile(
|
|
652
|
+
file: Pick<FileNode, 'baseName' | 'path'> & {
|
|
653
|
+
sources?: FileNode['sources']
|
|
654
|
+
},
|
|
655
|
+
): void
|
|
665
656
|
/**
|
|
666
657
|
* Merge a partial config update into the current build configuration.
|
|
667
658
|
*/
|