@forklaunch/core 0.2.8 → 0.2.10
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/lib/src/services/configInjector.d.ts +20 -0
- package/lib/src/services/configInjector.d.ts.map +1 -0
- package/lib/src/services/configInjector.js +74 -0
- package/lib/src/services/index.d.ts +4 -0
- package/lib/src/services/index.d.ts.map +1 -1
- package/lib/src/services/index.js +4 -0
- package/lib/src/services/interfaces/baseService.d.ts +1 -1
- package/lib/src/services/interfaces/baseService.d.ts.map +1 -1
- package/lib/src/services/serviceFactory.d.ts +15 -0
- package/lib/src/services/serviceFactory.d.ts.map +1 -0
- package/lib/src/services/serviceFactory.js +22 -0
- package/lib/src/services/types/configInjector.types.d.ts +23 -0
- package/lib/src/services/types/configInjector.types.d.ts.map +1 -0
- package/lib/src/services/types/configInjector.types.js +6 -0
- package/lib/src/services/types/entityManager.types.d.ts +4 -0
- package/lib/src/services/types/entityManager.types.d.ts.map +1 -0
- package/lib/src/services/types/entityManager.types.js +1 -0
- package/lib/src/services/types/serviceFactory.types.d.ts +23 -0
- package/lib/src/services/types/serviceFactory.types.d.ts.map +1 -0
- package/lib/src/services/types/serviceFactory.types.js +6 -0
- package/lib/tests/configInjector.test.d.ts +2 -0
- package/lib/tests/configInjector.test.d.ts.map +1 -0
- package/lib/tests/configInjector.test.js +91 -0
- package/lib/tests/expressLikeRouterInstantiation.test.js +4 -1
- package/lib/tests/serviceFactory.test.d.ts +2 -0
- package/lib/tests/serviceFactory.test.d.ts.map +1 -0
- package/lib/tests/serviceFactory.test.js +36 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +15 -15
- package/LICENSE +0 -21
@@ -0,0 +1,20 @@
|
|
1
|
+
import { AnySchemaValidator } from '@forklaunch/validator';
|
2
|
+
import { ConfigValidator, Constructed, ResolvedConfigValidator, Singleton } from './types/configInjector.types';
|
3
|
+
export declare class ConfigInjector<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>> {
|
4
|
+
private schemaValidator;
|
5
|
+
private configShapes;
|
6
|
+
private dependenciesDefinition;
|
7
|
+
instances: {
|
8
|
+
[K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];
|
9
|
+
};
|
10
|
+
private loadSingletons;
|
11
|
+
private resolveInstance;
|
12
|
+
constructor(schemaValidator: SV, configShapes: CV, dependenciesDefinition: {
|
13
|
+
[K in keyof CV]: Singleton<ResolvedConfigValidator<SV, CV>[K]> | Constructed<Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]>;
|
14
|
+
});
|
15
|
+
validateConfigSingletons(config: Partial<ResolvedConfigValidator<SV, CV>>): boolean;
|
16
|
+
resolve<T extends keyof CV>(token: T, context?: Record<string, unknown>, resolutionPath?: (keyof CV)[]): ResolvedConfigValidator<SV, CV>[T];
|
17
|
+
createScope(): ConfigInjector<SV, CV>;
|
18
|
+
dispose(): void;
|
19
|
+
}
|
20
|
+
//# sourceMappingURL=configInjector.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"configInjector.d.ts","sourceRoot":"","sources":["../../../src/services/configInjector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAmB,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EACL,eAAe,EACf,WAAW,EAEX,uBAAuB,EACvB,SAAS,EACV,MAAM,8BAA8B,CAAC;AAEtC,qBAAa,cAAc,CACzB,EAAE,SAAS,kBAAkB,EAC7B,EAAE,SAAS,eAAe,CAAC,EAAE,CAAC;IAkD5B,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,sBAAsB;IAlDhC,SAAS,EAAE;SACR,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,EAAE,uBAAuB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;KACrD,CAAM;IAEP,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,eAAe;gBAmCb,eAAe,EAAE,EAAE,EACnB,YAAY,EAAE,EAAE,EAChB,sBAAsB,EAAE;SAC7B,CAAC,IAAI,MAAM,EAAE,GACV,SAAS,CAAC,uBAAuB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAC7C,WAAW,CACT,IAAI,CAAC,uBAAuB,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,EACxC,uBAAuB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CACnC;KACN;IAKH,wBAAwB,CACtB,MAAM,EAAE,OAAO,CAAC,uBAAuB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,GAC/C,OAAO;IAYV,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,EACxB,KAAK,EAAE,CAAC,EACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,cAAc,GAAE,CAAC,MAAM,EAAE,CAAC,EAAO,GAChC,uBAAuB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAuCrC,WAAW,IAAI,cAAc,CAAC,EAAE,EAAE,EAAE,CAAC;IAQrC,OAAO,IAAI,IAAI;CAIhB"}
|
@@ -0,0 +1,74 @@
|
|
1
|
+
import { extractArgumentNames, isNever } from '@forklaunch/common';
|
2
|
+
import { Lifetime } from './types/configInjector.types';
|
3
|
+
export class ConfigInjector {
|
4
|
+
schemaValidator;
|
5
|
+
configShapes;
|
6
|
+
dependenciesDefinition;
|
7
|
+
instances = {};
|
8
|
+
loadSingletons() {
|
9
|
+
for (const token in this.dependenciesDefinition) {
|
10
|
+
const definition = this.dependenciesDefinition[token];
|
11
|
+
if (definition.lifetime === Lifetime.Singleton) {
|
12
|
+
this.instances[token] = definition.value;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
}
|
16
|
+
resolveInstance(token, definition, context, resolutionPath = []) {
|
17
|
+
const resolvedArguments = Object.fromEntries(extractArgumentNames(definition.factory)[0]
|
18
|
+
.replace('{', '')
|
19
|
+
.replace('}', '')
|
20
|
+
.split(',')
|
21
|
+
.map((arg) => arg.trim())
|
22
|
+
.map((arg) => {
|
23
|
+
resolutionPath = [...resolutionPath, token];
|
24
|
+
if (resolutionPath.includes(arg)) {
|
25
|
+
throw new Error(`Circular dependency detected: ${resolutionPath.join(' -> ')} -> ${arg}`);
|
26
|
+
}
|
27
|
+
const resolvedArg = this.resolve(arg, context, resolutionPath);
|
28
|
+
return [arg, resolvedArg];
|
29
|
+
}));
|
30
|
+
return definition.factory(resolvedArguments, this.resolve.bind(this), context ?? {});
|
31
|
+
}
|
32
|
+
constructor(schemaValidator, configShapes, dependenciesDefinition) {
|
33
|
+
this.schemaValidator = schemaValidator;
|
34
|
+
this.configShapes = configShapes;
|
35
|
+
this.dependenciesDefinition = dependenciesDefinition;
|
36
|
+
this.loadSingletons();
|
37
|
+
}
|
38
|
+
validateConfigSingletons(config) {
|
39
|
+
return this.schemaValidator.validate(Object.fromEntries(Object.entries(this.configShapes).filter(([key]) => this.dependenciesDefinition[key].lifetime === Lifetime.Singleton)), config);
|
40
|
+
}
|
41
|
+
resolve(token, context, resolutionPath = []) {
|
42
|
+
const instance = this.instances[token];
|
43
|
+
if (!instance) {
|
44
|
+
const definition = this.dependenciesDefinition[token];
|
45
|
+
switch (definition.lifetime) {
|
46
|
+
case Lifetime.Singleton: {
|
47
|
+
return definition.value;
|
48
|
+
}
|
49
|
+
case Lifetime.Scoped: {
|
50
|
+
const scopedInstance = this.resolveInstance(token, definition, context, resolutionPath);
|
51
|
+
this.instances[token] = scopedInstance;
|
52
|
+
return scopedInstance;
|
53
|
+
}
|
54
|
+
case Lifetime.Transient: {
|
55
|
+
return this.resolveInstance(token, definition, context, resolutionPath);
|
56
|
+
}
|
57
|
+
default: {
|
58
|
+
isNever(definition);
|
59
|
+
throw new Error(`Unable to resolve lifetime for dependency ${String(token)}, ${resolutionPath}`);
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
else {
|
64
|
+
return instance;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
createScope() {
|
68
|
+
return new ConfigInjector(this.schemaValidator, this.configShapes, this.dependenciesDefinition);
|
69
|
+
}
|
70
|
+
dispose() {
|
71
|
+
this.instances = {};
|
72
|
+
this.loadSingletons();
|
73
|
+
}
|
74
|
+
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC"}
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"baseService.d.ts","sourceRoot":"","sources":["../../../../src/services/interfaces/baseService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,
|
1
|
+
{"version":3,"file":"baseService.d.ts","sourceRoot":"","sources":["../../../../src/services/interfaces/baseService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,EAAE,EAAE,aAAa,CAAC;CACnB"}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { AnySchemaValidator } from '@forklaunch/validator';
|
2
|
+
import { ConfigInjector } from './configInjector';
|
3
|
+
import { ConfigValidator } from './types/configInjector.types';
|
4
|
+
import { EntityManager } from './types/entityManager.types';
|
5
|
+
export declare class ServiceFactoryInternal<SV extends AnySchemaValidator, Options> {
|
6
|
+
private _schemaValidator;
|
7
|
+
private configInjector;
|
8
|
+
private serviceToken;
|
9
|
+
private entityManager;
|
10
|
+
private globalOptions?;
|
11
|
+
constructor(_schemaValidator: SV, configInjector: ConfigInjector<SV, ConfigValidator<SV>>, serviceToken: keyof ConfigValidator<SV>, entityManager: EntityManager, globalOptions?: Options | undefined);
|
12
|
+
create<Opt extends Options>(options?: Opt): ConfigValidator<SV>[keyof ConfigValidator<SV>];
|
13
|
+
}
|
14
|
+
export declare const ServiceFactory: <SV extends AnySchemaValidator, Options>(schemaValidator: SV, configInjector: ConfigInjector<SV, ConfigValidator<SV>>, serviceToken: keyof ConfigValidator<SV>, entityManager: EntityManager, globalOptions?: Options) => ServiceFactoryInternal<SV, Options>;
|
15
|
+
//# sourceMappingURL=serviceFactory.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"serviceFactory.d.ts","sourceRoot":"","sources":["../../../src/services/serviceFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,qBAAa,sBAAsB,CAAC,EAAE,SAAS,kBAAkB,EAAE,OAAO;IAEtE,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,aAAa,CAAC;gBAJd,gBAAgB,EAAE,EAAE,EACpB,cAAc,EAAE,cAAc,CAAC,EAAE,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC,EACvD,YAAY,EAAE,MAAM,eAAe,CAAC,EAAE,CAAC,EACvC,aAAa,EAAE,aAAa,EAC5B,aAAa,CAAC,EAAE,OAAO,YAAA;IAGjC,MAAM,CAAC,GAAG,SAAS,OAAO,EACxB,OAAO,CAAC,EAAE,GAAG,GACZ,eAAe,CAAC,EAAE,CAAC,CAAC,MAAM,eAAe,CAAC,EAAE,CAAC,CAAC;CAKlD;AAED,eAAO,MAAM,cAAc,GAAI,EAAE,SAAS,kBAAkB,EAAE,OAAO,mBAClD,EAAE,kBACH,cAAc,CAAC,EAAE,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC,gBACzC,MAAM,eAAe,CAAC,EAAE,CAAC,iBACxB,aAAa,kBACZ,OAAO,wCASxB,CAAC"}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
export class ServiceFactoryInternal {
|
2
|
+
_schemaValidator;
|
3
|
+
configInjector;
|
4
|
+
serviceToken;
|
5
|
+
entityManager;
|
6
|
+
globalOptions;
|
7
|
+
constructor(_schemaValidator, configInjector, serviceToken, entityManager, globalOptions) {
|
8
|
+
this._schemaValidator = _schemaValidator;
|
9
|
+
this.configInjector = configInjector;
|
10
|
+
this.serviceToken = serviceToken;
|
11
|
+
this.entityManager = entityManager;
|
12
|
+
this.globalOptions = globalOptions;
|
13
|
+
}
|
14
|
+
create(options) {
|
15
|
+
return this.configInjector.resolve(this.serviceToken, {
|
16
|
+
entityManager: this.entityManager.fork(options ?? this.globalOptions)
|
17
|
+
});
|
18
|
+
}
|
19
|
+
}
|
20
|
+
export const ServiceFactory = (schemaValidator, configInjector, serviceToken, entityManager, globalOptions) => {
|
21
|
+
return new ServiceFactoryInternal(schemaValidator, configInjector, serviceToken, entityManager, globalOptions);
|
22
|
+
};
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { AnySchemaValidator, IdiomaticSchema, Schema } from '@forklaunch/validator';
|
2
|
+
export declare enum Lifetime {
|
3
|
+
Singleton = 0,
|
4
|
+
Transient = 1,
|
5
|
+
Scoped = 2
|
6
|
+
}
|
7
|
+
export type Singleton<Value> = {
|
8
|
+
lifetime: Lifetime.Singleton;
|
9
|
+
value: Value;
|
10
|
+
};
|
11
|
+
export type Constructed<Args, Return> = {
|
12
|
+
lifetime: Lifetime.Transient | Lifetime.Scoped;
|
13
|
+
factory: (args: Args, resolve: <T extends keyof Args>(token: T, context?: Record<string, unknown>) => Args[T], context: Record<string, unknown>) => Return;
|
14
|
+
};
|
15
|
+
export type Constructor = new (...args: never[]) => unknown;
|
16
|
+
export type SchemaConstructor<SV extends AnySchemaValidator> = new (...args: unknown[]) => IdiomaticSchema<SV>;
|
17
|
+
export type Function = (...args: never[]) => unknown;
|
18
|
+
export type SchemaFunction<SV extends AnySchemaValidator> = (args: unknown) => IdiomaticSchema<SV>;
|
19
|
+
export type ConfigValidator<SV extends AnySchemaValidator> = Record<string, Function | SchemaFunction<SV> | Constructor | SchemaConstructor<SV> | IdiomaticSchema<SV>>;
|
20
|
+
export type ResolvedConfigValidator<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>> = {
|
21
|
+
[M in keyof CV]: CV[M] extends SchemaConstructor<SV> ? Schema<InstanceType<CV[M]>, SV> : CV[M] extends SchemaFunction<SV> ? Schema<ReturnType<CV[M]>, SV> : CV[M] extends Function ? ReturnType<CV[M]> : CV[M] extends Constructor ? InstanceType<CV[M]> : Schema<CV[M], SV>;
|
22
|
+
};
|
23
|
+
//# sourceMappingURL=configInjector.types.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"configInjector.types.d.ts","sourceRoot":"","sources":["../../../../src/services/types/configInjector.types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,MAAM,EACP,MAAM,uBAAuB,CAAC;AAE/B,oBAAY,QAAQ;IAClB,SAAS,IAAA;IACT,SAAS,IAAA;IACT,MAAM,IAAA;CACP;AAED,MAAM,MAAM,SAAS,CAAC,KAAK,IAAI;IAC7B,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC;IAC7B,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,IAAI,EAAE,MAAM,IAAI;IACtC,QAAQ,EAAE,QAAQ,CAAC,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC/C,OAAO,EAAE,CACP,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,CAAC,CAAC,SAAS,MAAM,IAAI,EAC5B,KAAK,EAAE,CAAC,EACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,IAAI,CAAC,CAAC,CAAC,EACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC;AAC5D,MAAM,MAAM,iBAAiB,CAAC,EAAE,SAAS,kBAAkB,IAAI,KAC7D,GAAG,IAAI,EAAE,OAAO,EAAE,KACf,eAAe,CAAC,EAAE,CAAC,CAAC;AACzB,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC;AACrD,MAAM,MAAM,cAAc,CAAC,EAAE,SAAS,kBAAkB,IAAI,CAC1D,IAAI,EAAE,OAAO,KACV,eAAe,CAAC,EAAE,CAAC,CAAC;AAEzB,MAAM,MAAM,eAAe,CAAC,EAAE,SAAS,kBAAkB,IAAI,MAAM,CACjE,MAAM,EACJ,QAAQ,GACR,cAAc,CAAC,EAAE,CAAC,GAClB,WAAW,GACX,iBAAiB,CAAC,EAAE,CAAC,GACrB,eAAe,CAAC,EAAE,CAAC,CACtB,CAAC;AAEF,MAAM,MAAM,uBAAuB,CACjC,EAAE,SAAS,kBAAkB,EAC7B,EAAE,SAAS,eAAe,CAAC,EAAE,CAAC,IAC5B;KACD,CAAC,IAAI,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,iBAAiB,CAAC,EAAE,CAAC,GAChD,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAC/B,EAAE,CAAC,CAAC,CAAC,SAAS,cAAc,CAAC,EAAE,CAAC,GAC9B,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAC7B,EAAE,CAAC,CAAC,CAAC,SAAS,QAAQ,GACpB,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GACjB,EAAE,CAAC,CAAC,CAAC,SAAS,WAAW,GACvB,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GACnB,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;CAC5B,CAAC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"entityManager.types.d.ts","sourceRoot":"","sources":["../../../../src/services/types/entityManager.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,aAAa,CAAC;CACrD,CAAC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { AnySchemaValidator, IdiomaticSchema, Schema } from '@forklaunch/validator';
|
2
|
+
export declare enum Lifetime {
|
3
|
+
Singleton = 0,
|
4
|
+
Transient = 1,
|
5
|
+
Scoped = 2
|
6
|
+
}
|
7
|
+
export type Singleton<Value> = {
|
8
|
+
lifetime: Lifetime.Singleton;
|
9
|
+
value: Value;
|
10
|
+
};
|
11
|
+
export type Constructed<Args, Return> = {
|
12
|
+
lifetime: Lifetime.Transient | Lifetime.Scoped;
|
13
|
+
factory: (args: Args, resolve: <T extends keyof Args>(token: T, context?: Record<string, unknown>) => Args[T], context: Record<string, unknown>) => Return;
|
14
|
+
};
|
15
|
+
export type Constructor = new (...args: never[]) => unknown;
|
16
|
+
export type SchemaConstructor<SV extends AnySchemaValidator> = new (...args: unknown[]) => IdiomaticSchema<SV>;
|
17
|
+
export type Function = (...args: never[]) => unknown;
|
18
|
+
export type SchemaFunction<SV extends AnySchemaValidator> = (args: unknown) => IdiomaticSchema<SV>;
|
19
|
+
export type ConfigValidator<SV extends AnySchemaValidator> = Record<string, Function | SchemaFunction<SV> | Constructor | SchemaConstructor<SV> | IdiomaticSchema<SV>>;
|
20
|
+
export type ResolvedConfigValidator<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>> = {
|
21
|
+
[M in keyof CV]: CV[M] extends SchemaConstructor<SV> ? Schema<InstanceType<CV[M]>, SV> : CV[M] extends SchemaFunction<SV> ? Schema<ReturnType<CV[M]>, SV> : CV[M] extends Function ? ReturnType<CV[M]> : CV[M] extends Constructor ? InstanceType<CV[M]> : Schema<CV[M], SV>;
|
22
|
+
};
|
23
|
+
//# sourceMappingURL=serviceFactory.types.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"serviceFactory.types.d.ts","sourceRoot":"","sources":["../../../../src/services/types/serviceFactory.types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,MAAM,EACP,MAAM,uBAAuB,CAAC;AAE/B,oBAAY,QAAQ;IAClB,SAAS,IAAA;IACT,SAAS,IAAA;IACT,MAAM,IAAA;CACP;AAED,MAAM,MAAM,SAAS,CAAC,KAAK,IAAI;IAC7B,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC;IAC7B,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,IAAI,EAAE,MAAM,IAAI;IACtC,QAAQ,EAAE,QAAQ,CAAC,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC/C,OAAO,EAAE,CACP,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,CAAC,CAAC,SAAS,MAAM,IAAI,EAC5B,KAAK,EAAE,CAAC,EACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,IAAI,CAAC,CAAC,CAAC,EACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC;AAC5D,MAAM,MAAM,iBAAiB,CAAC,EAAE,SAAS,kBAAkB,IAAI,KAC7D,GAAG,IAAI,EAAE,OAAO,EAAE,KACf,eAAe,CAAC,EAAE,CAAC,CAAC;AACzB,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC;AACrD,MAAM,MAAM,cAAc,CAAC,EAAE,SAAS,kBAAkB,IAAI,CAC1D,IAAI,EAAE,OAAO,KACV,eAAe,CAAC,EAAE,CAAC,CAAC;AAEzB,MAAM,MAAM,eAAe,CAAC,EAAE,SAAS,kBAAkB,IAAI,MAAM,CACjE,MAAM,EACJ,QAAQ,GACR,cAAc,CAAC,EAAE,CAAC,GAClB,WAAW,GACX,iBAAiB,CAAC,EAAE,CAAC,GACrB,eAAe,CAAC,EAAE,CAAC,CACtB,CAAC;AAEF,MAAM,MAAM,uBAAuB,CACjC,EAAE,SAAS,kBAAkB,EAC7B,EAAE,SAAS,eAAe,CAAC,EAAE,CAAC,IAC5B;KACD,CAAC,IAAI,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,iBAAiB,CAAC,EAAE,CAAC,GAChD,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAC/B,EAAE,CAAC,CAAC,CAAC,SAAS,cAAc,CAAC,EAAE,CAAC,GAC9B,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAC7B,EAAE,CAAC,CAAC,CAAC,SAAS,QAAQ,GACpB,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GACjB,EAAE,CAAC,CAAC,CAAC,SAAS,WAAW,GACvB,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GACnB,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;CAC5B,CAAC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"configInjector.test.d.ts","sourceRoot":"","sources":["../../tests/configInjector.test.ts"],"names":[],"mappings":""}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
import { number, SchemaValidator, string } from '@forklaunch/validator/typebox';
|
2
|
+
import { ConfigInjector } from '../src/services/configInjector';
|
3
|
+
import { Lifetime } from '../src/services/types/configInjector.types';
|
4
|
+
class X {
|
5
|
+
a;
|
6
|
+
b;
|
7
|
+
constructor(a, b) {
|
8
|
+
this.a = a;
|
9
|
+
this.b = b;
|
10
|
+
}
|
11
|
+
dummy() {
|
12
|
+
return `${this.a}${this.b()}`;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
describe('serviceFactory', () => {
|
16
|
+
const configInjector = new ConfigInjector(SchemaValidator(), {
|
17
|
+
a: string,
|
18
|
+
b: number,
|
19
|
+
c: X,
|
20
|
+
d: number,
|
21
|
+
e: number,
|
22
|
+
f: number
|
23
|
+
}, {
|
24
|
+
a: {
|
25
|
+
lifetime: Lifetime.Singleton,
|
26
|
+
value: 'a'
|
27
|
+
},
|
28
|
+
b: {
|
29
|
+
lifetime: Lifetime.Transient,
|
30
|
+
factory: ({ a }) => 5
|
31
|
+
},
|
32
|
+
c: {
|
33
|
+
lifetime: Lifetime.Scoped,
|
34
|
+
factory: ({ a }, resolve, context) => {
|
35
|
+
const b = () => resolve('b') * context.num;
|
36
|
+
return new X(a, b);
|
37
|
+
}
|
38
|
+
},
|
39
|
+
d: {
|
40
|
+
lifetime: Lifetime.Transient,
|
41
|
+
factory: ({ e }) => e
|
42
|
+
},
|
43
|
+
e: {
|
44
|
+
lifetime: Lifetime.Transient,
|
45
|
+
factory: ({ f }) => f
|
46
|
+
},
|
47
|
+
f: {
|
48
|
+
lifetime: Lifetime.Transient,
|
49
|
+
factory: ({ d }) => d
|
50
|
+
}
|
51
|
+
});
|
52
|
+
test('loadSingletons', () => {
|
53
|
+
expect(configInjector.instances).toEqual({
|
54
|
+
a: 'a'
|
55
|
+
});
|
56
|
+
});
|
57
|
+
test('basicResolve', () => {
|
58
|
+
expect(configInjector.resolve('a')).toBe('a');
|
59
|
+
expect(configInjector.resolve('b')).toBe(5);
|
60
|
+
expect(configInjector
|
61
|
+
.resolve('c', {
|
62
|
+
num: 4
|
63
|
+
})
|
64
|
+
.dummy()).toBe('a20');
|
65
|
+
expect(Object.keys(configInjector.instances)).toEqual(['a', 'c']);
|
66
|
+
});
|
67
|
+
test('circular dependency', () => {
|
68
|
+
expect(() => configInjector.resolve('d')).toThrowErrorMatchingInlineSnapshot('[Error: Circular dependency detected: d -> e -> f -> d]');
|
69
|
+
expect(() => configInjector.resolve('e')).toThrowErrorMatchingInlineSnapshot('[Error: Circular dependency detected: e -> f -> d -> e]');
|
70
|
+
expect(() => {
|
71
|
+
configInjector.resolve('f');
|
72
|
+
}).toThrowErrorMatchingInlineSnapshot('[Error: Circular dependency detected: f -> d -> e -> f]');
|
73
|
+
});
|
74
|
+
test('validateConfigSingletons', () => {
|
75
|
+
expect(configInjector.validateConfigSingletons({
|
76
|
+
a: 'a'
|
77
|
+
})).toBe(true);
|
78
|
+
expect(configInjector.validateConfigSingletons({
|
79
|
+
a: 5
|
80
|
+
})).toBe(false);
|
81
|
+
});
|
82
|
+
test('createScope', () => {
|
83
|
+
const scope = configInjector.createScope();
|
84
|
+
expect(scope).toBeInstanceOf(ConfigInjector);
|
85
|
+
expect(scope.instances).not.toEqual(configInjector.instances);
|
86
|
+
});
|
87
|
+
test('dispose', () => {
|
88
|
+
configInjector.dispose();
|
89
|
+
expect(configInjector.instances).toEqual({ a: 'a' });
|
90
|
+
});
|
91
|
+
});
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { date, number, SchemaValidator, string } from '@forklaunch/validator/typebox';
|
2
2
|
import { ForklaunchExpressLikeRouter, typedHandler } from '../src/http';
|
3
3
|
import { typedAuthHandler } from '../src/http/handlers/typedAuthHandler';
|
4
|
+
// TODO: write tests
|
4
5
|
const contractDetails = {
|
5
6
|
name: 'string',
|
6
7
|
summary: 'string',
|
@@ -55,7 +56,9 @@ const xasd = typedHandler(SchemaValidator(), '/test/:name/:id', 'trace', {
|
|
55
56
|
const l = res.getHeaders()['x-correlation-id'];
|
56
57
|
res.status(200).send(new Date());
|
57
58
|
});
|
58
|
-
const xa = new ForklaunchExpressLikeRouter('/l', SchemaValidator(),
|
59
|
+
const xa = new ForklaunchExpressLikeRouter('/l', SchemaValidator(),
|
60
|
+
// TODO: implement this
|
61
|
+
{});
|
59
62
|
const bl = xa.trace('/test/:name/:id', {
|
60
63
|
name: 'string',
|
61
64
|
summary: 'string',
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"serviceFactory.test.d.ts","sourceRoot":"","sources":["../../tests/serviceFactory.test.ts"],"names":[],"mappings":""}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import { number, SchemaValidator, string } from '@forklaunch/validator/typebox';
|
2
|
+
import { ConfigInjector } from '../src/services/serviceFactory';
|
3
|
+
import { Lifetime } from '../src/services/types/serviceFactory.types';
|
4
|
+
class X {
|
5
|
+
a;
|
6
|
+
b;
|
7
|
+
constructor(a, b) {
|
8
|
+
this.a = a;
|
9
|
+
this.b = b;
|
10
|
+
}
|
11
|
+
}
|
12
|
+
// build in cycle detection during runtime
|
13
|
+
const x = new ConfigInjector(SchemaValidator(), {
|
14
|
+
a: string,
|
15
|
+
b: number,
|
16
|
+
c: X
|
17
|
+
}, {
|
18
|
+
a: {
|
19
|
+
lifetime: Lifetime.Singleton,
|
20
|
+
value: 'a'
|
21
|
+
},
|
22
|
+
b: {
|
23
|
+
lifetime: Lifetime.Transient,
|
24
|
+
factory: ({ a }) => Number(a)
|
25
|
+
},
|
26
|
+
c: {
|
27
|
+
lifetime: Lifetime.Transient,
|
28
|
+
factory: ({ a }, resolve) => {
|
29
|
+
const b = () => resolve('b');
|
30
|
+
return new X(a, b);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
});
|
34
|
+
const u = x.resolve('a');
|
35
|
+
const v = x.resolve('b');
|
36
|
+
const w = x.resolve('c');
|