@kubb/core 5.0.0-beta.1 → 5.0.0-beta.11
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 +9 -39
- package/dist/{PluginDriver-BXibeQk-.cjs → PluginDriver-C1OsqGBJ.cjs} +106 -56
- package/dist/PluginDriver-C1OsqGBJ.cjs.map +1 -0
- package/dist/{PluginDriver-DV3p2Hky.js → PluginDriver-CGypdXHg.js} +101 -57
- package/dist/PluginDriver-CGypdXHg.js.map +1 -0
- package/dist/{types-CuNocrbJ.d.ts → createKubb-BSfMDBwR.d.ts} +1533 -1505
- package/dist/index.cjs +249 -209
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -185
- package/dist/index.js +249 -209
- package/dist/index.js.map +1 -1
- package/dist/mocks.cjs +1 -1
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.ts +1 -1
- package/dist/mocks.js +1 -1
- package/dist/mocks.js.map +1 -1
- package/package.json +5 -12
- package/src/FileManager.ts +8 -0
- package/src/FileProcessor.ts +12 -7
- package/src/PluginDriver.ts +49 -7
- package/src/constants.ts +6 -2
- package/src/createAdapter.ts +77 -1
- package/src/createKubb.ts +973 -141
- package/src/defineGenerator.ts +92 -4
- package/src/defineLogger.ts +42 -3
- package/src/defineMiddleware.ts +1 -1
- package/src/definePlugin.ts +304 -8
- package/src/defineResolver.ts +185 -52
- package/src/devtools.ts +8 -1
- package/src/index.ts +1 -1
- package/src/mocks.ts +1 -2
- package/src/storages/fsStorage.ts +6 -31
- package/src/types.ts +38 -1292
- package/dist/PluginDriver-BXibeQk-.cjs.map +0 -1
- package/dist/PluginDriver-DV3p2Hky.js.map +0 -1
- package/src/Kubb.ts +0 -300
- package/src/renderNode.ts +0 -35
- package/src/utils/diagnostics.ts +0 -18
- package/src/utils/isInputPath.ts +0 -10
- package/src/utils/packageJSON.ts +0 -99
package/src/defineResolver.ts
CHANGED
|
@@ -2,17 +2,159 @@ import path from 'node:path'
|
|
|
2
2
|
import { camelCase, pascalCase } from '@internals/utils'
|
|
3
3
|
import type { FileNode, InputNode, Node, OperationNode, SchemaNode } from '@kubb/ast'
|
|
4
4
|
import { createFile, isOperationNode, isSchemaNode } from '@kubb/ast'
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
5
|
+
import type { PluginFactoryOptions } from './definePlugin.ts'
|
|
6
|
+
import { getMode } from './definePlugin.ts'
|
|
7
|
+
import type { Config, Group, Output } from './types.ts'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Type/string pattern filter for include/exclude/override matching.
|
|
11
|
+
*/
|
|
12
|
+
type PatternFilter = {
|
|
13
|
+
type: string
|
|
14
|
+
pattern: string | RegExp
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Pattern filter with partial option overrides applied when the pattern matches.
|
|
19
|
+
*/
|
|
20
|
+
type PatternOverride<TOptions> = PatternFilter & {
|
|
21
|
+
options: Omit<Partial<TOptions>, 'override'>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Context for resolving filtered options for a given operation or schema node.
|
|
26
|
+
*
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
export type ResolveOptionsContext<TOptions> = {
|
|
30
|
+
options: TOptions
|
|
31
|
+
exclude?: Array<PatternFilter>
|
|
32
|
+
include?: Array<PatternFilter>
|
|
33
|
+
override?: Array<PatternOverride<TOptions>>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Base constraint for all plugin resolver objects.
|
|
38
|
+
*
|
|
39
|
+
* `default`, `resolveOptions`, `resolvePath`, `resolveFile`, `resolveBanner`, and `resolveFooter`
|
|
40
|
+
* are injected automatically by `defineResolver` — extend this type to add custom resolution methods.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* type MyResolver = Resolver & {
|
|
45
|
+
* resolveName(node: SchemaNode): string
|
|
46
|
+
* resolveTypedName(node: SchemaNode): string
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export type Resolver = {
|
|
51
|
+
name: string
|
|
52
|
+
pluginName: string
|
|
53
|
+
default(name: string, type?: 'file' | 'function' | 'type' | 'const'): string
|
|
54
|
+
resolveOptions<TOptions>(node: Node, context: ResolveOptionsContext<TOptions>): TOptions | null
|
|
55
|
+
resolvePath(params: ResolverPathParams, context: ResolverContext): string
|
|
56
|
+
resolveFile(params: ResolverFileParams, context: ResolverContext): FileNode
|
|
57
|
+
resolveBanner(node: InputNode | null, context: ResolveBannerContext): string | undefined
|
|
58
|
+
resolveFooter(node: InputNode | null, context: ResolveBannerContext): string | undefined
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* File-specific parameters for `Resolver.resolvePath`.
|
|
63
|
+
*
|
|
64
|
+
* Pass alongside a `ResolverContext` to identify which file to resolve.
|
|
65
|
+
* Provide `tag` for tag-based grouping or `path` for path-based grouping.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* resolver.resolvePath(
|
|
70
|
+
* { baseName: 'petTypes.ts', tag: 'pets' },
|
|
71
|
+
* { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },
|
|
72
|
+
* )
|
|
73
|
+
* // → '/src/types/petsController/petTypes.ts'
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export type ResolverPathParams = {
|
|
77
|
+
baseName: FileNode['baseName']
|
|
78
|
+
pathMode?: 'single' | 'split'
|
|
79
|
+
/**
|
|
80
|
+
* Tag value used when `group.type === 'tag'`.
|
|
81
|
+
*/
|
|
82
|
+
tag?: string
|
|
83
|
+
/**
|
|
84
|
+
* Path value used when `group.type === 'path'`.
|
|
85
|
+
*/
|
|
86
|
+
path?: string
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Shared context passed as the second argument to `Resolver.resolvePath` and `Resolver.resolveFile`.
|
|
91
|
+
*
|
|
92
|
+
* Describes where on disk output is rooted, which output config is active, and the optional
|
|
93
|
+
* grouping strategy that controls subdirectory layout.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* const context: ResolverContext = {
|
|
98
|
+
* root: config.root,
|
|
99
|
+
* output,
|
|
100
|
+
* group,
|
|
101
|
+
* }
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export type ResolverContext = {
|
|
105
|
+
root: string
|
|
106
|
+
output: Output
|
|
107
|
+
group?: Group
|
|
108
|
+
/**
|
|
109
|
+
* Plugin name used to populate `meta.pluginName` on the resolved file.
|
|
110
|
+
*/
|
|
111
|
+
pluginName?: string
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* File-specific parameters for `Resolver.resolveFile`.
|
|
116
|
+
*
|
|
117
|
+
* Pass alongside a `ResolverContext` to fully describe the file to resolve.
|
|
118
|
+
* `tag` and `path` are used only when a matching `group` is present in the context.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```ts
|
|
122
|
+
* resolver.resolveFile(
|
|
123
|
+
* { name: 'listPets', extname: '.ts', tag: 'pets' },
|
|
124
|
+
* { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },
|
|
125
|
+
* )
|
|
126
|
+
* // → { baseName: 'listPets.ts', path: '/src/types/petsController/listPets.ts', ... }
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export type ResolverFileParams = {
|
|
130
|
+
name: string
|
|
131
|
+
extname: FileNode['extname']
|
|
132
|
+
/**
|
|
133
|
+
* Tag value used when `group.type === 'tag'`.
|
|
134
|
+
*/
|
|
135
|
+
tag?: string
|
|
136
|
+
/**
|
|
137
|
+
* Path value used when `group.type === 'path'`.
|
|
138
|
+
*/
|
|
139
|
+
path?: string
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Context passed to `Resolver.resolveBanner` and `Resolver.resolveFooter`.
|
|
144
|
+
*
|
|
145
|
+
* `output` is optional — not every plugin configures a banner/footer.
|
|
146
|
+
* `config` carries the global Kubb config, used to derive the default Kubb banner.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* resolver.resolveBanner(inputNode, { output: { banner: '// generated' }, config })
|
|
151
|
+
* // → '// generated'
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export type ResolveBannerContext = {
|
|
155
|
+
output?: Pick<Output, 'banner' | 'footer'>
|
|
156
|
+
config: Config
|
|
157
|
+
}
|
|
16
158
|
|
|
17
159
|
/**
|
|
18
160
|
* Builder type for the plugin-specific resolver fields.
|
|
@@ -20,19 +162,16 @@ import type {
|
|
|
20
162
|
* `default`, `resolveOptions`, `resolvePath`, `resolveFile`, `resolveBanner`, and `resolveFooter`
|
|
21
163
|
* are optional — built-in fallbacks are injected when omitted.
|
|
22
164
|
*
|
|
23
|
-
*
|
|
24
|
-
* call sibling resolver methods without using `this`. Because `ctx` is captured by the closure
|
|
25
|
-
* and the resolver is populated after the builder runs, `ctx` correctly reflects any overrides
|
|
26
|
-
* that were applied by the builder itself.
|
|
165
|
+
* Methods in the returned object can call sibling resolver methods via `this`.
|
|
27
166
|
*/
|
|
28
|
-
type ResolverBuilder<T extends PluginFactoryOptions> = (
|
|
167
|
+
type ResolverBuilder<T extends PluginFactoryOptions> = () => Omit<
|
|
29
168
|
T['resolver'],
|
|
30
169
|
'default' | 'resolveOptions' | 'resolvePath' | 'resolveFile' | 'resolveBanner' | 'resolveFooter' | 'name' | 'pluginName'
|
|
31
170
|
> &
|
|
32
171
|
Partial<Pick<T['resolver'], 'default' | 'resolveOptions' | 'resolvePath' | 'resolveFile' | 'resolveBanner' | 'resolveFooter'>> & {
|
|
33
172
|
name: string
|
|
34
173
|
pluginName: T['name']
|
|
35
|
-
}
|
|
174
|
+
} & ThisType<T['resolver']>
|
|
36
175
|
|
|
37
176
|
// String patterns are compiled lazily and cached — the same filter is reused for every node.
|
|
38
177
|
const stringPatternCache = new Map<string, RegExp>()
|
|
@@ -215,7 +354,7 @@ export function defaultResolveOptions<TOptions>(
|
|
|
215
354
|
* ```
|
|
216
355
|
*/
|
|
217
356
|
export function defaultResolvePath({ baseName, pathMode, tag, path: groupPath }: ResolverPathParams, { root, output, group }: ResolverContext): string {
|
|
218
|
-
const mode = pathMode ??
|
|
357
|
+
const mode = pathMode ?? getMode(path.resolve(root, output.path))
|
|
219
358
|
|
|
220
359
|
if (mode === 'single') {
|
|
221
360
|
return path.resolve(root, output.path)
|
|
@@ -268,35 +407,35 @@ export function defaultResolvePath({ baseName, pathMode, tag, path: groupPath }:
|
|
|
268
407
|
*
|
|
269
408
|
* @example Resolve a schema file
|
|
270
409
|
* ```ts
|
|
271
|
-
* const file = defaultResolveFile(
|
|
410
|
+
* const file = defaultResolveFile.call(
|
|
411
|
+
* resolver,
|
|
272
412
|
* { name: 'pet', extname: '.ts' },
|
|
273
413
|
* { root: '/src', output: { path: 'types' } },
|
|
274
|
-
* resolver,
|
|
275
414
|
* )
|
|
276
415
|
* // → { baseName: 'pet.ts', path: '/src/types/pet.ts', sources: [], ... }
|
|
277
416
|
* ```
|
|
278
417
|
*
|
|
279
418
|
* @example Resolve an operation file with tag grouping
|
|
280
419
|
* ```ts
|
|
281
|
-
* const file = defaultResolveFile(
|
|
420
|
+
* const file = defaultResolveFile.call(
|
|
421
|
+
* resolver,
|
|
282
422
|
* { name: 'listPets', extname: '.ts', tag: 'pets' },
|
|
283
423
|
* { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },
|
|
284
|
-
* resolver,
|
|
285
424
|
* )
|
|
286
425
|
* // → { baseName: 'listPets.ts', path: '/src/types/petsController/listPets.ts', ... }
|
|
287
426
|
* ```
|
|
288
427
|
*/
|
|
289
|
-
export function defaultResolveFile({ name, extname, tag, path: groupPath }: ResolverFileParams, context: ResolverContext
|
|
290
|
-
const pathMode =
|
|
291
|
-
const resolvedName = pathMode === 'single' ? '' :
|
|
428
|
+
export function defaultResolveFile(this: Resolver, { name, extname, tag, path: groupPath }: ResolverFileParams, context: ResolverContext): FileNode {
|
|
429
|
+
const pathMode = getMode(path.resolve(context.root, context.output.path))
|
|
430
|
+
const resolvedName = pathMode === 'single' ? '' : this.default(name, 'file')
|
|
292
431
|
const baseName = `${resolvedName}${extname}` as FileNode['baseName']
|
|
293
|
-
const filePath =
|
|
432
|
+
const filePath = this.resolvePath({ baseName, pathMode, tag, path: groupPath }, context)
|
|
294
433
|
|
|
295
434
|
return createFile({
|
|
296
435
|
path: filePath,
|
|
297
436
|
baseName: path.basename(filePath) as `${string}.${string}`,
|
|
298
437
|
meta: {
|
|
299
|
-
pluginName:
|
|
438
|
+
pluginName: this.pluginName,
|
|
300
439
|
},
|
|
301
440
|
sources: [],
|
|
302
441
|
imports: [],
|
|
@@ -325,9 +464,9 @@ export function buildDefaultBanner({
|
|
|
325
464
|
if (first && 'path' in first) {
|
|
326
465
|
source = path.basename(first.path)
|
|
327
466
|
}
|
|
328
|
-
} else if ('path' in config.input) {
|
|
467
|
+
} else if (config.input && 'path' in config.input) {
|
|
329
468
|
source = path.basename(config.input.path)
|
|
330
|
-
} else if ('data' in config.input) {
|
|
469
|
+
} else if (config.input && 'data' in config.input) {
|
|
331
470
|
source = 'text content'
|
|
332
471
|
}
|
|
333
472
|
|
|
@@ -459,25 +598,24 @@ export function defaultResolveFooter(node: InputNode | undefined, { output }: Re
|
|
|
459
598
|
* - `resolvePath` — output path computation
|
|
460
599
|
* - `resolveFile` — full `FileNode` construction
|
|
461
600
|
*
|
|
462
|
-
*
|
|
463
|
-
* call sibling resolver methods using `ctx` instead of `this`.
|
|
601
|
+
* Methods in the returned object can call sibling resolver methods via `this`.
|
|
464
602
|
*
|
|
465
603
|
* @example Basic resolver with naming helpers
|
|
466
604
|
* ```ts
|
|
467
|
-
* export const resolver = defineResolver<PluginTs>((
|
|
605
|
+
* export const resolver = defineResolver<PluginTs>(() => ({
|
|
468
606
|
* name: 'default',
|
|
469
607
|
* resolveName(node) {
|
|
470
|
-
* return
|
|
608
|
+
* return this.default(node.name, 'function')
|
|
471
609
|
* },
|
|
472
610
|
* resolveTypedName(node) {
|
|
473
|
-
* return
|
|
611
|
+
* return this.default(node.name, 'type')
|
|
474
612
|
* },
|
|
475
613
|
* }))
|
|
476
614
|
* ```
|
|
477
615
|
*
|
|
478
616
|
* @example Override resolvePath for a custom output structure
|
|
479
617
|
* ```ts
|
|
480
|
-
* export const resolver = defineResolver<PluginTs>((
|
|
618
|
+
* export const resolver = defineResolver<PluginTs>(() => ({
|
|
481
619
|
* name: 'custom',
|
|
482
620
|
* resolvePath({ baseName }, { root, output }) {
|
|
483
621
|
* return path.resolve(root, output.path, 'generated', baseName)
|
|
@@ -485,37 +623,32 @@ export function defaultResolveFooter(node: InputNode | undefined, { output }: Re
|
|
|
485
623
|
* }))
|
|
486
624
|
* ```
|
|
487
625
|
*
|
|
488
|
-
* @example Use
|
|
626
|
+
* @example Use this.default inside a helper
|
|
489
627
|
* ```ts
|
|
490
|
-
* export const resolver = defineResolver<PluginTs>((
|
|
628
|
+
* export const resolver = defineResolver<PluginTs>(() => ({
|
|
491
629
|
* name: 'default',
|
|
492
630
|
* resolveParamName(node, param) {
|
|
493
|
-
* return
|
|
631
|
+
* return this.default(`${node.operationId} ${param.in} ${param.name}`, 'type')
|
|
494
632
|
* },
|
|
495
633
|
* }))
|
|
496
634
|
* ```
|
|
497
635
|
*/
|
|
498
636
|
export function defineResolver<T extends PluginFactoryOptions>(build: ResolverBuilder<T>): T['resolver'] {
|
|
499
|
-
//
|
|
500
|
-
//
|
|
501
|
-
|
|
502
|
-
// properties (including any overrides from the builder itself).
|
|
503
|
-
const resolver = {} as T['resolver']
|
|
637
|
+
// `resolver` is kept so the default `resolveFile` wrapper can reference the fully assembled
|
|
638
|
+
// object via `.call(resolver, ...)` at call-time, after the result is assigned below.
|
|
639
|
+
let resolver: T['resolver']
|
|
504
640
|
|
|
505
|
-
|
|
641
|
+
const result = {
|
|
506
642
|
default: defaultResolver,
|
|
507
643
|
resolveOptions: defaultResolveOptions,
|
|
508
644
|
resolvePath: defaultResolvePath,
|
|
509
|
-
|
|
510
|
-
// Unlike other defaults which can be assigned directly, defaultResolveFile requires the
|
|
511
|
-
// resolver as its third parameter.
|
|
512
|
-
resolveFile: (params: ResolverFileParams, context: ResolverContext) => defaultResolveFile(params, context, resolver as Resolver),
|
|
645
|
+
resolveFile: (params: ResolverFileParams, context: ResolverContext) => defaultResolveFile.call(resolver as Resolver, params, context),
|
|
513
646
|
resolveBanner: defaultResolveBanner,
|
|
514
647
|
resolveFooter: defaultResolveFooter,
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
648
|
+
...build(),
|
|
649
|
+
} as T['resolver']
|
|
650
|
+
|
|
651
|
+
resolver = result
|
|
519
652
|
|
|
520
653
|
return resolver
|
|
521
654
|
}
|
package/src/devtools.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import type { InputNode } from '@kubb/ast'
|
|
2
2
|
import { deflateSync, inflateSync } from 'fflate'
|
|
3
3
|
import { x } from 'tinyexec'
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
export type DevtoolsOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* Open the AST inspector in Kubb Studio (`/ast`). Defaults to the main Studio page.
|
|
8
|
+
* @default false
|
|
9
|
+
*/
|
|
10
|
+
ast?: boolean
|
|
11
|
+
}
|
|
5
12
|
|
|
6
13
|
/**
|
|
7
14
|
* Encodes an `InputNode` as a compressed, URL-safe string.
|
package/src/index.ts
CHANGED
|
@@ -17,4 +17,4 @@ export { PluginDriver } from './PluginDriver.ts'
|
|
|
17
17
|
export { fsStorage } from './storages/fsStorage.ts'
|
|
18
18
|
export { memoryStorage } from './storages/memoryStorage.ts'
|
|
19
19
|
export * from './types.ts'
|
|
20
|
-
export { isInputPath } from './
|
|
20
|
+
export { isInputPath } from './createKubb.ts'
|
package/src/mocks.ts
CHANGED
|
@@ -2,8 +2,7 @@ import { resolve } from 'node:path'
|
|
|
2
2
|
import type { FileNode, OperationNode, SchemaNode, Visitor } from '@kubb/ast'
|
|
3
3
|
import { transform } from '@kubb/ast'
|
|
4
4
|
import { FileManager } from './FileManager.ts'
|
|
5
|
-
import { PluginDriver } from './PluginDriver.ts'
|
|
6
|
-
import { applyHookResult } from './renderNode.ts'
|
|
5
|
+
import { applyHookResult, PluginDriver } from './PluginDriver.ts'
|
|
7
6
|
import type { Adapter, AdapterFactoryOptions, Config, Generator, GeneratorContext, NormalizedPlugin, PluginFactoryOptions } from './types.ts'
|
|
8
7
|
|
|
9
8
|
/**
|
|
@@ -4,13 +4,6 @@ import { join, resolve } from 'node:path'
|
|
|
4
4
|
import { clean, write } from '@internals/utils'
|
|
5
5
|
import { createStorage } from '../createStorage.ts'
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* Detects the filesystem error used to indicate that a path does not exist.
|
|
9
|
-
*/
|
|
10
|
-
function isMissingPathError(error: unknown): error is NodeJS.ErrnoException {
|
|
11
|
-
return typeof error === 'object' && error !== null && 'code' in error && (error as NodeJS.ErrnoException).code === 'ENOENT'
|
|
12
|
-
}
|
|
13
|
-
|
|
14
7
|
/**
|
|
15
8
|
* Built-in filesystem storage driver.
|
|
16
9
|
*
|
|
@@ -42,27 +35,15 @@ export const fsStorage = createStorage(() => ({
|
|
|
42
35
|
try {
|
|
43
36
|
await access(resolve(key))
|
|
44
37
|
return true
|
|
45
|
-
} catch (
|
|
46
|
-
|
|
47
|
-
return false
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
throw new Error(`Failed to access storage item "${key}"`, {
|
|
51
|
-
cause: error as Error,
|
|
52
|
-
})
|
|
38
|
+
} catch (_error) {
|
|
39
|
+
return false
|
|
53
40
|
}
|
|
54
41
|
},
|
|
55
42
|
async getItem(key: string) {
|
|
56
43
|
try {
|
|
57
44
|
return await readFile(resolve(key), 'utf8')
|
|
58
|
-
} catch (
|
|
59
|
-
|
|
60
|
-
return null
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
throw new Error(`Failed to read storage item "${key}"`, {
|
|
64
|
-
cause: error as Error,
|
|
65
|
-
})
|
|
45
|
+
} catch (_error) {
|
|
46
|
+
return null
|
|
66
47
|
}
|
|
67
48
|
},
|
|
68
49
|
async setItem(key: string, value: string) {
|
|
@@ -81,14 +62,8 @@ export const fsStorage = createStorage(() => ({
|
|
|
81
62
|
entries = (await readdir(dir, {
|
|
82
63
|
withFileTypes: true,
|
|
83
64
|
})) as Array<Dirent>
|
|
84
|
-
} catch (
|
|
85
|
-
|
|
86
|
-
return
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
throw new Error(`Failed to list storage keys under "${resolvedBase}"`, {
|
|
90
|
-
cause: error as Error,
|
|
91
|
-
})
|
|
65
|
+
} catch (_error) {
|
|
66
|
+
return
|
|
92
67
|
}
|
|
93
68
|
for (const entry of entries) {
|
|
94
69
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name
|