@kubb/core 5.0.0-beta.41 → 5.0.0-beta.43
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-Ba-FcsPo.d.ts → diagnostics-CuBWjwYc.d.ts} +152 -24
- package/dist/index.cjs +269 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +16 -2
- package/dist/index.js +269 -26
- package/dist/index.js.map +1 -1
- package/dist/{memoryStorage-DZqlEW7H.cjs → memoryStorage-Biujme_q.cjs} +149 -10
- package/dist/memoryStorage-Biujme_q.cjs.map +1 -0
- package/dist/{memoryStorage-DA1bnMte.js → memoryStorage-C0n47hZ2.js} +150 -11
- package/dist/memoryStorage-C0n47hZ2.js.map +1 -0
- package/dist/mocks.cjs +1 -1
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.ts +1 -1
- package/dist/mocks.js +1 -1
- package/dist/mocks.js.map +1 -1
- package/package.json +7 -15
- package/src/Fingerprint.ts +98 -0
- package/src/KubbDriver.ts +68 -8
- package/src/Manifest.ts +85 -0
- package/src/Telemetry.ts +13 -1
- package/src/caches/fsCache.ts +103 -0
- package/src/createCache.ts +74 -0
- package/src/createKubb.ts +33 -4
- package/src/createRenderer.ts +2 -17
- package/src/defineParser.ts +1 -1
- package/src/index.ts +2 -0
- package/src/storages/fsStorage.ts +15 -23
- package/src/types.ts +2 -0
- package/dist/memoryStorage-DA1bnMte.js.map +0 -1
- package/dist/memoryStorage-DZqlEW7H.cjs.map +0 -1
|
@@ -238,6 +238,83 @@ type AdapterBuilder<T extends AdapterFactoryOptions> = (options: T['options']) =
|
|
|
238
238
|
*/
|
|
239
239
|
declare function createAdapter<T extends AdapterFactoryOptions = AdapterFactoryOptions>(build: AdapterBuilder<T>): (options?: T['options']) => Adapter<T>;
|
|
240
240
|
//#endregion
|
|
241
|
+
//#region src/createCache.d.ts
|
|
242
|
+
/**
|
|
243
|
+
* A snapshot of a completed build: the final rendered source of every generated
|
|
244
|
+
* file, keyed by its path relative to the output root. Restoring a snapshot writes
|
|
245
|
+
* those sources straight to storage, skipping generation entirely.
|
|
246
|
+
*
|
|
247
|
+
* Paths are relative, not absolute, so the snapshot never depends on where the
|
|
248
|
+
* project lives on disk.
|
|
249
|
+
*/
|
|
250
|
+
type CachedSnapshot = {
|
|
251
|
+
/**
|
|
252
|
+
* Final source per output file, keyed by the path relative to
|
|
253
|
+
* `resolve(config.root, config.output.path)`.
|
|
254
|
+
*/
|
|
255
|
+
files: Record<string, string>;
|
|
256
|
+
};
|
|
257
|
+
/**
|
|
258
|
+
* Backend that stores build snapshots for incremental ("hot") rebuilds. When the
|
|
259
|
+
* input fingerprint matches a stored key, Kubb restores the snapshot instead of
|
|
260
|
+
* regenerating. Kubb ships with `fsCache` (local disk). Implement this interface to
|
|
261
|
+
* back the cache with any other store.
|
|
262
|
+
*
|
|
263
|
+
* @see {@link createCache} to build a custom backend.
|
|
264
|
+
*/
|
|
265
|
+
type Cache = {
|
|
266
|
+
/**
|
|
267
|
+
* Identifier used in logs and diagnostics (`'fs'`, `'memory'`).
|
|
268
|
+
*/
|
|
269
|
+
readonly name: string;
|
|
270
|
+
/**
|
|
271
|
+
* Returns the snapshot stored under `key`, or `null` on a miss. A backend never
|
|
272
|
+
* throws on a miss or a transient failure. It returns `null` so the build falls
|
|
273
|
+
* through to regeneration.
|
|
274
|
+
*/
|
|
275
|
+
restore(params: {
|
|
276
|
+
key: string;
|
|
277
|
+
}): Promise<CachedSnapshot | null>;
|
|
278
|
+
/**
|
|
279
|
+
* Stores `snapshot` under `key`. Only called after a successful build with no
|
|
280
|
+
* error diagnostics.
|
|
281
|
+
*/
|
|
282
|
+
persist(params: {
|
|
283
|
+
key: string;
|
|
284
|
+
snapshot: CachedSnapshot;
|
|
285
|
+
}): Promise<void>;
|
|
286
|
+
/**
|
|
287
|
+
* Optional teardown called after the build. Use to flush buffers or close
|
|
288
|
+
* connections.
|
|
289
|
+
*/
|
|
290
|
+
dispose?(): Promise<void>;
|
|
291
|
+
};
|
|
292
|
+
/**
|
|
293
|
+
* Defines a custom cache backend. The builder receives user options and returns a
|
|
294
|
+
* {@link Cache}. Reach for this when the filesystem backend doesn't fit, for
|
|
295
|
+
* example to store snapshots in Redis or a database.
|
|
296
|
+
*
|
|
297
|
+
* @example In-memory cache (the built-in implementation)
|
|
298
|
+
* ```ts
|
|
299
|
+
* import { createCache } from '@kubb/core'
|
|
300
|
+
*
|
|
301
|
+
* export const memoryCache = createCache(() => {
|
|
302
|
+
* const store = new Map<string, CachedSnapshot>()
|
|
303
|
+
*
|
|
304
|
+
* return {
|
|
305
|
+
* name: 'memory',
|
|
306
|
+
* async restore({ key }) {
|
|
307
|
+
* return store.get(key) ?? null
|
|
308
|
+
* },
|
|
309
|
+
* async persist({ key, snapshot }) {
|
|
310
|
+
* store.set(key, snapshot)
|
|
311
|
+
* },
|
|
312
|
+
* }
|
|
313
|
+
* })
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
316
|
+
declare function createCache<TOptions = Record<string, never>>(build: (options: TOptions) => Cache): (options?: TOptions) => Cache;
|
|
317
|
+
//#endregion
|
|
241
318
|
//#region src/constants.d.ts
|
|
242
319
|
/**
|
|
243
320
|
* Stable codes Kubb attaches to a `Diagnostic`. Each maps to a known failure mode
|
|
@@ -424,15 +501,6 @@ type Renderer<TElement = unknown> = {
|
|
|
424
501
|
* Called once per render cycle. Must resolve before {@link files} is read.
|
|
425
502
|
*/
|
|
426
503
|
render(element: TElement): Promise<void>;
|
|
427
|
-
/**
|
|
428
|
-
* Tears down the renderer and releases any held resources.
|
|
429
|
-
* Pass an `Error` to signal a failure, a number for an exit code, or omit for a clean shutdown.
|
|
430
|
-
*/
|
|
431
|
-
unmount(error?: Error | number | null): void;
|
|
432
|
-
/**
|
|
433
|
-
* Releases any held resources. `[Symbol.dispose]` delegates here.
|
|
434
|
-
*/
|
|
435
|
-
dispose(): void;
|
|
436
504
|
/**
|
|
437
505
|
* Accumulated {@link FileNode} results produced by the last {@link render} call.
|
|
438
506
|
* Not populated when {@link stream} is implemented.
|
|
@@ -445,7 +513,7 @@ type Renderer<TElement = unknown> = {
|
|
|
445
513
|
stream?(element: TElement): Iterable<FileNode>;
|
|
446
514
|
/**
|
|
447
515
|
* Disposer hook so renderers participate in `using` blocks: `using r = rendererFactory()`
|
|
448
|
-
*
|
|
516
|
+
* runs cleanup on every exit path, including thrown errors.
|
|
449
517
|
*/
|
|
450
518
|
[Symbol.dispose](): void;
|
|
451
519
|
};
|
|
@@ -478,14 +546,8 @@ type RendererFactory<TElement = unknown> = () => Renderer<TElement>;
|
|
|
478
546
|
* get files() {
|
|
479
547
|
* return runtime.files
|
|
480
548
|
* },
|
|
481
|
-
* dispose() {
|
|
482
|
-
* runtime.dispose()
|
|
483
|
-
* },
|
|
484
|
-
* unmount(error) {
|
|
485
|
-
* runtime.dispose(error)
|
|
486
|
-
* },
|
|
487
549
|
* [Symbol.dispose]() {
|
|
488
|
-
*
|
|
550
|
+
* runtime.dispose()
|
|
489
551
|
* },
|
|
490
552
|
* }
|
|
491
553
|
* })
|
|
@@ -493,6 +555,47 @@ type RendererFactory<TElement = unknown> = () => Renderer<TElement>;
|
|
|
493
555
|
*/
|
|
494
556
|
declare function createRenderer<TElement = unknown>(factory: RendererFactory<TElement>): RendererFactory<TElement>;
|
|
495
557
|
//#endregion
|
|
558
|
+
//#region src/caches/fsCache.d.ts
|
|
559
|
+
/**
|
|
560
|
+
* Options for {@link fsCache}.
|
|
561
|
+
*/
|
|
562
|
+
type FsCacheOptions = {
|
|
563
|
+
/**
|
|
564
|
+
* Directory that holds the cache. Resolved against `process.cwd()` when relative.
|
|
565
|
+
*
|
|
566
|
+
* @default 'node_modules/.cache/kubb'
|
|
567
|
+
*/
|
|
568
|
+
dir?: string;
|
|
569
|
+
/**
|
|
570
|
+
* Maximum number of build snapshots to keep. The least-recently-used entries are
|
|
571
|
+
* evicted once the cache grows past it.
|
|
572
|
+
*
|
|
573
|
+
* @default 50
|
|
574
|
+
*/
|
|
575
|
+
maxEntries?: number;
|
|
576
|
+
/**
|
|
577
|
+
* Days a snapshot may go untouched before it is evicted.
|
|
578
|
+
*
|
|
579
|
+
* @default 7
|
|
580
|
+
*/
|
|
581
|
+
ttlDays?: number;
|
|
582
|
+
};
|
|
583
|
+
/**
|
|
584
|
+
* Local filesystem cache. Stores each build snapshot as content blobs plus an index,
|
|
585
|
+
* tracked by a manifest under `node_modules/.cache/kubb/` (the Nx and Vitest
|
|
586
|
+
* convention). Least-recently-used and expired entries are pruned on every persist.
|
|
587
|
+
*
|
|
588
|
+
* @example
|
|
589
|
+
* ```ts
|
|
590
|
+
* import { fsCache } from '@kubb/core'
|
|
591
|
+
*
|
|
592
|
+
* export default defineConfig({
|
|
593
|
+
* cache: fsCache(),
|
|
594
|
+
* })
|
|
595
|
+
* ```
|
|
596
|
+
*/
|
|
597
|
+
declare const fsCache: (options?: FsCacheOptions | undefined) => Cache;
|
|
598
|
+
//#endregion
|
|
496
599
|
//#region src/defineLogger.d.ts
|
|
497
600
|
/**
|
|
498
601
|
* Numeric log-level thresholds used internally to compare verbosity.
|
|
@@ -679,7 +782,7 @@ type Parser<TMeta extends object = object, TNode = unknown> = {
|
|
|
679
782
|
*/
|
|
680
783
|
extNames: Array<FileNode['extname']> | undefined;
|
|
681
784
|
/**
|
|
682
|
-
*
|
|
785
|
+
* Serialize the file's AST into source code.
|
|
683
786
|
*/
|
|
684
787
|
parse(file: FileNode<TMeta>, options?: PrintOptions): string;
|
|
685
788
|
/**
|
|
@@ -1976,6 +2079,26 @@ type Config<TInput = Input> = {
|
|
|
1976
2079
|
* @see {@link Storage} interface for implementing custom backends.
|
|
1977
2080
|
*/
|
|
1978
2081
|
storage: Storage;
|
|
2082
|
+
/**
|
|
2083
|
+
* Incremental build cache. Kubb fingerprints the inputs (spec content, config, plugin options,
|
|
2084
|
+
* versions) and, on an unchanged "hot" run, restores the previously generated output instead of
|
|
2085
|
+
* regenerating it. Same idea as Nx's computation cache.
|
|
2086
|
+
*
|
|
2087
|
+
* `defineConfig` enables `fsCache()` (local disk under `node_modules/.cache/kubb`) by default.
|
|
2088
|
+
* Pass another backend to change where snapshots live, or `false` to turn caching off. A bare
|
|
2089
|
+
* `createKubb` leaves it off unless a cache is provided.
|
|
2090
|
+
*
|
|
2091
|
+
* @example
|
|
2092
|
+
* ```ts
|
|
2093
|
+
* import { fsCache } from '@kubb/core'
|
|
2094
|
+
*
|
|
2095
|
+
* cache: fsCache({ dir: '.kubb-cache' })
|
|
2096
|
+
* cache: false
|
|
2097
|
+
* ```
|
|
2098
|
+
*
|
|
2099
|
+
* @see {@link Cache} interface for implementing custom backends.
|
|
2100
|
+
*/
|
|
2101
|
+
cache?: Cache;
|
|
1979
2102
|
/**
|
|
1980
2103
|
* Plugins that run during the build to generate code and transform the AST. Each one processes
|
|
1981
2104
|
* the adapter's AST and can emit files for a different target (TypeScript, Zod, Faker). A plugin
|
|
@@ -2078,7 +2201,12 @@ type Config<TInput = Input> = {
|
|
|
2078
2201
|
* })
|
|
2079
2202
|
* ```
|
|
2080
2203
|
*/
|
|
2081
|
-
type UserConfig<TInput = Input> = Omit<Config<TInput>, 'root' | 'plugins' | 'parsers' | 'adapter' | 'storage' | 'reporters'> & {
|
|
2204
|
+
type UserConfig<TInput = Input> = Omit<Config<TInput>, 'root' | 'plugins' | 'parsers' | 'adapter' | 'storage' | 'reporters' | 'cache'> & {
|
|
2205
|
+
/**
|
|
2206
|
+
* Incremental build cache. Defaults to `fsCache()` (local disk). Pass another {@link Cache}
|
|
2207
|
+
* backend, or `false` to turn caching off.
|
|
2208
|
+
*/
|
|
2209
|
+
cache?: Cache | false;
|
|
2082
2210
|
/**
|
|
2083
2211
|
* Project root directory, absolute or relative to the config file location.
|
|
2084
2212
|
* @default process.cwd()
|
|
@@ -2383,7 +2511,7 @@ type KubbDiagnosticContext = {
|
|
|
2383
2511
|
};
|
|
2384
2512
|
type KubbFilesProcessingStartContext = {
|
|
2385
2513
|
/**
|
|
2386
|
-
* Files about to be
|
|
2514
|
+
* Files about to be serialized and written.
|
|
2387
2515
|
*/
|
|
2388
2516
|
files: Array<FileNode>;
|
|
2389
2517
|
};
|
|
@@ -2401,7 +2529,7 @@ type KubbFileProcessingUpdate = {
|
|
|
2401
2529
|
*/
|
|
2402
2530
|
percentage: number;
|
|
2403
2531
|
/**
|
|
2404
|
-
*
|
|
2532
|
+
* Serialized file content, or `undefined` when the file produced no output.
|
|
2405
2533
|
*/
|
|
2406
2534
|
source?: string;
|
|
2407
2535
|
/**
|
|
@@ -2421,7 +2549,7 @@ type KubbFilesProcessingUpdateContext = {
|
|
|
2421
2549
|
};
|
|
2422
2550
|
type KubbFilesProcessingEndContext = {
|
|
2423
2551
|
/**
|
|
2424
|
-
* All files that were
|
|
2552
|
+
* All files that were serialized in this batch.
|
|
2425
2553
|
*/
|
|
2426
2554
|
files: Array<FileNode>;
|
|
2427
2555
|
};
|
|
@@ -2966,5 +3094,5 @@ declare class Diagnostics {
|
|
|
2966
3094
|
static formatLines(diagnostic: Diagnostic): Array<string>;
|
|
2967
3095
|
}
|
|
2968
3096
|
//#endregion
|
|
2969
|
-
export { Output as $, KubbHookEndContext as A, defineLogger as At, UserConfig as B,
|
|
2970
|
-
//# sourceMappingURL=diagnostics-
|
|
3097
|
+
export { Output as $, KubbHookEndContext as A, defineLogger as At, UserConfig as B, CachedSnapshot as Bt, KubbErrorContext as C, UserReporter as Ct, KubbFilesProcessingUpdateContext as D, LoggerContext as Dt, KubbFilesProcessingStartContext as E, Logger as Et, KubbLifecycleStartContext as F, RendererFactory as Ft, KubbDriver as G, createAdapter as Gt, Generator$1 as H, Adapter as Ht, KubbPluginsEndContext as I, createRenderer as It, Include as J, Exclude$1 as K, AsyncEventEmitter as Kt, KubbSuccessContext as L, Storage as Lt, KubbHookStartContext as M, FsCacheOptions as Mt, KubbHooks as N, fsCache as Nt, KubbGenerationEndContext as O, LoggerOptions as Ot, KubbInfoContext as P, Renderer as Pt, NormalizedPlugin as Q, KubbWarnContext as R, createStorage as Rt, KubbDiagnosticContext as S, ReporterName as St, KubbFilesProcessingEndContext as T, selectReporters as Tt, GeneratorContext as U, AdapterFactoryOptions as Ut, createKubb as V, createCache as Vt, defineGenerator as W, AdapterSource as Wt, KubbPluginSetupContext as X, KubbPluginEndContext as Y, KubbPluginStartContext as Z, InputPath as _, Parser as _t, DiagnosticLocation as a, ResolveBannerContext as at, KubbBuildStartContext as b, Reporter as bt, PerformanceDiagnostic as c, Resolver as ct, SerializedDiagnostic as d, ResolverPathParams as dt, Override as et, UpdateDiagnostic as f, defineResolver as ft, InputData as g, ParsedFile as gt, Config as h, FileProcessorHooks as ht, DiagnosticKind as i, BannerMeta as it, KubbHookLineContext as j, logLevel as jt, KubbGenerationStartContext as k, UserLogger as kt, ProblemCode as l, ResolverContext as lt, CLIOptions as m, defineMiddleware as mt, DiagnosticByCode as n, PluginFactoryOptions as nt, DiagnosticSeverity as o, ResolveBannerFile as ot, BuildOutput as p, Middleware as pt, Group as q, DiagnosticDoc as r, definePlugin as rt, Diagnostics as s, ResolveOptionsContext as st, Diagnostic as t, Plugin as tt, ProblemDiagnostic as u, ResolverFileParams as ut, Kubb$1 as v, defineParser as vt, KubbFileProcessingUpdate as w, createReporter as wt, KubbConfigEndContext as x, ReporterContext as xt, KubbBuildEndContext as y, GenerationResult as yt, PossibleConfig as z, Cache as zt };
|
|
3098
|
+
//# sourceMappingURL=diagnostics-CuBWjwYc.d.ts.map
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_memoryStorage = require("./memoryStorage-
|
|
3
|
-
let node_util = require("node:util");
|
|
2
|
+
const require_memoryStorage = require("./memoryStorage-Biujme_q.cjs");
|
|
4
3
|
let node_crypto = require("node:crypto");
|
|
4
|
+
let node_util = require("node:util");
|
|
5
5
|
let node_fs_promises = require("node:fs/promises");
|
|
6
6
|
let node_path = require("node:path");
|
|
7
7
|
let node_dns = require("node:dns");
|
|
@@ -61,7 +61,7 @@ const randomColors = [
|
|
|
61
61
|
*/
|
|
62
62
|
function randomCliColor(text) {
|
|
63
63
|
if (!text) return "";
|
|
64
|
-
return (0, node_util.styleText)(randomColors[(0, node_crypto.
|
|
64
|
+
return (0, node_util.styleText)(randomColors[(0, node_crypto.hash)("sha256", text, "buffer").readUInt32BE(0) % randomColors.length] ?? "white", text);
|
|
65
65
|
}
|
|
66
66
|
//#endregion
|
|
67
67
|
//#region ../../internals/utils/src/env.ts
|
|
@@ -81,8 +81,72 @@ function isCIEnvironment() {
|
|
|
81
81
|
return !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI || process.env.BITBUCKET_BUILD_NUMBER || process.env.JENKINS_URL || process.env.CIRCLECI || process.env.TRAVIS || process.env.TEAMCITY_VERSION || process.env.BUILDKITE || process.env.TF_BUILD);
|
|
82
82
|
}
|
|
83
83
|
//#endregion
|
|
84
|
+
//#region ../../internals/utils/src/runtime.ts
|
|
85
|
+
/**
|
|
86
|
+
* Returns `true` when the current process is running under Bun.
|
|
87
|
+
*
|
|
88
|
+
* Detection keys off the global `Bun` object rather than `process.versions`,
|
|
89
|
+
* because Bun polyfills `process.versions.node` for Node compatibility and would
|
|
90
|
+
* otherwise look like Node.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* if (isBun()) {
|
|
95
|
+
* await Bun.write(path, data)
|
|
96
|
+
* }
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
function isBun() {
|
|
100
|
+
return typeof Bun !== "undefined";
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Returns `true` when the current process is running under Deno.
|
|
104
|
+
*/
|
|
105
|
+
function isDeno() {
|
|
106
|
+
return typeof globalThis.Deno !== "undefined";
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Returns the name of the runtime executing the current process.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```ts
|
|
113
|
+
* getRuntimeName() // 'bun' when run with `bun kubb`, 'node' otherwise
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
function getRuntimeName() {
|
|
117
|
+
if (isBun()) return "bun";
|
|
118
|
+
if (isDeno()) return "deno";
|
|
119
|
+
return "node";
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Returns the version of the active runtime, or an empty string when it cannot be read.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```ts
|
|
126
|
+
* getRuntimeVersion() // '1.3.11' under Bun, '22.22.2' under Node
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
function getRuntimeVersion() {
|
|
130
|
+
if (isBun()) return process.versions.bun ?? "";
|
|
131
|
+
if (isDeno()) return globalThis.Deno?.version?.deno ?? "";
|
|
132
|
+
return process.versions?.node ?? "";
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
84
135
|
//#region ../../internals/utils/src/fs.ts
|
|
85
136
|
/**
|
|
137
|
+
* Reads the file at `path` as a UTF-8 string.
|
|
138
|
+
* Uses `Bun.file().text()` when running under Bun, `fs.readFile` otherwise.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* const source = await read('./src/Pet.ts')
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
async function read(path) {
|
|
146
|
+
if (isBun()) return Bun.file(path).text();
|
|
147
|
+
return (0, node_fs_promises.readFile)(path, { encoding: "utf8" });
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
86
150
|
* Writes `data` to `path`, trimming leading/trailing whitespace before saving.
|
|
87
151
|
* Skips the write when the trimmed content is empty or identical to what is already on disk.
|
|
88
152
|
* Creates any missing parent directories automatically.
|
|
@@ -99,7 +163,7 @@ async function write(path, data, options = {}) {
|
|
|
99
163
|
const trimmed = data.trim();
|
|
100
164
|
if (trimmed === "") return null;
|
|
101
165
|
const resolved = (0, node_path.resolve)(path);
|
|
102
|
-
if (
|
|
166
|
+
if (isBun()) {
|
|
103
167
|
const file = Bun.file(resolved);
|
|
104
168
|
if ((await file.exists() ? await file.text() : null) === trimmed) return null;
|
|
105
169
|
await Bun.write(resolved, trimmed);
|
|
@@ -177,6 +241,25 @@ async function executeIfOnline(fn) {
|
|
|
177
241
|
}
|
|
178
242
|
}
|
|
179
243
|
//#endregion
|
|
244
|
+
//#region ../../internals/utils/src/path.ts
|
|
245
|
+
/**
|
|
246
|
+
* Converts a filesystem path to use POSIX (`/`) separators.
|
|
247
|
+
*
|
|
248
|
+
* Most of the codebase compares and composes paths as strings (prefix matching, joining for
|
|
249
|
+
* import specifiers, splitting on `/`). On POSIX `path.resolve` already returns `/`-separated
|
|
250
|
+
* paths, but on Windows it returns `\`-separated paths, which breaks every such comparison.
|
|
251
|
+
*
|
|
252
|
+
* Routing every path that crosses a module boundary through `toPosixPath` keeps the rest of the
|
|
253
|
+
* code platform-agnostic. The conversion runs unconditionally so Windows-specific behavior is
|
|
254
|
+
* exercisable from POSIX CI.
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* toPosixPath('C:\\repo\\src\\pet.ts') // 'C:/repo/src/pet.ts'
|
|
258
|
+
*/
|
|
259
|
+
function toPosixPath(filePath) {
|
|
260
|
+
return filePath.replaceAll("\\", "/");
|
|
261
|
+
}
|
|
262
|
+
//#endregion
|
|
180
263
|
//#region src/createAdapter.ts
|
|
181
264
|
/**
|
|
182
265
|
* Defines a custom adapter that translates a spec format into Kubb's universal
|
|
@@ -212,6 +295,35 @@ function createAdapter(build) {
|
|
|
212
295
|
return (options) => build(options ?? {});
|
|
213
296
|
}
|
|
214
297
|
//#endregion
|
|
298
|
+
//#region src/createCache.ts
|
|
299
|
+
/**
|
|
300
|
+
* Defines a custom cache backend. The builder receives user options and returns a
|
|
301
|
+
* {@link Cache}. Reach for this when the filesystem backend doesn't fit, for
|
|
302
|
+
* example to store snapshots in Redis or a database.
|
|
303
|
+
*
|
|
304
|
+
* @example In-memory cache (the built-in implementation)
|
|
305
|
+
* ```ts
|
|
306
|
+
* import { createCache } from '@kubb/core'
|
|
307
|
+
*
|
|
308
|
+
* export const memoryCache = createCache(() => {
|
|
309
|
+
* const store = new Map<string, CachedSnapshot>()
|
|
310
|
+
*
|
|
311
|
+
* return {
|
|
312
|
+
* name: 'memory',
|
|
313
|
+
* async restore({ key }) {
|
|
314
|
+
* return store.get(key) ?? null
|
|
315
|
+
* },
|
|
316
|
+
* async persist({ key, snapshot }) {
|
|
317
|
+
* store.set(key, snapshot)
|
|
318
|
+
* },
|
|
319
|
+
* }
|
|
320
|
+
* })
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
323
|
+
function createCache(build) {
|
|
324
|
+
return (options) => build(options ?? {});
|
|
325
|
+
}
|
|
326
|
+
//#endregion
|
|
215
327
|
//#region src/storages/fsStorage.ts
|
|
216
328
|
/**
|
|
217
329
|
* Built-in filesystem storage driver.
|
|
@@ -263,21 +375,21 @@ const fsStorage = require_memoryStorage.createStorage(() => ({
|
|
|
263
375
|
},
|
|
264
376
|
async getKeys(base) {
|
|
265
377
|
const resolvedBase = (0, node_path.resolve)(base ?? process.cwd());
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}
|
|
273
|
-
for (const entry of entries) {
|
|
274
|
-
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
275
|
-
if (entry.isDirectory()) yield* walk((0, node_path.join)(dir, entry.name), rel);
|
|
276
|
-
else yield rel;
|
|
277
|
-
}
|
|
378
|
+
if (isBun()) {
|
|
379
|
+
const bunGlob = new Bun.Glob("**/*");
|
|
380
|
+
return Array.fromAsync(bunGlob.scan({
|
|
381
|
+
cwd: resolvedBase,
|
|
382
|
+
onlyFiles: true,
|
|
383
|
+
dot: true
|
|
384
|
+
}));
|
|
278
385
|
}
|
|
279
386
|
const keys = [];
|
|
280
|
-
|
|
387
|
+
try {
|
|
388
|
+
for await (const entry of (0, node_fs_promises.glob)("**/*", {
|
|
389
|
+
cwd: resolvedBase,
|
|
390
|
+
withFileTypes: true
|
|
391
|
+
})) if (entry.isFile()) keys.push(toPosixPath((0, node_path.relative)(resolvedBase, (0, node_path.join)(entry.parentPath, entry.name))));
|
|
392
|
+
} catch (_error) {}
|
|
281
393
|
return keys;
|
|
282
394
|
},
|
|
283
395
|
async clear(base) {
|
|
@@ -336,6 +448,7 @@ function resolveConfig(userConfig) {
|
|
|
336
448
|
...userConfig.output
|
|
337
449
|
},
|
|
338
450
|
storage: userConfig.storage ?? fsStorage(),
|
|
451
|
+
cache: userConfig.cache === false ? void 0 : userConfig.cache,
|
|
339
452
|
reporters: userConfig.reporters ?? [],
|
|
340
453
|
plugins: userConfig.plugins ?? []
|
|
341
454
|
};
|
|
@@ -766,6 +879,8 @@ var Telemetry = class Telemetry {
|
|
|
766
879
|
command: options.command,
|
|
767
880
|
kubbVersion: options.kubbVersion,
|
|
768
881
|
nodeVersion: node_process.default.versions.node.split(".")[0],
|
|
882
|
+
runtime: getRuntimeName(),
|
|
883
|
+
runtimeVersion: getRuntimeVersion().split(".")[0],
|
|
769
884
|
platform: node_os.default.platform(),
|
|
770
885
|
ci: isCIEnvironment(),
|
|
771
886
|
plugins: options.plugins ?? [],
|
|
@@ -796,6 +911,14 @@ var Telemetry = class Telemetry {
|
|
|
796
911
|
key: "kubb.node_version",
|
|
797
912
|
value: { stringValue: event.nodeVersion }
|
|
798
913
|
},
|
|
914
|
+
{
|
|
915
|
+
key: "kubb.runtime",
|
|
916
|
+
value: { stringValue: event.runtime }
|
|
917
|
+
},
|
|
918
|
+
{
|
|
919
|
+
key: "kubb.runtime_version",
|
|
920
|
+
value: { stringValue: event.runtimeVersion }
|
|
921
|
+
},
|
|
799
922
|
{
|
|
800
923
|
key: "kubb.platform",
|
|
801
924
|
value: { stringValue: event.platform }
|
|
@@ -906,14 +1029,8 @@ var Telemetry = class Telemetry {
|
|
|
906
1029
|
* get files() {
|
|
907
1030
|
* return runtime.files
|
|
908
1031
|
* },
|
|
909
|
-
* dispose() {
|
|
910
|
-
* runtime.dispose()
|
|
911
|
-
* },
|
|
912
|
-
* unmount(error) {
|
|
913
|
-
* runtime.dispose(error)
|
|
914
|
-
* },
|
|
915
1032
|
* [Symbol.dispose]() {
|
|
916
|
-
*
|
|
1033
|
+
* runtime.dispose()
|
|
917
1034
|
* },
|
|
918
1035
|
* }
|
|
919
1036
|
* })
|
|
@@ -1027,6 +1144,132 @@ function defineParser(parser) {
|
|
|
1027
1144
|
return parser;
|
|
1028
1145
|
}
|
|
1029
1146
|
//#endregion
|
|
1147
|
+
//#region src/Manifest.ts
|
|
1148
|
+
/**
|
|
1149
|
+
* Reads and prunes the local cache manifest. All methods are static, so call them as
|
|
1150
|
+
* `Manifest.read(dir)` and `Manifest.prune(data, ...)`. A damaged manifest reads as empty so the
|
|
1151
|
+
* cache degrades to misses instead of throwing. Writing goes through `write` from `@internals/utils`.
|
|
1152
|
+
*/
|
|
1153
|
+
var Manifest = class Manifest {
|
|
1154
|
+
/**
|
|
1155
|
+
* On-disk layout version for the manifest itself. Bumped when the manifest shape changes; a
|
|
1156
|
+
* mismatch makes the whole local cache read as empty.
|
|
1157
|
+
*/
|
|
1158
|
+
static version = 1;
|
|
1159
|
+
/**
|
|
1160
|
+
* Reads the manifest at `dir/manifest.json`. A missing, corrupt, or version-mismatched file reads
|
|
1161
|
+
* as an empty manifest.
|
|
1162
|
+
*/
|
|
1163
|
+
static async read(dir) {
|
|
1164
|
+
try {
|
|
1165
|
+
const parsed = JSON.parse(await read((0, node_path.join)(dir, "manifest.json")));
|
|
1166
|
+
if (parsed.version !== Manifest.version || typeof parsed.entries !== "object") return Manifest.#empty();
|
|
1167
|
+
return parsed;
|
|
1168
|
+
} catch {
|
|
1169
|
+
return Manifest.#empty();
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
/**
|
|
1173
|
+
* Selects the keys to evict so the cache stays within `ttlDays` and `maxEntries`. Returns the
|
|
1174
|
+
* surviving manifest plus the evicted keys (the caller deletes their blobs). Pure, does no IO.
|
|
1175
|
+
*/
|
|
1176
|
+
static prune(manifest, { maxEntries, ttlDays, now }) {
|
|
1177
|
+
const ttlMs = ttlDays * 24 * 60 * 60 * 1e3;
|
|
1178
|
+
const removed = [];
|
|
1179
|
+
const kept = [];
|
|
1180
|
+
for (const [key, entry] of Object.entries(manifest.entries)) if (now - entry.lastAccess > ttlMs) removed.push(key);
|
|
1181
|
+
else kept.push([key, entry]);
|
|
1182
|
+
if (kept.length > maxEntries) {
|
|
1183
|
+
kept.sort((a, b) => b[1].lastAccess - a[1].lastAccess);
|
|
1184
|
+
for (const [key] of kept.splice(maxEntries)) removed.push(key);
|
|
1185
|
+
}
|
|
1186
|
+
return {
|
|
1187
|
+
manifest: {
|
|
1188
|
+
version: Manifest.version,
|
|
1189
|
+
entries: Object.fromEntries(kept)
|
|
1190
|
+
},
|
|
1191
|
+
removed
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
static #empty() {
|
|
1195
|
+
return {
|
|
1196
|
+
version: Manifest.version,
|
|
1197
|
+
entries: {}
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
};
|
|
1201
|
+
//#endregion
|
|
1202
|
+
//#region src/caches/fsCache.ts
|
|
1203
|
+
function blobName(relativePath) {
|
|
1204
|
+
return `${(0, node_crypto.createHash)("sha256").update(relativePath).digest("hex")}.blob`;
|
|
1205
|
+
}
|
|
1206
|
+
/**
|
|
1207
|
+
* Local filesystem cache. Stores each build snapshot as content blobs plus an index,
|
|
1208
|
+
* tracked by a manifest under `node_modules/.cache/kubb/` (the Nx and Vitest
|
|
1209
|
+
* convention). Least-recently-used and expired entries are pruned on every persist.
|
|
1210
|
+
*
|
|
1211
|
+
* @example
|
|
1212
|
+
* ```ts
|
|
1213
|
+
* import { fsCache } from '@kubb/core'
|
|
1214
|
+
*
|
|
1215
|
+
* export default defineConfig({
|
|
1216
|
+
* cache: fsCache(),
|
|
1217
|
+
* })
|
|
1218
|
+
* ```
|
|
1219
|
+
*/
|
|
1220
|
+
const fsCache = createCache((options = {}) => {
|
|
1221
|
+
const dir = (0, node_path.resolve)(options.dir ?? (0, node_path.join)("node_modules", ".cache", "kubb"));
|
|
1222
|
+
const maxEntries = options.maxEntries ?? 50;
|
|
1223
|
+
const ttlDays = options.ttlDays ?? 7;
|
|
1224
|
+
const blobsDir = (0, node_path.join)(dir, "blobs");
|
|
1225
|
+
const manifestPath = (0, node_path.join)(dir, "manifest.json");
|
|
1226
|
+
return {
|
|
1227
|
+
name: "fs",
|
|
1228
|
+
async restore({ key }) {
|
|
1229
|
+
const manifest = await Manifest.read(dir);
|
|
1230
|
+
const entry = manifest.entries[key];
|
|
1231
|
+
if (!entry) return null;
|
|
1232
|
+
try {
|
|
1233
|
+
const index = JSON.parse(await read((0, node_path.join)(blobsDir, key, "index.json")));
|
|
1234
|
+
const files = {};
|
|
1235
|
+
for (const { path, blob } of index) files[path] = await read((0, node_path.join)(blobsDir, key, blob));
|
|
1236
|
+
entry.lastAccess = Date.now();
|
|
1237
|
+
await write(manifestPath, JSON.stringify(manifest)).catch(() => {});
|
|
1238
|
+
return { files };
|
|
1239
|
+
} catch {
|
|
1240
|
+
return null;
|
|
1241
|
+
}
|
|
1242
|
+
},
|
|
1243
|
+
async persist({ key, snapshot }) {
|
|
1244
|
+
const entryDir = (0, node_path.join)(blobsDir, key);
|
|
1245
|
+
const index = [];
|
|
1246
|
+
for (const [path, source] of Object.entries(snapshot.files)) {
|
|
1247
|
+
const blob = blobName(path);
|
|
1248
|
+
await write((0, node_path.join)(entryDir, blob), source);
|
|
1249
|
+
index.push({
|
|
1250
|
+
path,
|
|
1251
|
+
blob
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1254
|
+
await write((0, node_path.join)(entryDir, "index.json"), JSON.stringify(index));
|
|
1255
|
+
const manifest = await Manifest.read(dir);
|
|
1256
|
+
const now = Date.now();
|
|
1257
|
+
manifest.entries[key] = {
|
|
1258
|
+
files: index.map((item) => item.path),
|
|
1259
|
+
createdAt: now,
|
|
1260
|
+
lastAccess: now
|
|
1261
|
+
};
|
|
1262
|
+
const pruned = Manifest.prune(manifest, {
|
|
1263
|
+
maxEntries,
|
|
1264
|
+
ttlDays,
|
|
1265
|
+
now
|
|
1266
|
+
});
|
|
1267
|
+
await Promise.all(pruned.removed.map((removedKey) => clean((0, node_path.join)(blobsDir, removedKey))));
|
|
1268
|
+
await write(manifestPath, JSON.stringify(pruned.manifest));
|
|
1269
|
+
}
|
|
1270
|
+
};
|
|
1271
|
+
});
|
|
1272
|
+
//#endregion
|
|
1030
1273
|
exports.AsyncEventEmitter = require_memoryStorage.AsyncEventEmitter;
|
|
1031
1274
|
exports.Diagnostics = require_memoryStorage.Diagnostics;
|
|
1032
1275
|
exports.KubbDriver = require_memoryStorage.KubbDriver;
|
|
@@ -1040,6 +1283,7 @@ Object.defineProperty(exports, "ast", {
|
|
|
1040
1283
|
});
|
|
1041
1284
|
exports.cliReporter = cliReporter;
|
|
1042
1285
|
exports.createAdapter = createAdapter;
|
|
1286
|
+
exports.createCache = createCache;
|
|
1043
1287
|
exports.createKubb = createKubb;
|
|
1044
1288
|
exports.createRenderer = createRenderer;
|
|
1045
1289
|
exports.createReporter = createReporter;
|
|
@@ -1051,6 +1295,7 @@ exports.defineParser = defineParser;
|
|
|
1051
1295
|
exports.definePlugin = require_memoryStorage.definePlugin;
|
|
1052
1296
|
exports.defineResolver = require_memoryStorage.defineResolver;
|
|
1053
1297
|
exports.fileReporter = fileReporter;
|
|
1298
|
+
exports.fsCache = fsCache;
|
|
1054
1299
|
exports.fsStorage = fsStorage;
|
|
1055
1300
|
exports.jsonReporter = jsonReporter;
|
|
1056
1301
|
exports.logLevel = logLevel;
|