@xyo-network/bridge-abstract 2.102.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.
- package/LICENSE +165 -0
- package/README.md +13 -0
- package/dist/browser/AbstractBridge.d.cts +36 -0
- package/dist/browser/AbstractBridge.d.cts.map +1 -0
- package/dist/browser/AbstractBridge.d.mts +36 -0
- package/dist/browser/AbstractBridge.d.mts.map +1 -0
- package/dist/browser/AbstractBridge.d.ts +36 -0
- package/dist/browser/AbstractBridge.d.ts.map +1 -0
- package/dist/browser/AbstractBridgeModuleResolver.d.cts +21 -0
- package/dist/browser/AbstractBridgeModuleResolver.d.cts.map +1 -0
- package/dist/browser/AbstractBridgeModuleResolver.d.mts +21 -0
- package/dist/browser/AbstractBridgeModuleResolver.d.mts.map +1 -0
- package/dist/browser/AbstractBridgeModuleResolver.d.ts +21 -0
- package/dist/browser/AbstractBridgeModuleResolver.d.ts.map +1 -0
- package/dist/browser/AbstractModuleProxy/AbstractModuleProxy.d.cts +74 -0
- package/dist/browser/AbstractModuleProxy/AbstractModuleProxy.d.cts.map +1 -0
- package/dist/browser/AbstractModuleProxy/AbstractModuleProxy.d.mts +74 -0
- package/dist/browser/AbstractModuleProxy/AbstractModuleProxy.d.mts.map +1 -0
- package/dist/browser/AbstractModuleProxy/AbstractModuleProxy.d.ts +74 -0
- package/dist/browser/AbstractModuleProxy/AbstractModuleProxy.d.ts.map +1 -0
- package/dist/browser/AbstractModuleProxy/ModuleProxyResolver.d.cts +65 -0
- package/dist/browser/AbstractModuleProxy/ModuleProxyResolver.d.cts.map +1 -0
- package/dist/browser/AbstractModuleProxy/ModuleProxyResolver.d.mts +65 -0
- package/dist/browser/AbstractModuleProxy/ModuleProxyResolver.d.mts.map +1 -0
- package/dist/browser/AbstractModuleProxy/ModuleProxyResolver.d.ts +65 -0
- package/dist/browser/AbstractModuleProxy/ModuleProxyResolver.d.ts.map +1 -0
- package/dist/browser/AbstractModuleProxy/index.d.cts +3 -0
- package/dist/browser/AbstractModuleProxy/index.d.cts.map +1 -0
- package/dist/browser/AbstractModuleProxy/index.d.mts +3 -0
- package/dist/browser/AbstractModuleProxy/index.d.mts.map +1 -0
- package/dist/browser/AbstractModuleProxy/index.d.ts +3 -0
- package/dist/browser/AbstractModuleProxy/index.d.ts.map +1 -0
- package/dist/browser/index.cjs +585 -0
- package/dist/browser/index.cjs.map +1 -0
- package/dist/browser/index.d.cts +5 -0
- package/dist/browser/index.d.cts.map +1 -0
- package/dist/browser/index.d.mts +5 -0
- package/dist/browser/index.d.mts.map +1 -0
- package/dist/browser/index.d.ts +5 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +564 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/wrapModuleWithType.d.cts +5 -0
- package/dist/browser/wrapModuleWithType.d.cts.map +1 -0
- package/dist/browser/wrapModuleWithType.d.mts +5 -0
- package/dist/browser/wrapModuleWithType.d.mts.map +1 -0
- package/dist/browser/wrapModuleWithType.d.ts +5 -0
- package/dist/browser/wrapModuleWithType.d.ts.map +1 -0
- package/dist/neutral/AbstractBridge.d.cts +36 -0
- package/dist/neutral/AbstractBridge.d.cts.map +1 -0
- package/dist/neutral/AbstractBridge.d.mts +36 -0
- package/dist/neutral/AbstractBridge.d.mts.map +1 -0
- package/dist/neutral/AbstractBridge.d.ts +36 -0
- package/dist/neutral/AbstractBridge.d.ts.map +1 -0
- package/dist/neutral/AbstractBridgeModuleResolver.d.cts +21 -0
- package/dist/neutral/AbstractBridgeModuleResolver.d.cts.map +1 -0
- package/dist/neutral/AbstractBridgeModuleResolver.d.mts +21 -0
- package/dist/neutral/AbstractBridgeModuleResolver.d.mts.map +1 -0
- package/dist/neutral/AbstractBridgeModuleResolver.d.ts +21 -0
- package/dist/neutral/AbstractBridgeModuleResolver.d.ts.map +1 -0
- package/dist/neutral/AbstractModuleProxy/AbstractModuleProxy.d.cts +74 -0
- package/dist/neutral/AbstractModuleProxy/AbstractModuleProxy.d.cts.map +1 -0
- package/dist/neutral/AbstractModuleProxy/AbstractModuleProxy.d.mts +74 -0
- package/dist/neutral/AbstractModuleProxy/AbstractModuleProxy.d.mts.map +1 -0
- package/dist/neutral/AbstractModuleProxy/AbstractModuleProxy.d.ts +74 -0
- package/dist/neutral/AbstractModuleProxy/AbstractModuleProxy.d.ts.map +1 -0
- package/dist/neutral/AbstractModuleProxy/ModuleProxyResolver.d.cts +65 -0
- package/dist/neutral/AbstractModuleProxy/ModuleProxyResolver.d.cts.map +1 -0
- package/dist/neutral/AbstractModuleProxy/ModuleProxyResolver.d.mts +65 -0
- package/dist/neutral/AbstractModuleProxy/ModuleProxyResolver.d.mts.map +1 -0
- package/dist/neutral/AbstractModuleProxy/ModuleProxyResolver.d.ts +65 -0
- package/dist/neutral/AbstractModuleProxy/ModuleProxyResolver.d.ts.map +1 -0
- package/dist/neutral/AbstractModuleProxy/index.d.cts +3 -0
- package/dist/neutral/AbstractModuleProxy/index.d.cts.map +1 -0
- package/dist/neutral/AbstractModuleProxy/index.d.mts +3 -0
- package/dist/neutral/AbstractModuleProxy/index.d.mts.map +1 -0
- package/dist/neutral/AbstractModuleProxy/index.d.ts +3 -0
- package/dist/neutral/AbstractModuleProxy/index.d.ts.map +1 -0
- package/dist/neutral/index.cjs +585 -0
- package/dist/neutral/index.cjs.map +1 -0
- package/dist/neutral/index.d.cts +5 -0
- package/dist/neutral/index.d.cts.map +1 -0
- package/dist/neutral/index.d.mts +5 -0
- package/dist/neutral/index.d.mts.map +1 -0
- package/dist/neutral/index.d.ts +5 -0
- package/dist/neutral/index.d.ts.map +1 -0
- package/dist/neutral/index.js +564 -0
- package/dist/neutral/index.js.map +1 -0
- package/dist/neutral/wrapModuleWithType.d.cts +5 -0
- package/dist/neutral/wrapModuleWithType.d.cts.map +1 -0
- package/dist/neutral/wrapModuleWithType.d.mts +5 -0
- package/dist/neutral/wrapModuleWithType.d.mts.map +1 -0
- package/dist/neutral/wrapModuleWithType.d.ts +5 -0
- package/dist/neutral/wrapModuleWithType.d.ts.map +1 -0
- package/dist/node/AbstractBridge.d.cts +36 -0
- package/dist/node/AbstractBridge.d.cts.map +1 -0
- package/dist/node/AbstractBridge.d.mts +36 -0
- package/dist/node/AbstractBridge.d.mts.map +1 -0
- package/dist/node/AbstractBridge.d.ts +36 -0
- package/dist/node/AbstractBridge.d.ts.map +1 -0
- package/dist/node/AbstractBridgeModuleResolver.d.cts +21 -0
- package/dist/node/AbstractBridgeModuleResolver.d.cts.map +1 -0
- package/dist/node/AbstractBridgeModuleResolver.d.mts +21 -0
- package/dist/node/AbstractBridgeModuleResolver.d.mts.map +1 -0
- package/dist/node/AbstractBridgeModuleResolver.d.ts +21 -0
- package/dist/node/AbstractBridgeModuleResolver.d.ts.map +1 -0
- package/dist/node/AbstractModuleProxy/AbstractModuleProxy.d.cts +74 -0
- package/dist/node/AbstractModuleProxy/AbstractModuleProxy.d.cts.map +1 -0
- package/dist/node/AbstractModuleProxy/AbstractModuleProxy.d.mts +74 -0
- package/dist/node/AbstractModuleProxy/AbstractModuleProxy.d.mts.map +1 -0
- package/dist/node/AbstractModuleProxy/AbstractModuleProxy.d.ts +74 -0
- package/dist/node/AbstractModuleProxy/AbstractModuleProxy.d.ts.map +1 -0
- package/dist/node/AbstractModuleProxy/ModuleProxyResolver.d.cts +65 -0
- package/dist/node/AbstractModuleProxy/ModuleProxyResolver.d.cts.map +1 -0
- package/dist/node/AbstractModuleProxy/ModuleProxyResolver.d.mts +65 -0
- package/dist/node/AbstractModuleProxy/ModuleProxyResolver.d.mts.map +1 -0
- package/dist/node/AbstractModuleProxy/ModuleProxyResolver.d.ts +65 -0
- package/dist/node/AbstractModuleProxy/ModuleProxyResolver.d.ts.map +1 -0
- package/dist/node/AbstractModuleProxy/index.d.cts +3 -0
- package/dist/node/AbstractModuleProxy/index.d.cts.map +1 -0
- package/dist/node/AbstractModuleProxy/index.d.mts +3 -0
- package/dist/node/AbstractModuleProxy/index.d.mts.map +1 -0
- package/dist/node/AbstractModuleProxy/index.d.ts +3 -0
- package/dist/node/AbstractModuleProxy/index.d.ts.map +1 -0
- package/dist/node/index.cjs +609 -0
- package/dist/node/index.cjs.map +1 -0
- package/dist/node/index.d.cts +5 -0
- package/dist/node/index.d.cts.map +1 -0
- package/dist/node/index.d.mts +5 -0
- package/dist/node/index.d.mts.map +1 -0
- package/dist/node/index.d.ts +5 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +580 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/wrapModuleWithType.d.cts +5 -0
- package/dist/node/wrapModuleWithType.d.cts.map +1 -0
- package/dist/node/wrapModuleWithType.d.mts +5 -0
- package/dist/node/wrapModuleWithType.d.mts.map +1 -0
- package/dist/node/wrapModuleWithType.d.ts +5 -0
- package/dist/node/wrapModuleWithType.d.ts.map +1 -0
- package/package.json +92 -0
- package/src/AbstractBridge.ts +232 -0
- package/src/AbstractBridgeModuleResolver.ts +42 -0
- package/src/AbstractModuleProxy/AbstractModuleProxy.ts +268 -0
- package/src/AbstractModuleProxy/ModuleProxyResolver.ts +143 -0
- package/src/AbstractModuleProxy/index.ts +2 -0
- package/src/index.ts +4 -0
- package/src/wrapModuleWithType.ts +32 -0
- package/typedoc.json +5 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
import { forget } from '@xylabs/forget'
|
|
3
|
+
import { Address, asAddress } from '@xylabs/hex'
|
|
4
|
+
import { compact } from '@xylabs/lodash'
|
|
5
|
+
import { toJsonString } from '@xylabs/object'
|
|
6
|
+
import { AccountInstance } from '@xyo-network/account-model'
|
|
7
|
+
import { ArchivistInstance } from '@xyo-network/archivist-model'
|
|
8
|
+
import { QueryBoundWitness } from '@xyo-network/boundwitness-model'
|
|
9
|
+
import { BoundWitnessWrapper, QueryBoundWitnessWrapper } from '@xyo-network/boundwitness-wrapper'
|
|
10
|
+
import { QuerySendFinishedEventArgs, QuerySendStartedEventArgs } from '@xyo-network/bridge-model'
|
|
11
|
+
import { ModuleManifestPayload, ModuleManifestPayloadSchema, NodeManifestPayload, NodeManifestPayloadSchema } from '@xyo-network/manifest-model'
|
|
12
|
+
import { AbstractModuleInstance } from '@xyo-network/module-abstract'
|
|
13
|
+
import {
|
|
14
|
+
AddressPreviousHashPayload,
|
|
15
|
+
AddressPreviousHashSchema,
|
|
16
|
+
ArchivingModuleConfig,
|
|
17
|
+
DeadModuleError,
|
|
18
|
+
Module,
|
|
19
|
+
ModuleAddressQuery,
|
|
20
|
+
ModuleAddressQuerySchema,
|
|
21
|
+
ModuleConfigSchema,
|
|
22
|
+
ModuleInstance,
|
|
23
|
+
ModuleManifestQuery,
|
|
24
|
+
ModuleManifestQuerySchema,
|
|
25
|
+
ModuleName,
|
|
26
|
+
ModuleParams,
|
|
27
|
+
ModuleQueryHandlerResult,
|
|
28
|
+
ModuleQueryResult,
|
|
29
|
+
ModuleResolver,
|
|
30
|
+
ModuleStateQuerySchema,
|
|
31
|
+
} from '@xyo-network/module-model'
|
|
32
|
+
import { ModuleWrapper } from '@xyo-network/module-wrapper'
|
|
33
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
34
|
+
import { isPayloadOfSchemaType, ModuleError, ModuleErrorSchema, Payload, WithMeta } from '@xyo-network/payload-model'
|
|
35
|
+
import { QueryPayload, QuerySchema } from '@xyo-network/query-payload-plugin'
|
|
36
|
+
import { LRUCache } from 'lru-cache'
|
|
37
|
+
|
|
38
|
+
import { ModuleProxyResolver } from './ModuleProxyResolver'
|
|
39
|
+
|
|
40
|
+
export type ModuleProxyParams = ModuleParams<
|
|
41
|
+
{
|
|
42
|
+
schema: ModuleConfigSchema
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
account: AccountInstance
|
|
46
|
+
archiving?: ArchivingModuleConfig['archiving'] & { resolveArchivists: () => Promise<ArchivistInstance[]> }
|
|
47
|
+
host: ModuleResolver
|
|
48
|
+
moduleAddress: Address
|
|
49
|
+
onQuerySendFinished?: (args: Omit<QuerySendFinishedEventArgs, 'module'>) => void
|
|
50
|
+
onQuerySendStarted?: (args: Omit<QuerySendStartedEventArgs, 'module'>) => void
|
|
51
|
+
}
|
|
52
|
+
>
|
|
53
|
+
|
|
54
|
+
export abstract class AbstractModuleProxy<
|
|
55
|
+
TWrappedModule extends ModuleInstance = ModuleInstance,
|
|
56
|
+
TParams extends Omit<ModuleProxyParams, 'config'> & { config: TWrappedModule['config'] } = Omit<ModuleProxyParams, 'config'> & {
|
|
57
|
+
config: TWrappedModule['config']
|
|
58
|
+
},
|
|
59
|
+
>
|
|
60
|
+
extends AbstractModuleInstance<TParams, TWrappedModule['eventData']>
|
|
61
|
+
implements ModuleInstance<TParams, TWrappedModule['eventData']>
|
|
62
|
+
{
|
|
63
|
+
static requiredQueries: string[] = [ModuleStateQuerySchema]
|
|
64
|
+
|
|
65
|
+
protected _config?: ModuleInstance['config']
|
|
66
|
+
protected _publicChildren?: ModuleInstance[]
|
|
67
|
+
protected _state: Payload[] | undefined = undefined
|
|
68
|
+
protected _stateInProcess = false
|
|
69
|
+
|
|
70
|
+
private _spamTrap = new LRUCache<string, number>({ max: 1000, ttl: 1000 * 60, ttlAutopurge: true })
|
|
71
|
+
|
|
72
|
+
constructor(params: TParams) {
|
|
73
|
+
params.addToResolvers = false
|
|
74
|
+
super(AbstractModuleProxy.privateConstructorKey, params, params.account)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
override get address() {
|
|
78
|
+
return this.params.moduleAddress
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
override get archiving(): ArchivingModuleConfig['archiving'] | undefined {
|
|
82
|
+
return this.params?.archiving
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
override get config() {
|
|
86
|
+
return assertEx(this._config, () => 'Config not set')
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
override get queries(): string[] {
|
|
90
|
+
const queryPayloads = assertEx(this._state, () => 'Module state not found. Make sure proxy has been started').filter((item) =>
|
|
91
|
+
isPayloadOfSchemaType<QueryPayload>(QuerySchema)(item),
|
|
92
|
+
) as QueryPayload[]
|
|
93
|
+
return queryPayloads.map((payload) => payload.query)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
protected override get _queryAccountPaths() {
|
|
97
|
+
return this._baseModuleQueryAccountPaths
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static hasRequiredQueries(module: Module) {
|
|
101
|
+
return this.missingRequiredQueries(module).length === 0
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
static missingRequiredQueries(module: Module): string[] {
|
|
105
|
+
const moduleQueries = module.queries
|
|
106
|
+
return compact(
|
|
107
|
+
this.requiredQueries.map((query) => {
|
|
108
|
+
return moduleQueries.includes(query) ? null : query
|
|
109
|
+
}),
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async addressPreviousHash(): Promise<AddressPreviousHashPayload> {
|
|
114
|
+
const queryPayload: ModuleAddressQuery = { schema: ModuleAddressQuerySchema }
|
|
115
|
+
const result: AddressPreviousHashPayload = assertEx(
|
|
116
|
+
(await this.sendQuery(queryPayload, undefined, this.account)).find(
|
|
117
|
+
isPayloadOfSchemaType<AddressPreviousHashPayload>(AddressPreviousHashSchema),
|
|
118
|
+
) as WithMeta<AddressPreviousHashPayload>,
|
|
119
|
+
() => 'Result did not include correct payload',
|
|
120
|
+
)
|
|
121
|
+
return result
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
childAddressByName(name: ModuleName): Address | undefined {
|
|
125
|
+
const nodeManifests = this._state?.filter(isPayloadOfSchemaType<NodeManifestPayload>(NodeManifestPayloadSchema))
|
|
126
|
+
const childPairs = nodeManifests?.flatMap((nodeManifest) => Object.entries(nodeManifest.status?.children ?? {}) as [Address, ModuleName | null][])
|
|
127
|
+
return asAddress(childPairs?.find(([_, childName]) => childName === name)?.[0])
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async childAddressMap(): Promise<Record<Address, ModuleName | null>> {
|
|
131
|
+
const state = await this.state()
|
|
132
|
+
const result: Record<Address, ModuleName | null> = {}
|
|
133
|
+
const nodeManifests = state.filter(isPayloadOfSchemaType<NodeManifestPayload>(NodeManifestPayloadSchema))
|
|
134
|
+
for (const manifest of nodeManifests) {
|
|
135
|
+
const children = manifest.modules?.public ?? []
|
|
136
|
+
for (const child of children) {
|
|
137
|
+
if (typeof child === 'object') {
|
|
138
|
+
const address = child.status?.address
|
|
139
|
+
if (address) {
|
|
140
|
+
result[address] = child.config.name ?? null
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return result
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
override async manifest(maxDepth?: number): Promise<ModuleManifestPayload> {
|
|
149
|
+
const queryPayload: ModuleManifestQuery = { schema: ModuleManifestQuerySchema, ...(maxDepth === undefined ? {} : { maxDepth }) }
|
|
150
|
+
return (await this.sendQuery(queryPayload))[0] as WithMeta<ModuleManifestPayload>
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
override async moduleAddress(): Promise<AddressPreviousHashPayload[]> {
|
|
154
|
+
const queryPayload: ModuleAddressQuery = { schema: ModuleAddressQuerySchema }
|
|
155
|
+
return (await this.sendQuery(queryPayload)) as WithMeta<AddressPreviousHashPayload>[]
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
override async previousHash(): Promise<string | undefined> {
|
|
159
|
+
const queryPayload: ModuleAddressQuery = { schema: ModuleAddressQuerySchema }
|
|
160
|
+
return ((await this.sendQuery(queryPayload)).pop() as WithMeta<AddressPreviousHashPayload>).previousHash
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
override async publicChildren() {
|
|
164
|
+
this._publicChildren = this._publicChildren ?? (await super.publicChildren())
|
|
165
|
+
return this._publicChildren
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
override async query<T extends QueryBoundWitness = QueryBoundWitness>(query: T, payloads?: Payload[]): Promise<ModuleQueryResult> {
|
|
169
|
+
this._checkDead()
|
|
170
|
+
return await this.busy(async () => {
|
|
171
|
+
try {
|
|
172
|
+
await this.checkSpam(query)
|
|
173
|
+
this.params.onQuerySendStarted?.({ payloads, query })
|
|
174
|
+
const result = await this.proxyQueryHandler<T>(query, payloads)
|
|
175
|
+
this.params.onQuerySendFinished?.({ payloads, query, result, status: 'success' })
|
|
176
|
+
if (this.archiving && this.isAllowedArchivingQuery(query.schema)) {
|
|
177
|
+
forget(this.storeToArchivists(result.flat()))
|
|
178
|
+
}
|
|
179
|
+
forget(this.emit('moduleQueried', { module: this, payloads, query, result }))
|
|
180
|
+
return result
|
|
181
|
+
} catch (ex) {
|
|
182
|
+
this.params.onQuerySendFinished?.({ payloads, query, status: 'failure' })
|
|
183
|
+
const error = ex as Error
|
|
184
|
+
this._lastError = error
|
|
185
|
+
//this.status = 'dead'
|
|
186
|
+
const deadError = new DeadModuleError(this.address, error)
|
|
187
|
+
const errorPayload: ModuleError = {
|
|
188
|
+
message: deadError.message,
|
|
189
|
+
name: deadError.name,
|
|
190
|
+
schema: ModuleErrorSchema,
|
|
191
|
+
}
|
|
192
|
+
const sourceQuery = await PayloadBuilder.build(assertEx(QueryBoundWitnessWrapper.unwrap(query), () => 'Invalid query'))
|
|
193
|
+
return await this.bindQueryResult(sourceQuery, [], undefined, [errorPayload])
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
override queryHandler<T extends QueryBoundWitness = QueryBoundWitness>(
|
|
199
|
+
_query: T,
|
|
200
|
+
_payloads?: Payload[],
|
|
201
|
+
_queryConfig?: TWrappedModule['params']['config'],
|
|
202
|
+
): Promise<ModuleQueryHandlerResult> {
|
|
203
|
+
throw new Error('queryHandler should never be called')
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
override async queryable<T extends QueryBoundWitness = QueryBoundWitness>(
|
|
207
|
+
_query: T,
|
|
208
|
+
_payloads?: Payload[],
|
|
209
|
+
_queryConfig?: TWrappedModule['params']['config'],
|
|
210
|
+
): Promise<boolean> {
|
|
211
|
+
return await Promise.resolve(true)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
override async resolveArchivingArchivists(): Promise<ArchivistInstance[]> {
|
|
215
|
+
return (await this.params.archiving?.resolveArchivists()) ?? []
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
setConfig(config: TWrappedModule['params']['config']) {
|
|
219
|
+
this._config = config
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
override async startHandler(): Promise<boolean> {
|
|
223
|
+
const state = await this.state()
|
|
224
|
+
const manifestPayload = state.find(
|
|
225
|
+
(payload) => isPayloadOfSchemaType(NodeManifestPayloadSchema)(payload) || isPayloadOfSchemaType(ModuleManifestPayloadSchema)(payload),
|
|
226
|
+
) as ModuleManifestPayload
|
|
227
|
+
const manifest = assertEx(manifestPayload, () => "Can't find manifest payload")
|
|
228
|
+
this.setConfig({ ...manifest.config })
|
|
229
|
+
this.downResolver.addResolver(
|
|
230
|
+
new ModuleProxyResolver({
|
|
231
|
+
childAddressMap: await this.childAddressMap(),
|
|
232
|
+
host: this.params.host,
|
|
233
|
+
module: this,
|
|
234
|
+
moduleIdentifierTransformers: this.params.moduleIdentifierTransformers,
|
|
235
|
+
}),
|
|
236
|
+
)
|
|
237
|
+
return await super.startHandler()
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
override async state(): Promise<Payload[]> {
|
|
241
|
+
if (this._state === undefined) {
|
|
242
|
+
//temporarily add ModuleStateQuerySchema to the schema list so we can wrap it and get the real query list
|
|
243
|
+
const stateQueryPayload: QueryPayload = { query: ModuleStateQuerySchema, schema: QuerySchema }
|
|
244
|
+
const manifestQueryPayload: QueryPayload = { query: ModuleManifestQuerySchema, schema: QuerySchema }
|
|
245
|
+
this._state = [stateQueryPayload, manifestQueryPayload]
|
|
246
|
+
const wrapper = ModuleWrapper.wrap(this, this.account)
|
|
247
|
+
this._state = await wrapper.state()
|
|
248
|
+
}
|
|
249
|
+
return this._state
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
protected async filterErrors(result: ModuleQueryResult): Promise<ModuleError[]> {
|
|
253
|
+
const wrapper = await BoundWitnessWrapper.wrap(result[0], result[1])
|
|
254
|
+
return wrapper.payloadsBySchema<WithMeta<ModuleError>>(ModuleErrorSchema)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
//this checks and warns if we are getting spammed by the same query
|
|
258
|
+
private async checkSpam(query: QueryBoundWitness) {
|
|
259
|
+
const hash = await PayloadBuilder.hash(query)
|
|
260
|
+
const previousCount = this._spamTrap.get(hash) ?? 0
|
|
261
|
+
if (previousCount > 0) {
|
|
262
|
+
this.logger?.warn(`Spam trap triggered for query: ${hash} from ${toJsonString(query.addresses)}`)
|
|
263
|
+
}
|
|
264
|
+
this._spamTrap.set(hash, previousCount + 1)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
abstract proxyQueryHandler<T extends QueryBoundWitness = QueryBoundWitness>(query: T, payloads?: Payload[]): Promise<ModuleQueryResult>
|
|
268
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
import { exists } from '@xylabs/exists'
|
|
3
|
+
import { Address } from '@xylabs/hex'
|
|
4
|
+
import { Promisable } from '@xylabs/promise'
|
|
5
|
+
import { Account } from '@xyo-network/account'
|
|
6
|
+
import {
|
|
7
|
+
isAddressModuleFilter,
|
|
8
|
+
isNameModuleFilter,
|
|
9
|
+
ModuleFilter,
|
|
10
|
+
ModuleFilterOptions,
|
|
11
|
+
ModuleIdentifier,
|
|
12
|
+
ModuleIdentifierTransformer,
|
|
13
|
+
ModuleInstance,
|
|
14
|
+
ModuleName,
|
|
15
|
+
ModuleResolver,
|
|
16
|
+
ModuleResolverInstance,
|
|
17
|
+
ObjectFilterOptions,
|
|
18
|
+
ObjectResolverPriority,
|
|
19
|
+
} from '@xyo-network/module-model'
|
|
20
|
+
import { CompositeModuleResolver } from '@xyo-network/module-resolver'
|
|
21
|
+
|
|
22
|
+
import { wrapModuleWithType } from '../wrapModuleWithType'
|
|
23
|
+
|
|
24
|
+
export interface ModuleProxyResolverOptions {
|
|
25
|
+
childAddressMap: Record<Address, ModuleName | null>
|
|
26
|
+
host: ModuleResolver
|
|
27
|
+
module: ModuleInstance
|
|
28
|
+
moduleIdentifierTransformers?: ModuleIdentifierTransformer[]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class ModuleProxyResolver<T extends ModuleProxyResolverOptions = ModuleProxyResolverOptions> implements ModuleResolverInstance {
|
|
32
|
+
private downResolver: CompositeModuleResolver
|
|
33
|
+
|
|
34
|
+
constructor(private options: T) {
|
|
35
|
+
this.downResolver = new CompositeModuleResolver({ moduleIdentifierTransformers: options.moduleIdentifierTransformers, root: this.root })
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get priority() {
|
|
39
|
+
return ObjectResolverPriority.VeryLow
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get root() {
|
|
43
|
+
return this.options.module
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
protected get childAddressMap() {
|
|
47
|
+
return this.options.childAddressMap
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
protected get host() {
|
|
51
|
+
return this.options.host
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
protected get module() {
|
|
55
|
+
return this.options.module
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
addResolver(_resolver: ModuleResolver): this {
|
|
59
|
+
throw new Error('Not supported')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
removeResolver(_resolver: ModuleResolver): this {
|
|
63
|
+
throw new Error('Not supported')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** @deprecated do not pass undefined. If trying to get all, pass '*' */
|
|
67
|
+
async resolve(): Promise<ModuleInstance[]>
|
|
68
|
+
async resolve<T extends ModuleInstance = ModuleInstance>(all: '*', options?: ModuleFilterOptions<T>): Promise<T[]>
|
|
69
|
+
async resolve<T extends ModuleInstance = ModuleInstance>(filter: ModuleFilter<T>, options?: ModuleFilterOptions<T>): Promise<T[]>
|
|
70
|
+
async resolve<T extends ModuleInstance = ModuleInstance>(id: ModuleIdentifier, options?: ModuleFilterOptions<T>): Promise<T | undefined>
|
|
71
|
+
/** @deprecated use '*' if trying to resolve all */
|
|
72
|
+
async resolve<T extends ModuleInstance = ModuleInstance>(filter?: ModuleFilter<T>, options?: ModuleFilterOptions<T>): Promise<T[]>
|
|
73
|
+
async resolve<T extends ModuleInstance = ModuleInstance>(
|
|
74
|
+
idOrFilter: ModuleFilter<T> | ModuleIdentifier = '*',
|
|
75
|
+
options?: ModuleFilterOptions<T>,
|
|
76
|
+
): Promise<T | T[] | undefined> {
|
|
77
|
+
//console.log(`childAddressMap: ${toJsonString(this.childAddressMap, 10)}`)
|
|
78
|
+
const direction = options?.direction ?? 'all'
|
|
79
|
+
if (idOrFilter === '*') {
|
|
80
|
+
//get all the child addresses. if they have been resolved before, they should be in downResolver
|
|
81
|
+
const childAddresses = Object.keys(this.childAddressMap)
|
|
82
|
+
const resolvedChildren = await Promise.all(childAddresses.map<Promise<T | undefined>>((address) => this.resolve<T>(address, options)))
|
|
83
|
+
return resolvedChildren.filter(exists)
|
|
84
|
+
} else if (typeof idOrFilter === 'string') {
|
|
85
|
+
const idParts = idOrFilter.split(':')
|
|
86
|
+
const firstPart: ModuleIdentifier = assertEx(idParts.shift(), () => 'Invalid module identifier at first position')
|
|
87
|
+
const firstPartAddress = await this.resolveIdentifier(firstPart)
|
|
88
|
+
if (firstPartAddress) {
|
|
89
|
+
const remainingParts = idParts.length > 0 ? idParts.join(':') : undefined
|
|
90
|
+
if (direction === 'down' || direction === 'all') {
|
|
91
|
+
const downResolverModule = await this.downResolver.resolve<T>(firstPartAddress)
|
|
92
|
+
if (downResolverModule) {
|
|
93
|
+
return remainingParts ? downResolverModule.resolve(remainingParts, options) : downResolverModule
|
|
94
|
+
}
|
|
95
|
+
//if it is a known child, create a proxy
|
|
96
|
+
const addressToProxy =
|
|
97
|
+
Object.keys(this.childAddressMap).includes(firstPartAddress as Address) ?
|
|
98
|
+
(firstPartAddress as Address)
|
|
99
|
+
: (Object.entries(this.childAddressMap).find(([_, value]) => value === firstPartAddress)?.[0] as Address | undefined)
|
|
100
|
+
if (addressToProxy) {
|
|
101
|
+
const proxy = await this.host.resolve(addressToProxy, { ...options, direction: 'down' })
|
|
102
|
+
if (proxy) {
|
|
103
|
+
const wrapped = wrapModuleWithType(proxy, Account.randomSync()) as unknown as T
|
|
104
|
+
return remainingParts ? wrapped?.resolve(remainingParts, options) : wrapped
|
|
105
|
+
}
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return
|
|
111
|
+
} else {
|
|
112
|
+
const filter = idOrFilter
|
|
113
|
+
if (isAddressModuleFilter(filter)) {
|
|
114
|
+
const results = (await Promise.all(filter.address.map((item) => this.resolve(item, options)))).filter(exists)
|
|
115
|
+
return results
|
|
116
|
+
} else if (isNameModuleFilter(filter)) {
|
|
117
|
+
return (await Promise.all(filter.name.map((item) => this.resolve(item, options)))).filter(exists)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
resolveIdentifier(id: ModuleIdentifier, _options?: ObjectFilterOptions): Promisable<Address | undefined> {
|
|
123
|
+
//check if any of the modules have the id as an address
|
|
124
|
+
if (this.childAddressMap[id as Address]) {
|
|
125
|
+
return id as Address
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
//check if id is a name of one of modules in the resolver
|
|
129
|
+
const addressFromName = Object.entries(this.childAddressMap).find(([, name]) => name === id)?.[0] as Address | undefined
|
|
130
|
+
if (addressFromName) {
|
|
131
|
+
return addressFromName
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async resolvePrivate<T extends ModuleInstance = ModuleInstance>(all: '*', options?: ObjectFilterOptions<T>): Promise<T[]>
|
|
136
|
+
async resolvePrivate<T extends ModuleInstance = ModuleInstance>(id: ModuleIdentifier, options?: ObjectFilterOptions<T>): Promise<T | undefined>
|
|
137
|
+
async resolvePrivate<T extends ModuleInstance = ModuleInstance>(
|
|
138
|
+
id: ModuleIdentifier,
|
|
139
|
+
_options?: ObjectFilterOptions<T>,
|
|
140
|
+
): Promise<T | T[] | undefined> {
|
|
141
|
+
if (id === '*') return await Promise.resolve([])
|
|
142
|
+
}
|
|
143
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AccountInstance } from '@xyo-network/account-model'
|
|
2
|
+
import { isArchivistModule } from '@xyo-network/archivist-model'
|
|
3
|
+
import { ArchivistWrapper } from '@xyo-network/archivist-wrapper'
|
|
4
|
+
import { isDivinerModule } from '@xyo-network/diviner-model'
|
|
5
|
+
import { DivinerWrapper } from '@xyo-network/diviner-wrapper'
|
|
6
|
+
import { Module } from '@xyo-network/module-model'
|
|
7
|
+
import { ModuleWrapper } from '@xyo-network/module-wrapper'
|
|
8
|
+
import { isNodeModule } from '@xyo-network/node-model'
|
|
9
|
+
import { NodeWrapper } from '@xyo-network/node-wrapper'
|
|
10
|
+
import { isSentinelModule } from '@xyo-network/sentinel-model'
|
|
11
|
+
import { SentinelWrapper } from '@xyo-network/sentinel-wrapper'
|
|
12
|
+
import { isWitnessModule } from '@xyo-network/witness-model'
|
|
13
|
+
import { WitnessWrapper } from '@xyo-network/witness-wrapper'
|
|
14
|
+
|
|
15
|
+
export const wrapModuleWithType = (module: Module, account: AccountInstance): ModuleWrapper => {
|
|
16
|
+
if (isArchivistModule(module)) {
|
|
17
|
+
return ArchivistWrapper.wrap(module, account)
|
|
18
|
+
}
|
|
19
|
+
if (isDivinerModule(module)) {
|
|
20
|
+
return DivinerWrapper.wrap(module, account)
|
|
21
|
+
}
|
|
22
|
+
if (isNodeModule(module)) {
|
|
23
|
+
return NodeWrapper.wrap(module, account)
|
|
24
|
+
}
|
|
25
|
+
if (isSentinelModule(module)) {
|
|
26
|
+
return SentinelWrapper.wrap(module, account)
|
|
27
|
+
}
|
|
28
|
+
if (isWitnessModule(module)) {
|
|
29
|
+
return WitnessWrapper.wrap(module, account)
|
|
30
|
+
}
|
|
31
|
+
throw 'Failed to wrap'
|
|
32
|
+
}
|