@kubb/fabric-core 0.5.3 → 0.5.5

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.
Files changed (65) hide show
  1. package/README.md +21 -23
  2. package/dist/{Fabric-BzIhBn8t.d.cts → Fabric-CtqeUUFU.d.ts} +24 -25
  3. package/dist/{Fabric-igvWKffO.d.ts → Fabric-DlBN6CDR.d.cts} +24 -25
  4. package/dist/{defaultParser-n9VW2iVf.cjs → defaultParser-CIF-0xIK.cjs} +3 -3
  5. package/dist/{defaultParser-n9VW2iVf.cjs.map → defaultParser-CIF-0xIK.cjs.map} +1 -1
  6. package/dist/{defaultParser-Csot2aaT.js → defaultParser-DPHcM2NR.js} +3 -3
  7. package/dist/{defaultParser-Csot2aaT.js.map → defaultParser-DPHcM2NR.js.map} +1 -1
  8. package/dist/defineParser-Bxv4mb-N.js +11 -0
  9. package/dist/{createParser-D_ANHZTa.js.map → defineParser-Bxv4mb-N.js.map} +1 -1
  10. package/dist/defineParser-DODGK4rM.cjs +17 -0
  11. package/dist/{createParser-C4IkyTs5.cjs.map → defineParser-DODGK4rM.cjs.map} +1 -1
  12. package/dist/{defineProperty-Bhq3jwZe.cjs → defineProperty-BOlj8-IY.cjs} +10 -10
  13. package/dist/{defineProperty-Bhq3jwZe.cjs.map → defineProperty-BOlj8-IY.cjs.map} +1 -1
  14. package/dist/{defineProperty-BQu382bn.js → defineProperty-D2uejjT1.js} +10 -10
  15. package/dist/{defineProperty-BQu382bn.js.map → defineProperty-D2uejjT1.js.map} +1 -1
  16. package/dist/index.cjs +77 -87
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +7 -22
  19. package/dist/index.d.ts +7 -22
  20. package/dist/index.js +78 -87
  21. package/dist/index.js.map +1 -1
  22. package/dist/parsers/typescript.cjs +2 -2
  23. package/dist/parsers/typescript.d.cts +2 -2
  24. package/dist/parsers/typescript.d.ts +2 -2
  25. package/dist/parsers/typescript.js +2 -2
  26. package/dist/parsers.cjs +5 -5
  27. package/dist/parsers.cjs.map +1 -1
  28. package/dist/parsers.d.cts +6 -6
  29. package/dist/parsers.d.ts +6 -6
  30. package/dist/parsers.js +5 -5
  31. package/dist/parsers.js.map +1 -1
  32. package/dist/plugins.cjs +37 -37
  33. package/dist/plugins.cjs.map +1 -1
  34. package/dist/plugins.d.cts +4 -4
  35. package/dist/plugins.d.ts +4 -4
  36. package/dist/plugins.js +37 -37
  37. package/dist/plugins.js.map +1 -1
  38. package/dist/types.d.cts +1 -1
  39. package/dist/types.d.ts +1 -1
  40. package/dist/{typescriptParser-BN1vEX-I.d.ts → typescriptParser-BAlwCe3a.d.ts} +2 -2
  41. package/dist/{typescriptParser-Cw2wm0gX.js → typescriptParser-BLX7eX2k.js} +3 -3
  42. package/dist/{typescriptParser-Cw2wm0gX.js.map → typescriptParser-BLX7eX2k.js.map} +1 -1
  43. package/dist/{typescriptParser-BlRK18rx.d.cts → typescriptParser-CnzxSeDN.d.cts} +2 -2
  44. package/dist/{typescriptParser-DRdx9q2o.cjs → typescriptParser-OjFZ_DeI.cjs} +3 -3
  45. package/dist/{typescriptParser-DRdx9q2o.cjs.map → typescriptParser-OjFZ_DeI.cjs.map} +1 -1
  46. package/package.json +1 -1
  47. package/src/Fabric.ts +28 -24
  48. package/src/FileManager.ts +6 -6
  49. package/src/FileProcessor.ts +5 -5
  50. package/src/createFabric.ts +96 -2
  51. package/src/index.ts +0 -1
  52. package/src/parsers/defaultParser.ts +2 -2
  53. package/src/parsers/{createParser.ts → defineParser.ts} +1 -1
  54. package/src/parsers/index.ts +1 -2
  55. package/src/parsers/tsxParser.ts +2 -2
  56. package/src/parsers/typescriptParser.ts +2 -2
  57. package/src/plugins/barrelPlugin.ts +3 -3
  58. package/src/plugins/{createPlugin.ts → definePlugin.ts} +1 -1
  59. package/src/plugins/fsPlugin.ts +3 -3
  60. package/src/plugins/graphPlugin.ts +3 -3
  61. package/src/plugins/index.ts +1 -1
  62. package/src/plugins/loggerPlugin.ts +41 -31
  63. package/dist/createParser-C4IkyTs5.cjs +0 -17
  64. package/dist/createParser-D_ANHZTa.js +0 -11
  65. package/src/defineFabric.ts +0 -119
