@kubb/fabric-core 0.2.18 → 0.3.0
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/{Fabric-CVe8cc8b.d.ts → Fabric-RmoYWGrr.d.cts} +4 -4
- package/dist/{Fabric-BezqNTQ9.d.cts → Fabric-cIhiQpgN.d.ts} +4 -4
- package/dist/defineProperty-DwFON4j7.cjs +367 -0
- package/dist/defineProperty-DwFON4j7.cjs.map +1 -0
- package/dist/defineProperty-fiNt9UhD.js +325 -0
- package/dist/defineProperty-fiNt9UhD.js.map +1 -0
- package/dist/{getRelativePath-C6lvNCs7.cjs → getRelativePath-eCdp2Z8M.cjs} +1 -2
- package/dist/{getRelativePath-C6lvNCs7.cjs.map → getRelativePath-eCdp2Z8M.cjs.map} +1 -1
- package/dist/index.cjs +26 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +26 -25
- package/dist/index.js.map +1 -1
- package/dist/parsers/typescript.cjs +2 -2
- package/dist/parsers/typescript.d.cts +2 -2
- package/dist/parsers/typescript.d.ts +2 -2
- package/dist/parsers/typescript.js +1 -1
- package/dist/parsers.cjs +2 -2
- package/dist/parsers.d.cts +2 -2
- package/dist/parsers.d.ts +2 -2
- package/dist/parsers.js +1 -1
- package/dist/plugins.cjs +79 -46
- package/dist/plugins.cjs.map +1 -1
- package/dist/plugins.d.cts +1 -1
- package/dist/plugins.d.ts +1 -1
- package/dist/plugins.js +78 -43
- package/dist/plugins.js.map +1 -1
- package/dist/types.d.cts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/{typescriptParser-CWT7zCJy.js → typescriptParser-BFhqWjdo.js} +20 -35
- package/dist/typescriptParser-BFhqWjdo.js.map +1 -0
- package/dist/{typescriptParser-B5SxjtvV.d.ts → typescriptParser-BjqVuRHF.d.cts} +3 -14
- package/dist/{typescriptParser-PfAO0SSm.d.cts → typescriptParser-Cy9_9o6I.d.ts} +3 -14
- package/dist/{typescriptParser-CNHO6H2_.cjs → typescriptParser-DJxEGCz3.cjs} +21 -36
- package/dist/typescriptParser-DJxEGCz3.cjs.map +1 -0
- package/package.json +1 -1
- package/src/Fabric.ts +1 -1
- package/src/FileManager.ts +8 -8
- package/src/FileProcessor.ts +8 -15
- package/src/createFile.ts +110 -57
- package/src/defineFabric.ts +15 -3
- package/src/parsers/typescriptParser.ts +33 -50
- package/src/plugins/barrelPlugin.ts +63 -36
- package/src/utils/TreeNode.ts +54 -27
- package/dist/defineProperty-DZi5DvrW.cjs +0 -390
- package/dist/defineProperty-DZi5DvrW.cjs.map +0 -1
- package/dist/defineProperty-DcP1vZ2K.js +0 -346
- package/dist/defineProperty-DcP1vZ2K.js.map +0 -1
- package/dist/typescriptParser-CNHO6H2_.cjs.map +0 -1
- package/dist/typescriptParser-CWT7zCJy.js.map +0 -1
|
@@ -6,29 +6,11 @@ import { createParser } from './createParser.ts'
|
|
|
6
6
|
|
|
7
7
|
const { factory } = ts
|
|
8
8
|
|
|
9
|
-
type PrintOptions = {
|
|
10
|
-
source?: string
|
|
11
|
-
baseName?: string
|
|
12
|
-
scriptKind?: ts.ScriptKind
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Escaped new lines in code with block comments so they can be restored by {@link restoreNewLines}
|
|
17
|
-
*/
|
|
18
|
-
const escapeNewLines = (code: string) => code.replace(/\n\n/g, '\n/* :newline: */')
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Reverses {@link escapeNewLines} and restores new lines
|
|
22
|
-
*/
|
|
23
|
-
const restoreNewLines = (code: string) => code.replace(/\/\* :newline: \*\//g, '\n')
|
|
24
|
-
|
|
25
9
|
/**
|
|
26
10
|
* Convert AST TypeScript/TSX nodes to a string based on the TypeScript printer.
|
|
27
|
-
* Ensures consistent output across environments.
|
|
28
|
-
* Also works as a formatter when `source` is provided without `elements`.
|
|
29
11
|
*/
|
|
30
|
-
export function print(elements: Array<ts.Node>
|
|
31
|
-
const sourceFile = ts.createSourceFile(
|
|
12
|
+
export function print(...elements: Array<ts.Node>): string {
|
|
13
|
+
const sourceFile = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)
|
|
32
14
|
|
|
33
15
|
const printer = ts.createPrinter({
|
|
34
16
|
omitTrailingSemicolon: true,
|
|
@@ -37,18 +19,9 @@ export function print(elements: Array<ts.Node> = [], { source = '', baseName = '
|
|
|
37
19
|
noEmitHelpers: true,
|
|
38
20
|
})
|
|
39
21
|
|
|
40
|
-
|
|
22
|
+
const output = printer.printList(ts.ListFormat.MultiLine, factory.createNodeArray(elements), sourceFile)
|
|
41
23
|
|
|
42
|
-
|
|
43
|
-
// Print only provided nodes
|
|
44
|
-
const nodes = elements.filter(Boolean).sort((a, b) => (a.pos ?? 0) - (b.pos ?? 0))
|
|
45
|
-
output = printer.printList(ts.ListFormat.MultiLine, factory.createNodeArray(nodes), sourceFile)
|
|
46
|
-
} else {
|
|
47
|
-
// Format the whole file
|
|
48
|
-
output = printer.printFile(sourceFile)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return restoreNewLines(output).replace(/\r\n/g, '\n')
|
|
24
|
+
return output.replace(/\r\n/g, '\n')
|
|
52
25
|
}
|
|
53
26
|
|
|
54
27
|
export function createImport({
|
|
@@ -153,36 +126,46 @@ export const typescriptParser = createParser({
|
|
|
153
126
|
extNames: ['.ts', '.js'],
|
|
154
127
|
install() {},
|
|
155
128
|
async parse(file, options = { extname: '.ts' }) {
|
|
156
|
-
const
|
|
129
|
+
const sourceParts: Array<string> = []
|
|
130
|
+
for (const item of file.sources) {
|
|
131
|
+
if (item.value) {
|
|
132
|
+
sourceParts.push(item.value)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const source = sourceParts.join('\n\n')
|
|
157
136
|
|
|
158
|
-
const importNodes =
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
137
|
+
const importNodes: Array<ts.ImportDeclaration> = []
|
|
138
|
+
for (const item of file.imports) {
|
|
139
|
+
const importPath = item.root ? getRelativePath(item.root, item.path) : item.path
|
|
140
|
+
const hasExtname = !!path.extname(importPath)
|
|
162
141
|
|
|
163
|
-
|
|
142
|
+
importNodes.push(
|
|
143
|
+
createImport({
|
|
164
144
|
name: item.name,
|
|
165
145
|
path: options.extname && hasExtname ? `${trimExtName(importPath)}${options.extname}` : item.root ? trimExtName(importPath) : importPath,
|
|
166
146
|
isTypeOnly: item.isTypeOnly,
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const exportNodes = file.exports
|
|
172
|
-
.map((item) => {
|
|
173
|
-
const exportPath = item.path
|
|
147
|
+
}),
|
|
148
|
+
)
|
|
149
|
+
}
|
|
174
150
|
|
|
175
|
-
|
|
151
|
+
const exportNodes: Array<ts.ExportDeclaration> = []
|
|
152
|
+
for (const item of file.exports) {
|
|
153
|
+
const exportPath = item.path
|
|
154
|
+
const hasExtname = !!path.extname(exportPath)
|
|
176
155
|
|
|
177
|
-
|
|
156
|
+
exportNodes.push(
|
|
157
|
+
createExport({
|
|
178
158
|
name: item.name,
|
|
179
159
|
path: options.extname && hasExtname ? `${trimExtName(item.path)}${options.extname}` : trimExtName(item.path),
|
|
180
160
|
isTypeOnly: item.isTypeOnly,
|
|
181
161
|
asAlias: item.asAlias,
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
|
|
162
|
+
}),
|
|
163
|
+
)
|
|
164
|
+
}
|
|
185
165
|
|
|
186
|
-
|
|
166
|
+
const parts = [file.banner, print(...importNodes, ...exportNodes), source, file.footer].filter(
|
|
167
|
+
(segment): segment is string => segment != null,
|
|
168
|
+
)
|
|
169
|
+
return parts.join('\n')
|
|
187
170
|
},
|
|
188
171
|
})
|
|
@@ -50,6 +50,20 @@ export function getBarrelFiles({ files, root, mode }: GetBarrelFilesOptions): Ar
|
|
|
50
50
|
return []
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
const indexableSourcesMap = new Map<KubbFile.File, Array<KubbFile.Source>>()
|
|
54
|
+
|
|
55
|
+
for (const file of files) {
|
|
56
|
+
const indexableSources: Array<KubbFile.Source> = []
|
|
57
|
+
for (const source of file.sources || []) {
|
|
58
|
+
if (source.isIndexable && source.name) {
|
|
59
|
+
indexableSources.push(source)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (indexableSources.length > 0) {
|
|
63
|
+
indexableSourcesMap.set(file, indexableSources)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
53
67
|
const cachedFiles = new Map<KubbFile.Path, KubbFile.File>()
|
|
54
68
|
const dedupe = new Map<KubbFile.Path, Set<string>>()
|
|
55
69
|
|
|
@@ -82,41 +96,40 @@ export function getBarrelFiles({ files, root, mode }: GetBarrelFilesOptions): Ar
|
|
|
82
96
|
|
|
83
97
|
const seen = dedupe.get(barrelPath)!
|
|
84
98
|
|
|
85
|
-
|
|
86
|
-
node.leaves.forEach((leaf) => {
|
|
99
|
+
for (const leaf of node.leaves) {
|
|
87
100
|
const file = leaf.data.file
|
|
88
|
-
if (!file) {
|
|
89
|
-
|
|
101
|
+
if (!file || !file.path) {
|
|
102
|
+
continue
|
|
90
103
|
}
|
|
91
104
|
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
105
|
+
const indexableSources = indexableSourcesMap.get(file)
|
|
106
|
+
if (!indexableSources) {
|
|
107
|
+
continue
|
|
108
|
+
}
|
|
97
109
|
|
|
110
|
+
for (const source of indexableSources) {
|
|
98
111
|
const key = `${source.name}|${source.isTypeOnly ? '1' : '0'}`
|
|
99
112
|
if (seen.has(key)) {
|
|
100
|
-
|
|
113
|
+
continue
|
|
101
114
|
}
|
|
102
115
|
seen.add(key)
|
|
103
116
|
|
|
104
117
|
// Always compute relative path from the parent directory to the file path
|
|
105
118
|
barrelFile!.exports!.push({
|
|
106
|
-
name: [source.name],
|
|
119
|
+
name: [source.name!],
|
|
107
120
|
path: getRelativePath(parentPath, file.path),
|
|
108
121
|
isTypeOnly: source.isTypeOnly,
|
|
109
122
|
})
|
|
110
123
|
|
|
111
124
|
barrelFile!.sources.push({
|
|
112
|
-
name: source.name
|
|
125
|
+
name: source.name!,
|
|
113
126
|
isTypeOnly: source.isTypeOnly,
|
|
114
127
|
value: '', // TODO use parser to generate import
|
|
115
128
|
isExportable: mode === 'all' || mode === 'named',
|
|
116
129
|
isIndexable: mode === 'all' || mode === 'named',
|
|
117
130
|
})
|
|
118
|
-
}
|
|
119
|
-
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
120
133
|
})
|
|
121
134
|
|
|
122
135
|
const result = [...cachedFiles.values()]
|
|
@@ -162,32 +175,46 @@ export const barrelPlugin = createPlugin<Options, ExtendOptions>({
|
|
|
162
175
|
|
|
163
176
|
const rootPath = path.resolve(root, 'index.ts')
|
|
164
177
|
|
|
165
|
-
const barrelFiles
|
|
166
|
-
|
|
167
|
-
|
|
178
|
+
const barrelFiles: Array<KubbFile.ResolvedFile> = []
|
|
179
|
+
for (const file of ctx.files) {
|
|
180
|
+
for (const source of file.sources) {
|
|
181
|
+
if (source.isIndexable) {
|
|
182
|
+
barrelFiles.push(file)
|
|
183
|
+
|
|
184
|
+
break
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const fileTypeCache = new Map<KubbFile.ResolvedFile, boolean>()
|
|
190
|
+
for (const file of barrelFiles) {
|
|
191
|
+
fileTypeCache.set(
|
|
192
|
+
file,
|
|
193
|
+
file.sources.every((source) => source.isTypeOnly),
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const exports: Array<KubbFile.Export> = []
|
|
198
|
+
for (const file of barrelFiles) {
|
|
199
|
+
const containsOnlyTypes = fileTypeCache.get(file) ?? false
|
|
200
|
+
|
|
201
|
+
for (const source of file.sources) {
|
|
202
|
+
if (!file.path || !source.isIndexable) {
|
|
203
|
+
continue
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
exports.push({
|
|
207
|
+
name: mode === 'all' ? undefined : [source.name],
|
|
208
|
+
path: getRelativePath(rootPath, file.path),
|
|
209
|
+
isTypeOnly: mode === 'all' ? containsOnlyTypes : source.isTypeOnly,
|
|
210
|
+
} as KubbFile.Export)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
168
213
|
|
|
169
214
|
const entryFile = createFile({
|
|
170
215
|
path: rootPath,
|
|
171
216
|
baseName: 'index.ts',
|
|
172
|
-
exports
|
|
173
|
-
.flatMap((file) => {
|
|
174
|
-
const containsOnlyTypes = file.sources.every((source) => source.isTypeOnly)
|
|
175
|
-
|
|
176
|
-
return file.sources
|
|
177
|
-
?.map((source) => {
|
|
178
|
-
if (!file.path || !source.isIndexable) {
|
|
179
|
-
return undefined
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
return {
|
|
183
|
-
name: mode === 'all' ? undefined : [source.name],
|
|
184
|
-
path: getRelativePath(rootPath, file.path),
|
|
185
|
-
isTypeOnly: mode === 'all' ? containsOnlyTypes : source.isTypeOnly,
|
|
186
|
-
} as KubbFile.Export
|
|
187
|
-
})
|
|
188
|
-
.filter(Boolean)
|
|
189
|
-
})
|
|
190
|
-
.filter(Boolean),
|
|
217
|
+
exports,
|
|
191
218
|
sources: [],
|
|
192
219
|
})
|
|
193
220
|
|
package/src/utils/TreeNode.ts
CHANGED
|
@@ -15,6 +15,7 @@ export class TreeNode<TData = unknown> {
|
|
|
15
15
|
data: TData
|
|
16
16
|
parent?: TreeNode<TData>
|
|
17
17
|
children: Array<TreeNode<TData>> = []
|
|
18
|
+
#childrenMap = new Map<string, TreeNode<TData>>()
|
|
18
19
|
#cachedLeaves?: Array<TreeNode<TData>>
|
|
19
20
|
|
|
20
21
|
constructor(data: TData, parent?: TreeNode<TData>) {
|
|
@@ -25,20 +26,35 @@ export class TreeNode<TData = unknown> {
|
|
|
25
26
|
addChild(data: TData): TreeNode<TData> {
|
|
26
27
|
const child = new TreeNode(data, this)
|
|
27
28
|
this.children.push(child)
|
|
29
|
+
// Update Map if data has a name property (for BarrelData)
|
|
30
|
+
if (typeof data === 'object' && data !== null && 'name' in data) {
|
|
31
|
+
this.#childrenMap.set((data as { name: string }).name, child)
|
|
32
|
+
}
|
|
28
33
|
this.#cachedLeaves = undefined // invalidate cached leaves
|
|
29
34
|
return child
|
|
30
35
|
}
|
|
31
36
|
|
|
37
|
+
getChildByName(name: string): TreeNode<TData> | undefined {
|
|
38
|
+
return this.#childrenMap.get(name)
|
|
39
|
+
}
|
|
40
|
+
|
|
32
41
|
get leaves(): Array<TreeNode<TData>> {
|
|
33
42
|
if (this.#cachedLeaves) return this.#cachedLeaves
|
|
34
43
|
if (this.children.length === 0) return [this]
|
|
35
44
|
|
|
36
|
-
const stack: Array<TreeNode<TData>> = [...this.children]
|
|
37
45
|
const result: Array<TreeNode<TData>> = []
|
|
46
|
+
const stack: Array<TreeNode<TData>> = [...this.children]
|
|
47
|
+
const visited = new Set<TreeNode<TData>>()
|
|
38
48
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
49
|
+
while (stack.length > 0) {
|
|
50
|
+
const node = stack.pop()!
|
|
51
|
+
if (visited.has(node)) {
|
|
52
|
+
continue
|
|
53
|
+
}
|
|
54
|
+
visited.add(node)
|
|
55
|
+
|
|
56
|
+
if (node.children.length > 0) {
|
|
57
|
+
stack.push(...node.children)
|
|
42
58
|
} else {
|
|
43
59
|
result.push(node)
|
|
44
60
|
}
|
|
@@ -51,12 +67,15 @@ export class TreeNode<TData = unknown> {
|
|
|
51
67
|
forEach(callback: (node: TreeNode<TData>) => void): this {
|
|
52
68
|
const stack: Array<TreeNode<TData>> = [this]
|
|
53
69
|
|
|
54
|
-
for (
|
|
70
|
+
for (let i = 0; i < stack.length; i++) {
|
|
71
|
+
const node = stack[i]!
|
|
55
72
|
callback(node)
|
|
56
|
-
|
|
57
|
-
|
|
73
|
+
|
|
74
|
+
if (node.children.length > 0) {
|
|
75
|
+
stack.push(...node.children)
|
|
58
76
|
}
|
|
59
77
|
}
|
|
78
|
+
|
|
60
79
|
return this
|
|
61
80
|
}
|
|
62
81
|
|
|
@@ -71,19 +90,28 @@ export class TreeNode<TData = unknown> {
|
|
|
71
90
|
const nodes: Array<{ id: string; label: string }> = []
|
|
72
91
|
const edges: Array<{ from: string; to: string }> = []
|
|
73
92
|
|
|
74
|
-
|
|
93
|
+
const stack: Array<TreeNode<BarrelData>> = [root]
|
|
94
|
+
|
|
95
|
+
for (let i = 0; i < stack.length; i++) {
|
|
96
|
+
const node = stack[i]!
|
|
97
|
+
|
|
75
98
|
nodes.push({
|
|
76
99
|
id: node.data.path,
|
|
77
100
|
label: node.data.name,
|
|
78
101
|
})
|
|
79
102
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
103
|
+
const children = node.children
|
|
104
|
+
if (children.length > 0) {
|
|
105
|
+
for (let j = 0, len = children.length; j < len; j++) {
|
|
106
|
+
const child = children[j]!
|
|
107
|
+
edges.push({
|
|
108
|
+
from: node.data.path,
|
|
109
|
+
to: child.data.path,
|
|
110
|
+
})
|
|
111
|
+
stack.push(child)
|
|
112
|
+
}
|
|
85
113
|
}
|
|
86
|
-
}
|
|
114
|
+
}
|
|
87
115
|
|
|
88
116
|
return { nodes, edges }
|
|
89
117
|
}
|
|
@@ -93,11 +121,15 @@ export class TreeNode<TData = unknown> {
|
|
|
93
121
|
const normalizedRoot = normalizePath(rootFolder)
|
|
94
122
|
const rootPrefix = normalizedRoot.endsWith('/') ? normalizedRoot : `${normalizedRoot}/`
|
|
95
123
|
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
124
|
+
const normalizedPaths = new Map<KubbFile.File, string>()
|
|
125
|
+
const filteredFiles: Array<KubbFile.File> = []
|
|
126
|
+
for (const file of files) {
|
|
127
|
+
const filePath = normalizedPaths.get(file) ?? normalizePath(file.path)
|
|
128
|
+
normalizedPaths.set(file, filePath)
|
|
129
|
+
if (!filePath.endsWith('.json') && (!rootFolder || filePath.startsWith(rootPrefix))) {
|
|
130
|
+
filteredFiles.push(file)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
101
133
|
|
|
102
134
|
if (filteredFiles.length === 0) {
|
|
103
135
|
return null
|
|
@@ -110,7 +142,8 @@ export class TreeNode<TData = unknown> {
|
|
|
110
142
|
})
|
|
111
143
|
|
|
112
144
|
for (const file of filteredFiles) {
|
|
113
|
-
const
|
|
145
|
+
const filePath = normalizedPaths.get(file)!
|
|
146
|
+
const relPath = filePath.slice(rootPrefix.length)
|
|
114
147
|
const parts = relPath.split('/')
|
|
115
148
|
|
|
116
149
|
let current = treeNode
|
|
@@ -120,13 +153,7 @@ export class TreeNode<TData = unknown> {
|
|
|
120
153
|
const isLast = index === parts.length - 1
|
|
121
154
|
currentPath += (currentPath.endsWith('/') ? '' : '/') + part
|
|
122
155
|
|
|
123
|
-
let next
|
|
124
|
-
for (const child of current.children) {
|
|
125
|
-
if ((child.data as BarrelData).name === part) {
|
|
126
|
-
next = child
|
|
127
|
-
break
|
|
128
|
-
}
|
|
129
|
-
}
|
|
156
|
+
let next = current.getChildByName(part)
|
|
130
157
|
|
|
131
158
|
if (!next) {
|
|
132
159
|
next = current.addChild({
|