@proto-kit/common 0.1.1-develop.211 → 0.1.1-develop.2137

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 (258) hide show
  1. package/dist/cache/CacheManifest.d.ts +11 -0
  2. package/dist/cache/CacheManifest.d.ts.map +1 -0
  3. package/dist/cache/CacheManifest.js +56 -0
  4. package/dist/cache/CacheManifest.js.map +1 -0
  5. package/dist/cache/ProxyCache.d.ts +13 -0
  6. package/dist/cache/ProxyCache.d.ts.map +1 -0
  7. package/dist/cache/ProxyCache.js +24 -0
  8. package/dist/cache/ProxyCache.js.map +1 -0
  9. package/dist/cache/RemoteCache.d.ts +8 -0
  10. package/dist/cache/RemoteCache.d.ts.map +1 -0
  11. package/dist/cache/RemoteCache.js +2 -0
  12. package/dist/cache/RemoteCache.js.map +1 -0
  13. package/dist/cache/RemoteCacheCompiler.d.ts +16 -0
  14. package/dist/cache/RemoteCacheCompiler.d.ts.map +1 -0
  15. package/dist/cache/RemoteCacheCompiler.js +104 -0
  16. package/dist/cache/RemoteCacheCompiler.js.map +1 -0
  17. package/dist/compiling/AtomicCompileHelper.d.ts +15 -0
  18. package/dist/compiling/AtomicCompileHelper.d.ts.map +1 -0
  19. package/dist/compiling/AtomicCompileHelper.js +61 -0
  20. package/dist/compiling/AtomicCompileHelper.js.map +1 -0
  21. package/dist/compiling/CompilableModule.d.ts +6 -0
  22. package/dist/compiling/CompilableModule.d.ts.map +1 -0
  23. package/dist/compiling/CompilableModule.js +2 -0
  24. package/dist/compiling/CompilableModule.js.map +1 -0
  25. package/dist/compiling/CompileRegistry.d.ts +25 -0
  26. package/dist/compiling/CompileRegistry.d.ts.map +1 -0
  27. package/dist/compiling/CompileRegistry.js +62 -0
  28. package/dist/compiling/CompileRegistry.js.map +1 -0
  29. package/dist/compiling/services/ChildVerificationKeyService.d.ts +10 -0
  30. package/dist/compiling/services/ChildVerificationKeyService.d.ts.map +1 -0
  31. package/dist/compiling/services/ChildVerificationKeyService.js +27 -0
  32. package/dist/compiling/services/ChildVerificationKeyService.js.map +1 -0
  33. package/dist/config/ChildContainerCreatable.d.ts +5 -0
  34. package/dist/config/ChildContainerCreatable.d.ts.map +1 -0
  35. package/dist/config/ChildContainerCreatable.js +2 -0
  36. package/dist/config/ChildContainerCreatable.js.map +1 -0
  37. package/dist/config/ChildContainerProvider.d.ts +5 -0
  38. package/dist/config/ChildContainerProvider.d.ts.map +1 -0
  39. package/dist/config/ChildContainerProvider.js +2 -0
  40. package/dist/config/ChildContainerProvider.js.map +1 -0
  41. package/dist/config/ConfigurableModule.d.ts +6 -2
  42. package/dist/config/ConfigurableModule.d.ts.map +1 -1
  43. package/dist/config/ConfigurableModule.js +5 -0
  44. package/dist/config/ConfigurableModule.js.map +1 -0
  45. package/dist/config/ModuleContainer.d.ts +70 -23
  46. package/dist/config/ModuleContainer.d.ts.map +1 -1
  47. package/dist/config/ModuleContainer.js +164 -31
  48. package/dist/config/ModuleContainer.js.map +1 -0
  49. package/dist/config/Startable.d.ts +4 -0
  50. package/dist/config/Startable.d.ts.map +1 -0
  51. package/dist/config/Startable.js +2 -0
  52. package/dist/config/Startable.js.map +1 -0
  53. package/dist/config/injectAlias.d.ts +18 -0
  54. package/dist/config/injectAlias.d.ts.map +1 -0
  55. package/dist/config/injectAlias.js +47 -0
  56. package/dist/config/injectAlias.js.map +1 -0
  57. package/dist/dependencyFactory/DependencyFactory.d.ts +14 -9
  58. package/dist/dependencyFactory/DependencyFactory.d.ts.map +1 -1
  59. package/dist/dependencyFactory/DependencyFactory.js +2 -96
  60. package/dist/dependencyFactory/DependencyFactory.js.map +1 -0
  61. package/dist/dependencyFactory/injectOptional.d.ts +16 -0
  62. package/dist/dependencyFactory/injectOptional.d.ts.map +1 -0
  63. package/dist/dependencyFactory/injectOptional.js +40 -0
  64. package/dist/dependencyFactory/injectOptional.js.map +1 -0
  65. package/dist/dummyVerificationKey.d.ts +3 -0
  66. package/dist/dummyVerificationKey.d.ts.map +1 -0
  67. package/dist/dummyVerificationKey.js +8 -0
  68. package/dist/dummyVerificationKey.js.map +1 -0
  69. package/dist/events/EventEmitter.d.ts +19 -0
  70. package/dist/events/EventEmitter.d.ts.map +1 -0
  71. package/dist/events/EventEmitter.js +35 -0
  72. package/dist/events/EventEmitter.js.map +1 -0
  73. package/dist/events/EventEmitterProxy.d.ts +18 -0
  74. package/dist/events/EventEmitterProxy.d.ts.map +1 -0
  75. package/dist/events/EventEmitterProxy.js +35 -0
  76. package/dist/events/EventEmitterProxy.js.map +1 -0
  77. package/dist/events/EventEmittingComponent.d.ts +9 -0
  78. package/dist/events/EventEmittingComponent.d.ts.map +1 -0
  79. package/dist/events/EventEmittingComponent.js +2 -0
  80. package/dist/events/EventEmittingComponent.js.map +1 -0
  81. package/dist/events/ReplayingSingleUseEventEmitter.d.ts +17 -0
  82. package/dist/events/ReplayingSingleUseEventEmitter.d.ts.map +1 -0
  83. package/dist/events/ReplayingSingleUseEventEmitter.js +34 -0
  84. package/dist/events/ReplayingSingleUseEventEmitter.js.map +1 -0
  85. package/dist/index.d.ts +27 -1
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +28 -2
  88. package/dist/index.js.map +1 -0
  89. package/dist/log.d.ts +37 -0
  90. package/dist/log.d.ts.map +1 -0
  91. package/dist/log.js +117 -0
  92. package/dist/log.js.map +1 -0
  93. package/dist/trees/InMemoryLinkedLeafStore.d.ts +21 -0
  94. package/dist/trees/InMemoryLinkedLeafStore.d.ts.map +1 -0
  95. package/dist/trees/InMemoryLinkedLeafStore.js +26 -0
  96. package/dist/trees/InMemoryLinkedLeafStore.js.map +1 -0
  97. package/dist/trees/InMemoryLinkedMerkleLeafStore.d.ts +7 -0
  98. package/dist/trees/InMemoryLinkedMerkleLeafStore.d.ts.map +1 -0
  99. package/dist/trees/InMemoryLinkedMerkleLeafStore.js +6 -0
  100. package/dist/trees/InMemoryLinkedMerkleLeafStore.js.map +1 -0
  101. package/dist/trees/InMemoryMerkleTreeStorage.d.ts +11 -0
  102. package/dist/trees/InMemoryMerkleTreeStorage.d.ts.map +1 -0
  103. package/dist/trees/InMemoryMerkleTreeStorage.js +13 -0
  104. package/dist/trees/InMemoryMerkleTreeStorage.js.map +1 -0
  105. package/dist/trees/LinkedMerkleTree.d.ts +345 -0
  106. package/dist/trees/LinkedMerkleTree.d.ts.map +1 -0
  107. package/dist/trees/LinkedMerkleTree.js +337 -0
  108. package/dist/trees/LinkedMerkleTree.js.map +1 -0
  109. package/dist/trees/LinkedMerkleTreeStore.d.ts +24 -0
  110. package/dist/trees/LinkedMerkleTreeStore.d.ts.map +1 -0
  111. package/dist/trees/LinkedMerkleTreeStore.js +2 -0
  112. package/dist/trees/LinkedMerkleTreeStore.js.map +1 -0
  113. package/dist/trees/MerkleTreeStore.d.ts +5 -0
  114. package/dist/trees/MerkleTreeStore.d.ts.map +1 -0
  115. package/dist/trees/MerkleTreeStore.js +2 -0
  116. package/dist/trees/MerkleTreeStore.js.map +1 -0
  117. package/dist/trees/MockAsyncMerkleStore.d.ts +9 -0
  118. package/dist/trees/MockAsyncMerkleStore.d.ts.map +1 -0
  119. package/dist/trees/MockAsyncMerkleStore.js +20 -0
  120. package/dist/trees/MockAsyncMerkleStore.js.map +1 -0
  121. package/dist/trees/RollupMerkleTree.d.ts +147 -0
  122. package/dist/trees/RollupMerkleTree.d.ts.map +1 -0
  123. package/dist/trees/RollupMerkleTree.js +218 -0
  124. package/dist/trees/RollupMerkleTree.js.map +1 -0
  125. package/dist/trees/VirtualMerkleTreeStore.d.ts +13 -0
  126. package/dist/trees/VirtualMerkleTreeStore.d.ts.map +1 -0
  127. package/dist/trees/VirtualMerkleTreeStore.js +18 -0
  128. package/dist/trees/VirtualMerkleTreeStore.js.map +1 -0
  129. package/dist/trees/lmt/AbstractLinkedMerkleTree.d.ts +288 -0
  130. package/dist/trees/lmt/AbstractLinkedMerkleTree.d.ts.map +1 -0
  131. package/dist/trees/lmt/AbstractLinkedMerkleTree.js +22 -0
  132. package/dist/trees/lmt/AbstractLinkedMerkleTree.js.map +1 -0
  133. package/dist/trees/lmt/InMemoryLinkedLeafStore.d.ts +21 -0
  134. package/dist/trees/lmt/InMemoryLinkedLeafStore.d.ts.map +1 -0
  135. package/dist/trees/lmt/InMemoryLinkedLeafStore.js +26 -0
  136. package/dist/trees/lmt/InMemoryLinkedLeafStore.js.map +1 -0
  137. package/dist/trees/lmt/InMemoryLinkedMerkleLeafStore.d.ts +7 -0
  138. package/dist/trees/lmt/InMemoryLinkedMerkleLeafStore.d.ts.map +1 -0
  139. package/dist/trees/lmt/InMemoryLinkedMerkleLeafStore.js +6 -0
  140. package/dist/trees/lmt/InMemoryLinkedMerkleLeafStore.js.map +1 -0
  141. package/dist/trees/lmt/LinkedLeafStore.d.ts +16 -0
  142. package/dist/trees/lmt/LinkedLeafStore.d.ts.map +1 -0
  143. package/dist/trees/lmt/LinkedLeafStore.js +2 -0
  144. package/dist/trees/lmt/LinkedLeafStore.js.map +1 -0
  145. package/dist/trees/lmt/LinkedLinkedStore.d.ts +16 -0
  146. package/dist/trees/lmt/LinkedLinkedStore.d.ts.map +1 -0
  147. package/dist/trees/lmt/LinkedLinkedStore.js +2 -0
  148. package/dist/trees/lmt/LinkedLinkedStore.js.map +1 -0
  149. package/dist/trees/lmt/LinkedMerkleTree.d.ts +11 -0
  150. package/dist/trees/lmt/LinkedMerkleTree.d.ts.map +1 -0
  151. package/dist/trees/lmt/LinkedMerkleTree.js +241 -0
  152. package/dist/trees/lmt/LinkedMerkleTree.js.map +1 -0
  153. package/dist/trees/lmt/LinkedMerkleTreeCircuitOps.d.ts +113 -0
  154. package/dist/trees/lmt/LinkedMerkleTreeCircuitOps.d.ts.map +1 -0
  155. package/dist/trees/lmt/LinkedMerkleTreeCircuitOps.js +113 -0
  156. package/dist/trees/lmt/LinkedMerkleTreeCircuitOps.js.map +1 -0
  157. package/dist/trees/lmt/LinkedMerkleTreeDatabase.d.ts +7 -0
  158. package/dist/trees/lmt/LinkedMerkleTreeDatabase.d.ts.map +1 -0
  159. package/dist/trees/lmt/LinkedMerkleTreeDatabase.js +2 -0
  160. package/dist/trees/lmt/LinkedMerkleTreeDatabase.js.map +1 -0
  161. package/dist/trees/lmt/LinkedMerkleTreeStore.d.ts +16 -0
  162. package/dist/trees/lmt/LinkedMerkleTreeStore.d.ts.map +1 -0
  163. package/dist/trees/lmt/LinkedMerkleTreeStore.js +2 -0
  164. package/dist/trees/lmt/LinkedMerkleTreeStore.js.map +1 -0
  165. package/dist/trees/lmt/LinkedMerkleTreeTypes.d.ts +74 -0
  166. package/dist/trees/lmt/LinkedMerkleTreeTypes.d.ts.map +1 -0
  167. package/dist/trees/lmt/LinkedMerkleTreeTypes.js +50 -0
  168. package/dist/trees/lmt/LinkedMerkleTreeTypes.js.map +1 -0
  169. package/dist/trees/sparse/InMemoryMerkleTreeStorage.d.ts +11 -0
  170. package/dist/trees/sparse/InMemoryMerkleTreeStorage.d.ts.map +1 -0
  171. package/dist/trees/sparse/InMemoryMerkleTreeStorage.js +13 -0
  172. package/dist/trees/sparse/InMemoryMerkleTreeStorage.js.map +1 -0
  173. package/dist/trees/sparse/MerkleTreeStore.d.ts +5 -0
  174. package/dist/trees/sparse/MerkleTreeStore.d.ts.map +1 -0
  175. package/dist/trees/sparse/MerkleTreeStore.js +2 -0
  176. package/dist/trees/sparse/MerkleTreeStore.js.map +1 -0
  177. package/dist/trees/sparse/MockAsyncMerkleStore.d.ts +9 -0
  178. package/dist/trees/sparse/MockAsyncMerkleStore.d.ts.map +1 -0
  179. package/dist/trees/sparse/MockAsyncMerkleStore.js +20 -0
  180. package/dist/trees/sparse/MockAsyncMerkleStore.js.map +1 -0
  181. package/dist/trees/sparse/RollupMerkleTree.d.ts +158 -0
  182. package/dist/trees/sparse/RollupMerkleTree.d.ts.map +1 -0
  183. package/dist/trees/sparse/RollupMerkleTree.js +330 -0
  184. package/dist/trees/sparse/RollupMerkleTree.js.map +1 -0
  185. package/dist/types.d.ts +62 -0
  186. package/dist/types.d.ts.map +1 -1
  187. package/dist/types.js +14 -1
  188. package/dist/types.js.map +1 -0
  189. package/dist/union/union.d.ts +177 -0
  190. package/dist/union/union.d.ts.map +1 -0
  191. package/dist/union/union.js +35 -0
  192. package/dist/union/union.js.map +1 -0
  193. package/dist/utils.d.ts +57 -2
  194. package/dist/utils.d.ts.map +1 -1
  195. package/dist/utils.js +153 -4
  196. package/dist/utils.js.map +1 -0
  197. package/dist/zkProgrammable/ProvableMethodExecutionContext.d.ts +4 -3
  198. package/dist/zkProgrammable/ProvableMethodExecutionContext.d.ts.map +1 -1
  199. package/dist/zkProgrammable/ProvableMethodExecutionContext.js +2 -3
  200. package/dist/zkProgrammable/ProvableMethodExecutionContext.js.map +1 -0
  201. package/dist/zkProgrammable/ZkProgrammable.d.ts +32 -11
  202. package/dist/zkProgrammable/ZkProgrammable.d.ts.map +1 -1
  203. package/dist/zkProgrammable/ZkProgrammable.js +36 -17
  204. package/dist/zkProgrammable/ZkProgrammable.js.map +1 -0
  205. package/dist/zkProgrammable/provableMethod.d.ts +7 -4
  206. package/dist/zkProgrammable/provableMethod.d.ts.map +1 -1
  207. package/dist/zkProgrammable/provableMethod.js +30 -14
  208. package/dist/zkProgrammable/provableMethod.js.map +1 -0
  209. package/jest.config.cjs +12 -1
  210. package/package.json +9 -7
  211. package/src/cache/CacheManifest.ts +57 -0
  212. package/src/cache/ProxyCache.ts +30 -0
  213. package/src/cache/RemoteCache.ts +9 -0
  214. package/src/cache/RemoteCacheCompiler.ts +131 -0
  215. package/src/compiling/AtomicCompileHelper.ts +71 -0
  216. package/src/compiling/CompilableModule.ts +6 -0
  217. package/src/compiling/CompileRegistry.ts +64 -0
  218. package/src/compiling/services/ChildVerificationKeyService.ts +26 -0
  219. package/src/config/ChildContainerCreatable.ts +5 -0
  220. package/src/config/ChildContainerProvider.ts +5 -0
  221. package/src/config/ConfigurableModule.ts +15 -2
  222. package/src/config/ModuleContainer.ts +286 -58
  223. package/src/config/Startable.ts +3 -0
  224. package/src/config/injectAlias.ts +70 -0
  225. package/src/dependencyFactory/DependencyFactory.ts +34 -109
  226. package/src/dummyVerificationKey.ts +10 -0
  227. package/src/events/EventEmitter.ts +61 -0
  228. package/src/events/EventEmitterProxy.ts +81 -0
  229. package/src/events/EventEmittingComponent.ts +11 -0
  230. package/src/events/ReplayingSingleUseEventEmitter.ts +42 -0
  231. package/src/index.ts +27 -2
  232. package/src/log.ts +145 -0
  233. package/src/trees/lmt/AbstractLinkedMerkleTree.ts +102 -0
  234. package/src/trees/lmt/InMemoryLinkedLeafStore.ts +42 -0
  235. package/src/trees/lmt/LinkedLeafStore.ts +13 -0
  236. package/src/trees/lmt/LinkedMerkleTree.ts +335 -0
  237. package/src/trees/lmt/LinkedMerkleTreeCircuitOps.ts +188 -0
  238. package/src/trees/lmt/LinkedMerkleTreeTypes.ts +53 -0
  239. package/src/trees/sparse/InMemoryMerkleTreeStorage.ts +17 -0
  240. package/src/trees/sparse/MerkleTreeStore.ts +5 -0
  241. package/src/trees/sparse/MockAsyncMerkleStore.ts +30 -0
  242. package/src/trees/sparse/RollupMerkleTree.ts +512 -0
  243. package/src/types.ts +53 -2
  244. package/src/utils.ts +281 -5
  245. package/src/zkProgrammable/ProvableMethodExecutionContext.ts +6 -6
  246. package/src/zkProgrammable/ZkProgrammable.ts +90 -35
  247. package/src/zkProgrammable/provableMethod.ts +50 -23
  248. package/test/config/ContainerEvents.test.ts +65 -0
  249. package/test/config/ModuleContainer.test.ts +146 -15
  250. package/test/config/injectAlias.test.ts +28 -0
  251. package/test/trees/LinkedMerkleTree.test.ts +124 -0
  252. package/test/trees/LinkedMerkleTreeCircuitOps.test.ts +147 -0
  253. package/test/trees/MerkleTree.test.ts +251 -0
  254. package/test/tsconfig.json +5 -2
  255. package/test/zkProgrammable/ZkProgrammable.test.ts +145 -119
  256. package/tsconfig.json +1 -1
  257. package/LICENSE.md +0 -201
  258. package/tsconfig.test.json +0 -9
