@kubb/core 5.0.0-alpha.5 → 5.0.0-alpha.50
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-DtwggkXg.cjs +1082 -0
- package/dist/PluginDriver-DtwggkXg.cjs.map +1 -0
- package/dist/PluginDriver-mXeqWp-U.js +979 -0
- package/dist/PluginDriver-mXeqWp-U.js.map +1 -0
- package/dist/index.cjs +1013 -1829
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +274 -265
- package/dist/index.js +1003 -1799
- package/dist/index.js.map +1 -1
- package/dist/mocks.cjs +138 -0
- package/dist/mocks.cjs.map +1 -0
- package/dist/mocks.d.ts +74 -0
- package/dist/mocks.js +133 -0
- package/dist/mocks.js.map +1 -0
- package/dist/types-DfEv9d_c.d.ts +1721 -0
- package/package.json +51 -57
- package/src/FileManager.ts +133 -0
- package/src/FileProcessor.ts +86 -0
- package/src/Kubb.ts +154 -101
- package/src/PluginDriver.ts +418 -0
- package/src/constants.ts +43 -47
- package/src/createAdapter.ts +25 -0
- package/src/createKubb.ts +614 -0
- package/src/createRenderer.ts +57 -0
- package/src/createStorage.ts +58 -0
- package/src/defineGenerator.ts +88 -100
- package/src/defineLogger.ts +13 -3
- package/src/defineParser.ts +45 -0
- package/src/definePlugin.ts +68 -7
- package/src/defineResolver.ts +501 -0
- package/src/devtools.ts +14 -14
- package/src/index.ts +12 -17
- package/src/mocks.ts +171 -0
- package/src/renderNode.ts +35 -0
- package/src/storages/fsStorage.ts +40 -11
- package/src/storages/memoryStorage.ts +4 -3
- package/src/types.ts +575 -205
- package/src/utils/TreeNode.ts +47 -9
- package/src/utils/diagnostics.ts +4 -1
- package/src/utils/getBarrelFiles.ts +94 -16
- package/src/utils/isInputPath.ts +10 -0
- package/src/utils/packageJSON.ts +99 -0
- package/dist/PluginManager-vZodFEMe.d.ts +0 -1056
- package/dist/chunk-ByKO4r7w.cjs +0 -38
- package/dist/hooks.cjs +0 -60
- package/dist/hooks.cjs.map +0 -1
- package/dist/hooks.d.ts +0 -56
- package/dist/hooks.js +0 -56
- package/dist/hooks.js.map +0 -1
- package/src/BarrelManager.ts +0 -74
- package/src/PackageManager.ts +0 -180
- package/src/PluginManager.ts +0 -667
- package/src/PromiseManager.ts +0 -40
- package/src/build.ts +0 -419
- package/src/config.ts +0 -56
- package/src/defineAdapter.ts +0 -22
- package/src/defineStorage.ts +0 -56
- package/src/errors.ts +0 -1
- package/src/hooks/index.ts +0 -4
- package/src/hooks/useKubb.ts +0 -46
- package/src/hooks/useMode.ts +0 -11
- package/src/hooks/usePlugin.ts +0 -11
- package/src/hooks/usePluginManager.ts +0 -11
- package/src/utils/FunctionParams.ts +0 -155
- package/src/utils/executeStrategies.ts +0 -81
- package/src/utils/formatters.ts +0 -56
- package/src/utils/getConfigs.ts +0 -30
- package/src/utils/getPlugins.ts +0 -23
- package/src/utils/linters.ts +0 -25
- package/src/utils/resolveOptions.ts +0 -93
package/dist/index.cjs
CHANGED
|
@@ -1,37 +1,21 @@
|
|
|
1
|
-
Object.
|
|
2
|
-
|
|
3
|
-
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
-
});
|
|
5
|
-
const require_chunk = require("./chunk-ByKO4r7w.cjs");
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_PluginDriver = require("./PluginDriver-DtwggkXg.cjs");
|
|
6
3
|
let node_events = require("node:events");
|
|
7
|
-
let node_util = require("node:util");
|
|
8
|
-
let node_fs = require("node:fs");
|
|
9
4
|
let node_fs_promises = require("node:fs/promises");
|
|
10
5
|
let node_path = require("node:path");
|
|
11
|
-
node_path =
|
|
6
|
+
node_path = require_PluginDriver.__toESM(node_path, 1);
|
|
12
7
|
let _kubb_ast = require("@kubb/ast");
|
|
13
|
-
|
|
14
|
-
let _kubb_react_fabric_parsers = require("@kubb/react-fabric/parsers");
|
|
15
|
-
let _kubb_react_fabric_plugins = require("@kubb/react-fabric/plugins");
|
|
16
|
-
let node_perf_hooks = require("node:perf_hooks");
|
|
17
|
-
let fflate = require("fflate");
|
|
18
|
-
let tinyexec = require("tinyexec");
|
|
8
|
+
_kubb_ast = require_PluginDriver.__toESM(_kubb_ast, 1);
|
|
19
9
|
let node_process = require("node:process");
|
|
20
|
-
|
|
21
|
-
node_module = require_chunk.__toESM(node_module);
|
|
22
|
-
let node_os = require("node:os");
|
|
23
|
-
node_os = require_chunk.__toESM(node_os);
|
|
24
|
-
let node_url = require("node:url");
|
|
25
|
-
let empathic_package = require("empathic/package");
|
|
26
|
-
empathic_package = require_chunk.__toESM(empathic_package);
|
|
27
|
-
let semver = require("semver");
|
|
28
|
-
let remeda = require("remeda");
|
|
29
|
-
//#region ../../internals/utils/dist/index.js
|
|
30
|
-
/** Thrown when a plugin's configuration or input fails validation. */
|
|
31
|
-
var ValidationPluginError = class extends Error {};
|
|
10
|
+
//#region ../../internals/utils/src/errors.ts
|
|
32
11
|
/**
|
|
33
12
|
* Thrown when one or more errors occur during a Kubb build.
|
|
34
13
|
* Carries the full list of underlying errors on `errors`.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* throw new BuildError('Build failed', { errors: [err1, err2] })
|
|
18
|
+
* ```
|
|
35
19
|
*/
|
|
36
20
|
var BuildError = class extends Error {
|
|
37
21
|
errors;
|
|
@@ -43,19 +27,34 @@ var BuildError = class extends Error {
|
|
|
43
27
|
};
|
|
44
28
|
/**
|
|
45
29
|
* Coerces an unknown thrown value to an `Error` instance.
|
|
46
|
-
*
|
|
47
|
-
*
|
|
30
|
+
* Returns the value as-is when it is already an `Error`; otherwise wraps it with `String(value)`.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* try { ... } catch(err) {
|
|
35
|
+
* throw new BuildError('Build failed', { cause: toError(err), errors: [] })
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
48
38
|
*/
|
|
49
39
|
function toError(value) {
|
|
50
40
|
return value instanceof Error ? value : new Error(String(value));
|
|
51
41
|
}
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region ../../internals/utils/src/asyncEventEmitter.ts
|
|
52
44
|
/**
|
|
53
|
-
*
|
|
45
|
+
* Typed `EventEmitter` that awaits all async listeners before resolving.
|
|
54
46
|
* Wraps Node's `EventEmitter` with full TypeScript event-map inference.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* const emitter = new AsyncEventEmitter<{ build: [name: string] }>()
|
|
51
|
+
* emitter.on('build', async (name) => { console.log(name) })
|
|
52
|
+
* await emitter.emit('build', 'petstore') // all listeners awaited
|
|
53
|
+
* ```
|
|
55
54
|
*/
|
|
56
55
|
var AsyncEventEmitter = class {
|
|
57
56
|
/**
|
|
58
|
-
*
|
|
57
|
+
* Maximum number of listeners per event before Node emits a memory-leak warning.
|
|
59
58
|
* @default 10
|
|
60
59
|
*/
|
|
61
60
|
constructor(maxListener = 10) {
|
|
@@ -63,31 +62,48 @@ var AsyncEventEmitter = class {
|
|
|
63
62
|
}
|
|
64
63
|
#emitter = new node_events.EventEmitter();
|
|
65
64
|
/**
|
|
66
|
-
* Emits
|
|
65
|
+
* Emits `eventName` and awaits all registered listeners sequentially.
|
|
67
66
|
* Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* await emitter.emit('build', 'petstore')
|
|
71
|
+
* ```
|
|
68
72
|
*/
|
|
69
73
|
async emit(eventName, ...eventArgs) {
|
|
70
74
|
const listeners = this.#emitter.listeners(eventName);
|
|
71
75
|
if (listeners.length === 0) return;
|
|
72
|
-
|
|
76
|
+
for (const listener of listeners) try {
|
|
77
|
+
await listener(...eventArgs);
|
|
78
|
+
} catch (err) {
|
|
79
|
+
let serializedArgs;
|
|
73
80
|
try {
|
|
74
|
-
|
|
75
|
-
} catch
|
|
76
|
-
|
|
77
|
-
try {
|
|
78
|
-
serializedArgs = JSON.stringify(eventArgs);
|
|
79
|
-
} catch {
|
|
80
|
-
serializedArgs = String(eventArgs);
|
|
81
|
-
}
|
|
82
|
-
throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
|
|
81
|
+
serializedArgs = JSON.stringify(eventArgs);
|
|
82
|
+
} catch {
|
|
83
|
+
serializedArgs = String(eventArgs);
|
|
83
84
|
}
|
|
84
|
-
|
|
85
|
+
throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
|
|
86
|
+
}
|
|
85
87
|
}
|
|
86
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Registers a persistent listener for `eventName`.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* emitter.on('build', async (name) => { console.log(name) })
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
87
96
|
on(eventName, handler) {
|
|
88
97
|
this.#emitter.on(eventName, handler);
|
|
89
98
|
}
|
|
90
|
-
/**
|
|
99
|
+
/**
|
|
100
|
+
* Registers a one-shot listener that removes itself after the first invocation.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* emitter.onOnce('build', async (name) => { console.log(name) })
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
91
107
|
onOnce(eventName, handler) {
|
|
92
108
|
const wrapper = (...args) => {
|
|
93
109
|
this.off(eventName, wrapper);
|
|
@@ -95,237 +111,53 @@ var AsyncEventEmitter = class {
|
|
|
95
111
|
};
|
|
96
112
|
this.on(eventName, wrapper);
|
|
97
113
|
}
|
|
98
|
-
/**
|
|
114
|
+
/**
|
|
115
|
+
* Removes a previously registered listener.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* emitter.off('build', handler)
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
99
122
|
off(eventName, handler) {
|
|
100
123
|
this.#emitter.off(eventName, handler);
|
|
101
124
|
}
|
|
102
|
-
/**
|
|
125
|
+
/**
|
|
126
|
+
* Returns the number of listeners registered for `eventName`.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```ts
|
|
130
|
+
* emitter.on('build', handler)
|
|
131
|
+
* emitter.listenerCount('build') // 1
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
listenerCount(eventName) {
|
|
135
|
+
return this.#emitter.listenerCount(eventName);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Removes all listeners from every event channel.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* emitter.removeAll()
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
103
145
|
removeAll() {
|
|
104
146
|
this.#emitter.removeAllListeners();
|
|
105
147
|
}
|
|
106
148
|
};
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region ../../internals/utils/src/time.ts
|
|
107
151
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* and capitalizes each word according to `pascal`.
|
|
111
|
-
*
|
|
112
|
-
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
113
|
-
*/
|
|
114
|
-
function toCamelOrPascal(text, pascal) {
|
|
115
|
-
return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
|
|
116
|
-
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
117
|
-
if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
|
|
118
|
-
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
119
|
-
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Splits `text` on `.` and applies `transformPart` to each segment.
|
|
123
|
-
* The last segment receives `isLast = true`, all earlier segments receive `false`.
|
|
124
|
-
* Segments are joined with `/` to form a file path.
|
|
125
|
-
*/
|
|
126
|
-
function applyToFileParts(text, transformPart) {
|
|
127
|
-
const parts = text.split(".");
|
|
128
|
-
return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Converts `text` to camelCase.
|
|
132
|
-
* When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
|
|
152
|
+
* Calculates elapsed time in milliseconds from a high-resolution `process.hrtime` start time.
|
|
153
|
+
* Rounds to 2 decimal places for sub-millisecond precision without noise.
|
|
133
154
|
*
|
|
134
155
|
* @example
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
prefix,
|
|
141
|
-
suffix
|
|
142
|
-
} : {}));
|
|
143
|
-
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
144
|
-
}
|
|
145
|
-
/** Returns a `CLIAdapter` with type inference. Pass a different adapter to `createCLI` to swap the CLI engine. */
|
|
146
|
-
function defineCLIAdapter(adapter) {
|
|
147
|
-
return adapter;
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Serializes `CommandDefinition[]` to a plain, JSON-serializable structure.
|
|
151
|
-
* Use to expose CLI capabilities to AI agents or MCP tools.
|
|
152
|
-
*/
|
|
153
|
-
function getCommandSchema(defs) {
|
|
154
|
-
return defs.map(serializeCommand);
|
|
155
|
-
}
|
|
156
|
-
function serializeCommand(def) {
|
|
157
|
-
return {
|
|
158
|
-
name: def.name,
|
|
159
|
-
description: def.description,
|
|
160
|
-
arguments: def.arguments,
|
|
161
|
-
options: serializeOptions(def.options ?? {}),
|
|
162
|
-
subCommands: def.subCommands ? def.subCommands.map(serializeCommand) : []
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
function serializeOptions(options) {
|
|
166
|
-
return Object.entries(options).map(([name, opt]) => {
|
|
167
|
-
return {
|
|
168
|
-
name,
|
|
169
|
-
flags: `${opt.short ? `-${opt.short}, ` : ""}--${name}${opt.type === "string" ? ` <${opt.hint ?? name}>` : ""}`,
|
|
170
|
-
type: opt.type,
|
|
171
|
-
description: opt.description,
|
|
172
|
-
...opt.default !== void 0 ? { default: opt.default } : {},
|
|
173
|
-
...opt.hint ? { hint: opt.hint } : {},
|
|
174
|
-
...opt.enum ? { enum: opt.enum } : {},
|
|
175
|
-
...opt.required ? { required: opt.required } : {}
|
|
176
|
-
};
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
/** Prints formatted help output for a command using its `CommandDefinition`. */
|
|
180
|
-
function renderHelp(def, parentName) {
|
|
181
|
-
const schema = getCommandSchema([def])[0];
|
|
182
|
-
const programName = parentName ? `${parentName} ${schema.name}` : schema.name;
|
|
183
|
-
const argsPart = schema.arguments?.length ? ` ${schema.arguments.join(" ")}` : "";
|
|
184
|
-
const subCmdPart = schema.subCommands.length ? " <command>" : "";
|
|
185
|
-
console.log(`\n${(0, node_util.styleText)("bold", "Usage:")} ${programName}${argsPart}${subCmdPart} [options]\n`);
|
|
186
|
-
if (schema.description) console.log(` ${schema.description}\n`);
|
|
187
|
-
if (schema.subCommands.length) {
|
|
188
|
-
console.log((0, node_util.styleText)("bold", "Commands:"));
|
|
189
|
-
for (const sub of schema.subCommands) console.log(` ${(0, node_util.styleText)("cyan", sub.name.padEnd(16))}${sub.description}`);
|
|
190
|
-
console.log();
|
|
191
|
-
}
|
|
192
|
-
const options = [...schema.options, {
|
|
193
|
-
name: "help",
|
|
194
|
-
flags: "-h, --help",
|
|
195
|
-
type: "boolean",
|
|
196
|
-
description: "Show help"
|
|
197
|
-
}];
|
|
198
|
-
console.log((0, node_util.styleText)("bold", "Options:"));
|
|
199
|
-
for (const opt of options) {
|
|
200
|
-
const flags = (0, node_util.styleText)("cyan", opt.flags.padEnd(30));
|
|
201
|
-
const defaultPart = opt.default !== void 0 ? (0, node_util.styleText)("dim", ` (default: ${opt.default})`) : "";
|
|
202
|
-
console.log(` ${flags}${opt.description}${defaultPart}`);
|
|
203
|
-
}
|
|
204
|
-
console.log();
|
|
205
|
-
}
|
|
206
|
-
function buildParseOptions(def) {
|
|
207
|
-
const result = { help: {
|
|
208
|
-
type: "boolean",
|
|
209
|
-
short: "h"
|
|
210
|
-
} };
|
|
211
|
-
for (const [name, opt] of Object.entries(def.options ?? {})) result[name] = {
|
|
212
|
-
type: opt.type,
|
|
213
|
-
...opt.short ? { short: opt.short } : {},
|
|
214
|
-
...opt.default !== void 0 ? { default: opt.default } : {}
|
|
215
|
-
};
|
|
216
|
-
return result;
|
|
217
|
-
}
|
|
218
|
-
async function runCommand(def, argv, parentName) {
|
|
219
|
-
const parseOptions = buildParseOptions(def);
|
|
220
|
-
let parsed;
|
|
221
|
-
try {
|
|
222
|
-
const result = (0, node_util.parseArgs)({
|
|
223
|
-
args: argv,
|
|
224
|
-
options: parseOptions,
|
|
225
|
-
allowPositionals: true,
|
|
226
|
-
strict: false
|
|
227
|
-
});
|
|
228
|
-
parsed = {
|
|
229
|
-
values: result.values,
|
|
230
|
-
positionals: result.positionals
|
|
231
|
-
};
|
|
232
|
-
} catch {
|
|
233
|
-
renderHelp(def, parentName);
|
|
234
|
-
process.exit(1);
|
|
235
|
-
}
|
|
236
|
-
if (parsed.values["help"]) {
|
|
237
|
-
renderHelp(def, parentName);
|
|
238
|
-
process.exit(0);
|
|
239
|
-
}
|
|
240
|
-
for (const [name, opt] of Object.entries(def.options ?? {})) if (opt.required && parsed.values[name] === void 0) {
|
|
241
|
-
console.error((0, node_util.styleText)("red", `Error: --${name} is required`));
|
|
242
|
-
renderHelp(def, parentName);
|
|
243
|
-
process.exit(1);
|
|
244
|
-
}
|
|
245
|
-
if (!def.run) {
|
|
246
|
-
renderHelp(def, parentName);
|
|
247
|
-
process.exit(0);
|
|
248
|
-
}
|
|
249
|
-
try {
|
|
250
|
-
await def.run(parsed);
|
|
251
|
-
} catch (err) {
|
|
252
|
-
console.error((0, node_util.styleText)("red", `Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
253
|
-
renderHelp(def, parentName);
|
|
254
|
-
process.exit(1);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
function printRootHelp(programName, version, defs) {
|
|
258
|
-
console.log(`\n${(0, node_util.styleText)("bold", "Usage:")} ${programName} <command> [options]\n`);
|
|
259
|
-
console.log(` Kubb generation — v${version}\n`);
|
|
260
|
-
console.log((0, node_util.styleText)("bold", "Commands:"));
|
|
261
|
-
for (const def of defs) console.log(` ${(0, node_util.styleText)("cyan", def.name.padEnd(16))}${def.description}`);
|
|
262
|
-
console.log();
|
|
263
|
-
console.log((0, node_util.styleText)("bold", "Options:"));
|
|
264
|
-
console.log(` ${(0, node_util.styleText)("cyan", "-v, --version".padEnd(30))}Show version number`);
|
|
265
|
-
console.log(` ${(0, node_util.styleText)("cyan", "-h, --help".padEnd(30))}Show help`);
|
|
266
|
-
console.log();
|
|
267
|
-
console.log(`Run ${(0, node_util.styleText)("cyan", `${programName} <command> --help`)} for command-specific help.\n`);
|
|
268
|
-
}
|
|
269
|
-
defineCLIAdapter({
|
|
270
|
-
renderHelp(def, parentName) {
|
|
271
|
-
renderHelp(def, parentName);
|
|
272
|
-
},
|
|
273
|
-
async run(defs, argv, opts) {
|
|
274
|
-
const { programName, defaultCommandName, version } = opts;
|
|
275
|
-
const args = argv.length >= 2 && argv[0]?.includes("node") ? argv.slice(2) : argv;
|
|
276
|
-
if (args[0] === "--version" || args[0] === "-v") {
|
|
277
|
-
console.log(version);
|
|
278
|
-
process.exit(0);
|
|
279
|
-
}
|
|
280
|
-
if (args[0] === "--help" || args[0] === "-h") {
|
|
281
|
-
printRootHelp(programName, version, defs);
|
|
282
|
-
process.exit(0);
|
|
283
|
-
}
|
|
284
|
-
if (args.length === 0) {
|
|
285
|
-
const defaultDef = defs.find((d) => d.name === defaultCommandName);
|
|
286
|
-
if (defaultDef?.run) await runCommand(defaultDef, [], programName);
|
|
287
|
-
else printRootHelp(programName, version, defs);
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
const [first, ...rest] = args;
|
|
291
|
-
const isKnownSubcommand = defs.some((d) => d.name === first);
|
|
292
|
-
let def;
|
|
293
|
-
let commandArgv;
|
|
294
|
-
let parentName;
|
|
295
|
-
if (isKnownSubcommand) {
|
|
296
|
-
def = defs.find((d) => d.name === first);
|
|
297
|
-
commandArgv = rest;
|
|
298
|
-
parentName = programName;
|
|
299
|
-
} else {
|
|
300
|
-
def = defs.find((d) => d.name === defaultCommandName);
|
|
301
|
-
commandArgv = args;
|
|
302
|
-
parentName = programName;
|
|
303
|
-
}
|
|
304
|
-
if (!def) {
|
|
305
|
-
console.error(`Unknown command: ${first}`);
|
|
306
|
-
printRootHelp(programName, version, defs);
|
|
307
|
-
process.exit(1);
|
|
308
|
-
}
|
|
309
|
-
if (def.subCommands?.length) {
|
|
310
|
-
const [subName, ...subRest] = commandArgv;
|
|
311
|
-
const subDef = def.subCommands.find((s) => s.name === subName);
|
|
312
|
-
if (subName === "--help" || subName === "-h") {
|
|
313
|
-
renderHelp(def, parentName);
|
|
314
|
-
process.exit(0);
|
|
315
|
-
}
|
|
316
|
-
if (!subDef) {
|
|
317
|
-
renderHelp(def, parentName);
|
|
318
|
-
process.exit(subName ? 1 : 0);
|
|
319
|
-
}
|
|
320
|
-
await runCommand(subDef, subRest, `${parentName} ${def.name}`);
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
await runCommand(def, commandArgv, parentName);
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
/**
|
|
327
|
-
* Calculates elapsed time in milliseconds from a high-resolution start time.
|
|
328
|
-
* Rounds to 2 decimal places to provide sub-millisecond precision without noise.
|
|
156
|
+
* ```ts
|
|
157
|
+
* const start = process.hrtime()
|
|
158
|
+
* doWork()
|
|
159
|
+
* getElapsedMs(start) // 42.35
|
|
160
|
+
* ```
|
|
329
161
|
*/
|
|
330
162
|
function getElapsedMs(hrStart) {
|
|
331
163
|
const [seconds, nanoseconds] = process.hrtime(hrStart);
|
|
@@ -333,39 +165,22 @@ function getElapsedMs(hrStart) {
|
|
|
333
165
|
return Math.round(ms * 100) / 100;
|
|
334
166
|
}
|
|
335
167
|
/**
|
|
336
|
-
* Converts a millisecond duration into a human-readable string.
|
|
337
|
-
*
|
|
168
|
+
* Converts a millisecond duration into a human-readable string (`ms`, `s`, or `m s`).
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* formatMs(250) // '250ms'
|
|
173
|
+
* formatMs(1500) // '1.50s'
|
|
174
|
+
* formatMs(90000) // '1m 30.0s'
|
|
175
|
+
* ```
|
|
338
176
|
*/
|
|
339
177
|
function formatMs(ms) {
|
|
340
178
|
if (ms >= 6e4) return `${Math.floor(ms / 6e4)}m ${(ms % 6e4 / 1e3).toFixed(1)}s`;
|
|
341
179
|
if (ms >= 1e3) return `${(ms / 1e3).toFixed(2)}s`;
|
|
342
180
|
return `${Math.round(ms)}ms`;
|
|
343
181
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
* Falls back to `255` for any channel that cannot be parsed.
|
|
347
|
-
*/
|
|
348
|
-
function parseHex(color) {
|
|
349
|
-
const int = Number.parseInt(color.replace("#", ""), 16);
|
|
350
|
-
return Number.isNaN(int) ? {
|
|
351
|
-
r: 255,
|
|
352
|
-
g: 255,
|
|
353
|
-
b: 255
|
|
354
|
-
} : {
|
|
355
|
-
r: int >> 16 & 255,
|
|
356
|
-
g: int >> 8 & 255,
|
|
357
|
-
b: int & 255
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
/**
|
|
361
|
-
* Returns a function that wraps a string in a 24-bit ANSI true-color escape sequence
|
|
362
|
-
* for the given hex color.
|
|
363
|
-
*/
|
|
364
|
-
function hex(color) {
|
|
365
|
-
const { r, g, b } = parseHex(color);
|
|
366
|
-
return (text) => `\x1b[38;2;${r};${g};${b}m${text}\x1b[0m`;
|
|
367
|
-
}
|
|
368
|
-
hex("#F55A17"), hex("#F5A217"), hex("#F58517"), hex("#B45309"), hex("#FFFFFF"), hex("#adadc6"), hex("#FDA4AF");
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region ../../internals/utils/src/fs.ts
|
|
369
184
|
/**
|
|
370
185
|
* Converts all backslashes to forward slashes.
|
|
371
186
|
* Extended-length Windows paths (`\\?\...`) are left unchanged.
|
|
@@ -375,8 +190,14 @@ function toSlash(p) {
|
|
|
375
190
|
return p.replaceAll("\\", "/");
|
|
376
191
|
}
|
|
377
192
|
/**
|
|
378
|
-
* Returns the relative path from `rootDir` to `filePath`, always using
|
|
379
|
-
*
|
|
193
|
+
* Returns the relative path from `rootDir` to `filePath`, always using forward slashes
|
|
194
|
+
* and prefixed with `./` when not already traversing upward.
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```ts
|
|
198
|
+
* getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'
|
|
199
|
+
* getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'
|
|
200
|
+
* ```
|
|
380
201
|
*/
|
|
381
202
|
function getRelativePath(rootDir, filePath) {
|
|
382
203
|
if (!rootDir || !filePath) throw new Error(`Root and file should be filled in when retrieving the relativePath, ${rootDir || ""} ${filePath || ""}`);
|
|
@@ -386,43 +207,43 @@ function getRelativePath(rootDir, filePath) {
|
|
|
386
207
|
/**
|
|
387
208
|
* Resolves to `true` when the file or directory at `path` exists.
|
|
388
209
|
* Uses `Bun.file().exists()` when running under Bun, `fs.access` otherwise.
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```ts
|
|
213
|
+
* if (await exists('./kubb.config.ts')) {
|
|
214
|
+
* const content = await read('./kubb.config.ts')
|
|
215
|
+
* }
|
|
216
|
+
* ```
|
|
389
217
|
*/
|
|
390
218
|
async function exists(path) {
|
|
391
219
|
if (typeof Bun !== "undefined") return Bun.file(path).exists();
|
|
392
220
|
return (0, node_fs_promises.access)(path).then(() => true, () => false);
|
|
393
221
|
}
|
|
394
222
|
/**
|
|
395
|
-
* Reads the file at `path` as a UTF-8 string.
|
|
396
|
-
* Uses `Bun.file().text()` when running under Bun, `fs.readFile` otherwise.
|
|
397
|
-
*/
|
|
398
|
-
async function read(path) {
|
|
399
|
-
if (typeof Bun !== "undefined") return Bun.file(path).text();
|
|
400
|
-
return (0, node_fs_promises.readFile)(path, { encoding: "utf8" });
|
|
401
|
-
}
|
|
402
|
-
/** Synchronous counterpart of `read`. */
|
|
403
|
-
function readSync(path) {
|
|
404
|
-
return (0, node_fs.readFileSync)(path, { encoding: "utf8" });
|
|
405
|
-
}
|
|
406
|
-
/**
|
|
407
223
|
* Writes `data` to `path`, trimming leading/trailing whitespace before saving.
|
|
408
|
-
* Skips the write
|
|
409
|
-
* identical to what is already on disk.
|
|
224
|
+
* Skips the write when the trimmed content is empty or identical to what is already on disk.
|
|
410
225
|
* Creates any missing parent directories automatically.
|
|
411
|
-
* When `sanity` is `true`, re-reads the file after writing and throws if the
|
|
412
|
-
*
|
|
226
|
+
* When `sanity` is `true`, re-reads the file after writing and throws if the content does not match.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```ts
|
|
230
|
+
* await write('./src/Pet.ts', source) // writes and returns trimmed content
|
|
231
|
+
* await write('./src/Pet.ts', source) // null — file unchanged
|
|
232
|
+
* await write('./src/Pet.ts', ' ') // null — empty content skipped
|
|
233
|
+
* ```
|
|
413
234
|
*/
|
|
414
235
|
async function write(path, data, options = {}) {
|
|
415
236
|
const trimmed = data.trim();
|
|
416
|
-
if (trimmed === "") return
|
|
237
|
+
if (trimmed === "") return null;
|
|
417
238
|
const resolved = (0, node_path.resolve)(path);
|
|
418
239
|
if (typeof Bun !== "undefined") {
|
|
419
240
|
const file = Bun.file(resolved);
|
|
420
|
-
if ((await file.exists() ? await file.text() : null) === trimmed) return
|
|
241
|
+
if ((await file.exists() ? await file.text() : null) === trimmed) return null;
|
|
421
242
|
await Bun.write(resolved, trimmed);
|
|
422
243
|
return trimmed;
|
|
423
244
|
}
|
|
424
245
|
try {
|
|
425
|
-
if (await (0, node_fs_promises.readFile)(resolved, { encoding: "utf-8" }) === trimmed) return
|
|
246
|
+
if (await (0, node_fs_promises.readFile)(resolved, { encoding: "utf-8" }) === trimmed) return null;
|
|
426
247
|
} catch {}
|
|
427
248
|
await (0, node_fs_promises.mkdir)((0, node_path.dirname)(resolved), { recursive: true });
|
|
428
249
|
await (0, node_fs_promises.writeFile)(resolved, trimmed, { encoding: "utf-8" });
|
|
@@ -433,124 +254,31 @@ async function write(path, data, options = {}) {
|
|
|
433
254
|
}
|
|
434
255
|
return trimmed;
|
|
435
256
|
}
|
|
436
|
-
/**
|
|
257
|
+
/**
|
|
258
|
+
* Recursively removes `path`. Silently succeeds when `path` does not exist.
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```ts
|
|
262
|
+
* await clean('./dist')
|
|
263
|
+
* ```
|
|
264
|
+
*/
|
|
437
265
|
async function clean(path) {
|
|
438
266
|
return (0, node_fs_promises.rm)(path, {
|
|
439
267
|
recursive: true,
|
|
440
268
|
force: true
|
|
441
269
|
});
|
|
442
270
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
* Use this when you need to track usage frequency but always emit the original identifier.
|
|
446
|
-
*/
|
|
447
|
-
function setUniqueName(originalName, data) {
|
|
448
|
-
let used = data[originalName] || 0;
|
|
449
|
-
if (used) {
|
|
450
|
-
data[originalName] = ++used;
|
|
451
|
-
return originalName;
|
|
452
|
-
}
|
|
453
|
-
data[originalName] = 1;
|
|
454
|
-
return originalName;
|
|
455
|
-
}
|
|
456
|
-
/**
|
|
457
|
-
* JavaScript and Java reserved words.
|
|
458
|
-
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
459
|
-
*/
|
|
460
|
-
const reservedWords = [
|
|
461
|
-
"abstract",
|
|
462
|
-
"arguments",
|
|
463
|
-
"boolean",
|
|
464
|
-
"break",
|
|
465
|
-
"byte",
|
|
466
|
-
"case",
|
|
467
|
-
"catch",
|
|
468
|
-
"char",
|
|
469
|
-
"class",
|
|
470
|
-
"const",
|
|
471
|
-
"continue",
|
|
472
|
-
"debugger",
|
|
473
|
-
"default",
|
|
474
|
-
"delete",
|
|
475
|
-
"do",
|
|
476
|
-
"double",
|
|
477
|
-
"else",
|
|
478
|
-
"enum",
|
|
479
|
-
"eval",
|
|
480
|
-
"export",
|
|
481
|
-
"extends",
|
|
482
|
-
"false",
|
|
483
|
-
"final",
|
|
484
|
-
"finally",
|
|
485
|
-
"float",
|
|
486
|
-
"for",
|
|
487
|
-
"function",
|
|
488
|
-
"goto",
|
|
489
|
-
"if",
|
|
490
|
-
"implements",
|
|
491
|
-
"import",
|
|
492
|
-
"in",
|
|
493
|
-
"instanceof",
|
|
494
|
-
"int",
|
|
495
|
-
"interface",
|
|
496
|
-
"let",
|
|
497
|
-
"long",
|
|
498
|
-
"native",
|
|
499
|
-
"new",
|
|
500
|
-
"null",
|
|
501
|
-
"package",
|
|
502
|
-
"private",
|
|
503
|
-
"protected",
|
|
504
|
-
"public",
|
|
505
|
-
"return",
|
|
506
|
-
"short",
|
|
507
|
-
"static",
|
|
508
|
-
"super",
|
|
509
|
-
"switch",
|
|
510
|
-
"synchronized",
|
|
511
|
-
"this",
|
|
512
|
-
"throw",
|
|
513
|
-
"throws",
|
|
514
|
-
"transient",
|
|
515
|
-
"true",
|
|
516
|
-
"try",
|
|
517
|
-
"typeof",
|
|
518
|
-
"var",
|
|
519
|
-
"void",
|
|
520
|
-
"volatile",
|
|
521
|
-
"while",
|
|
522
|
-
"with",
|
|
523
|
-
"yield",
|
|
524
|
-
"Array",
|
|
525
|
-
"Date",
|
|
526
|
-
"hasOwnProperty",
|
|
527
|
-
"Infinity",
|
|
528
|
-
"isFinite",
|
|
529
|
-
"isNaN",
|
|
530
|
-
"isPrototypeOf",
|
|
531
|
-
"length",
|
|
532
|
-
"Math",
|
|
533
|
-
"name",
|
|
534
|
-
"NaN",
|
|
535
|
-
"Number",
|
|
536
|
-
"Object",
|
|
537
|
-
"prototype",
|
|
538
|
-
"String",
|
|
539
|
-
"toString",
|
|
540
|
-
"undefined",
|
|
541
|
-
"valueOf"
|
|
542
|
-
];
|
|
543
|
-
/**
|
|
544
|
-
* Prefixes a word with `_` when it is a reserved JavaScript/Java identifier
|
|
545
|
-
* or starts with a digit.
|
|
546
|
-
*/
|
|
547
|
-
function transformReservedWord(word) {
|
|
548
|
-
const firstChar = word.charCodeAt(0);
|
|
549
|
-
if (word && (reservedWords.includes(word) || firstChar >= 48 && firstChar <= 57)) return `_${word}`;
|
|
550
|
-
return word;
|
|
551
|
-
}
|
|
271
|
+
//#endregion
|
|
272
|
+
//#region ../../internals/utils/src/reserved.ts
|
|
552
273
|
/**
|
|
553
274
|
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* ```ts
|
|
278
|
+
* isValidVarName('status') // true
|
|
279
|
+
* isValidVarName('class') // false (reserved word)
|
|
280
|
+
* isValidVarName('42foo') // false (starts with digit)
|
|
281
|
+
* ```
|
|
554
282
|
*/
|
|
555
283
|
function isValidVarName(name) {
|
|
556
284
|
try {
|
|
@@ -560,6 +288,8 @@ function isValidVarName(name) {
|
|
|
560
288
|
}
|
|
561
289
|
return true;
|
|
562
290
|
}
|
|
291
|
+
//#endregion
|
|
292
|
+
//#region ../../internals/utils/src/urlPath.ts
|
|
563
293
|
/**
|
|
564
294
|
* Parses and transforms an OpenAPI/Swagger path string into various URL formats.
|
|
565
295
|
*
|
|
@@ -569,18 +299,33 @@ function isValidVarName(name) {
|
|
|
569
299
|
* p.template // '`/pet/${petId}`'
|
|
570
300
|
*/
|
|
571
301
|
var URLPath = class {
|
|
572
|
-
/**
|
|
302
|
+
/**
|
|
303
|
+
* The raw OpenAPI/Swagger path string, e.g. `/pet/{petId}`.
|
|
304
|
+
*/
|
|
573
305
|
path;
|
|
574
306
|
#options;
|
|
575
307
|
constructor(path, options = {}) {
|
|
576
308
|
this.path = path;
|
|
577
309
|
this.#options = options;
|
|
578
310
|
}
|
|
579
|
-
/** Converts the OpenAPI path to Express-style colon syntax, e.g. `/pet/{petId}` → `/pet/:petId`.
|
|
311
|
+
/** Converts the OpenAPI path to Express-style colon syntax, e.g. `/pet/{petId}` → `/pet/:petId`.
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```ts
|
|
315
|
+
* new URLPath('/pet/{petId}').URL // '/pet/:petId'
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
580
318
|
get URL() {
|
|
581
319
|
return this.toURLPath();
|
|
582
320
|
}
|
|
583
|
-
/** Returns `true` when `path` is a fully-qualified URL (e.g. starts with `https://`).
|
|
321
|
+
/** Returns `true` when `path` is a fully-qualified URL (e.g. starts with `https://`).
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* ```ts
|
|
325
|
+
* new URLPath('https://petstore.swagger.io/v2/pet').isURL // true
|
|
326
|
+
* new URLPath('/pet/{petId}').isURL // false
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
584
329
|
get isURL() {
|
|
585
330
|
try {
|
|
586
331
|
return !!new URL(this.path).href;
|
|
@@ -598,19 +343,35 @@ var URLPath = class {
|
|
|
598
343
|
get template() {
|
|
599
344
|
return this.toTemplateString();
|
|
600
345
|
}
|
|
601
|
-
/** Returns the path and its extracted params as a structured `URLObject`, or as a stringified expression when `stringify` is set.
|
|
346
|
+
/** Returns the path and its extracted params as a structured `URLObject`, or as a stringified expression when `stringify` is set.
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* ```ts
|
|
350
|
+
* new URLPath('/pet/{petId}').object
|
|
351
|
+
* // { url: '/pet/:petId', params: { petId: 'petId' } }
|
|
352
|
+
* ```
|
|
353
|
+
*/
|
|
602
354
|
get object() {
|
|
603
355
|
return this.toObject();
|
|
604
356
|
}
|
|
605
|
-
/** Returns a map of path parameter names, or `undefined` when the path has no parameters.
|
|
357
|
+
/** Returns a map of path parameter names, or `undefined` when the path has no parameters.
|
|
358
|
+
*
|
|
359
|
+
* @example
|
|
360
|
+
* ```ts
|
|
361
|
+
* new URLPath('/pet/{petId}').params // { petId: 'petId' }
|
|
362
|
+
* new URLPath('/pet').params // undefined
|
|
363
|
+
* ```
|
|
364
|
+
*/
|
|
606
365
|
get params() {
|
|
607
366
|
return this.getParams();
|
|
608
367
|
}
|
|
609
368
|
#transformParam(raw) {
|
|
610
|
-
const param = isValidVarName(raw) ? raw : camelCase(raw);
|
|
611
|
-
return this.#options.casing === "camelcase" ? camelCase(param) : param;
|
|
369
|
+
const param = isValidVarName(raw) ? raw : require_PluginDriver.camelCase(raw);
|
|
370
|
+
return this.#options.casing === "camelcase" ? require_PluginDriver.camelCase(param) : param;
|
|
612
371
|
}
|
|
613
|
-
/**
|
|
372
|
+
/**
|
|
373
|
+
* Iterates over every `{param}` token in `path`, calling `fn` with the raw token and transformed name.
|
|
374
|
+
*/
|
|
614
375
|
#eachParam(fn) {
|
|
615
376
|
for (const match of this.path.matchAll(/\{([^}]+)\}/g)) {
|
|
616
377
|
const raw = match[1];
|
|
@@ -647,6 +408,12 @@ var URLPath = class {
|
|
|
647
408
|
* Extracts all `{param}` segments from the path and returns them as a key-value map.
|
|
648
409
|
* An optional `replacer` transforms each parameter name in both key and value positions.
|
|
649
410
|
* Returns `undefined` when no path parameters are found.
|
|
411
|
+
*
|
|
412
|
+
* @example
|
|
413
|
+
* ```ts
|
|
414
|
+
* new URLPath('/pet/{petId}/tag/{tagId}').getParams()
|
|
415
|
+
* // { petId: 'petId', tagId: 'tagId' }
|
|
416
|
+
* ```
|
|
650
417
|
*/
|
|
651
418
|
getParams(replacer) {
|
|
652
419
|
const params = {};
|
|
@@ -656,126 +423,36 @@ var URLPath = class {
|
|
|
656
423
|
});
|
|
657
424
|
return Object.keys(params).length > 0 ? params : void 0;
|
|
658
425
|
}
|
|
659
|
-
/** Converts the OpenAPI path to Express-style colon syntax
|
|
426
|
+
/** Converts the OpenAPI path to Express-style colon syntax.
|
|
427
|
+
*
|
|
428
|
+
* @example
|
|
429
|
+
* ```ts
|
|
430
|
+
* new URLPath('/pet/{petId}').toURLPath() // '/pet/:petId'
|
|
431
|
+
* ```
|
|
432
|
+
*/
|
|
660
433
|
toURLPath() {
|
|
661
434
|
return this.path.replace(/\{([^}]+)\}/g, ":$1");
|
|
662
435
|
}
|
|
663
436
|
};
|
|
664
437
|
//#endregion
|
|
665
|
-
//#region src/
|
|
666
|
-
function defineConfig(config) {
|
|
667
|
-
return config;
|
|
668
|
-
}
|
|
669
|
-
/**
|
|
670
|
-
* Type guard to check if a given config has an `input.path`.
|
|
671
|
-
*/
|
|
672
|
-
function isInputPath(config) {
|
|
673
|
-
return typeof config?.input === "object" && config.input !== null && "path" in config.input;
|
|
674
|
-
}
|
|
675
|
-
//#endregion
|
|
676
|
-
//#region src/constants.ts
|
|
677
|
-
const DEFAULT_STUDIO_URL = "https://studio.kubb.dev";
|
|
678
|
-
const BARREL_FILENAME = "index.ts";
|
|
679
|
-
const DEFAULT_BANNER = "simple";
|
|
680
|
-
const DEFAULT_EXTENSION = { ".ts": ".ts" };
|
|
681
|
-
const PATH_SEPARATORS = ["/", "\\"];
|
|
682
|
-
const logLevel = {
|
|
683
|
-
silent: Number.NEGATIVE_INFINITY,
|
|
684
|
-
error: 0,
|
|
685
|
-
warn: 1,
|
|
686
|
-
info: 3,
|
|
687
|
-
verbose: 4,
|
|
688
|
-
debug: 5
|
|
689
|
-
};
|
|
690
|
-
const linters = {
|
|
691
|
-
eslint: {
|
|
692
|
-
command: "eslint",
|
|
693
|
-
args: (outputPath) => [outputPath, "--fix"],
|
|
694
|
-
errorMessage: "Eslint not found"
|
|
695
|
-
},
|
|
696
|
-
biome: {
|
|
697
|
-
command: "biome",
|
|
698
|
-
args: (outputPath) => [
|
|
699
|
-
"lint",
|
|
700
|
-
"--fix",
|
|
701
|
-
outputPath
|
|
702
|
-
],
|
|
703
|
-
errorMessage: "Biome not found"
|
|
704
|
-
},
|
|
705
|
-
oxlint: {
|
|
706
|
-
command: "oxlint",
|
|
707
|
-
args: (outputPath) => ["--fix", outputPath],
|
|
708
|
-
errorMessage: "Oxlint not found"
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
|
-
const formatters = {
|
|
712
|
-
prettier: {
|
|
713
|
-
command: "prettier",
|
|
714
|
-
args: (outputPath) => [
|
|
715
|
-
"--ignore-unknown",
|
|
716
|
-
"--write",
|
|
717
|
-
outputPath
|
|
718
|
-
],
|
|
719
|
-
errorMessage: "Prettier not found"
|
|
720
|
-
},
|
|
721
|
-
biome: {
|
|
722
|
-
command: "biome",
|
|
723
|
-
args: (outputPath) => [
|
|
724
|
-
"format",
|
|
725
|
-
"--write",
|
|
726
|
-
outputPath
|
|
727
|
-
],
|
|
728
|
-
errorMessage: "Biome not found"
|
|
729
|
-
},
|
|
730
|
-
oxfmt: {
|
|
731
|
-
command: "oxfmt",
|
|
732
|
-
args: (outputPath) => [outputPath],
|
|
733
|
-
errorMessage: "Oxfmt not found"
|
|
734
|
-
}
|
|
735
|
-
};
|
|
736
|
-
//#endregion
|
|
737
|
-
//#region src/devtools.ts
|
|
438
|
+
//#region src/createAdapter.ts
|
|
738
439
|
/**
|
|
739
|
-
*
|
|
440
|
+
* Creates an adapter factory. Call the returned function with optional options to get the adapter instance.
|
|
740
441
|
*
|
|
741
|
-
*
|
|
742
|
-
*
|
|
743
|
-
*
|
|
744
|
-
*
|
|
745
|
-
*
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
return Buffer.from(compressed).toString("base64url");
|
|
750
|
-
}
|
|
751
|
-
/**
|
|
752
|
-
* Constructs the Kubb Studio URL for the given `RootNode`.
|
|
753
|
-
* When `options.ast` is `true`, navigates to the AST inspector (`/ast`).
|
|
754
|
-
* The `root` is encoded and attached as the `?root=` query parameter so Studio
|
|
755
|
-
* can decode and render it without a round-trip to any server.
|
|
756
|
-
*/
|
|
757
|
-
function getStudioUrl(root, studioUrl, options = {}) {
|
|
758
|
-
return `${studioUrl.replace(/\/$/, "")}${options.ast ? "/ast" : ""}?root=${encodeAst(root)}`;
|
|
759
|
-
}
|
|
760
|
-
/**
|
|
761
|
-
* Opens the Kubb Studio URL for the given `RootNode` in the default browser —
|
|
442
|
+
* @example
|
|
443
|
+
* export const myAdapter = createAdapter<MyAdapter>((options) => {
|
|
444
|
+
* return {
|
|
445
|
+
* name: 'my-adapter',
|
|
446
|
+
* options,
|
|
447
|
+
* async parse(source) { ... },
|
|
448
|
+
* }
|
|
449
|
+
* })
|
|
762
450
|
*
|
|
763
|
-
*
|
|
451
|
+
* // instantiate
|
|
452
|
+
* const adapter = myAdapter({ validate: true })
|
|
764
453
|
*/
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
const cmd = process.platform === "win32" ? "cmd" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
768
|
-
const args = process.platform === "win32" ? [
|
|
769
|
-
"/c",
|
|
770
|
-
"start",
|
|
771
|
-
"",
|
|
772
|
-
url
|
|
773
|
-
] : [url];
|
|
774
|
-
try {
|
|
775
|
-
await (0, tinyexec.x)(cmd, args);
|
|
776
|
-
} catch {
|
|
777
|
-
console.log(`\n ${url}\n`);
|
|
778
|
-
}
|
|
454
|
+
function createAdapter(build) {
|
|
455
|
+
return (options) => build(options ?? {});
|
|
779
456
|
}
|
|
780
457
|
//#endregion
|
|
781
458
|
//#region ../../node_modules/.pnpm/yocto-queue@1.2.2/node_modules/yocto-queue/index.js
|
|
@@ -905,494 +582,83 @@ function validateConcurrency(concurrency) {
|
|
|
905
582
|
if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) throw new TypeError("Expected `concurrency` to be a number from 1 and up");
|
|
906
583
|
}
|
|
907
584
|
//#endregion
|
|
908
|
-
//#region src/
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
*/
|
|
912
|
-
function hookSeq(promises) {
|
|
913
|
-
return promises.filter(Boolean).reduce((promise, func) => {
|
|
914
|
-
if (typeof func !== "function") throw new Error("HookSeq needs a function that returns a promise `() => Promise<unknown>`");
|
|
915
|
-
return promise.then((state) => {
|
|
916
|
-
const calledFunc = func(state);
|
|
917
|
-
if (calledFunc) return calledFunc.then(Array.prototype.concat.bind(state));
|
|
918
|
-
return state;
|
|
919
|
-
});
|
|
920
|
-
}, Promise.resolve([]));
|
|
585
|
+
//#region src/FileProcessor.ts
|
|
586
|
+
function joinSources(file) {
|
|
587
|
+
return file.sources.map((item) => (0, _kubb_ast.extractStringsFromNodes)(item.nodes)).filter(Boolean).join("\n\n");
|
|
921
588
|
}
|
|
922
589
|
/**
|
|
923
|
-
*
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
for (const func of promises.filter(Boolean)) promise = promise.then((state) => {
|
|
928
|
-
if (nullCheck(state)) return state;
|
|
929
|
-
return func(state);
|
|
930
|
-
});
|
|
931
|
-
return promise;
|
|
932
|
-
}
|
|
933
|
-
/**
|
|
934
|
-
* Runs an array of promise functions with optional concurrency limit.
|
|
590
|
+
* Converts a single file to a string using the registered parsers.
|
|
591
|
+
* Falls back to joining source values when no matching parser is found.
|
|
592
|
+
*
|
|
593
|
+
* @internal
|
|
935
594
|
*/
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
595
|
+
var FileProcessor = class {
|
|
596
|
+
#limit = pLimit(100);
|
|
597
|
+
async parse(file, { parsers, extension } = {}) {
|
|
598
|
+
const parseExtName = extension?.[file.extname] || void 0;
|
|
599
|
+
if (!parsers || !file.extname) return joinSources(file);
|
|
600
|
+
const parser = parsers.get(file.extname);
|
|
601
|
+
if (!parser) return joinSources(file);
|
|
602
|
+
return parser.parse(file, { extname: parseExtName });
|
|
603
|
+
}
|
|
604
|
+
async run(files, { parsers, mode = "sequential", extension, onStart, onEnd, onUpdate } = {}) {
|
|
605
|
+
await onStart?.(files);
|
|
606
|
+
const total = files.length;
|
|
607
|
+
let processed = 0;
|
|
608
|
+
const processOne = async (file) => {
|
|
609
|
+
const source = await this.parse(file, {
|
|
610
|
+
extension,
|
|
611
|
+
parsers
|
|
612
|
+
});
|
|
613
|
+
const currentProcessed = ++processed;
|
|
614
|
+
const percentage = currentProcessed / total * 100;
|
|
615
|
+
await onUpdate?.({
|
|
616
|
+
file,
|
|
617
|
+
source,
|
|
618
|
+
processed: currentProcessed,
|
|
619
|
+
percentage,
|
|
620
|
+
total
|
|
621
|
+
});
|
|
622
|
+
};
|
|
623
|
+
if (mode === "sequential") for (const file of files) await processOne(file);
|
|
624
|
+
else await Promise.all(files.map((file) => this.#limit(() => processOne(file))));
|
|
625
|
+
await onEnd?.(files);
|
|
626
|
+
return files;
|
|
953
627
|
}
|
|
954
628
|
};
|
|
955
|
-
|
|
956
|
-
|
|
629
|
+
//#endregion
|
|
630
|
+
//#region src/createStorage.ts
|
|
631
|
+
/**
|
|
632
|
+
* Creates a storage factory. Call the returned function with optional options to get the storage instance.
|
|
633
|
+
*
|
|
634
|
+
* @example
|
|
635
|
+
* export const memoryStorage = createStorage(() => {
|
|
636
|
+
* const store = new Map<string, string>()
|
|
637
|
+
* return {
|
|
638
|
+
* name: 'memory',
|
|
639
|
+
* async hasItem(key) { return store.has(key) },
|
|
640
|
+
* async getItem(key) { return store.get(key) ?? null },
|
|
641
|
+
* async setItem(key, value) { store.set(key, value) },
|
|
642
|
+
* async removeItem(key) { store.delete(key) },
|
|
643
|
+
* async getKeys(base) {
|
|
644
|
+
* const keys = [...store.keys()]
|
|
645
|
+
* return base ? keys.filter((k) => k.startsWith(base)) : keys
|
|
646
|
+
* },
|
|
647
|
+
* async clear(base) { if (!base) store.clear() },
|
|
648
|
+
* }
|
|
649
|
+
* })
|
|
650
|
+
*/
|
|
651
|
+
function createStorage(build) {
|
|
652
|
+
return (options) => build(options ?? {});
|
|
957
653
|
}
|
|
958
654
|
//#endregion
|
|
959
|
-
//#region src/
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
655
|
+
//#region src/storages/fsStorage.ts
|
|
656
|
+
/**
|
|
657
|
+
* Detects the filesystem error used to indicate that a path does not exist.
|
|
658
|
+
*/
|
|
659
|
+
function isMissingPathError(error) {
|
|
660
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
963
661
|
}
|
|
964
|
-
var PluginManager = class {
|
|
965
|
-
config;
|
|
966
|
-
options;
|
|
967
|
-
/**
|
|
968
|
-
* The universal `@kubb/ast` `RootNode` produced by the adapter, set by
|
|
969
|
-
* the build pipeline after the adapter's `parse()` resolves.
|
|
970
|
-
*/
|
|
971
|
-
rootNode = void 0;
|
|
972
|
-
adapter = void 0;
|
|
973
|
-
#studioIsOpen = false;
|
|
974
|
-
#plugins = /* @__PURE__ */ new Set();
|
|
975
|
-
#usedPluginNames = {};
|
|
976
|
-
#promiseManager;
|
|
977
|
-
constructor(config, options) {
|
|
978
|
-
this.config = config;
|
|
979
|
-
this.options = options;
|
|
980
|
-
this.#promiseManager = new PromiseManager({ nullCheck: (state) => !!state?.result });
|
|
981
|
-
[...config.plugins || []].forEach((plugin) => {
|
|
982
|
-
const parsedPlugin = this.#parse(plugin);
|
|
983
|
-
this.#plugins.add(parsedPlugin);
|
|
984
|
-
});
|
|
985
|
-
}
|
|
986
|
-
get events() {
|
|
987
|
-
return this.options.events;
|
|
988
|
-
}
|
|
989
|
-
getContext(plugin) {
|
|
990
|
-
const plugins = [...this.#plugins];
|
|
991
|
-
const pluginManager = this;
|
|
992
|
-
const baseContext = {
|
|
993
|
-
fabric: this.options.fabric,
|
|
994
|
-
config: this.config,
|
|
995
|
-
plugin,
|
|
996
|
-
events: this.options.events,
|
|
997
|
-
pluginManager: this,
|
|
998
|
-
mode: getMode((0, node_path.resolve)(this.config.root, this.config.output.path)),
|
|
999
|
-
addFile: async (...files) => {
|
|
1000
|
-
await this.options.fabric.addFile(...files);
|
|
1001
|
-
},
|
|
1002
|
-
upsertFile: async (...files) => {
|
|
1003
|
-
await this.options.fabric.upsertFile(...files);
|
|
1004
|
-
},
|
|
1005
|
-
get rootNode() {
|
|
1006
|
-
return pluginManager.rootNode;
|
|
1007
|
-
},
|
|
1008
|
-
get adapter() {
|
|
1009
|
-
return pluginManager.adapter;
|
|
1010
|
-
},
|
|
1011
|
-
openInStudio(options) {
|
|
1012
|
-
if (!pluginManager.config.devtools || pluginManager.#studioIsOpen) return;
|
|
1013
|
-
if (typeof pluginManager.config.devtools !== "object") throw new Error("Devtools must be an object");
|
|
1014
|
-
if (!pluginManager.rootNode || !pluginManager.adapter) throw new Error("adapter is not defined, make sure you have set the parser in kubb.config.ts");
|
|
1015
|
-
pluginManager.#studioIsOpen = true;
|
|
1016
|
-
const studioUrl = pluginManager.config.devtools?.studioUrl ?? "https://studio.kubb.dev";
|
|
1017
|
-
return openInStudio(pluginManager.rootNode, studioUrl, options);
|
|
1018
|
-
}
|
|
1019
|
-
};
|
|
1020
|
-
const mergedExtras = {};
|
|
1021
|
-
for (const p of plugins) if (typeof p.inject === "function") {
|
|
1022
|
-
const result = p.inject.call(baseContext, baseContext);
|
|
1023
|
-
if (result !== null && typeof result === "object") Object.assign(mergedExtras, result);
|
|
1024
|
-
}
|
|
1025
|
-
return {
|
|
1026
|
-
...baseContext,
|
|
1027
|
-
...mergedExtras
|
|
1028
|
-
};
|
|
1029
|
-
}
|
|
1030
|
-
get plugins() {
|
|
1031
|
-
return this.#getSortedPlugins();
|
|
1032
|
-
}
|
|
1033
|
-
getFile({ name, mode, extname, pluginName, options }) {
|
|
1034
|
-
const resolvedName = mode ? mode === "single" ? "" : this.resolveName({
|
|
1035
|
-
name,
|
|
1036
|
-
pluginName,
|
|
1037
|
-
type: "file"
|
|
1038
|
-
}) : name;
|
|
1039
|
-
const path = this.resolvePath({
|
|
1040
|
-
baseName: `${resolvedName}${extname}`,
|
|
1041
|
-
mode,
|
|
1042
|
-
pluginName,
|
|
1043
|
-
options
|
|
1044
|
-
});
|
|
1045
|
-
if (!path) throw new Error(`Filepath should be defined for resolvedName "${resolvedName}" and pluginName "${pluginName}"`);
|
|
1046
|
-
return {
|
|
1047
|
-
path,
|
|
1048
|
-
baseName: (0, node_path.basename)(path),
|
|
1049
|
-
meta: { pluginName },
|
|
1050
|
-
sources: [],
|
|
1051
|
-
imports: [],
|
|
1052
|
-
exports: []
|
|
1053
|
-
};
|
|
1054
|
-
}
|
|
1055
|
-
resolvePath = (params) => {
|
|
1056
|
-
const defaultPath = (0, node_path.resolve)((0, node_path.resolve)(this.config.root, this.config.output.path), params.baseName);
|
|
1057
|
-
if (params.pluginName) return this.hookForPluginSync({
|
|
1058
|
-
pluginName: params.pluginName,
|
|
1059
|
-
hookName: "resolvePath",
|
|
1060
|
-
parameters: [
|
|
1061
|
-
params.baseName,
|
|
1062
|
-
params.mode,
|
|
1063
|
-
params.options
|
|
1064
|
-
]
|
|
1065
|
-
})?.at(0) || defaultPath;
|
|
1066
|
-
return this.hookFirstSync({
|
|
1067
|
-
hookName: "resolvePath",
|
|
1068
|
-
parameters: [
|
|
1069
|
-
params.baseName,
|
|
1070
|
-
params.mode,
|
|
1071
|
-
params.options
|
|
1072
|
-
]
|
|
1073
|
-
})?.result || defaultPath;
|
|
1074
|
-
};
|
|
1075
|
-
resolveName = (params) => {
|
|
1076
|
-
if (params.pluginName) {
|
|
1077
|
-
const names = this.hookForPluginSync({
|
|
1078
|
-
pluginName: params.pluginName,
|
|
1079
|
-
hookName: "resolveName",
|
|
1080
|
-
parameters: [params.name.trim(), params.type]
|
|
1081
|
-
});
|
|
1082
|
-
return transformReservedWord([...new Set(names)].at(0) || params.name);
|
|
1083
|
-
}
|
|
1084
|
-
const name = this.hookFirstSync({
|
|
1085
|
-
hookName: "resolveName",
|
|
1086
|
-
parameters: [params.name.trim(), params.type]
|
|
1087
|
-
})?.result;
|
|
1088
|
-
return transformReservedWord(name ?? params.name);
|
|
1089
|
-
};
|
|
1090
|
-
/**
|
|
1091
|
-
* Run a specific hookName for plugin x.
|
|
1092
|
-
*/
|
|
1093
|
-
async hookForPlugin({ pluginName, hookName, parameters }) {
|
|
1094
|
-
const plugins = this.getPluginsByName(hookName, pluginName);
|
|
1095
|
-
this.events.emit("plugins:hook:progress:start", {
|
|
1096
|
-
hookName,
|
|
1097
|
-
plugins
|
|
1098
|
-
});
|
|
1099
|
-
const items = [];
|
|
1100
|
-
for (const plugin of plugins) {
|
|
1101
|
-
const result = await this.#execute({
|
|
1102
|
-
strategy: "hookFirst",
|
|
1103
|
-
hookName,
|
|
1104
|
-
parameters,
|
|
1105
|
-
plugin
|
|
1106
|
-
});
|
|
1107
|
-
if (result !== void 0 && result !== null) items.push(result);
|
|
1108
|
-
}
|
|
1109
|
-
this.events.emit("plugins:hook:progress:end", { hookName });
|
|
1110
|
-
return items;
|
|
1111
|
-
}
|
|
1112
|
-
/**
|
|
1113
|
-
* Run a specific hookName for plugin x.
|
|
1114
|
-
*/
|
|
1115
|
-
hookForPluginSync({ pluginName, hookName, parameters }) {
|
|
1116
|
-
return this.getPluginsByName(hookName, pluginName).map((plugin) => {
|
|
1117
|
-
return this.#executeSync({
|
|
1118
|
-
strategy: "hookFirst",
|
|
1119
|
-
hookName,
|
|
1120
|
-
parameters,
|
|
1121
|
-
plugin
|
|
1122
|
-
});
|
|
1123
|
-
}).filter((x) => x !== null);
|
|
1124
|
-
}
|
|
1125
|
-
/**
|
|
1126
|
-
* Returns the first non-null result.
|
|
1127
|
-
*/
|
|
1128
|
-
async hookFirst({ hookName, parameters, skipped }) {
|
|
1129
|
-
const plugins = this.#getSortedPlugins(hookName).filter((plugin) => {
|
|
1130
|
-
return skipped ? !skipped.has(plugin) : true;
|
|
1131
|
-
});
|
|
1132
|
-
this.events.emit("plugins:hook:progress:start", {
|
|
1133
|
-
hookName,
|
|
1134
|
-
plugins
|
|
1135
|
-
});
|
|
1136
|
-
const promises = plugins.map((plugin) => {
|
|
1137
|
-
return async () => {
|
|
1138
|
-
const value = await this.#execute({
|
|
1139
|
-
strategy: "hookFirst",
|
|
1140
|
-
hookName,
|
|
1141
|
-
parameters,
|
|
1142
|
-
plugin
|
|
1143
|
-
});
|
|
1144
|
-
return Promise.resolve({
|
|
1145
|
-
plugin,
|
|
1146
|
-
result: value
|
|
1147
|
-
});
|
|
1148
|
-
};
|
|
1149
|
-
});
|
|
1150
|
-
const result = await this.#promiseManager.run("first", promises);
|
|
1151
|
-
this.events.emit("plugins:hook:progress:end", { hookName });
|
|
1152
|
-
return result;
|
|
1153
|
-
}
|
|
1154
|
-
/**
|
|
1155
|
-
* Returns the first non-null result.
|
|
1156
|
-
*/
|
|
1157
|
-
hookFirstSync({ hookName, parameters, skipped }) {
|
|
1158
|
-
let parseResult = null;
|
|
1159
|
-
const plugins = this.#getSortedPlugins(hookName).filter((plugin) => {
|
|
1160
|
-
return skipped ? !skipped.has(plugin) : true;
|
|
1161
|
-
});
|
|
1162
|
-
for (const plugin of plugins) {
|
|
1163
|
-
parseResult = {
|
|
1164
|
-
result: this.#executeSync({
|
|
1165
|
-
strategy: "hookFirst",
|
|
1166
|
-
hookName,
|
|
1167
|
-
parameters,
|
|
1168
|
-
plugin
|
|
1169
|
-
}),
|
|
1170
|
-
plugin
|
|
1171
|
-
};
|
|
1172
|
-
if (parseResult?.result != null) break;
|
|
1173
|
-
}
|
|
1174
|
-
return parseResult;
|
|
1175
|
-
}
|
|
1176
|
-
/**
|
|
1177
|
-
* Runs all plugins in parallel based on `this.plugin` order and `pre`/`post` settings.
|
|
1178
|
-
*/
|
|
1179
|
-
async hookParallel({ hookName, parameters }) {
|
|
1180
|
-
const plugins = this.#getSortedPlugins(hookName);
|
|
1181
|
-
this.events.emit("plugins:hook:progress:start", {
|
|
1182
|
-
hookName,
|
|
1183
|
-
plugins
|
|
1184
|
-
});
|
|
1185
|
-
const pluginStartTimes = /* @__PURE__ */ new Map();
|
|
1186
|
-
const promises = plugins.map((plugin) => {
|
|
1187
|
-
return () => {
|
|
1188
|
-
pluginStartTimes.set(plugin, node_perf_hooks.performance.now());
|
|
1189
|
-
return this.#execute({
|
|
1190
|
-
strategy: "hookParallel",
|
|
1191
|
-
hookName,
|
|
1192
|
-
parameters,
|
|
1193
|
-
plugin
|
|
1194
|
-
});
|
|
1195
|
-
};
|
|
1196
|
-
});
|
|
1197
|
-
const results = await this.#promiseManager.run("parallel", promises, { concurrency: this.options.concurrency });
|
|
1198
|
-
results.forEach((result, index) => {
|
|
1199
|
-
if (isPromiseRejectedResult(result)) {
|
|
1200
|
-
const plugin = this.#getSortedPlugins(hookName)[index];
|
|
1201
|
-
if (plugin) {
|
|
1202
|
-
const startTime = pluginStartTimes.get(plugin) ?? node_perf_hooks.performance.now();
|
|
1203
|
-
this.events.emit("error", result.reason, {
|
|
1204
|
-
plugin,
|
|
1205
|
-
hookName,
|
|
1206
|
-
strategy: "hookParallel",
|
|
1207
|
-
duration: Math.round(node_perf_hooks.performance.now() - startTime),
|
|
1208
|
-
parameters
|
|
1209
|
-
});
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
});
|
|
1213
|
-
this.events.emit("plugins:hook:progress:end", { hookName });
|
|
1214
|
-
return results.reduce((acc, result) => {
|
|
1215
|
-
if (result.status === "fulfilled") acc.push(result.value);
|
|
1216
|
-
return acc;
|
|
1217
|
-
}, []);
|
|
1218
|
-
}
|
|
1219
|
-
/**
|
|
1220
|
-
* Chains plugins
|
|
1221
|
-
*/
|
|
1222
|
-
async hookSeq({ hookName, parameters }) {
|
|
1223
|
-
const plugins = this.#getSortedPlugins(hookName);
|
|
1224
|
-
this.events.emit("plugins:hook:progress:start", {
|
|
1225
|
-
hookName,
|
|
1226
|
-
plugins
|
|
1227
|
-
});
|
|
1228
|
-
const promises = plugins.map((plugin) => {
|
|
1229
|
-
return () => this.#execute({
|
|
1230
|
-
strategy: "hookSeq",
|
|
1231
|
-
hookName,
|
|
1232
|
-
parameters,
|
|
1233
|
-
plugin
|
|
1234
|
-
});
|
|
1235
|
-
});
|
|
1236
|
-
await this.#promiseManager.run("seq", promises);
|
|
1237
|
-
this.events.emit("plugins:hook:progress:end", { hookName });
|
|
1238
|
-
}
|
|
1239
|
-
#getSortedPlugins(hookName) {
|
|
1240
|
-
const plugins = [...this.#plugins];
|
|
1241
|
-
if (hookName) return plugins.filter((plugin) => hookName in plugin);
|
|
1242
|
-
return plugins.map((plugin) => {
|
|
1243
|
-
if (plugin.pre) {
|
|
1244
|
-
let missingPlugins = plugin.pre.filter((pluginName) => !plugins.find((pluginToFind) => pluginToFind.name === pluginName));
|
|
1245
|
-
if (missingPlugins.includes("plugin-oas") && this.adapter) missingPlugins = missingPlugins.filter((pluginName) => pluginName !== "plugin-oas");
|
|
1246
|
-
if (missingPlugins.length > 0) throw new ValidationPluginError(`The plugin '${plugin.name}' has a pre set that references missing plugins for '${missingPlugins.join(", ")}'`);
|
|
1247
|
-
}
|
|
1248
|
-
return plugin;
|
|
1249
|
-
}).sort((a, b) => {
|
|
1250
|
-
if (b.pre?.includes(a.name)) return 1;
|
|
1251
|
-
if (b.post?.includes(a.name)) return -1;
|
|
1252
|
-
return 0;
|
|
1253
|
-
});
|
|
1254
|
-
}
|
|
1255
|
-
getPluginByName(pluginName) {
|
|
1256
|
-
return [...this.#plugins].find((item) => item.name === pluginName);
|
|
1257
|
-
}
|
|
1258
|
-
getPluginsByName(hookName, pluginName) {
|
|
1259
|
-
const plugins = [...this.plugins];
|
|
1260
|
-
const pluginByPluginName = plugins.filter((plugin) => hookName in plugin).filter((item) => item.name === pluginName);
|
|
1261
|
-
if (!pluginByPluginName?.length) {
|
|
1262
|
-
const corePlugin = plugins.find((plugin) => plugin.name === "core" && hookName in plugin);
|
|
1263
|
-
return corePlugin ? [corePlugin] : [];
|
|
1264
|
-
}
|
|
1265
|
-
return pluginByPluginName;
|
|
1266
|
-
}
|
|
1267
|
-
/**
|
|
1268
|
-
* Run an async plugin hook and return the result.
|
|
1269
|
-
* @param hookName Name of the plugin hook. Must be either in `PluginHooks` or `OutputPluginValueHooks`.
|
|
1270
|
-
* @param args Arguments passed to the plugin hook.
|
|
1271
|
-
* @param plugin The actual pluginObject to run.
|
|
1272
|
-
*/
|
|
1273
|
-
#emitProcessingEnd({ startTime, output, strategy, hookName, plugin, parameters }) {
|
|
1274
|
-
this.events.emit("plugins:hook:processing:end", {
|
|
1275
|
-
duration: Math.round(node_perf_hooks.performance.now() - startTime),
|
|
1276
|
-
parameters,
|
|
1277
|
-
output,
|
|
1278
|
-
strategy,
|
|
1279
|
-
hookName,
|
|
1280
|
-
plugin
|
|
1281
|
-
});
|
|
1282
|
-
}
|
|
1283
|
-
#execute({ strategy, hookName, parameters, plugin }) {
|
|
1284
|
-
const hook = plugin[hookName];
|
|
1285
|
-
if (!hook) return null;
|
|
1286
|
-
this.events.emit("plugins:hook:processing:start", {
|
|
1287
|
-
strategy,
|
|
1288
|
-
hookName,
|
|
1289
|
-
parameters,
|
|
1290
|
-
plugin
|
|
1291
|
-
});
|
|
1292
|
-
const startTime = node_perf_hooks.performance.now();
|
|
1293
|
-
return (async () => {
|
|
1294
|
-
try {
|
|
1295
|
-
const output = typeof hook === "function" ? await Promise.resolve(hook.apply(this.getContext(plugin), parameters ?? [])) : hook;
|
|
1296
|
-
this.#emitProcessingEnd({
|
|
1297
|
-
startTime,
|
|
1298
|
-
output,
|
|
1299
|
-
strategy,
|
|
1300
|
-
hookName,
|
|
1301
|
-
plugin,
|
|
1302
|
-
parameters
|
|
1303
|
-
});
|
|
1304
|
-
return output;
|
|
1305
|
-
} catch (error) {
|
|
1306
|
-
this.events.emit("error", error, {
|
|
1307
|
-
plugin,
|
|
1308
|
-
hookName,
|
|
1309
|
-
strategy,
|
|
1310
|
-
duration: Math.round(node_perf_hooks.performance.now() - startTime)
|
|
1311
|
-
});
|
|
1312
|
-
return null;
|
|
1313
|
-
}
|
|
1314
|
-
})();
|
|
1315
|
-
}
|
|
1316
|
-
/**
|
|
1317
|
-
* Run a sync plugin hook and return the result.
|
|
1318
|
-
* @param hookName Name of the plugin hook. Must be in `PluginHooks`.
|
|
1319
|
-
* @param args Arguments passed to the plugin hook.
|
|
1320
|
-
* @param plugin The actual plugin
|
|
1321
|
-
*/
|
|
1322
|
-
#executeSync({ strategy, hookName, parameters, plugin }) {
|
|
1323
|
-
const hook = plugin[hookName];
|
|
1324
|
-
if (!hook) return null;
|
|
1325
|
-
this.events.emit("plugins:hook:processing:start", {
|
|
1326
|
-
strategy,
|
|
1327
|
-
hookName,
|
|
1328
|
-
parameters,
|
|
1329
|
-
plugin
|
|
1330
|
-
});
|
|
1331
|
-
const startTime = node_perf_hooks.performance.now();
|
|
1332
|
-
try {
|
|
1333
|
-
const output = typeof hook === "function" ? hook.apply(this.getContext(plugin), parameters) : hook;
|
|
1334
|
-
this.#emitProcessingEnd({
|
|
1335
|
-
startTime,
|
|
1336
|
-
output,
|
|
1337
|
-
strategy,
|
|
1338
|
-
hookName,
|
|
1339
|
-
plugin,
|
|
1340
|
-
parameters
|
|
1341
|
-
});
|
|
1342
|
-
return output;
|
|
1343
|
-
} catch (error) {
|
|
1344
|
-
this.events.emit("error", error, {
|
|
1345
|
-
plugin,
|
|
1346
|
-
hookName,
|
|
1347
|
-
strategy,
|
|
1348
|
-
duration: Math.round(node_perf_hooks.performance.now() - startTime)
|
|
1349
|
-
});
|
|
1350
|
-
return null;
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
#parse(plugin) {
|
|
1354
|
-
const usedPluginNames = this.#usedPluginNames;
|
|
1355
|
-
setUniqueName(plugin.name, usedPluginNames);
|
|
1356
|
-
const usageCount = usedPluginNames[plugin.name];
|
|
1357
|
-
if (usageCount && usageCount > 1) throw new ValidationPluginError(`Duplicate plugin "${plugin.name}" detected. Each plugin can only be used once. Use a different configuration instead of adding multiple instances of the same plugin.`);
|
|
1358
|
-
return {
|
|
1359
|
-
install() {},
|
|
1360
|
-
...plugin
|
|
1361
|
-
};
|
|
1362
|
-
}
|
|
1363
|
-
};
|
|
1364
|
-
//#endregion
|
|
1365
|
-
//#region src/defineStorage.ts
|
|
1366
|
-
/**
|
|
1367
|
-
* Wraps a storage builder so the `options` argument is optional, following the
|
|
1368
|
-
* same factory pattern as `definePlugin`, `defineLogger`, and `defineAdapter`.
|
|
1369
|
-
*
|
|
1370
|
-
* The builder receives the resolved options object and must return a
|
|
1371
|
-
* `DefineStorage`-compatible object that includes a `name` string.
|
|
1372
|
-
*
|
|
1373
|
-
* @example
|
|
1374
|
-
* ```ts
|
|
1375
|
-
* import { defineStorage } from '@kubb/core'
|
|
1376
|
-
*
|
|
1377
|
-
* export const memoryStorage = defineStorage((_options) => {
|
|
1378
|
-
* const store = new Map<string, string>()
|
|
1379
|
-
* return {
|
|
1380
|
-
* name: 'memory',
|
|
1381
|
-
* async hasItem(key) { return store.has(key) },
|
|
1382
|
-
* async getItem(key) { return store.get(key) ?? null },
|
|
1383
|
-
* async setItem(key, value) { store.set(key, value) },
|
|
1384
|
-
* async removeItem(key) { store.delete(key) },
|
|
1385
|
-
* async getKeys() { return [...store.keys()] },
|
|
1386
|
-
* async clear() { store.clear() },
|
|
1387
|
-
* }
|
|
1388
|
-
* })
|
|
1389
|
-
* ```
|
|
1390
|
-
*/
|
|
1391
|
-
function defineStorage(build) {
|
|
1392
|
-
return (options) => build(options ?? {});
|
|
1393
|
-
}
|
|
1394
|
-
//#endregion
|
|
1395
|
-
//#region src/storages/fsStorage.ts
|
|
1396
662
|
/**
|
|
1397
663
|
* Built-in filesystem storage driver.
|
|
1398
664
|
*
|
|
@@ -1408,7 +674,8 @@ function defineStorage(build) {
|
|
|
1408
674
|
*
|
|
1409
675
|
* @example
|
|
1410
676
|
* ```ts
|
|
1411
|
-
* import {
|
|
677
|
+
* import { fsStorage } from '@kubb/core'
|
|
678
|
+
* import { defineConfig } from 'kubb'
|
|
1412
679
|
*
|
|
1413
680
|
* export default defineConfig({
|
|
1414
681
|
* input: { path: './petStore.yaml' },
|
|
@@ -1416,21 +683,23 @@ function defineStorage(build) {
|
|
|
1416
683
|
* })
|
|
1417
684
|
* ```
|
|
1418
685
|
*/
|
|
1419
|
-
const fsStorage =
|
|
686
|
+
const fsStorage = createStorage(() => ({
|
|
1420
687
|
name: "fs",
|
|
1421
688
|
async hasItem(key) {
|
|
1422
689
|
try {
|
|
1423
690
|
await (0, node_fs_promises.access)((0, node_path.resolve)(key));
|
|
1424
691
|
return true;
|
|
1425
|
-
} catch {
|
|
1426
|
-
return false;
|
|
692
|
+
} catch (error) {
|
|
693
|
+
if (isMissingPathError(error)) return false;
|
|
694
|
+
throw new Error(`Failed to access storage item "${key}"`, { cause: error });
|
|
1427
695
|
}
|
|
1428
696
|
},
|
|
1429
697
|
async getItem(key) {
|
|
1430
698
|
try {
|
|
1431
699
|
return await (0, node_fs_promises.readFile)((0, node_path.resolve)(key), "utf8");
|
|
1432
|
-
} catch {
|
|
1433
|
-
return null;
|
|
700
|
+
} catch (error) {
|
|
701
|
+
if (isMissingPathError(error)) return null;
|
|
702
|
+
throw new Error(`Failed to read storage item "${key}"`, { cause: error });
|
|
1434
703
|
}
|
|
1435
704
|
},
|
|
1436
705
|
async setItem(key, value) {
|
|
@@ -1441,12 +710,14 @@ const fsStorage = defineStorage(() => ({
|
|
|
1441
710
|
},
|
|
1442
711
|
async getKeys(base) {
|
|
1443
712
|
const keys = [];
|
|
713
|
+
const resolvedBase = (0, node_path.resolve)(base ?? process.cwd());
|
|
1444
714
|
async function walk(dir, prefix) {
|
|
1445
715
|
let entries;
|
|
1446
716
|
try {
|
|
1447
717
|
entries = await (0, node_fs_promises.readdir)(dir, { withFileTypes: true });
|
|
1448
|
-
} catch {
|
|
1449
|
-
return;
|
|
718
|
+
} catch (error) {
|
|
719
|
+
if (isMissingPathError(error)) return;
|
|
720
|
+
throw new Error(`Failed to list storage keys under "${resolvedBase}"`, { cause: error });
|
|
1450
721
|
}
|
|
1451
722
|
for (const entry of entries) {
|
|
1452
723
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
@@ -1454,7 +725,7 @@ const fsStorage = defineStorage(() => ({
|
|
|
1454
725
|
else keys.push(rel);
|
|
1455
726
|
}
|
|
1456
727
|
}
|
|
1457
|
-
await walk(
|
|
728
|
+
await walk(resolvedBase, "");
|
|
1458
729
|
return keys;
|
|
1459
730
|
},
|
|
1460
731
|
async clear(base) {
|
|
@@ -1464,11 +735,14 @@ const fsStorage = defineStorage(() => ({
|
|
|
1464
735
|
}));
|
|
1465
736
|
//#endregion
|
|
1466
737
|
//#region package.json
|
|
1467
|
-
var version = "5.0.0-alpha.
|
|
738
|
+
var version = "5.0.0-alpha.50";
|
|
1468
739
|
//#endregion
|
|
1469
740
|
//#region src/utils/diagnostics.ts
|
|
1470
741
|
/**
|
|
1471
|
-
*
|
|
742
|
+
* Returns a snapshot of the current runtime environment.
|
|
743
|
+
*
|
|
744
|
+
* Useful for attaching context to debug logs and error reports so that
|
|
745
|
+
* issues can be reproduced without manual information gathering.
|
|
1472
746
|
*/
|
|
1473
747
|
function getDiagnosticInfo() {
|
|
1474
748
|
return {
|
|
@@ -1480,670 +754,94 @@ function getDiagnosticInfo() {
|
|
|
1480
754
|
};
|
|
1481
755
|
}
|
|
1482
756
|
//#endregion
|
|
1483
|
-
//#region src/
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
"Environment:",
|
|
1502
|
-
Object.entries(diagnosticInfo).map(([key, value]) => ` • ${key}: ${value}`).join("\n")
|
|
1503
|
-
]
|
|
1504
|
-
});
|
|
1505
|
-
try {
|
|
1506
|
-
if (isInputPath(userConfig) && !new URLPath(userConfig.input.path).isURL) {
|
|
1507
|
-
await exists(userConfig.input.path);
|
|
1508
|
-
await events.emit("debug", {
|
|
1509
|
-
date: /* @__PURE__ */ new Date(),
|
|
1510
|
-
logs: [`✓ Input file validated: ${userConfig.input.path}`]
|
|
1511
|
-
});
|
|
1512
|
-
}
|
|
1513
|
-
} catch (caughtError) {
|
|
1514
|
-
if (isInputPath(userConfig)) {
|
|
1515
|
-
const error = caughtError;
|
|
1516
|
-
throw new Error(`Cannot read file/URL defined in \`input.path\` or set with \`kubb generate PATH\` in the CLI of your Kubb config ${userConfig.input.path}`, { cause: error });
|
|
1517
|
-
}
|
|
757
|
+
//#region src/utils/TreeNode.ts
|
|
758
|
+
/**
|
|
759
|
+
* Tree structure used to build per-directory barrel (`index.ts`) files from a
|
|
760
|
+
* flat list of generated {@link FileNode} entries.
|
|
761
|
+
*
|
|
762
|
+
* Each node represents either a directory or a file within the output tree.
|
|
763
|
+
* Use {@link TreeNode.build} to construct a root node from a file list, then
|
|
764
|
+
* traverse with {@link TreeNode.forEach}, {@link TreeNode.leaves}, or the
|
|
765
|
+
* `*Deep` helpers.
|
|
766
|
+
*/
|
|
767
|
+
var TreeNode = class TreeNode {
|
|
768
|
+
data;
|
|
769
|
+
parent;
|
|
770
|
+
children = [];
|
|
771
|
+
#cachedLeaves = void 0;
|
|
772
|
+
constructor(data, parent) {
|
|
773
|
+
this.data = data;
|
|
774
|
+
this.parent = parent;
|
|
1518
775
|
}
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
barrelType: "named",
|
|
1525
|
-
extension: DEFAULT_EXTENSION,
|
|
1526
|
-
defaultBanner: DEFAULT_BANNER,
|
|
1527
|
-
...userConfig.output
|
|
1528
|
-
},
|
|
1529
|
-
devtools: userConfig.devtools ? {
|
|
1530
|
-
studioUrl: DEFAULT_STUDIO_URL,
|
|
1531
|
-
...typeof userConfig.devtools === "boolean" ? {} : userConfig.devtools
|
|
1532
|
-
} : void 0,
|
|
1533
|
-
plugins: userConfig.plugins
|
|
1534
|
-
};
|
|
1535
|
-
const storage = definedConfig.output.write === false ? null : definedConfig.output.storage ?? fsStorage();
|
|
1536
|
-
if (definedConfig.output.clean) {
|
|
1537
|
-
await events.emit("debug", {
|
|
1538
|
-
date: /* @__PURE__ */ new Date(),
|
|
1539
|
-
logs: ["Cleaning output directories", ` • Output: ${definedConfig.output.path}`]
|
|
1540
|
-
});
|
|
1541
|
-
await storage?.clear((0, node_path.resolve)(definedConfig.root, definedConfig.output.path));
|
|
776
|
+
addChild(data) {
|
|
777
|
+
const child = new TreeNode(data, this);
|
|
778
|
+
if (!this.children) this.children = [];
|
|
779
|
+
this.children.push(child);
|
|
780
|
+
return child;
|
|
1542
781
|
}
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
date: /* @__PURE__ */ new Date(),
|
|
1550
|
-
logs: [`Writing ${files.length} files...`]
|
|
1551
|
-
});
|
|
1552
|
-
});
|
|
1553
|
-
fabric.context.on("file:processing:update", async (params) => {
|
|
1554
|
-
const { file, source } = params;
|
|
1555
|
-
await events.emit("file:processing:update", {
|
|
1556
|
-
...params,
|
|
1557
|
-
config: definedConfig,
|
|
1558
|
-
source
|
|
1559
|
-
});
|
|
1560
|
-
if (source) {
|
|
1561
|
-
const key = (0, node_path.relative)((0, node_path.resolve)(definedConfig.root), file.path);
|
|
1562
|
-
await storage?.setItem(key, source);
|
|
1563
|
-
sources.set(file.path, source);
|
|
1564
|
-
}
|
|
1565
|
-
});
|
|
1566
|
-
fabric.context.on("files:processing:end", async (files) => {
|
|
1567
|
-
await events.emit("files:processing:end", files);
|
|
1568
|
-
await events.emit("debug", {
|
|
1569
|
-
date: /* @__PURE__ */ new Date(),
|
|
1570
|
-
logs: [`✓ File write process completed for ${files.length} files`]
|
|
1571
|
-
});
|
|
1572
|
-
});
|
|
1573
|
-
await events.emit("debug", {
|
|
1574
|
-
date: /* @__PURE__ */ new Date(),
|
|
1575
|
-
logs: [
|
|
1576
|
-
"✓ Fabric initialized",
|
|
1577
|
-
` • Storage: ${storage ? storage.name : "disabled (dry-run)"}`,
|
|
1578
|
-
` • Barrel type: ${definedConfig.output.barrelType || "none"}`
|
|
1579
|
-
]
|
|
1580
|
-
});
|
|
1581
|
-
const pluginManager = new PluginManager(definedConfig, {
|
|
1582
|
-
fabric,
|
|
1583
|
-
events,
|
|
1584
|
-
concurrency: 15
|
|
1585
|
-
});
|
|
1586
|
-
if (definedConfig.adapter) {
|
|
1587
|
-
const source = inputToAdapterSource(definedConfig);
|
|
1588
|
-
await events.emit("debug", {
|
|
1589
|
-
date: /* @__PURE__ */ new Date(),
|
|
1590
|
-
logs: [`Running adapter: ${definedConfig.adapter.name}`]
|
|
1591
|
-
});
|
|
1592
|
-
pluginManager.adapter = definedConfig.adapter;
|
|
1593
|
-
pluginManager.rootNode = await definedConfig.adapter.parse(source);
|
|
1594
|
-
await events.emit("debug", {
|
|
1595
|
-
date: /* @__PURE__ */ new Date(),
|
|
1596
|
-
logs: [
|
|
1597
|
-
`✓ Adapter '${definedConfig.adapter.name}' resolved RootNode`,
|
|
1598
|
-
` • Schemas: ${pluginManager.rootNode.schemas.length}`,
|
|
1599
|
-
` • Operations: ${pluginManager.rootNode.operations.length}`
|
|
1600
|
-
]
|
|
1601
|
-
});
|
|
782
|
+
/**
|
|
783
|
+
* Returns the root ancestor of this node, walking up via `parent` links.
|
|
784
|
+
*/
|
|
785
|
+
get root() {
|
|
786
|
+
if (!this.parent) return this;
|
|
787
|
+
return this.parent.root;
|
|
1602
788
|
}
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
throw new BuildError(`Build Error with ${failedPlugins.size} failed plugins`, { errors });
|
|
1616
|
-
}
|
|
1617
|
-
return {
|
|
1618
|
-
failedPlugins,
|
|
1619
|
-
fabric,
|
|
1620
|
-
files,
|
|
1621
|
-
pluginManager,
|
|
1622
|
-
pluginTimings,
|
|
1623
|
-
error: void 0,
|
|
1624
|
-
sources
|
|
1625
|
-
};
|
|
1626
|
-
}
|
|
1627
|
-
async function safeBuild(options, overrides) {
|
|
1628
|
-
const { fabric, pluginManager, events, sources } = overrides ? overrides : await setup(options);
|
|
1629
|
-
const failedPlugins = /* @__PURE__ */ new Set();
|
|
1630
|
-
const pluginTimings = /* @__PURE__ */ new Map();
|
|
1631
|
-
const config = pluginManager.config;
|
|
1632
|
-
try {
|
|
1633
|
-
for (const plugin of pluginManager.plugins) {
|
|
1634
|
-
const context = pluginManager.getContext(plugin);
|
|
1635
|
-
const hrStart = process.hrtime();
|
|
1636
|
-
const installer = plugin.install.bind(context);
|
|
1637
|
-
try {
|
|
1638
|
-
const timestamp = /* @__PURE__ */ new Date();
|
|
1639
|
-
await events.emit("plugin:start", plugin);
|
|
1640
|
-
await events.emit("debug", {
|
|
1641
|
-
date: timestamp,
|
|
1642
|
-
logs: ["Installing plugin...", ` • Plugin Name: ${plugin.name}`]
|
|
1643
|
-
});
|
|
1644
|
-
await installer(context);
|
|
1645
|
-
const duration = getElapsedMs(hrStart);
|
|
1646
|
-
pluginTimings.set(plugin.name, duration);
|
|
1647
|
-
await events.emit("plugin:end", plugin, {
|
|
1648
|
-
duration,
|
|
1649
|
-
success: true
|
|
1650
|
-
});
|
|
1651
|
-
await events.emit("debug", {
|
|
1652
|
-
date: /* @__PURE__ */ new Date(),
|
|
1653
|
-
logs: [`✓ Plugin installed successfully (${formatMs(duration)})`]
|
|
1654
|
-
});
|
|
1655
|
-
} catch (caughtError) {
|
|
1656
|
-
const error = caughtError;
|
|
1657
|
-
const errorTimestamp = /* @__PURE__ */ new Date();
|
|
1658
|
-
const duration = getElapsedMs(hrStart);
|
|
1659
|
-
await events.emit("plugin:end", plugin, {
|
|
1660
|
-
duration,
|
|
1661
|
-
success: false,
|
|
1662
|
-
error
|
|
1663
|
-
});
|
|
1664
|
-
await events.emit("debug", {
|
|
1665
|
-
date: errorTimestamp,
|
|
1666
|
-
logs: [
|
|
1667
|
-
"✗ Plugin installation failed",
|
|
1668
|
-
` • Plugin Name: ${plugin.name}`,
|
|
1669
|
-
` • Error: ${error.constructor.name} - ${error.message}`,
|
|
1670
|
-
" • Stack Trace:",
|
|
1671
|
-
error.stack || "No stack trace available"
|
|
1672
|
-
]
|
|
1673
|
-
});
|
|
1674
|
-
failedPlugins.add({
|
|
1675
|
-
plugin,
|
|
1676
|
-
error
|
|
1677
|
-
});
|
|
1678
|
-
}
|
|
1679
|
-
}
|
|
1680
|
-
if (config.output.barrelType) {
|
|
1681
|
-
const rootPath = (0, node_path.resolve)((0, node_path.resolve)(config.root), config.output.path, BARREL_FILENAME);
|
|
1682
|
-
const rootDir = (0, node_path.dirname)(rootPath);
|
|
1683
|
-
await events.emit("debug", {
|
|
1684
|
-
date: /* @__PURE__ */ new Date(),
|
|
1685
|
-
logs: [
|
|
1686
|
-
"Generating barrel file",
|
|
1687
|
-
` • Type: ${config.output.barrelType}`,
|
|
1688
|
-
` • Path: ${rootPath}`
|
|
1689
|
-
]
|
|
1690
|
-
});
|
|
1691
|
-
const barrelFiles = fabric.files.filter((file) => {
|
|
1692
|
-
return file.sources.some((source) => source.isIndexable);
|
|
1693
|
-
});
|
|
1694
|
-
await events.emit("debug", {
|
|
1695
|
-
date: /* @__PURE__ */ new Date(),
|
|
1696
|
-
logs: [`Found ${barrelFiles.length} indexable files for barrel export`]
|
|
1697
|
-
});
|
|
1698
|
-
const existingBarrel = fabric.files.find((f) => f.path === rootPath);
|
|
1699
|
-
const rootFile = {
|
|
1700
|
-
path: rootPath,
|
|
1701
|
-
baseName: BARREL_FILENAME,
|
|
1702
|
-
exports: buildBarrelExports({
|
|
1703
|
-
barrelFiles,
|
|
1704
|
-
rootDir,
|
|
1705
|
-
existingExports: new Set(existingBarrel?.exports?.flatMap((e) => Array.isArray(e.name) ? e.name : [e.name]).filter((n) => Boolean(n)) ?? []),
|
|
1706
|
-
config,
|
|
1707
|
-
pluginManager
|
|
1708
|
-
}),
|
|
1709
|
-
sources: [],
|
|
1710
|
-
imports: [],
|
|
1711
|
-
meta: {}
|
|
1712
|
-
};
|
|
1713
|
-
await fabric.upsertFile(rootFile);
|
|
1714
|
-
await events.emit("debug", {
|
|
1715
|
-
date: /* @__PURE__ */ new Date(),
|
|
1716
|
-
logs: [`✓ Generated barrel file (${rootFile.exports?.length || 0} exports)`]
|
|
1717
|
-
});
|
|
1718
|
-
}
|
|
1719
|
-
const files = [...fabric.files];
|
|
1720
|
-
await fabric.write({ extension: config.output.extension });
|
|
1721
|
-
return {
|
|
1722
|
-
failedPlugins,
|
|
1723
|
-
fabric,
|
|
1724
|
-
files,
|
|
1725
|
-
pluginManager,
|
|
1726
|
-
pluginTimings,
|
|
1727
|
-
sources
|
|
1728
|
-
};
|
|
1729
|
-
} catch (error) {
|
|
1730
|
-
return {
|
|
1731
|
-
failedPlugins,
|
|
1732
|
-
fabric,
|
|
1733
|
-
files: [],
|
|
1734
|
-
pluginManager,
|
|
1735
|
-
pluginTimings,
|
|
1736
|
-
error,
|
|
1737
|
-
sources
|
|
1738
|
-
};
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, pluginManager }) {
|
|
1742
|
-
const pluginNameMap = /* @__PURE__ */ new Map();
|
|
1743
|
-
for (const plugin of pluginManager.plugins) pluginNameMap.set(plugin.name, plugin);
|
|
1744
|
-
return barrelFiles.flatMap((file) => {
|
|
1745
|
-
const containsOnlyTypes = file.sources?.every((source) => source.isTypeOnly);
|
|
1746
|
-
return (file.sources ?? []).flatMap((source) => {
|
|
1747
|
-
if (!file.path || !source.isIndexable) return [];
|
|
1748
|
-
const meta = file.meta;
|
|
1749
|
-
const pluginOptions = (meta?.pluginName ? pluginNameMap.get(meta.pluginName) : void 0)?.options;
|
|
1750
|
-
if (!pluginOptions || pluginOptions.output?.barrelType === false) return [];
|
|
1751
|
-
const exportName = config.output.barrelType === "all" ? void 0 : source.name ? [source.name] : void 0;
|
|
1752
|
-
if (exportName?.some((n) => existingExports.has(n))) return [];
|
|
1753
|
-
return [{
|
|
1754
|
-
name: exportName,
|
|
1755
|
-
path: getRelativePath(rootDir, file.path),
|
|
1756
|
-
isTypeOnly: config.output.barrelType === "all" ? containsOnlyTypes : source.isTypeOnly
|
|
1757
|
-
}];
|
|
1758
|
-
});
|
|
1759
|
-
});
|
|
1760
|
-
}
|
|
1761
|
-
/**
|
|
1762
|
-
* Maps the resolved `Config['input']` shape into an `AdapterSource` that
|
|
1763
|
-
* the adapter's `parse()` can consume.
|
|
1764
|
-
*/
|
|
1765
|
-
function inputToAdapterSource(config) {
|
|
1766
|
-
if (Array.isArray(config.input)) return {
|
|
1767
|
-
type: "paths",
|
|
1768
|
-
paths: config.input.map((i) => (0, node_path.resolve)(config.root, i.path))
|
|
1769
|
-
};
|
|
1770
|
-
if ("data" in config.input) return {
|
|
1771
|
-
type: "data",
|
|
1772
|
-
data: config.input.data
|
|
1773
|
-
};
|
|
1774
|
-
return {
|
|
1775
|
-
type: "path",
|
|
1776
|
-
path: (0, node_path.resolve)(config.root, config.input.path)
|
|
1777
|
-
};
|
|
1778
|
-
}
|
|
1779
|
-
//#endregion
|
|
1780
|
-
//#region src/defineAdapter.ts
|
|
1781
|
-
/**
|
|
1782
|
-
* Wraps an adapter builder to make the options parameter optional.
|
|
1783
|
-
*
|
|
1784
|
-
* @example
|
|
1785
|
-
* ```ts
|
|
1786
|
-
* export const adapterOas = defineAdapter<OasAdapter>((options) => {
|
|
1787
|
-
* const { validate = true, dateType = 'string' } = options
|
|
1788
|
-
* return {
|
|
1789
|
-
* name: adapterOasName,
|
|
1790
|
-
* options: { validate, dateType, ... },
|
|
1791
|
-
* parse(source) { ... },
|
|
1792
|
-
* }
|
|
1793
|
-
* })
|
|
1794
|
-
* ```
|
|
1795
|
-
*/
|
|
1796
|
-
function defineAdapter(build) {
|
|
1797
|
-
return (options) => build(options ?? {});
|
|
1798
|
-
}
|
|
1799
|
-
//#endregion
|
|
1800
|
-
//#region src/defineGenerator.ts
|
|
1801
|
-
function defineGenerator(generator) {
|
|
1802
|
-
if (generator.type === "react") return {
|
|
1803
|
-
version: "2",
|
|
1804
|
-
Operations() {
|
|
1805
|
-
return null;
|
|
1806
|
-
},
|
|
1807
|
-
Operation() {
|
|
1808
|
-
return null;
|
|
1809
|
-
},
|
|
1810
|
-
Schema() {
|
|
1811
|
-
return null;
|
|
1812
|
-
},
|
|
1813
|
-
...generator
|
|
1814
|
-
};
|
|
1815
|
-
return {
|
|
1816
|
-
version: "2",
|
|
1817
|
-
async operations() {
|
|
1818
|
-
return [];
|
|
1819
|
-
},
|
|
1820
|
-
async operation() {
|
|
1821
|
-
return [];
|
|
1822
|
-
},
|
|
1823
|
-
async schema() {
|
|
1824
|
-
return [];
|
|
1825
|
-
},
|
|
1826
|
-
...generator
|
|
1827
|
-
};
|
|
1828
|
-
}
|
|
1829
|
-
//#endregion
|
|
1830
|
-
//#region src/defineLogger.ts
|
|
1831
|
-
function defineLogger(logger) {
|
|
1832
|
-
return { ...logger };
|
|
1833
|
-
}
|
|
1834
|
-
//#endregion
|
|
1835
|
-
//#region src/definePlugin.ts
|
|
1836
|
-
/**
|
|
1837
|
-
* Wraps a plugin builder to make the options parameter optional.
|
|
1838
|
-
*/
|
|
1839
|
-
function definePlugin(build) {
|
|
1840
|
-
return (options) => build(options ?? {});
|
|
1841
|
-
}
|
|
1842
|
-
//#endregion
|
|
1843
|
-
//#region src/PackageManager.ts
|
|
1844
|
-
var PackageManager = class PackageManager {
|
|
1845
|
-
static #cache = {};
|
|
1846
|
-
#cwd;
|
|
1847
|
-
constructor(workspace) {
|
|
1848
|
-
if (workspace) this.#cwd = workspace;
|
|
1849
|
-
}
|
|
1850
|
-
set workspace(workspace) {
|
|
1851
|
-
this.#cwd = workspace;
|
|
1852
|
-
}
|
|
1853
|
-
get workspace() {
|
|
1854
|
-
return this.#cwd;
|
|
1855
|
-
}
|
|
1856
|
-
normalizeDirectory(directory) {
|
|
1857
|
-
const lastChar = directory[directory.length - 1];
|
|
1858
|
-
if (lastChar && !PATH_SEPARATORS.includes(lastChar)) return `${directory}/`;
|
|
1859
|
-
return directory;
|
|
1860
|
-
}
|
|
1861
|
-
getLocation(path) {
|
|
1862
|
-
let location = path;
|
|
1863
|
-
if (this.#cwd) location = node_module.default.createRequire(this.normalizeDirectory(this.#cwd)).resolve(path);
|
|
1864
|
-
return location;
|
|
1865
|
-
}
|
|
1866
|
-
async import(path) {
|
|
1867
|
-
let location = this.getLocation(path);
|
|
1868
|
-
if (node_os.default.platform() === "win32") location = (0, node_url.pathToFileURL)(location).href;
|
|
1869
|
-
const module = await import(location);
|
|
1870
|
-
return module?.default ?? module;
|
|
1871
|
-
}
|
|
1872
|
-
async getPackageJSON() {
|
|
1873
|
-
const pkgPath = empathic_package.up({ cwd: this.#cwd });
|
|
1874
|
-
if (!pkgPath) return;
|
|
1875
|
-
const json = await read(pkgPath);
|
|
1876
|
-
return JSON.parse(json);
|
|
1877
|
-
}
|
|
1878
|
-
getPackageJSONSync() {
|
|
1879
|
-
const pkgPath = empathic_package.up({ cwd: this.#cwd });
|
|
1880
|
-
if (!pkgPath) return;
|
|
1881
|
-
const json = readSync(pkgPath);
|
|
1882
|
-
return JSON.parse(json);
|
|
1883
|
-
}
|
|
1884
|
-
static setVersion(dependency, version) {
|
|
1885
|
-
PackageManager.#cache[dependency] = version;
|
|
1886
|
-
}
|
|
1887
|
-
#match(packageJSON, dependency) {
|
|
1888
|
-
const dependencies = {
|
|
1889
|
-
...packageJSON.dependencies || {},
|
|
1890
|
-
...packageJSON.devDependencies || {}
|
|
1891
|
-
};
|
|
1892
|
-
if (typeof dependency === "string" && dependencies[dependency]) return dependencies[dependency];
|
|
1893
|
-
const matchedDependency = Object.keys(dependencies).find((dep) => dep.match(dependency));
|
|
1894
|
-
return matchedDependency ? dependencies[matchedDependency] : void 0;
|
|
1895
|
-
}
|
|
1896
|
-
async getVersion(dependency) {
|
|
1897
|
-
if (typeof dependency === "string" && PackageManager.#cache[dependency]) return PackageManager.#cache[dependency];
|
|
1898
|
-
const packageJSON = await this.getPackageJSON();
|
|
1899
|
-
if (!packageJSON) return;
|
|
1900
|
-
return this.#match(packageJSON, dependency);
|
|
1901
|
-
}
|
|
1902
|
-
getVersionSync(dependency) {
|
|
1903
|
-
if (typeof dependency === "string" && PackageManager.#cache[dependency]) return PackageManager.#cache[dependency];
|
|
1904
|
-
const packageJSON = this.getPackageJSONSync();
|
|
1905
|
-
if (!packageJSON) return;
|
|
1906
|
-
return this.#match(packageJSON, dependency);
|
|
1907
|
-
}
|
|
1908
|
-
async isValid(dependency, version) {
|
|
1909
|
-
const packageVersion = await this.getVersion(dependency);
|
|
1910
|
-
if (!packageVersion) return false;
|
|
1911
|
-
if (packageVersion === version) return true;
|
|
1912
|
-
const semVer = (0, semver.coerce)(packageVersion);
|
|
1913
|
-
if (!semVer) return false;
|
|
1914
|
-
return (0, semver.satisfies)(semVer, version);
|
|
1915
|
-
}
|
|
1916
|
-
isValidSync(dependency, version) {
|
|
1917
|
-
const packageVersion = this.getVersionSync(dependency);
|
|
1918
|
-
if (!packageVersion) return false;
|
|
1919
|
-
if (packageVersion === version) return true;
|
|
1920
|
-
const semVer = (0, semver.coerce)(packageVersion);
|
|
1921
|
-
if (!semVer) return false;
|
|
1922
|
-
return (0, semver.satisfies)(semVer, version);
|
|
1923
|
-
}
|
|
1924
|
-
};
|
|
1925
|
-
//#endregion
|
|
1926
|
-
//#region src/storages/memoryStorage.ts
|
|
1927
|
-
/**
|
|
1928
|
-
* In-memory storage driver. Useful for testing and dry-run scenarios where
|
|
1929
|
-
* generated output should be captured without touching the filesystem.
|
|
1930
|
-
*
|
|
1931
|
-
* All data lives in a `Map` scoped to the storage instance and is discarded
|
|
1932
|
-
* when the instance is garbage-collected.
|
|
1933
|
-
*
|
|
1934
|
-
* @example
|
|
1935
|
-
* ```ts
|
|
1936
|
-
* import { defineConfig, memoryStorage } from '@kubb/core'
|
|
1937
|
-
*
|
|
1938
|
-
* export default defineConfig({
|
|
1939
|
-
* input: { path: './petStore.yaml' },
|
|
1940
|
-
* output: { path: './src/gen', storage: memoryStorage() },
|
|
1941
|
-
* })
|
|
1942
|
-
* ```
|
|
1943
|
-
*/
|
|
1944
|
-
const memoryStorage = defineStorage(() => {
|
|
1945
|
-
const store = /* @__PURE__ */ new Map();
|
|
1946
|
-
return {
|
|
1947
|
-
name: "memory",
|
|
1948
|
-
async hasItem(key) {
|
|
1949
|
-
return store.has(key);
|
|
1950
|
-
},
|
|
1951
|
-
async getItem(key) {
|
|
1952
|
-
return store.get(key) ?? null;
|
|
1953
|
-
},
|
|
1954
|
-
async setItem(key, value) {
|
|
1955
|
-
store.set(key, value);
|
|
1956
|
-
},
|
|
1957
|
-
async removeItem(key) {
|
|
1958
|
-
store.delete(key);
|
|
1959
|
-
},
|
|
1960
|
-
async getKeys(base) {
|
|
1961
|
-
const keys = [...store.keys()];
|
|
1962
|
-
return base ? keys.filter((k) => k.startsWith(base)) : keys;
|
|
1963
|
-
},
|
|
1964
|
-
async clear(base) {
|
|
1965
|
-
if (!base) {
|
|
1966
|
-
store.clear();
|
|
1967
|
-
return;
|
|
1968
|
-
}
|
|
1969
|
-
for (const key of store.keys()) if (key.startsWith(base)) store.delete(key);
|
|
1970
|
-
}
|
|
1971
|
-
};
|
|
1972
|
-
});
|
|
1973
|
-
//#endregion
|
|
1974
|
-
//#region src/utils/FunctionParams.ts
|
|
1975
|
-
/**
|
|
1976
|
-
* @deprecated
|
|
1977
|
-
*/
|
|
1978
|
-
var FunctionParams = class FunctionParams {
|
|
1979
|
-
#items = [];
|
|
1980
|
-
get items() {
|
|
1981
|
-
return this.#items.flat();
|
|
1982
|
-
}
|
|
1983
|
-
add(item) {
|
|
1984
|
-
if (!item) return this;
|
|
1985
|
-
if (Array.isArray(item)) {
|
|
1986
|
-
item.filter((x) => x !== void 0).forEach((it) => {
|
|
1987
|
-
this.#items.push(it);
|
|
1988
|
-
});
|
|
1989
|
-
return this;
|
|
1990
|
-
}
|
|
1991
|
-
this.#items.push(item);
|
|
1992
|
-
return this;
|
|
1993
|
-
}
|
|
1994
|
-
static #orderItems(items) {
|
|
1995
|
-
return (0, remeda.sortBy)(items.filter(Boolean), [(item) => Array.isArray(item), "desc"], [(item) => !Array.isArray(item) && item.default !== void 0, "asc"], [(item) => Array.isArray(item) || (item.required ?? true), "desc"]);
|
|
1996
|
-
}
|
|
1997
|
-
static #addParams(acc, item) {
|
|
1998
|
-
const { enabled = true, name, type, required = true, ...rest } = item;
|
|
1999
|
-
if (!enabled) return acc;
|
|
2000
|
-
if (!name) {
|
|
2001
|
-
acc.push(`${type}${rest.default ? ` = ${rest.default}` : ""}`);
|
|
2002
|
-
return acc;
|
|
2003
|
-
}
|
|
2004
|
-
const parameterName = name.startsWith("{") ? name : camelCase(name);
|
|
2005
|
-
if (type) if (required) acc.push(`${parameterName}: ${type}${rest.default ? ` = ${rest.default}` : ""}`);
|
|
2006
|
-
else acc.push(`${parameterName}?: ${type}`);
|
|
2007
|
-
else acc.push(`${parameterName}`);
|
|
2008
|
-
return acc;
|
|
2009
|
-
}
|
|
2010
|
-
static toObject(items) {
|
|
2011
|
-
let type = [];
|
|
2012
|
-
let name = [];
|
|
2013
|
-
const enabled = items.every((item) => item.enabled) ? items.at(0)?.enabled : true;
|
|
2014
|
-
const required = items.every((item) => item.required) ?? true;
|
|
2015
|
-
items.forEach((item) => {
|
|
2016
|
-
name = FunctionParams.#addParams(name, {
|
|
2017
|
-
...item,
|
|
2018
|
-
type: void 0
|
|
2019
|
-
});
|
|
2020
|
-
if (items.some((item) => item.type)) type = FunctionParams.#addParams(type, item);
|
|
2021
|
-
});
|
|
2022
|
-
return {
|
|
2023
|
-
name: `{ ${name.join(", ")} }`,
|
|
2024
|
-
type: type.length ? `{ ${type.join("; ")} }` : void 0,
|
|
2025
|
-
enabled,
|
|
2026
|
-
required
|
|
2027
|
-
};
|
|
2028
|
-
}
|
|
2029
|
-
toObject() {
|
|
2030
|
-
const items = FunctionParams.#orderItems(this.#items).flat();
|
|
2031
|
-
return FunctionParams.toObject(items);
|
|
2032
|
-
}
|
|
2033
|
-
static toString(items) {
|
|
2034
|
-
return FunctionParams.#orderItems(items).reduce((acc, item) => {
|
|
2035
|
-
if (Array.isArray(item)) {
|
|
2036
|
-
if (item.length <= 0) return acc;
|
|
2037
|
-
const subItems = FunctionParams.#orderItems(item);
|
|
2038
|
-
const objectItem = FunctionParams.toObject(subItems);
|
|
2039
|
-
return FunctionParams.#addParams(acc, objectItem);
|
|
2040
|
-
}
|
|
2041
|
-
return FunctionParams.#addParams(acc, item);
|
|
2042
|
-
}, []).join(", ");
|
|
2043
|
-
}
|
|
2044
|
-
toString() {
|
|
2045
|
-
const items = FunctionParams.#orderItems(this.#items);
|
|
2046
|
-
return FunctionParams.toString(items);
|
|
2047
|
-
}
|
|
2048
|
-
};
|
|
2049
|
-
//#endregion
|
|
2050
|
-
//#region src/utils/formatters.ts
|
|
2051
|
-
/**
|
|
2052
|
-
* Check if a formatter command is available in the system.
|
|
2053
|
-
*
|
|
2054
|
-
* @param formatter - The formatter to check ('biome', 'prettier', or 'oxfmt')
|
|
2055
|
-
* @returns Promise that resolves to true if the formatter is available, false otherwise
|
|
2056
|
-
*
|
|
2057
|
-
* @remarks
|
|
2058
|
-
* This function checks availability by running `<formatter> --version` command.
|
|
2059
|
-
* All supported formatters (biome, prettier, oxfmt) implement the --version flag.
|
|
2060
|
-
*/
|
|
2061
|
-
async function isFormatterAvailable(formatter) {
|
|
2062
|
-
try {
|
|
2063
|
-
await (0, tinyexec.x)(formatter, ["--version"], { nodeOptions: { stdio: "ignore" } });
|
|
2064
|
-
return true;
|
|
2065
|
-
} catch {
|
|
2066
|
-
return false;
|
|
2067
|
-
}
|
|
2068
|
-
}
|
|
2069
|
-
/**
|
|
2070
|
-
* Detect which formatter is available in the system.
|
|
2071
|
-
*
|
|
2072
|
-
* @returns Promise that resolves to the first available formatter or undefined if none are found
|
|
2073
|
-
*
|
|
2074
|
-
* @remarks
|
|
2075
|
-
* Checks in order of preference: biome, oxfmt, prettier.
|
|
2076
|
-
* Uses the `--version` flag to detect if each formatter command is available.
|
|
2077
|
-
* This is a reliable method as all supported formatters implement this flag.
|
|
2078
|
-
*
|
|
2079
|
-
* @example
|
|
2080
|
-
* ```typescript
|
|
2081
|
-
* const formatter = await detectFormatter()
|
|
2082
|
-
* if (formatter) {
|
|
2083
|
-
* console.log(`Using ${formatter} for formatting`)
|
|
2084
|
-
* } else {
|
|
2085
|
-
* console.log('No formatter found')
|
|
2086
|
-
* }
|
|
2087
|
-
* ```
|
|
2088
|
-
*/
|
|
2089
|
-
async function detectFormatter() {
|
|
2090
|
-
for (const formatter of [
|
|
2091
|
-
"biome",
|
|
2092
|
-
"oxfmt",
|
|
2093
|
-
"prettier"
|
|
2094
|
-
]) if (await isFormatterAvailable(formatter)) return formatter;
|
|
2095
|
-
}
|
|
2096
|
-
//#endregion
|
|
2097
|
-
//#region src/utils/TreeNode.ts
|
|
2098
|
-
var TreeNode = class TreeNode {
|
|
2099
|
-
data;
|
|
2100
|
-
parent;
|
|
2101
|
-
children = [];
|
|
2102
|
-
#cachedLeaves = void 0;
|
|
2103
|
-
constructor(data, parent) {
|
|
2104
|
-
this.data = data;
|
|
2105
|
-
this.parent = parent;
|
|
2106
|
-
}
|
|
2107
|
-
addChild(data) {
|
|
2108
|
-
const child = new TreeNode(data, this);
|
|
2109
|
-
if (!this.children) this.children = [];
|
|
2110
|
-
this.children.push(child);
|
|
2111
|
-
return child;
|
|
2112
|
-
}
|
|
2113
|
-
get root() {
|
|
2114
|
-
if (!this.parent) return this;
|
|
2115
|
-
return this.parent.root;
|
|
2116
|
-
}
|
|
2117
|
-
get leaves() {
|
|
2118
|
-
if (!this.children || this.children.length === 0) return [this];
|
|
2119
|
-
if (this.#cachedLeaves) return this.#cachedLeaves;
|
|
2120
|
-
const leaves = [];
|
|
2121
|
-
for (const child of this.children) leaves.push(...child.leaves);
|
|
2122
|
-
this.#cachedLeaves = leaves;
|
|
2123
|
-
return leaves;
|
|
789
|
+
/**
|
|
790
|
+
* Returns all leaf descendants (nodes with no children) of this node.
|
|
791
|
+
*
|
|
792
|
+
* Results are cached after the first traversal.
|
|
793
|
+
*/
|
|
794
|
+
get leaves() {
|
|
795
|
+
if (!this.children || this.children.length === 0) return [this];
|
|
796
|
+
if (this.#cachedLeaves) return this.#cachedLeaves;
|
|
797
|
+
const leaves = [];
|
|
798
|
+
for (const child of this.children) leaves.push(...child.leaves);
|
|
799
|
+
this.#cachedLeaves = leaves;
|
|
800
|
+
return leaves;
|
|
2124
801
|
}
|
|
802
|
+
/**
|
|
803
|
+
* Visits this node and every descendant in depth-first order.
|
|
804
|
+
*/
|
|
2125
805
|
forEach(callback) {
|
|
2126
806
|
if (typeof callback !== "function") throw new TypeError("forEach() callback must be a function");
|
|
2127
807
|
callback(this);
|
|
2128
808
|
for (const child of this.children) child.forEach(callback);
|
|
2129
809
|
return this;
|
|
2130
810
|
}
|
|
811
|
+
/**
|
|
812
|
+
* Finds the first leaf that satisfies `predicate`, or `undefined` when none match.
|
|
813
|
+
*/
|
|
2131
814
|
findDeep(predicate) {
|
|
2132
815
|
if (typeof predicate !== "function") throw new TypeError("find() predicate must be a function");
|
|
2133
816
|
return this.leaves.find(predicate);
|
|
2134
817
|
}
|
|
818
|
+
/**
|
|
819
|
+
* Calls `callback` for every leaf of this node.
|
|
820
|
+
*/
|
|
2135
821
|
forEachDeep(callback) {
|
|
2136
822
|
if (typeof callback !== "function") throw new TypeError("forEach() callback must be a function");
|
|
2137
823
|
this.leaves.forEach(callback);
|
|
2138
824
|
}
|
|
825
|
+
/**
|
|
826
|
+
* Returns all leaves that satisfy `callback`.
|
|
827
|
+
*/
|
|
2139
828
|
filterDeep(callback) {
|
|
2140
829
|
if (typeof callback !== "function") throw new TypeError("filter() callback must be a function");
|
|
2141
830
|
return this.leaves.filter(callback);
|
|
2142
831
|
}
|
|
832
|
+
/**
|
|
833
|
+
* Maps every leaf through `callback` and returns the resulting array.
|
|
834
|
+
*/
|
|
2143
835
|
mapDeep(callback) {
|
|
2144
836
|
if (typeof callback !== "function") throw new TypeError("map() callback must be a function");
|
|
2145
837
|
return this.leaves.map(callback);
|
|
2146
838
|
}
|
|
839
|
+
/**
|
|
840
|
+
* Builds a {@link TreeNode} tree from a flat list of files.
|
|
841
|
+
*
|
|
842
|
+
* - Filters to files under `root` (when provided) and skips `.json` files.
|
|
843
|
+
* - Returns `null` when no files match.
|
|
844
|
+
*/
|
|
2147
845
|
static build(files, root) {
|
|
2148
846
|
try {
|
|
2149
847
|
const filteredTree = buildDirectoryTree(files, root);
|
|
@@ -2152,14 +850,14 @@ var TreeNode = class TreeNode {
|
|
|
2152
850
|
name: filteredTree.name,
|
|
2153
851
|
path: filteredTree.path,
|
|
2154
852
|
file: filteredTree.file,
|
|
2155
|
-
type: getMode(filteredTree.path)
|
|
853
|
+
type: require_PluginDriver.PluginDriver.getMode(filteredTree.path)
|
|
2156
854
|
});
|
|
2157
855
|
const recurse = (node, item) => {
|
|
2158
856
|
const subNode = node.addChild({
|
|
2159
857
|
name: item.name,
|
|
2160
858
|
path: item.path,
|
|
2161
859
|
file: item.file,
|
|
2162
|
-
type: getMode(item.path)
|
|
860
|
+
type: require_PluginDriver.PluginDriver.getMode(item.path)
|
|
2163
861
|
});
|
|
2164
862
|
if (item.children?.length) item.children?.forEach((child) => {
|
|
2165
863
|
recurse(subNode, child);
|
|
@@ -2214,69 +912,66 @@ function buildDirectoryTree(files, rootFolder = "") {
|
|
|
2214
912
|
return root;
|
|
2215
913
|
}
|
|
2216
914
|
//#endregion
|
|
2217
|
-
//#region src/
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
if (!item.data.name) return;
|
|
2234
|
-
(item.
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
isExportable: false,
|
|
2247
|
-
isIndexable: false
|
|
2248
|
-
});
|
|
2249
|
-
});
|
|
915
|
+
//#region src/utils/getBarrelFiles.ts
|
|
916
|
+
function getBarrelFilesByRoot(root, files) {
|
|
917
|
+
const cachedFiles = /* @__PURE__ */ new Map();
|
|
918
|
+
TreeNode.build(files, root)?.forEach((treeNode) => {
|
|
919
|
+
if (!treeNode?.children || !treeNode.parent?.data.path) return;
|
|
920
|
+
const barrelFile = (0, _kubb_ast.createFile)({
|
|
921
|
+
path: (0, node_path.join)(treeNode.parent?.data.path, require_PluginDriver.BARREL_FILENAME),
|
|
922
|
+
baseName: require_PluginDriver.BARREL_FILENAME,
|
|
923
|
+
exports: [],
|
|
924
|
+
imports: [],
|
|
925
|
+
sources: []
|
|
926
|
+
});
|
|
927
|
+
const previousBarrelFile = cachedFiles.get(barrelFile.path);
|
|
928
|
+
treeNode.leaves.forEach((item) => {
|
|
929
|
+
if (!item.data.name) return;
|
|
930
|
+
(item.data.file?.sources || []).forEach((source) => {
|
|
931
|
+
if (!item.data.file?.path || !source.isIndexable || !source.name) return;
|
|
932
|
+
if (previousBarrelFile?.sources.some((item) => item.name === source.name && item.isTypeOnly === source.isTypeOnly)) return;
|
|
933
|
+
barrelFile.exports.push((0, _kubb_ast.createExport)({
|
|
934
|
+
name: [source.name],
|
|
935
|
+
path: getRelativePath(treeNode.parent?.data.path, item.data.path),
|
|
936
|
+
isTypeOnly: source.isTypeOnly
|
|
937
|
+
}));
|
|
938
|
+
barrelFile.sources.push((0, _kubb_ast.createSource)({
|
|
939
|
+
name: source.name,
|
|
940
|
+
isTypeOnly: source.isTypeOnly,
|
|
941
|
+
isExportable: false,
|
|
942
|
+
isIndexable: false
|
|
943
|
+
}));
|
|
2250
944
|
});
|
|
2251
|
-
if (previousBarrelFile) {
|
|
2252
|
-
previousBarrelFile.sources.push(...barrelFile.sources);
|
|
2253
|
-
previousBarrelFile.exports?.push(...barrelFile.exports || []);
|
|
2254
|
-
} else cachedFiles.set(barrelFile.path, barrelFile);
|
|
2255
945
|
});
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
946
|
+
if (previousBarrelFile) {
|
|
947
|
+
previousBarrelFile.sources.push(...barrelFile.sources);
|
|
948
|
+
previousBarrelFile.exports.push(...barrelFile.exports);
|
|
949
|
+
} else cachedFiles.set(barrelFile.path, barrelFile);
|
|
950
|
+
});
|
|
951
|
+
return [...cachedFiles.values()];
|
|
952
|
+
}
|
|
2261
953
|
function trimExtName(text) {
|
|
2262
954
|
const dotIndex = text.lastIndexOf(".");
|
|
2263
955
|
if (dotIndex > 0 && !text.includes("/", dotIndex)) return text.slice(0, dotIndex);
|
|
2264
956
|
return text;
|
|
2265
957
|
}
|
|
958
|
+
/**
|
|
959
|
+
* Generates `index.ts` barrel files for all directories under `root/output.path`.
|
|
960
|
+
*
|
|
961
|
+
* - Returns an empty array when `type` is falsy or `'propagate'`.
|
|
962
|
+
* - Skips generation when the output path itself ends with `index` (already a barrel).
|
|
963
|
+
* - When `type` is `'all'`, strips named exports so every re-export becomes a wildcard (`export * from`).
|
|
964
|
+
* - Attaches `meta` to each barrel file for downstream plugin identification.
|
|
965
|
+
*/
|
|
2266
966
|
async function getBarrelFiles(files, { type, meta = {}, root, output }) {
|
|
2267
967
|
if (!type || type === "propagate") return [];
|
|
2268
|
-
const barrelManager = new BarrelManager();
|
|
2269
968
|
const pathToBuildFrom = (0, node_path.join)(root, output.path);
|
|
2270
969
|
if (trimExtName(pathToBuildFrom).endsWith("index")) return [];
|
|
2271
|
-
const barrelFiles =
|
|
2272
|
-
files,
|
|
2273
|
-
root: pathToBuildFrom,
|
|
2274
|
-
meta
|
|
2275
|
-
});
|
|
970
|
+
const barrelFiles = getBarrelFilesByRoot(pathToBuildFrom, files);
|
|
2276
971
|
if (type === "all") return barrelFiles.map((file) => {
|
|
2277
972
|
return {
|
|
2278
973
|
...file,
|
|
2279
|
-
exports: file.exports
|
|
974
|
+
exports: file.exports.map((exportItem) => {
|
|
2280
975
|
return {
|
|
2281
976
|
...exportItem,
|
|
2282
977
|
name: void 0
|
|
@@ -2292,142 +987,631 @@ async function getBarrelFiles(files, { type, meta = {}, root, output }) {
|
|
|
2292
987
|
});
|
|
2293
988
|
}
|
|
2294
989
|
//#endregion
|
|
2295
|
-
//#region src/utils/
|
|
2296
|
-
function
|
|
2297
|
-
return
|
|
2298
|
-
}
|
|
2299
|
-
function isObjectPlugins(plugins) {
|
|
2300
|
-
return plugins instanceof Object && !Array.isArray(plugins);
|
|
2301
|
-
}
|
|
2302
|
-
function getPlugins(plugins) {
|
|
2303
|
-
if (isObjectPlugins(plugins)) throw new Error("Object plugins are not supported anymore, best to use http://kubb.dev/getting-started/configure#json");
|
|
2304
|
-
if (isJSONPlugins(plugins)) throw new Error("JSON plugins are not supported anymore, best to use http://kubb.dev/getting-started/configure#json");
|
|
2305
|
-
return Promise.resolve(plugins);
|
|
990
|
+
//#region src/utils/isInputPath.ts
|
|
991
|
+
function isInputPath(config) {
|
|
992
|
+
return typeof config?.input === "object" && config.input !== null && "path" in config.input;
|
|
2306
993
|
}
|
|
2307
994
|
//#endregion
|
|
2308
|
-
//#region src/
|
|
995
|
+
//#region src/createKubb.ts
|
|
996
|
+
async function setup(userConfig, options = {}) {
|
|
997
|
+
const hooks = options.hooks ?? new AsyncEventEmitter();
|
|
998
|
+
const sources = /* @__PURE__ */ new Map();
|
|
999
|
+
const diagnosticInfo = getDiagnosticInfo();
|
|
1000
|
+
if (Array.isArray(userConfig.input)) await hooks.emit("kubb:warn", "This feature is still under development — use with caution");
|
|
1001
|
+
await hooks.emit("kubb:debug", {
|
|
1002
|
+
date: /* @__PURE__ */ new Date(),
|
|
1003
|
+
logs: [
|
|
1004
|
+
"Configuration:",
|
|
1005
|
+
` • Name: ${userConfig.name || "unnamed"}`,
|
|
1006
|
+
` • Root: ${userConfig.root || process.cwd()}`,
|
|
1007
|
+
` • Output: ${userConfig.output?.path || "not specified"}`,
|
|
1008
|
+
` • Plugins: ${userConfig.plugins?.length || 0}`,
|
|
1009
|
+
"Output Settings:",
|
|
1010
|
+
` • Storage: ${userConfig.output?.storage ? `custom(${userConfig.output.storage.name})` : userConfig.output?.write === false ? "disabled" : "filesystem (default)"}`,
|
|
1011
|
+
` • Formatter: ${userConfig.output?.format || "none"}`,
|
|
1012
|
+
` • Linter: ${userConfig.output?.lint || "none"}`,
|
|
1013
|
+
"Environment:",
|
|
1014
|
+
Object.entries(diagnosticInfo).map(([key, value]) => ` • ${key}: ${value}`).join("\n")
|
|
1015
|
+
]
|
|
1016
|
+
});
|
|
1017
|
+
try {
|
|
1018
|
+
if (isInputPath(userConfig) && !new URLPath(userConfig.input.path).isURL) {
|
|
1019
|
+
await exists(userConfig.input.path);
|
|
1020
|
+
await hooks.emit("kubb:debug", {
|
|
1021
|
+
date: /* @__PURE__ */ new Date(),
|
|
1022
|
+
logs: [`✓ Input file validated: ${userConfig.input.path}`]
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
} catch (caughtError) {
|
|
1026
|
+
if (isInputPath(userConfig)) {
|
|
1027
|
+
const error = caughtError;
|
|
1028
|
+
throw new Error(`Cannot read file/URL defined in \`input.path\` or set with \`kubb generate PATH\` in the CLI of your Kubb config ${userConfig.input.path}`, { cause: error });
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
if (!userConfig.adapter) throw new Error("Adapter should be defined");
|
|
1032
|
+
const config = {
|
|
1033
|
+
...userConfig,
|
|
1034
|
+
root: userConfig.root || process.cwd(),
|
|
1035
|
+
parsers: userConfig.parsers ?? [],
|
|
1036
|
+
adapter: userConfig.adapter,
|
|
1037
|
+
output: {
|
|
1038
|
+
write: true,
|
|
1039
|
+
barrelType: "named",
|
|
1040
|
+
extension: require_PluginDriver.DEFAULT_EXTENSION,
|
|
1041
|
+
defaultBanner: require_PluginDriver.DEFAULT_BANNER,
|
|
1042
|
+
...userConfig.output
|
|
1043
|
+
},
|
|
1044
|
+
devtools: userConfig.devtools ? {
|
|
1045
|
+
studioUrl: require_PluginDriver.DEFAULT_STUDIO_URL,
|
|
1046
|
+
...typeof userConfig.devtools === "boolean" ? {} : userConfig.devtools
|
|
1047
|
+
} : void 0,
|
|
1048
|
+
plugins: userConfig.plugins
|
|
1049
|
+
};
|
|
1050
|
+
const storage = config.output.write === false ? null : config.output.storage ?? fsStorage();
|
|
1051
|
+
if (config.output.clean) {
|
|
1052
|
+
await hooks.emit("kubb:debug", {
|
|
1053
|
+
date: /* @__PURE__ */ new Date(),
|
|
1054
|
+
logs: ["Cleaning output directories", ` • Output: ${config.output.path}`]
|
|
1055
|
+
});
|
|
1056
|
+
await storage?.clear((0, node_path.resolve)(config.root, config.output.path));
|
|
1057
|
+
}
|
|
1058
|
+
const driver = new require_PluginDriver.PluginDriver(config, { hooks });
|
|
1059
|
+
const adapter = config.adapter;
|
|
1060
|
+
if (!adapter) throw new Error("No adapter configured. Please provide an adapter in your kubb.config.ts.");
|
|
1061
|
+
const source = inputToAdapterSource(config);
|
|
1062
|
+
await hooks.emit("kubb:debug", {
|
|
1063
|
+
date: /* @__PURE__ */ new Date(),
|
|
1064
|
+
logs: [`Running adapter: ${adapter.name}`]
|
|
1065
|
+
});
|
|
1066
|
+
driver.adapter = adapter;
|
|
1067
|
+
driver.inputNode = await adapter.parse(source);
|
|
1068
|
+
await hooks.emit("kubb:debug", {
|
|
1069
|
+
date: /* @__PURE__ */ new Date(),
|
|
1070
|
+
logs: [
|
|
1071
|
+
`✓ Adapter '${adapter.name}' resolved InputNode`,
|
|
1072
|
+
` • Schemas: ${driver.inputNode.schemas.length}`,
|
|
1073
|
+
` • Operations: ${driver.inputNode.operations.length}`
|
|
1074
|
+
]
|
|
1075
|
+
});
|
|
1076
|
+
return {
|
|
1077
|
+
config,
|
|
1078
|
+
hooks,
|
|
1079
|
+
driver,
|
|
1080
|
+
sources,
|
|
1081
|
+
storage
|
|
1082
|
+
};
|
|
1083
|
+
}
|
|
2309
1084
|
/**
|
|
2310
|
-
*
|
|
1085
|
+
* Walks the AST and dispatches nodes to a plugin's direct AST hooks
|
|
1086
|
+
* (`schema`, `operation`, `operations`).
|
|
2311
1087
|
*/
|
|
2312
|
-
async function
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
1088
|
+
async function runPluginAstHooks(plugin, context) {
|
|
1089
|
+
const { adapter, inputNode, resolver, driver } = context;
|
|
1090
|
+
const { exclude, include, override } = plugin.options;
|
|
1091
|
+
if (!adapter || !inputNode) throw new Error(`[${plugin.name}] No adapter found. Add an OAS adapter (e.g. pluginOas()) before this plugin in your Kubb config.`);
|
|
1092
|
+
function resolveRenderer(gen) {
|
|
1093
|
+
return gen.renderer === null ? void 0 : gen.renderer ?? plugin.renderer ?? context.config.renderer;
|
|
1094
|
+
}
|
|
1095
|
+
const generators = plugin.generators ?? [];
|
|
1096
|
+
const collectedOperations = [];
|
|
1097
|
+
const generatorContext = {
|
|
1098
|
+
...context,
|
|
1099
|
+
resolver: driver.getResolver(plugin.name)
|
|
1100
|
+
};
|
|
1101
|
+
await (0, _kubb_ast.walk)(inputNode, {
|
|
1102
|
+
depth: "shallow",
|
|
1103
|
+
async schema(node) {
|
|
1104
|
+
const transformedNode = plugin.transformer ? (0, _kubb_ast.transform)(node, plugin.transformer) : node;
|
|
1105
|
+
const options = resolver.resolveOptions(transformedNode, {
|
|
1106
|
+
options: plugin.options,
|
|
1107
|
+
exclude,
|
|
1108
|
+
include,
|
|
1109
|
+
override
|
|
1110
|
+
});
|
|
1111
|
+
if (options === null) return;
|
|
1112
|
+
const ctx = {
|
|
1113
|
+
...generatorContext,
|
|
1114
|
+
options
|
|
1115
|
+
};
|
|
1116
|
+
for (const gen of generators) {
|
|
1117
|
+
if (!gen.schema) continue;
|
|
1118
|
+
await require_PluginDriver.applyHookResult(await gen.schema(transformedNode, ctx), driver, resolveRenderer(gen));
|
|
1119
|
+
}
|
|
1120
|
+
await driver.hooks.emit("kubb:generate:schema", transformedNode, ctx);
|
|
1121
|
+
},
|
|
1122
|
+
async operation(node) {
|
|
1123
|
+
const transformedNode = plugin.transformer ? (0, _kubb_ast.transform)(node, plugin.transformer) : node;
|
|
1124
|
+
const options = resolver.resolveOptions(transformedNode, {
|
|
1125
|
+
options: plugin.options,
|
|
1126
|
+
exclude,
|
|
1127
|
+
include,
|
|
1128
|
+
override
|
|
1129
|
+
});
|
|
1130
|
+
if (options !== null) {
|
|
1131
|
+
collectedOperations.push(transformedNode);
|
|
1132
|
+
const ctx = {
|
|
1133
|
+
...generatorContext,
|
|
1134
|
+
options
|
|
1135
|
+
};
|
|
1136
|
+
for (const gen of generators) {
|
|
1137
|
+
if (!gen.operation) continue;
|
|
1138
|
+
await require_PluginDriver.applyHookResult(await gen.operation(transformedNode, ctx), driver, resolveRenderer(gen));
|
|
1139
|
+
}
|
|
1140
|
+
await driver.hooks.emit("kubb:generate:operation", transformedNode, ctx);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
});
|
|
1144
|
+
if (collectedOperations.length > 0) {
|
|
1145
|
+
const ctx = {
|
|
1146
|
+
...generatorContext,
|
|
1147
|
+
options: plugin.options
|
|
1148
|
+
};
|
|
1149
|
+
for (const gen of generators) {
|
|
1150
|
+
if (!gen.operations) continue;
|
|
1151
|
+
await require_PluginDriver.applyHookResult(await gen.operations(collectedOperations, ctx), driver, resolveRenderer(gen));
|
|
1152
|
+
}
|
|
1153
|
+
await driver.hooks.emit("kubb:generate:operations", collectedOperations, ctx);
|
|
2322
1154
|
}
|
|
2323
|
-
return results;
|
|
2324
1155
|
}
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
1156
|
+
async function safeBuild(setupResult) {
|
|
1157
|
+
const { driver, hooks, sources, storage } = setupResult;
|
|
1158
|
+
const failedPlugins = /* @__PURE__ */ new Set();
|
|
1159
|
+
const pluginTimings = /* @__PURE__ */ new Map();
|
|
1160
|
+
const config = driver.config;
|
|
2328
1161
|
try {
|
|
2329
|
-
await
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
1162
|
+
await driver.emitSetupHooks();
|
|
1163
|
+
if (driver.adapter && driver.inputNode) await hooks.emit("kubb:build:start", {
|
|
1164
|
+
config,
|
|
1165
|
+
adapter: driver.adapter,
|
|
1166
|
+
inputNode: driver.inputNode,
|
|
1167
|
+
getPlugin: driver.getPlugin.bind(driver)
|
|
1168
|
+
});
|
|
1169
|
+
for (const plugin of driver.plugins.values()) {
|
|
1170
|
+
const context = driver.getContext(plugin);
|
|
1171
|
+
const hrStart = process.hrtime();
|
|
1172
|
+
const { output } = plugin.options ?? {};
|
|
1173
|
+
const root = (0, node_path.resolve)(config.root, config.output.path);
|
|
1174
|
+
try {
|
|
1175
|
+
const timestamp = /* @__PURE__ */ new Date();
|
|
1176
|
+
await hooks.emit("kubb:plugin:start", plugin);
|
|
1177
|
+
await hooks.emit("kubb:debug", {
|
|
1178
|
+
date: timestamp,
|
|
1179
|
+
logs: ["Starting plugin...", ` • Plugin Name: ${plugin.name}`]
|
|
1180
|
+
});
|
|
1181
|
+
if (plugin.generators?.length || driver.hasRegisteredGenerators(plugin.name)) await runPluginAstHooks(plugin, context);
|
|
1182
|
+
if (output) {
|
|
1183
|
+
const barrelFiles = await getBarrelFiles(driver.fileManager.files, {
|
|
1184
|
+
type: output.barrelType ?? "named",
|
|
1185
|
+
root,
|
|
1186
|
+
output,
|
|
1187
|
+
meta: { pluginName: plugin.name }
|
|
1188
|
+
});
|
|
1189
|
+
await context.upsertFile(...barrelFiles);
|
|
1190
|
+
}
|
|
1191
|
+
const duration = getElapsedMs(hrStart);
|
|
1192
|
+
pluginTimings.set(plugin.name, duration);
|
|
1193
|
+
await hooks.emit("kubb:plugin:end", plugin, {
|
|
1194
|
+
duration,
|
|
1195
|
+
success: true
|
|
1196
|
+
});
|
|
1197
|
+
await hooks.emit("kubb:debug", {
|
|
1198
|
+
date: /* @__PURE__ */ new Date(),
|
|
1199
|
+
logs: [`✓ Plugin started successfully (${formatMs(duration)})`]
|
|
1200
|
+
});
|
|
1201
|
+
} catch (caughtError) {
|
|
1202
|
+
const error = caughtError;
|
|
1203
|
+
const errorTimestamp = /* @__PURE__ */ new Date();
|
|
1204
|
+
const duration = getElapsedMs(hrStart);
|
|
1205
|
+
await hooks.emit("kubb:plugin:end", plugin, {
|
|
1206
|
+
duration,
|
|
1207
|
+
success: false,
|
|
1208
|
+
error
|
|
1209
|
+
});
|
|
1210
|
+
await hooks.emit("kubb:debug", {
|
|
1211
|
+
date: errorTimestamp,
|
|
1212
|
+
logs: [
|
|
1213
|
+
"✗ Plugin start failed",
|
|
1214
|
+
` • Plugin Name: ${plugin.name}`,
|
|
1215
|
+
` • Error: ${error.constructor.name} - ${error.message}`,
|
|
1216
|
+
" • Stack Trace:",
|
|
1217
|
+
error.stack || "No stack trace available"
|
|
1218
|
+
]
|
|
1219
|
+
});
|
|
1220
|
+
failedPlugins.add({
|
|
1221
|
+
plugin,
|
|
1222
|
+
error
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
if (config.output.barrelType) {
|
|
1227
|
+
const rootPath = (0, node_path.resolve)((0, node_path.resolve)(config.root), config.output.path, require_PluginDriver.BARREL_FILENAME);
|
|
1228
|
+
const rootDir = (0, node_path.dirname)(rootPath);
|
|
1229
|
+
await hooks.emit("kubb:debug", {
|
|
1230
|
+
date: /* @__PURE__ */ new Date(),
|
|
1231
|
+
logs: [
|
|
1232
|
+
"Generating barrel file",
|
|
1233
|
+
` • Type: ${config.output.barrelType}`,
|
|
1234
|
+
` • Path: ${rootPath}`
|
|
1235
|
+
]
|
|
1236
|
+
});
|
|
1237
|
+
const barrelFiles = driver.fileManager.files.filter((file) => {
|
|
1238
|
+
return file.sources.some((source) => source.isIndexable);
|
|
1239
|
+
});
|
|
1240
|
+
await hooks.emit("kubb:debug", {
|
|
1241
|
+
date: /* @__PURE__ */ new Date(),
|
|
1242
|
+
logs: [`Found ${barrelFiles.length} indexable files for barrel export`]
|
|
1243
|
+
});
|
|
1244
|
+
const existingBarrel = driver.fileManager.files.find((f) => f.path === rootPath);
|
|
1245
|
+
const rootFile = (0, _kubb_ast.createFile)({
|
|
1246
|
+
path: rootPath,
|
|
1247
|
+
baseName: require_PluginDriver.BARREL_FILENAME,
|
|
1248
|
+
exports: buildBarrelExports({
|
|
1249
|
+
barrelFiles,
|
|
1250
|
+
rootDir,
|
|
1251
|
+
existingExports: new Set(existingBarrel?.exports?.flatMap((e) => Array.isArray(e.name) ? e.name : [e.name]).filter((n) => Boolean(n)) ?? []),
|
|
1252
|
+
config,
|
|
1253
|
+
driver
|
|
1254
|
+
}).map((e) => (0, _kubb_ast.createExport)(e)),
|
|
1255
|
+
sources: [],
|
|
1256
|
+
imports: [],
|
|
1257
|
+
meta: {}
|
|
1258
|
+
});
|
|
1259
|
+
driver.fileManager.upsert(rootFile);
|
|
1260
|
+
await hooks.emit("kubb:debug", {
|
|
1261
|
+
date: /* @__PURE__ */ new Date(),
|
|
1262
|
+
logs: [`✓ Generated barrel file (${rootFile.exports?.length || 0} exports)`]
|
|
1263
|
+
});
|
|
1264
|
+
}
|
|
1265
|
+
const files = driver.fileManager.files;
|
|
1266
|
+
const parsersMap = /* @__PURE__ */ new Map();
|
|
1267
|
+
for (const parser of config.parsers) if (parser.extNames) for (const extname of parser.extNames) parsersMap.set(extname, parser);
|
|
1268
|
+
const fileProcessor = new FileProcessor();
|
|
1269
|
+
await hooks.emit("kubb:debug", {
|
|
1270
|
+
date: /* @__PURE__ */ new Date(),
|
|
1271
|
+
logs: [`Writing ${files.length} files...`]
|
|
1272
|
+
});
|
|
1273
|
+
await fileProcessor.run(files, {
|
|
1274
|
+
parsers: parsersMap,
|
|
1275
|
+
extension: config.output.extension,
|
|
1276
|
+
onStart: async (processingFiles) => {
|
|
1277
|
+
await hooks.emit("kubb:files:processing:start", processingFiles);
|
|
1278
|
+
},
|
|
1279
|
+
onUpdate: async ({ file, source, processed, total, percentage }) => {
|
|
1280
|
+
await hooks.emit("kubb:file:processing:update", {
|
|
1281
|
+
file,
|
|
1282
|
+
source,
|
|
1283
|
+
processed,
|
|
1284
|
+
total,
|
|
1285
|
+
percentage,
|
|
1286
|
+
config
|
|
1287
|
+
});
|
|
1288
|
+
if (source) {
|
|
1289
|
+
await storage?.setItem(file.path, source);
|
|
1290
|
+
sources.set(file.path, source);
|
|
1291
|
+
}
|
|
1292
|
+
},
|
|
1293
|
+
onEnd: async (processedFiles) => {
|
|
1294
|
+
await hooks.emit("kubb:files:processing:end", processedFiles);
|
|
1295
|
+
await hooks.emit("kubb:debug", {
|
|
1296
|
+
date: /* @__PURE__ */ new Date(),
|
|
1297
|
+
logs: [`✓ File write process completed for ${processedFiles.length} files`]
|
|
1298
|
+
});
|
|
1299
|
+
}
|
|
1300
|
+
});
|
|
1301
|
+
await hooks.emit("kubb:build:end", {
|
|
1302
|
+
files,
|
|
1303
|
+
config,
|
|
1304
|
+
outputDir: (0, node_path.resolve)(config.root, config.output.path)
|
|
1305
|
+
});
|
|
1306
|
+
return {
|
|
1307
|
+
failedPlugins,
|
|
1308
|
+
files,
|
|
1309
|
+
driver,
|
|
1310
|
+
pluginTimings,
|
|
1311
|
+
sources
|
|
1312
|
+
};
|
|
1313
|
+
} catch (error) {
|
|
1314
|
+
return {
|
|
1315
|
+
failedPlugins,
|
|
1316
|
+
files: [],
|
|
1317
|
+
driver,
|
|
1318
|
+
pluginTimings,
|
|
1319
|
+
error,
|
|
1320
|
+
sources
|
|
1321
|
+
};
|
|
1322
|
+
} finally {
|
|
1323
|
+
driver.dispose();
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
async function build(setupResult) {
|
|
1327
|
+
const { files, driver, failedPlugins, pluginTimings, error, sources } = await safeBuild(setupResult);
|
|
1328
|
+
if (error) throw error;
|
|
1329
|
+
if (failedPlugins.size > 0) {
|
|
1330
|
+
const errors = [...failedPlugins].map(({ error }) => error);
|
|
1331
|
+
throw new BuildError(`Build Error with ${failedPlugins.size} failed plugins`, { errors });
|
|
2333
1332
|
}
|
|
1333
|
+
return {
|
|
1334
|
+
failedPlugins,
|
|
1335
|
+
files,
|
|
1336
|
+
driver,
|
|
1337
|
+
pluginTimings,
|
|
1338
|
+
error: void 0,
|
|
1339
|
+
sources
|
|
1340
|
+
};
|
|
2334
1341
|
}
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
1342
|
+
function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }) {
|
|
1343
|
+
const pluginNameMap = /* @__PURE__ */ new Map();
|
|
1344
|
+
for (const plugin of driver.plugins.values()) pluginNameMap.set(plugin.name, plugin);
|
|
1345
|
+
return barrelFiles.flatMap((file) => {
|
|
1346
|
+
const containsOnlyTypes = file.sources?.every((source) => source.isTypeOnly);
|
|
1347
|
+
return (file.sources ?? []).flatMap((source) => {
|
|
1348
|
+
if (!file.path || !source.isIndexable) return [];
|
|
1349
|
+
const meta = file.meta;
|
|
1350
|
+
const pluginOptions = (meta?.pluginName ? pluginNameMap.get(meta.pluginName) : void 0)?.options;
|
|
1351
|
+
if (!pluginOptions || pluginOptions.output?.barrelType === false) return [];
|
|
1352
|
+
const exportName = config.output.barrelType === "all" ? void 0 : source.name ? [source.name] : void 0;
|
|
1353
|
+
if (exportName?.some((n) => existingExports.has(n))) return [];
|
|
1354
|
+
return [(0, _kubb_ast.createExport)({
|
|
1355
|
+
name: exportName,
|
|
1356
|
+
path: getRelativePath(rootDir, file.path),
|
|
1357
|
+
isTypeOnly: config.output.barrelType === "all" ? containsOnlyTypes : source.isTypeOnly
|
|
1358
|
+
})];
|
|
1359
|
+
});
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
function inputToAdapterSource(config) {
|
|
1363
|
+
if (Array.isArray(config.input)) return {
|
|
1364
|
+
type: "paths",
|
|
1365
|
+
paths: config.input.map((i) => new URLPath(i.path).isURL ? i.path : (0, node_path.resolve)(config.root, i.path))
|
|
1366
|
+
};
|
|
1367
|
+
if ("data" in config.input) return {
|
|
1368
|
+
type: "data",
|
|
1369
|
+
data: config.input.data
|
|
1370
|
+
};
|
|
1371
|
+
if (new URLPath(config.input.path).isURL) return {
|
|
1372
|
+
type: "path",
|
|
1373
|
+
path: config.input.path
|
|
1374
|
+
};
|
|
1375
|
+
return {
|
|
1376
|
+
type: "path",
|
|
1377
|
+
path: (0, node_path.resolve)(config.root, config.input.path)
|
|
1378
|
+
};
|
|
1379
|
+
}
|
|
1380
|
+
/**
|
|
1381
|
+
* Creates a Kubb instance bound to a single config entry.
|
|
1382
|
+
*
|
|
1383
|
+
* Accepts a user-facing config shape and resolves it to a full {@link Config} during
|
|
1384
|
+
* `setup()`. The instance then holds shared state (`hooks`, `sources`, `driver`, `config`)
|
|
1385
|
+
* across the `setup → build` lifecycle. Attach event listeners to `kubb.hooks` before
|
|
1386
|
+
* calling `setup()` or `build()`.
|
|
1387
|
+
*
|
|
1388
|
+
* @example
|
|
1389
|
+
* ```ts
|
|
1390
|
+
* const kubb = createKubb(userConfig)
|
|
1391
|
+
*
|
|
1392
|
+
* kubb.hooks.on('kubb:plugin:end', (plugin, { duration }) => {
|
|
1393
|
+
* console.log(`${plugin.name} completed in ${duration}ms`)
|
|
1394
|
+
* })
|
|
1395
|
+
*
|
|
1396
|
+
* const { files, failedPlugins } = await kubb.safeBuild()
|
|
1397
|
+
* ```
|
|
1398
|
+
*/
|
|
1399
|
+
function createKubb(userConfig, options = {}) {
|
|
1400
|
+
const hooks = options.hooks ?? new AsyncEventEmitter();
|
|
1401
|
+
let setupResult;
|
|
1402
|
+
const instance = {
|
|
1403
|
+
get hooks() {
|
|
1404
|
+
return hooks;
|
|
1405
|
+
},
|
|
1406
|
+
get sources() {
|
|
1407
|
+
return setupResult?.sources ?? /* @__PURE__ */ new Map();
|
|
1408
|
+
},
|
|
1409
|
+
get driver() {
|
|
1410
|
+
return setupResult?.driver;
|
|
1411
|
+
},
|
|
1412
|
+
get config() {
|
|
1413
|
+
return setupResult?.config;
|
|
1414
|
+
},
|
|
1415
|
+
async setup() {
|
|
1416
|
+
setupResult = await setup(userConfig, { hooks });
|
|
1417
|
+
},
|
|
1418
|
+
async build() {
|
|
1419
|
+
if (!setupResult) await instance.setup();
|
|
1420
|
+
return build(setupResult);
|
|
1421
|
+
},
|
|
1422
|
+
async safeBuild() {
|
|
1423
|
+
if (!setupResult) await instance.setup();
|
|
1424
|
+
return safeBuild(setupResult);
|
|
1425
|
+
}
|
|
1426
|
+
};
|
|
1427
|
+
return instance;
|
|
2341
1428
|
}
|
|
2342
1429
|
//#endregion
|
|
2343
|
-
//#region src/
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
1430
|
+
//#region src/createRenderer.ts
|
|
1431
|
+
/**
|
|
1432
|
+
* Creates a renderer factory for use in generator definitions.
|
|
1433
|
+
*
|
|
1434
|
+
* Wrap your renderer factory function with this helper to register it as the
|
|
1435
|
+
* renderer for a generator. Core will call this factory once per render cycle
|
|
1436
|
+
* to obtain a fresh renderer instance.
|
|
1437
|
+
*
|
|
1438
|
+
* @example
|
|
1439
|
+
* ```ts
|
|
1440
|
+
* // packages/renderer-jsx/src/index.ts
|
|
1441
|
+
* export const jsxRenderer = createRenderer(() => {
|
|
1442
|
+
* const runtime = new Runtime()
|
|
1443
|
+
* return {
|
|
1444
|
+
* async render(element) { await runtime.render(element) },
|
|
1445
|
+
* get files() { return runtime.nodes },
|
|
1446
|
+
* unmount(error) { runtime.unmount(error) },
|
|
1447
|
+
* }
|
|
1448
|
+
* })
|
|
1449
|
+
*
|
|
1450
|
+
* // packages/plugin-zod/src/generators/zodGenerator.tsx
|
|
1451
|
+
* import { jsxRenderer } from '@kubb/renderer-jsx'
|
|
1452
|
+
* export const zodGenerator = defineGenerator<PluginZod>({
|
|
1453
|
+
* name: 'zod',
|
|
1454
|
+
* renderer: jsxRenderer,
|
|
1455
|
+
* schema(node, options) { return <File ...>...</File> },
|
|
1456
|
+
* })
|
|
1457
|
+
* ```
|
|
1458
|
+
*/
|
|
1459
|
+
function createRenderer(factory) {
|
|
1460
|
+
return factory;
|
|
2352
1461
|
}
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
1462
|
+
//#endregion
|
|
1463
|
+
//#region src/defineGenerator.ts
|
|
1464
|
+
/**
|
|
1465
|
+
* Defines a generator. Returns the object as-is with correct `this` typings.
|
|
1466
|
+
* `applyHookResult` handles renderer elements and `File[]` uniformly using
|
|
1467
|
+
* the generator's declared `renderer` factory.
|
|
1468
|
+
*/
|
|
1469
|
+
function defineGenerator(generator) {
|
|
1470
|
+
return generator;
|
|
2358
1471
|
}
|
|
1472
|
+
//#endregion
|
|
1473
|
+
//#region src/defineLogger.ts
|
|
2359
1474
|
/**
|
|
2360
|
-
*
|
|
2361
|
-
* `exclude`, `include`, and `override` rules from the plugin configuration.
|
|
1475
|
+
* Wraps a logger definition into a typed {@link Logger}.
|
|
2362
1476
|
*
|
|
2363
|
-
*
|
|
2364
|
-
*
|
|
1477
|
+
* @example
|
|
1478
|
+
* export const myLogger = defineLogger({
|
|
1479
|
+
* name: 'my-logger',
|
|
1480
|
+
* install(context, options) {
|
|
1481
|
+
* context.on('kubb:info', (message) => console.log('ℹ', message))
|
|
1482
|
+
* context.on('kubb:error', (error) => console.error('✗', error.message))
|
|
1483
|
+
* },
|
|
1484
|
+
* })
|
|
1485
|
+
*/
|
|
1486
|
+
function defineLogger(logger) {
|
|
1487
|
+
return logger;
|
|
1488
|
+
}
|
|
1489
|
+
//#endregion
|
|
1490
|
+
//#region src/defineParser.ts
|
|
1491
|
+
/**
|
|
1492
|
+
* Defines a parser with type safety.
|
|
2365
1493
|
*
|
|
2366
|
-
*
|
|
2367
|
-
*
|
|
1494
|
+
* Use this function to create parsers that transform generated files to strings
|
|
1495
|
+
* based on their extension.
|
|
2368
1496
|
*
|
|
2369
1497
|
* @example
|
|
2370
|
-
*
|
|
2371
|
-
*
|
|
1498
|
+
* ```ts
|
|
1499
|
+
* import { defineParser } from '@kubb/core'
|
|
1500
|
+
*
|
|
1501
|
+
* export const jsonParser = defineParser({
|
|
1502
|
+
* name: 'json',
|
|
1503
|
+
* extNames: ['.json'],
|
|
1504
|
+
* parse(file) {
|
|
1505
|
+
* const { extractStringsFromNodes } = await import('@kubb/ast')
|
|
1506
|
+
* return file.sources.map((s) => extractStringsFromNodes(s.nodes ?? [])).join('\n')
|
|
1507
|
+
* },
|
|
1508
|
+
* })
|
|
1509
|
+
* ```
|
|
2372
1510
|
*/
|
|
2373
|
-
function
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
1511
|
+
function defineParser(parser) {
|
|
1512
|
+
return parser;
|
|
1513
|
+
}
|
|
1514
|
+
//#endregion
|
|
1515
|
+
//#region src/definePlugin.ts
|
|
1516
|
+
/**
|
|
1517
|
+
* Creates a plugin factory using the hook-style (`hooks:`) API.
|
|
1518
|
+
*
|
|
1519
|
+
* The returned factory is called with optional options and produces a `Plugin`
|
|
1520
|
+
* that coexists with plugins created via the legacy `createPlugin` API in the same
|
|
1521
|
+
* `kubb.config.ts`.
|
|
1522
|
+
*
|
|
1523
|
+
* Lifecycle handlers are registered on the `PluginDriver`'s `AsyncEventEmitter`, enabling
|
|
1524
|
+
* both the plugin's own handlers and external tooling (CLI, devtools) to observe every event.
|
|
1525
|
+
*
|
|
1526
|
+
* @example
|
|
1527
|
+
* ```ts
|
|
1528
|
+
* // With PluginFactoryOptions (recommended for real plugins)
|
|
1529
|
+
* export const pluginTs = definePlugin<PluginTs>((options) => ({
|
|
1530
|
+
* name: 'plugin-ts',
|
|
1531
|
+
* hooks: {
|
|
1532
|
+
* 'kubb:plugin:setup'(ctx) {
|
|
1533
|
+
* ctx.setResolver(resolverTs) // typed as Partial<ResolverTs>
|
|
1534
|
+
* },
|
|
1535
|
+
* },
|
|
1536
|
+
* }))
|
|
1537
|
+
* ```
|
|
1538
|
+
*/
|
|
1539
|
+
function definePlugin(factory) {
|
|
1540
|
+
return (options) => factory(options ?? {});
|
|
2396
1541
|
}
|
|
2397
1542
|
//#endregion
|
|
1543
|
+
//#region src/storages/memoryStorage.ts
|
|
1544
|
+
/**
|
|
1545
|
+
* In-memory storage driver. Useful for testing and dry-run scenarios where
|
|
1546
|
+
* generated output should be captured without touching the filesystem.
|
|
1547
|
+
*
|
|
1548
|
+
* All data lives in a `Map` scoped to the storage instance and is discarded
|
|
1549
|
+
* when the instance is garbage-collected.
|
|
1550
|
+
*
|
|
1551
|
+
* @example
|
|
1552
|
+
* ```ts
|
|
1553
|
+
* import { memoryStorage } from '@kubb/core'
|
|
1554
|
+
* import { defineConfig } from 'kubb'
|
|
1555
|
+
*
|
|
1556
|
+
* export default defineConfig({
|
|
1557
|
+
* input: { path: './petStore.yaml' },
|
|
1558
|
+
* output: { path: './src/gen', storage: memoryStorage() },
|
|
1559
|
+
* })
|
|
1560
|
+
* ```
|
|
1561
|
+
*/
|
|
1562
|
+
const memoryStorage = createStorage(() => {
|
|
1563
|
+
const store = /* @__PURE__ */ new Map();
|
|
1564
|
+
return {
|
|
1565
|
+
name: "memory",
|
|
1566
|
+
async hasItem(key) {
|
|
1567
|
+
return store.has(key);
|
|
1568
|
+
},
|
|
1569
|
+
async getItem(key) {
|
|
1570
|
+
return store.get(key) ?? null;
|
|
1571
|
+
},
|
|
1572
|
+
async setItem(key, value) {
|
|
1573
|
+
store.set(key, value);
|
|
1574
|
+
},
|
|
1575
|
+
async removeItem(key) {
|
|
1576
|
+
store.delete(key);
|
|
1577
|
+
},
|
|
1578
|
+
async getKeys(base) {
|
|
1579
|
+
const keys = [...store.keys()];
|
|
1580
|
+
return base ? keys.filter((k) => k.startsWith(base)) : keys;
|
|
1581
|
+
},
|
|
1582
|
+
async clear(base) {
|
|
1583
|
+
if (!base) {
|
|
1584
|
+
store.clear();
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
for (const key of store.keys()) if (key.startsWith(base)) store.delete(key);
|
|
1588
|
+
}
|
|
1589
|
+
};
|
|
1590
|
+
});
|
|
1591
|
+
//#endregion
|
|
2398
1592
|
exports.AsyncEventEmitter = AsyncEventEmitter;
|
|
2399
|
-
exports.
|
|
2400
|
-
exports.
|
|
2401
|
-
exports.
|
|
2402
|
-
exports.PromiseManager = PromiseManager;
|
|
1593
|
+
exports.FileManager = require_PluginDriver.FileManager;
|
|
1594
|
+
exports.FileProcessor = FileProcessor;
|
|
1595
|
+
exports.PluginDriver = require_PluginDriver.PluginDriver;
|
|
2403
1596
|
exports.URLPath = URLPath;
|
|
2404
|
-
exports
|
|
2405
|
-
exports.default = build;
|
|
2406
|
-
exports.defineAdapter = defineAdapter;
|
|
2407
|
-
exports.defineConfig = defineConfig;
|
|
2408
|
-
exports.defineGenerator = defineGenerator;
|
|
2409
|
-
exports.defineLogger = defineLogger;
|
|
2410
|
-
exports.definePlugin = definePlugin;
|
|
2411
|
-
Object.defineProperty(exports, "definePrinter", {
|
|
1597
|
+
Object.defineProperty(exports, "ast", {
|
|
2412
1598
|
enumerable: true,
|
|
2413
1599
|
get: function() {
|
|
2414
|
-
return _kubb_ast
|
|
1600
|
+
return _kubb_ast;
|
|
2415
1601
|
}
|
|
2416
1602
|
});
|
|
2417
|
-
exports.
|
|
2418
|
-
exports.
|
|
2419
|
-
exports.
|
|
2420
|
-
exports.
|
|
1603
|
+
exports.createAdapter = createAdapter;
|
|
1604
|
+
exports.createKubb = createKubb;
|
|
1605
|
+
exports.createRenderer = createRenderer;
|
|
1606
|
+
exports.createStorage = createStorage;
|
|
1607
|
+
exports.defineGenerator = defineGenerator;
|
|
1608
|
+
exports.defineLogger = defineLogger;
|
|
1609
|
+
exports.defineParser = defineParser;
|
|
1610
|
+
exports.definePlugin = definePlugin;
|
|
1611
|
+
exports.defineResolver = require_PluginDriver.defineResolver;
|
|
2421
1612
|
exports.fsStorage = fsStorage;
|
|
2422
|
-
exports.getBarrelFiles = getBarrelFiles;
|
|
2423
|
-
exports.getConfigs = getConfigs;
|
|
2424
|
-
exports.getMode = getMode;
|
|
2425
1613
|
exports.isInputPath = isInputPath;
|
|
2426
|
-
exports.
|
|
2427
|
-
exports.logLevel = logLevel;
|
|
1614
|
+
exports.logLevel = require_PluginDriver.logLevel;
|
|
2428
1615
|
exports.memoryStorage = memoryStorage;
|
|
2429
|
-
exports.resolveOptions = resolveOptions;
|
|
2430
|
-
exports.safeBuild = safeBuild;
|
|
2431
|
-
exports.setup = setup;
|
|
2432
1616
|
|
|
2433
1617
|
//# sourceMappingURL=index.cjs.map
|