@forklaunch/core 0.5.5 → 0.6.0

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.
Files changed (45) hide show
  1. package/lib/__test__/index.d.mts +11 -0
  2. package/lib/__test__/index.d.ts +11 -0
  3. package/lib/__test__/index.js +54 -0
  4. package/lib/__test__/index.js.map +1 -0
  5. package/lib/__test__/index.mjs +30 -0
  6. package/lib/__test__/index.mjs.map +1 -0
  7. package/lib/{cache → src/cache}/index.d.mts +1 -1
  8. package/lib/{cache → src/cache}/index.d.ts +1 -1
  9. package/lib/src/cache/index.js.map +1 -0
  10. package/lib/src/cache/index.mjs.map +1 -0
  11. package/lib/{controllers → src/controllers}/index.d.mts +2 -0
  12. package/lib/{controllers → src/controllers}/index.d.ts +2 -0
  13. package/lib/src/controllers/index.js.map +1 -0
  14. package/lib/{dtoMapper → src/dtoMapper}/index.d.mts +67 -1
  15. package/lib/{dtoMapper → src/dtoMapper}/index.d.ts +67 -1
  16. package/lib/{dtoMapper → src/dtoMapper}/index.js +36 -2
  17. package/lib/src/dtoMapper/index.js.map +1 -0
  18. package/lib/{dtoMapper → src/dtoMapper}/index.mjs +33 -1
  19. package/lib/src/dtoMapper/index.mjs.map +1 -0
  20. package/lib/{http → src/http}/index.d.mts +2 -2
  21. package/lib/{http → src/http}/index.d.ts +2 -2
  22. package/lib/{http → src/http}/index.js +8 -3
  23. package/lib/{http → src/http}/index.js.map +1 -1
  24. package/lib/{http → src/http}/index.mjs +9 -4
  25. package/lib/src/http/index.mjs.map +1 -0
  26. package/lib/{services → src/services}/index.d.mts +43 -13
  27. package/lib/{services → src/services}/index.d.ts +43 -13
  28. package/lib/{services → src/services}/index.js +56 -12
  29. package/lib/src/services/index.js.map +1 -0
  30. package/lib/{services → src/services}/index.mjs +55 -12
  31. package/lib/src/services/index.mjs.map +1 -0
  32. package/package.json +52 -46
  33. package/lib/cache/index.js.map +0 -1
  34. package/lib/cache/index.mjs.map +0 -1
  35. package/lib/controllers/index.js.map +0 -1
  36. package/lib/dtoMapper/index.js.map +0 -1
  37. package/lib/dtoMapper/index.mjs.map +0 -1
  38. package/lib/http/index.mjs.map +0 -1
  39. package/lib/services/index.js.map +0 -1
  40. package/lib/services/index.mjs.map +0 -1
  41. /package/lib/{cache → src/cache}/index.js +0 -0
  42. /package/lib/{cache → src/cache}/index.mjs +0 -0
  43. /package/lib/{controllers → src/controllers}/index.js +0 -0
  44. /package/lib/{controllers → src/controllers}/index.mjs +0 -0
  45. /package/lib/{controllers → src/controllers}/index.mjs.map +0 -0
@@ -1,46 +1,59 @@
1
1
  import { AnySchemaValidator, IdiomaticSchema, Schema, ParseResult } from '@forklaunch/validator';
2
- import { EntityManager as EntityManager$1 } from '@mikro-orm/core';
2
+ import { EntityManager as EntityManager$1, Collection } from '@mikro-orm/core';
3
3
 
4
4
  declare enum Lifetime {
5
5
  Singleton = 0,
6
6
  Transient = 1,
7
7
  Scoped = 2
8
8
  }