@@ -1,12 +1,34 @@
1
1
  import "reflect-metadata";
2
2
 
3
- import { container, Frequency, InjectionToken, Lifecycle } from "tsyringe";
3
+ import {
4
+ DependencyContainer,
5
+ Frequency,
6
+ InjectionToken,
7
+ instanceCachingFactory,
8
+ isClassProvider,
9
+ isFactoryProvider,
10
+ isTokenProvider,
11
+ isValueProvider,
12
+ Lifecycle,
13
+ } from "tsyringe";
4
14
  import log from "loglevel";
5
-
6
- import { StringKeyOf, TypedClass } from "../types";
7
- import { DependencyFactory } from "../dependencyFactory/DependencyFactory";
8
-
9
- import { Configurable, ConfigurableModule } from "./ConfigurableModule";
15
+ import merge from "lodash/merge";
16
+
17
+ import { MergeObjects, StringKeyOf, TypedClass } from "../types";
18
+ import {
19
+ DependencyFactory,
20
+ InferDependencies,
21
+ } from "../dependencyFactory/DependencyFactory";
22
+ import { EventEmitterProxy } from "../events/EventEmitterProxy";
23
+
24
+ import {
25
+ Configurable,
26
+ ConfigurableModule,
27
+ NoConfig,
28
+ } from "./ConfigurableModule";
29
+ import { ChildContainerProvider } from "./ChildContainerProvider";
30
+ import { ChildContainerCreatable } from "./ChildContainerCreatable";
31
+ import { getInjectAliases } from "./injectAlias";
10
32
 
