Skip to content

Commit b249311

Browse files
authored
fix bugs (#5300)
1 parent 69edd06 commit b249311

File tree

16 files changed

+215
-188
lines changed

16 files changed

+215
-188
lines changed

lib/actor.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ export default function (obj = {}, container) {
7575
if (!container) {
7676
container = Container
7777
}
78-
78+
79+
// Get existing actor or create a new one
7980
const actor = container.actor() || new Actor()
8081

8182
// load all helpers once container initialized
@@ -111,14 +112,17 @@ export default function (obj = {}, container) {
111112
}
112113
})
113114

114-
container.append({
115-
support: {
116-
I: actor,
117-
},
118-
})
115+
// Update container.support.I to ensure it has the latest actor reference
116+
if (!container.actor() || container.actor() !== actor) {
117+
container.append({
118+
support: {
119+
I: actor,
120+
},
121+
})
122+
}
119123
})
120-
// store.actor = actor;
121-
// add custom steps from actor
124+
125+
// add custom steps from actor immediately
122126
Object.keys(obj).forEach(key => {
123127
const ms = new MetaStep('I', key)
124128
ms.setContext(actor)

lib/container.js

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ let container = {
2222
helpers: {},
2323
support: {},
2424
proxySupport: {},
25+
proxySupportConfig: {}, // Track config used to create proxySupport
2526
plugins: {},
2627
actor: null,
2728
/**
@@ -32,7 +33,7 @@ let container = {
3233
translation: {},
3334
/** @type {Result | null} */
3435
result: null,
35-
sharedKeys: new Set() // Track keys shared via share() function
36+
sharedKeys: new Set(), // Track keys shared via share() function
3637
}
3738

3839
/**
@@ -67,14 +68,15 @@ class Container {
6768
container.support = {}
6869
container.helpers = await createHelpers(config.helpers || {})
6970
container.translation = await loadTranslation(config.translation || null, config.vocabularies || [])
70-
container.proxySupport = createSupportObjects(config.include || {})
71+
container.proxySupportConfig = config.include || {}
72+
container.proxySupport = createSupportObjects(container.proxySupportConfig)
7173
container.plugins = await createPlugins(config.plugins || {}, opts)
7274
container.result = new Result()
7375

7476
// Preload includes (so proxies can expose real objects synchronously)
7577
const includes = config.include || {}
7678

77-
// Ensure I is available for DI modules at import time
79+
// Check if custom I is provided
7880
if (Object.prototype.hasOwnProperty.call(includes, 'I')) {
7981
try {
8082
const mod = includes.I
@@ -89,7 +91,7 @@ class Container {
8991
throw new Error(`Could not include object I: ${e.message}`)
9092
}
9193
} else {
92-
// Create default actor if not provided via includes
94+
// Create default actor - this sets up the callback in asyncHelperPromise
9395
createActor()
9496
}
9597

@@ -110,6 +112,9 @@ class Container {
110112
}
111113
}
112114

115+
// Wait for all async helpers to finish loading and populate the actor
116+
await asyncHelperPromise
117+
113118
if (opts && opts.ai) ai.enable(config.ai) // enable AI Assistant
114119
if (config.gherkin) await loadGherkinStepsAsync(config.gherkin.steps || [])
115120
if (opts && typeof opts.timeouts === 'boolean') store.timeouts = opts.timeouts
@@ -204,8 +209,10 @@ class Container {
204209

205210
// If new support objects are added, update the proxy support
206211
if (newContainer.support) {
207-
const newProxySupport = createSupportObjects(newContainer.support)
208-
container.proxySupport = { ...container.proxySupport, ...newProxySupport }
212+
// Merge the new support config with existing config
213+
container.proxySupportConfig = { ...container.proxySupportConfig, ...newContainer.support }
214+
// Recreate the proxy with merged config
215+
container.proxySupport = createSupportObjects(container.proxySupportConfig)
209216
}
210217

211218
debug('appended', JSON.stringify(newContainer).slice(0, 300))
@@ -221,6 +228,7 @@ class Container {
221228
static async clear(newHelpers = {}, newSupport = {}, newPlugins = {}) {
222229
container.helpers = newHelpers
223230
container.translation = await loadTranslation()
231+
container.proxySupportConfig = newSupport
224232
container.proxySupport = createSupportObjects(newSupport)
225233
container.plugins = newPlugins
226234
container.sharedKeys = new Set() // Clear shared keys
@@ -250,10 +258,10 @@ class Container {
250258
// Instead of using append which replaces the entire container,
251259
// directly update the support object to maintain proxy references
252260
Object.assign(container.support, data)
253-
261+
254262
// Track which keys were explicitly shared
255263
Object.keys(data).forEach(key => container.sharedKeys.add(key))
256-
264+
257265
if (!options.local) {
258266
WorkerStorage.share(data)
259267
}
@@ -292,7 +300,7 @@ async function createHelpers(config) {
292300
if (!HelperClass) {
293301
const helperResult = requireHelperFromModule(helperName, config)
294302
if (helperResult instanceof Promise) {
295-
// Handle async ESM loading
303+
// Handle async ESM loading - create placeholder
296304
helpers[helperName] = {}
297305
asyncHelperPromise = asyncHelperPromise
298306
.then(() => helperResult)
@@ -311,8 +319,7 @@ async function createHelpers(config) {
311319

312320
checkHelperRequirements(ResolvedHelperClass)
313321
helpers[helperName] = new ResolvedHelperClass(config[helperName])
314-
if (helpers[helperName]._init) await helpers[helperName]._init()
315-
debug(`helper ${helperName} async initialized`)
322+
debug(`helper ${helperName} async loaded`)
316323
})
317324
continue
318325
} else {
@@ -332,9 +339,8 @@ async function createHelpers(config) {
332339
throw new Error(`Helper class from module '${helperName}' is not a class. Use CJS async module syntax.`)
333340
}
334341

335-
debug(`helper ${helperName} async initialized`)
336-
337342
helpers[helperName] = new ResolvedHelperClass(config[helperName])
343+
debug(`helper ${helperName} async CJS loaded`)
338344
})
339345

340346
continue
@@ -349,9 +355,18 @@ async function createHelpers(config) {
349355
}
350356
}
351357

352-
for (const name in helpers) {
353-
if (helpers[name]._init) await helpers[name]._init()
354-
}
358+
// Don't await here - let Container.create() handle the await
359+
// This allows actor callbacks to be registered before resolution
360+
asyncHelperPromise = asyncHelperPromise.then(async () => {
361+
// Call _init on all helpers after they're all loaded
362+
for (const name in helpers) {
363+
if (helpers[name]._init) {
364+
await helpers[name]._init()
365+
debug(`helper ${name} _init() called`)
366+
}
367+
}
368+
})
369+
355370
return helpers
356371
}
357372

@@ -525,10 +540,17 @@ function createSupportObjects(config) {
525540
return [...new Set([...keys, ...container.sharedKeys])]
526541
},
527542
getOwnPropertyDescriptor(target, prop) {
543+
// For destructuring to work, we need to return the actual value from the getter
544+
let value
545+
if (container.sharedKeys.has(prop) && prop in container.support) {
546+
value = container.support[prop]
547+
} else {
548+
value = lazyLoad(prop)
549+
}
528550
return {
529551
enumerable: true,
530552
configurable: true,
531-
value: target[prop],
553+
value: value,
532554
}
533555
},
534556
get(target, key) {
@@ -677,24 +699,23 @@ async function loadSupportObject(modulePath, supportObjectName) {
677699
// Use dynamic import for both ESM and CJS modules
678700
let importPath = modulePath
679701
let tempJsFile = null
680-
702+
681703
if (typeof importPath === 'string') {
682704
const ext = path.extname(importPath)
683-
705+
684706
// Handle TypeScript files
685707
if (ext === '.ts') {
686708
try {
687709
// Use the TypeScript transpilation utility
688710
const typescript = await import('typescript')
689711
const { tempFile, allTempFiles } = await transpileTypeScript(importPath, typescript)
690-
712+
691713
debug(`Transpiled TypeScript file: ${importPath} -> ${tempFile}`)
692-
714+
693715
// Attach cleanup handler
694716
importPath = tempFile
695717
// Store temp files list in a way that cleanup can access them
696718
tempJsFile = allTempFiles
697-
698719
} catch (tsError) {
699720
throw new Error(`Failed to load TypeScript file ${importPath}: ${tsError.message}. Make sure 'typescript' package is installed.`)
700721
}
@@ -703,7 +724,7 @@ async function loadSupportObject(modulePath, supportObjectName) {
703724
importPath = `${importPath}.js`
704725
}
705726
}
706-
727+
707728
let obj
708729
try {
709730
obj = await import(importPath)

lib/helper/GraphQL.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class GraphQL extends Helper {
4545
timeout: 10000,
4646
defaultHeaders: {},
4747
endpoint: '',
48+
onRequest: null,
49+
onResponse: null,
4850
}
4951
this.options = Object.assign(this.options, config)
5052
this.headers = { ...this.options.defaultHeaders }
@@ -87,8 +89,8 @@ class GraphQL extends Helper {
8789

8890
request.headers = { ...this.headers, ...request.headers }
8991

90-
if (this.config.onRequest) {
91-
await this.config.onRequest(request)
92+
if (this.options.onRequest) {
93+
await this.options.onRequest(request)
9294
}
9395

9496
this.debugSection('Request', JSON.stringify(request))
@@ -102,8 +104,8 @@ class GraphQL extends Helper {
102104
response = err.response
103105
}
104106

105-
if (this.config.onResponse) {
106-
await this.config.onResponse(response)
107+
if (this.options.onResponse) {
108+
await this.options.onResponse(response)
107109
}
108110

109111
this.debugSection('Response', JSON.stringify(response.data))

lib/helper/JSONResponse.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ class JSONResponse extends Helper {
7272
if (!this.helpers[this.options.requestHelper]) {
7373
throw new Error(`Error setting JSONResponse, helper ${this.options.requestHelper} is not enabled in config, helpers: ${Object.keys(this.helpers)}`)
7474
}
75-
const origOnResponse = this.helpers[this.options.requestHelper].config.onResponse
76-
this.helpers[this.options.requestHelper].config.onResponse = response => {
75+
const origOnResponse = this.helpers[this.options.requestHelper].options.onResponse
76+
this.helpers[this.options.requestHelper].options.onResponse = response => {
7777
this.response = response
7878
if (typeof origOnResponse === 'function') origOnResponse(response)
7979
}
@@ -83,7 +83,6 @@ class JSONResponse extends Helper {
8383
this.response = null
8484
}
8585

86-
8786
/**
8887
* Checks that response code is equal to the provided one
8988
*
@@ -372,4 +371,4 @@ class JSONResponse extends Helper {
372371
}
373372
}
374373

375-
export { JSONResponse as default }
374+
export { JSONResponse, JSONResponse as default }

0 commit comments

Comments
 (0)