9
- type Singleton<Args, Value> = {
9
+ type Singleton<Type, Args, Value> = {
10
10
  lifetime: Lifetime.Singleton;
11
+ type: Type;
11
12
  value: Value;
12
- } | ConstructedSingleton<Args, Value>;
13
- type ConstructedSingleton<Args, Return> = {
13
+ } | ConstructedSingleton<Type, Args, Value>;
14
+ type ConstructedSingleton<Type, Args, Return> = {
14
15
  lifetime: Lifetime.Singleton;
16
+ type: Type;
15
17
  factory: (args: Args, resolve: <T extends keyof Args>(token: T, context?: Record<string, unknown>) => Args[T], context: Record<string, unknown>) => Return;
16
18
  };
17
- type Constructed<Args, Return> = {
19
+ type Constructed<Type, Args, Return> = {
18
20
  lifetime: Lifetime.Transient | Lifetime.Scoped;
21
+ type: Type;
19
22
  factory: (args: Args, resolve: <T extends keyof Args>(token: T, context?: Record<string, unknown>) => Args[T], context: Record<string, unknown>) => Return;
20
23
  };
21
24
  type Constructor = new (...args: never[]) => unknown;
22
25
  type SchemaConstructor<SV extends AnySchemaValidator> = new (...args: unknown[]) => IdiomaticSchema<SV>;
23
26
  type Function = (...args: never[]) => unknown;
24
27
  type SchemaFunction<SV extends AnySchemaValidator> = (args: unknown) => IdiomaticSchema<SV>;
25
- type ConfigValidator<SV extends AnySchemaValidator> = Record<string, Function | SchemaFunction<SV> | Constructor | SchemaConstructor<SV> | IdiomaticSchema<SV>>;
28
+ type ConfigTypes<SV extends AnySchemaValidator> = Function | SchemaFunction<SV> | Constructor | SchemaConstructor<SV> | IdiomaticSchema<SV>;
29
+ type ConfigValidator<SV extends AnySchemaValidator> = Record<string, ConfigTypes<SV> | Record<string, ConfigTypes<SV>>>;
30
+ type ResolveConfigValue<SV extends AnySchemaValidator, T> = T extends SchemaConstructor<SV> ? Schema<InstanceType<T>, SV> : T extends SchemaFunction<SV> ? Schema<ReturnType<T>, SV> : T extends Function ? ReturnType<T> : T extends Constructor ? InstanceType<T> : T extends Record<string, ConfigTypes<SV>> ? {
31
+ [K in keyof T]: ResolveConfigValue<SV, T[K]>;
32
+ } : Schema<T, SV>;
26
33
  type ResolvedConfigValidator<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>> = {
27
- [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>;
34
+ [M in keyof CV]: ResolveConfigValue<SV, CV[M]>;
28
35
  };
29
36
  type ScopedDependencyFactory<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>, M extends keyof CV> = (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[M];
30
37
 
38
+ declare function createConfigInjector<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>>(schemaValidator: SV, dependenciesDefinition: {
39
+ [K in keyof CV]: Singleton<CV[K], Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]> | Constructed<CV[K], Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]>;
40
+ }): ConfigInjector<SV, CV>;
31
41
  declare class ConfigInjector<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>> {
32
42
  private schemaValidator;
33
- private configShapes;
34
43
  private dependenciesDefinition;
35
44
  instances: {
36
45
  [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];
37
46
  };
47
+ readonly configShapes: CV;
48
+ load(inheritedScopeInstances?: {
49
+ [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];
50
+ }): this;
38
51
  private loadSingletons;
39
52
  private resolveInstance;
40
- constructor(schemaValidator: SV, configShapes: CV, dependenciesDefinition: {
41
- [K in keyof CV]: Singleton<Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]> | Constructed<Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]>;
42
- }, inheritedScopeInstances?: {
43
- [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];
53
+ constructor(schemaValidator: SV, dependenciesDefinition: {
54
+ [K in keyof CV]: (Singleton<CV[K], Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]> | Constructed<CV[K], Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]>) & {
55
+ type: CV[K];
56
+ };
44
57
  });
45
58
  safeValidateConfigSingletons(): ParseResult<ValidConfigInjector<SV, CV>>;
46
59
  validateConfigSingletons(configName: string): ValidConfigInjector<SV, CV>;
@@ -48,6 +61,14 @@ declare class ConfigInjector<SV extends AnySchemaValidator, CV extends ConfigVal
48
61
  scopedResolver<T extends keyof CV>(token: T, context?: Record<string, unknown>, resolutionPath?: (keyof CV)[]): (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[T];
49
62
  createScope(): ConfigInjector<SV, CV>;
50
63
  dispose(): void;
64
+ chain<ChainedCV extends ConfigValidator<SV>>(dependenciesDefinition: {
65
+ [K in keyof ChainedCV]: {
66
+ type: ChainedCV[K];
67
+ } & (Singleton<ChainedCV[K], Omit<ResolvedConfigValidator<SV, CV & ChainedCV>, K>, ResolvedConfigValidator<SV, ChainedCV>[K]> | Constructed<ChainedCV[K], Omit<ResolvedConfigValidator<SV, CV & ChainedCV>, K>, ResolvedConfigValidator<SV, ChainedCV>[K]>);
68
+ }): ConfigInjector<SV, CV & ChainedCV>;
69
+ tokens(): {
70
+ [K in keyof CV]: K;
71
+ };
51
72
  }
52
73
  declare class ValidConfigInjector<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>> extends ConfigInjector<SV, CV> {
53
74
  validConfigInjector: void;
@@ -72,5 +93,14 @@ interface BaseService {
72
93
  type EntityManager = {
73
94
  fork: <Options>(options?: Options) => EntityManager;
74
95
  };
96
+ type DependencyShapes<CreateDependencies extends (...args: never[]) => {
97
+ serviceDependencies: {
98
+ configShapes: unknown;
99
+ };
100
+ }> = ReturnType<CreateDependencies>['serviceDependencies']['configShapes'];
101
+
102
+ type MapNestedDtoArraysToCollections<Dto, Keys extends string> = Omit<Dto, Keys> & {
103
+ [K in Keys]: Collection<object>;
104
+ };
75
105
 
76
- export { type BaseService, ConfigInjector, type ConfigValidator, type Constructed, type ConstructedSingleton, type Constructor, type EntityManager, type Function, Lifetime, type ResolvedConfigValidator, type SchemaConstructor, type SchemaFunction, type ScopedDependencyFactory, type Singleton, ValidConfigInjector, getEnvVar };
106
+ export { type BaseService, ConfigInjector, type ConfigValidator, type Constructed, type ConstructedSingleton, type Constructor, type DependencyShapes, type EntityManager, type Function, Lifetime, type MapNestedDtoArraysToCollections, type ResolvedConfigValidator, type SchemaConstructor, type SchemaFunction, type ScopedDependencyFactory, type Singleton, ValidConfigInjector, createConfigInjector, getEnvVar };
@@ -1,46 +1,59 @@
1
1
  import { AnySchemaValidator, IdiomaticSchema, Schema, ParseResult } from '@forklaunch/validator';
2
- import { EntityManager as EntityManager$1 } from '@mikro-orm/core';
2
+ import { EntityManager as EntityManager$1, Collection } from '@mikro-orm/core';
3
3
 
4
4
  declare enum Lifetime {
5
5
  Singleton = 0,
6
6
  Transient = 1,
7
7
  Scoped = 2
8
8
  }
9
- type Singleton<Args, Value> = {
9
+ type Singleton<Type, Args, Value> = {
10
10
  lifetime: Lifetime.Singleton;
11
+ type: Type;
11
12
  value: Value;
12
- } | ConstructedSingleton<Args, Value>;
13
- type ConstructedSingleton<Args, Return> = {
13
+ } | ConstructedSingleton<Type, Args, Value>;
14
+ type ConstructedSingleton<Type, Args, Return> = {
14
15
  lifetime: Lifetime.Singleton;
16
+ type: Type;
15
17
  factory: (args: Args, resolve: <T extends keyof Args>(token: T, context?: Record<string, unknown>) => Args[T], context: Record<string, unknown>) => Return;
16
18
  };
17
- type Constructed<Args, Return> = {
19
+ type Constructed<Type, Args, Return> = {
18
20
  lifetime: Lifetime.Transient | Lifetime.Scoped;
21
+ type: Type;
19
22
  factory: (args: Args, resolve: <T extends keyof Args>(token: T, context?: Record<string, unknown>) => Args[T], context: Record<string, unknown>) => Return;
20
23
  };
21
24
  type Constructor = new (...args: never[]) => unknown;
22
25
  type SchemaConstructor<SV extends AnySchemaValidator> = new (...args: unknown[]) => IdiomaticSchema<SV>;
23
26
  type Function = (...args: never[]) => unknown;
24
27
  type SchemaFunction<SV extends AnySchemaValidator> = (args: unknown) => IdiomaticSchema<SV>;
25
- type ConfigValidator<SV extends AnySchemaValidator> = Record<string, Function | SchemaFunction<SV> | Constructor | SchemaConstructor<SV> | IdiomaticSchema<SV>>;
28
+ type ConfigTypes<SV extends AnySchemaValidator> = Function | SchemaFunction<SV> | Constructor | SchemaConstructor<SV> | IdiomaticSchema<SV>;
29
+ type ConfigValidator<SV extends AnySchemaValidator> = Record<string, ConfigTypes<SV> | Record<string, ConfigTypes<SV>>>;
30
+ type ResolveConfigValue<SV extends AnySchemaValidator, T> = T extends SchemaConstructor<SV> ? Schema<InstanceType<T>, SV> : T extends SchemaFunction<SV> ? Schema<ReturnType<T>, SV> : T extends Function ? ReturnType<T> : T extends Constructor ? InstanceType<T> : T extends Record<string, ConfigTypes<SV>> ? {
31
+ [K in keyof T]: ResolveConfigValue<SV, T[K]>;
32
+ } : Schema<T, SV>;
26
33
  type ResolvedConfigValidator<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>> = {
27
- [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>;
34
+ [M in keyof CV]: ResolveConfigValue<SV, CV[M]>;
28
35
  };
29
36
  type ScopedDependencyFactory<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>, M extends keyof CV> = (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[M];
30
37
 
38
+ declare function createConfigInjector<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>>(schemaValidator: SV, dependenciesDefinition: {
39
+ [K in keyof CV]: Singleton<CV[K], Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]> | Constructed<CV[K], Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]>;
40
+ }): ConfigInjector<SV, CV>;
31
41
  declare class ConfigInjector<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>> {
32
42
  private schemaValidator;
33
- private configShapes;
34
43
  private dependenciesDefinition;
35
44
  instances: {
36
45
  [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];
37
46
  };
47
+ readonly configShapes: CV;
48
+ load(inheritedScopeInstances?: {
49
+ [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];
50
+ }): this;
38
51
  private loadSingletons;
39
52
  private resolveInstance;
40
- constructor(schemaValidator: SV, configShapes: CV, dependenciesDefinition: {
41
- [K in keyof CV]: Singleton<Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]> | Constructed<Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]>;
42
- }, inheritedScopeInstances?: {
43
- [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];
53
+ constructor(schemaValidator: SV, dependenciesDefinition: {
54
+ [K in keyof CV]: (Singleton<CV[K], Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]> | Constructed<CV[K], Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]>) & {
55
+ type: CV[K];
56
+ };
44
57
  });
45
58
  safeValidateConfigSingletons(): ParseResult<ValidConfigInjector<SV, CV>>;
46
59
  validateConfigSingletons(configName: string): ValidConfigInjector<SV, CV>;
@@ -48,6 +61,14 @@ declare class ConfigInjector<SV extends AnySchemaValidator, CV extends ConfigVal
48
61
  scopedResolver<T extends keyof CV>(token: T, context?: Record<string, unknown>, resolutionPath?: (keyof CV)[]): (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[T];
49
62
  createScope(): ConfigInjector<SV, CV>;
50
63
  dispose(): void;
64
+ chain<ChainedCV extends ConfigValidator<SV>>(dependenciesDefinition: {
65
+ [K in keyof ChainedCV]: {
66
+ type: ChainedCV[K];
67
+ } & (Singleton<ChainedCV[K], Omit<ResolvedConfigValidator<SV, CV & ChainedCV>, K>, ResolvedConfigValidator<SV, ChainedCV>[K]> | Constructed<ChainedCV[K], Omit<ResolvedConfigValidator<SV, CV & ChainedCV>, K>, ResolvedConfigValidator<SV, ChainedCV>[K]>);
68
+ }): ConfigInjector<SV, CV & ChainedCV>;
69
+ tokens(): {
70
+ [K in keyof CV]: K;
71
+ };
51
72
  }
52
73
  declare class ValidConfigInjector<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>> extends ConfigInjector<SV, CV> {
53
74
  validConfigInjector: void;
@@ -72,5 +93,14 @@ interface BaseService {
72
93
  type EntityManager = {
73
94
  fork: <Options>(options?: Options) => EntityManager;
74
95
  };
96
+ type DependencyShapes<CreateDependencies extends (...args: never[]) => {
97
+ serviceDependencies: {
98
+ configShapes: unknown;
99
+ };
100
+ }> = ReturnType<CreateDependencies>['serviceDependencies']['configShapes'];
101
+
102
+ type MapNestedDtoArraysToCollections<Dto, Keys extends string> = Omit<Dto, Keys> & {
103
+ [K in Keys]: Collection<object>;
104
+ };
75
105
 
76
- export { type BaseService, ConfigInjector, type ConfigValidator, type Constructed, type ConstructedSingleton, type Constructor, type EntityManager, type Function, Lifetime, type ResolvedConfigValidator, type SchemaConstructor, type SchemaFunction, type ScopedDependencyFactory, type Singleton, ValidConfigInjector, getEnvVar };
106
+ export { type BaseService, ConfigInjector, type ConfigValidator, type Constructed, type ConstructedSingleton, type Constructor, type DependencyShapes, type EntityManager, type Function, Lifetime, type MapNestedDtoArraysToCollections, type ResolvedConfigValidator, type SchemaConstructor, type SchemaFunction, type ScopedDependencyFactory, type Singleton, ValidConfigInjector, createConfigInjector, getEnvVar };
@@ -23,6 +23,7 @@ __export(services_exports, {
23
23
  ConfigInjector: () => ConfigInjector,
24
24
  Lifetime: () => Lifetime,
25
25
  ValidConfigInjector: () => ValidConfigInjector,
26
+ createConfigInjector: () => createConfigInjector,
26
27
  getEnvVar: () => getEnvVar
27
28
  });
28
29
  module.exports = __toCommonJS(services_exports);
@@ -55,14 +56,30 @@ function isConstructor(value) {
55
56
  }
56
57
 
57
58
  // src/services/configInjector.ts
59
+ function createConfigInjector(schemaValidator, dependenciesDefinition) {
60
+ return new ConfigInjector(schemaValidator, dependenciesDefinition);
61
+ }
58
62
  var ConfigInjector = class _ConfigInjector {
59
- constructor(schemaValidator, configShapes, dependenciesDefinition, inheritedScopeInstances) {
63
+ constructor(schemaValidator, dependenciesDefinition) {
60
64
  this.schemaValidator = schemaValidator;
61
- this.configShapes = configShapes;
62
65
  this.dependenciesDefinition = dependenciesDefinition;
63
- this.loadSingletons(inheritedScopeInstances);
66
+ this.configShapes = Object.entries(this.dependenciesDefinition).reduce(
67
+ (acc, [key, { type }]) => ({
68
+ ...acc,
69
+ [key]: type
70
+ }),
71
+ {}
72
+ );
73
+ this.loadSingletons();
64
74
  }
65
75
  instances = {};
76
+ configShapes;
77
+ load(inheritedScopeInstances) {
78
+ for (const token in inheritedScopeInstances) {
79
+ this.instances[token] = inheritedScopeInstances[token];
80
+ }
81
+ return this;
82
+ }
66
83
  loadSingletons(inheritedScopeInstances) {
67
84
  for (const token in this.dependenciesDefinition) {
68
85
  const definition = this.dependenciesDefinition[token];
@@ -79,10 +96,11 @@ var ConfigInjector = class _ConfigInjector {
79
96
  }
80
97
  }
81
98
  }
99
+ return this;
82
100
  }
83
101
  resolveInstance(token, definition, context, resolutionPath = []) {
84
102
  const injectorArgument = (0, import_common.extractArgumentNames)(definition.factory)[0];
85
- if (injectorArgument === "_args") {
103
+ if (!injectorArgument || injectorArgument === "_args") {
86
104
  return definition.factory(
87
105
  {},
88
106
  this.resolve.bind(this),
@@ -176,10 +194,8 @@ var ConfigInjector = class _ConfigInjector {
176
194
  ok: true,
177
195
  value: new ValidConfigInjector(
178
196
  this.schemaValidator,
179
- this.configShapes,
180
- this.dependenciesDefinition,
181
- this.instances
182
- )
197
+ this.dependenciesDefinition
198
+ ).loadSingletons({ ...this.instances })
183
199
  } : {
184
200
  ok: false,
185
201
  errors: [
@@ -208,9 +224,22 @@ var ConfigInjector = class _ConfigInjector {
208
224
  }
209
225
  switch (definition.lifetime) {
210
226
  case 0 /* Singleton */: {
227
+ if (isConstructedSingleton(definition) && !this.instances[token]) {
228
+ this.instances[token] = this.resolveInstance(
229
+ token,
230
+ definition,
231
+ context,
232
+ resolutionPath
233
+ );
234
+ }
211
235
  return this.instances[token];
212
236
  }
213
237
  case 2 /* Scoped */: {
238
+ if (!isConstructed(definition)) {
239
+ throw new Error(
240
+ `Invalid dependency definition for ${String(token)}`
241
+ );
242
+ }
214
243
  const scopedInstance = this.resolveInstance(
215
244
  token,
216
245
  definition,
@@ -221,6 +250,11 @@ var ConfigInjector = class _ConfigInjector {
221
250
  return scopedInstance;
222
251
  }
223
252
  case 1 /* Transient */: {
253
+ if (!isConstructed(definition)) {
254
+ throw new Error(
255
+ `Invalid dependency definition for ${String(token)}`
256
+ );
257
+ }
224
258
  return this.resolveInstance(
225
259
  token,
226
260
  definition,
@@ -247,15 +281,24 @@ var ConfigInjector = class _ConfigInjector {
247
281
  createScope() {
248
282
  return new _ConfigInjector(
249
283
  this.schemaValidator,
250
- this.configShapes,
251
- this.dependenciesDefinition,
252
- this.instances
253
- );
284
+ this.dependenciesDefinition
285
+ ).loadSingletons({ ...this.instances });
254
286
  }
255
287
  dispose() {
256
288
  this.instances = {};
257
289
  this.loadSingletons();
258
290
  }
291
+ chain(dependenciesDefinition) {
292
+ return new _ConfigInjector(this.schemaValidator, {
293
+ ...this.dependenciesDefinition,
294
+ ...dependenciesDefinition
295
+ }).load({ ...this.instances });
296
+ }
297
+ tokens() {
298
+ return Object.fromEntries(
299
+ Object.keys(this.dependenciesDefinition).map((key) => [key, key])
300
+ );
301
+ }
259
302
  };
260
303
  var ValidConfigInjector = class extends ConfigInjector {
261
304
  validConfigInjector;
@@ -271,6 +314,7 @@ function getEnvVar(name) {
271
314
  ConfigInjector,
272
315
  Lifetime,
273
316
  ValidConfigInjector,
317
+ createConfigInjector,
274
318
  getEnvVar
275
319
  });
276
320
  //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/services/index.ts","../../../src/services/configInjector.ts","../../../src/services/guards/isConstructed.ts","../../../src/services/types/configInjector.types.ts","../../../src/services/guards/isConstructedSingleton.ts","../../../src/services/guards/isConstructor.ts","../../../src/services/getEnvVar.ts"],"sourcesContent":["export * from './configInjector';\nexport * from './getEnvVar';\nexport * from './interfaces/baseService';\nexport * from './types/configInjector.types';\nexport * from './types/entityManager.types';\nexport * from './types/service.types';\n","import { extractArgumentNames, isNever } from '@forklaunch/common';\nimport {\n AnySchemaValidator,\n IdiomaticSchema,\n ParseResult,\n prettyPrintParseErrors,\n SchemaValidator\n} from '@forklaunch/validator';\nimport { isConstructed } from './guards/isConstructed';\nimport { isConstructedSingleton } from './guards/isConstructedSingleton';\nimport { isConstructor } from './guards/isConstructor';\nimport {\n ConfigValidator,\n Constructed,\n ConstructedSingleton,\n Lifetime,\n ResolvedConfigValidator,\n SchemaConstructor,\n SchemaFunction,\n Singleton\n} from './types/configInjector.types';\n\nexport function createConfigInjector<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n>(\n schemaValidator: SV,\n dependenciesDefinition: {\n [K in keyof CV]:\n | Singleton<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >\n | Constructed<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >;\n }\n) {\n return new ConfigInjector<SV, CV>(schemaValidator, dependenciesDefinition);\n}\n\nexport class ConfigInjector<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n> {\n instances: {\n [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];\n } = {};\n\n readonly configShapes: CV;\n\n load(inheritedScopeInstances?: {\n [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];\n }): this {\n for (const token in inheritedScopeInstances) {\n this.instances[token] = inheritedScopeInstances[token];\n }\n return this;\n }\n\n private loadSingletons(inheritedScopeInstances?: {\n [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];\n }): this {\n for (const token in this.dependenciesDefinition) {\n const definition = this.dependenciesDefinition[token];\n if (definition.lifetime === Lifetime.Singleton) {\n if (inheritedScopeInstances && inheritedScopeInstances[token]) {\n this.instances[token] = inheritedScopeInstances[token];\n } else if (\n isConstructedSingleton<\n CV[typeof token],\n Omit<ResolvedConfigValidator<SV, CV>, typeof token>,\n ResolvedConfigValidator<SV, CV>[typeof token]\n >(definition)\n ) {\n this.instances[token] = this.resolveInstance<typeof token>(\n token,\n definition\n );\n } else {\n this.instances[token] = definition.value;\n }\n }\n }\n return this;\n }\n\n private resolveInstance<T extends keyof CV>(\n token: T,\n definition:\n | ConstructedSingleton<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >\n | Constructed<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >,\n context?: Record<string, unknown>,\n resolutionPath: (keyof CV)[] = []\n ): ResolvedConfigValidator<SV, CV>[T] {\n const injectorArgument = extractArgumentNames(definition.factory)[0];\n // short circuit as no args\n if (!injectorArgument || injectorArgument === '_args') {\n return definition.factory(\n {} as Omit<ResolvedConfigValidator<SV, CV>, T>,\n this.resolve.bind(this),\n context ?? ({} as Record<string, unknown>)\n );\n }\n\n if (!injectorArgument.startsWith('{') || !injectorArgument.endsWith('}')) {\n throw new Error(\n `Invalid injector argument for ${String(\n token\n )}: ${injectorArgument}. Please use object destructuring syntax: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment.`\n );\n }\n const resolvedArguments = Object.fromEntries(\n injectorArgument\n .replace('{', '')\n .replace('}', '')\n .split(',')\n .map((arg) => arg.split(':')[0].trim())\n .map((arg) => {\n const newResolutionPath = [...resolutionPath, token];\n if (resolutionPath.includes(arg)) {\n throw new Error(\n `Circular dependency detected: ${newResolutionPath.join(\n ' -> '\n )} -> ${arg}`\n );\n }\n const resolvedArg = this.resolve(arg, context, newResolutionPath);\n return [arg, resolvedArg];\n })\n ) as unknown as Omit<ResolvedConfigValidator<SV, CV>, T>;\n return definition.factory(\n resolvedArguments,\n this.resolve.bind(this),\n context ?? ({} as Record<string, unknown>)\n );\n }\n\n constructor(\n private schemaValidator: SV,\n private dependenciesDefinition: {\n [K in keyof CV]: (\n | Singleton<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >\n | Constructed<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >\n ) & {\n type: CV[K];\n };\n }\n ) {\n this.configShapes = Object.entries(this.dependenciesDefinition).reduce(\n (acc, [key, { type }]) => ({\n ...acc,\n [key]: type\n }),\n {} as Record<keyof CV, CV[keyof CV]>\n ) as CV;\n this.loadSingletons();\n }\n\n safeValidateConfigSingletons(): ParseResult<ValidConfigInjector<SV, CV>> {\n const validNonSchemaSingletons = Object.entries(this.configShapes).reduce<\n ParseResult<ResolvedConfigValidator<SV, CV>>\n >(\n (acc, [key, value]) => {\n if (\n this.dependenciesDefinition[key].lifetime === Lifetime.Singleton &&\n !(this.schemaValidator as SchemaValidator).isSchema<\n SchemaFunction<SV> | SchemaConstructor<SV> | IdiomaticSchema<SV>\n >(value) &&\n isConstructor(value)\n ) {\n if (!(this.instances[key] instanceof value)) {\n const expected = value.name;\n const receivedValue: unknown = this.instances[key];\n const received = isConstructed(receivedValue)\n ? receivedValue.constructor.name\n : typeof receivedValue;\n\n if (acc.ok) {\n acc = {\n ok: false,\n errors: []\n };\n }\n acc.errors?.push({\n message: `Expected ${expected}, received ${received}`,\n path: [key]\n });\n } else {\n if (acc.ok) {\n acc = {\n ok: true,\n value: {\n ...acc.value,\n [key]: this.instances[key]\n }\n };\n }\n }\n return acc;\n }\n return acc;\n },\n {\n ok: true,\n value: {} as ResolvedConfigValidator<SV, CV>\n }\n );\n\n const singletons = Object.fromEntries(\n Object.entries(this.configShapes).filter(\n ([key, value]) =>\n this.dependenciesDefinition[key].lifetime === Lifetime.Singleton &&\n (this.schemaValidator as SchemaValidator).isSchema(value)\n )\n );\n const schemaSingletonParseResult = (\n this.schemaValidator as SchemaValidator\n ).parse(\n (this.schemaValidator as SchemaValidator).schemify(singletons),\n Object.fromEntries(\n Object.keys(singletons).map((key) => {\n const dependency = this.dependenciesDefinition[key];\n return [\n key,\n dependency.lifetime === Lifetime.Singleton\n ? this.instances[key]\n : undefined\n ];\n })\n )\n );\n\n const configKeys = Object.keys(this.configShapes);\n\n return validNonSchemaSingletons.ok && schemaSingletonParseResult.ok\n ? {\n ok: true as const,\n value: new ValidConfigInjector<SV, CV>(\n this.schemaValidator,\n this.dependenciesDefinition\n ).loadSingletons({ ...this.instances })\n }\n : {\n ok: false as const,\n errors: [\n ...(!validNonSchemaSingletons.ok && validNonSchemaSingletons.errors\n ? validNonSchemaSingletons.errors\n : []),\n ...(!schemaSingletonParseResult.ok &&\n schemaSingletonParseResult.errors\n ? schemaSingletonParseResult.errors\n : [])\n ].sort(\n (a, b) =>\n configKeys.indexOf(a.path[0]) - configKeys.indexOf(b.path[0])\n )\n };\n }\n\n validateConfigSingletons(configName: string): ValidConfigInjector<SV, CV> {\n const safeValidateResult = this.safeValidateConfigSingletons();\n\n if (safeValidateResult.ok) {\n return safeValidateResult.value;\n }\n\n throw new Error(\n prettyPrintParseErrors(safeValidateResult.errors, configName)\n );\n }\n\n resolve<T extends keyof CV>(\n token: T,\n context?: Record<string, unknown>,\n resolutionPath: (keyof CV)[] = []\n ): ResolvedConfigValidator<SV, CV>[T] {\n const instance = this.instances[token];\n if (!instance) {\n const definition = this.dependenciesDefinition[token];\n\n if (!definition) {\n throw new Error(`Unable to resolve dependency ${String(token)}`);\n }\n\n switch (definition.lifetime) {\n case Lifetime.Singleton: {\n if (\n isConstructedSingleton<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >(definition) &&\n !this.instances[token]\n ) {\n this.instances[token] = this.resolveInstance<T>(\n token,\n definition,\n context,\n resolutionPath\n );\n }\n return this.instances[token] as ResolvedConfigValidator<SV, CV>[T];\n }\n case Lifetime.Scoped: {\n if (\n !isConstructed<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >(definition)\n ) {\n throw new Error(\n `Invalid dependency definition for ${String(token)}`\n );\n }\n\n const scopedInstance = this.resolveInstance<T>(\n token,\n definition,\n context,\n resolutionPath\n );\n this.instances[token] = scopedInstance;\n return scopedInstance;\n }\n case Lifetime.Transient: {\n if (\n !isConstructed<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >(definition)\n ) {\n throw new Error(\n `Invalid dependency definition for ${String(token)}`\n );\n }\n\n return this.resolveInstance<T>(\n token,\n definition,\n context,\n resolutionPath\n );\n }\n default: {\n isNever(definition);\n throw new Error(\n `Unable to resolve lifetime for dependency ${String(\n token\n )}, ${resolutionPath}`\n );\n }\n }\n } else {\n return instance;\n }\n }\n\n scopedResolver<T extends keyof CV>(\n token: T,\n context?: Record<string, unknown>,\n resolutionPath: (keyof CV)[] = []\n ): (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[T] {\n return (scope) =>\n (scope ?? this.createScope()).resolve<T>(token, context, resolutionPath);\n }\n\n createScope(): ConfigInjector<SV, CV> {\n return new ConfigInjector<SV, CV>(\n this.schemaValidator,\n this.dependenciesDefinition\n ).loadSingletons({ ...this.instances });\n }\n\n dispose(): void {\n this.instances = {};\n this.loadSingletons();\n }\n\n chain<ChainedCV extends ConfigValidator<SV>>(dependenciesDefinition: {\n [K in keyof ChainedCV]: {\n type: ChainedCV[K];\n } & (\n | Singleton<\n ChainedCV[K],\n Omit<ResolvedConfigValidator<SV, CV & ChainedCV>, K>,\n ResolvedConfigValidator<SV, ChainedCV>[K]\n >\n | Constructed<\n ChainedCV[K],\n Omit<ResolvedConfigValidator<SV, CV & ChainedCV>, K>,\n ResolvedConfigValidator<SV, ChainedCV>[K]\n >\n );\n }): ConfigInjector<SV, CV & ChainedCV> {\n return new ConfigInjector<SV, CV>(this.schemaValidator, {\n ...this.dependenciesDefinition,\n ...dependenciesDefinition\n }).load({ ...this.instances }) as unknown as ConfigInjector<\n SV,\n CV & ChainedCV\n >;\n }\n\n tokens(): {\n [K in keyof CV]: K;\n } {\n return Object.fromEntries(\n Object.keys(this.dependenciesDefinition).map((key) => [key, key])\n ) as {\n [K in keyof CV]: K;\n };\n }\n}\n\nexport class ValidConfigInjector<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n> extends ConfigInjector<SV, CV> {\n validConfigInjector!: void;\n}\n","import { Constructed } from '../types/configInjector.types';\n\nexport function isConstructed<Type, Args, Return>(\n value: unknown\n): value is Constructed<Type, Args, Return> {\n return (\n typeof value === 'object' &&\n value != null &&\n 'constructor' in value &&\n value.constructor != null\n );\n}\n","import {\n AnySchemaValidator,\n IdiomaticSchema,\n Schema\n} from '@forklaunch/validator';\nimport { ConfigInjector } from '../configInjector';\n\nexport enum Lifetime {\n Singleton,\n Transient,\n Scoped\n}\n\nexport type Singleton<Type, Args, Value> =\n | {\n lifetime: Lifetime.Singleton;\n type: Type;\n value: Value;\n }\n | ConstructedSingleton<Type, Args, Value>;\n\nexport type ConstructedSingleton<Type, Args, Return> = {\n lifetime: Lifetime.Singleton;\n type: Type;\n factory: (\n args: Args,\n resolve: <T extends keyof Args>(\n token: T,\n context?: Record<string, unknown>\n ) => Args[T],\n context: Record<string, unknown>\n ) => Return;\n};\n\nexport type Constructed<Type, Args, Return> = {\n lifetime: Lifetime.Transient | Lifetime.Scoped;\n type: Type;\n factory: (\n args: Args,\n resolve: <T extends keyof Args>(\n token: T,\n context?: Record<string, unknown>\n ) => Args[T],\n context: Record<string, unknown>\n ) => Return;\n};\n\nexport type Constructor = new (...args: never[]) => unknown;\nexport type SchemaConstructor<SV extends AnySchemaValidator> = new (\n ...args: unknown[]\n) => IdiomaticSchema<SV>;\nexport type Function = (...args: never[]) => unknown;\nexport type SchemaFunction<SV extends AnySchemaValidator> = (\n args: unknown\n) => IdiomaticSchema<SV>;\n\ntype ConfigTypes<SV extends AnySchemaValidator> =\n | Function\n | SchemaFunction<SV>\n | Constructor\n | SchemaConstructor<SV>\n | IdiomaticSchema<SV>;\n\nexport type ConfigValidator<SV extends AnySchemaValidator> = Record<\n string,\n ConfigTypes<SV> | Record<string, ConfigTypes<SV>>\n>;\n\ntype ResolveConfigValue<SV extends AnySchemaValidator, T> =\n T extends SchemaConstructor<SV>\n ? Schema<InstanceType<T>, SV>\n : T extends SchemaFunction<SV>\n ? Schema<ReturnType<T>, SV>\n : T extends Function\n ? ReturnType<T>\n : T extends Constructor\n ? InstanceType<T>\n : T extends Record<string, ConfigTypes<SV>>\n ? {\n [K in keyof T]: ResolveConfigValue<SV, T[K]>;\n }\n : Schema<T, SV>;\n\nexport type ResolvedConfigValidator<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n> = {\n [M in keyof CV]: ResolveConfigValue<SV, CV[M]>;\n};\n\nexport type ScopedDependencyFactory<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>,\n M extends keyof CV\n> = (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[M];\n","import { ConstructedSingleton, Lifetime } from '../types/configInjector.types';\n\nexport function isConstructedSingleton<Type, Args, Return>(\n value: unknown\n): value is ConstructedSingleton<Type, Args, Return> {\n return (\n typeof value === 'object' &&\n value != null &&\n 'lifetime' in value &&\n value.lifetime === Lifetime.Singleton &&\n 'factory' in value\n );\n}\n","import { Constructor } from '../types/configInjector.types';\n\nexport function isConstructor(value: unknown): value is Constructor {\n return (\n typeof value === 'function' &&\n value.constructor != null &&\n value.prototype != null\n );\n}\n","// This is a simple function that returns the value of an environment variable.\n// It casts a potentially undefined value to a string, since it will be validated in order to be bootstrapped.\n\nexport function getEnvVar(name: string): string {\n const value = process.env[name];\n return value as string;\n}\n"],"mappings":"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","names":["Lifetime"]}
@@ -28,14 +28,30 @@ function isConstructor(value) {
28
28
  }
29
29
 
30
30
  // src/services/configInjector.ts
31
+ function createConfigInjector(schemaValidator, dependenciesDefinition) {
32
+ return new ConfigInjector(schemaValidator, dependenciesDefinition);
33
+ }
31
34
  var ConfigInjector = class _ConfigInjector {
32
- constructor(schemaValidator, configShapes, dependenciesDefinition, inheritedScopeInstances) {
35
+ constructor(schemaValidator, dependenciesDefinition) {
33
36
  this.schemaValidator = schemaValidator;
34
- this.configShapes = configShapes;
35
37
  this.dependenciesDefinition = dependenciesDefinition;
36
- this.loadSingletons(inheritedScopeInstances);
38
+ this.configShapes = Object.entries(this.dependenciesDefinition).reduce(
39
+ (acc, [key, { type }]) => ({
40
+ ...acc,
41
+ [key]: type
42
+ }),
43
+ {}
44
+ );
45
+ this.loadSingletons();
37
46
  }
38
47
  instances = {};
48
+ configShapes;
49
+ load(inheritedScopeInstances) {
50
+ for (const token in inheritedScopeInstances) {
51
+ this.instances[token] = inheritedScopeInstances[token];
52
+ }
53
+ return this;
54
+ }
39
55
  loadSingletons(inheritedScopeInstances) {
40
56
  for (const token in this.dependenciesDefinition) {
41
57
  const definition = this.dependenciesDefinition[token];
@@ -52,10 +68,11 @@ var ConfigInjector = class _ConfigInjector {
52
68
  }
53
69
  }
54
70
  }
71
+ return this;
55
72
  }
56
73
  resolveInstance(token, definition, context, resolutionPath = []) {
57
74
  const injectorArgument = extractArgumentNames(definition.factory)[0];
58
- if (injectorArgument === "_args") {
75
+ if (!injectorArgument || injectorArgument === "_args") {
59
76
  return definition.factory(
60
77
  {},
61
78
  this.resolve.bind(this),
@@ -149,10 +166,8 @@ var ConfigInjector = class _ConfigInjector {
149
166
  ok: true,
150
167
  value: new ValidConfigInjector(
151
168
  this.schemaValidator,
152
- this.configShapes,
153
- this.dependenciesDefinition,
154
- this.instances
155
- )
169
+ this.dependenciesDefinition
170
+ ).loadSingletons({ ...this.instances })
156
171
  } : {
157
172
  ok: false,
158
173
  errors: [
@@ -181,9 +196,22 @@ var ConfigInjector = class _ConfigInjector {
181
196
  }
182
197
  switch (definition.lifetime) {
183
198
  case 0 /* Singleton */: {
199
+ if (isConstructedSingleton(definition) && !this.instances[token]) {
200
+ this.instances[token] = this.resolveInstance(
201
+ token,
202
+ definition,
203
+ context,
204
+ resolutionPath
205
+ );
206
+ }
184
207
  return this.instances[token];
185
208
  }
186
209
  case 2 /* Scoped */: {
210
+ if (!isConstructed(definition)) {
211
+ throw new Error(
212
+ `Invalid dependency definition for ${String(token)}`
213
+ );
214
+ }
187
215
  const scopedInstance = this.resolveInstance(
188
216
  token,
189
217
  definition,
@@ -194,6 +222,11 @@ var ConfigInjector = class _ConfigInjector {
194
222
  return scopedInstance;
195
223
  }
196
224
  case 1 /* Transient */: {
225
+ if (!isConstructed(definition)) {
226
+ throw new Error(
227
+ `Invalid dependency definition for ${String(token)}`
228
+ );
229
+ }
197
230
  return this.resolveInstance(
198
231
  token,
199
232
  definition,
@@ -220,15 +253,24 @@ var ConfigInjector = class _ConfigInjector {
220
253
  createScope() {
221
254
  return new _ConfigInjector(
222
255
  this.schemaValidator,
223
- this.configShapes,
224
- this.dependenciesDefinition,
225
- this.instances
226
- );
256
+ this.dependenciesDefinition
257
+ ).loadSingletons({ ...this.instances });
227
258
  }
228
259
  dispose() {
229
260
  this.instances = {};
230
261
  this.loadSingletons();
231
262
  }
263
+ chain(dependenciesDefinition) {
264
+ return new _ConfigInjector(this.schemaValidator, {
265
+ ...this.dependenciesDefinition,
266
+ ...dependenciesDefinition
267
+ }).load({ ...this.instances });
268
+ }
269
+ tokens() {
270
+ return Object.fromEntries(
271
+ Object.keys(this.dependenciesDefinition).map((key) => [key, key])
272
+ );
273
+ }
232
274
  };
233
275
  var ValidConfigInjector = class extends ConfigInjector {
234
276
  validConfigInjector;
@@ -243,6 +285,7 @@ export {
243
285
  ConfigInjector,
244
286
  Lifetime,
245
287
  ValidConfigInjector,
288
+ createConfigInjector,
246
289
  getEnvVar
247
290
  };
248
291
  //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/services/configInjector.ts","../../../src/services/guards/isConstructed.ts","../../../src/services/types/configInjector.types.ts","../../../src/services/guards/isConstructedSingleton.ts","../../../src/services/guards/isConstructor.ts","../../../src/services/getEnvVar.ts"],"sourcesContent":["import { extractArgumentNames, isNever } from '@forklaunch/common';\nimport {\n AnySchemaValidator,\n IdiomaticSchema,\n ParseResult,\n prettyPrintParseErrors,\n SchemaValidator\n} from '@forklaunch/validator';\nimport { isConstructed } from './guards/isConstructed';\nimport { isConstructedSingleton } from './guards/isConstructedSingleton';\nimport { isConstructor } from './guards/isConstructor';\nimport {\n ConfigValidator,\n Constructed,\n ConstructedSingleton,\n Lifetime,\n ResolvedConfigValidator,\n SchemaConstructor,\n SchemaFunction,\n Singleton\n} from './types/configInjector.types';\n\nexport function createConfigInjector<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n>(\n schemaValidator: SV,\n dependenciesDefinition: {\n [K in keyof CV]:\n | Singleton<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >\n | Constructed<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >;\n }\n) {\n return new ConfigInjector<SV, CV>(schemaValidator, dependenciesDefinition);\n}\n\nexport class ConfigInjector<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n> {\n instances: {\n [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];\n } = {};\n\n readonly configShapes: CV;\n\n load(inheritedScopeInstances?: {\n [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];\n }): this {\n for (const token in inheritedScopeInstances) {\n this.instances[token] = inheritedScopeInstances[token];\n }\n return this;\n }\n\n private loadSingletons(inheritedScopeInstances?: {\n [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];\n }): this {\n for (const token in this.dependenciesDefinition) {\n const definition = this.dependenciesDefinition[token];\n if (definition.lifetime === Lifetime.Singleton) {\n if (inheritedScopeInstances && inheritedScopeInstances[token]) {\n this.instances[token] = inheritedScopeInstances[token];\n } else if (\n isConstructedSingleton<\n CV[typeof token],\n Omit<ResolvedConfigValidator<SV, CV>, typeof token>,\n ResolvedConfigValidator<SV, CV>[typeof token]\n >(definition)\n ) {\n this.instances[token] = this.resolveInstance<typeof token>(\n token,\n definition\n );\n } else {\n this.instances[token] = definition.value;\n }\n }\n }\n return this;\n }\n\n private resolveInstance<T extends keyof CV>(\n token: T,\n definition:\n | ConstructedSingleton<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >\n | Constructed<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >,\n context?: Record<string, unknown>,\n resolutionPath: (keyof CV)[] = []\n ): ResolvedConfigValidator<SV, CV>[T] {\n const injectorArgument = extractArgumentNames(definition.factory)[0];\n // short circuit as no args\n if (!injectorArgument || injectorArgument === '_args') {\n return definition.factory(\n {} as Omit<ResolvedConfigValidator<SV, CV>, T>,\n this.resolve.bind(this),\n context ?? ({} as Record<string, unknown>)\n );\n }\n\n if (!injectorArgument.startsWith('{') || !injectorArgument.endsWith('}')) {\n throw new Error(\n `Invalid injector argument for ${String(\n token\n )}: ${injectorArgument}. Please use object destructuring syntax: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment.`\n );\n }\n const resolvedArguments = Object.fromEntries(\n injectorArgument\n .replace('{', '')\n .replace('}', '')\n .split(',')\n .map((arg) => arg.split(':')[0].trim())\n .map((arg) => {\n const newResolutionPath = [...resolutionPath, token];\n if (resolutionPath.includes(arg)) {\n throw new Error(\n `Circular dependency detected: ${newResolutionPath.join(\n ' -> '\n )} -> ${arg}`\n );\n }\n const resolvedArg = this.resolve(arg, context, newResolutionPath);\n return [arg, resolvedArg];\n })\n ) as unknown as Omit<ResolvedConfigValidator<SV, CV>, T>;\n return definition.factory(\n resolvedArguments,\n this.resolve.bind(this),\n context ?? ({} as Record<string, unknown>)\n );\n }\n\n constructor(\n private schemaValidator: SV,\n private dependenciesDefinition: {\n [K in keyof CV]: (\n | Singleton<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >\n | Constructed<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >\n ) & {\n type: CV[K];\n };\n }\n ) {\n this.configShapes = Object.entries(this.dependenciesDefinition).reduce(\n (acc, [key, { type }]) => ({\n ...acc,\n [key]: type\n }),\n {} as Record<keyof CV, CV[keyof CV]>\n ) as CV;\n this.loadSingletons();\n }\n\n safeValidateConfigSingletons(): ParseResult<ValidConfigInjector<SV, CV>> {\n const validNonSchemaSingletons = Object.entries(this.configShapes).reduce<\n ParseResult<ResolvedConfigValidator<SV, CV>>\n >(\n (acc, [key, value]) => {\n if (\n this.dependenciesDefinition[key].lifetime === Lifetime.Singleton &&\n !(this.schemaValidator as SchemaValidator).isSchema<\n SchemaFunction<SV> | SchemaConstructor<SV> | IdiomaticSchema<SV>\n >(value) &&\n isConstructor(value)\n ) {\n if (!(this.instances[key] instanceof value)) {\n const expected = value.name;\n const receivedValue: unknown = this.instances[key];\n const received = isConstructed(receivedValue)\n ? receivedValue.constructor.name\n : typeof receivedValue;\n\n if (acc.ok) {\n acc = {\n ok: false,\n errors: []\n };\n }\n acc.errors?.push({\n message: `Expected ${expected}, received ${received}`,\n path: [key]\n });\n } else {\n if (acc.ok) {\n acc = {\n ok: true,\n value: {\n ...acc.value,\n [key]: this.instances[key]\n }\n };\n }\n }\n return acc;\n }\n return acc;\n },\n {\n ok: true,\n value: {} as ResolvedConfigValidator<SV, CV>\n }\n );\n\n const singletons = Object.fromEntries(\n Object.entries(this.configShapes).filter(\n ([key, value]) =>\n this.dependenciesDefinition[key].lifetime === Lifetime.Singleton &&\n (this.schemaValidator as SchemaValidator).isSchema(value)\n )\n );\n const schemaSingletonParseResult = (\n this.schemaValidator as SchemaValidator\n ).parse(\n (this.schemaValidator as SchemaValidator).schemify(singletons),\n Object.fromEntries(\n Object.keys(singletons).map((key) => {\n const dependency = this.dependenciesDefinition[key];\n return [\n key,\n dependency.lifetime === Lifetime.Singleton\n ? this.instances[key]\n : undefined\n ];\n })\n )\n );\n\n const configKeys = Object.keys(this.configShapes);\n\n return validNonSchemaSingletons.ok && schemaSingletonParseResult.ok\n ? {\n ok: true as const,\n value: new ValidConfigInjector<SV, CV>(\n this.schemaValidator,\n this.dependenciesDefinition\n ).loadSingletons({ ...this.instances })\n }\n : {\n ok: false as const,\n errors: [\n ...(!validNonSchemaSingletons.ok && validNonSchemaSingletons.errors\n ? validNonSchemaSingletons.errors\n : []),\n ...(!schemaSingletonParseResult.ok &&\n schemaSingletonParseResult.errors\n ? schemaSingletonParseResult.errors\n : [])\n ].sort(\n (a, b) =>\n configKeys.indexOf(a.path[0]) - configKeys.indexOf(b.path[0])\n )\n };\n }\n\n validateConfigSingletons(configName: string): ValidConfigInjector<SV, CV> {\n const safeValidateResult = this.safeValidateConfigSingletons();\n\n if (safeValidateResult.ok) {\n return safeValidateResult.value;\n }\n\n throw new Error(\n prettyPrintParseErrors(safeValidateResult.errors, configName)\n );\n }\n\n resolve<T extends keyof CV>(\n token: T,\n context?: Record<string, unknown>,\n resolutionPath: (keyof CV)[] = []\n ): ResolvedConfigValidator<SV, CV>[T] {\n const instance = this.instances[token];\n if (!instance) {\n const definition = this.dependenciesDefinition[token];\n\n if (!definition) {\n throw new Error(`Unable to resolve dependency ${String(token)}`);\n }\n\n switch (definition.lifetime) {\n case Lifetime.Singleton: {\n if (\n isConstructedSingleton<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >(definition) &&\n !this.instances[token]\n ) {\n this.instances[token] = this.resolveInstance<T>(\n token,\n definition,\n context,\n resolutionPath\n );\n }\n return this.instances[token] as ResolvedConfigValidator<SV, CV>[T];\n }\n case Lifetime.Scoped: {\n if (\n !isConstructed<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >(definition)\n ) {\n throw new Error(\n `Invalid dependency definition for ${String(token)}`\n );\n }\n\n const scopedInstance = this.resolveInstance<T>(\n token,\n definition,\n context,\n resolutionPath\n );\n this.instances[token] = scopedInstance;\n return scopedInstance;\n }\n case Lifetime.Transient: {\n if (\n !isConstructed<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >(definition)\n ) {\n throw new Error(\n `Invalid dependency definition for ${String(token)}`\n );\n }\n\n return this.resolveInstance<T>(\n token,\n definition,\n context,\n resolutionPath\n );\n }\n default: {\n isNever(definition);\n throw new Error(\n `Unable to resolve lifetime for dependency ${String(\n token\n )}, ${resolutionPath}`\n );\n }\n }\n } else {\n return instance;\n }\n }\n\n scopedResolver<T extends keyof CV>(\n token: T,\n context?: Record<string, unknown>,\n resolutionPath: (keyof CV)[] = []\n ): (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[T] {\n return (scope) =>\n (scope ?? this.createScope()).resolve<T>(token, context, resolutionPath);\n }\n\n createScope(): ConfigInjector<SV, CV> {\n return new ConfigInjector<SV, CV>(\n this.schemaValidator,\n this.dependenciesDefinition\n ).loadSingletons({ ...this.instances });\n }\n\n dispose(): void {\n this.instances = {};\n this.loadSingletons();\n }\n\n chain<ChainedCV extends ConfigValidator<SV>>(dependenciesDefinition: {\n [K in keyof ChainedCV]: {\n type: ChainedCV[K];\n } & (\n | Singleton<\n ChainedCV[K],\n Omit<ResolvedConfigValidator<SV, CV & ChainedCV>, K>,\n ResolvedConfigValidator<SV, ChainedCV>[K]\n >\n | Constructed<\n ChainedCV[K],\n Omit<ResolvedConfigValidator<SV, CV & ChainedCV>, K>,\n ResolvedConfigValidator<SV, ChainedCV>[K]\n >\n );\n }): ConfigInjector<SV, CV & ChainedCV> {\n return new ConfigInjector<SV, CV>(this.schemaValidator, {\n ...this.dependenciesDefinition,\n ...dependenciesDefinition\n }).load({ ...this.instances }) as unknown as ConfigInjector<\n SV,\n CV & ChainedCV\n >;\n }\n\n tokens(): {\n [K in keyof CV]: K;\n } {\n return Object.fromEntries(\n Object.keys(this.dependenciesDefinition).map((key) => [key, key])\n ) as {\n [K in keyof CV]: K;\n };\n }\n}\n\nexport class ValidConfigInjector<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n> extends ConfigInjector<SV, CV> {\n validConfigInjector!: void;\n}\n","import { Constructed } from '../types/configInjector.types';\n\nexport function isConstructed<Type, Args, Return>(\n value: unknown\n): value is Constructed<Type, Args, Return> {\n return (\n typeof value === 'object' &&\n value != null &&\n 'constructor' in value &&\n value.constructor != null\n );\n}\n","import {\n AnySchemaValidator,\n IdiomaticSchema,\n Schema\n} from '@forklaunch/validator';\nimport { ConfigInjector } from '../configInjector';\n\nexport enum Lifetime {\n Singleton,\n Transient,\n Scoped\n}\n\nexport type Singleton<Type, Args, Value> =\n | {\n lifetime: Lifetime.Singleton;\n type: Type;\n value: Value;\n }\n | ConstructedSingleton<Type, Args, Value>;\n\nexport type ConstructedSingleton<Type, Args, Return> = {\n lifetime: Lifetime.Singleton;\n type: Type;\n factory: (\n args: Args,\n resolve: <T extends keyof Args>(\n token: T,\n context?: Record<string, unknown>\n ) => Args[T],\n context: Record<string, unknown>\n ) => Return;\n};\n\nexport type Constructed<Type, Args, Return> = {\n lifetime: Lifetime.Transient | Lifetime.Scoped;\n type: Type;\n factory: (\n args: Args,\n resolve: <T extends keyof Args>(\n token: T,\n context?: Record<string, unknown>\n ) => Args[T],\n context: Record<string, unknown>\n ) => Return;\n};\n\nexport type Constructor = new (...args: never[]) => unknown;\nexport type SchemaConstructor<SV extends AnySchemaValidator> = new (\n ...args: unknown[]\n) => IdiomaticSchema<SV>;\nexport type Function = (...args: never[]) => unknown;\nexport type SchemaFunction<SV extends AnySchemaValidator> = (\n args: unknown\n) => IdiomaticSchema<SV>;\n\ntype ConfigTypes<SV extends AnySchemaValidator> =\n | Function\n | SchemaFunction<SV>\n | Constructor\n | SchemaConstructor<SV>\n | IdiomaticSchema<SV>;\n\nexport type ConfigValidator<SV extends AnySchemaValidator> = Record<\n string,\n ConfigTypes<SV> | Record<string, ConfigTypes<SV>>\n>;\n\ntype ResolveConfigValue<SV extends AnySchemaValidator, T> =\n T extends SchemaConstructor<SV>\n ? Schema<InstanceType<T>, SV>\n : T extends SchemaFunction<SV>\n ? Schema<ReturnType<T>, SV>\n : T extends Function\n ? ReturnType<T>\n : T extends Constructor\n ? InstanceType<T>\n : T extends Record<string, ConfigTypes<SV>>\n ? {\n [K in keyof T]: ResolveConfigValue<SV, T[K]>;\n }\n : Schema<T, SV>;\n\nexport type ResolvedConfigValidator<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n> = {\n [M in keyof CV]: ResolveConfigValue<SV, CV[M]>;\n};\n\nexport type ScopedDependencyFactory<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>,\n M extends keyof CV\n> = (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[M];\n","import { ConstructedSingleton, Lifetime } from '../types/configInjector.types';\n\nexport function isConstructedSingleton<Type, Args, Return>(\n value: unknown\n): value is ConstructedSingleton<Type, Args, Return> {\n return (\n typeof value === 'object' &&\n value != null &&\n 'lifetime' in value &&\n value.lifetime === Lifetime.Singleton &&\n 'factory' in value\n );\n}\n","import { Constructor } from '../types/configInjector.types';\n\nexport function isConstructor(value: unknown): value is Constructor {\n return (\n typeof value === 'function' &&\n value.constructor != null &&\n value.prototype != null\n );\n}\n","// This is a simple function that returns the value of an environment variable.\n// It casts a potentially undefined value to a string, since it will be validated in order to be bootstrapped.\n\nexport function getEnvVar(name: string): string {\n const value = process.env[name];\n return value as string;\n}\n"],"mappings":"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","names":["Lifetime"]}