Skip to content

Commit 33fe949

Browse files
committed
Remove configure empty config requirement for NoConfig modules
1 parent 332d51f commit 33fe949

File tree

2 files changed

+64
-9
lines changed

2 files changed

+64
-9
lines changed

packages/common/src/config/ModuleContainer.ts

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,18 +85,39 @@ export interface ModulesRecord<
8585
[name: string]: ModuleType;
8686
}
8787

88-
// config record derived from the provided modules and their config types
89-
export type ModulesConfig<Modules extends ModulesRecord> = {
90-
// this will translate into = key: module name, value: module.config
91-
[ConfigKey in StringKeyOf<Modules>]: InstanceType<
92-
Modules[ConfigKey]
93-
> extends Configurable<infer Config>
88+
type ExtractConfig<Module extends BaseModuleType> =
89+
InstanceType<Module> extends Configurable<infer Config>
9490
? Config extends NoConfig
9591
? Config | undefined
9692
: Config
9793
: never;
94+
95+
type OnlyDefined<R extends Record<string, unknown>> = {
96+
[Key in keyof R as NoConfig extends R[Key] ? never : Key]: R[Key];
97+
};
98+
type OptionalUndefined<R extends Record<string, unknown>> = {
99+
[Key in keyof R as NoConfig extends R[Key] ? Key : never]?: R[Key];
100+
};
101+
102+
type MakeNoConfigOptional<A extends Record<string, unknown>> = OnlyDefined<A> &
103+
OptionalUndefined<A>;
104+
105+
export type CompletedModulesConfig<Modules extends ModulesRecord> = {
106+
// this will translate into = key: module name, value: module.config
107+
[ConfigKey in StringKeyOf<Modules>]: ExtractConfig<Modules[ConfigKey]>;
98108
};
99109

110+
// config record derived from the provided modules and their config types
111+
export type ModulesConfig<Modules extends ModulesRecord> = MakeNoConfigOptional<
112+
CompletedModulesConfig<Modules>
113+
>;
114+
115+
// export type MakeNeeded<R extends { }>
116+
117+
// export type ShortConfig<Modules extends ModulesRecord> =
118+
// ModulesConfig<Modules>
119+
// >;
120+
100121
/**
101122
* This type make any config partial (i.e. optional) up to the first level
102123
* So { Module: { a: { b: string } } }
@@ -289,6 +310,26 @@ export class ModuleContainer<
289310
});
290311
}
291312

313+
private completeConfig(
314+
config: ModulesConfig<Modules>
315+
): ModulesConfig<Modules> {
316+
const keys = Object.keys(config);
317+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
318+
const moduleNames = this.moduleNames as StringKeyOf<Modules>[];
319+
const noConfigParts = moduleNames
320+
.filter((moduleName) => !keys.includes(moduleName))
321+
.reduce<Record<string, NoConfig>>((obj, moduleName) => {
322+
obj[moduleName] = {};
323+
return obj;
324+
}, {});
325+
326+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
327+
return {
328+
...config,
329+
...noConfigParts,
330+
} as unknown as ModulesConfig<Modules>;
331+
}
332+
292333
/**
293334
* Provide additional configuration after the ModuleContainer was created.
294335
*
@@ -298,7 +339,7 @@ export class ModuleContainer<
298339
* @param config
299340
*/
300341
public configure(config: ModulesConfig<Modules>) {
301-
this.config = config;
342+
this.config = this.completeConfig(config);
302343
}
303344

304345
public configurePartial(config: RecursivePartial<ModulesConfig<Modules>>) {
@@ -316,8 +357,14 @@ export class ModuleContainer<
316357
super.config = merge<
317358
ModulesConfig<Modules> | NoConfig,
318359
ModulesConfig<Modules>
319-
>(this.currentConfig ?? {}, config);
360+
>(this.currentConfig ?? {}, this.completeConfig(config));
320361
}
362+
// public set config(config: ShortConfig<Modules>) {
363+
// super.config = merge<ShortConfig<Modules> | NoConfig, ShortConfig<Modules>>(
364+
// this.currentConfig ?? {},
365+
// config
366+
// );
367+
// }
321368

322369
/**
323370
* Resolves a module from the current module container
@@ -359,7 +406,11 @@ export class ModuleContainer<
359406
moduleName: StringKeyOf<Modules>,
360407
containedModule: InstanceType<Modules[StringKeyOf<Modules>]>
361408
) {
362-
const config = super.config?.[moduleName];
409+
const config =
410+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
411+
(super.config as unknown as CompletedModulesConfig<Modules>)?.[
412+
moduleName
413+
];
363414
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
364415
if (!config) {
365416
throw errors.configNotSetInContainer(moduleName.toString());

packages/common/test/config/ModuleContainer.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ class TestModule
5050
}
5151
}
5252

53+
class NoConfigModule extends BaseTestModule<NoConfig> {}
54+
5355
interface OtherTestModuleConfig {
5456
otherTestConfigProperty: number;
5557
}
@@ -79,6 +81,7 @@ describe("moduleContainer", () => {
7981
let container: TestModuleContainer<{
8082
TestModule: typeof TestModule;
8183
OtherTestModule: typeof OtherTestModule;
84+
NoConfigModule: typeof NoConfigModule;
8285
}>;
8386
const testConfigProperty = 0;
8487

@@ -89,6 +92,7 @@ describe("moduleContainer", () => {
8992
OtherTestModule,
9093
// this module would not be assignable to TestModuleContainer
9194
// WrongTestModule,
95+
NoConfigModule,
9296
},
9397
});
9498
});

0 commit comments

Comments
 (0)