@kubb/core 5.0.0-alpha.22 → 5.0.0-alpha.23

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/core",
3
- "version": "5.0.0-alpha.22",
3
+ "version": "5.0.0-alpha.23",
4
4
  "description": "Core functionality for Kubb's plugin-based code generation system, providing the foundation for transforming OpenAPI specifications.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -71,7 +71,7 @@
71
71
  "remeda": "^2.33.6",
72
72
  "semver": "^7.7.4",
73
73
  "tinyexec": "^1.0.4",
74
- "@kubb/ast": "5.0.0-alpha.22"
74
+ "@kubb/ast": "5.0.0-alpha.23"
75
75
  },
76
76
  "devDependencies": {
77
77
  "@types/semver": "^7.7.1",
@@ -1,10 +1,10 @@
1
1
  import { basename, extname, resolve } from 'node:path'
2
2
  import { performance } from 'node:perf_hooks'
3
3
  import type { AsyncEventEmitter } from '@internals/utils'
4
- import { isPromiseRejectedResult, setUniqueName, transformReservedWord, ValidationPluginError } from '@internals/utils'
4
+ import { isPromiseRejectedResult, transformReservedWord } from '@internals/utils'
5
5
  import type { RootNode } from '@kubb/ast/types'
6
6
  import type { FabricFile, Fabric as FabricType } from '@kubb/fabric-core/types'
7
- import { CORE_PLUGIN_NAME, DEFAULT_STUDIO_URL } from './constants.ts'
7
+ import { DEFAULT_STUDIO_URL } from './constants.ts'
8
8
  import { openInStudio as openInStudioFn } from './devtools.ts'
9
9
 
10
10
  import type {
@@ -21,7 +21,6 @@ import type {
21
21
  PluginWithLifeCycle,
22
22
  ResolveNameParams,
23
23
  ResolvePathParams,
24
- UserPlugin,
25
24
  } from './types.ts'
26
25
  import { hookFirst, hookParallel, hookSeq } from './utils/executeStrategies.ts'
27
26
 
@@ -96,17 +95,21 @@ export class PluginDriver {
96
95
  adapter: Adapter | undefined = undefined
97
96
  #studioIsOpen = false
98
97
 
99
- readonly #plugins = new Set<Plugin>()
100
- readonly #usedPluginNames: Record<string, number> = {}
98
+ readonly plugins = new Map<string, Plugin>()
101
99
 
102
100
  constructor(config: Config, options: Options) {
103
101
  this.config = config
104
102
  this.options = options
105
- ;[...(config.plugins || [])].forEach((plugin) => {
106
- const parsedPlugin = this.#parse(plugin as UserPlugin)
107
-
108
- this.#plugins.add(parsedPlugin)
109
- })
103
+ config.plugins
104
+ .map((plugin) => Object.assign({ install() {} }, plugin) as unknown as Plugin)
105
+ .sort((a, b) => {
106
+ if (b.pre?.includes(a.name)) return 1
107
+ if (b.post?.includes(a.name)) return -1
108
+ return 0
109
+ })
110
+ .forEach((plugin) => {
111
+ this.plugins.set(plugin.name, plugin)
112
+ })
110
113
  }
111
114
 
112
115
  get events() {
@@ -114,16 +117,15 @@ export class PluginDriver {
114
117
  }
115
118
 
116
119
  getContext<TOptions extends PluginFactoryOptions>(plugin: Plugin<TOptions>): PluginContext<TOptions> & Record<string, unknown> {
117
- const plugins = [...this.#plugins]
118
120
  const driver = this
119
121
 
120
122
  const baseContext = {
121
- fabric: this.options.fabric,
122
- config: this.config,
123
+ fabric: driver.options.fabric,
124
+ config: driver.config,
123
125
  plugin,
124
- events: this.options.events,
125
- driver: this,
126
- mode: getMode(resolve(this.config.root, this.config.output.path)),
126
+ getPlugin: driver.getPlugin.bind(driver),
127
+ events: driver.options.events,
128
+ driver: driver,
127
129
  addFile: async (...files: Array<FabricFile.File>) => {
128
130
  await this.options.fabric.addFile(...files)
129
131
  },
@@ -136,6 +138,9 @@ export class PluginDriver {
136
138
  get adapter(): Adapter | undefined {
137
139
  return driver.adapter
138
140
  },
141
+ get resolver() {
142
+ return plugin.resolver
143
+ },
139
144
  openInStudio(options?: DevtoolsOptions) {
140
145
  if (!driver.config.devtools || driver.#studioIsOpen) {
141
146
  return
@@ -158,9 +163,10 @@ export class PluginDriver {
158
163
  } as unknown as PluginContext<TOptions>
159
164
 
160
165
  const mergedExtras: Record<string, unknown> = {}
161
- for (const p of plugins) {
162
- if (typeof p.inject === 'function') {
163
- const result = (p.inject as (this: PluginContext, context: PluginContext) => unknown).call(
166
+
167
+ for (const plugin of this.plugins.values()) {
168
+ if (typeof plugin.inject === 'function') {
169
+ const result = (plugin.inject as (this: PluginContext, context: PluginContext) => unknown).call(
164
170
  baseContext as unknown as PluginContext,
165
171
  baseContext as unknown as PluginContext,
166
172
  )
@@ -175,11 +181,9 @@ export class PluginDriver {
175
181
  ...mergedExtras,
176
182
  }
177
183
  }
178
-
179
- get plugins(): Array<Plugin> {
180
- return this.#getSortedPlugins()
181
- }
182
-
184
+ /**
185
+ * @deprecated use resolvers context instead
186
+ */
183
187
  getFile<TOptions = object>({ name, mode, extname, pluginName, options }: GetFileOptions<TOptions>): FabricFile.File<{ pluginName: string }> {
184
188
  const resolvedName = mode ? (mode === 'single' ? '' : this.resolveName({ name, pluginName, type: 'file' })) : name
185
189
 
@@ -206,6 +210,9 @@ export class PluginDriver {
206
210
  }
207
211
  }
208
212
 
213
+ /**
214
+ * @deprecated use resolvers context instead
215
+ */
209
216
  resolvePath = <TOptions = object>(params: ResolvePathParams<TOptions>): FabricFile.Path => {
210
217
  const root = resolve(this.config.root, this.config.output.path)
211
218
  const defaultPath = resolve(root, params.baseName)
@@ -227,7 +234,9 @@ export class PluginDriver {
227
234
 
228
235
  return firstResult?.result || defaultPath
229
236
  }
230
- //TODO refactor by using the order of plugins and the cache of the fileManager instead of guessing and recreating the name/path
237
+ /**
238
+ * @deprecated use resolvers context instead
239
+ */
231
240
  resolveName = (params: ResolveNameParams): string => {
232
241
  if (params.pluginName) {
233
242
  const names = this.hookForPluginSync({
@@ -236,9 +245,7 @@ export class PluginDriver {
236
245
  parameters: [params.name.trim(), params.type],
237
246
  })
238
247
 
239
- const uniqueNames = new Set(names)
240
-
241
- return transformReservedWord([...uniqueNames].at(0) || params.name)
248
+ return transformReservedWord(names?.at(0) ?? params.name)
242
249
  }
243
250
 
244
251
  const name = this.hookFirstSync({
@@ -261,36 +268,32 @@ export class PluginDriver {
261
268
  hookName: H
262
269
  parameters: PluginParameter<H>
263
270
  }): Promise<Array<ReturnType<ParseResult<H>> | null>> {
264
- const plugins = this.getPluginsByName(hookName, pluginName)
271
+ const plugin = this.plugins.get(pluginName)
272
+
273
+ if (!plugin) {
274
+ return [null]
275
+ }
265
276
 
266
277
  this.events.emit('plugins:hook:progress:start', {
267
278
  hookName,
268
- plugins,
279
+ plugins: [plugin],
269
280
  })
270
281
 
271
- const items: Array<ReturnType<ParseResult<H>>> = []
272
-
273
- for (const plugin of plugins) {
274
- const result = await this.#execute<H>({
275
- strategy: 'hookFirst',
276
- hookName,
277
- parameters,
278
- plugin,
279
- })
280
-
281
- if (result !== undefined && result !== null) {
282
- items.push(result)
283
- }
284
- }
282
+ const result = await this.#execute<H>({
283
+ strategy: 'hookFirst',
284
+ hookName,
285
+ parameters,
286
+ plugin,
287
+ })
285
288
 
286
289
  this.events.emit('plugins:hook:progress:end', { hookName })
287
290
 
288
- return items
291
+ return [result]
289
292
  }
293
+
290
294
  /**
291
295
  * Run a specific hookName for plugin x.
292
296
  */
293
-
294
297
  hookForPluginSync<H extends PluginLifecycleHooks>({
295
298
  pluginName,
296
299
  hookName,
@@ -300,20 +303,20 @@ export class PluginDriver {
300
303
  hookName: H
301
304
  parameters: PluginParameter<H>
302
305
  }): Array<ReturnType<ParseResult<H>>> | null {
303
- const plugins = this.getPluginsByName(hookName, pluginName)
306
+ const plugin = this.plugins.get(pluginName)
304
307
 
305
- const result = plugins
306
- .map((plugin) => {
307
- return this.#executeSync<H>({
308
- strategy: 'hookFirst',
309
- hookName,
310
- parameters,
311
- plugin,
312
- })
313
- })
314
- .filter((x): x is NonNullable<typeof x> => x !== null)
308
+ if (!plugin) {
309
+ return null
310
+ }
315
311
 
316
- return result
312
+ const result = this.#executeSync<H>({
313
+ strategy: 'hookFirst',
314
+ hookName,
315
+ parameters,
316
+ plugin,
317
+ })
318
+
319
+ return result !== null ? [result] : []
317
320
  }
318
321
 
319
322
  /**
@@ -328,9 +331,10 @@ export class PluginDriver {
328
331
  parameters: PluginParameter<H>
329
332
  skipped?: ReadonlySet<Plugin> | null
330
333
  }): Promise<SafeParseResult<H>> {
331
- const plugins = this.#getSortedPlugins(hookName).filter((plugin) => {
332
- return skipped ? !skipped.has(plugin) : true
333
- })
334
+ const plugins: Array<Plugin> = []
335
+ for (const plugin of this.plugins.values()) {
336
+ if (hookName in plugin && (skipped ? !skipped.has(plugin) : true)) plugins.push(plugin)
337
+ }
334
338
 
335
339
  this.events.emit('plugins:hook:progress:start', { hookName, plugins })
336
340
 
@@ -370,11 +374,11 @@ export class PluginDriver {
370
374
  skipped?: ReadonlySet<Plugin> | null
371
375
  }): SafeParseResult<H> | null {
372
376
  let parseResult: SafeParseResult<H> | null = null
373
- const plugins = this.#getSortedPlugins(hookName).filter((plugin) => {
374
- return skipped ? !skipped.has(plugin) : true
375
- })
376
377
 
377
- for (const plugin of plugins) {
378
+ for (const plugin of this.plugins.values()) {
379
+ if (!(hookName in plugin)) continue
380
+ if (skipped?.has(plugin)) continue
381
+
378
382
  parseResult = {
379
383
  result: this.#executeSync<H>({
380
384
  strategy: 'hookFirst',
@@ -385,9 +389,7 @@ export class PluginDriver {
385
389
  plugin,
386
390
  } as SafeParseResult<H>
387
391
 
388
- if (parseResult?.result != null) {
389
- break
390
- }
392
+ if (parseResult.result != null) break
391
393
  }
392
394
 
393
395
  return parseResult
@@ -403,7 +405,10 @@ export class PluginDriver {
403
405
  hookName: H
404
406
  parameters?: Parameters<RequiredPluginLifecycle[H]> | undefined
405
407
  }): Promise<Awaited<TOutput>[]> {
406
- const plugins = this.#getSortedPlugins(hookName)
408
+ const plugins: Array<Plugin> = []
409
+ for (const plugin of this.plugins.values()) {
410
+ if (hookName in plugin) plugins.push(plugin)
411
+ }
407
412
  this.events.emit('plugins:hook:progress:start', { hookName, plugins })
408
413
 
409
414
  const pluginStartTimes = new Map<Plugin, number>()
@@ -424,7 +429,7 @@ export class PluginDriver {
424
429
 
425
430
  results.forEach((result, index) => {
426
431
  if (isPromiseRejectedResult<Error>(result)) {
427
- const plugin = this.#getSortedPlugins(hookName)[index]
432
+ const plugin = plugins[index]
428
433
 
429
434
  if (plugin) {
430
435
  const startTime = pluginStartTimes.get(plugin) ?? performance.now()
@@ -453,7 +458,10 @@ export class PluginDriver {
453
458
  * Chains plugins
454
459
  */
455
460
  async hookSeq<H extends PluginLifecycleHooks>({ hookName, parameters }: { hookName: H; parameters?: PluginParameter<H> }): Promise<void> {
456
- const plugins = this.#getSortedPlugins(hookName)
461
+ const plugins: Array<Plugin> = []
462
+ for (const plugin of this.plugins.values()) {
463
+ if (hookName in plugin) plugins.push(plugin)
464
+ }
457
465
  this.events.emit('plugins:hook:progress:start', { hookName, plugins })
458
466
 
459
467
  const promises = plugins.map((plugin) => {
@@ -471,62 +479,8 @@ export class PluginDriver {
471
479
  this.events.emit('plugins:hook:progress:end', { hookName })
472
480
  }
473
481
 
474
- #getSortedPlugins(hookName?: keyof PluginLifecycle): Array<Plugin> {
475
- const plugins = [...this.#plugins]
476
-
477
- if (hookName) {
478
- return plugins.filter((plugin) => hookName in plugin)
479
- }
480
- // TODO add test case for sorting with pre/post
481
-
482
- return plugins
483
- .map((plugin) => {
484
- if (plugin.pre) {
485
- let missingPlugins = plugin.pre.filter((pluginName) => !plugins.find((pluginToFind) => pluginToFind.name === pluginName))
486
-
487
- // when adapter is set, we can ignore the depends on plugin-oas, in v5 this will not be needed anymore
488
- if (missingPlugins.includes('plugin-oas') && this.adapter) {
489
- missingPlugins = missingPlugins.filter((pluginName) => pluginName !== 'plugin-oas')
490
- }
491
-
492
- if (missingPlugins.length > 0) {
493
- throw new ValidationPluginError(`The plugin '${plugin.name}' has a pre set that references missing plugins for '${missingPlugins.join(', ')}'`)
494
- }
495
- }
496
-
497
- return plugin
498
- })
499
- .sort((a, b) => {
500
- if (b.pre?.includes(a.name)) {
501
- return 1
502
- }
503
- if (b.post?.includes(a.name)) {
504
- return -1
505
- }
506
- return 0
507
- })
508
- }
509
-
510
- getPluginByName(pluginName: string): Plugin | undefined {
511
- const plugins = [...this.#plugins]
512
-
513
- return plugins.find((item) => item.name === pluginName)
514
- }
515
-
516
- getPluginsByName(hookName: keyof PluginWithLifeCycle, pluginName: string): Plugin[] {
517
- const plugins = [...this.plugins]
518
-
519
- const pluginByPluginName = plugins.filter((plugin) => hookName in plugin).filter((item) => item.name === pluginName)
520
-
521
- if (!pluginByPluginName?.length) {
522
- // fallback on the core plugin when there is no match
523
-
524
- const corePlugin = plugins.find((plugin) => plugin.name === CORE_PLUGIN_NAME && hookName in plugin)
525
-
526
- return corePlugin ? [corePlugin] : []
527
- }
528
-
529
- return pluginByPluginName
482
+ getPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>(pluginName: string): Plugin<TOptions> | undefined {
483
+ return this.plugins.get(pluginName) as Plugin<TOptions> | undefined
530
484
  }
531
485
 
532
486
  /**
@@ -662,22 +616,4 @@ export class PluginDriver {
662
616
  return null
663
617
  }
664
618
  }
665
-
666
- #parse(plugin: UserPlugin): Plugin {
667
- const usedPluginNames = this.#usedPluginNames
668
-
669
- setUniqueName(plugin.name, usedPluginNames)
670
-
671
- const usageCount = usedPluginNames[plugin.name]
672
- if (usageCount && usageCount > 1) {
673
- throw new ValidationPluginError(
674
- `Duplicate plugin "${plugin.name}" detected. Each plugin can only be used once. Use a different configuration instead of adding multiple instances of the same plugin.`,
675
- )
676
- }
677
-
678
- return {
679
- install() {},
680
- ...plugin,
681
- } as unknown as Plugin
682
- }
683
619
  }
package/src/build.ts CHANGED
@@ -274,7 +274,7 @@ export async function safeBuild(options: BuildOptions, overrides?: SetupResult):
274
274
  const config = driver.config
275
275
 
276
276
  try {
277
- for (const plugin of driver.plugins) {
277
+ for (const plugin of driver.plugins.values()) {
278
278
  const context = driver.getContext(plugin)
279
279
  const hrStart = process.hrtime()
280
280
 
@@ -403,7 +403,7 @@ type BuildBarrelExportsParams = {
403
403
 
404
404
  function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }: BuildBarrelExportsParams): FabricFile.Export[] {
405
405
  const pluginNameMap = new Map<string, Plugin>()
406
- for (const plugin of driver.plugins) {
406
+ for (const plugin of driver.plugins.values()) {
407
407
  pluginNameMap.set(plugin.name, plugin)
408
408
  }
409
409
 
package/src/constants.ts CHANGED
@@ -5,16 +5,6 @@ import type { FabricFile } from '@kubb/fabric-core/types'
5
5
  */
6
6
  export const DEFAULT_STUDIO_URL = 'https://studio.kubb.dev' as const
7
7
 
8
- /**
9
- * Internal plugin name used to identify the core Kubb runtime.
10
- */
11
- export const CORE_PLUGIN_NAME = 'core' as const
12
-
13
- /**
14
- * Maximum number of event-emitter listeners before Node.js emits a warning.
15
- */
16
- export const DEFAULT_MAX_LISTENERS = 100
17
-
18
8
  /**
19
9
  * Default number of plugins that may run concurrently during a build.
20
10
  */
@@ -1,6 +1,7 @@
1
1
  import type { OperationNode, SchemaNode } from '@kubb/ast/types'
2
2
  import type { FabricFile } from '@kubb/fabric-core/types'
3
3
  import type { FabricReactNode } from '@kubb/react-fabric/types'
4
+ import type { PluginDriver } from './PluginDriver.ts'
4
5
  import type { Adapter, Config, Plugin, PluginFactoryOptions } from './types.ts'
5
6
 
6
7
  export type Version = '1' | '2'
@@ -12,7 +13,9 @@ export type OperationsV2Props<TPlugin extends PluginFactoryOptions = PluginFacto
12
13
  config: Config
13
14
  plugin: Plugin<TPlugin>
14
15
  adapter: Adapter
16
+ driver: PluginDriver
15
17
  options: Plugin<TPlugin>['options']
18
+ resolver: TPlugin['resolver']
16
19
  nodes: Array<OperationNode>
17
20
  }
18
21
 
@@ -22,8 +25,10 @@ export type OperationsV2Props<TPlugin extends PluginFactoryOptions = PluginFacto
22
25
  export type OperationV2Props<TPlugin extends PluginFactoryOptions = PluginFactoryOptions> = {
23
26
  config: Config
24
27
  adapter: Adapter
28
+ driver: PluginDriver
25
29
  plugin: Plugin<TPlugin>
26
30
  options: Plugin<TPlugin>['options']
31
+ resolver: TPlugin['resolver']
27
32
  node: OperationNode
28
33
  }
29
34
 
@@ -33,8 +38,10 @@ export type OperationV2Props<TPlugin extends PluginFactoryOptions = PluginFactor
33
38
  export type SchemaV2Props<TPlugin extends PluginFactoryOptions = PluginFactoryOptions> = {
34
39
  config: Config
35
40
  adapter: Adapter
41
+ driver: PluginDriver
36
42
  plugin: Plugin<TPlugin>
37
43
  options: Plugin<TPlugin>['options']
44
+ resolver: TPlugin['resolver']
38
45
  node: SchemaNode
39
46
  }
40
47
 
@@ -204,16 +204,7 @@ export function defaultResolvePath(
204
204
  }
205
205
 
206
206
  if (group && (groupPath || tag)) {
207
- const groupName = group.name
208
- ? group.name
209
- : (ctx: { group: string }) => {
210
- if (group.type === 'path') {
211
- return `${ctx.group.split('/')[1]}`
212
- }
213
- return `${camelCase(ctx.group)}Controller`
214
- }
215
-
216
- return path.resolve(root, output.path, groupName({ group: group.type === 'path' ? groupPath! : tag! }), baseName) as FabricFile.Path
207
+ return path.resolve(root, output.path, group.name({ group: group.type === 'path' ? groupPath! : tag! }), baseName) as FabricFile.Path
217
208
  }
218
209
 
219
210
  return path.resolve(root, output.path, baseName) as FabricFile.Path
@@ -2,9 +2,7 @@ import { useFabric } from '@kubb/react-fabric'
2
2
  import type { PluginDriver } from '../PluginDriver.ts'
3
3
 
4
4
  /**
5
- * Returns the `PluginDriver` instance from Fabric context.
6
- *
7
- * Use this inside React generator components to access the driver, config, and adapter.
5
+ * @deprecated use `driver` from the generator component props instead
8
6
  */
9
7
  export function useDriver(): PluginDriver {
10
8
  const { meta } = useFabric<{ driver: PluginDriver }>()
package/src/index.ts CHANGED
@@ -6,10 +6,8 @@ export { formatters, linters, logLevel } from './constants.ts'
6
6
  export { createAdapter } from './createAdapter.ts'
7
7
  export { createPlugin } from './createPlugin.ts'
8
8
  export { createStorage } from './createStorage.ts'
9
- export { defineBuilder } from './defineBuilder.ts'
10
9
  export { defineGenerator } from './defineGenerator.ts'
11
10
  export { defineLogger } from './defineLogger.ts'
12
- export { definePreset } from './definePreset.ts'
13
11
  export { definePresets } from './definePresets.ts'
14
12
  export {
15
13
  buildDefaultBanner,
@@ -12,6 +12,7 @@ type BuildOperationsV2Options<TOptions extends PluginFactoryOptions> = {
12
12
  adapter: Adapter
13
13
  driver: PluginDriver
14
14
  options: TOptions['resolvedOptions']
15
+ resolver: TOptions['resolver']
15
16
  }
16
17
 
17
18
  /**
@@ -30,8 +31,8 @@ export async function renderOperations<TOptions extends PluginFactoryOptions>(
30
31
  const fabricChild = createReactFabric()
31
32
 
32
33
  await fabricChild.render(
33
- <Fabric meta={{ plugin, driver }}>
34
- <Component config={config} plugin={plugin} adapter={adapter} nodes={nodes} options={options.options} />
34
+ <Fabric>
35
+ <Component config={config} plugin={plugin} driver={driver} adapter={adapter} nodes={nodes} options={options.options} resolver={options.resolver} />
35
36
  </Fabric>,
36
37
  )
37
38
 
@@ -47,6 +48,7 @@ type BuildOperationV2Options<TOptions extends PluginFactoryOptions> = {
47
48
  adapter: Adapter
48
49
  driver: PluginDriver
49
50
  options: TOptions['resolvedOptions']
51
+ resolver: TOptions['resolver']
50
52
  }
51
53
 
52
54
  /**
@@ -62,8 +64,8 @@ export async function renderOperation<TOptions extends PluginFactoryOptions>(nod
62
64
  const fabricChild = createReactFabric()
63
65
 
64
66
  await fabricChild.render(
65
- <Fabric meta={{ plugin, driver }}>
66
- <Component config={config} plugin={plugin} adapter={adapter} node={node} options={options.options} />
67
+ <Fabric>
68
+ <Component config={config} plugin={plugin} driver={driver} adapter={adapter} node={node} options={options.options} resolver={options.resolver} />
67
69
  </Fabric>,
68
70
  )
69
71
 
@@ -79,6 +81,7 @@ type BuildSchemaV2Options<TOptions extends PluginFactoryOptions> = {
79
81
  adapter: Adapter
80
82
  driver: PluginDriver
81
83
  options: TOptions['resolvedOptions']
84
+ resolver: TOptions['resolver']
82
85
  }
83
86
 
84
87
  /**
@@ -94,8 +97,8 @@ export async function renderSchema<TOptions extends PluginFactoryOptions>(node:
94
97
  const fabricChild = createReactFabric()
95
98
 
96
99
  await fabricChild.render(
97
- <Fabric meta={{ plugin, driver }}>
98
- <Component config={config} plugin={plugin} adapter={adapter} node={node} options={options.options} />
100
+ <Fabric>
101
+ <Component config={config} plugin={plugin} driver={driver} adapter={adapter} node={node} options={options.options} resolver={options.resolver} />
99
102
  </Fabric>,
100
103
  )
101
104