@kubb/core 5.0.0-beta.84 → 5.0.0-beta.85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{diagnostics-DuaXn2bT.d.ts → Diagnostics-PnPLU3kj.d.ts} +314 -402
- package/dist/index.cjs +729 -973
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -93
- package/dist/index.js +690 -934
- package/dist/index.js.map +1 -1
- package/dist/mocks.cjs +7 -14
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.ts +1 -1
- package/dist/mocks.js +3 -10
- package/dist/mocks.js.map +1 -1
- package/dist/{memoryStorage-BjUIqpYE.js → usingCtx-BABTfo1g.js} +160 -480
- package/dist/usingCtx-BABTfo1g.js.map +1 -0
- package/dist/{memoryStorage-DQ6qXJ8o.cjs → usingCtx-fxRpJw0P.cjs} +159 -521
- package/dist/usingCtx-fxRpJw0P.cjs.map +1 -0
- package/package.json +2 -2
- package/dist/memoryStorage-BjUIqpYE.js.map +0 -1
- package/dist/memoryStorage-DQ6qXJ8o.cjs.map +0 -1
|
@@ -24,10 +24,37 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
enumerable: true
|
|
25
25
|
}) : target, mod));
|
|
26
26
|
//#endregion
|
|
27
|
-
let node_events = require("node:events");
|
|
28
27
|
let node_fs_promises = require("node:fs/promises");
|
|
29
28
|
let node_path = require("node:path");
|
|
30
29
|
let _kubb_ast = require("@kubb/ast");
|
|
30
|
+
let node_events = require("node:events");
|
|
31
|
+
//#region ../../internals/utils/src/casing.ts
|
|
32
|
+
/**
|
|
33
|
+
* Shared implementation for camelCase and PascalCase conversion.
|
|
34
|
+
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
35
|
+
* and capitalizes each word according to `pascal`.
|
|
36
|
+
*
|
|
37
|
+
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
38
|
+
*/
|
|
39
|
+
function toCamelOrPascal(text, pascal) {
|
|
40
|
+
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) => {
|
|
41
|
+
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
42
|
+
return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
|
|
43
|
+
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Converts `text` to camelCase.
|
|
47
|
+
*
|
|
48
|
+
* @example Word boundaries
|
|
49
|
+
* `camelCase('hello-world') // 'helloWorld'`
|
|
50
|
+
*
|
|
51
|
+
* @example With a prefix
|
|
52
|
+
* `camelCase('tag', { prefix: 'create' }) // 'createTag'`
|
|
53
|
+
*/
|
|
54
|
+
function camelCase(text, { prefix = "", suffix = "" } = {}) {
|
|
55
|
+
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
31
58
|
//#region ../../internals/utils/src/errors.ts
|
|
32
59
|
/**
|
|
33
60
|
* Thrown when one or more errors occur during a Kubb build.
|
|
@@ -73,152 +100,6 @@ function getErrorMessage(value) {
|
|
|
73
100
|
return value instanceof Error ? value.message : String(value);
|
|
74
101
|
}
|
|
75
102
|
//#endregion
|
|
76
|
-
//#region ../../internals/utils/src/asyncEventEmitter.ts
|
|
77
|
-
/**
|
|
78
|
-
* Typed `EventEmitter` that awaits all async listeners before resolving.
|
|
79
|
-
* Wraps Node's `EventEmitter` with full TypeScript event-map inference.
|
|
80
|
-
*
|
|
81
|
-
* @example
|
|
82
|
-
* ```ts
|
|
83
|
-
* const emitter = new AsyncEventEmitter<{ build: [name: string] }>()
|
|
84
|
-
* emitter.on('build', async (name) => { console.log(name) })
|
|
85
|
-
* await emitter.emit('build', 'petstore') // all listeners awaited
|
|
86
|
-
* ```
|
|
87
|
-
*/
|
|
88
|
-
var AsyncEventEmitter = class {
|
|
89
|
-
/**
|
|
90
|
-
* Maximum number of listeners per event before Node emits a memory-leak warning.
|
|
91
|
-
* @default 10
|
|
92
|
-
*/
|
|
93
|
-
constructor(maxListener = 10) {
|
|
94
|
-
this.#emitter.setMaxListeners(maxListener);
|
|
95
|
-
}
|
|
96
|
-
#emitter = new node_events.EventEmitter();
|
|
97
|
-
/**
|
|
98
|
-
* Emits `eventName` and awaits all registered listeners sequentially.
|
|
99
|
-
* Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
|
|
100
|
-
*
|
|
101
|
-
* @example
|
|
102
|
-
* ```ts
|
|
103
|
-
* await emitter.emit('build', 'petstore')
|
|
104
|
-
* ```
|
|
105
|
-
*/
|
|
106
|
-
emit(eventName, ...eventArgs) {
|
|
107
|
-
const listeners = this.#emitter.listeners(eventName);
|
|
108
|
-
if (listeners.length === 0) return;
|
|
109
|
-
return this.#emitAll(eventName, listeners, eventArgs);
|
|
110
|
-
}
|
|
111
|
-
async #emitAll(eventName, listeners, eventArgs) {
|
|
112
|
-
for (const listener of listeners) try {
|
|
113
|
-
await listener(...eventArgs);
|
|
114
|
-
} catch (err) {
|
|
115
|
-
let serializedArgs;
|
|
116
|
-
try {
|
|
117
|
-
serializedArgs = JSON.stringify(eventArgs);
|
|
118
|
-
} catch {
|
|
119
|
-
serializedArgs = String(eventArgs);
|
|
120
|
-
}
|
|
121
|
-
throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Registers a persistent listener for `eventName`.
|
|
126
|
-
*
|
|
127
|
-
* @example
|
|
128
|
-
* ```ts
|
|
129
|
-
* emitter.on('build', async (name) => { console.log(name) })
|
|
130
|
-
* ```
|
|
131
|
-
*/
|
|
132
|
-
on(eventName, handler) {
|
|
133
|
-
this.#emitter.on(eventName, handler);
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Removes a previously registered listener.
|
|
137
|
-
*
|
|
138
|
-
* @example
|
|
139
|
-
* ```ts
|
|
140
|
-
* emitter.off('build', handler)
|
|
141
|
-
* ```
|
|
142
|
-
*/
|
|
143
|
-
off(eventName, handler) {
|
|
144
|
-
this.#emitter.off(eventName, handler);
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Returns the number of listeners registered for `eventName`.
|
|
148
|
-
*
|
|
149
|
-
* @example
|
|
150
|
-
* ```ts
|
|
151
|
-
* emitter.on('build', handler)
|
|
152
|
-
* emitter.listenerCount('build') // 1
|
|
153
|
-
* ```
|
|
154
|
-
*/
|
|
155
|
-
listenerCount(eventName) {
|
|
156
|
-
return this.#emitter.listenerCount(eventName);
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Raises or lowers the per-event listener ceiling before Node warns about a memory leak.
|
|
160
|
-
* Set this above the expected listener count when many listeners attach by design.
|
|
161
|
-
*
|
|
162
|
-
* @example
|
|
163
|
-
* ```ts
|
|
164
|
-
* emitter.setMaxListeners(40)
|
|
165
|
-
* ```
|
|
166
|
-
*/
|
|
167
|
-
setMaxListeners(max) {
|
|
168
|
-
this.#emitter.setMaxListeners(max);
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Removes all listeners from every event channel.
|
|
172
|
-
*
|
|
173
|
-
* @example
|
|
174
|
-
* ```ts
|
|
175
|
-
* emitter.removeAll()
|
|
176
|
-
* ```
|
|
177
|
-
*/
|
|
178
|
-
removeAll() {
|
|
179
|
-
this.#emitter.removeAllListeners();
|
|
180
|
-
}
|
|
181
|
-
};
|
|
182
|
-
//#endregion
|
|
183
|
-
//#region ../../internals/utils/src/casing.ts
|
|
184
|
-
/**
|
|
185
|
-
* Shared implementation for camelCase and PascalCase conversion.
|
|
186
|
-
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
187
|
-
* and capitalizes each word according to `pascal`.
|
|
188
|
-
*
|
|
189
|
-
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
190
|
-
*/
|
|
191
|
-
function toCamelOrPascal(text, pascal) {
|
|
192
|
-
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) => {
|
|
193
|
-
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
194
|
-
return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
|
|
195
|
-
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Converts `text` to camelCase.
|
|
199
|
-
*
|
|
200
|
-
* @example Word boundaries
|
|
201
|
-
* `camelCase('hello-world') // 'helloWorld'`
|
|
202
|
-
*
|
|
203
|
-
* @example With a prefix
|
|
204
|
-
* `camelCase('tag', { prefix: 'create' }) // 'createTag'`
|
|
205
|
-
*/
|
|
206
|
-
function camelCase(text, { prefix = "", suffix = "" } = {}) {
|
|
207
|
-
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Converts `text` to PascalCase.
|
|
211
|
-
*
|
|
212
|
-
* @example Word boundaries
|
|
213
|
-
* `pascalCase('hello-world') // 'HelloWorld'`
|
|
214
|
-
*
|
|
215
|
-
* @example With a suffix
|
|
216
|
-
* `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`
|
|
217
|
-
*/
|
|
218
|
-
function pascalCase(text, { prefix = "", suffix = "" } = {}) {
|
|
219
|
-
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
220
|
-
}
|
|
221
|
-
//#endregion
|
|
222
103
|
//#region ../../internals/utils/src/runtime.ts
|
|
223
104
|
/**
|
|
224
105
|
* Detects the JavaScript runtime executing the current process and exposes its name and version.
|
|
@@ -393,151 +274,130 @@ function toFilePath(name, caseLast = camelCase) {
|
|
|
393
274
|
return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
|
|
394
275
|
}
|
|
395
276
|
//#endregion
|
|
396
|
-
//#region src/
|
|
277
|
+
//#region src/asyncEventEmitter.ts
|
|
397
278
|
/**
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
"contentType"
|
|
408
|
-
]);
|
|
409
|
-
/**
|
|
410
|
-
* Stable codes Kubb attaches to a `Diagnostic`. Each maps to a known failure mode
|
|
411
|
-
* and stays stable so it can be referenced in tooling and (later) docs. Reference
|
|
412
|
-
* these instead of inlining the string at a throw site.
|
|
279
|
+
* Typed `EventEmitter` that awaits all async listeners before resolving.
|
|
280
|
+
* Wraps Node's `EventEmitter` with full TypeScript event-map inference.
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* ```ts
|
|
284
|
+
* const emitter = new AsyncEventEmitter<{ build: [name: string] }>()
|
|
285
|
+
* emitter.on('build', async (name) => { console.log(name) })
|
|
286
|
+
* await emitter.emit('build', 'petstore') // all listeners awaited
|
|
287
|
+
* ```
|
|
413
288
|
*/
|
|
414
|
-
|
|
415
|
-
/**
|
|
416
|
-
* Fallback for an unstructured error with no specific code.
|
|
417
|
-
*/
|
|
418
|
-
unknown: "KUBB_UNKNOWN",
|
|
419
|
-
/**
|
|
420
|
-
* The `input.path` file or URL could not be read.
|
|
421
|
-
*/
|
|
422
|
-
inputNotFound: "KUBB_INPUT_NOT_FOUND",
|
|
423
|
-
/**
|
|
424
|
-
* An adapter was configured without an `input`.
|
|
425
|
-
*/
|
|
426
|
-
inputRequired: "KUBB_INPUT_REQUIRED",
|
|
427
|
-
/**
|
|
428
|
-
* A `$ref` (or equivalent reference) could not be resolved in the source document.
|
|
429
|
-
*/
|
|
430
|
-
refNotFound: "KUBB_REF_NOT_FOUND",
|
|
431
|
-
/**
|
|
432
|
-
* A server variable value is not allowed by its `enum`.
|
|
433
|
-
*/
|
|
434
|
-
invalidServerVariable: "KUBB_INVALID_SERVER_VARIABLE",
|
|
435
|
-
/**
|
|
436
|
-
* A required plugin is missing from the config.
|
|
437
|
-
*/
|
|
438
|
-
pluginNotFound: "KUBB_PLUGIN_NOT_FOUND",
|
|
439
|
-
/**
|
|
440
|
-
* A plugin threw while generating.
|
|
441
|
-
*/
|
|
442
|
-
pluginFailed: "KUBB_PLUGIN_FAILED",
|
|
443
|
-
/**
|
|
444
|
-
* A plugin reported a non-fatal warning through `ctx.warn`.
|
|
445
|
-
*/
|
|
446
|
-
pluginWarning: "KUBB_PLUGIN_WARNING",
|
|
447
|
-
/**
|
|
448
|
-
* A plugin reported an informational message through `ctx.info`.
|
|
449
|
-
*/
|
|
450
|
-
pluginInfo: "KUBB_PLUGIN_INFO",
|
|
451
|
-
/**
|
|
452
|
-
* A schema uses a `format` Kubb does not map to a specific type. Reserved for
|
|
453
|
-
* adapters to emit as a `warning`.
|
|
454
|
-
*/
|
|
455
|
-
unsupportedFormat: "KUBB_UNSUPPORTED_FORMAT",
|
|
456
|
-
/**
|
|
457
|
-
* A referenced schema or operation is marked `deprecated`. Reserved for adapters
|
|
458
|
-
* to emit as an `info`.
|
|
459
|
-
*/
|
|
460
|
-
deprecated: "KUBB_DEPRECATED",
|
|
461
|
-
/**
|
|
462
|
-
* An adapter is required but the config has none. The build cannot read the input
|
|
463
|
-
* without one.
|
|
464
|
-
*/
|
|
465
|
-
adapterRequired: "KUBB_ADAPTER_REQUIRED",
|
|
289
|
+
var AsyncEventEmitter = class {
|
|
466
290
|
/**
|
|
467
|
-
*
|
|
468
|
-
*
|
|
291
|
+
* Maximum number of listeners per event before Node emits a memory-leak warning.
|
|
292
|
+
* @default 10
|
|
469
293
|
*/
|
|
470
|
-
|
|
294
|
+
constructor(maxListener = 10) {
|
|
295
|
+
this.#emitter.setMaxListeners(maxListener);
|
|
296
|
+
}
|
|
297
|
+
#emitter = new node_events.EventEmitter();
|
|
471
298
|
/**
|
|
472
|
-
*
|
|
299
|
+
* Emits `eventName` and awaits all registered listeners sequentially.
|
|
300
|
+
* Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
|
|
301
|
+
*
|
|
302
|
+
* @example
|
|
303
|
+
* ```ts
|
|
304
|
+
* await emitter.emit('build', 'petstore')
|
|
305
|
+
* ```
|
|
473
306
|
*/
|
|
474
|
-
|
|
307
|
+
emit(eventName, ...eventArgs) {
|
|
308
|
+
const listeners = this.#emitter.listeners(eventName);
|
|
309
|
+
if (listeners.length === 0) return;
|
|
310
|
+
return this.#emitAll(eventName, listeners, eventArgs);
|
|
311
|
+
}
|
|
312
|
+
async #emitAll(eventName, listeners, eventArgs) {
|
|
313
|
+
for (const listener of listeners) try {
|
|
314
|
+
await listener(...eventArgs);
|
|
315
|
+
} catch (err) {
|
|
316
|
+
let serializedArgs;
|
|
317
|
+
try {
|
|
318
|
+
serializedArgs = JSON.stringify(eventArgs);
|
|
319
|
+
} catch {
|
|
320
|
+
serializedArgs = String(eventArgs);
|
|
321
|
+
}
|
|
322
|
+
throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
|
|
323
|
+
}
|
|
324
|
+
}
|
|
475
325
|
/**
|
|
476
|
-
*
|
|
326
|
+
* Registers a persistent listener for `eventName`.
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* ```ts
|
|
330
|
+
* emitter.on('build', async (name) => { console.log(name) })
|
|
331
|
+
* ```
|
|
477
332
|
*/
|
|
478
|
-
|
|
333
|
+
on(eventName, handler) {
|
|
334
|
+
this.#emitter.on(eventName, handler);
|
|
335
|
+
}
|
|
479
336
|
/**
|
|
480
|
-
*
|
|
337
|
+
* Removes a previously registered listener.
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* ```ts
|
|
341
|
+
* emitter.off('build', handler)
|
|
342
|
+
* ```
|
|
481
343
|
*/
|
|
482
|
-
|
|
344
|
+
off(eventName, handler) {
|
|
345
|
+
this.#emitter.off(eventName, handler);
|
|
346
|
+
}
|
|
483
347
|
/**
|
|
484
|
-
*
|
|
348
|
+
* Returns the number of listeners registered for `eventName`.
|
|
349
|
+
*
|
|
350
|
+
* @example
|
|
351
|
+
* ```ts
|
|
352
|
+
* emitter.on('build', handler)
|
|
353
|
+
* emitter.listenerCount('build') // 1
|
|
354
|
+
* ```
|
|
485
355
|
*/
|
|
486
|
-
|
|
356
|
+
listenerCount(eventName) {
|
|
357
|
+
return this.#emitter.listenerCount(eventName);
|
|
358
|
+
}
|
|
487
359
|
/**
|
|
488
|
-
*
|
|
360
|
+
* Raises or lowers the per-event listener ceiling before Node warns about a memory leak.
|
|
361
|
+
* Set this above the expected listener count when many listeners attach by design.
|
|
362
|
+
*
|
|
363
|
+
* @example
|
|
364
|
+
* ```ts
|
|
365
|
+
* emitter.setMaxListeners(40)
|
|
366
|
+
* ```
|
|
489
367
|
*/
|
|
490
|
-
|
|
368
|
+
setMaxListeners(max) {
|
|
369
|
+
this.#emitter.setMaxListeners(max);
|
|
370
|
+
}
|
|
491
371
|
/**
|
|
492
|
-
*
|
|
372
|
+
* Removes all listeners from every event channel.
|
|
373
|
+
*
|
|
374
|
+
* @example
|
|
375
|
+
* ```ts
|
|
376
|
+
* emitter.removeAll()
|
|
377
|
+
* ```
|
|
493
378
|
*/
|
|
494
|
-
|
|
379
|
+
removeAll() {
|
|
380
|
+
this.#emitter.removeAllListeners();
|
|
381
|
+
}
|
|
495
382
|
};
|
|
496
383
|
//#endregion
|
|
497
|
-
//#region src/createStorage.ts
|
|
498
|
-
/**
|
|
499
|
-
* Defines a custom storage backend. The builder receives user options and
|
|
500
|
-
* returns a `Storage` implementation. Kubb ships with filesystem and in-memory
|
|
501
|
-
* storages. A custom backend writes generated files elsewhere, such as cloud
|
|
502
|
-
* storage or a database.
|
|
503
|
-
*
|
|
504
|
-
* @example In-memory storage (the built-in implementation)
|
|
505
|
-
* ```ts
|
|
506
|
-
* import { createStorage } from '@kubb/core'
|
|
507
|
-
*
|
|
508
|
-
* export const memoryStorage = createStorage(() => {
|
|
509
|
-
* const store = new Map<string, string>()
|
|
510
|
-
*
|
|
511
|
-
* return {
|
|
512
|
-
* name: 'memory',
|
|
513
|
-
* async hasItem(key) {
|
|
514
|
-
* return store.has(key)
|
|
515
|
-
* },
|
|
516
|
-
* async getItem(key) {
|
|
517
|
-
* return store.get(key) ?? null
|
|
518
|
-
* },
|
|
519
|
-
* async setItem(key, value) {
|
|
520
|
-
* store.set(key, value)
|
|
521
|
-
* },
|
|
522
|
-
* async removeItem(key) {
|
|
523
|
-
* store.delete(key)
|
|
524
|
-
* },
|
|
525
|
-
* async getKeys(base) {
|
|
526
|
-
* const keys = [...store.keys()]
|
|
527
|
-
* return base ? keys.filter((k) => k.startsWith(base)) : keys
|
|
528
|
-
* },
|
|
529
|
-
* async clear(base) {
|
|
530
|
-
* if (!base) store.clear()
|
|
531
|
-
* },
|
|
532
|
-
* }
|
|
533
|
-
* })
|
|
534
|
-
* ```
|
|
535
|
-
*/
|
|
536
|
-
function createStorage(build) {
|
|
537
|
-
return (options) => build(options ?? {});
|
|
538
|
-
}
|
|
539
|
-
//#endregion
|
|
540
384
|
//#region src/FileManager.ts
|
|
385
|
+
function joinSources(file) {
|
|
386
|
+
return file.sources.map((source) => (0, _kubb_ast.extractStringsFromNodes)(source.nodes)).filter(Boolean).join("\n\n");
|
|
387
|
+
}
|
|
388
|
+
async function parseCopy(file) {
|
|
389
|
+
let content;
|
|
390
|
+
try {
|
|
391
|
+
content = await read(file.copy);
|
|
392
|
+
} catch (err) {
|
|
393
|
+
throw new Error(`[kubb] Could not copy file into output: ${file.copy}`, { cause: err });
|
|
394
|
+
}
|
|
395
|
+
return [
|
|
396
|
+
file.banner,
|
|
397
|
+
content,
|
|
398
|
+
file.footer
|
|
399
|
+
].filter((segment) => Boolean(segment)).map((segment) => segment.trimEnd()).join("\n");
|
|
400
|
+
}
|
|
541
401
|
function mergeFile(a, b) {
|
|
542
402
|
return {
|
|
543
403
|
...a,
|
|
@@ -562,22 +422,20 @@ function compareFiles(a, b) {
|
|
|
562
422
|
return 0;
|
|
563
423
|
}
|
|
564
424
|
/**
|
|
565
|
-
* In-memory file store for generated files
|
|
566
|
-
*
|
|
567
|
-
* path length (barrel `index.ts` last
|
|
425
|
+
* In-memory file store for generated files, and the writer that turns them into source
|
|
426
|
+
* strings on `storage`. Files sharing a `path` are merged (sources/imports/exports
|
|
427
|
+
* concatenated). The `files` getter is sorted by path length (barrel `index.ts` last
|
|
428
|
+
* within a bucket).
|
|
568
429
|
*
|
|
569
430
|
* @example
|
|
570
431
|
* ```ts
|
|
571
432
|
* const manager = new FileManager()
|
|
572
433
|
* manager.upsert(myFile)
|
|
573
434
|
* manager.files // sorted view
|
|
435
|
+
* await manager.write(manager.files, { storage: fsStorage() })
|
|
574
436
|
* ```
|
|
575
437
|
*/
|
|
576
438
|
var FileManager = class {
|
|
577
|
-
/**
|
|
578
|
-
* Subscribe to file-store changes. Listeners on `upsert` see each resolved file as it lands
|
|
579
|
-
* through `add` or `upsert`.
|
|
580
|
-
*/
|
|
581
439
|
hooks = new AsyncEventEmitter();
|
|
582
440
|
#cache = /* @__PURE__ */ new Map();
|
|
583
441
|
#sorted = null;
|
|
@@ -595,7 +453,6 @@ var FileManager = class {
|
|
|
595
453
|
const merged = existing && mergeExisting ? _kubb_ast.ast.factory.createFile(mergeFile(existing, file)) : _kubb_ast.ast.factory.createFile(file);
|
|
596
454
|
this.#cache.set(merged.path, merged);
|
|
597
455
|
resolved.push(merged);
|
|
598
|
-
this.hooks.emit("upsert", merged);
|
|
599
456
|
}
|
|
600
457
|
if (resolved.length > 0) this.#sorted = null;
|
|
601
458
|
return resolved;
|
|
@@ -608,13 +465,6 @@ var FileManager = class {
|
|
|
608
465
|
}
|
|
609
466
|
return [...seen.values()];
|
|
610
467
|
}
|
|
611
|
-
getByPath(path) {
|
|
612
|
-
return this.#cache.get(path) ?? null;
|
|
613
|
-
}
|
|
614
|
-
deleteByPath(path) {
|
|
615
|
-
if (!this.#cache.delete(path)) return;
|
|
616
|
-
this.#sorted = null;
|
|
617
|
-
}
|
|
618
468
|
clear() {
|
|
619
469
|
this.#cache.clear();
|
|
620
470
|
this.#sorted = null;
|
|
@@ -627,9 +477,6 @@ var FileManager = class {
|
|
|
627
477
|
this.clear();
|
|
628
478
|
this.hooks.removeAll();
|
|
629
479
|
}
|
|
630
|
-
[Symbol.dispose]() {
|
|
631
|
-
this.dispose();
|
|
632
|
-
}
|
|
633
480
|
/**
|
|
634
481
|
* All stored files in stable sort order (shortest path first, barrel files
|
|
635
482
|
* last within a length bucket). Returns a cached view, do not mutate.
|
|
@@ -637,163 +484,46 @@ var FileManager = class {
|
|
|
637
484
|
get files() {
|
|
638
485
|
return this.#sorted ??= [...this.#cache.values()].sort(compareFiles);
|
|
639
486
|
}
|
|
640
|
-
};
|
|
641
|
-
//#endregion
|
|
642
|
-
//#region src/FileProcessor.ts
|
|
643
|
-
function joinSources(file) {
|
|
644
|
-
const sources = file.sources;
|
|
645
|
-
if (sources.length === 0) return "";
|
|
646
|
-
const parts = [];
|
|
647
|
-
for (const source of sources) {
|
|
648
|
-
const text = (0, _kubb_ast.extractStringsFromNodes)(source.nodes);
|
|
649
|
-
if (text) parts.push(text);
|
|
650
|
-
}
|
|
651
|
-
return parts.join("\n\n");
|
|
652
|
-
}
|
|
653
|
-
async function parseCopy(file) {
|
|
654
|
-
let content;
|
|
655
|
-
try {
|
|
656
|
-
content = await read(file.copy);
|
|
657
|
-
} catch (err) {
|
|
658
|
-
throw new Error(`[kubb] Could not copy file into output: ${file.copy}`, { cause: err });
|
|
659
|
-
}
|
|
660
|
-
return [
|
|
661
|
-
file.banner,
|
|
662
|
-
content,
|
|
663
|
-
file.footer
|
|
664
|
-
].filter((segment) => Boolean(segment)).map((segment) => segment.trimEnd()).join("\n");
|
|
665
|
-
}
|
|
666
|
-
/**
|
|
667
|
-
* Turns `FileNode`s into source strings and writes them to storage.
|
|
668
|
-
*
|
|
669
|
-
* Two modes share the same instance. Stateless mode (`parse`, `stream`, `run`) just runs the
|
|
670
|
-
* conversion. Queue mode (`enqueue`, `flush`, `drain`) buffers files deduped by path and
|
|
671
|
-
* writes each batch through storage with up to `STREAM_FLUSH_EVERY` requests in flight.
|
|
672
|
-
*
|
|
673
|
-
* `flush` does not wait for its batch to finish, so dispatch can overlap with IO. The next
|
|
674
|
-
* `flush` or `drain` picks the in-flight batch up. `drain` blocks until everything has been
|
|
675
|
-
* written and is meant for the end of a build.
|
|
676
|
-
*
|
|
677
|
-
* To surface build-level hook signals (`kubb:files:processing:*` and friends) subscribe to
|
|
678
|
-
* `hooks` and re-emit on the kubb bus.
|
|
679
|
-
*/
|
|
680
|
-
var FileProcessor = class {
|
|
681
|
-
hooks = new AsyncEventEmitter();
|
|
682
|
-
#parsers;
|
|
683
|
-
#storage;
|
|
684
|
-
#extension;
|
|
685
|
-
#pending = /* @__PURE__ */ new Map();
|
|
686
|
-
#runningFlush = null;
|
|
687
|
-
constructor(options) {
|
|
688
|
-
this.#parsers = options.parsers ?? null;
|
|
689
|
-
this.#storage = options.storage;
|
|
690
|
-
this.#extension = options.extension ?? null;
|
|
691
|
-
}
|
|
692
487
|
/**
|
|
693
|
-
*
|
|
488
|
+
* Converts a file's AST sources (or its `copy` source) into the final on-disk string.
|
|
694
489
|
*/
|
|
695
|
-
|
|
696
|
-
return this.#pending.size;
|
|
697
|
-
}
|
|
698
|
-
async parse(file) {
|
|
490
|
+
async parse(file, { parsers, extension } = {}) {
|
|
699
491
|
if (file.copy) return parseCopy(file);
|
|
700
|
-
const
|
|
701
|
-
const parseExtName = this.#extension?.[file.extname] || void 0;
|
|
492
|
+
const parseExtName = extension?.[file.extname] || void 0;
|
|
702
493
|
if (!parsers || !file.extname) return joinSources(file);
|
|
703
494
|
const parser = parsers.get(file.extname);
|
|
704
495
|
if (!parser) return joinSources(file);
|
|
705
496
|
return parser.parse(file, { extname: parseExtName });
|
|
706
497
|
}
|
|
707
|
-
|
|
498
|
+
/**
|
|
499
|
+
* Converts and writes every file at once, letting `storage.setItem` decide how much of
|
|
500
|
+
* that runs concurrently.
|
|
501
|
+
*/
|
|
502
|
+
async write(files, { storage, parsers, extension }) {
|
|
503
|
+
if (files.length === 0) return;
|
|
504
|
+
await this.hooks.emit("start", files);
|
|
708
505
|
const total = files.length;
|
|
709
|
-
if (total === 0) return;
|
|
710
506
|
let processed = 0;
|
|
711
|
-
|
|
712
|
-
const source = await this.parse(file
|
|
507
|
+
await Promise.all(files.map(async (file) => {
|
|
508
|
+
const source = await this.parse(file, {
|
|
509
|
+
parsers,
|
|
510
|
+
extension
|
|
511
|
+
});
|
|
713
512
|
processed++;
|
|
714
|
-
|
|
513
|
+
await this.hooks.emit("update", {
|
|
715
514
|
file,
|
|
716
515
|
source,
|
|
717
516
|
processed,
|
|
718
517
|
total,
|
|
719
518
|
percentage: processed / total * 100
|
|
720
|
-
};
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
async run(files) {
|
|
724
|
-
await this.hooks.emit("start", files);
|
|
725
|
-
for await (const { file, source, processed, total, percentage } of this.stream(files)) await this.hooks.emit("update", {
|
|
726
|
-
file,
|
|
727
|
-
source,
|
|
728
|
-
processed,
|
|
729
|
-
percentage,
|
|
730
|
-
total
|
|
731
|
-
});
|
|
732
|
-
await this.hooks.emit("end", files);
|
|
733
|
-
return files;
|
|
734
|
-
}
|
|
735
|
-
/**
|
|
736
|
-
* Adds a file to the next flush. A later `enqueue` for the same path replaces the previous
|
|
737
|
-
* entry, matching `FileManager.upsert`. Fires the `enqueue` event.
|
|
738
|
-
*/
|
|
739
|
-
enqueue(file) {
|
|
740
|
-
this.#pending.set(file.path, file);
|
|
741
|
-
this.hooks.emit("enqueue", file);
|
|
742
|
-
}
|
|
743
|
-
/**
|
|
744
|
-
* Starts processing the queued files. Waits for any previous flush to finish (so two
|
|
745
|
-
* batches never run together) and then returns without waiting for the new one. The next
|
|
746
|
-
* `flush` or `drain` picks up the in-flight task.
|
|
747
|
-
*/
|
|
748
|
-
async flush() {
|
|
749
|
-
if (this.#runningFlush) await this.#runningFlush;
|
|
750
|
-
if (this.#pending.size === 0) return;
|
|
751
|
-
const batch = [...this.#pending.values()];
|
|
752
|
-
this.#pending.clear();
|
|
753
|
-
this.#runningFlush = this.#processAndWrite(batch).finally(() => {
|
|
754
|
-
this.#runningFlush = null;
|
|
755
|
-
});
|
|
756
|
-
}
|
|
757
|
-
/**
|
|
758
|
-
* Waits for the in-flight flush and writes any files still queued. Fires the `drain` event
|
|
759
|
-
* when both are done.
|
|
760
|
-
*/
|
|
761
|
-
async drain() {
|
|
762
|
-
if (this.#runningFlush) await this.#runningFlush;
|
|
763
|
-
if (this.#pending.size > 0) {
|
|
764
|
-
const batch = [...this.#pending.values()];
|
|
765
|
-
this.#pending.clear();
|
|
766
|
-
await this.#processAndWrite(batch);
|
|
767
|
-
}
|
|
768
|
-
await this.hooks.emit("drain");
|
|
769
|
-
}
|
|
770
|
-
async #processAndWrite(files) {
|
|
771
|
-
const storage = this.#storage;
|
|
772
|
-
await this.hooks.emit("start", files);
|
|
773
|
-
const queue = [];
|
|
774
|
-
for await (const item of this.stream(files)) {
|
|
775
|
-
await this.hooks.emit("update", item);
|
|
776
|
-
if (item.source) {
|
|
777
|
-
queue.push(storage.setItem(item.file.path, item.source));
|
|
778
|
-
if (queue.length >= 50) await Promise.all(queue.splice(0));
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
await Promise.all(queue);
|
|
519
|
+
});
|
|
520
|
+
if (source) await storage.setItem(file.path, source);
|
|
521
|
+
}));
|
|
782
522
|
await this.hooks.emit("end", files);
|
|
783
523
|
}
|
|
784
|
-
/**
|
|
785
|
-
* Clears every listener and the pending queue.
|
|
786
|
-
*/
|
|
787
|
-
dispose() {
|
|
788
|
-
this.hooks.removeAll();
|
|
789
|
-
this.#pending.clear();
|
|
790
|
-
}
|
|
791
|
-
[Symbol.dispose]() {
|
|
792
|
-
this.dispose();
|
|
793
|
-
}
|
|
794
524
|
};
|
|
795
525
|
//#endregion
|
|
796
|
-
//#region \0@oxc-project+runtime@0.
|
|
526
|
+
//#region \0@oxc-project+runtime@0.138.0/helpers/esm/usingCtx.js
|
|
797
527
|
function _usingCtx() {
|
|
798
528
|
var r = "function" == typeof SuppressedError ? SuppressedError : function(r, e) {
|
|
799
529
|
var n = Error();
|
|
@@ -853,56 +583,6 @@ function _usingCtx() {
|
|
|
853
583
|
};
|
|
854
584
|
}
|
|
855
585
|
//#endregion
|
|
856
|
-
//#region src/storages/memoryStorage.ts
|
|
857
|
-
/**
|
|
858
|
-
* In-memory storage driver. Useful for testing and dry-run scenarios where
|
|
859
|
-
* generated output should be captured without touching the filesystem.
|
|
860
|
-
*
|
|
861
|
-
* All data lives in a `Map` scoped to the storage instance and is discarded
|
|
862
|
-
* when the instance is garbage-collected.
|
|
863
|
-
*
|
|
864
|
-
* @example
|
|
865
|
-
* ```ts
|
|
866
|
-
* import { memoryStorage } from '@kubb/core'
|
|
867
|
-
* import { defineConfig } from 'kubb'
|
|
868
|
-
*
|
|
869
|
-
* export default defineConfig({
|
|
870
|
-
* input: { path: './petStore.yaml' },
|
|
871
|
-
* output: { path: './src/gen' },
|
|
872
|
-
* storage: memoryStorage(),
|
|
873
|
-
* })
|
|
874
|
-
* ```
|
|
875
|
-
*/
|
|
876
|
-
const memoryStorage = createStorage(() => {
|
|
877
|
-
const store = /* @__PURE__ */ new Map();
|
|
878
|
-
return {
|
|
879
|
-
name: "memory",
|
|
880
|
-
async hasItem(key) {
|
|
881
|
-
return store.has(key);
|
|
882
|
-
},
|
|
883
|
-
async getItem(key) {
|
|
884
|
-
return store.get(key) ?? null;
|
|
885
|
-
},
|
|
886
|
-
async setItem(key, value) {
|
|
887
|
-
store.set(key, value);
|
|
888
|
-
},
|
|
889
|
-
async removeItem(key) {
|
|
890
|
-
store.delete(key);
|
|
891
|
-
},
|
|
892
|
-
async getKeys(base) {
|
|
893
|
-
const keys = [...store.keys()];
|
|
894
|
-
return base ? keys.filter((k) => k.startsWith(base)) : keys;
|
|
895
|
-
},
|
|
896
|
-
async clear(base) {
|
|
897
|
-
if (!base) {
|
|
898
|
-
store.clear();
|
|
899
|
-
return;
|
|
900
|
-
}
|
|
901
|
-
for (const key of store.keys()) if (key.startsWith(base)) store.delete(key);
|
|
902
|
-
}
|
|
903
|
-
};
|
|
904
|
-
});
|
|
905
|
-
//#endregion
|
|
906
586
|
Object.defineProperty(exports, "AsyncEventEmitter", {
|
|
907
587
|
enumerable: true,
|
|
908
588
|
get: function() {
|
|
@@ -921,18 +601,6 @@ Object.defineProperty(exports, "FileManager", {
|
|
|
921
601
|
return FileManager;
|
|
922
602
|
}
|
|
923
603
|
});
|
|
924
|
-
Object.defineProperty(exports, "FileProcessor", {
|
|
925
|
-
enumerable: true,
|
|
926
|
-
get: function() {
|
|
927
|
-
return FileProcessor;
|
|
928
|
-
}
|
|
929
|
-
});
|
|
930
|
-
Object.defineProperty(exports, "OPERATION_FILTER_TYPES", {
|
|
931
|
-
enumerable: true,
|
|
932
|
-
get: function() {
|
|
933
|
-
return OPERATION_FILTER_TYPES;
|
|
934
|
-
}
|
|
935
|
-
});
|
|
936
604
|
Object.defineProperty(exports, "__name", {
|
|
937
605
|
enumerable: true,
|
|
938
606
|
get: function() {
|
|
@@ -963,42 +631,12 @@ Object.defineProperty(exports, "clean", {
|
|
|
963
631
|
return clean;
|
|
964
632
|
}
|
|
965
633
|
});
|
|
966
|
-
Object.defineProperty(exports, "createStorage", {
|
|
967
|
-
enumerable: true,
|
|
968
|
-
get: function() {
|
|
969
|
-
return createStorage;
|
|
970
|
-
}
|
|
971
|
-
});
|
|
972
|
-
Object.defineProperty(exports, "diagnosticCode", {
|
|
973
|
-
enumerable: true,
|
|
974
|
-
get: function() {
|
|
975
|
-
return diagnosticCode;
|
|
976
|
-
}
|
|
977
|
-
});
|
|
978
634
|
Object.defineProperty(exports, "getErrorMessage", {
|
|
979
635
|
enumerable: true,
|
|
980
636
|
get: function() {
|
|
981
637
|
return getErrorMessage;
|
|
982
638
|
}
|
|
983
639
|
});
|
|
984
|
-
Object.defineProperty(exports, "memoryStorage", {
|
|
985
|
-
enumerable: true,
|
|
986
|
-
get: function() {
|
|
987
|
-
return memoryStorage;
|
|
988
|
-
}
|
|
989
|
-
});
|
|
990
|
-
Object.defineProperty(exports, "pascalCase", {
|
|
991
|
-
enumerable: true,
|
|
992
|
-
get: function() {
|
|
993
|
-
return pascalCase;
|
|
994
|
-
}
|
|
995
|
-
});
|
|
996
|
-
Object.defineProperty(exports, "runtime", {
|
|
997
|
-
enumerable: true,
|
|
998
|
-
get: function() {
|
|
999
|
-
return runtime;
|
|
1000
|
-
}
|
|
1001
|
-
});
|
|
1002
640
|
Object.defineProperty(exports, "toFilePath", {
|
|
1003
641
|
enumerable: true,
|
|
1004
642
|
get: function() {
|
|
@@ -1018,4 +656,4 @@ Object.defineProperty(exports, "write", {
|
|
|
1018
656
|
}
|
|
1019
657
|
});
|
|
1020
658
|
|
|
1021
|
-
//# sourceMappingURL=
|
|
659
|
+
//# sourceMappingURL=usingCtx-fxRpJw0P.cjs.map
|