Skip to content

Commit cbf82f6

Browse files
committed
fix(common): resolve extras in configurable module builder async methods
1 parent 3c9a6e1 commit cbf82f6

File tree

3 files changed

+64
-2
lines changed

3 files changed

+64
-2
lines changed

packages/common/module-utils/configurable-module.builder.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Logger } from '../services/logger.service';
44
import { randomStringGenerator } from '../utils/random-string-generator.util';
55
import {
66
ASYNC_METHOD_SUFFIX,
7+
ASYNC_OPTIONS_METADATA_KEYS,
78
CONFIGURABLE_MODULE_ID,
89
DEFAULT_FACTORY_CLASS_METHOD_KEY,
910
DEFAULT_METHOD_KEY,
@@ -254,7 +255,7 @@ export class ConfigurableModuleBuilder<
254255
},
255256
{
256257
...self.extras,
257-
...options,
258+
...this.extractExtrasFromAsyncOptions(options, self.extras),
258259
},
259260
);
260261
}
@@ -277,8 +278,28 @@ export class ConfigurableModuleBuilder<
277278
return moduleOptions as ModuleOptions;
278279
}
279280

281+
private static extractExtrasFromAsyncOptions(
282+
input: ConfigurableModuleAsyncOptions<ModuleOptions> &
283+
ExtraModuleDefinitionOptions,
284+
extras: ExtraModuleDefinitionOptions | undefined,
285+
): Partial<ExtraModuleDefinitionOptions> {
286+
if (!extras) {
287+
return {};
288+
}
289+
const extrasOptions = {};
290+
291+
Object.keys(input as object)
292+
.filter(key => !ASYNC_OPTIONS_METADATA_KEYS.includes(key as any))
293+
.forEach(key => {
294+
extrasOptions[key] = input[key];
295+
});
296+
297+
return extrasOptions;
298+
}
299+
280300
private static createAsyncProviders(
281-
options: ConfigurableModuleAsyncOptions<ModuleOptions>,
301+
options: ConfigurableModuleAsyncOptions<ModuleOptions> &
302+
ExtraModuleDefinitionOptions,
282303
): Provider[] {
283304
if (options.useExisting || options.useFactory) {
284305
if (options.inject && options.provideInjectionTokensFrom) {

packages/common/module-utils/constants.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,16 @@ export const DEFAULT_FACTORY_CLASS_METHOD_KEY = 'create';
33

44
export const ASYNC_METHOD_SUFFIX = 'Async';
55
export const CONFIGURABLE_MODULE_ID = 'CONFIGURABLE_MODULE_ID';
6+
7+
/**
8+
* List of keys that are specific to ConfigurableModuleAsyncOptions
9+
* and should be excluded when extracting user-defined extras.
10+
*/
11+
export const ASYNC_OPTIONS_METADATA_KEYS = [
12+
'useFactory',
13+
'useClass',
14+
'useExisting',
15+
'inject',
16+
'imports',
17+
'provideInjectionTokensFrom',
18+
] as const;

packages/common/test/module-utils/configurable-module.builder.spec.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,34 @@ describe('ConfigurableModuleBuilder', () => {
2424
global: true,
2525
});
2626
});
27+
28+
it('should preserve extras in registerAsync transformation', () => {
29+
let capturedExtras: any;
30+
31+
const { ConfigurableModuleClass } = new ConfigurableModuleBuilder()
32+
.setExtras(
33+
{ folder: 'default' },
34+
(definition, extras: { folder: string }) => {
35+
capturedExtras = extras;
36+
return {
37+
...definition,
38+
customProperty: `folder: ${extras.folder}`,
39+
};
40+
},
41+
)
42+
.build();
43+
44+
const asyncResult = ConfigurableModuleClass.registerAsync({
45+
useFactory: () => ({}),
46+
folder: 'forRootAsync',
47+
});
48+
49+
expect(capturedExtras).to.deep.equal({ folder: 'forRootAsync' });
50+
expect(asyncResult).to.have.property(
51+
'customProperty',
52+
'folder: forRootAsync',
53+
);
54+
});
2755
});
2856
describe('setClassMethodName', () => {
2957
it('should set static class method name and return typed builder', () => {

0 commit comments

Comments
 (0)