@@ -1,3 +1,97 @@
1
- import { defineFabric } from './defineFabric.ts'
1
+ import { isFunction } from 'remeda'
2
+ import type { Fabric, FabricConfig, FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'
3
+ import { FileManager } from './FileManager.ts'
4
+ import type * as KubbFile from './KubbFile.ts'
5
+ import type { Parser } from './parsers/types.ts'
6
+ import type { Plugin } from './plugins/types.ts'
7
+ import { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'
2
8
 
3
- export const createFabric = defineFabric()
9
+ /**
10
+ * Creates a new Fabric instance
11
+ *
12
+ * @example
13
+ * const fabric = createFabric()
14
+ * fabric.use(myPlugin())
15
+ */
16
+ export function createFabric<T extends FabricOptions>(config: FabricConfig<T> = { mode: 'sequential' } as FabricConfig<T>): Fabric<T> {
17
+ const events = new AsyncEventEmitter<FabricEvents>()
18
+ const installedPlugins = new Set<Plugin<any>>()
19
+ const installedParsers = new Map<KubbFile.Extname, Parser<any>>()
20
+ const installedParserNames = new Set<string>()
21
+ const fileManager = new FileManager({ events })
22
+
23
+ const context: FabricContext<T> = {
24
+ get files() {
25
+ return fileManager.files
26
+ },
27
+ async addFile(...files) {
28
+ await fileManager.add(...files)
29
+ },
30
+ config,
31
+ fileManager,
32
+ installedPlugins,
33
+ installedParsers,
34
+ on: events.on.bind(events),
35
+ off: events.off.bind(events),
36
+ onOnce: events.onOnce.bind(events),
37
+ removeAll: events.removeAll.bind(events),
38
+ emit: events.emit.bind(events),
39
+ } as FabricContext<T>
40
+
41
+ const fabric: Fabric<T> = {
42
+ context,
43
+ get files() {
44
+ return fileManager.files
45
+ },
46
+ async addFile(...files) {
47
+ await fileManager.add(...files)
48
+ },
49
+ async upsertFile(...files) {
50
+ await fileManager.upsert(...files)
51
+ },
52
+ async use(pluginOrParser, ...options) {
53
+ if (pluginOrParser.type === 'plugin') {
54
+ if (installedPlugins.has(pluginOrParser)) {
55
+ console.warn(`Plugin "${pluginOrParser.name}" already applied.`)
56
+ } else {
57
+ installedPlugins.add(pluginOrParser)
58
+ }
59
+
60
+ if (isFunction(pluginOrParser.inject)) {
61
+ const injecter = pluginOrParser.inject
62
+
63
+ const injected = (injecter as any)(context, ...options)
64
+ Object.assign(fabric, injected)
65
+ }
66
+ }
67
+
68
+ if (pluginOrParser.type === 'parser') {
69
+ if (installedParserNames.has(pluginOrParser.name)) {
70
+ console.warn(`Parser "${pluginOrParser.name}" already applied.`)
71
+ } else {
72
+ installedParserNames.add(pluginOrParser.name)
73
+ }
74
+
75
+ if (pluginOrParser.extNames) {
76
+ for (const extName of pluginOrParser.extNames) {
77
+ const existing = installedParsers.get(extName)
78
+ if (existing && existing.name !== pluginOrParser.name) {
79
+ console.warn(`Parser "${pluginOrParser.name}" is overriding parser "${existing.name}" for extension "${extName}".`)
80
+ }
81
+ installedParsers.set(extName, pluginOrParser)
82
+ }
83
+ }
84
+ }
85
+
86
+ if (isFunction(pluginOrParser.install)) {
87
+ const installer = pluginOrParser.install
88
+
89
+ await (installer as any)(context, ...options)
90
+ }
91
+
92
+ return fabric
93
+ },
94
+ } as Fabric<T>
95
+
96
+ return fabric
97
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export { createFabric } from './createFabric.ts'
2
2
  export { createFile } from './createFile.ts'
3
- export { defineFabric } from './defineFabric.ts'
4
3
  // we need this to override the globals of `fabric.use`
5
4
  export type { Fabric } from './Fabric.ts'
6
5
  export { FileManager } from './FileManager.ts'
@@ -1,6 +1,6 @@
1
- import { createParser } from './createParser.ts'
1
+ import { defineParser } from './defineParser.ts'
2
2
 
3
- export const defaultParser = createParser({
3
+ export const defaultParser = defineParser({
4
4
  name: 'default',
5
5
  extNames: ['.json'],
6
6
  install() {},
@@ -1,6 +1,6 @@
1
1
  import type { Parser, UserParser } from './types.ts'
2
2
 
3
- export function createParser<TOptions = unknown, TMeta extends object = any>(parser: UserParser<TOptions, TMeta>): Parser<TOptions, TMeta> {
3
+ export function defineParser<TOptions = unknown, TMeta extends object = any>(parser: UserParser<TOptions, TMeta>): Parser<TOptions, TMeta> {
4
4
  return {
5
5
  type: 'parser',
6
6
  ...parser,
@@ -1,5 +1,4 @@
1
- export { createParser } from './createParser.ts'
2
-
3
1
  export { defaultParser } from './defaultParser.ts'
2
+ export { defineParser } from './defineParser.ts'
4
3
  export { tsxParser } from './tsxParser.ts'
5
4
  export { typescriptParser } from './typescriptParser.ts'
@@ -1,7 +1,7 @@
1
- import { createParser } from './createParser.ts'
1
+ import { defineParser } from './defineParser.ts'
2
2
  import { typescriptParser } from './typescriptParser.ts'
3
3
 
4
- export const tsxParser = createParser({
4
+ export const tsxParser = defineParser({
5
5
  name: 'tsx',
6
6
  extNames: ['.tsx', '.jsx'],
7
7
  install() {},
@@ -2,7 +2,7 @@ import path from 'node:path'
2
2
  import ts from 'typescript'
3
3
  import { getRelativePath } from '../utils/getRelativePath.ts'
4
4
  import { trimExtName } from '../utils/trimExtName.ts'
5
- import { createParser } from './createParser.ts'
5
+ import { defineParser } from './defineParser.ts'
6
6
 
7
7
  const { factory } = ts
8
8
 
@@ -122,7 +122,7 @@ export function createExport({
122
122
  )
123
123
  }
124
124
 
125
- export const typescriptParser = createParser({
125
+ export const typescriptParser = defineParser({
126
126
  name: 'typescript',
127
127
  extNames: ['.ts', '.js'],
128
128
  install() {},
@@ -5,7 +5,7 @@ import { createFile } from '../createFile.ts'
5
5
  import type * as KubbFile from '../KubbFile.ts'
6
6
  import { getRelativePath } from '../utils/getRelativePath.ts'
7
7
  import { TreeNode } from '../utils/TreeNode.ts'
8
- import { createPlugin } from './createPlugin.ts'
8
+ import { definePlugin } from './definePlugin.ts'
9
9
 
10
10
  type Mode = 'all' | 'named' | 'propagate' | false
11
11
 
@@ -144,7 +144,7 @@ export function getBarrelFiles({ files, root, mode }: GetBarrelFilesOptions): Ar
144
144
  return result
145
145
  }
146
146
 
147
- export const barrelPlugin = createPlugin<Options, ExtendOptions>({
147
+ export const barrelPlugin = definePlugin<Options, ExtendOptions>({
148
148
  name: 'barrel',
149
149
  install(ctx, options) {
150
150
  if (!options) {
@@ -155,7 +155,7 @@ export const barrelPlugin = createPlugin<Options, ExtendOptions>({
155
155
  return undefined
156
156
  }
157
157
 
158
- ctx.on('write:start', async ({ files }) => {
158
+ ctx.on('files:writing:start', async ({ files }) => {
159
159
  const root = options.root
160
160
  const barrelFiles = getBarrelFiles({ files, root, mode: options.mode })
161
161
 
@@ -1,6 +1,6 @@
1
1
  import type { Plugin, UserPlugin } from './types.ts'
2
2
 
3
- export function createPlugin<Options = unknown, TAppExtension extends Record<string, any> = {}>(
3
+ export function definePlugin<Options = unknown, TAppExtension extends Record<string, any> = {}>(
4
4
  plugin: UserPlugin<Options, TAppExtension>,
5
5
  ): Plugin<Options, TAppExtension> {
6
6
  return {
@@ -1,7 +1,7 @@
1
1
  import { resolve } from 'node:path'
2
2
  import fs from 'fs-extra'
3
3
  import type * as KubbFile from '../KubbFile.ts'
4
- import { createPlugin } from './createPlugin.ts'
4
+ import { definePlugin } from './definePlugin.ts'
5
5
 
6
6
  type WriteOptions = {
7
7
  extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>
@@ -85,14 +85,14 @@ declare global {
85
85
  }
86
86
  }
87
87
 
88
- export const fsPlugin = createPlugin<Options, ExtendOptions>({
88
+ export const fsPlugin = definePlugin<Options, ExtendOptions>({
89
89
  name: 'fs',
90
90
  install(ctx, options = {}) {
91
91
  if (options.clean) {
92
92
  fs.removeSync(options.clean.path)
93
93
  }
94
94
 
95
- ctx.on('process:progress', async ({ file, source }) => {
95
+ ctx.on('files:processing:update', async ({ file, source }) => {
96
96
  if (options.onBeforeWrite) {
97
97
  await options.onBeforeWrite(file.path, source)
98
98
  }
@@ -6,7 +6,7 @@ import { createFile } from '../createFile.ts'
6
6
  import type * as KubbFile from '../KubbFile.ts'
7
7
  import { open } from '../utils/open.ts'
8
8
  import { type Graph, TreeNode } from '../utils/TreeNode.ts'
9
- import { createPlugin } from './createPlugin.ts'
9
+ import { definePlugin } from './definePlugin.ts'
10
10
 
11
11
  type Options = {
12
12
  root: string
@@ -84,14 +84,14 @@ async function serve(root: string) {
84
84
  })
85
85
  }
86
86
 
87
- export const graphPlugin = createPlugin<Options>({
87
+ export const graphPlugin = definePlugin<Options>({
88
88
  name: 'graph',
89
89
  install(ctx, options) {
90
90
  if (!options) {
91
91
  throw new Error('Graph plugin requires options.root and options.mode')
92
92
  }
93
93
 
94
- ctx.on('write:start', async ({ files }) => {
94
+ ctx.on('files:writing:start', async ({ files }) => {
95
95
  const root = options.root
96
96
 
97
97
  const graph = getGraph({ files, root })
@@ -1,5 +1,5 @@
1
1
  export { barrelPlugin } from './barrelPlugin.ts'
2
- export { createPlugin } from './createPlugin.ts'
2
+ export { definePlugin } from './definePlugin.ts'
3
3
  export { fsPlugin } from './fsPlugin.ts'
4
4
  export { graphPlugin } from './graphPlugin.ts'
5
5
  export { loggerPlugin } from './loggerPlugin.ts'
@@ -6,10 +6,9 @@ import { createConsola, type LogLevel } from 'consola'
6
6
  import { WebSocket, WebSocketServer } from 'ws'
7
7
  import type { FabricEvents } from '../Fabric.ts'
8
8
  import type * as KubbFile from '../KubbFile.ts'
9
- import { createPlugin } from './createPlugin.ts'
9
+ import { definePlugin } from './definePlugin.ts'
10
10
 
11
11
  type Broadcast = <T = unknown>(event: keyof FabricEvents | string, payload: T) => void
12
-
13
12
  type WebSocketOptions = {
14
13
  /**
15
14
  * Hostname to bind the websocket server to.
@@ -43,7 +42,10 @@ type Options = {
43
42
  websocket?: boolean | WebSocketOptions
44
43
  }
45
44
 
46
- function normalizeAddress(address: AddressInfo): { host: string; port: number } {
45
+ function normalizeAddress(address: AddressInfo): {
46
+ host: string
47
+ port: number
48
+ } {
47
49
  const host = address.address === '::' ? '127.0.0.1' : address.address
48
50
 
49
51
  return { host, port: address.port }
@@ -76,7 +78,7 @@ const createProgressBar = () =>
76
78
  Presets.shades_grey,
77
79
  )
78
80
 
79
- export const loggerPlugin = createPlugin<Options>({
81
+ export const loggerPlugin = definePlugin<Options>({
80
82
  name: 'logger',
81
83
  install(ctx, options = {}) {
82
84
  const { level, websocket = true, progress = true } = options
@@ -140,40 +142,43 @@ export const loggerPlugin = createPlugin<Options>({
140
142
 
141
143
  const formatPath = (path: string) => relative(process.cwd(), path)
142
144
 
143
- ctx.on('start', async () => {
145
+ ctx.on('lifecycle:start', async () => {
144
146
  logger.start('Starting Fabric run')
145
- broadcast('start', { timestamp: Date.now() })
147
+ broadcast('lifecycle:start', { timestamp: Date.now() })
146
148
  })
147
149
 
148
- ctx.on('render', async () => {
150
+ ctx.on('lifecycle:render', async () => {
149
151
  logger.info('Rendering application graph')
150
- broadcast('render', { timestamp: Date.now() })
152
+ broadcast('lifecycle:render', { timestamp: Date.now() })
151
153
  })
152
154
 
153
- ctx.on('file:add', async ({ files }) => {
155
+ ctx.on('files:added', async ({ files }) => {
154
156
  if (!files.length) {
155
157
  return
156
158
  }
157
159
 
158
160
  logger.info(`Queued ${pluralize('file', files.length)}`)
159
- broadcast('file:add', {
161
+ broadcast('files:added', {
160
162
  files: files.map(serializeFile),
161
163
  })
162
164
  })
163
165
 
164
- ctx.on('file:resolve:path', async ({ file }) => {
166
+ ctx.on('file:path:resolving', async ({ file }) => {
165
167
  logger.info(`Resolving path for ${formatPath(file.path)}`)
166
- broadcast('file:resolve:path', { file: serializeFile(file) })
168
+ broadcast('file:path:resolving', { file: serializeFile(file) })
167
169
  })
168
170
 
169
- ctx.on('file:resolve:name', async ({ file }) => {
171
+ ctx.on('file:name:resolving', async ({ file }) => {
170
172
  logger.info(`Resolving name for ${formatPath(file.path)}`)
171
- broadcast('file:resolve:name', { file: serializeFile(file) })
173
+ broadcast('file:name:resolving', { file: serializeFile(file) })
172
174
  })
173
175
 
174
- ctx.on('process:start', async ({ files }) => {
176
+ ctx.on('files:processing:start', async ({ files }) => {
175
177
  logger.start(`Processing ${pluralize('file', files.length)}`)
176
- broadcast('process:start', { total: files.length, timestamp: Date.now() })
178
+ broadcast('files:processing:start', {
179
+ total: files.length,
180
+ timestamp: Date.now(),
181
+ })
177
182
 
178
183
  if (progressBar) {
179
184
  logger.pauseLogs()
@@ -181,20 +186,20 @@ export const loggerPlugin = createPlugin<Options>({
181
186
  }
182
187
  })
183
188
 
184
- ctx.on('file:start', async ({ file, index, total }) => {
189
+ ctx.on('file:processing:start', async ({ file, index, total }) => {
185
190
  logger.info(`Processing [${index + 1}/${total}] ${formatPath(file.path)}`)
186
- broadcast('file:start', {
191
+ broadcast('file:processing:start', {
187
192
  index,
188
193
  total,
189
194
  file: serializeFile(file),
190
195
  })
191
196
  })
192
197
 
193
- ctx.on('process:progress', async ({ processed, total, percentage, file }) => {
198
+ ctx.on('files:processing:update', async ({ processed, total, percentage, file }) => {
194
199
  const formattedPercentage = Number.isFinite(percentage) ? percentage.toFixed(1) : '0.0'
195
200
 
196
201
  logger.info(`Progress ${formattedPercentage}% (${processed}/${total}) → ${formatPath(file.path)}`)
197
- broadcast('process:progress', {
202
+ broadcast('files:processing:update', {
198
203
  processed,
199
204
  total,
200
205
  percentage,
@@ -202,36 +207,41 @@ export const loggerPlugin = createPlugin<Options>({
202
207
  })
203
208
 
204
209
  if (progressBar) {
205
- progressBar.increment(1, { message: `Writing ${formatPath(file.path)}` })
210
+ progressBar.increment(1, {
211
+ message: `Writing ${formatPath(file.path)}`,
212
+ })
206
213
  }
207
214
  })
208
215
 
209
- ctx.on('file:end', async ({ file, index, total }) => {
216
+ ctx.on('file:processing:end', async ({ file, index, total }) => {
210
217
  logger.success(`Finished [${index + 1}/${total}] ${formatPath(file.path)}`)
211
- broadcast('file:end', {
218
+ broadcast('file:processing:end', {
212
219
  index,
213
220
  total,
214
221
  file: serializeFile(file),
215
222
  })
216
223
  })
217
224
 
218
- ctx.on('write:start', async ({ files }) => {
225
+ ctx.on('files:writing:start', async ({ files }) => {
219
226
  logger.start(`Writing ${pluralize('file', files.length)} to disk`)
220
- broadcast('write:start', {
227
+ broadcast('files:writing:start', {
221
228
  files: files.map(serializeFile),
222
229
  })
223
230
  })
224
231
 
225
- ctx.on('write:end', async ({ files }) => {
232
+ ctx.on('files:writing:end', async ({ files }) => {
226
233
  logger.success(`Written ${pluralize('file', files.length)} to disk`)
227
- broadcast('write:end', {
234
+ broadcast('files:writing:end', {
228
235
  files: files.map(serializeFile),
229
236
  })
230
237
  })
231
238
 
232
- ctx.on('process:end', async ({ files }) => {
239
+ ctx.on('files:processing:end', async ({ files }) => {
233
240
  logger.success(`Processed ${pluralize('file', files.length)}`)
234
- broadcast('process:end', { total: files.length, timestamp: Date.now() })
241
+ broadcast('files:processing:end', {
242
+ total: files.length,
243
+ timestamp: Date.now(),
244
+ })
235
245
 
236
246
  if (progressBar) {
237
247
  progressBar.update(files.length, { message: 'Done ✅' })
@@ -241,9 +251,9 @@ export const loggerPlugin = createPlugin<Options>({
241
251
  }
242
252
  })
243
253
 
244
- ctx.on('end', async () => {
254
+ ctx.on('lifecycle:end', async () => {
245
255
  logger.success('Fabric run completed')
246
- broadcast('end', { timestamp: Date.now() })
256
+ broadcast('lifecycle:end', { timestamp: Date.now() })
247
257
 
248
258
  if (progressBar) {
249
259
  progressBar.stop()
@@ -1,17 +0,0 @@
1
-
2
- //#region src/parsers/createParser.ts
3
- function createParser(parser) {
4
- return {
5
- type: "parser",
6
- ...parser
7
- };
8
- }
9
-
10
- //#endregion
11
- Object.defineProperty(exports, 'createParser', {
12
- enumerable: true,
13
- get: function () {
14
- return createParser;
15
- }
16
- });
17
- //# sourceMappingURL=createParser-C4IkyTs5.cjs.map
@@ -1,11 +0,0 @@
1
- //#region src/parsers/createParser.ts
2
- function createParser(parser) {
3
- return {
4
- type: "parser",
5
- ...parser
6
- };
7
- }
8
-
9
- //#endregion
10
- export { createParser as t };
11
- //# sourceMappingURL=createParser-D_ANHZTa.js.map
@@ -1,119 +0,0 @@
1
- import { isFunction } from 'remeda'
2
- import type { Fabric, FabricConfig, FabricContext, FabricEvents, FabricOptions } from './Fabric.ts'
3
- import { FileManager } from './FileManager.ts'
4
- import type * as KubbFile from './KubbFile.ts'
5
- import type { Parser } from './parsers/types.ts'
6
- import type { Plugin } from './plugins/types.ts'
7
- import { AsyncEventEmitter } from './utils/AsyncEventEmitter.ts'
8
-
9
- /**
10
- * Function that initializes the root Fabric instance.
11
- *
12
- * Used for setting up plugins, parsers, or performing side effects
13
- * once the Fabric context is ready.
14
- */
15
- type FabricInitializer<T extends FabricOptions> = (fabric: Fabric<T>) => void | Promise<void>
16
-
17
- /**
18
- * A function returned by {@link defineFabric} that creates a Fabric instance.
19
- */
20
- export type CreateFabric<T extends FabricOptions> = (config?: FabricConfig<T>) => Fabric<T>
21
-
22
- /**
23
- * Defines a new Fabric factory function.
24
- *
25
- * @example
26
- * export const createFabric = defineFabric((fabric) => {
27
- * fabric.use(myPlugin())
28
- * })
29
- */
30
- export function defineFabric<T extends FabricOptions>(init?: FabricInitializer<T>): CreateFabric<T> {
31
- function create(config: FabricConfig<T> = { mode: 'sequential' } as FabricConfig<T>): Fabric<T> {
32
- const events = new AsyncEventEmitter<FabricEvents>()
33
- const installedPlugins = new Set<Plugin<any>>()
34
- const installedParsers = new Map<KubbFile.Extname, Parser<any>>()
35
- const installedParserNames = new Set<string>()
36
- const fileManager = new FileManager({ events })
37
-
38
- const context: FabricContext<T> = {
39
- get files() {
40
- return fileManager.files
41
- },
42
- async addFile(...files) {
43
- await fileManager.add(...files)
44
- },
45
- config,
46
- fileManager,
47
- installedPlugins,
48
- installedParsers,
49
- on: events.on.bind(events),
50
- off: events.off.bind(events),
51
- onOnce: events.onOnce.bind(events),
52
- removeAll: events.removeAll.bind(events),
53
- emit: events.emit.bind(events),
54
- } as FabricContext<T>
55
-
56
- const fabric: Fabric<T> = {
57
- context,
58
- get files() {
59
- return fileManager.files
60
- },
61
- async addFile(...files) {
62
- await fileManager.add(...files)
63
- },
64
- async upsertFile(...files) {
65
- await fileManager.upsert(...files)
66
- },
67
- async use(pluginOrParser, ...options) {
68
- if (pluginOrParser.type === 'plugin') {
69
- if (installedPlugins.has(pluginOrParser)) {
70
- console.warn(`Plugin "${pluginOrParser.name}" already applied.`)
71
- } else {
72
- installedPlugins.add(pluginOrParser)
73
- }
74
-
75
- if (isFunction(pluginOrParser.inject)) {
76
- const injecter = pluginOrParser.inject
77
-
78
- const injected = (injecter as any)(context, ...options)
79
- Object.assign(fabric, injected)
80
- }
81
- }
82
-
83
- if (pluginOrParser.type === 'parser') {
84
- if (installedParserNames.has(pluginOrParser.name)) {
85
- console.warn(`Parser "${pluginOrParser.name}" already applied.`)
86
- } else {
87
- installedParserNames.add(pluginOrParser.name)
88
- }
89
-
90
- if (pluginOrParser.extNames) {
91
- for (const extName of pluginOrParser.extNames) {
92
- const existing = installedParsers.get(extName)
93
- if (existing && existing.name !== pluginOrParser.name) {
94
- console.warn(`Parser "${pluginOrParser.name}" is overriding parser "${existing.name}" for extension "${extName}".`)
95
- }
96
- installedParsers.set(extName, pluginOrParser)
97
- }
98
- }
99
- }
100
-
101
- if (isFunction(pluginOrParser.install)) {
102
- const installer = pluginOrParser.install
103
-
104
- await (installer as any)(context, ...options)
105
- }
106
-
107
- return fabric
108
- },
109
- } as Fabric<T>
110
-
111
- if (init) {
112
- init(fabric)
113
- }
114
-
115
- return fabric
116
- }
117
-
118
- return create
119
- }