@proto-kit/common 0.1.1-develop.340 → 0.1.1-develop.455
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/dist/config/ConfigurableModule.d.ts +2 -1
- package/dist/config/ConfigurableModule.d.ts.map +1 -1
- package/dist/config/ModuleContainer.d.ts +35 -11
- package/dist/config/ModuleContainer.d.ts.map +1 -1
- package/dist/config/ModuleContainer.js +86 -19
- package/dist/dependencyFactory/DependencyFactory.d.ts +13 -9
- package/dist/dependencyFactory/DependencyFactory.d.ts.map +1 -1
- package/dist/dependencyFactory/DependencyFactory.js +1 -97
- package/dist/events/EventEmitter.d.ts +14 -0
- package/dist/events/EventEmitter.d.ts.map +1 -0
- package/dist/events/EventEmitter.js +35 -0
- package/dist/events/EventEmitterProxy.d.ts +17 -0
- package/dist/events/EventEmitterProxy.d.ts.map +1 -0
- package/dist/events/EventEmitterProxy.js +21 -0
- package/dist/events/EventEmittingComponent.d.ts +6 -0
- package/dist/events/EventEmittingComponent.d.ts.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/trees/InMemoryMerkleTreeStorage.d.ts +11 -0
- package/dist/trees/InMemoryMerkleTreeStorage.d.ts.map +1 -0
- package/dist/trees/InMemoryMerkleTreeStorage.js +12 -0
- package/dist/trees/MerkleTreeStore.d.ts +5 -0
- package/dist/trees/MerkleTreeStore.d.ts.map +1 -0
- package/dist/trees/MerkleTreeStore.js +1 -0
- package/dist/trees/MockAsyncMerkleStore.d.ts +9 -0
- package/dist/trees/MockAsyncMerkleStore.d.ts.map +1 -0
- package/dist/trees/MockAsyncMerkleStore.js +19 -0
- package/dist/trees/RollupMerkleTree.d.ts +126 -0
- package/dist/trees/RollupMerkleTree.d.ts.map +1 -0
- package/dist/trees/RollupMerkleTree.js +216 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/zkProgrammable/ZkProgrammable.d.ts +1 -1
- package/dist/zkProgrammable/ZkProgrammable.d.ts.map +1 -1
- package/dist/zkProgrammable/ZkProgrammable.js +4 -4
- package/dist/zkProgrammable/provableMethod.d.ts +1 -1
- package/dist/zkProgrammable/provableMethod.d.ts.map +1 -1
- package/dist/zkProgrammable/provableMethod.js +2 -2
- package/package.json +2 -2
- package/src/config/ConfigurableModule.ts +3 -1
- package/src/config/ModuleContainer.ts +150 -30
- package/src/dependencyFactory/DependencyFactory.ts +25 -114
- package/src/events/EventEmitter.ts +58 -0
- package/src/events/EventEmitterProxy.ts +57 -0
- package/src/events/EventEmittingComponent.ts +7 -0
- package/src/index.ts +7 -0
- package/src/trees/InMemoryMerkleTreeStorage.ts +17 -0
- package/src/trees/MerkleTreeStore.ts +5 -0
- package/src/trees/MockAsyncMerkleStore.ts +29 -0
- package/src/trees/RollupMerkleTree.ts +354 -0
- package/src/trees/VirtualMerkleTreeStore.ts +21 -0
- package/src/types.ts +12 -0
- package/src/zkProgrammable/ZkProgrammable.ts +5 -4
- package/src/zkProgrammable/provableMethod.ts +2 -2
- package/test/config/ContainerEvents.test.ts +86 -0
- package/test/config/ModuleContainer.test.ts +111 -6
- package/test/trees/MerkleTree.test.ts +105 -0
- package/dist/config/ChildContainerStartable.d.ts +0 -5
- package/dist/config/ChildContainerStartable.d.ts.map +0 -1
- /package/dist/{config/ChildContainerStartable.js → events/EventEmittingComponent.js} +0 -0
|
@@ -4,17 +4,38 @@ import "reflect-metadata";
|
|
|
4
4
|
import {
|
|
5
5
|
DependencyContainer,
|
|
6
6
|
Frequency,
|
|
7
|
+
injectable,
|
|
7
8
|
InjectionToken,
|
|
9
|
+
instancePerContainerCachingFactory,
|
|
10
|
+
isClassProvider,
|
|
11
|
+
isFactoryProvider,
|
|
12
|
+
isValueProvider,
|
|
8
13
|
Lifecycle,
|
|
9
14
|
} from "tsyringe";
|
|
10
15
|
import log from "loglevel";
|
|
16
|
+
import merge from "lodash/merge";
|
|
11
17
|
|
|
12
|
-
import { StringKeyOf, TypedClass } from "../types";
|
|
13
|
-
import {
|
|
18
|
+
import { MergeObjects, StringKeyOf, TypedClass } from "../types";
|
|
19
|
+
import {
|
|
20
|
+
DependencyFactory,
|
|
21
|
+
InferDependencies,
|
|
22
|
+
} from "../dependencyFactory/DependencyFactory";
|
|
14
23
|
|
|
15
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
Configurable,
|
|
26
|
+
ConfigurableModule,
|
|
27
|
+
NoConfig,
|
|
28
|
+
} from "./ConfigurableModule";
|
|
16
29
|
import { ChildContainerProvider } from "./ChildContainerProvider";
|
|
17
30
|
import { ChildContainerCreatable } from "./ChildContainerCreatable";
|
|
31
|
+
import { EventEmitter } from "../events/EventEmitter";
|
|
32
|
+
import {
|
|
33
|
+
EventEmittingComponent,
|
|
34
|
+
EventsRecord,
|
|
35
|
+
} from "../events/EventEmittingComponent";
|
|
36
|
+
import { EventEmitterProxy } from "../events/EventEmitterProxy";
|
|
37
|
+
import { memoize } from "lodash";
|
|
38
|
+
import { Memoize } from "typescript-memoize";
|
|
18
39
|
|
|
19
40
|
const errors = {
|
|
20
41
|
configNotSetInContainer: (moduleName: string) =>
|
|
@@ -78,10 +99,16 @@ export type ModulesConfig<Modules extends ModulesRecord> = {
|
|
|
78
99
|
[ConfigKey in StringKeyOf<Modules>]: InstanceType<
|
|
79
100
|
Modules[ConfigKey]
|
|
80
101
|
> extends Configurable<infer Config>
|
|
81
|
-
? Config
|
|
102
|
+
? Config extends NoConfig
|
|
103
|
+
? Config | undefined
|
|
104
|
+
: Config
|
|
82
105
|
: never;
|
|
83
106
|
};
|
|
84
107
|
|
|
108
|
+
export type RecursivePartial<T> = {
|
|
109
|
+
[Key in keyof T]?: T[Key] extends object ? RecursivePartial<T[Key]> : T[Key];
|
|
110
|
+
};
|
|
111
|
+
|
|
85
112
|
/**
|
|
86
113
|
* Parameters required when creating a module container instance
|
|
87
114
|
*/
|
|
@@ -91,6 +118,23 @@ export interface ModuleContainerDefinition<Modules extends ModulesRecord> {
|
|
|
91
118
|
config?: ModulesConfig<Modules>;
|
|
92
119
|
}
|
|
93
120
|
|
|
121
|
+
// Removes all keys with a "never" value from an object
|
|
122
|
+
export type FilterNeverValues<Type extends Record<string, unknown>> = {
|
|
123
|
+
[Key in keyof Type as Type[Key] extends never ? never : Key]: Type[Key];
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export type DependenciesFromModules<Modules extends ModulesRecord> =
|
|
127
|
+
FilterNeverValues<{
|
|
128
|
+
[Key in keyof Modules]: Modules[Key] extends TypedClass<DependencyFactory>
|
|
129
|
+
? InferDependencies<InstanceType<Modules[Key]>>
|
|
130
|
+
: never;
|
|
131
|
+
}>;
|
|
132
|
+
|
|
133
|
+
export type ResolvableModules<Modules extends ModulesRecord> = MergeObjects<
|
|
134
|
+
DependenciesFromModules<Modules>
|
|
135
|
+
> &
|
|
136
|
+
Modules;
|
|
137
|
+
|
|
94
138
|
/**
|
|
95
139
|
* Reusable module container facilitating registration, resolution
|
|
96
140
|
* configuration, decoration and validation of modules
|
|
@@ -107,8 +151,13 @@ export class ModuleContainer<
|
|
|
107
151
|
// DI container holding all the registered modules
|
|
108
152
|
private providedContainer?: DependencyContainer = undefined;
|
|
109
153
|
|
|
154
|
+
private eventEmitterProxy: EventEmitterProxy<Modules> | undefined = undefined;
|
|
155
|
+
|
|
110
156
|
public constructor(public definition: ModuleContainerDefinition<Modules>) {
|
|
111
157
|
super();
|
|
158
|
+
if (definition.config !== undefined) {
|
|
159
|
+
this.config = definition.config;
|
|
160
|
+
}
|
|
112
161
|
}
|
|
113
162
|
|
|
114
163
|
/**
|
|
@@ -161,16 +210,16 @@ export class ModuleContainer<
|
|
|
161
210
|
modules: Modules,
|
|
162
211
|
moduleName: string
|
|
163
212
|
): asserts moduleName is StringKeyOf<Modules> {
|
|
164
|
-
this.isValidModuleName(modules, moduleName)
|
|
213
|
+
if (!this.isValidModuleName(modules, moduleName)) {
|
|
214
|
+
throw errors.onlyValidModuleNames(moduleName);
|
|
215
|
+
}
|
|
165
216
|
}
|
|
166
217
|
|
|
167
218
|
public isValidModuleName(
|
|
168
219
|
modules: Modules,
|
|
169
220
|
moduleName: number | string | symbol
|
|
170
|
-
):
|
|
171
|
-
|
|
172
|
-
throw errors.onlyValidModuleNames(moduleName);
|
|
173
|
-
}
|
|
221
|
+
): moduleName is StringKeyOf<Modules> {
|
|
222
|
+
return Object.prototype.hasOwnProperty.call(modules, moduleName);
|
|
174
223
|
}
|
|
175
224
|
|
|
176
225
|
public assertContainerInitialized(
|
|
@@ -207,16 +256,11 @@ export class ModuleContainer<
|
|
|
207
256
|
}
|
|
208
257
|
}
|
|
209
258
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
factories: TypedClass<DependencyFactory>[]
|
|
216
|
-
) {
|
|
217
|
-
factories.forEach((factory) => {
|
|
218
|
-
this.container.resolve(factory).initDependencies(this.container);
|
|
219
|
-
});
|
|
259
|
+
public get events(): EventEmitterProxy<Modules> {
|
|
260
|
+
if (this.eventEmitterProxy === undefined) {
|
|
261
|
+
this.eventEmitterProxy = new EventEmitterProxy<Modules>(this);
|
|
262
|
+
}
|
|
263
|
+
return this.eventEmitterProxy;
|
|
220
264
|
}
|
|
221
265
|
|
|
222
266
|
/**
|
|
@@ -250,13 +294,22 @@ export class ModuleContainer<
|
|
|
250
294
|
* @param config
|
|
251
295
|
*/
|
|
252
296
|
public configure(config: ModulesConfig<Modules>) {
|
|
253
|
-
this.
|
|
297
|
+
this.config = config;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
public configurePartial(config: RecursivePartial<ModulesConfig<Modules>>) {
|
|
301
|
+
this.config = merge<
|
|
302
|
+
ModulesConfig<Modules> | NoConfig,
|
|
303
|
+
RecursivePartial<ModulesConfig<Modules>>
|
|
304
|
+
>(this.currentConfig ?? {}, config);
|
|
254
305
|
}
|
|
255
306
|
|
|
256
307
|
// eslint-disable-next-line accessor-pairs
|
|
257
308
|
public set config(config: ModulesConfig<Modules>) {
|
|
258
|
-
super.config =
|
|
259
|
-
|
|
309
|
+
super.config = merge<
|
|
310
|
+
ModulesConfig<Modules> | NoConfig,
|
|
311
|
+
ModulesConfig<Modules>
|
|
312
|
+
>(this.currentConfig ?? {}, config);
|
|
260
313
|
}
|
|
261
314
|
|
|
262
315
|
/**
|
|
@@ -269,12 +322,12 @@ export class ModuleContainer<
|
|
|
269
322
|
* @param moduleName
|
|
270
323
|
* @returns
|
|
271
324
|
*/
|
|
272
|
-
public resolve<
|
|
273
|
-
moduleName:
|
|
274
|
-
): InstanceType<Modules[
|
|
275
|
-
return this.container.resolve<
|
|
276
|
-
|
|
277
|
-
);
|
|
325
|
+
public resolve<KeyType extends StringKeyOf<ResolvableModules<Modules>>>(
|
|
326
|
+
moduleName: KeyType
|
|
327
|
+
): InstanceType<ResolvableModules<Modules>[KeyType]> {
|
|
328
|
+
return this.container.resolve<
|
|
329
|
+
InstanceType<ResolvableModules<Modules>[KeyType]>
|
|
330
|
+
>(moduleName);
|
|
278
331
|
}
|
|
279
332
|
|
|
280
333
|
public resolveOrFail<ModuleType>(
|
|
@@ -299,14 +352,77 @@ export class ModuleContainer<
|
|
|
299
352
|
moduleName: StringKeyOf<Modules>,
|
|
300
353
|
containedModule: InstanceType<Modules[StringKeyOf<Modules>]>
|
|
301
354
|
) {
|
|
302
|
-
|
|
355
|
+
// Has to be super.config, getters behave really weird when subtyping
|
|
356
|
+
const config = super.config?.[moduleName];
|
|
303
357
|
|
|
304
358
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
305
359
|
if (!config) {
|
|
306
360
|
throw errors.configNotSetInContainer(moduleName.toString());
|
|
307
361
|
}
|
|
308
362
|
|
|
309
|
-
containedModule
|
|
363
|
+
if (containedModule instanceof ModuleContainer) {
|
|
364
|
+
containedModule.configure(config);
|
|
365
|
+
} else {
|
|
366
|
+
containedModule.config = config;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
371
|
+
private isDependencyFactory(type: any): type is DependencyFactory {
|
|
372
|
+
return "dependencies" in type;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Inject a set of dependencies using the given list of DependencyFactories
|
|
377
|
+
* This method should be called during startup
|
|
378
|
+
*/
|
|
379
|
+
protected initializeDependencyFactories(factories: StringKeyOf<Modules>[]) {
|
|
380
|
+
factories.forEach((factoryName) => {
|
|
381
|
+
this.resolve(factoryName);
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Retrieves all dependencies generated by a particular dependencyfactory
|
|
387
|
+
* and injects them inside this modulecontainer's DI container.
|
|
388
|
+
* This will be automatically called for every module, but can also be called
|
|
389
|
+
* explicitly to initialize an extra factory
|
|
390
|
+
* @param factory
|
|
391
|
+
* @private
|
|
392
|
+
*/
|
|
393
|
+
protected useDependencyFactory(factory: DependencyFactory) {
|
|
394
|
+
const dependencies = factory.dependencies();
|
|
395
|
+
|
|
396
|
+
Object.entries(dependencies).forEach(([rawKey, declaration]) => {
|
|
397
|
+
const key = rawKey.charAt(0).toUpperCase() + rawKey.slice(1);
|
|
398
|
+
|
|
399
|
+
if (
|
|
400
|
+
!this.container.isRegistered(key) ||
|
|
401
|
+
declaration.forceOverwrite === true
|
|
402
|
+
) {
|
|
403
|
+
// Find correct provider type and call respective register
|
|
404
|
+
if (isValueProvider(declaration)) {
|
|
405
|
+
this.container.register(key, declaration);
|
|
406
|
+
} else if (isFactoryProvider(declaration)) {
|
|
407
|
+
// this enables us to have a singletoned factory
|
|
408
|
+
// that returns the same instance for each resolve
|
|
409
|
+
this.container.register(key, {
|
|
410
|
+
useFactory: instancePerContainerCachingFactory(
|
|
411
|
+
declaration.useFactory
|
|
412
|
+
),
|
|
413
|
+
});
|
|
414
|
+
} else if (isClassProvider(declaration)) {
|
|
415
|
+
this.container.register(key, declaration, {
|
|
416
|
+
lifecycle: Lifecycle.Singleton,
|
|
417
|
+
});
|
|
418
|
+
} else {
|
|
419
|
+
// Can never be reached
|
|
420
|
+
throw new Error("Above if-statement is exhaustive");
|
|
421
|
+
}
|
|
422
|
+
} else {
|
|
423
|
+
log.debug(`Dependency ${key} already registered, skipping`);
|
|
424
|
+
}
|
|
425
|
+
});
|
|
310
426
|
}
|
|
311
427
|
|
|
312
428
|
/**
|
|
@@ -328,6 +444,10 @@ export class ModuleContainer<
|
|
|
328
444
|
container.reset();
|
|
329
445
|
return container;
|
|
330
446
|
});
|
|
447
|
+
|
|
448
|
+
if (this.isDependencyFactory(containedModule)) {
|
|
449
|
+
this.useDependencyFactory(containedModule);
|
|
450
|
+
}
|
|
331
451
|
},
|
|
332
452
|
{ frequency: ModuleContainer.moduleDecorationFrequency }
|
|
333
453
|
);
|
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ClassProvider,
|
|
3
|
+
FactoryProvider,
|
|
4
|
+
ValueProvider,
|
|
5
|
+
} from "tsyringe";
|
|
2
6
|
|
|
3
7
|
import { TypedClass } from "../types";
|
|
4
|
-
import {
|
|
8
|
+
import { BaseModuleInstanceType } from "../config/ModuleContainer";
|
|
5
9
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
export type DependencyDeclaration<Dependency> =
|
|
11
|
+
| ClassProvider<Dependency>
|
|
12
|
+
| FactoryProvider<Dependency>
|
|
13
|
+
| ValueProvider<Dependency>;
|
|
9
14
|
|
|
10
|
-
|
|
11
|
-
new Error(
|
|
12
|
-
"You cannot access the depdendency method directly, use container.resolve"
|
|
13
|
-
),
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const globalFactoryDependencies = new Map<
|
|
15
|
+
export type DependencyRecord = Record<
|
|
17
16
|
string,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
| undefined
|
|
22
|
-
>();
|
|
17
|
+
DependencyDeclaration<unknown> & { forceOverwrite?: boolean }
|
|
18
|
+
>;
|
|
23
19
|
|
|
24
20
|
/**
|
|
25
21
|
* This is an abstract class for creating DependencyFactories, a pattern
|
|
@@ -32,105 +28,20 @@ const globalFactoryDependencies = new Map<
|
|
|
32
28
|
*
|
|
33
29
|
* DependencyFactories are designed to only be used statically for sets of
|
|
34
30
|
* deps that are necessary for the sequencer to work.
|
|
35
|
-
*
|
|
36
|
-
* Every Factory need the @dependencyFactory annotation (which basically
|
|
37
|
-
* proxies @injectable()) and every method that returns a dependency has to be
|
|
38
|
-
* of the format `() => Dependency` and be annotated with @dependency.
|
|
39
31
|
*/
|
|
40
|
-
export
|
|
41
|
-
|
|
42
|
-
const dependencies =
|
|
43
|
-
globalFactoryDependencies.get(this.constructor.name) ?? {};
|
|
44
|
-
|
|
45
|
-
for (const [key, useFactory] of Object.entries(dependencies)) {
|
|
46
|
-
container.register(`${key}_singleton-prototype`, {
|
|
47
|
-
useFactory: useFactory.bind(this),
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
const upperCaseKey = key.charAt(0).toUpperCase() + key.slice(1);
|
|
51
|
-
|
|
52
|
-
container.register(
|
|
53
|
-
upperCaseKey,
|
|
54
|
-
{
|
|
55
|
-
useToken: `${key}_singleton-prototype`,
|
|
56
|
-
},
|
|
57
|
-
{ lifecycle: Lifecycle.ContainerScoped }
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
log.debug(
|
|
61
|
-
`Registered dependency ${upperCaseKey} from factory ${this.constructor.name}`
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
32
|
+
export interface DependencyFactory {
|
|
33
|
+
dependencies: () => DependencyRecord;
|
|
65
34
|
}
|
|
66
35
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
// }
|
|
71
|
-
//
|
|
72
|
-
// export abstract class DF2<Types extends DTypes> {
|
|
73
|
-
// public constructor(private factories: Factories<Types>) {
|
|
74
|
-
//
|
|
75
|
-
// }
|
|
76
|
-
// generateDependencies(): Types {
|
|
77
|
-
// let x = this.factories;
|
|
78
|
-
// return {} as Types;
|
|
79
|
-
// }
|
|
80
|
-
// }
|
|
36
|
+
export type TypeFromDependencyDeclaration<
|
|
37
|
+
Declaration extends DependencyDeclaration<unknown>
|
|
38
|
+
> = Declaration extends DependencyDeclaration<infer Dependency> ? Dependency : never;
|
|
81
39
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// return undefined;
|
|
86
|
-
// }
|
|
87
|
-
// }
|
|
88
|
-
// return new c();
|
|
89
|
-
// }
|
|
90
|
-
|
|
91
|
-
// class DF2I extends DF2<{x: typeof ConfigurableModule}> {
|
|
92
|
-
// constructor() {
|
|
93
|
-
// super({
|
|
94
|
-
// x: this.x
|
|
95
|
-
// });
|
|
96
|
-
// }
|
|
97
|
-
//
|
|
98
|
-
// x(): ConfigurableModule<any> {
|
|
99
|
-
// return {} as ConfigurableModule<any>;
|
|
100
|
-
// }
|
|
101
|
-
//
|
|
102
|
-
// }
|
|
103
|
-
|
|
104
|
-
export function dependency() {
|
|
105
|
-
return function decorator<Target extends DependencyFactory, Dependency>(
|
|
106
|
-
target: Target,
|
|
107
|
-
key: string,
|
|
108
|
-
descriptor: TypedPropertyDescriptor<() => Dependency>
|
|
109
|
-
) {
|
|
110
|
-
if (descriptor.value !== undefined) {
|
|
111
|
-
const className = target.constructor.name;
|
|
112
|
-
if (!globalFactoryDependencies.has(className)) {
|
|
113
|
-
globalFactoryDependencies.set(className, {});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
117
|
-
globalFactoryDependencies.get(target.constructor.name)![key] =
|
|
118
|
-
descriptor.value;
|
|
119
|
-
|
|
120
|
-
descriptor.value = () => {
|
|
121
|
-
throw errors.dependencyFactoryCalledDirectly();
|
|
122
|
-
};
|
|
123
|
-
} else {
|
|
124
|
-
throw errors.descriptorUndefined();
|
|
125
|
-
}
|
|
126
|
-
return descriptor;
|
|
127
|
-
};
|
|
128
|
-
}
|
|
40
|
+
export type MapDependencyRecordToTypes<Record extends DependencyRecord> = {
|
|
41
|
+
[Key in keyof Record]: TypedClass<TypeFromDependencyDeclaration<Record[Key]>>;
|
|
42
|
+
};
|
|
129
43
|
|
|
130
|
-
export
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
injectable()(target);
|
|
135
|
-
};
|
|
136
|
-
}
|
|
44
|
+
export type InferDependencies<Class extends BaseModuleInstanceType> =
|
|
45
|
+
Class extends DependencyFactory
|
|
46
|
+
? MapDependencyRecordToTypes<ReturnType<Class["dependencies"]>>
|
|
47
|
+
: never;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { EventsRecord } from "./EventEmittingComponent";
|
|
2
|
+
|
|
3
|
+
type ListenersHolder<Events extends EventsRecord> = {
|
|
4
|
+
// eslint-disable-next-line putout/putout
|
|
5
|
+
[key in keyof Events]?: ((...args: Events[key]) => void)[];
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export class EventEmitter<Events extends EventsRecord> {
|
|
9
|
+
private readonly listeners: ListenersHolder<Events> = {};
|
|
10
|
+
|
|
11
|
+
// eslint-disable-next-line putout/putout
|
|
12
|
+
private readonly wildcardListeners: ((
|
|
13
|
+
event: keyof Events,
|
|
14
|
+
args: Events[keyof Events]
|
|
15
|
+
) => void)[] = [];
|
|
16
|
+
|
|
17
|
+
public emit<Key extends keyof Events>(
|
|
18
|
+
event: Key,
|
|
19
|
+
...parameters: Events[Key]
|
|
20
|
+
) {
|
|
21
|
+
const listeners = this.listeners[event];
|
|
22
|
+
if (listeners !== undefined) {
|
|
23
|
+
listeners.forEach((listener) => {
|
|
24
|
+
listener(...parameters);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
this.wildcardListeners.forEach((wildcardListener) => {
|
|
28
|
+
wildcardListener(event, parameters);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public onAll(listener: (event: keyof Events, args: unknown[]) => void): void {
|
|
33
|
+
this.wildcardListeners.push(listener);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public on<Key extends keyof Events>(
|
|
37
|
+
event: Key,
|
|
38
|
+
listener: (...args: Events[Key]) => void
|
|
39
|
+
) {
|
|
40
|
+
(this.listeners[event] ??= []).push(listener);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Primitive .off() with identity comparison for now.
|
|
45
|
+
* Could be replaced by returning an id in .on() and using that.
|
|
46
|
+
*/
|
|
47
|
+
public off<Key extends keyof Events>(
|
|
48
|
+
event: Key,
|
|
49
|
+
listener: (...args: Events[Key]) => void
|
|
50
|
+
) {
|
|
51
|
+
const events = this.listeners[event];
|
|
52
|
+
if (events !== undefined) {
|
|
53
|
+
this.listeners[event] = events.filter(
|
|
54
|
+
(candidate) => candidate !== listener
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BaseModuleType,
|
|
3
|
+
ModuleContainer,
|
|
4
|
+
ModulesRecord,
|
|
5
|
+
} from "../config/ModuleContainer";
|
|
6
|
+
import { StringKeyOf, UnionToIntersection } from "../types";
|
|
7
|
+
|
|
8
|
+
import { EventEmitter } from "./EventEmitter";
|
|
9
|
+
import { EventEmittingComponent, EventsRecord } from "./EventEmittingComponent";
|
|
10
|
+
|
|
11
|
+
export type CastToEventsRecord<Record> = Record extends EventsRecord
|
|
12
|
+
? Record
|
|
13
|
+
: {};
|
|
14
|
+
|
|
15
|
+
export type ModuleEvents<ModuleType extends BaseModuleType> =
|
|
16
|
+
InstanceType<ModuleType> extends EventEmittingComponent<infer Events>
|
|
17
|
+
? Events
|
|
18
|
+
: InstanceType<ModuleType> extends ModuleContainer<infer NestedModules>
|
|
19
|
+
? CastToEventsRecord<ContainerEvents<NestedModules>>
|
|
20
|
+
: EventsRecord;
|
|
21
|
+
|
|
22
|
+
export type ContainerEvents<Modules extends ModulesRecord> = {
|
|
23
|
+
[Key in StringKeyOf<Modules>]: ModuleEvents<Modules[Key]>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type FlattenObject<Target extends Record<string, EventsRecord>> =
|
|
27
|
+
UnionToIntersection<Target[keyof Target]>;
|
|
28
|
+
|
|
29
|
+
export type FlattenedContainerEvents<Modules extends ModulesRecord> =
|
|
30
|
+
FlattenObject<ContainerEvents<Modules>>;
|
|
31
|
+
|
|
32
|
+
export class EventEmitterProxy<
|
|
33
|
+
Modules extends ModulesRecord
|
|
34
|
+
> extends EventEmitter<CastToEventsRecord<FlattenedContainerEvents<Modules>>> {
|
|
35
|
+
public constructor(private readonly container: ModuleContainer<Modules>) {
|
|
36
|
+
super();
|
|
37
|
+
container.moduleNames.forEach((moduleName) => {
|
|
38
|
+
if (
|
|
39
|
+
container.isValidModuleName(container.definition.modules, moduleName)
|
|
40
|
+
) {
|
|
41
|
+
const module = container.resolve(moduleName);
|
|
42
|
+
if (this.isEventEmitter(module)) {
|
|
43
|
+
module.events.onAll((events: any, args: unknown[]) => {
|
|
44
|
+
this.emit(events, ...(args as any));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private isEventEmitter(
|
|
52
|
+
module: any
|
|
53
|
+
): module is EventEmittingComponent<EventsRecord> {
|
|
54
|
+
const emitter = module.events;
|
|
55
|
+
return emitter !== undefined && emitter instanceof EventEmitter;
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -9,3 +9,10 @@ export * from "./zkProgrammable/provableMethod";
|
|
|
9
9
|
export * from "./utils";
|
|
10
10
|
export * from "./dependencyFactory/DependencyFactory";
|
|
11
11
|
export * from "./log";
|
|
12
|
+
export * from "./events/EventEmittingComponent";
|
|
13
|
+
export * from "./events/EventEmitter";
|
|
14
|
+
export * from "./trees/MerkleTreeStore";
|
|
15
|
+
export * from "./trees/InMemoryMerkleTreeStorage";
|
|
16
|
+
export * from "./trees/RollupMerkleTree";
|
|
17
|
+
export * from "./events/EventEmitterProxy";
|
|
18
|
+
export * from "./trees/MockAsyncMerkleStore";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { MerkleTreeStore } from "./MerkleTreeStore";
|
|
2
|
+
|
|
3
|
+
export class InMemoryMerkleTreeStorage implements MerkleTreeStore {
|
|
4
|
+
protected nodes: {
|
|
5
|
+
[key: number]: {
|
|
6
|
+
[key: string]: bigint;
|
|
7
|
+
};
|
|
8
|
+
} = {};
|
|
9
|
+
|
|
10
|
+
public getNode(key: bigint, level: number): bigint | undefined {
|
|
11
|
+
return this.nodes[level]?.[key.toString()];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public setNode(key: bigint, level: number, value: bigint): void {
|
|
15
|
+
(this.nodes[level] ??= {})[key.toString()] = value;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { InMemoryMerkleTreeStorage } from "./InMemoryMerkleTreeStorage";
|
|
2
|
+
import { noop } from "./../utils";
|
|
3
|
+
|
|
4
|
+
export class MockAsyncMerkleTreeStore {
|
|
5
|
+
public readonly store = new InMemoryMerkleTreeStorage();
|
|
6
|
+
|
|
7
|
+
public commit(): void {
|
|
8
|
+
noop();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public openTransaction(): void {
|
|
12
|
+
noop();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public async getNodeAsync(
|
|
16
|
+
key: bigint,
|
|
17
|
+
level: number
|
|
18
|
+
): Promise<bigint | undefined> {
|
|
19
|
+
return this.store.getNode(key, level);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public async setNodeAsync(
|
|
23
|
+
key: bigint,
|
|
24
|
+
level: number,
|
|
25
|
+
value: bigint
|
|
26
|
+
): Promise<void> {
|
|
27
|
+
this.store.setNode(key, level, value);
|
|
28
|
+
}
|
|
29
|
+
}
|