@xyo-network/module-abstract 2.92.11 → 2.93.0-rc.2
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/browser/AbstractModule.d.cts +4 -12
- package/dist/browser/AbstractModule.d.cts.map +1 -1
- package/dist/browser/AbstractModule.d.mts +4 -12
- package/dist/browser/AbstractModule.d.mts.map +1 -1
- package/dist/browser/AbstractModule.d.ts +4 -12
- package/dist/browser/AbstractModule.d.ts.map +1 -1
- package/dist/browser/AbstractModuleInstance.d.cts +13 -3
- package/dist/browser/AbstractModuleInstance.d.cts.map +1 -1
- package/dist/browser/AbstractModuleInstance.d.mts +13 -3
- package/dist/browser/AbstractModuleInstance.d.mts.map +1 -1
- package/dist/browser/AbstractModuleInstance.d.ts +13 -3
- package/dist/browser/AbstractModuleInstance.d.ts.map +1 -1
- package/dist/browser/ResolveHelper.d.cts +19 -0
- package/dist/browser/ResolveHelper.d.cts.map +1 -0
- package/dist/browser/ResolveHelper.d.mts +19 -0
- package/dist/browser/ResolveHelper.d.mts.map +1 -0
- package/dist/browser/ResolveHelper.d.ts +19 -0
- package/dist/browser/ResolveHelper.d.ts.map +1 -0
- package/dist/browser/index.cjs +144 -70
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.d.cts +1 -0
- package/dist/browser/index.d.cts.map +1 -1
- package/dist/browser/index.d.mts +1 -0
- package/dist/browser/index.d.mts.map +1 -1
- package/dist/browser/index.d.ts +1 -0
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +145 -71
- package/dist/browser/index.js.map +1 -1
- package/dist/node/AbstractModule.d.cts +4 -12
- package/dist/node/AbstractModule.d.cts.map +1 -1
- package/dist/node/AbstractModule.d.mts +4 -12
- package/dist/node/AbstractModule.d.mts.map +1 -1
- package/dist/node/AbstractModule.d.ts +4 -12
- package/dist/node/AbstractModule.d.ts.map +1 -1
- package/dist/node/AbstractModuleInstance.d.cts +13 -3
- package/dist/node/AbstractModuleInstance.d.cts.map +1 -1
- package/dist/node/AbstractModuleInstance.d.mts +13 -3
- package/dist/node/AbstractModuleInstance.d.mts.map +1 -1
- package/dist/node/AbstractModuleInstance.d.ts +13 -3
- package/dist/node/AbstractModuleInstance.d.ts.map +1 -1
- package/dist/node/ResolveHelper.d.cts +19 -0
- package/dist/node/ResolveHelper.d.cts.map +1 -0
- package/dist/node/ResolveHelper.d.mts +19 -0
- package/dist/node/ResolveHelper.d.mts.map +1 -0
- package/dist/node/ResolveHelper.d.ts +19 -0
- package/dist/node/ResolveHelper.d.ts.map +1 -0
- package/dist/node/index.cjs +152 -78
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +1 -0
- package/dist/node/index.d.cts.map +1 -1
- package/dist/node/index.d.mts +1 -0
- package/dist/node/index.d.mts.map +1 -1
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +152 -79
- package/dist/node/index.js.map +1 -1
- package/package.json +28 -27
- package/src/AbstractModule.ts +25 -103
- package/src/AbstractModuleInstance.ts +69 -4
- package/src/ResolveHelper.ts +121 -0
- package/src/index.ts +1 -0
package/src/AbstractModule.ts
CHANGED
|
@@ -20,10 +20,10 @@ import { ModuleManifestPayload, ModuleManifestPayloadSchema } from '@xyo-network
|
|
|
20
20
|
import {
|
|
21
21
|
AddressPreviousHashPayload,
|
|
22
22
|
AddressPreviousHashSchema,
|
|
23
|
+
ArchivingModuleConfig,
|
|
23
24
|
CreatableModule,
|
|
24
25
|
CreatableModuleFactory,
|
|
25
26
|
DeadModuleError,
|
|
26
|
-
duplicateModules,
|
|
27
27
|
isModuleName,
|
|
28
28
|
Module,
|
|
29
29
|
ModuleAddressQuerySchema,
|
|
@@ -35,11 +35,9 @@ import {
|
|
|
35
35
|
ModuleDiscoverQuerySchema,
|
|
36
36
|
ModuleEventData,
|
|
37
37
|
ModuleFactory,
|
|
38
|
-
ModuleFilter,
|
|
39
|
-
ModuleFilterOptions,
|
|
40
|
-
ModuleIdentifier,
|
|
41
38
|
ModuleInstance,
|
|
42
39
|
ModuleManifestQuerySchema,
|
|
40
|
+
ModuleName,
|
|
43
41
|
ModuleParams,
|
|
44
42
|
ModuleQueriedEventArgs,
|
|
45
43
|
ModuleQueries,
|
|
@@ -67,7 +65,7 @@ export abstract class AbstractModule<TParams extends ModuleParams = ModuleParams
|
|
|
67
65
|
{
|
|
68
66
|
static readonly allowRandomAccount: boolean = true
|
|
69
67
|
static configSchemas: string[]
|
|
70
|
-
static override defaultLogger: Logger = new ConsoleLogger(LogLevel.
|
|
68
|
+
static override defaultLogger: Logger = new ConsoleLogger(LogLevel.warn)
|
|
71
69
|
static enableLazyLoad = false
|
|
72
70
|
|
|
73
71
|
protected static privateConstructorKey = Date.now().toString()
|
|
@@ -129,6 +127,10 @@ export abstract class AbstractModule<TParams extends ModuleParams = ModuleParams
|
|
|
129
127
|
return !!this.config.security?.allowAnonymous
|
|
130
128
|
}
|
|
131
129
|
|
|
130
|
+
get archiving(): ArchivingModuleConfig['archiving'] | undefined {
|
|
131
|
+
return this.config.archiving
|
|
132
|
+
}
|
|
133
|
+
|
|
132
134
|
get config(): TParams['config'] {
|
|
133
135
|
return this.params.config
|
|
134
136
|
}
|
|
@@ -356,58 +358,6 @@ export abstract class AbstractModule<TParams extends ModuleParams = ModuleParams
|
|
|
356
358
|
return validators.every((validator) => validator(query, payloads))
|
|
357
359
|
}
|
|
358
360
|
|
|
359
|
-
/** @deprecated do not pass undefined. If trying to get all, pass '*' */
|
|
360
|
-
async resolve(): Promise<ModuleInstance[]>
|
|
361
|
-
async resolve<T extends ModuleInstance = ModuleInstance>(all: '*', options?: ModuleFilterOptions<T>): Promise<T[]>
|
|
362
|
-
async resolve<T extends ModuleInstance = ModuleInstance>(filter: ModuleFilter, options?: ModuleFilterOptions<T>): Promise<T[]>
|
|
363
|
-
async resolve<T extends ModuleInstance = ModuleInstance>(id: ModuleIdentifier, options?: ModuleFilterOptions<T>): Promise<T | undefined>
|
|
364
|
-
/** @deprecated use '*' if trying to resolve all */
|
|
365
|
-
async resolve<T extends ModuleInstance = ModuleInstance>(filter?: ModuleFilter, options?: ModuleFilterOptions<T>): Promise<T[]>
|
|
366
|
-
async resolve<T extends ModuleInstance = ModuleInstance>(
|
|
367
|
-
idOrFilter: ModuleFilter<T> | ModuleIdentifier = '*',
|
|
368
|
-
{ required = 'log', ...options }: ModuleFilterOptions<T> = {},
|
|
369
|
-
): Promise<T | T[] | undefined> {
|
|
370
|
-
const childOptions = { ...options, required: false }
|
|
371
|
-
const direction = options?.direction ?? 'all'
|
|
372
|
-
const up = direction === 'up' || direction === 'all'
|
|
373
|
-
const down = direction === 'down' || direction === 'all'
|
|
374
|
-
let result: T | T[] | undefined
|
|
375
|
-
if (idOrFilter === '*') {
|
|
376
|
-
if (this.dead) {
|
|
377
|
-
return []
|
|
378
|
-
}
|
|
379
|
-
return [
|
|
380
|
-
...(down ? await (this.downResolver as CompositeModuleResolver).resolve<T>('*', childOptions) : []),
|
|
381
|
-
...(up ? await (this.upResolver as CompositeModuleResolver).resolve<T>('*', childOptions) : []),
|
|
382
|
-
].filter(duplicateModules)
|
|
383
|
-
} else {
|
|
384
|
-
switch (typeof idOrFilter) {
|
|
385
|
-
case 'string': {
|
|
386
|
-
if (this.dead) {
|
|
387
|
-
return undefined
|
|
388
|
-
}
|
|
389
|
-
result =
|
|
390
|
-
(down ? await (this.downResolver as CompositeModuleResolver).resolve<T>(idOrFilter, childOptions) : undefined) ??
|
|
391
|
-
(up ? await (this.upResolver as CompositeModuleResolver).resolve<T>(idOrFilter, childOptions) : undefined)
|
|
392
|
-
break
|
|
393
|
-
}
|
|
394
|
-
default: {
|
|
395
|
-
if (this.dead) {
|
|
396
|
-
return []
|
|
397
|
-
}
|
|
398
|
-
const filter: ModuleFilter<T> | undefined = idOrFilter
|
|
399
|
-
result = [
|
|
400
|
-
...(down ? await (this.downResolver as CompositeModuleResolver).resolve<T>(filter, childOptions) : []),
|
|
401
|
-
...(up ? await (this.upResolver as CompositeModuleResolver).resolve<T>(filter, childOptions) : []),
|
|
402
|
-
].filter(duplicateModules)
|
|
403
|
-
break
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
this.validateRequiredResolve(required, result, idOrFilter)
|
|
408
|
-
return result
|
|
409
|
-
}
|
|
410
|
-
|
|
411
361
|
start(_timeout?: number): Promisable<boolean> {
|
|
412
362
|
//using promise as mutex
|
|
413
363
|
this._startPromise = this._startPromise ?? this.startHandler()
|
|
@@ -544,7 +494,7 @@ export abstract class AbstractModule<TParams extends ModuleParams = ModuleParams
|
|
|
544
494
|
await Promise.all(payloads.map((payload) => PayloadBuilder.build(payload))),
|
|
545
495
|
await Promise.all((errors ?? [])?.map((error) => PayloadBuilder.build(error))),
|
|
546
496
|
]
|
|
547
|
-
if (this.
|
|
497
|
+
if (this.archiving) {
|
|
548
498
|
await this.storeToArchivists(result.flat())
|
|
549
499
|
}
|
|
550
500
|
return result
|
|
@@ -573,7 +523,7 @@ export abstract class AbstractModule<TParams extends ModuleParams = ModuleParams
|
|
|
573
523
|
}
|
|
574
524
|
|
|
575
525
|
protected async discoverHandler(_maxDepth?: number): Promise<Payload[]> {
|
|
576
|
-
const config = this.config
|
|
526
|
+
const config = await PayloadBuilder.build(this.config)
|
|
577
527
|
const address = await new PayloadBuilder<AddressPayload>({ schema: AddressSchema })
|
|
578
528
|
.fields({ address: this.address, name: this.config?.name })
|
|
579
529
|
.build()
|
|
@@ -582,10 +532,10 @@ export abstract class AbstractModule<TParams extends ModuleParams = ModuleParams
|
|
|
582
532
|
return await new PayloadBuilder<QueryPayload>({ schema: QuerySchema }).fields({ query }).build()
|
|
583
533
|
}),
|
|
584
534
|
)
|
|
585
|
-
const configSchema
|
|
535
|
+
const configSchema = await PayloadBuilder.build<ConfigPayload>({
|
|
586
536
|
config: config.schema,
|
|
587
537
|
schema: ConfigSchema,
|
|
588
|
-
}
|
|
538
|
+
})
|
|
589
539
|
return compact([config, configSchema, address, ...queries])
|
|
590
540
|
}
|
|
591
541
|
|
|
@@ -615,9 +565,20 @@ export abstract class AbstractModule<TParams extends ModuleParams = ModuleParams
|
|
|
615
565
|
}
|
|
616
566
|
}
|
|
617
567
|
|
|
618
|
-
protected manifestHandler(
|
|
568
|
+
protected async manifestHandler(maxDepth: number = 1, _ignoreAddresses: Address[] = []): Promise<ModuleManifestPayload> {
|
|
619
569
|
const name = this.config.name ?? 'Anonymous'
|
|
620
|
-
|
|
570
|
+
const children = await this.downResolver.resolve('*', { direction: 'down', maxDepth })
|
|
571
|
+
const childAddressToName: Record<Address, ModuleName | null> = {}
|
|
572
|
+
for (const child of children) {
|
|
573
|
+
if (child.address !== this.address) {
|
|
574
|
+
childAddressToName[child.address] = child.config.name ?? null
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
return {
|
|
578
|
+
config: { name, ...this.config },
|
|
579
|
+
schema: ModuleManifestPayloadSchema,
|
|
580
|
+
status: { address: this.address, children: childAddressToName },
|
|
581
|
+
}
|
|
621
582
|
}
|
|
622
583
|
|
|
623
584
|
protected moduleAddressHandler(): Promisable<AddressPreviousHashPayload[]> {
|
|
@@ -686,13 +647,6 @@ export abstract class AbstractModule<TParams extends ModuleParams = ModuleParams
|
|
|
686
647
|
return resultPayloads
|
|
687
648
|
}
|
|
688
649
|
|
|
689
|
-
protected async resolveArchivingArchivists(): Promise<ArchivistInstance[]> {
|
|
690
|
-
const archivists = this.config.archiving?.archivists
|
|
691
|
-
if (!archivists) return []
|
|
692
|
-
const resolved = await Promise.all(archivists.map((archivist) => this.resolve(archivist)))
|
|
693
|
-
return compact(resolved.map((mod) => asArchivistInstance(mod)))
|
|
694
|
-
}
|
|
695
|
-
|
|
696
650
|
protected async startHandler(): Promise<boolean> {
|
|
697
651
|
this.validateConfig()
|
|
698
652
|
await this.initializeQueryAccounts()
|
|
@@ -709,17 +663,6 @@ export abstract class AbstractModule<TParams extends ModuleParams = ModuleParams
|
|
|
709
663
|
return true
|
|
710
664
|
}
|
|
711
665
|
|
|
712
|
-
protected async storeToArchivists(payloads: Payload[]): Promise<Payload[]> {
|
|
713
|
-
const archivists = await this.resolveArchivingArchivists()
|
|
714
|
-
return (
|
|
715
|
-
await Promise.all(
|
|
716
|
-
archivists.map((archivist) => {
|
|
717
|
-
return archivist.insert?.(payloads)
|
|
718
|
-
}),
|
|
719
|
-
)
|
|
720
|
-
).map(([bw]) => bw)
|
|
721
|
-
}
|
|
722
|
-
|
|
723
666
|
protected subscribeHandler() {
|
|
724
667
|
return
|
|
725
668
|
}
|
|
@@ -755,26 +698,5 @@ export abstract class AbstractModule<TParams extends ModuleParams = ModuleParams
|
|
|
755
698
|
}, true)
|
|
756
699
|
}
|
|
757
700
|
|
|
758
|
-
|
|
759
|
-
required: boolean | 'warn' | 'log',
|
|
760
|
-
result: ModuleInstance[] | ModuleInstance | undefined,
|
|
761
|
-
idOrFilter: ModuleIdentifier | ModuleFilter,
|
|
762
|
-
) {
|
|
763
|
-
if (required && (result === undefined || (Array.isArray(result) && result.length > 0))) {
|
|
764
|
-
switch (required) {
|
|
765
|
-
case 'warn': {
|
|
766
|
-
this.logger.warn('resolve failed', idOrFilter)
|
|
767
|
-
break
|
|
768
|
-
}
|
|
769
|
-
case 'log': {
|
|
770
|
-
this.logger.log('resolve failed', idOrFilter)
|
|
771
|
-
break
|
|
772
|
-
}
|
|
773
|
-
default: {
|
|
774
|
-
this.logger.error('resolve failed', idOrFilter)
|
|
775
|
-
break
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
}
|
|
701
|
+
protected abstract storeToArchivists(payloads: Payload[]): Promise<Payload[]>
|
|
780
702
|
}
|
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
import { assertEx } from '@xylabs/assert'
|
|
2
2
|
import { Address } from '@xylabs/hex'
|
|
3
|
+
import { compact } from '@xylabs/lodash'
|
|
3
4
|
import { AccountInstance } from '@xyo-network/account-model'
|
|
5
|
+
import { ArchivistInstance, asArchivistInstance } from '@xyo-network/archivist-model'
|
|
4
6
|
import { ModuleManifestPayload } from '@xyo-network/manifest-model'
|
|
5
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
AddressPreviousHashPayload,
|
|
9
|
+
ModuleDescriptionPayload,
|
|
10
|
+
ModuleEventData,
|
|
11
|
+
ModuleFilter,
|
|
12
|
+
ModuleFilterOptions,
|
|
13
|
+
ModuleIdentifier,
|
|
14
|
+
ModuleInstance,
|
|
15
|
+
ModuleParams,
|
|
16
|
+
} from '@xyo-network/module-model'
|
|
6
17
|
import { Payload } from '@xyo-network/payload-model'
|
|
7
18
|
|
|
8
19
|
import { AbstractModule } from './AbstractModule'
|
|
20
|
+
import { ResolveHelper, ResolveHelperConfig } from './ResolveHelper'
|
|
9
21
|
|
|
10
22
|
export abstract class AbstractModuleInstance<TParams extends ModuleParams = ModuleParams, TEventData extends ModuleEventData = ModuleEventData>
|
|
11
23
|
extends AbstractModule<TParams, TEventData>
|
|
12
|
-
implements
|
|
24
|
+
implements ModuleInstance<TParams, TEventData>
|
|
13
25
|
{
|
|
14
26
|
constructor(privateConstructorKey: string, params: TParams, account: AccountInstance) {
|
|
15
27
|
assertEx(AbstractModule.privateConstructorKey === privateConstructorKey, () => 'Use create function instead of constructor')
|
|
@@ -27,10 +39,10 @@ export abstract class AbstractModuleInstance<TParams extends ModuleParams = Modu
|
|
|
27
39
|
})
|
|
28
40
|
}
|
|
29
41
|
|
|
30
|
-
discover(): Promise<Payload[]> {
|
|
42
|
+
discover(maxDepth = 5): Promise<Payload[]> {
|
|
31
43
|
this._checkDead()
|
|
32
44
|
return this.busy(async () => {
|
|
33
|
-
return await this.discoverHandler()
|
|
45
|
+
return await this.discoverHandler(maxDepth)
|
|
34
46
|
})
|
|
35
47
|
}
|
|
36
48
|
|
|
@@ -48,6 +60,41 @@ export abstract class AbstractModuleInstance<TParams extends ModuleParams = Modu
|
|
|
48
60
|
})
|
|
49
61
|
}
|
|
50
62
|
|
|
63
|
+
/** @deprecated do not pass undefined. If trying to get all, pass '*' */
|
|
64
|
+
async resolve(): Promise<ModuleInstance[]>
|
|
65
|
+
async resolve<T extends ModuleInstance = ModuleInstance>(all: '*', options?: ModuleFilterOptions<T>): Promise<T[]>
|
|
66
|
+
async resolve<T extends ModuleInstance = ModuleInstance>(filter: ModuleFilter, options?: ModuleFilterOptions<T>): Promise<T[]>
|
|
67
|
+
async resolve<T extends ModuleInstance = ModuleInstance>(id: ModuleIdentifier, options?: ModuleFilterOptions<T>): Promise<T | undefined>
|
|
68
|
+
/** @deprecated use '*' if trying to resolve all */
|
|
69
|
+
async resolve<T extends ModuleInstance = ModuleInstance>(filter?: ModuleFilter, options?: ModuleFilterOptions<T>): Promise<T[]>
|
|
70
|
+
async resolve<T extends ModuleInstance = ModuleInstance>(
|
|
71
|
+
idOrFilter: ModuleFilter<T> | ModuleIdentifier = '*',
|
|
72
|
+
options: ModuleFilterOptions<T> = {},
|
|
73
|
+
): Promise<T | T[] | undefined> {
|
|
74
|
+
const config: ResolveHelperConfig = {
|
|
75
|
+
address: this.address,
|
|
76
|
+
dead: this.dead,
|
|
77
|
+
downResolver: this.downResolver,
|
|
78
|
+
logger: this.logger,
|
|
79
|
+
module: this,
|
|
80
|
+
upResolver: this.upResolver,
|
|
81
|
+
}
|
|
82
|
+
if (idOrFilter === '*') {
|
|
83
|
+
return await ResolveHelper.resolve(config, idOrFilter, options)
|
|
84
|
+
}
|
|
85
|
+
switch (typeof idOrFilter) {
|
|
86
|
+
case 'string': {
|
|
87
|
+
return await ResolveHelper.resolve(config, idOrFilter, options)
|
|
88
|
+
}
|
|
89
|
+
case 'object': {
|
|
90
|
+
return await ResolveHelper.resolve(config, idOrFilter, options)
|
|
91
|
+
}
|
|
92
|
+
default: {
|
|
93
|
+
return await ResolveHelper.resolve(config, idOrFilter, options)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
51
98
|
state() {
|
|
52
99
|
this._checkDead()
|
|
53
100
|
return this.busy(async () => {
|
|
@@ -59,4 +106,22 @@ export abstract class AbstractModuleInstance<TParams extends ModuleParams = Modu
|
|
|
59
106
|
this._checkDead()
|
|
60
107
|
return this.subscribeHandler()
|
|
61
108
|
}
|
|
109
|
+
|
|
110
|
+
protected async resolveArchivingArchivists(): Promise<ArchivistInstance[]> {
|
|
111
|
+
const archivists = this.config.archiving?.archivists
|
|
112
|
+
if (!archivists) return []
|
|
113
|
+
const resolved = await Promise.all(archivists.map((archivist) => this.resolve(archivist)))
|
|
114
|
+
return compact(resolved.map((mod) => asArchivistInstance(mod)))
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
protected async storeToArchivists(payloads: Payload[]): Promise<Payload[]> {
|
|
118
|
+
const archivists = await this.resolveArchivingArchivists()
|
|
119
|
+
return (
|
|
120
|
+
await Promise.all(
|
|
121
|
+
archivists.map((archivist) => {
|
|
122
|
+
return archivist.insert?.(payloads)
|
|
123
|
+
}),
|
|
124
|
+
)
|
|
125
|
+
).map(([bw]) => bw)
|
|
126
|
+
}
|
|
62
127
|
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/* eslint-disable complexity */
|
|
2
|
+
import { Address } from '@xylabs/hex'
|
|
3
|
+
import { IdLogger, Logger } from '@xylabs/logger'
|
|
4
|
+
import { toJsonString } from '@xylabs/object'
|
|
5
|
+
import { duplicateModules, ModuleFilter, ModuleFilterOptions, ModuleIdentifier, ModuleInstance, ModuleResolver } from '@xyo-network/module-model'
|
|
6
|
+
|
|
7
|
+
export interface ResolveHelperConfig {
|
|
8
|
+
address: Address
|
|
9
|
+
dead?: boolean
|
|
10
|
+
downResolver?: ModuleResolver
|
|
11
|
+
logger?: Logger
|
|
12
|
+
module: ModuleInstance
|
|
13
|
+
upResolver?: ModuleResolver
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class ResolveHelper {
|
|
17
|
+
static defaultLogger?: Logger
|
|
18
|
+
static async resolve<T extends ModuleInstance = ModuleInstance>(
|
|
19
|
+
config: ResolveHelperConfig,
|
|
20
|
+
all: '*',
|
|
21
|
+
options?: ModuleFilterOptions<T>,
|
|
22
|
+
): Promise<T[]>
|
|
23
|
+
static async resolve<T extends ModuleInstance = ModuleInstance>(
|
|
24
|
+
config: ResolveHelperConfig,
|
|
25
|
+
filter: ModuleFilter,
|
|
26
|
+
options?: ModuleFilterOptions<T>,
|
|
27
|
+
): Promise<T[]>
|
|
28
|
+
static async resolve<T extends ModuleInstance = ModuleInstance>(
|
|
29
|
+
config: ResolveHelperConfig,
|
|
30
|
+
id: ModuleIdentifier,
|
|
31
|
+
options?: ModuleFilterOptions<T>,
|
|
32
|
+
): Promise<T | undefined>
|
|
33
|
+
static async resolve<T extends ModuleInstance = ModuleInstance>(
|
|
34
|
+
config: ResolveHelperConfig,
|
|
35
|
+
idOrFilter: ModuleFilter<T> | ModuleIdentifier = '*',
|
|
36
|
+
{ visibility, maxDepth = 5, required = 'log', ...options }: ModuleFilterOptions<T> = {},
|
|
37
|
+
): Promise<T | T[] | undefined> {
|
|
38
|
+
const { module, logger = this.defaultLogger, dead = false, upResolver, downResolver } = config
|
|
39
|
+
const log = logger ? new IdLogger(logger, () => `ResolveHelper [${module.id}][${idOrFilter}][${visibility}]`) : undefined
|
|
40
|
+
const childOptions: ModuleFilterOptions<T> = { ...options, direction: 'down', maxDepth: maxDepth - 1, required: false, visibility }
|
|
41
|
+
const direction = options?.direction ?? 'all'
|
|
42
|
+
const up = direction === 'up' || direction === 'all'
|
|
43
|
+
const down = direction === 'down' || direction === 'all'
|
|
44
|
+
let result: T | T[] | undefined
|
|
45
|
+
log?.debug('start', idOrFilter, maxDepth)
|
|
46
|
+
if (idOrFilter === '*') {
|
|
47
|
+
if (dead) {
|
|
48
|
+
log?.warn('failed [dead]', idOrFilter)
|
|
49
|
+
return []
|
|
50
|
+
}
|
|
51
|
+
const modules = [
|
|
52
|
+
...(down ? await (downResolver as ModuleResolver).resolve<T>('*', childOptions) : []),
|
|
53
|
+
...(up ? await (upResolver as ModuleResolver).resolve<T>('*', childOptions) : []),
|
|
54
|
+
]
|
|
55
|
+
.filter(duplicateModules)
|
|
56
|
+
.filter((module) => module.address !== config.address)
|
|
57
|
+
|
|
58
|
+
if (modules.length > 0) {
|
|
59
|
+
log?.log('modules [count]', modules.length)
|
|
60
|
+
log?.debug('modules', toJsonString(modules, 4))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (maxDepth === 0) {
|
|
64
|
+
return modules
|
|
65
|
+
}
|
|
66
|
+
const childModules = (await Promise.all(modules.map(async (module) => await module.resolve<T>('*', childOptions))))
|
|
67
|
+
.flat()
|
|
68
|
+
.filter(duplicateModules)
|
|
69
|
+
return [module as T, ...modules, ...childModules].filter(duplicateModules)
|
|
70
|
+
} else {
|
|
71
|
+
switch (typeof idOrFilter) {
|
|
72
|
+
case 'string': {
|
|
73
|
+
if (dead) {
|
|
74
|
+
return undefined
|
|
75
|
+
}
|
|
76
|
+
result =
|
|
77
|
+
(down ? await (downResolver as ModuleResolver).resolve<T>(idOrFilter, childOptions) : undefined) ??
|
|
78
|
+
(up ? await (upResolver as ModuleResolver).resolve<T>(idOrFilter, childOptions) : undefined)
|
|
79
|
+
break
|
|
80
|
+
}
|
|
81
|
+
default: {
|
|
82
|
+
if (dead) {
|
|
83
|
+
return []
|
|
84
|
+
}
|
|
85
|
+
const filter: ModuleFilter<T> | undefined = idOrFilter
|
|
86
|
+
result = [
|
|
87
|
+
...(down ? await (downResolver as ModuleResolver).resolve<T>(filter, childOptions) : []),
|
|
88
|
+
...(up ? await (upResolver as ModuleResolver).resolve<T>(filter, childOptions) : []),
|
|
89
|
+
].filter(duplicateModules)
|
|
90
|
+
break
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
this.validateRequiredResolve(required, result, idOrFilter, logger)
|
|
95
|
+
return result
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
static validateRequiredResolve(
|
|
99
|
+
required: boolean | 'warn' | 'log',
|
|
100
|
+
result: ModuleInstance[] | ModuleInstance | undefined,
|
|
101
|
+
idOrFilter: ModuleIdentifier | ModuleFilter,
|
|
102
|
+
logger = this.defaultLogger,
|
|
103
|
+
) {
|
|
104
|
+
const log = logger ? new IdLogger(logger, () => `validateRequiredResolve [${idOrFilter}][${result}]`) : undefined
|
|
105
|
+
if (required && (result === undefined || (Array.isArray(result) && result.length > 0))) {
|
|
106
|
+
switch (required) {
|
|
107
|
+
case 'warn': {
|
|
108
|
+
log?.warn('resolve failed', idOrFilter)
|
|
109
|
+
break
|
|
110
|
+
}
|
|
111
|
+
case 'log': {
|
|
112
|
+
log?.log('resolve failed', idOrFilter)
|
|
113
|
+
break
|
|
114
|
+
}
|
|
115
|
+
default: {
|
|
116
|
+
throw new Error(`resolve failed [${idOrFilter}]`)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
package/src/index.ts
CHANGED