@kubb/fabric-core 0.2.14 → 0.2.16
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 +5 -1
- package/dist/{Fabric-BfnUdEpq.d.cts → Fabric-AmREkq58.d.ts} +108 -63
- package/dist/{Fabric-CxMkO4Rt.d.ts → Fabric-CBrTERuf.d.cts} +108 -63
- package/dist/{defineProperty-CspRhtP3.cjs → defineProperty-Dlhh3lSJ.cjs} +58 -44
- package/dist/defineProperty-Dlhh3lSJ.cjs.map +1 -0
- package/dist/{defineProperty-BtekiGIK.js → defineProperty-_FBdEen_.js} +53 -39
- package/dist/defineProperty-_FBdEen_.js.map +1 -0
- package/dist/index.cjs +102 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -3
- package/dist/index.d.ts +25 -3
- package/dist/index.js +102 -60
- package/dist/index.js.map +1 -1
- package/dist/parsers/typescript.d.cts +2 -2
- package/dist/parsers/typescript.d.ts +2 -2
- package/dist/parsers.cjs.map +1 -1
- package/dist/parsers.d.cts +2 -2
- package/dist/parsers.d.ts +2 -2
- package/dist/parsers.js.map +1 -1
- package/dist/plugins.cjs +98 -104
- package/dist/plugins.cjs.map +1 -1
- package/dist/plugins.d.cts +30 -40
- package/dist/plugins.d.ts +30 -40
- package/dist/plugins.js +94 -100
- package/dist/plugins.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +2 -3
- package/dist/types.d.ts +2 -3
- package/dist/types.js.map +1 -1
- package/dist/{typescriptParser-Dz9T1BQ1.d.cts → typescriptParser-C3B3dzh_.d.cts} +2 -2
- package/dist/typescriptParser-CNHO6H2_.cjs.map +1 -1
- package/dist/typescriptParser-CWT7zCJy.js.map +1 -1
- package/dist/{typescriptParser-DypTa1AN.d.ts → typescriptParser-DaOfAlmM.d.ts} +2 -2
- package/package.json +1 -1
- package/src/Fabric.ts +102 -52
- package/src/FileManager.ts +23 -6
- package/src/FileProcessor.ts +3 -4
- package/src/KubbFile.ts +0 -2
- package/src/createFile.ts +90 -74
- package/src/defineFabric.ts +53 -28
- package/src/index.ts +3 -3
- package/src/parsers/tsxParser.ts +1 -1
- package/src/parsers/types.ts +1 -1
- package/src/parsers/typescriptParser.ts +1 -1
- package/src/plugins/barrelPlugin.ts +13 -21
- package/src/plugins/fsPlugin.ts +8 -16
- package/src/plugins/graphPlugin.ts +8 -9
- package/src/plugins/index.ts +2 -3
- package/src/plugins/progressPlugin.ts +6 -6
- package/src/plugins/types.ts +1 -1
- package/src/types.ts +1 -2
- package/src/utils/AsyncEventEmitter.ts +29 -8
- package/dist/defineFabric-CR1OjcoI.d.ts +0 -9
- package/dist/defineFabric-TvKfRefj.d.cts +0 -9
- package/dist/defineProperty-BtekiGIK.js.map +0 -1
- package/dist/defineProperty-CspRhtP3.cjs.map +0 -1
- package/src/utils/EventEmitter.ts +0 -31
package/src/Fabric.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import type { FileManager } from './FileManager.ts'
|
|
1
2
|
import type * as KubbFile from './KubbFile.ts'
|
|
2
|
-
import type { Plugin } from './plugins/types.ts'
|
|
3
3
|
import type { Parser } from './parsers/types.ts'
|
|
4
|
+
import type { Plugin } from './plugins/types.ts'
|
|
4
5
|
import type { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'
|
|
5
|
-
import type { FileManager } from './FileManager.ts'
|
|
6
6
|
|
|
7
7
|
declare global {
|
|
8
8
|
namespace Kubb {
|
|
@@ -10,51 +10,61 @@ declare global {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Component placeholder type.
|
|
15
|
+
* May later be extended to support specific runtime renderers.
|
|
16
|
+
*/
|
|
13
17
|
export type Component = any
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Defines core runtime options for Fabric.
|
|
21
|
+
*/
|
|
22
|
+
export interface FabricOptions {
|
|
16
23
|
/**
|
|
24
|
+
* Determines how Fabric processes files.
|
|
25
|
+
* - `sequential`: files are processed one by one
|
|
26
|
+
* - `parallel`: files are processed concurrently
|
|
27
|
+
*
|
|
17
28
|
* @default 'sequential'
|
|
18
29
|
*/
|
|
19
30
|
mode?: FabricMode
|
|
20
31
|
}
|
|
21
32
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Available modes for file processing.
|
|
35
|
+
*/
|
|
36
|
+
export type FabricMode = 'sequential' | 'parallel'
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Event definitions emitted during the Fabric lifecycle.
|
|
40
|
+
*/
|
|
41
|
+
export interface FabricEvents {
|
|
42
|
+
/** Called at the beginning of the app lifecycle. */
|
|
26
43
|
start: []
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
*/
|
|
44
|
+
|
|
45
|
+
/** Called at the end of the app lifecycle. */
|
|
30
46
|
end: []
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
*/
|
|
47
|
+
|
|
48
|
+
/** Called when Fabric is rendering. */
|
|
34
49
|
render: [{ fabric: Fabric }]
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*/
|
|
50
|
+
|
|
51
|
+
/** Called once before any files are processed. */
|
|
38
52
|
'process:start': [{ files: KubbFile.ResolvedFile[] }]
|
|
39
|
-
/**
|
|
40
|
-
* Called when FileManager is adding files to its cache
|
|
41
|
-
*/
|
|
42
53
|
|
|
54
|
+
/** Called when files are added to the FileManager cache. */
|
|
43
55
|
'file:add': [{ files: KubbFile.ResolvedFile[] }]
|
|
56
|
+
|
|
44
57
|
'write:start': [{ files: KubbFile.ResolvedFile[] }]
|
|
45
58
|
'write:end': [{ files: KubbFile.ResolvedFile[] }]
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
*/
|
|
59
|
+
|
|
60
|
+
/** Called for each file when processing begins. */
|
|
49
61
|
'file:start': [{ file: KubbFile.ResolvedFile; index: number; total: number }]
|
|
50
62
|
|
|
51
|
-
/**
|
|
52
|
-
* Called for each file when processing finishes.
|
|
53
|
-
*/
|
|
63
|
+
/** Called for each file when processing completes. */
|
|
54
64
|
'file:end': [{ file: KubbFile.ResolvedFile; index: number; total: number }]
|
|
55
65
|
|
|
56
66
|
/**
|
|
57
|
-
* Called periodically (or
|
|
67
|
+
* Called periodically (or per file) to indicate progress.
|
|
58
68
|
* Useful for progress bars or logging.
|
|
59
69
|
*/
|
|
60
70
|
'process:progress': [
|
|
@@ -67,50 +77,90 @@ export type FabricEvents = {
|
|
|
67
77
|
},
|
|
68
78
|
]
|
|
69
79
|
|
|
70
|
-
/**
|
|
71
|
-
* Called once all files have been processed successfully.
|
|
72
|
-
*/
|
|
80
|
+
/** Called once all files have been processed successfully. */
|
|
73
81
|
'process:end': [{ files: KubbFile.ResolvedFile[] }]
|
|
74
82
|
}
|
|
75
83
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Shared context passed to all plugins, parsers, and Fabric internals.
|
|
86
|
+
*/
|
|
87
|
+
export interface FabricContext<T extends FabricOptions = FabricOptions> extends AsyncEventEmitter<FabricEvents> {
|
|
88
|
+
/** The active Fabric configuration. */
|
|
89
|
+
config?: FabricConfig<T>
|
|
90
|
+
|
|
91
|
+
/** The internal file manager handling file creation, merging, and writing. */
|
|
79
92
|
fileManager: FileManager
|
|
93
|
+
|
|
94
|
+
/** List of files currently in memory. */
|
|
95
|
+
files: KubbFile.ResolvedFile[]
|
|
96
|
+
|
|
97
|
+
/** Add new files to the file manager. */
|
|
98
|
+
addFile(...files: KubbFile.File[]): Promise<void>
|
|
99
|
+
|
|
100
|
+
/** Track installed plugins and parsers to prevent duplicates. */
|
|
80
101
|
installedPlugins: Set<Plugin>
|
|
81
102
|
installedParsers: Set<Parser>
|
|
82
103
|
}
|
|
83
104
|
|
|
84
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Base configuration object for Fabric.
|
|
107
|
+
*/
|
|
108
|
+
export interface FabricConfig<T extends FabricOptions = FabricOptions> {
|
|
109
|
+
/** The runtime options used to configure Fabric. */
|
|
110
|
+
options: T
|
|
111
|
+
}
|
|
85
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Utility type that checks whether all properties of `T` are optional.
|
|
115
|
+
*/
|
|
86
116
|
type AllOptional<T> = {} extends T ? true : false
|
|
87
117
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Defines the signature of a plugin or parser's `install` function.
|
|
120
|
+
*/
|
|
92
121
|
export type Install<TOptions = unknown> = TOptions extends any[]
|
|
93
|
-
? (
|
|
122
|
+
? (context: FabricContext, ...options: TOptions) => void | Promise<void>
|
|
94
123
|
: AllOptional<TOptions> extends true
|
|
95
|
-
? (
|
|
96
|
-
: (
|
|
124
|
+
? (context: FabricContext, options?: TOptions) => void | Promise<void>
|
|
125
|
+
: (context: FabricContext, options: TOptions) => void | Promise<void>
|
|
97
126
|
|
|
98
|
-
|
|
99
|
-
|
|
127
|
+
/**
|
|
128
|
+
* Defines the signature of a plugin or parser's `inject` function.
|
|
129
|
+
* Returns an object that extends the Fabric instance.
|
|
130
|
+
*/
|
|
131
|
+
export type Inject<TOptions = unknown, TExtension extends Record<string, any> = {}> = TOptions extends any[]
|
|
132
|
+
? (context: FabricContext, ...options: TOptions) => Partial<TExtension>
|
|
100
133
|
: AllOptional<TOptions> extends true
|
|
101
|
-
? (
|
|
102
|
-
: (
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
134
|
+
? (context: FabricContext, options?: TOptions) => Partial<TExtension>
|
|
135
|
+
: (context: FabricContext, options: TOptions) => Partial<TExtension>
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The main Fabric runtime interface.
|
|
139
|
+
* Provides access to the current context, registered plugins, files, and utility methods.
|
|
140
|
+
*/
|
|
141
|
+
export interface Fabric<T extends FabricOptions = FabricOptions> extends Kubb.Fabric {
|
|
142
|
+
/** The shared context for this Fabric instance. */
|
|
143
|
+
context: FabricContext<T>
|
|
144
|
+
|
|
145
|
+
/** The files managed by this Fabric instance. */
|
|
146
|
+
files: KubbFile.ResolvedFile[]
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Install a plugin or parser into Fabric.
|
|
150
|
+
*
|
|
151
|
+
* @param target - The plugin or parser to install.
|
|
152
|
+
* @param options - Optional configuration or arguments for the target.
|
|
153
|
+
* @returns A Fabric instance extended by the plugin (if applicable).
|
|
154
|
+
*/
|
|
155
|
+
use<TPluginOptions = unknown, TMeta extends object = object, TExtension extends Record<string, any> = {}>(
|
|
156
|
+
target: Plugin<TPluginOptions, TExtension> | Parser<TPluginOptions, TMeta>,
|
|
109
157
|
...options: TPluginOptions extends any[]
|
|
110
158
|
? NoInfer<TPluginOptions>
|
|
111
159
|
: AllOptional<TPluginOptions> extends true
|
|
112
160
|
? [NoInfer<TPluginOptions>?] // Optional when all props are optional
|
|
113
161
|
: [NoInfer<TPluginOptions>] // Required otherwise
|
|
114
|
-
): (this &
|
|
115
|
-
|
|
162
|
+
): (this & TExtension) | Promise<this & TExtension>
|
|
163
|
+
|
|
164
|
+
/** Add one or more files to the Fabric file manager. */
|
|
165
|
+
addFile(...files: KubbFile.File[]): Promise<void>
|
|
116
166
|
}
|
package/src/FileManager.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type * as KubbFile from './KubbFile.ts'
|
|
2
|
-
import { Cache } from './utils/Cache.ts'
|
|
3
|
-
import { trimExtName } from './utils/trimExtName.ts'
|
|
4
1
|
import { orderBy } from 'natural-orderby'
|
|
5
2
|
import { createFile } from './createFile.ts'
|
|
3
|
+
import type { FabricEvents } from './Fabric.ts'
|
|
6
4
|
import { FileProcessor, type ProcessFilesProps } from './FileProcessor.ts'
|
|
5
|
+
import type * as KubbFile from './KubbFile.ts'
|
|
7
6
|
import { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'
|
|
8
|
-
import
|
|
7
|
+
import { Cache } from './utils/Cache.ts'
|
|
8
|
+
import { trimExtName } from './utils/trimExtName.ts'
|
|
9
9
|
|
|
10
10
|
function mergeFile<TMeta extends object = object>(a: KubbFile.File<TMeta>, b: KubbFile.File<TMeta>): KubbFile.File<TMeta> {
|
|
11
11
|
return {
|
|
@@ -22,6 +22,7 @@ type Options = {
|
|
|
22
22
|
|
|
23
23
|
export class FileManager {
|
|
24
24
|
#cache = new Cache<KubbFile.ResolvedFile>()
|
|
25
|
+
#filesCache: Array<KubbFile.ResolvedFile> | null = null
|
|
25
26
|
events: AsyncEventEmitter<FabricEvents>
|
|
26
27
|
processor: FileProcessor
|
|
27
28
|
|
|
@@ -64,6 +65,7 @@ export class FileManager {
|
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
flush() {
|
|
68
|
+
this.#filesCache = null
|
|
67
69
|
this.#cache.flush()
|
|
68
70
|
}
|
|
69
71
|
|
|
@@ -73,21 +75,36 @@ export class FileManager {
|
|
|
73
75
|
|
|
74
76
|
deleteByPath(path: KubbFile.Path): void {
|
|
75
77
|
this.#cache.delete(path)
|
|
78
|
+
this.#filesCache = null
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
clear(): void {
|
|
79
82
|
this.#cache.clear()
|
|
83
|
+
this.#filesCache = null
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
get files(): Array<KubbFile.ResolvedFile> {
|
|
87
|
+
if (this.#filesCache) {
|
|
88
|
+
return [...this.#filesCache]
|
|
89
|
+
}
|
|
90
|
+
|
|
83
91
|
const cachedKeys = this.#cache.keys()
|
|
84
92
|
|
|
85
93
|
// order by path length and if file is a barrel file
|
|
86
94
|
const keys = orderBy(cachedKeys, [(v) => v.length, (v) => trimExtName(v).endsWith('index')])
|
|
87
95
|
|
|
88
|
-
const files
|
|
96
|
+
const files: Array<KubbFile.ResolvedFile> = []
|
|
97
|
+
|
|
98
|
+
for (const key of keys) {
|
|
99
|
+
const file = this.#cache.get(key)
|
|
100
|
+
if (file) {
|
|
101
|
+
files.push(file)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
this.#filesCache = files
|
|
89
106
|
|
|
90
|
-
return files
|
|
107
|
+
return [...files]
|
|
91
108
|
}
|
|
92
109
|
|
|
93
110
|
//TODO add test and check if write of FileManager contains the newly added file
|
package/src/FileProcessor.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type * as KubbFile from './KubbFile.ts'
|
|
2
1
|
import pLimit from 'p-limit'
|
|
3
|
-
|
|
4
|
-
import type
|
|
2
|
+
import type { FabricEvents, FabricMode } from './Fabric.ts'
|
|
3
|
+
import type * as KubbFile from './KubbFile.ts'
|
|
5
4
|
import { defaultParser } from './parsers/defaultParser.ts'
|
|
5
|
+
import type { Parser } from './parsers/types.ts'
|
|
6
6
|
import { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'
|
|
7
|
-
import type { FabricEvents, FabricMode } from './Fabric.ts'
|
|
8
7
|
|
|
9
8
|
export type ProcessFilesProps = {
|
|
10
9
|
parsers?: Set<Parser>
|
package/src/KubbFile.ts
CHANGED
|
@@ -88,8 +88,6 @@ export type Path = string
|
|
|
88
88
|
|
|
89
89
|
export type AdvancedPath<T extends BaseName = BaseName> = `${BasePath}${T}`
|
|
90
90
|
|
|
91
|
-
export type OptionalPath = Path | undefined | null
|
|
92
|
-
|
|
93
91
|
export type File<TMeta extends object = object> = {
|
|
94
92
|
/**
|
|
95
93
|
* Name to be used to create the path
|
package/src/createFile.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import type * as KubbFile from './KubbFile.ts'
|
|
2
|
-
import { trimExtName } from './utils/trimExtName.ts'
|
|
3
1
|
import { createHash } from 'node:crypto'
|
|
4
2
|
import path from 'node:path'
|
|
5
|
-
import { isDeepEqual, uniqueBy } from 'remeda'
|
|
6
3
|
import { orderBy } from 'natural-orderby'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return createHash('sha256').update(str).digest('hex')
|
|
11
|
-
}
|
|
4
|
+
import { isDeepEqual, uniqueBy } from 'remeda'
|
|
5
|
+
import type * as KubbFile from './KubbFile.ts'
|
|
6
|
+
import { trimExtName } from './utils/trimExtName.ts'
|
|
12
7
|
|
|
13
8
|
export function combineSources(sources: Array<KubbFile.Source>): Array<KubbFile.Source> {
|
|
14
9
|
return uniqueBy(sources, (obj) => [obj.name, obj.isExportable, obj.isTypeOnly] as const)
|
|
@@ -65,79 +60,100 @@ export function combineExports(exports: Array<KubbFile.Export>): Array<KubbFile.
|
|
|
65
60
|
}
|
|
66
61
|
|
|
67
62
|
export function combineImports(imports: Array<KubbFile.Import>, exports: Array<KubbFile.Export>, source?: string): Array<KubbFile.Import> {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (!source) {
|
|
80
|
-
return true
|
|
63
|
+
const exportedNameLookup = new Set<string>()
|
|
64
|
+
for (const item of exports) {
|
|
65
|
+
const { name } = item
|
|
66
|
+
if (!name) {
|
|
67
|
+
continue
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (Array.isArray(name)) {
|
|
71
|
+
for (const value of name) {
|
|
72
|
+
if (value) {
|
|
73
|
+
exportedNameLookup.add(value)
|
|
81
74
|
}
|
|
82
|
-
|
|
83
|
-
const checker = (name?: string) => {
|
|
84
|
-
return name && source.includes(name)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return checker(importName) || exports.some(({ name }) => (Array.isArray(name) ? name.some(checker) : checker(name)))
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (curr.path === curr.root) {
|
|
91
|
-
// root and path are the same file, remove the "./" import
|
|
92
|
-
return prev
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// merge all names and check if the importName is being used in the generated source and if not filter those imports out
|
|
96
|
-
if (Array.isArray(name)) {
|
|
97
|
-
name = name.filter((item) => (typeof item === 'string' ? hasImportInSource(item) : hasImportInSource(item.propertyName)))
|
|
98
75
|
}
|
|
76
|
+
continue
|
|
77
|
+
}
|
|
99
78
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const prevByPathNameAndIsTypeOnly = prev.findLast((imp) => imp.path === curr.path && isDeepEqual(imp.name, name) && imp.isTypeOnly)
|
|
103
|
-
|
|
104
|
-
if (prevByPathNameAndIsTypeOnly) {
|
|
105
|
-
// we already have an export that has the same path but uses `isTypeOnly` (import type ...)
|
|
106
|
-
return prev
|
|
107
|
-
}
|
|
79
|
+
exportedNameLookup.add(name)
|
|
80
|
+
}
|
|
108
81
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
82
|
+
const usageCache = new Map<string, boolean>()
|
|
83
|
+
const hasImportInSource = (importName: string): boolean => {
|
|
84
|
+
if (!source) {
|
|
85
|
+
return true
|
|
86
|
+
}
|
|
113
87
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
{
|
|
119
|
-
...curr,
|
|
120
|
-
name,
|
|
121
|
-
},
|
|
122
|
-
]
|
|
123
|
-
}
|
|
88
|
+
const cached = usageCache.get(importName)
|
|
89
|
+
if (cached !== undefined) {
|
|
90
|
+
return cached
|
|
91
|
+
}
|
|
124
92
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
prevByPath.name = [...new Set([...prevByPath.name, ...name])]
|
|
93
|
+
const isUsed = source.includes(importName) || exportedNameLookup.has(importName)
|
|
94
|
+
usageCache.set(importName, isUsed)
|
|
128
95
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
// no import was found in the source, ignore import
|
|
133
|
-
if (!Array.isArray(name) && name && !hasImportInSource(name)) {
|
|
134
|
-
return prev
|
|
135
|
-
}
|
|
96
|
+
return isUsed
|
|
97
|
+
}
|
|
136
98
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
99
|
+
return orderBy(imports, [
|
|
100
|
+
(v) => !!Array.isArray(v.name),
|
|
101
|
+
(v) => !v.isTypeOnly,
|
|
102
|
+
(v) => v.path,
|
|
103
|
+
(v) => !!v.name,
|
|
104
|
+
(v) => (Array.isArray(v.name) ? orderBy(v.name) : v.name),
|
|
105
|
+
]).reduce<Array<KubbFile.Import>>((prev, curr) => {
|
|
106
|
+
let name = Array.isArray(curr.name) ? [...new Set(curr.name)] : curr.name
|
|
107
|
+
|
|
108
|
+
if (curr.path === curr.root) {
|
|
109
|
+
// root and path are the same file, remove the "./" import
|
|
110
|
+
return prev
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// merge all names and check if the importName is being used in the generated source and if not filter those imports out
|
|
114
|
+
if (Array.isArray(name)) {
|
|
115
|
+
name = name.filter((item) => (typeof item === 'string' ? hasImportInSource(item) : hasImportInSource(item.propertyName)))
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const prevByPath = prev.findLast((imp) => imp.path === curr.path && imp.isTypeOnly === curr.isTypeOnly)
|
|
119
|
+
const uniquePrev = prev.findLast((imp) => imp.path === curr.path && isDeepEqual(imp.name, name) && imp.isTypeOnly === curr.isTypeOnly)
|
|
120
|
+
const prevByPathNameAndIsTypeOnly = prev.findLast((imp) => imp.path === curr.path && isDeepEqual(imp.name, name) && imp.isTypeOnly)
|
|
121
|
+
|
|
122
|
+
if (prevByPathNameAndIsTypeOnly) {
|
|
123
|
+
// we already have an export that has the same path but uses `isTypeOnly` (import type ...)
|
|
124
|
+
return prev
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// already unique enough or name is empty
|
|
128
|
+
if (uniquePrev || (Array.isArray(name) && !name.length)) {
|
|
129
|
+
return prev
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// new item, append name
|
|
133
|
+
if (!prevByPath) {
|
|
134
|
+
return [
|
|
135
|
+
...prev,
|
|
136
|
+
{
|
|
137
|
+
...curr,
|
|
138
|
+
name,
|
|
139
|
+
},
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// merge all names when prev and current both have the same isTypeOnly set
|
|
144
|
+
if (prevByPath && Array.isArray(prevByPath.name) && Array.isArray(name) && prevByPath.isTypeOnly === curr.isTypeOnly) {
|
|
145
|
+
prevByPath.name = [...new Set([...prevByPath.name, ...name])]
|
|
146
|
+
|
|
147
|
+
return prev
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// no import was found in the source, ignore import
|
|
151
|
+
if (!Array.isArray(name) && name && !hasImportInSource(name)) {
|
|
152
|
+
return prev
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return [...prev, curr]
|
|
156
|
+
}, [])
|
|
141
157
|
}
|
|
142
158
|
|
|
143
159
|
/**
|
|
@@ -156,7 +172,7 @@ export function createFile<TMeta extends object = object>(file: KubbFile.File<TM
|
|
|
156
172
|
|
|
157
173
|
return {
|
|
158
174
|
...file,
|
|
159
|
-
id:
|
|
175
|
+
id: createHash('sha256').update(file.path).digest('hex'),
|
|
160
176
|
name: trimExtName(file.baseName),
|
|
161
177
|
extname,
|
|
162
178
|
imports: imports,
|
package/src/defineFabric.ts
CHANGED
|
@@ -1,79 +1,104 @@
|
|
|
1
|
-
import { FileManager } from './FileManager.ts'
|
|
2
1
|
import { isFunction } from 'remeda'
|
|
3
|
-
import type {
|
|
2
|
+
import type { Fabric, FabricConfig, FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'
|
|
3
|
+
import { FileManager } from './FileManager.ts'
|
|
4
4
|
import type { Parser } from './parsers/types.ts'
|
|
5
|
+
import type { Plugin } from './plugins/types.ts'
|
|
5
6
|
import { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'
|
|
6
|
-
import type { FabricConfig, FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'
|
|
7
|
-
|
|
8
|
-
import type { Fabric } from './Fabric.ts'
|
|
9
7
|
|
|
10
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Function that initializes the root Fabric instance.
|
|
10
|
+
*
|
|
11
|
+
* Used for setting up plugins, parsers, or performing side effects
|
|
12
|
+
* once the Fabric context is ready.
|
|
13
|
+
*/
|
|
14
|
+
type FabricInitializer<T extends FabricOptions> = (fabric: Fabric<T>) => void | Promise<void>
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
/**
|
|
17
|
+
* A function returned by {@link defineFabric} that creates a Fabric instance.
|
|
18
|
+
*/
|
|
19
|
+
export type CreateFabric<T extends FabricOptions> = (config?: FabricConfig<T>) => Fabric<T>
|
|
13
20
|
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Defines a new Fabric factory function.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* export const createFabric = defineFabric((fabric) => {
|
|
26
|
+
* fabric.use(myPlugin())
|
|
27
|
+
* })
|
|
28
|
+
*/
|
|
29
|
+
export function defineFabric<T extends FabricOptions>(init?: FabricInitializer<T>): CreateFabric<T> {
|
|
30
|
+
function create(config?: FabricConfig<T>): Fabric<T> {
|
|
16
31
|
const events = new AsyncEventEmitter<FabricEvents>()
|
|
17
32
|
const installedPlugins = new Set<Plugin<any>>()
|
|
18
33
|
const installedParsers = new Set<Parser<any>>()
|
|
19
34
|
const fileManager = new FileManager({ events })
|
|
20
|
-
|
|
21
|
-
|
|
35
|
+
|
|
36
|
+
const context: FabricContext<T> = {
|
|
37
|
+
get files() {
|
|
38
|
+
return fileManager.files
|
|
39
|
+
},
|
|
40
|
+
async addFile(...files) {
|
|
41
|
+
await fileManager.add(...files)
|
|
42
|
+
},
|
|
22
43
|
config,
|
|
23
44
|
fileManager,
|
|
24
45
|
installedPlugins,
|
|
25
46
|
installedParsers,
|
|
26
|
-
|
|
47
|
+
on: events.on.bind(events),
|
|
48
|
+
off: events.off.bind(events),
|
|
49
|
+
onOnce: events.onOnce.bind(events),
|
|
50
|
+
removeAll: events.removeAll.bind(events),
|
|
51
|
+
emit: events.emit.bind(events),
|
|
52
|
+
} as FabricContext<T>
|
|
27
53
|
|
|
28
|
-
const fabric = {
|
|
54
|
+
const fabric: Fabric<T> = {
|
|
29
55
|
context,
|
|
30
56
|
get files() {
|
|
31
57
|
return fileManager.files
|
|
32
58
|
},
|
|
33
|
-
async addFile(...
|
|
34
|
-
await fileManager.add(...
|
|
59
|
+
async addFile(...files) {
|
|
60
|
+
await fileManager.add(...files)
|
|
35
61
|
},
|
|
36
62
|
async use(pluginOrParser, ...options) {
|
|
37
|
-
const args = options
|
|
38
|
-
|
|
39
63
|
if (pluginOrParser.type === 'plugin') {
|
|
40
64
|
if (installedPlugins.has(pluginOrParser)) {
|
|
41
|
-
console.warn(`Plugin ${pluginOrParser.name}
|
|
65
|
+
console.warn(`Plugin "${pluginOrParser.name}" already applied.`)
|
|
42
66
|
} else {
|
|
43
67
|
installedPlugins.add(pluginOrParser)
|
|
44
68
|
}
|
|
45
69
|
|
|
46
|
-
if (
|
|
70
|
+
if (isFunction(pluginOrParser.inject)) {
|
|
47
71
|
const injecter = pluginOrParser.inject
|
|
48
72
|
|
|
49
|
-
const
|
|
50
|
-
Object.assign(fabric,
|
|
73
|
+
const injected = (injecter as any)(context, ...options)
|
|
74
|
+
Object.assign(fabric, injected)
|
|
51
75
|
}
|
|
52
76
|
}
|
|
77
|
+
|
|
53
78
|
if (pluginOrParser.type === 'parser') {
|
|
54
79
|
if (installedParsers.has(pluginOrParser)) {
|
|
55
|
-
console.warn(`Parser ${pluginOrParser.name}
|
|
80
|
+
console.warn(`Parser "${pluginOrParser.name}" already applied.`)
|
|
56
81
|
} else {
|
|
57
82
|
installedParsers.add(pluginOrParser)
|
|
58
83
|
}
|
|
59
84
|
}
|
|
60
85
|
|
|
61
|
-
if (
|
|
86
|
+
if (isFunction(pluginOrParser.install)) {
|
|
62
87
|
const installer = pluginOrParser.install
|
|
63
88
|
|
|
64
|
-
await (installer as any)(
|
|
89
|
+
await (installer as any)(context, ...options)
|
|
65
90
|
}
|
|
66
91
|
|
|
67
92
|
return fabric
|
|
68
93
|
},
|
|
69
|
-
} as Fabric<
|
|
94
|
+
} as Fabric<T>
|
|
70
95
|
|
|
71
|
-
if (
|
|
72
|
-
|
|
96
|
+
if (init) {
|
|
97
|
+
init(fabric)
|
|
73
98
|
}
|
|
74
99
|
|
|
75
100
|
return fabric
|
|
76
101
|
}
|
|
77
102
|
|
|
78
|
-
return
|
|
103
|
+
return create
|
|
79
104
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { createFabric } from './createFabric.ts'
|
|
2
|
-
export { defineFabric } from './defineFabric.ts'
|
|
3
|
-
export { FileManager } from './FileManager.ts'
|
|
4
2
|
export { createFile } from './createFile.ts'
|
|
5
|
-
export {
|
|
3
|
+
export { defineFabric } from './defineFabric.ts'
|
|
6
4
|
// we need this to override the globals of `fabric.use`
|
|
7
5
|
export type { Fabric } from './Fabric.ts'
|
|
6
|
+
export { FileManager } from './FileManager.ts'
|
|
7
|
+
export { FileProcessor } from './FileProcessor.ts'
|
package/src/parsers/tsxParser.ts
CHANGED
package/src/parsers/types.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
1
2
|
import ts from 'typescript'
|
|
2
3
|
import { getRelativePath } from '../utils/getRelativePath.ts'
|
|
3
4
|
import { trimExtName } from '../utils/trimExtName.ts'
|
|
4
|
-
import path from 'node:path'
|
|
5
5
|
import { createParser } from './createParser.ts'
|
|
6
6
|
|
|
7
7
|
const { factory } = ts
|