11
33
  const errors = {
12
34
  configNotSetInContainer: (moduleName: string) =>
@@ -16,8 +38,7 @@ const errors = {
16
38
 
17
39
  onlyValidModuleNames: (moduleName: NonNullable<unknown>) =>
18
40
  new Error(
19
- // eslint-disable-next-line max-len
20
- // eslint-disable-next-line @typescript-eslint/no-base-to-string,@typescript-eslint/restrict-template-expressions
41
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
21
42
  `Only known module names are allowed, using unknown module name: ${moduleName}`
22
43
  ),
23
44
 
@@ -35,17 +56,31 @@ const errors = {
35
56
  attempting to inject a dependency that is not registered
36
57
  as a runtime module for this chain: ${name}`
37
58
  ),
59
+
60
+ dependencyContainerNotSet: (className: string) =>
61
+ new Error(
62
+ `DependencyContainer not set. Be sure to only call DI-related function in create() and not inside the constructor. (${className})`
63
+ ),
64
+
65
+ validModuleInstance: (moduleName: string, moduleTypeName: string) =>
66
+ new Error(
67
+ `Incompatible module instance ("${moduleName}" not instanceof ${moduleTypeName})`
68
+ ),
38
69
  };
39
70
 
40
71
  export const ModuleContainerErrors = errors;
41
72
 
73
+ export interface BaseModuleInstanceType
74
+ extends ChildContainerCreatable,
75
+ Configurable<unknown> {}
76
+
42
77
  // determines that a module should be configurable by default
43
- export type BaseModuleType = TypedClass<Configurable<unknown>>;
78
+ export type BaseModuleType = TypedClass<BaseModuleInstanceType>;
44
79
 
45
80
  // allows to specify what kind of modules can be passed into a container
46
81
  export interface ModulesRecord<
47
82
  // use the default configurable module type
48
- ModuleType extends BaseModuleType = BaseModuleType
83
+ ModuleType extends BaseModuleType = BaseModuleType,
49
84
  > {
50
85
  [name: string]: ModuleType;
51
86
  }
@@ -56,26 +91,58 @@ export type ModulesConfig<Modules extends ModulesRecord> = {
56
91
  [ConfigKey in StringKeyOf<Modules>]: InstanceType<
57
92
  Modules[ConfigKey]
58
93
  > extends Configurable<infer Config>
59
- ? Config
94
+ ? Config extends NoConfig
95
+ ? Config | undefined
96
+ : Config
60
97
  : never;
61
98
  };
62
99
 
63
100
  /**
64
- * Parameters required when creating a module container instance
101
+ * This type make any config partial (i.e. optional) up to the first level
102
+ * So { Module: { a: { b: string } } }
103
+ * will become
104
+ * { Module?: { a?: { b: string } } }
105
+ * Note that b does not become optional, as we don't want nested objects to
106
+ * become unreasonably partialized (for example Field).
65
107
  */
66
- export interface ModuleContainerDefinition<Modules extends ModulesRecord> {
67
- modules: Modules;
68
- // config is optional, as it may be provided by the parent/wrapper class
69
- config?: ModulesConfig<Modules>;
108
+ export type RecursivePartial<T> = {
109
+ [Key in keyof T]?: Partial<T[Key]>;
110
+ };
111
+
112
+ // Removes all keys with a "never" value from an object
113
+ export type FilterNeverValues<Type extends Record<string, unknown>> = {
114
+ [Key in keyof Type as Type[Key] extends never ? never : Key]: Type[Key];
115
+ };
116
+
117
+ export type DependenciesFromModules<Modules extends ModulesRecord> =
118
+ FilterNeverValues<{
119
+ [Key in keyof Modules]: Modules[Key] extends TypedClass<DependencyFactory>
120
+ ? InferDependencies<InstanceType<Modules[Key]>>
121
+ : never;
122
+ }>;
123
+
124
+ export type ResolvableModules<Modules extends ModulesRecord> = MergeObjects<
125
+ DependenciesFromModules<Modules>
126
+ > &
127
+ Modules;
128
+
129
+ export interface ModuleContainerLike {
130
+ get dependencyContainer(): DependencyContainer;
131
+
132
+ resolveOrFail<ModuleType>(
133
+ moduleName: string,
134
+ moduleType: TypedClass<ModuleType>
135
+ ): ModuleType;
70
136
  }
71
137
 
72
138
  /**
73
139
  * Reusable module container facilitating registration, resolution
74
140
  * configuration, decoration and validation of modules
75
141
  */
76
- export class ModuleContainer<
77
- Modules extends ModulesRecord
78
- > extends ConfigurableModule<unknown> {
142
+ export class ModuleContainer<Modules extends ModulesRecord>
143
+ extends ConfigurableModule<ModulesConfig<Modules>>
144
+ implements ModuleContainerLike
145
+ {
79
146
  /**
80
147
  * Determines how often are modules decorated upon resolution
81
148
  * from the tsyringe DI container
@@ -83,19 +150,19 @@ export class ModuleContainer<
83
150
  private static readonly moduleDecorationFrequency: Frequency = "Once";
84
151
 
85
152
  // DI container holding all the registered modules
86
- protected readonly container = container.createChildContainer();
153
+ private providedContainer?: DependencyContainer = undefined;
87
154
 
88
- public constructor(public definition: ModuleContainerDefinition<Modules>) {
155
+ private eventEmitterProxy: EventEmitterProxy<Modules> | undefined = undefined;
156
+
157
+ public constructor(public definition: Modules) {
89
158
  super();
90
- // register all provided modules when the container is created
91
- this.registerModules(definition.modules);
92
159
  }
93
160
 
94
161
  /**
95
162
  * @returns list of module names
96
163
  */
97
164
  public get moduleNames() {
98
- return Object.keys(this.definition.modules);
165
+ return Object.keys(this.definition);
99
166
  }
100
167
 
101
168
  /**
@@ -127,27 +194,49 @@ export class ModuleContainer<
127
194
  });
128
195
  }
129
196
 
197
+ protected get container(): DependencyContainer {
198
+ this.assertContainerInitialized(this.providedContainer);
199
+ return this.providedContainer;
200
+ }
201
+
130
202
  /**
131
203
  * Assert that the iterated `moduleName` is of ModuleName type,
132
204
  * otherwise it may be just string e.g. when modules are iterated over
133
205
  * using e.g. a for loop.
134
206
  */
135
207
  public assertIsValidModuleName(
136
- modules: Modules,
137
208
  moduleName: string
138
209
  ): asserts moduleName is StringKeyOf<Modules> {
139
- this.isValidModuleName(modules, moduleName);
210
+ if (!this.isValidModuleName(this.definition, moduleName)) {
211
+ throw errors.onlyValidModuleNames(moduleName);
212
+ }
140
213
  }
141
214
 
142
215
  public isValidModuleName(
143
216
  modules: Modules,
144
217
  moduleName: number | string | symbol
145
- ): asserts moduleName is StringKeyOf<Modules> {
146
- if (!Object.prototype.hasOwnProperty.call(modules, moduleName)) {
147
- throw errors.onlyValidModuleNames(moduleName);
218
+ ): moduleName is StringKeyOf<Modules> {
219
+ return Object.prototype.hasOwnProperty.call(modules, moduleName);
220
+ }
221
+
222
+ public assertContainerInitialized(
223
+ container: DependencyContainer | undefined
224
+ ): asserts container is DependencyContainer {
225
+ if (container === undefined) {
226
+ throw errors.dependencyContainerNotSet(this.constructor.name);
148
227
  }
149
228
  }
150
229
 
230
+ protected registerAliases(originalToken: string, clas: TypedClass<any>) {
231
+ const aliases = getInjectAliases(clas);
232
+
233
+ aliases.forEach((alias) =>
234
+ this.container.register(alias, {
235
+ useToken: originalToken,
236
+ })
237
+ );
238
+ }
239
+
151
240
  /**
152
241
  * Register modules into the current container, and registers
153
242
  * a respective resolution hook in order to decorate the module
@@ -156,39 +245,41 @@ export class ModuleContainer<
156
245
  * @param modules
157
246
  */
158
247
  protected registerModules(modules: Modules) {
159
- for (const moduleName in modules) {
248
+ Object.keys(modules).forEach((moduleName) => {
160
249
  if (Object.prototype.hasOwnProperty.call(modules, moduleName)) {
161
- this.assertIsValidModuleName(modules, moduleName);
250
+ this.assertIsValidModuleName(moduleName);
162
251
 
163
252
  log.debug(`Registering module: ${moduleName}`);
164
253
 
254
+ const useClass = modules[moduleName];
255
+
165
256
  this.container.register(
166
257
  moduleName,
167
- { useClass: modules[moduleName] },
258
+ { useClass },
168
259
  { lifecycle: Lifecycle.ContainerScoped }
169
260
  );
170
261
  this.onAfterModuleResolution(moduleName);
262
+
263
+ this.registerAliases(moduleName, useClass);
264
+
265
+ if (this.isDependencyFactory(useClass)) {
266
+ this.useDependencyFactory(useClass);
267
+ }
171
268
  }
172
- }
269
+ });
173
270
  }
174
271
 
175
- /**
176
- * Inject a set of dependencies using the given list of DependencyFactories
177
- * This method should be called during startup
178
- */
179
- protected registerDependencyFactories(
180
- factories: TypedClass<DependencyFactory>[]
181
- ) {
182
- factories.forEach((factory) => {
183
- this.container.resolve(factory).initDependencies(this.container);
184
- });
272
+ public get events(): EventEmitterProxy<Modules> {
273
+ if (this.eventEmitterProxy === undefined) {
274
+ this.eventEmitterProxy = new EventEmitterProxy<Modules>(this);
275
+ }
276
+ return this.eventEmitterProxy;
185
277
  }
186
278
 
187
279
  /**
188
280
  * Register a non-module value into the current container
189
281
  * @param modules
190
282
  */
191
- // eslint-disable-next-line no-warning-comments
192
283
  // TODO Rename to plural since object is param
193
284
  public registerValue<Value>(modules: Record<string, Value>) {
194
285
  Object.entries(modules).forEach(([moduleName, useValue]) => {
@@ -205,7 +296,25 @@ export class ModuleContainer<
205
296
  * @param config
206
297
  */
207
298
  public configure(config: ModulesConfig<Modules>) {
208
- this.definition.config = config;
299
+ this.config = config;
300
+ }
301
+
302
+ public configurePartial(config: RecursivePartial<ModulesConfig<Modules>>) {
303
+ this.config = merge<
304
+ ModulesConfig<Modules> | NoConfig,
305
+ RecursivePartial<ModulesConfig<Modules>>
306
+ >(this.currentConfig ?? {}, config);
307
+ }
308
+
309
+ public get config() {
310
+ return super.config;
311
+ }
312
+
313
+ public set config(config: ModulesConfig<Modules>) {
314
+ super.config = merge<
315
+ ModulesConfig<Modules> | NoConfig,
316
+ ModulesConfig<Modules>
317
+ >(this.currentConfig ?? {}, config);
209
318
  }
210
319
 
211
320
  /**
@@ -218,23 +327,30 @@ export class ModuleContainer<
218
327
  * @param moduleName
219
328
  * @returns
220
329
  */
221
- public resolve<ResolvableModuleName extends StringKeyOf<Modules>>(
222
- moduleName: ResolvableModuleName
223
- ): InstanceType<Modules[ResolvableModuleName]> {
224
- return this.container.resolve<InstanceType<Modules[ResolvableModuleName]>>(
225
- moduleName
226
- );
330
+ public resolve<KeyType extends StringKeyOf<ResolvableModules<Modules>>>(
331
+ moduleName: KeyType
332
+ ): InstanceType<ResolvableModules<Modules>[KeyType]> {
333
+ return this.container.resolve<
334
+ InstanceType<ResolvableModules<Modules>[KeyType]>
335
+ >(moduleName);
227
336
  }
228
337
 
229
338
  public resolveOrFail<ModuleType>(
230
339
  moduleName: string,
231
- moduleType: TypedClass<ModuleType>
340
+ moduleType?: TypedClass<ModuleType>
232
341
  ) {
342
+ if (!this.container.isRegistered(moduleName)) {
343
+ throw new Error(`Dependency with token ${moduleName} not registered`);
344
+ }
345
+
233
346
  const instance = this.container.resolve<ModuleType>(moduleName);
234
- const isValidModuleInstance = instance instanceof moduleType;
235
347
 
236
- if (!isValidModuleInstance) {
237
- throw new Error("Incompatible module instance");
348
+ if (moduleType !== undefined) {
349
+ const isValidModuleInstance = instance instanceof moduleType;
350
+
351
+ if (!isValidModuleInstance) {
352
+ throw errors.validModuleInstance(moduleName, moduleType.name);
353
+ }
238
354
  }
239
355
 
240
356
  return instance;
@@ -248,14 +364,96 @@ export class ModuleContainer<
248
364
  moduleName: StringKeyOf<Modules>,
249
365
  containedModule: InstanceType<Modules[StringKeyOf<Modules>]>
250
366
  ) {
251
- const config = this.definition.config?.[moduleName];
252
-
367
+ const config = super.config?.[moduleName];
253
368
  // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
254
369
  if (!config) {
255
370
  throw errors.configNotSetInContainer(moduleName.toString());
256
371
  }
257
372
 
258
- containedModule.config = config;
373
+ if (containedModule instanceof ModuleContainer) {
374
+ containedModule.configure(config);
375
+ } else {
376
+ containedModule.config = config;
377
+ }
378
+ }
379
+
380
+ private isDependencyFactory(type: any): type is DependencyFactory {
381
+ return "dependencies" in type;
382
+ }
383
+
384
+ /**
385
+ * Inject a set of dependencies using the given list of DependencyFactories
386
+ * This method should be called during startup
387
+ */
388
+ protected initializeDependencyFactories(factories: StringKeyOf<Modules>[]) {
389
+ factories.forEach((factoryName) => {
390
+ this.resolve(factoryName);
391
+ });
392
+ }
393
+
394
+ /**
395
+ * Retrieves all dependencies generated by a particular dependencyfactory
396
+ * and injects them inside this modulecontainer's DI container.
397
+ * This will be automatically called for every module, but can also be called
398
+ * explicitly to initialize an extra factory
399
+ * @param factory
400
+ * @private
401
+ */
402
+ protected useDependencyFactory(factory: DependencyFactory) {
403
+ const dependencies = factory.dependencies();
404
+
405
+ // eslint-disable-next-line sonarjs/cognitive-complexity
406
+ Object.entries(dependencies).forEach(([rawKey, declaration]) => {
407
+ const key = rawKey.charAt(0).toUpperCase() + rawKey.slice(1);
408
+
409
+ if (
410
+ !this.container.isRegistered(key) ||
411
+ declaration.forceOverwrite === true
412
+ ) {
413
+ if (
414
+ this.container.isRegistered(key) &&
415
+ (declaration?.forceOverwrite ?? false)
416
+ ) {
417
+ log.warn(
418
+ `You are trying to overwrite dependency ${key}, which is already registered. This is currently not supported. Try to define your dependency earlier.`
419
+ );
420
+ }
421
+
422
+ // Find correct provider type and call respective register
423
+ if (isValueProvider(declaration)) {
424
+ this.container.register(key, declaration);
425
+ } else if (isFactoryProvider(declaration)) {
426
+ // this enables us to have a singletoned factory
427
+ // that returns the same instance for each resolve
428
+ this.container.register(key, {
429
+ useFactory: instanceCachingFactory(declaration.useFactory),
430
+ });
431
+ } else if (isClassProvider(declaration)) {
432
+ this.container.register(key, declaration, {
433
+ lifecycle: Lifecycle.Singleton,
434
+ });
435
+ this.registerAliases(
436
+ key,
437
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
438
+ declaration.useClass as TypedClass<unknown>
439
+ );
440
+
441
+ // Register static dependencies
442
+ if (this.isDependencyFactory(declaration.useClass)) {
443
+ this.useDependencyFactory(declaration.useClass);
444
+ }
445
+ } else if (isTokenProvider(declaration)) {
446
+ this.container.register(key, declaration, {
447
+ lifecycle: Lifecycle.Singleton,
448
+ });
449
+ } else {
450
+ // Can never be reached
451
+ throw new Error("Above if-statement is exhaustive");
452
+ }
453
+ } else {
454
+ log.debug(`Dependency ${key} already registered, skipping`);
455
+ }
456
+ });
259
457
  }
260
458
 
261
459
  /**
@@ -271,8 +469,38 @@ export class ModuleContainer<
271
469
  throw errors.unableToDecorateModule(containedModuleName);
272
470
  }
273
471
  this.decorateModule(moduleName, containedModule);
472
+ containedModule.create(() => {
473
+ const container = this.container.createChildContainer();
474
+ container.reset();
475
+ return container;
476
+ });
477
+
478
+ if (this.isDependencyFactory(containedModule)) {
479
+ this.useDependencyFactory(containedModule);
480
+ }
274
481
  },
275
482
  { frequency: ModuleContainer.moduleDecorationFrequency }
276
483
  );
277
484
  }
485
+
486
+ /**
487
+ * This is a placeholder for individual modules to override.
488
+ * This method will be called whenever the underlying container fully
489
+ * initialized
490
+ */
491
+ public create(childContainerProvider: ChildContainerProvider): void {
492
+ this.providedContainer = childContainerProvider();
493
+
494
+ this.registerValue({
495
+ ChildContainerProvider: () => this.container.createChildContainer(),
496
+ });
497
+
498
+ // register all provided modules when the container is created
499
+ this.registerModules(this.definition);
500
+ this.container.register("ParentContainer", { useValue: this });
501
+ }
502
+
503
+ public get dependencyContainer(): DependencyContainer {
504
+ return this.container;
505
+ }
278
506
  }
@@ -0,0 +1,3 @@
1
+ export interface Startable {
2
+ start(): Promise<void>;
3
+ }
@@ -0,0 +1,70 @@
1
+ import { TypedClass } from "../types";
2
+
3
+ export const injectAliasMetadataKey = "protokit-inject-alias";
4
+
5
+ /**
6
+ * Attaches metadata to the class that the ModuleContainer can pick up
7
+ * and inject this class in the DI container under the specified aliases.
8
+ * This method supports inheritance, therefore also gets aliases defined
9
+ * on superclasses
10
+ */
11
+ export function injectAlias(aliases: string[]) {
12
+ return (target: TypedClass<unknown>) => {
13
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
14
+ const superAliases = Reflect.getMetadata(
15
+ injectAliasMetadataKey,
16
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
17
+ Object.getPrototypeOf(target)
18
+ ) as string[] | undefined;
19
+
20
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
21
+ const existingAliases = Reflect.getMetadata(
22
+ injectAliasMetadataKey,
23
+ target
24
+ ) as string[] | undefined;
25
+
26
+ let allAliases = aliases;
27
+
28
+ if (superAliases !== undefined) {
29
+ allAliases = allAliases.concat(superAliases);
30
+ }
31
+ if (existingAliases !== undefined) {
32
+ allAliases = allAliases.concat(existingAliases);
33
+ }
34
+
35
+ Reflect.defineMetadata(
36
+ injectAliasMetadataKey,
37
+ allAliases.filter(
38
+ (value, index, array) => array.indexOf(value) === index
39
+ ),
40
+ target
41
+ );
42
+ };
43
+ }
44
+
45
+ /**
46
+ * Marks the class to implement a certain interface T, while also attaching
47
+ * a DI-injection alias as metadata, that will be picked up by the ModuleContainer
48
+ * to allow resolving by that interface name
49
+ * @param name The name of the injection alias, convention is to use the same as the name of T
50
+ */
51
+ export function implement<T>(name: string) {
52
+ return (
53
+ /**
54
+ * Check if the target class extends RuntimeModule, while
55
+ * also providing static config presets
56
+ */
57
+ target: TypedClass<T>
58
+ ) => {
59
+ injectAlias([name])(target);
60
+ };
61
+ }
62
+
63
+ export function getInjectAliases(target: TypedClass<unknown>): string[] {
64
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
65
+ const aliases = Reflect.getMetadata(
66
+ injectAliasMetadataKey,
67
+ target
68
+ ) as string[];
69
+ return aliases ?? [];
70
+ }