@xyo-network/bridge-http 3.10.2 → 3.10.4
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/{index-browser.mjs → index-client.mjs} +1 -1
- package/dist/neutral/{index-browser.mjs → index-client.mjs} +1 -1
- package/dist/node/index-client.mjs +362 -0
- package/dist/node/index-client.mjs.map +1 -0
- package/dist/types/{index-browser.d.ts → index-client.d.ts} +1 -1
- package/dist/types/index-client.d.ts.map +1 -0
- package/package.json +46 -35
- package/src/spec/HttpBridge.baddns.spec.ts +43 -0
- package/src/spec/HttpBridge.copilot.spec.ts +62 -0
- package/src/spec/HttpBridge.host.spec.ts +155 -0
- package/src/spec/HttpBridge.legacy.spec.ts +56 -0
- package/src/spec/HttpBridge.spec.ts +203 -0
- package/src/spec/HttpBridge.tests.spec.ts +86 -0
- package/src/spec/HttpBridge.xns.spec.ts +55 -0
- package/dist/types/index-browser.d.ts.map +0 -1
- package/eslint.config.mjs +0 -1
- package/typedoc.json +0 -5
- package/xy.config.ts +0 -10
- /package/dist/browser/{index-browser.mjs.map → index-client.mjs.map} +0 -0
- /package/dist/neutral/{index-browser.mjs.map → index-client.mjs.map} +0 -0
- /package/src/{index-browser.ts → index-client.ts} +0 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __reflectGet = Reflect.get;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
7
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
8
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
9
|
+
if (decorator = decorators[i])
|
|
10
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
11
|
+
if (kind && result) __defProp(target, key, result);
|
|
12
|
+
return result;
|
|
13
|
+
};
|
|
14
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
15
|
+
var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
|
|
16
|
+
|
|
17
|
+
// src/HttpBridgeClientOnly.ts
|
|
18
|
+
import { creatableModule as creatableModule2 } from "@xyo-network/module-model";
|
|
19
|
+
|
|
20
|
+
// src/HttpBridgeBase.ts
|
|
21
|
+
import { assertEx as assertEx3 } from "@xylabs/assert";
|
|
22
|
+
import { AxiosJson } from "@xylabs/axios";
|
|
23
|
+
import { exists as exists2 } from "@xylabs/exists";
|
|
24
|
+
import { forget as forget2 } from "@xylabs/forget";
|
|
25
|
+
import { toJsonString } from "@xylabs/object";
|
|
26
|
+
import { AbstractBridge } from "@xyo-network/bridge-abstract";
|
|
27
|
+
import {
|
|
28
|
+
NodeManifestPayloadSchema
|
|
29
|
+
} from "@xyo-network/manifest-model";
|
|
30
|
+
import {
|
|
31
|
+
creatableModule,
|
|
32
|
+
ModuleStateQuerySchema
|
|
33
|
+
} from "@xyo-network/module-model";
|
|
34
|
+
import { asAttachableNodeInstance } from "@xyo-network/node-model";
|
|
35
|
+
import {
|
|
36
|
+
isPayloadOfSchemaType
|
|
37
|
+
} from "@xyo-network/payload-model";
|
|
38
|
+
import { Mutex as Mutex2, Semaphore } from "async-mutex";
|
|
39
|
+
import { LRUCache as LRUCache2 } from "lru-cache";
|
|
40
|
+
|
|
41
|
+
// src/HttpBridgeConfig.ts
|
|
42
|
+
var HttpBridgeConfigSchema = "network.xyo.bridge.http.config";
|
|
43
|
+
|
|
44
|
+
// src/HttpBridgeModuleResolver.ts
|
|
45
|
+
import { assertEx as assertEx2 } from "@xylabs/assert";
|
|
46
|
+
import { isAddress as isAddress2 } from "@xylabs/hex";
|
|
47
|
+
import { Account } from "@xyo-network/account";
|
|
48
|
+
import { AbstractBridgeModuleResolver, wrapModuleWithType } from "@xyo-network/bridge-abstract";
|
|
49
|
+
import { ConfigSchema } from "@xyo-network/config-payload-plugin";
|
|
50
|
+
import {
|
|
51
|
+
asModuleInstance,
|
|
52
|
+
isModuleInstance,
|
|
53
|
+
ModuleConfigSchema,
|
|
54
|
+
ResolveHelper as ResolveHelper2
|
|
55
|
+
} from "@xyo-network/module-model";
|
|
56
|
+
import { Mutex } from "async-mutex";
|
|
57
|
+
import { LRUCache } from "lru-cache";
|
|
58
|
+
|
|
59
|
+
// src/ModuleProxy/ModuleProxy.ts
|
|
60
|
+
import { assertEx } from "@xylabs/assert";
|
|
61
|
+
import { exists } from "@xylabs/exists";
|
|
62
|
+
import { forget } from "@xylabs/forget";
|
|
63
|
+
import { isAddress } from "@xylabs/hex";
|
|
64
|
+
import { AbstractModuleProxy } from "@xyo-network/bridge-abstract";
|
|
65
|
+
import { ResolveHelper } from "@xyo-network/module-model";
|
|
66
|
+
var HttpModuleProxy = class _HttpModuleProxy extends AbstractModuleProxy {
|
|
67
|
+
static createCount = 0;
|
|
68
|
+
constructor(params) {
|
|
69
|
+
_HttpModuleProxy.createCount = _HttpModuleProxy.createCount + 1;
|
|
70
|
+
super(params);
|
|
71
|
+
if (Math.floor(_HttpModuleProxy.createCount / 10) === _HttpModuleProxy.createCount / 10) {
|
|
72
|
+
console.log(`HttpModuleProxy.createCount: ${_HttpModuleProxy.createCount}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async proxyQueryHandler(query, payloads = []) {
|
|
76
|
+
if (this.archiving && this.isAllowedArchivingQuery(query.schema)) {
|
|
77
|
+
forget(this.storeToArchivists([query, ...payloads ?? []]));
|
|
78
|
+
}
|
|
79
|
+
const result = await this.params.querySender.sendBridgeQuery(this.params.moduleAddress, query, payloads);
|
|
80
|
+
if (this.archiving && this.isAllowedArchivingQuery(query.schema)) {
|
|
81
|
+
forget(this.storeToArchivists(result.flat()));
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
async publicChildren() {
|
|
86
|
+
return (await Promise.all(
|
|
87
|
+
Object.values(await this.childAddressMap()).filter(exists).map((address) => this.resolve(address))
|
|
88
|
+
)).filter(exists);
|
|
89
|
+
}
|
|
90
|
+
async resolve(id = "*", options = {}) {
|
|
91
|
+
const config = {
|
|
92
|
+
address: this.address,
|
|
93
|
+
dead: this.dead,
|
|
94
|
+
downResolver: this.downResolver,
|
|
95
|
+
logger: this.logger,
|
|
96
|
+
mod: this,
|
|
97
|
+
transformers: this.moduleIdentifierTransformers,
|
|
98
|
+
upResolver: this.upResolver
|
|
99
|
+
};
|
|
100
|
+
if (id === "*") {
|
|
101
|
+
return [...await this.publicChildren(), await this.params.host.resolve(this.address)];
|
|
102
|
+
}
|
|
103
|
+
switch (typeof id) {
|
|
104
|
+
case "string": {
|
|
105
|
+
const parts = id.split(":");
|
|
106
|
+
const first = assertEx(parts.shift(), () => "Missing first");
|
|
107
|
+
const remainingPath = parts.join(":");
|
|
108
|
+
const address = isAddress(first) ? first : this.id === first ? this.address : this.childAddressByName(first);
|
|
109
|
+
if (!address) return void 0;
|
|
110
|
+
const firstInstance = await this.params.host.resolve(address);
|
|
111
|
+
return remainingPath ? await firstInstance?.resolve(remainingPath) : firstInstance;
|
|
112
|
+
}
|
|
113
|
+
default: {
|
|
114
|
+
return (await ResolveHelper.resolve(config, id, options)).filter((mod) => mod.address !== this.address);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// src/HttpBridgeModuleResolver.ts
|
|
121
|
+
var NotFoundModule = { notFound: true };
|
|
122
|
+
var HttpBridgeModuleResolver = class extends AbstractBridgeModuleResolver {
|
|
123
|
+
_resolvedCache = new LRUCache({ max: 1e3 });
|
|
124
|
+
_resolvedCacheMutex = new Mutex();
|
|
125
|
+
get querySender() {
|
|
126
|
+
return this.params.querySender;
|
|
127
|
+
}
|
|
128
|
+
moduleUrl(address) {
|
|
129
|
+
return new URL(address, this.params.rootUrl);
|
|
130
|
+
}
|
|
131
|
+
async resolveHandler(id, options, params) {
|
|
132
|
+
const parentResult = await super.resolveHandler(id, options);
|
|
133
|
+
if (parentResult.length > 0) {
|
|
134
|
+
return parentResult;
|
|
135
|
+
}
|
|
136
|
+
const idParts = id.split(":");
|
|
137
|
+
const untransformedFirstPart = assertEx2(idParts.shift(), () => "Missing module identifier");
|
|
138
|
+
const firstPart = await ResolveHelper2.transformModuleIdentifier(untransformedFirstPart);
|
|
139
|
+
assertEx2(isAddress2(firstPart), () => `Invalid module address: ${firstPart}`);
|
|
140
|
+
const remainderParts = idParts.join(":");
|
|
141
|
+
const instance = await this._resolvedCacheMutex.runExclusive(async () => {
|
|
142
|
+
const cachedMod = this._resolvedCache.get(firstPart);
|
|
143
|
+
if (cachedMod) {
|
|
144
|
+
if (isModuleInstance(cachedMod)) {
|
|
145
|
+
const result2 = idParts.length <= 0 ? cachedMod : cachedMod.resolve(remainderParts, { ...options, maxDepth: (options?.maxDepth ?? 5) - 1 });
|
|
146
|
+
return result2;
|
|
147
|
+
} else {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const account = await Account.random();
|
|
152
|
+
const finalParams = {
|
|
153
|
+
account,
|
|
154
|
+
archiving: this.params.archiving,
|
|
155
|
+
config: { schema: ModuleConfigSchema },
|
|
156
|
+
host: this,
|
|
157
|
+
moduleAddress: firstPart,
|
|
158
|
+
onQuerySendFinished: this.params.onQuerySendFinished,
|
|
159
|
+
onQuerySendStarted: this.params.onQuerySendStarted,
|
|
160
|
+
querySender: this.params.querySender,
|
|
161
|
+
...params
|
|
162
|
+
};
|
|
163
|
+
this.logger?.debug(`creating HttpProxy [${firstPart}] ${id}`);
|
|
164
|
+
const proxy = new HttpModuleProxy(finalParams);
|
|
165
|
+
let state;
|
|
166
|
+
try {
|
|
167
|
+
state = await proxy.state();
|
|
168
|
+
} catch (ex) {
|
|
169
|
+
const error = ex;
|
|
170
|
+
this.logger?.log(error.message);
|
|
171
|
+
}
|
|
172
|
+
if (!state) {
|
|
173
|
+
this._resolvedCache.set(firstPart, NotFoundModule);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const configSchema = state.find((payload) => payload.schema === ConfigSchema)?.config;
|
|
177
|
+
const config = assertEx2(
|
|
178
|
+
state.find((payload) => payload.schema === configSchema),
|
|
179
|
+
() => "Unable to locate config"
|
|
180
|
+
);
|
|
181
|
+
proxy.setConfig(config);
|
|
182
|
+
this.logger?.log(`created HttpProxy [${firstPart}] ${proxy.id}`);
|
|
183
|
+
await proxy.start?.();
|
|
184
|
+
const wrapped = wrapModuleWithType(proxy, account);
|
|
185
|
+
assertEx2(asModuleInstance(wrapped, {}), () => `Failed to asModuleInstance [${id}]`);
|
|
186
|
+
this._resolvedCache.set(wrapped.address, wrapped);
|
|
187
|
+
return wrapped;
|
|
188
|
+
});
|
|
189
|
+
const result = remainderParts.length > 0 ? await instance?.resolve(remainderParts, options) : instance;
|
|
190
|
+
return result ? [result] : [];
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// src/HttpBridgeBase.ts
|
|
195
|
+
var HttpBridgeBase = class extends AbstractBridge {
|
|
196
|
+
_axios;
|
|
197
|
+
_discoverRootsMutex = new Mutex2();
|
|
198
|
+
_failureTimeCache = new LRUCache2({ max: HttpBridgeBase.maxFailureCacheSize });
|
|
199
|
+
_querySemaphore;
|
|
200
|
+
_resolver;
|
|
201
|
+
get axios() {
|
|
202
|
+
this._axios = this._axios ?? this.params.axios ?? HttpBridgeBase.axios;
|
|
203
|
+
return this._axios;
|
|
204
|
+
}
|
|
205
|
+
get clientUrl() {
|
|
206
|
+
return assertEx3(this.config.client?.url ?? this.config.nodeUrl, () => "No Url Set");
|
|
207
|
+
}
|
|
208
|
+
get failureRetryTime() {
|
|
209
|
+
return this.config.failureRetryTime ?? HttpBridgeBase.defaultFailureRetryTime;
|
|
210
|
+
}
|
|
211
|
+
get maxConnections() {
|
|
212
|
+
return this.config.maxConnections ?? HttpBridgeBase.defaultMaxConnections;
|
|
213
|
+
}
|
|
214
|
+
get maxPayloadSizeWarning() {
|
|
215
|
+
return this.config.maxPayloadSizeWarning ?? HttpBridgeBase.defaultMaxPayloadSizeWarning;
|
|
216
|
+
}
|
|
217
|
+
get querySemaphore() {
|
|
218
|
+
this._querySemaphore = this._querySemaphore ?? new Semaphore(this.maxConnections);
|
|
219
|
+
return this._querySemaphore;
|
|
220
|
+
}
|
|
221
|
+
get resolver() {
|
|
222
|
+
this._resolver = this._resolver ?? new HttpBridgeModuleResolver({
|
|
223
|
+
additionalSigners: this.additionalSigners,
|
|
224
|
+
archiving: { ...this.archiving, resolveArchivists: this.resolveArchivingArchivists.bind(this) },
|
|
225
|
+
bridge: this,
|
|
226
|
+
onQuerySendFinished: (args) => {
|
|
227
|
+
forget2(this.emit("querySendFinished", { mod: this, ...args }));
|
|
228
|
+
},
|
|
229
|
+
onQuerySendStarted: (args) => {
|
|
230
|
+
forget2(this.emit("querySendStarted", { mod: this, ...args }));
|
|
231
|
+
},
|
|
232
|
+
querySender: this,
|
|
233
|
+
root: this,
|
|
234
|
+
rootUrl: this.clientUrl,
|
|
235
|
+
wrapperAccount: this.account
|
|
236
|
+
});
|
|
237
|
+
return this._resolver;
|
|
238
|
+
}
|
|
239
|
+
exposeHandler(_id, _options) {
|
|
240
|
+
throw new Error("Unsupported");
|
|
241
|
+
}
|
|
242
|
+
exposedHandler() {
|
|
243
|
+
throw new Error("Unsupported");
|
|
244
|
+
}
|
|
245
|
+
async getRoots(force) {
|
|
246
|
+
return await this._discoverRootsMutex.runExclusive(async () => {
|
|
247
|
+
if (this._roots === void 0 || force) {
|
|
248
|
+
const state = await this.getRootState();
|
|
249
|
+
this.logger?.debug(`HttpBridge:discoverRoots.state [${state?.length}]`);
|
|
250
|
+
const nodeManifest = state?.find(isPayloadOfSchemaType(NodeManifestPayloadSchema));
|
|
251
|
+
if (nodeManifest) {
|
|
252
|
+
const mods = (await this.resolveRootNode(nodeManifest)).filter(exists2);
|
|
253
|
+
this.logger?.debug(`HttpBridge:discoverRoots [${mods.length}]`);
|
|
254
|
+
this._roots = mods;
|
|
255
|
+
} else {
|
|
256
|
+
this._roots = [];
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return this._roots;
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
moduleUrl(address) {
|
|
263
|
+
return new URL(address, this.clientUrl);
|
|
264
|
+
}
|
|
265
|
+
async sendBridgeQuery(targetAddress, query, payloads) {
|
|
266
|
+
const lastFailureTime = this._failureTimeCache.get(targetAddress);
|
|
267
|
+
if (lastFailureTime !== void 0) {
|
|
268
|
+
const now = Date.now();
|
|
269
|
+
const timeSincePreviousFailure = now - lastFailureTime;
|
|
270
|
+
if (timeSincePreviousFailure > this.failureRetryTime) {
|
|
271
|
+
throw new Error(`target module failed recently [${targetAddress}] [${timeSincePreviousFailure}ms ago]`);
|
|
272
|
+
}
|
|
273
|
+
this._failureTimeCache.delete(targetAddress);
|
|
274
|
+
}
|
|
275
|
+
try {
|
|
276
|
+
await this.querySemaphore.acquire();
|
|
277
|
+
const payloadSize = JSON.stringify([query, payloads]).length;
|
|
278
|
+
if (payloadSize > this.maxPayloadSizeWarning) {
|
|
279
|
+
this.logger?.warn(
|
|
280
|
+
`Large targetQuery being sent: ${payloadSize} bytes [${this.address}][${this.moduleAddress}] [${query.schema}] [${payloads?.length}]`
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
const moduleUrl = this.moduleUrl(targetAddress).href;
|
|
284
|
+
const result = await this.axios.post(moduleUrl, [query, payloads]);
|
|
285
|
+
if (result.status === 404) {
|
|
286
|
+
throw `target module not found [${moduleUrl}] [${result.status}]`;
|
|
287
|
+
}
|
|
288
|
+
if (result.status >= 400) {
|
|
289
|
+
this.logger?.error(`targetQuery failed [${moduleUrl}]`);
|
|
290
|
+
throw `targetQuery failed [${moduleUrl}] [${result.status}]`;
|
|
291
|
+
}
|
|
292
|
+
return result.data?.data;
|
|
293
|
+
} catch (ex) {
|
|
294
|
+
const error = ex;
|
|
295
|
+
this.logger?.error(`Error: ${toJsonString(error)}`);
|
|
296
|
+
throw error;
|
|
297
|
+
} finally {
|
|
298
|
+
this.querySemaphore.release();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
unexposeHandler(_id, _options) {
|
|
302
|
+
throw new Error("Unsupported");
|
|
303
|
+
}
|
|
304
|
+
async getRootState() {
|
|
305
|
+
const queryPayload = { schema: ModuleStateQuerySchema };
|
|
306
|
+
const boundQuery = await this.bindQuery(queryPayload);
|
|
307
|
+
try {
|
|
308
|
+
const response = await this.axios.post(this.clientUrl.toString(), boundQuery);
|
|
309
|
+
if (response.status === 404) {
|
|
310
|
+
return [];
|
|
311
|
+
}
|
|
312
|
+
const [, payloads, errors] = response.data.data;
|
|
313
|
+
if (errors.length > 0) {
|
|
314
|
+
throw new Error(`getRootState failed: ${JSON.stringify(errors, null, 2)}`);
|
|
315
|
+
}
|
|
316
|
+
return payloads;
|
|
317
|
+
} catch (ex) {
|
|
318
|
+
const error = ex;
|
|
319
|
+
this.logger?.warn(`Unable to connect to remote node: ${error.message} [${this.clientUrl}]`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
async resolveRootNode(nodeManifest) {
|
|
323
|
+
const rootModule = assertEx3(
|
|
324
|
+
(await this.resolver.resolveHandler(
|
|
325
|
+
assertEx3(nodeManifest.status?.address, () => "Root has no address"),
|
|
326
|
+
void 0,
|
|
327
|
+
{ manifest: nodeManifest }
|
|
328
|
+
)).at(0),
|
|
329
|
+
() => `Root not found [${nodeManifest.status?.address}]`
|
|
330
|
+
);
|
|
331
|
+
assertEx3(rootModule.constructor.name !== "HttpModuleProxy", () => "rootModule is not a Wrapper");
|
|
332
|
+
const rootNode = asAttachableNodeInstance(rootModule, "Root modules is not a node");
|
|
333
|
+
if (rootNode) {
|
|
334
|
+
this.logger.debug(`rootNode: ${rootNode.id}`);
|
|
335
|
+
this.downResolver.addResolver(rootNode);
|
|
336
|
+
return [rootNode];
|
|
337
|
+
}
|
|
338
|
+
return [];
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
__publicField(HttpBridgeBase, "axios", new AxiosJson());
|
|
342
|
+
__publicField(HttpBridgeBase, "configSchemas", [...__superGet(HttpBridgeBase, HttpBridgeBase, "configSchemas"), HttpBridgeConfigSchema]);
|
|
343
|
+
__publicField(HttpBridgeBase, "defaultConfigSchema", HttpBridgeConfigSchema);
|
|
344
|
+
__publicField(HttpBridgeBase, "defaultFailureRetryTime", 1e3 * 60);
|
|
345
|
+
__publicField(HttpBridgeBase, "defaultMaxConnections", 4);
|
|
346
|
+
__publicField(HttpBridgeBase, "defaultMaxPayloadSizeWarning", 256 * 256);
|
|
347
|
+
__publicField(HttpBridgeBase, "maxFailureCacheSize", 1e3);
|
|
348
|
+
HttpBridgeBase = __decorateClass([
|
|
349
|
+
creatableModule()
|
|
350
|
+
], HttpBridgeBase);
|
|
351
|
+
|
|
352
|
+
// src/HttpBridgeClientOnly.ts
|
|
353
|
+
var HttpBridge = class extends HttpBridgeBase {
|
|
354
|
+
};
|
|
355
|
+
HttpBridge = __decorateClass([
|
|
356
|
+
creatableModule2()
|
|
357
|
+
], HttpBridge);
|
|
358
|
+
export {
|
|
359
|
+
HttpBridge,
|
|
360
|
+
HttpBridgeConfigSchema
|
|
361
|
+
};
|
|
362
|
+
//# sourceMappingURL=index-client.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/HttpBridgeClientOnly.ts","../../src/HttpBridgeBase.ts","../../src/HttpBridgeConfig.ts","../../src/HttpBridgeModuleResolver.ts","../../src/ModuleProxy/ModuleProxy.ts"],"sourcesContent":["import { BridgeParams } from '@xyo-network/bridge-model'\nimport { AnyConfigSchema, creatableModule } from '@xyo-network/module-model'\n\nimport { HttpBridgeBase } from './HttpBridgeBase.ts'\nimport { HttpBridgeConfig } from './HttpBridgeConfig.ts'\n\nexport interface HttpBridgeParams extends BridgeParams<AnyConfigSchema<HttpBridgeConfig>> {}\n\n@creatableModule()\nexport class HttpBridge<TParams extends HttpBridgeParams> extends HttpBridgeBase<TParams> {}\n","import { assertEx } from '@xylabs/assert'\nimport { AxiosJson } from '@xylabs/axios'\nimport { exists } from '@xylabs/exists'\nimport { forget } from '@xylabs/forget'\nimport { Address } from '@xylabs/hex'\nimport { toJsonString } from '@xylabs/object'\nimport { Promisable } from '@xylabs/promise'\nimport { ApiEnvelope } from '@xyo-network/api-models'\nimport { QueryBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractBridge } from '@xyo-network/bridge-abstract'\nimport {\n BridgeExposeOptions,\n BridgeModule,\n BridgeParams,\n BridgeUnexposeOptions,\n QuerySendFinishedEventArgs,\n QuerySendStartedEventArgs,\n} from '@xyo-network/bridge-model'\nimport {\n ModuleManifestPayload, NodeManifestPayload, NodeManifestPayloadSchema,\n} from '@xyo-network/manifest-model'\nimport {\n AnyConfigSchema,\n creatableModule,\n ModuleInstance,\n ModuleQueryResult,\n ModuleResolverInstance,\n ModuleStateQuery,\n ModuleStateQuerySchema,\n} from '@xyo-network/module-model'\nimport { asAttachableNodeInstance } from '@xyo-network/node-model'\nimport {\n isPayloadOfSchemaType, Payload, Schema,\n} from '@xyo-network/payload-model'\nimport { Mutex, Semaphore } from 'async-mutex'\nimport { AxiosError } from 'axios'\nimport { LRUCache } from 'lru-cache'\n\nimport { HttpBridgeConfig, HttpBridgeConfigSchema } from './HttpBridgeConfig.ts'\nimport { HttpBridgeModuleResolver } from './HttpBridgeModuleResolver.ts'\nimport { BridgeQuerySender } from './ModuleProxy/index.ts'\n\nexport interface HttpBridgeParams extends BridgeParams<AnyConfigSchema<HttpBridgeConfig>> {\n axios?: AxiosJson\n}\n\n@creatableModule()\nexport class HttpBridgeBase<TParams extends HttpBridgeParams> extends AbstractBridge<TParams> implements BridgeModule<TParams>, BridgeQuerySender {\n static readonly axios = new AxiosJson()\n static override readonly configSchemas: Schema[] = [...super.configSchemas, HttpBridgeConfigSchema]\n static override readonly defaultConfigSchema: Schema = HttpBridgeConfigSchema\n static readonly defaultFailureRetryTime = 1000 * 60\n static readonly defaultMaxConnections = 4\n static readonly defaultMaxPayloadSizeWarning = 256 * 256\n static readonly maxFailureCacheSize = 1000\n\n private _axios?: AxiosJson\n private _discoverRootsMutex = new Mutex()\n private _failureTimeCache = new LRUCache<Address, number>({ max: HttpBridgeBase.maxFailureCacheSize })\n private _querySemaphore?: Semaphore\n private _resolver?: HttpBridgeModuleResolver\n\n get axios() {\n this._axios = this._axios ?? this.params.axios ?? HttpBridgeBase.axios\n return this._axios\n }\n\n get clientUrl() {\n // eslint-disable-next-line sonarjs/deprecation\n return assertEx(this.config.client?.url ?? this.config.nodeUrl, () => 'No Url Set')\n }\n\n get failureRetryTime() {\n return this.config.failureRetryTime ?? HttpBridgeBase.defaultFailureRetryTime\n }\n\n get maxConnections() {\n return this.config.maxConnections ?? HttpBridgeBase.defaultMaxConnections\n }\n\n get maxPayloadSizeWarning() {\n return this.config.maxPayloadSizeWarning ?? HttpBridgeBase.defaultMaxPayloadSizeWarning\n }\n\n get querySemaphore() {\n this._querySemaphore = this._querySemaphore ?? new Semaphore(this.maxConnections)\n return this._querySemaphore\n }\n\n override get resolver() {\n this._resolver\n = this._resolver\n ?? new HttpBridgeModuleResolver({\n additionalSigners: this.additionalSigners,\n archiving: { ...this.archiving, resolveArchivists: this.resolveArchivingArchivists.bind(this) },\n bridge: this,\n onQuerySendFinished: (args: Omit<QuerySendFinishedEventArgs, 'mod'>) => {\n forget(this.emit('querySendFinished', { mod: this, ...args }))\n },\n onQuerySendStarted: (args: Omit<QuerySendStartedEventArgs, 'mod'>) => {\n forget(this.emit('querySendStarted', { mod: this, ...args }))\n },\n querySender: this,\n root: this,\n rootUrl: this.clientUrl,\n wrapperAccount: this.account,\n })\n return this._resolver\n }\n\n override exposeHandler(_id: string, _options?: BridgeExposeOptions | undefined): Promisable<ModuleInstance[]> {\n throw new Error('Unsupported')\n }\n\n override exposedHandler(): Promisable<Address[]> {\n throw new Error('Unsupported')\n }\n\n async getRoots(force?: boolean): Promise<ModuleInstance[]> {\n return await this._discoverRootsMutex.runExclusive(async () => {\n if (this._roots === undefined || force) {\n const state = await this.getRootState()\n this.logger?.debug(`HttpBridge:discoverRoots.state [${state?.length}]`)\n const nodeManifest = state?.find(isPayloadOfSchemaType<NodeManifestPayload>(NodeManifestPayloadSchema))\n if (nodeManifest) {\n const mods = (await this.resolveRootNode(nodeManifest)).filter(exists)\n this.logger?.debug(`HttpBridge:discoverRoots [${mods.length}]`)\n this._roots = mods\n } else {\n this._roots = []\n }\n }\n return this._roots\n })\n }\n\n moduleUrl(address: Address) {\n return new URL(address, this.clientUrl)\n }\n\n async sendBridgeQuery<TOut extends Payload = Payload, TQuery extends QueryBoundWitness = QueryBoundWitness, TIn extends Payload = Payload>(\n targetAddress: Address,\n query: TQuery,\n payloads?: TIn[],\n ): Promise<ModuleQueryResult<TOut>> {\n const lastFailureTime = this._failureTimeCache.get(targetAddress)\n if (lastFailureTime !== undefined) {\n const now = Date.now()\n const timeSincePreviousFailure = now - lastFailureTime\n if (timeSincePreviousFailure > this.failureRetryTime) {\n throw new Error(`target module failed recently [${targetAddress}] [${timeSincePreviousFailure}ms ago]`)\n }\n this._failureTimeCache.delete(targetAddress)\n }\n try {\n await this.querySemaphore.acquire()\n const payloadSize = JSON.stringify([query, payloads]).length\n if (payloadSize > this.maxPayloadSizeWarning) {\n this.logger?.warn(\n `Large targetQuery being sent: ${payloadSize} bytes [${this.address}][${this.moduleAddress}] [${query.schema}] [${payloads?.length}]`,\n )\n }\n const moduleUrl = this.moduleUrl(targetAddress).href\n const result = await this.axios.post<ApiEnvelope<ModuleQueryResult<TOut>>>(moduleUrl, [query, payloads])\n if (result.status === 404) {\n throw `target module not found [${moduleUrl}] [${result.status}]`\n }\n if (result.status >= 400) {\n this.logger?.error(`targetQuery failed [${moduleUrl}]`)\n throw `targetQuery failed [${moduleUrl}] [${result.status}]`\n }\n return result.data?.data\n } catch (ex) {\n const error = ex as AxiosError\n this.logger?.error(`Error: ${toJsonString(error)}`)\n throw error\n } finally {\n this.querySemaphore.release()\n }\n }\n\n override unexposeHandler(_id: string, _options?: BridgeUnexposeOptions | undefined): Promisable<ModuleInstance[]> {\n throw new Error('Unsupported')\n }\n\n private async getRootState() {\n const queryPayload: ModuleStateQuery = { schema: ModuleStateQuerySchema }\n const boundQuery = await this.bindQuery(queryPayload)\n try {\n const response = await this.axios.post<ApiEnvelope<ModuleQueryResult>>(this.clientUrl.toString(), boundQuery)\n if (response.status === 404) {\n return []\n }\n const [, payloads, errors] = response.data.data\n if (errors.length > 0) {\n throw new Error(`getRootState failed: ${JSON.stringify(errors, null, 2)}`)\n }\n return payloads\n } catch (ex) {\n const error = ex as Error\n this.logger?.warn(`Unable to connect to remote node: ${error.message} [${this.clientUrl}]`)\n }\n }\n\n private async resolveRootNode(nodeManifest: ModuleManifestPayload): Promise<ModuleInstance[]> {\n const rootModule = assertEx(\n (\n await this.resolver.resolveHandler(\n assertEx(nodeManifest.status?.address, () => 'Root has no address'),\n undefined,\n { manifest: nodeManifest },\n )\n ).at(0),\n () => `Root not found [${nodeManifest.status?.address}]`,\n )\n assertEx(rootModule.constructor.name !== 'HttpModuleProxy', () => 'rootModule is not a Wrapper')\n const rootNode = asAttachableNodeInstance(rootModule, 'Root modules is not a node')\n if (rootNode) {\n this.logger.debug(`rootNode: ${rootNode.id}`)\n this.downResolver.addResolver(rootNode as unknown as ModuleResolverInstance)\n return [rootNode]\n }\n return []\n }\n}\n","import type { EmptyObject } from '@xylabs/object'\nimport type { BridgeConfig } from '@xyo-network/bridge-model'\n\nexport const HttpBridgeConfigSchema = 'network.xyo.bridge.http.config' as const\nexport type HttpBridgeConfigSchema = typeof HttpBridgeConfigSchema\n\nexport type HttpBridgeConfig<TConfig extends EmptyObject = EmptyObject, TSchema extends string | void = void> = BridgeConfig<\n {\n client?: BridgeConfig['client'] & {\n url: string\n }\n failureRetryTime?: number\n failureTimeCacheMax?: number\n host?: {\n port: number\n }\n maxConnections?: number\n maxPayloadSizeWarning?: number\n /** @deprecated use client.url instead */\n nodeUrl?: string\n schema: HttpBridgeConfigSchema\n } & TConfig,\n TSchema extends string ? TSchema : HttpBridgeConfigSchema\n>\n","import { assertEx } from '@xylabs/assert'\nimport type { Address } from '@xylabs/hex'\nimport { isAddress } from '@xylabs/hex'\nimport { Account } from '@xyo-network/account'\nimport type { BridgeModuleResolverParams } from '@xyo-network/bridge-abstract'\nimport { AbstractBridgeModuleResolver, wrapModuleWithType } from '@xyo-network/bridge-abstract'\nimport type { ConfigPayload } from '@xyo-network/config-payload-plugin'\nimport { ConfigSchema } from '@xyo-network/config-payload-plugin'\nimport type {\n ModuleConfig,\n ModuleFilterOptions,\n ModuleIdentifier,\n ModuleInstance,\n} from '@xyo-network/module-model'\nimport {\n asModuleInstance,\n isModuleInstance,\n ModuleConfigSchema,\n ResolveHelper,\n} from '@xyo-network/module-model'\nimport type { Payload } from '@xyo-network/payload-model'\nimport { Mutex } from 'async-mutex'\nimport { LRUCache } from 'lru-cache'\n\nimport type { BridgeQuerySender, HttpModuleProxyParams } from './ModuleProxy/index.ts'\nimport { HttpModuleProxy } from './ModuleProxy/index.ts'\n\nconst NotFoundModule = { notFound: true }\n\nexport interface HttpBridgeModuleResolverParams extends BridgeModuleResolverParams {\n querySender: BridgeQuerySender\n rootUrl: string\n}\n\nexport class HttpBridgeModuleResolver<\n T extends HttpBridgeModuleResolverParams = HttpBridgeModuleResolverParams,\n> extends AbstractBridgeModuleResolver<T> {\n protected _resolvedCache = new LRUCache<Address, ModuleInstance | typeof NotFoundModule>({ max: 1000 })\n protected _resolvedCacheMutex = new Mutex()\n\n get querySender() {\n return this.params.querySender\n }\n\n moduleUrl(address: Address) {\n return new URL(address, this.params.rootUrl)\n }\n\n override async resolveHandler<T extends ModuleInstance = ModuleInstance>(\n id: ModuleIdentifier,\n options?: ModuleFilterOptions<T>,\n params?: Partial<HttpModuleProxyParams>,\n ): Promise<T[]> {\n const parentResult = await super.resolveHandler(id, options)\n if (parentResult.length > 0) {\n return parentResult\n }\n const idParts = id.split(':')\n const untransformedFirstPart = assertEx(idParts.shift(), () => 'Missing module identifier')\n const firstPart = await ResolveHelper.transformModuleIdentifier(untransformedFirstPart)\n assertEx(isAddress(firstPart), () => `Invalid module address: ${firstPart}`)\n const remainderParts = idParts.join(':')\n const instance: T | undefined = await this._resolvedCacheMutex.runExclusive(async () => {\n const cachedMod = this._resolvedCache.get(firstPart as Address)\n if (cachedMod) {\n if (isModuleInstance(cachedMod)) {\n const result = idParts.length <= 0 ? cachedMod : cachedMod.resolve(remainderParts, { ...options, maxDepth: (options?.maxDepth ?? 5) - 1 })\n return result as T\n } else {\n // return cached 404\n return\n }\n }\n const account = await Account.random()\n const finalParams: HttpModuleProxyParams = {\n account,\n archiving: this.params.archiving,\n config: { schema: ModuleConfigSchema },\n host: this,\n moduleAddress: firstPart as Address,\n onQuerySendFinished: this.params.onQuerySendFinished,\n onQuerySendStarted: this.params.onQuerySendStarted,\n querySender: this.params.querySender,\n ...params,\n }\n\n this.logger?.debug(`creating HttpProxy [${firstPart}] ${id}`)\n\n const proxy = new HttpModuleProxy<T, HttpModuleProxyParams>(finalParams)\n\n let state: Payload[] | undefined\n\n try {\n state = await proxy.state()\n } catch (ex) {\n const error = ex as Error\n this.logger?.log(error.message)\n }\n\n if (!state) {\n // cache the fact that it was not found\n this._resolvedCache.set(firstPart as Address, NotFoundModule)\n return\n }\n\n const configSchema = (state.find(payload => payload.schema === ConfigSchema) as ConfigPayload | undefined)?.config\n const config = assertEx(\n state.find(payload => payload.schema === configSchema),\n () => 'Unable to locate config',\n ) as ModuleConfig\n proxy.setConfig(config)\n\n this.logger?.log(`created HttpProxy [${firstPart}] ${proxy.id}`)\n\n await proxy.start?.()\n const wrapped = wrapModuleWithType(proxy, account) as unknown as T\n assertEx(asModuleInstance<T>(wrapped, {}), () => `Failed to asModuleInstance [${id}]`)\n this._resolvedCache.set(wrapped.address, wrapped)\n return wrapped as ModuleInstance as T\n })\n const result = remainderParts.length > 0 ? await instance?.resolve(remainderParts, options) : instance\n return result ? [result] : []\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { forget } from '@xylabs/forget'\nimport type { Address } from '@xylabs/hex'\nimport { isAddress } from '@xylabs/hex'\nimport type { QueryBoundWitness } from '@xyo-network/boundwitness-model'\nimport type { ModuleProxyParams } from '@xyo-network/bridge-abstract'\nimport { AbstractModuleProxy } from '@xyo-network/bridge-abstract'\nimport type {\n AttachableModuleInstance,\n ModuleFilterOptions,\n ModuleIdentifier,\n ModuleInstance,\n ModuleQueryResult,\n ResolveHelperConfig,\n} from '@xyo-network/module-model'\nimport { ResolveHelper } from '@xyo-network/module-model'\nimport type { Payload } from '@xyo-network/payload-model'\n\nexport interface BridgeQuerySender {\n sendBridgeQuery: <TOut extends Payload = Payload, TQuery extends QueryBoundWitness = QueryBoundWitness, TIn extends Payload = Payload>(\n targetAddress: Address,\n query: TQuery,\n payloads?: TIn[],\n ) => Promise<ModuleQueryResult<TOut>>\n}\n\nexport type HttpModuleProxyParams = ModuleProxyParams & {\n querySender: BridgeQuerySender\n}\n\nexport class HttpModuleProxy<\n TWrappedModule extends ModuleInstance = ModuleInstance,\n TParams extends Omit<HttpModuleProxyParams, 'config'> & { config: TWrappedModule['config'] } = Omit<HttpModuleProxyParams, 'config'> & {\n config: TWrappedModule['config']\n },\n>\n extends AbstractModuleProxy<TWrappedModule, TParams>\n implements AttachableModuleInstance<TParams, TWrappedModule['eventData']> {\n protected static createCount = 0\n\n constructor(params: TParams) {\n HttpModuleProxy.createCount = HttpModuleProxy.createCount + 1\n super(params)\n if (Math.floor(HttpModuleProxy.createCount / 10) === HttpModuleProxy.createCount / 10) {\n console.log(`HttpModuleProxy.createCount: ${HttpModuleProxy.createCount}`)\n }\n }\n\n async proxyQueryHandler<T extends QueryBoundWitness = QueryBoundWitness>(query: T, payloads: Payload[] = []): Promise<ModuleQueryResult> {\n if (this.archiving && this.isAllowedArchivingQuery(query.schema)) {\n forget(this.storeToArchivists([query, ...(payloads ?? [])]))\n }\n const result = await this.params.querySender.sendBridgeQuery(this.params.moduleAddress, query, payloads)\n if (this.archiving && this.isAllowedArchivingQuery(query.schema)) {\n forget(this.storeToArchivists(result.flat()))\n }\n return result\n }\n\n override async publicChildren(): Promise<ModuleInstance[]> {\n return (\n await Promise.all(\n Object.values(await this.childAddressMap())\n .filter(exists)\n .map(address => this.resolve(address)),\n )\n ).filter(exists)\n }\n\n /** @deprecated do not pass undefined. If trying to get all, pass '*' */\n override async resolve(): Promise<ModuleInstance[]>\n override async resolve<T extends ModuleInstance = ModuleInstance>(all: '*', options?: ModuleFilterOptions<T>): Promise<T[]>\n override async resolve<T extends ModuleInstance = ModuleInstance>(id: ModuleIdentifier, options?: ModuleFilterOptions<T>): Promise<T | undefined>\n override async resolve<T extends ModuleInstance = ModuleInstance>(\n id: ModuleIdentifier = '*',\n options: ModuleFilterOptions<T> = {},\n ): Promise<T | T[] | undefined> {\n const config: ResolveHelperConfig = {\n address: this.address,\n dead: this.dead,\n downResolver: this.downResolver,\n logger: this.logger,\n mod: this,\n transformers: this.moduleIdentifierTransformers,\n upResolver: this.upResolver,\n }\n if (id === '*') {\n return [...(await this.publicChildren()), await this.params.host.resolve(this.address)] as T[]\n }\n switch (typeof id) {\n case 'string': {\n const parts = id.split(':')\n const first = assertEx(parts.shift(), () => 'Missing first')\n const remainingPath = parts.join(':')\n const address\n = isAddress(first)\n ? first\n : this.id === first\n ? this.address\n : this.childAddressByName(first)\n if (!address) return undefined\n const firstInstance = (await this.params.host.resolve(address)) as ModuleInstance | undefined\n return (remainingPath ? await firstInstance?.resolve(remainingPath) : firstInstance) as T | undefined\n }\n default: {\n return (await ResolveHelper.resolve(config, id, options)).filter(mod => mod.address !== this.address)\n }\n }\n }\n}\n"],"mappings":"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","names":["creatableModule","assertEx","exists","forget","Mutex","LRUCache","assertEx","isAddress","ResolveHelper","assertEx","ResolveHelper","isAddress","result","Mutex","LRUCache","assertEx","forget","exists","creatableModule"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-client.d.ts","sourceRoot":"","sources":["../../src/index-client.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xyo-network/bridge-http",
|
|
3
|
-
"version": "3.10.
|
|
3
|
+
"version": "3.10.4",
|
|
4
4
|
"description": "Primary SDK for using XYO Protocol 2.0",
|
|
5
5
|
"homepage": "https://xyo.network",
|
|
6
6
|
"bugs": {
|
|
@@ -22,38 +22,49 @@
|
|
|
22
22
|
"exports": {
|
|
23
23
|
".": {
|
|
24
24
|
"browser": {
|
|
25
|
-
"types": "./dist/types/index-
|
|
26
|
-
"default": "./dist/browser/index-
|
|
25
|
+
"types": "./dist/types/index-client.d.ts",
|
|
26
|
+
"default": "./dist/browser/index-client.mjs"
|
|
27
27
|
},
|
|
28
28
|
"node": {
|
|
29
29
|
"types": "./dist/types/index.d.ts",
|
|
30
30
|
"default": "./dist/node/index.mjs"
|
|
31
31
|
},
|
|
32
|
-
"types": "./dist/types/index-
|
|
33
|
-
"default": "./dist/neutral/index-
|
|
32
|
+
"types": "./dist/types/index-client.d.ts",
|
|
33
|
+
"default": "./dist/neutral/index-client.mjs"
|
|
34
|
+
},
|
|
35
|
+
"./client": {
|
|
36
|
+
"types": "./dist/types/index-client.d.ts",
|
|
37
|
+
"default": "./dist/neutral/index-client.mjs"
|
|
34
38
|
},
|
|
35
39
|
"./package.json": "./package.json"
|
|
36
40
|
},
|
|
37
|
-
"module": "dist/neutral/index-
|
|
38
|
-
"types": "dist/types/index-
|
|
41
|
+
"module": "dist/neutral/index-client.mjs",
|
|
42
|
+
"types": "dist/types/index-client.d.ts",
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"src",
|
|
46
|
+
"README.md",
|
|
47
|
+
"LICENSE",
|
|
48
|
+
"package.json"
|
|
49
|
+
],
|
|
39
50
|
"dependencies": {
|
|
40
|
-
"@xylabs/assert": "^4.7.
|
|
41
|
-
"@xylabs/axios": "^4.7.
|
|
42
|
-
"@xylabs/exists": "^4.7.
|
|
43
|
-
"@xylabs/forget": "^4.7.
|
|
44
|
-
"@xylabs/hex": "^4.7.
|
|
45
|
-
"@xylabs/object": "^4.7.
|
|
46
|
-
"@xylabs/promise": "^4.7.
|
|
47
|
-
"@xyo-network/account": "^3.10.
|
|
48
|
-
"@xyo-network/api-models": "^3.10.
|
|
49
|
-
"@xyo-network/boundwitness-model": "^3.10.
|
|
50
|
-
"@xyo-network/bridge-abstract": "^3.10.
|
|
51
|
-
"@xyo-network/bridge-model": "^3.10.
|
|
52
|
-
"@xyo-network/config-payload-plugin": "^3.10.
|
|
53
|
-
"@xyo-network/manifest-model": "^3.10.
|
|
54
|
-
"@xyo-network/module-model": "^3.10.
|
|
55
|
-
"@xyo-network/node-model": "^3.10.
|
|
56
|
-
"@xyo-network/payload-model": "^3.10.
|
|
51
|
+
"@xylabs/assert": "^4.7.11",
|
|
52
|
+
"@xylabs/axios": "^4.7.11",
|
|
53
|
+
"@xylabs/exists": "^4.7.11",
|
|
54
|
+
"@xylabs/forget": "^4.7.11",
|
|
55
|
+
"@xylabs/hex": "^4.7.11",
|
|
56
|
+
"@xylabs/object": "^4.7.11",
|
|
57
|
+
"@xylabs/promise": "^4.7.11",
|
|
58
|
+
"@xyo-network/account": "^3.10.4",
|
|
59
|
+
"@xyo-network/api-models": "^3.10.4",
|
|
60
|
+
"@xyo-network/boundwitness-model": "^3.10.4",
|
|
61
|
+
"@xyo-network/bridge-abstract": "^3.10.4",
|
|
62
|
+
"@xyo-network/bridge-model": "^3.10.4",
|
|
63
|
+
"@xyo-network/config-payload-plugin": "^3.10.4",
|
|
64
|
+
"@xyo-network/manifest-model": "^3.10.4",
|
|
65
|
+
"@xyo-network/module-model": "^3.10.4",
|
|
66
|
+
"@xyo-network/node-model": "^3.10.4",
|
|
67
|
+
"@xyo-network/payload-model": "^3.10.4",
|
|
57
68
|
"async-mutex": "^0.5.0",
|
|
58
69
|
"axios": "^1.8.4",
|
|
59
70
|
"express": "^4.21.2",
|
|
@@ -62,21 +73,21 @@
|
|
|
62
73
|
},
|
|
63
74
|
"devDependencies": {
|
|
64
75
|
"@types/express": "^5.0.1",
|
|
65
|
-
"@types/node": "^22.13.
|
|
76
|
+
"@types/node": "^22.13.11",
|
|
66
77
|
"@xylabs/eslint-config-flat": "^6.1.4",
|
|
67
78
|
"@xylabs/sdk-api-express-ecs": "^2.1.0",
|
|
68
79
|
"@xylabs/ts-scripts-yarn3": "^6.1.4",
|
|
69
80
|
"@xylabs/tsconfig": "^6.1.4",
|
|
70
|
-
"@xylabs/vitest-extended": "^4.7.
|
|
71
|
-
"@xyo-network/account": "^3.10.
|
|
72
|
-
"@xyo-network/archivist-model": "^3.10.
|
|
73
|
-
"@xyo-network/bridge-abstract": "^3.10.
|
|
74
|
-
"@xyo-network/diviner-model": "^3.10.
|
|
75
|
-
"@xyo-network/module-resolver": "^3.10.
|
|
76
|
-
"@xyo-network/node-memory": "^3.10.
|
|
77
|
-
"@xyo-network/node-model": "^3.10.
|
|
78
|
-
"@xyo-network/payload-builder": "^3.10.
|
|
79
|
-
"@xyo-network/payload-wrapper": "^3.10.
|
|
81
|
+
"@xylabs/vitest-extended": "^4.7.11",
|
|
82
|
+
"@xyo-network/account": "^3.10.4",
|
|
83
|
+
"@xyo-network/archivist-model": "^3.10.4",
|
|
84
|
+
"@xyo-network/bridge-abstract": "^3.10.4",
|
|
85
|
+
"@xyo-network/diviner-model": "^3.10.4",
|
|
86
|
+
"@xyo-network/module-resolver": "^3.10.4",
|
|
87
|
+
"@xyo-network/node-memory": "^3.10.4",
|
|
88
|
+
"@xyo-network/node-model": "^3.10.4",
|
|
89
|
+
"@xyo-network/payload-builder": "^3.10.4",
|
|
90
|
+
"@xyo-network/payload-wrapper": "^3.10.4",
|
|
80
91
|
"get-port-please": "^3.1.2",
|
|
81
92
|
"typescript": "^5.8.2",
|
|
82
93
|
"vitest": "^3.0.9"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import '@xylabs/vitest-extended'
|
|
2
|
+
|
|
3
|
+
import { MemoryNode } from '@xyo-network/node-memory'
|
|
4
|
+
import {
|
|
5
|
+
describe, expect, it,
|
|
6
|
+
} from 'vitest'
|
|
7
|
+
|
|
8
|
+
import { HttpBridgeConfigSchema } from '../HttpBridgeConfig.ts'
|
|
9
|
+
import { HttpBridge } from '../HttpBridgeFull.ts'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @group module
|
|
13
|
+
* @group bridge
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
describe('HttpBridge', () => {
|
|
17
|
+
const baseUrl = 'https://sfjhskjdsfhdsk.com'
|
|
18
|
+
|
|
19
|
+
console.log(`HttpBridge:baseUrl ${baseUrl}`)
|
|
20
|
+
const cases = [
|
|
21
|
+
['/', `${baseUrl}`],
|
|
22
|
+
/* ['/node', `${baseUrl}/node`], */
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
it.each(cases)('HttpBridge: %s', async (_, nodeUrl) => {
|
|
26
|
+
const memNode = await MemoryNode.create({ account: 'random' })
|
|
27
|
+
|
|
28
|
+
const bridge = await HttpBridge.create({
|
|
29
|
+
account: 'random',
|
|
30
|
+
config: {
|
|
31
|
+
nodeUrl, schema: HttpBridgeConfigSchema, security: { allowAnonymous: true },
|
|
32
|
+
},
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
await bridge?.start?.()
|
|
36
|
+
|
|
37
|
+
await memNode.register(bridge)
|
|
38
|
+
await memNode.attach(bridge.address, true)
|
|
39
|
+
|
|
40
|
+
const modules = await memNode.resolve('*')
|
|
41
|
+
expect(modules.length).toBe(2)
|
|
42
|
+
})
|
|
43
|
+
})
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import '@xylabs/vitest-extended'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
beforeEach,
|
|
5
|
+
describe, expect, it,
|
|
6
|
+
} from 'vitest'
|
|
7
|
+
|
|
8
|
+
import { HttpBridgeConfigSchema } from '../HttpBridgeConfig.ts'
|
|
9
|
+
import type { HttpBridgeParams } from '../HttpBridgeFull.ts'
|
|
10
|
+
import { HttpBridge } from '../HttpBridgeFull.ts'
|
|
11
|
+
|
|
12
|
+
describe('HttpBridge', () => {
|
|
13
|
+
let httpBridge: HttpBridge<HttpBridgeParams>
|
|
14
|
+
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
httpBridge = await HttpBridge.create({
|
|
17
|
+
account: 'random',
|
|
18
|
+
config: {
|
|
19
|
+
name: 'TestBridge', nodeUrl: 'http://localhost:8080', schema: HttpBridgeConfigSchema, security: { allowAnonymous: true },
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('should create an instance of HttpBridge', () => {
|
|
25
|
+
expect(httpBridge).toBeInstanceOf(HttpBridge)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('should have axios instance', () => {
|
|
29
|
+
expect(httpBridge.axios).toBeDefined()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should have nodeUrl defined', () => {
|
|
33
|
+
expect(httpBridge.clientUrl).toBe('http://localhost:8080')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('should have resolver defined', () => {
|
|
37
|
+
expect(httpBridge.resolver).toBeDefined()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('should return correct moduleUrl', () => {
|
|
41
|
+
const address = '0x1234'
|
|
42
|
+
expect(httpBridge.moduleUrl(address).toString()).toBe('http://localhost:8080/0x1234')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('should throw error on call to exposeHandler', async () => {
|
|
46
|
+
try {
|
|
47
|
+
await httpBridge.exposeHandler('test')
|
|
48
|
+
expect('').toBe('exposeHandler should have thrown an error')
|
|
49
|
+
} catch (error) {
|
|
50
|
+
expect(error).toBeInstanceOf(Error)
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('should throw error on call to unexposeHandler', async () => {
|
|
55
|
+
try {
|
|
56
|
+
await httpBridge.unexposeHandler('test')
|
|
57
|
+
expect('').toBe('unexposeHandler should have thrown an error')
|
|
58
|
+
} catch (error) {
|
|
59
|
+
expect(error).toBeInstanceOf(Error)
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
})
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import '@xylabs/vitest-extended'
|
|
2
|
+
|
|
3
|
+
import type { ModuleDescriptionPayload } from '@xyo-network/module-model'
|
|
4
|
+
import { ModuleDescriptionSchema } from '@xyo-network/module-model'
|
|
5
|
+
import { MemoryNode } from '@xyo-network/node-memory'
|
|
6
|
+
import { asAttachableNodeInstance } from '@xyo-network/node-model'
|
|
7
|
+
import { isPayloadOfSchemaType } from '@xyo-network/payload-model'
|
|
8
|
+
import { getPort } from 'get-port-please'
|
|
9
|
+
import {
|
|
10
|
+
beforeAll,
|
|
11
|
+
beforeEach,
|
|
12
|
+
describe, expect, it,
|
|
13
|
+
} from 'vitest'
|
|
14
|
+
|
|
15
|
+
import type { HttpBridgeConfig } from '../HttpBridgeConfig.ts'
|
|
16
|
+
import { HttpBridgeConfigSchema } from '../HttpBridgeConfig.ts'
|
|
17
|
+
import type { HttpBridgeParams } from '../HttpBridgeFull.ts'
|
|
18
|
+
import { HttpBridge } from '../HttpBridgeFull.ts'
|
|
19
|
+
|
|
20
|
+
const account = 'random'
|
|
21
|
+
const schema = HttpBridgeConfigSchema
|
|
22
|
+
const security = { allowAnonymous: true }
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @group module
|
|
26
|
+
* @group bridge
|
|
27
|
+
*/
|
|
28
|
+
describe('HttpBridge', () => {
|
|
29
|
+
let port: number
|
|
30
|
+
let url: string
|
|
31
|
+
let hostBridge: HttpBridge<HttpBridgeParams>
|
|
32
|
+
let clientBridge: HttpBridge<HttpBridgeParams>
|
|
33
|
+
let hostNode: MemoryNode
|
|
34
|
+
let clientNode: MemoryNode
|
|
35
|
+
let hostSibling: MemoryNode
|
|
36
|
+
let clientSibling: MemoryNode
|
|
37
|
+
let hostDescendent: MemoryNode
|
|
38
|
+
let clientDescendent: MemoryNode
|
|
39
|
+
|
|
40
|
+
beforeAll(async () => {
|
|
41
|
+
// Create Host/Client Nodes
|
|
42
|
+
hostNode = await MemoryNode.create({ account })
|
|
43
|
+
clientNode = await MemoryNode.create({ account })
|
|
44
|
+
|
|
45
|
+
// Create Host/Client Bridges
|
|
46
|
+
port = await getPort()
|
|
47
|
+
url = `http://localhost:${port}`
|
|
48
|
+
|
|
49
|
+
const host: HttpBridgeConfig['host'] = { port }
|
|
50
|
+
const client: HttpBridgeConfig['client'] = { discoverRoots: 'start', url }
|
|
51
|
+
hostBridge = await HttpBridge.create({
|
|
52
|
+
account,
|
|
53
|
+
config: {
|
|
54
|
+
host, name: 'TestBridgeHost', schema, security,
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
clientBridge = await HttpBridge.create({
|
|
58
|
+
account,
|
|
59
|
+
config: {
|
|
60
|
+
client, name: 'TestBridgeClient', schema, security,
|
|
61
|
+
},
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
// Register Host/Client Bridges
|
|
65
|
+
await hostNode.register(hostBridge)
|
|
66
|
+
await hostNode.attach(hostBridge.address, true)
|
|
67
|
+
await clientNode.register(clientBridge)
|
|
68
|
+
await clientNode.attach(clientBridge.address, true)
|
|
69
|
+
|
|
70
|
+
// Create Host/Client Sibling Nodes
|
|
71
|
+
hostSibling = await MemoryNode.create({ account })
|
|
72
|
+
clientSibling = await MemoryNode.create({ account })
|
|
73
|
+
|
|
74
|
+
// Register Host/Client Siblings
|
|
75
|
+
await hostNode.register(hostSibling)
|
|
76
|
+
await hostNode.attach(hostSibling.address, true)
|
|
77
|
+
await clientNode.register(clientSibling)
|
|
78
|
+
await clientNode.attach(clientSibling.address, true)
|
|
79
|
+
|
|
80
|
+
// Create Host/Client Descendent Nodes
|
|
81
|
+
hostDescendent = await MemoryNode.create({ account })
|
|
82
|
+
clientDescendent = await MemoryNode.create({ account })
|
|
83
|
+
|
|
84
|
+
// Register Host/Client Siblings
|
|
85
|
+
await hostSibling.register(hostDescendent)
|
|
86
|
+
await hostSibling.attach(hostDescendent.address, true)
|
|
87
|
+
await clientSibling.register(clientDescendent)
|
|
88
|
+
await clientSibling.attach(clientDescendent.address, true)
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
describe('exposed module behavior', () => {
|
|
92
|
+
const cases: [string, () => MemoryNode][] = [
|
|
93
|
+
['parent', () => hostNode],
|
|
94
|
+
['sibling', () => hostSibling],
|
|
95
|
+
['descendent', () => hostDescendent],
|
|
96
|
+
]
|
|
97
|
+
describe.each(cases)('with %s module', (_, getSutModule) => {
|
|
98
|
+
let exposedMod: MemoryNode
|
|
99
|
+
beforeEach(() => {
|
|
100
|
+
exposedMod = getSutModule()
|
|
101
|
+
})
|
|
102
|
+
describe('before expose', () => {
|
|
103
|
+
it('should not be exposed', async () => {
|
|
104
|
+
expect(await hostBridge.exposed()).toBeEmpty()
|
|
105
|
+
})
|
|
106
|
+
it('should not be resolvable', async () => {
|
|
107
|
+
expect(await clientBridge.resolve(exposedMod.address)).toBeUndefined()
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
describe('after expose', () => {
|
|
111
|
+
beforeEach(async () => {
|
|
112
|
+
await hostBridge.expose(exposedMod.address)
|
|
113
|
+
})
|
|
114
|
+
it('should be exposed on host', async () => {
|
|
115
|
+
expect((await hostBridge.exposed()).includes(exposedMod.address)).toBeTrue()
|
|
116
|
+
})
|
|
117
|
+
it.skip('should be resolvable from client', async () => {
|
|
118
|
+
// TODO: Implement .connect on HttpBridge and call here before resolving
|
|
119
|
+
const result = await clientBridge.resolve(exposedMod.address)
|
|
120
|
+
expect(result).toBeDefined()
|
|
121
|
+
expect(asAttachableNodeInstance(result, () => `Failed to resolve correct object type [${result?.constructor.name}]`)).toBeDefined()
|
|
122
|
+
})
|
|
123
|
+
it.skip('should be queryable from client', async () => {
|
|
124
|
+
const bridgedHostedModule = await clientBridge.resolve(exposedMod.address)
|
|
125
|
+
expect(bridgedHostedModule).toBeDefined()
|
|
126
|
+
|
|
127
|
+
const bridgedHostedNode = asAttachableNodeInstance(
|
|
128
|
+
bridgedHostedModule,
|
|
129
|
+
() => `Failed to resolve correct object type [${bridgedHostedModule?.constructor.name}]`,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
if (bridgedHostedNode) {
|
|
133
|
+
const state = await bridgedHostedNode.state()
|
|
134
|
+
const description = state.find(isPayloadOfSchemaType<ModuleDescriptionPayload>(ModuleDescriptionSchema))
|
|
135
|
+
expect(description?.children).toBeArray()
|
|
136
|
+
expect(description?.queries).toBeArray()
|
|
137
|
+
expect(description?.queries?.length).toBeGreaterThan(0)
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
|
+
describe('after unexpose', () => {
|
|
142
|
+
beforeEach(async () => {
|
|
143
|
+
await hostBridge.expose(exposedMod.address)
|
|
144
|
+
await hostBridge.unexpose(exposedMod.address)
|
|
145
|
+
})
|
|
146
|
+
it('should not be exposed', async () => {
|
|
147
|
+
expect(await hostBridge.exposed()).toBeEmpty()
|
|
148
|
+
})
|
|
149
|
+
it('should not be resolvable', async () => {
|
|
150
|
+
expect(await clientBridge.resolve(exposedMod.address)).toBeUndefined()
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
})
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import '@xylabs/vitest-extended'
|
|
2
|
+
|
|
3
|
+
import { MemoryNode } from '@xyo-network/node-memory'
|
|
4
|
+
import type { NodeInstance } from '@xyo-network/node-model'
|
|
5
|
+
import { NodeConfigSchema } from '@xyo-network/node-model'
|
|
6
|
+
import {
|
|
7
|
+
describe, expect, it,
|
|
8
|
+
} from 'vitest'
|
|
9
|
+
|
|
10
|
+
import { HttpBridgeConfigSchema } from '../HttpBridgeConfig.ts'
|
|
11
|
+
import { HttpBridge } from '../HttpBridgeFull.ts'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @group module
|
|
15
|
+
* @group bridge
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
describe('HttpBridge', () => {
|
|
19
|
+
const baseUrl = `${process.env.API_DOMAIN ?? 'http://localhost:8080'}`
|
|
20
|
+
|
|
21
|
+
console.log(`HttpBridge:baseUrl ${baseUrl}`)
|
|
22
|
+
it('Discover', async () => {
|
|
23
|
+
const nodeUrl = `${baseUrl}/`
|
|
24
|
+
const memNode = await MemoryNode.create({ account: 'random', config: { name: 'MemoryNode', schema: NodeConfigSchema } })
|
|
25
|
+
|
|
26
|
+
const bridge = await HttpBridge.create({
|
|
27
|
+
account: 'random',
|
|
28
|
+
config: {
|
|
29
|
+
discoverRoots: 'start', name: 'HttpBridge', nodeUrl, schema: HttpBridgeConfigSchema, security: { allowAnonymous: true },
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
await memNode.register(bridge)
|
|
34
|
+
await memNode.attach(bridge.address, true)
|
|
35
|
+
|
|
36
|
+
const publicNode = await bridge.resolve<NodeInstance>('XYOPublic')
|
|
37
|
+
expect(publicNode).toBeDefined()
|
|
38
|
+
|
|
39
|
+
if (publicNode) {
|
|
40
|
+
console.log(`publicNode[${publicNode.address}]: ${publicNode.modName}`)
|
|
41
|
+
const publicNodeModules = await publicNode.resolve('*', { direction: 'down' })
|
|
42
|
+
expect(publicNodeModules).toBeArray()
|
|
43
|
+
expect(publicNodeModules.length).toBeGreaterThan(0)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const bridgeModules = await bridge.resolve('*', { direction: 'down' })
|
|
47
|
+
expect(bridgeModules).toBeArray()
|
|
48
|
+
expect(bridgeModules.length).toBeGreaterThan(0)
|
|
49
|
+
|
|
50
|
+
/*
|
|
51
|
+
const modules = await memNode.resolve('*')
|
|
52
|
+
expect(modules).toBeArray()
|
|
53
|
+
expect(modules.length).toBeGreaterThan(20)
|
|
54
|
+
*/
|
|
55
|
+
})
|
|
56
|
+
})
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/* eslint-disable complexity */
|
|
2
|
+
/* eslint-disable max-statements */
|
|
3
|
+
|
|
4
|
+
import '@xylabs/vitest-extended'
|
|
5
|
+
|
|
6
|
+
import { assertEx } from '@xylabs/assert'
|
|
7
|
+
import { HDWallet } from '@xyo-network/account'
|
|
8
|
+
import type { ApiConfig } from '@xyo-network/api-models'
|
|
9
|
+
import type { AttachableArchivistInstance } from '@xyo-network/archivist-model'
|
|
10
|
+
import {
|
|
11
|
+
asArchivistInstance,
|
|
12
|
+
asAttachableArchivistInstance,
|
|
13
|
+
isAttachableArchivistInstance,
|
|
14
|
+
} from '@xyo-network/archivist-model'
|
|
15
|
+
import type { ModuleDescriptionPayload } from '@xyo-network/module-model'
|
|
16
|
+
import {
|
|
17
|
+
isModule, isModuleInstance, isModuleObject,
|
|
18
|
+
ModuleDescriptionSchema,
|
|
19
|
+
} from '@xyo-network/module-model'
|
|
20
|
+
import { MemoryNode } from '@xyo-network/node-memory'
|
|
21
|
+
import { asAttachableNodeInstance, isNodeInstance } from '@xyo-network/node-model'
|
|
22
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
23
|
+
import type { Payload } from '@xyo-network/payload-model'
|
|
24
|
+
import { isPayloadOfSchemaType } from '@xyo-network/payload-model'
|
|
25
|
+
import { PayloadWrapper } from '@xyo-network/payload-wrapper'
|
|
26
|
+
import {
|
|
27
|
+
describe, expect, it,
|
|
28
|
+
} from 'vitest'
|
|
29
|
+
|
|
30
|
+
import { HttpBridgeConfigSchema } from '../HttpBridgeConfig.ts'
|
|
31
|
+
import { HttpBridge } from '../HttpBridgeFull.ts'
|
|
32
|
+
|
|
33
|
+
const archivistName = 'XYOPublic:Archivist' // TODO: This should be configurable
|
|
34
|
+
const discoverRoots = 'start'
|
|
35
|
+
const schema = HttpBridgeConfigSchema
|
|
36
|
+
const security = { allowAnonymous: true }
|
|
37
|
+
|
|
38
|
+
export const getApiConfig = (): ApiConfig => {
|
|
39
|
+
return { apiDomain: process.env.ARCHIVIST_API_DOMAIN || 'https://beta.api.archivist.xyo.network' }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const getArchivist = async (config: ApiConfig = getApiConfig()): Promise<AttachableArchivistInstance> => {
|
|
43
|
+
return assertEx(await tryGetArchivist(config), () => 'Archivist not found')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const tryGetArchivist = async (config: ApiConfig = getApiConfig()): Promise<AttachableArchivistInstance | undefined> => {
|
|
47
|
+
const url = config.root ? `${config.apiDomain}/${config.root}` : config.apiDomain
|
|
48
|
+
const account = await HDWallet.random()
|
|
49
|
+
const bridge = await HttpBridge.create({
|
|
50
|
+
account,
|
|
51
|
+
config: {
|
|
52
|
+
client: { discoverRoots, url }, schema, security,
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
await bridge.start()
|
|
56
|
+
const mod = await bridge.resolve(archivistName)
|
|
57
|
+
return isAttachableArchivistInstance(mod) ? mod : undefined
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @group module
|
|
62
|
+
* @group bridge
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
describe('HttpBridge', () => {
|
|
66
|
+
const baseUrl = `${process.env.API_DOMAIN ?? 'http://localhost:8080'}`
|
|
67
|
+
|
|
68
|
+
console.log(`HttpBridge:baseUrl ${baseUrl}`)
|
|
69
|
+
const cases = [
|
|
70
|
+
['/', `${baseUrl}`],
|
|
71
|
+
/* ['/node', `${baseUrl}/node`], */
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
it.each(cases)('HttpBridge: %s', async (_, nodeUrl) => {
|
|
75
|
+
const memNode = await MemoryNode.create({ account: 'random' })
|
|
76
|
+
const extraMemNode = await MemoryNode.create({ account: 'random' })
|
|
77
|
+
|
|
78
|
+
const bridge = await HttpBridge.create({
|
|
79
|
+
account: 'random',
|
|
80
|
+
config: {
|
|
81
|
+
discoverRoots: 'start', name: 'TestBridge', nodeUrl, schema: HttpBridgeConfigSchema, security: { allowAnonymous: true },
|
|
82
|
+
},
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
await bridge?.start?.()
|
|
86
|
+
await memNode.register(bridge)
|
|
87
|
+
await memNode.attach(bridge?.address, true)
|
|
88
|
+
|
|
89
|
+
const resolvedBridge = await memNode.resolve(bridge.id)
|
|
90
|
+
expect(resolvedBridge).toBeDefined()
|
|
91
|
+
|
|
92
|
+
const rootModule = await bridge?.resolve('XYOPublic')
|
|
93
|
+
expect(rootModule).toBeDefined()
|
|
94
|
+
|
|
95
|
+
const remoteNode = asAttachableNodeInstance(
|
|
96
|
+
rootModule,
|
|
97
|
+
() => `Failed to resolve correct object type [XYOPublic] [${rootModule?.constructor.name}]`,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
const state = await remoteNode.state()
|
|
101
|
+
const description = state.find(isPayloadOfSchemaType<ModuleDescriptionPayload>(ModuleDescriptionSchema))
|
|
102
|
+
expect(description?.children).toBeArray()
|
|
103
|
+
expect(description?.children?.length).toBeGreaterThan(0)
|
|
104
|
+
expect(description?.queries).toBeArray()
|
|
105
|
+
expect(description?.queries?.length).toBeGreaterThan(0)
|
|
106
|
+
|
|
107
|
+
const archivistByName1 = await rootModule?.resolve('Archivist')
|
|
108
|
+
expect(archivistByName1).toBeDefined()
|
|
109
|
+
const archivistByName2 = await bridge.resolve('XYOPublic:Archivist')
|
|
110
|
+
expect(archivistByName2).toBeDefined()
|
|
111
|
+
const publicXyo = await bridge.resolve('XYOPublic')
|
|
112
|
+
expect(publicXyo).toBeDefined()
|
|
113
|
+
const publicXyoSelfResolve = publicXyo?.resolve('XYOPublic')
|
|
114
|
+
expect(publicXyoSelfResolve).toBeDefined()
|
|
115
|
+
if (publicXyo) {
|
|
116
|
+
const bridgedArchivist = await getArchivist()
|
|
117
|
+
expect(bridgedArchivist).toBeDefined()
|
|
118
|
+
if (bridgedArchivist) {
|
|
119
|
+
const attachablePublicXyo = asAttachableArchivistInstance(archivistByName2, 'Failed to cast publicXyo')
|
|
120
|
+
expect(attachablePublicXyo).toBeDefined()
|
|
121
|
+
await extraMemNode.register(bridgedArchivist)
|
|
122
|
+
await extraMemNode.attach(bridgedArchivist.address, true)
|
|
123
|
+
const publicXyoNodeResolveAddress = await extraMemNode?.resolve(bridgedArchivist.address)
|
|
124
|
+
expect(publicXyoNodeResolveAddress).toBeDefined()
|
|
125
|
+
const publicXyoNodeResolve = await extraMemNode?.resolve('Archivist')
|
|
126
|
+
expect(publicXyoNodeResolve).toBeDefined()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const archivistByName3 = await publicXyo?.resolve('Archivist')
|
|
130
|
+
expect(archivistByName3).toBeDefined()
|
|
131
|
+
expect(archivistByName3).toEqual(archivistByName1)
|
|
132
|
+
expect(archivistByName3).toEqual(archivistByName2)
|
|
133
|
+
expect(archivistByName2).toBeDefined()
|
|
134
|
+
const archivistInstance = asArchivistInstance(archivistByName2, 'Failed to cast archivist')
|
|
135
|
+
expect(archivistInstance).toBeDefined()
|
|
136
|
+
const knownPayload = PayloadWrapper.parse({ schema: 'network.xyo.test' })?.payload as Payload
|
|
137
|
+
expect(knownPayload).toBeDefined()
|
|
138
|
+
const knownHash = await PayloadBuilder.dataHash(knownPayload as Payload)
|
|
139
|
+
const insertResult = await archivistInstance.insert([knownPayload])
|
|
140
|
+
expect(insertResult).toBeDefined()
|
|
141
|
+
const roundTripPayload = (await archivistInstance.get([knownHash]))[0]
|
|
142
|
+
expect(roundTripPayload).toBeDefined()
|
|
143
|
+
})
|
|
144
|
+
it.each(cases)('HttpBridge - Nested: %s', async (_, nodeUrl) => {
|
|
145
|
+
const memNode1 = await MemoryNode.create({ account: 'random', config: { schema: 'network.xyo.node.config' } })
|
|
146
|
+
const memNode2 = await MemoryNode.create({ account: 'random', config: { schema: 'network.xyo.node.config' } })
|
|
147
|
+
const memNode3 = await MemoryNode.create({ account: 'random', config: { schema: 'network.xyo.node.config' } })
|
|
148
|
+
|
|
149
|
+
await memNode1.register(memNode2)
|
|
150
|
+
await memNode1.attach(memNode2.address, true)
|
|
151
|
+
await memNode2.register(memNode3)
|
|
152
|
+
await memNode2.attach(memNode3.address, true)
|
|
153
|
+
|
|
154
|
+
const bridge = await HttpBridge.create({
|
|
155
|
+
account: 'random',
|
|
156
|
+
config: {
|
|
157
|
+
nodeUrl, schema: HttpBridgeConfigSchema, security: { allowAnonymous: true },
|
|
158
|
+
},
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
await bridge.getRoots()
|
|
162
|
+
const mod = await bridge.resolve('XYOPublic')
|
|
163
|
+
|
|
164
|
+
expect(mod).toBeDefined()
|
|
165
|
+
expect(isModule(mod)).toBeTrue()
|
|
166
|
+
expect(isModuleObject(mod)).toBeTrue()
|
|
167
|
+
|
|
168
|
+
const remoteNode = asAttachableNodeInstance(mod, `Failed to resolve [XYOPublic] - ${mod?.address} [${mod?.id}] [${mod?.constructor.name}]`)
|
|
169
|
+
|
|
170
|
+
expect(isNodeInstance(remoteNode)).toBeTrue()
|
|
171
|
+
expect(isModuleInstance(remoteNode)).toBeTrue()
|
|
172
|
+
|
|
173
|
+
await memNode3.register(remoteNode)
|
|
174
|
+
await memNode3.attach(remoteNode?.address, true)
|
|
175
|
+
const description = (await remoteNode.state()).find(isPayloadOfSchemaType<ModuleDescriptionPayload>(ModuleDescriptionSchema))
|
|
176
|
+
expect(description?.children).toBeArray()
|
|
177
|
+
expect(description?.children?.length).toBeGreaterThan(0)
|
|
178
|
+
expect(description?.queries).toBeArray()
|
|
179
|
+
expect(description?.queries?.length).toBeGreaterThan(0)
|
|
180
|
+
|
|
181
|
+
// Works if you supply the known address for 'Archivist'
|
|
182
|
+
// const [archivistByAddress] = await memNode.resolve({ address: ['461fd6970770e97d9f66c71658f4b96212581f0b'] })
|
|
183
|
+
// expect(archivistByAddress).toBeDefined()
|
|
184
|
+
|
|
185
|
+
/* const mods = await bridge.resolve('*')
|
|
186
|
+
for (const mod of mods) {
|
|
187
|
+
console.log(`module [${mod.address}]: ${mod.modName}`)
|
|
188
|
+
} */
|
|
189
|
+
|
|
190
|
+
const node = await bridge.resolve('XYOPublic')
|
|
191
|
+
expect(node).toBeDefined()
|
|
192
|
+
|
|
193
|
+
const archivistByName1 = await node?.resolve('Archivist')
|
|
194
|
+
expect(archivistByName1).toBeDefined()
|
|
195
|
+
|
|
196
|
+
const archivistByName2 = (await node?.resolve('Archivist'))
|
|
197
|
+
expect(archivistByName2).toBeDefined()
|
|
198
|
+
const payloadStatsDivinerByName = (await node?.resolve('PayloadStatsDiviner'))
|
|
199
|
+
expect(payloadStatsDivinerByName).toBeDefined()
|
|
200
|
+
const boundwitnessStatsDivinerByName = (await node?.resolve('BoundWitnessStatsDiviner'))
|
|
201
|
+
expect(boundwitnessStatsDivinerByName).toBeDefined()
|
|
202
|
+
})
|
|
203
|
+
})
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* eslint-disable sonarjs/assertions-in-tests */
|
|
2
|
+
/* eslint-disable max-nested-callbacks */
|
|
3
|
+
import '@xylabs/vitest-extended'
|
|
4
|
+
|
|
5
|
+
import type { AbstractBridge } from '@xyo-network/bridge-abstract'
|
|
6
|
+
import {
|
|
7
|
+
describe, expect, it,
|
|
8
|
+
} from 'vitest'
|
|
9
|
+
|
|
10
|
+
// TODO: Implement standard test suite for all Bridges here and then run
|
|
11
|
+
// against specific bridges
|
|
12
|
+
export const generateBridgeTests = (title: string, _bridge: AbstractBridge) => {
|
|
13
|
+
describe(title, () => {
|
|
14
|
+
describe('HttpBridge', () => {
|
|
15
|
+
describe('By name', () => {
|
|
16
|
+
it('should handle the case by name', () => {
|
|
17
|
+
// Add your test logic here
|
|
18
|
+
})
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
describe('By address', () => {
|
|
22
|
+
it('should handle the case by address', () => {
|
|
23
|
+
// Add your test logic here
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
describe('By exposed/unexposed', () => {
|
|
28
|
+
describe('Pre Exposed', () => {
|
|
29
|
+
it('should handle the case when pre exposed', () => {
|
|
30
|
+
// Add your test logic here
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
describe('Post Exposed', () => {
|
|
35
|
+
it('should handle the case when post exposed', () => {
|
|
36
|
+
// Add your test logic here
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
describe('Post Unexposed', () => {
|
|
41
|
+
it('should handle the case when post unexposed', () => {
|
|
42
|
+
// Add your test logic here
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
describe('By parent/sibling/child/grandchild', () => {
|
|
48
|
+
describe('ParentNode', () => {
|
|
49
|
+
it('should handle the case for ParentNode', () => {
|
|
50
|
+
// Add your test logic here
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
describe('Bridge', () => {
|
|
54
|
+
it('should handle the case for Bridge', () => {
|
|
55
|
+
// Add your test logic here
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
describe('SiblingNode', () => {
|
|
60
|
+
it('should handle the case for SiblingNode', () => {
|
|
61
|
+
// Add your test logic here
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
describe('ChildNode', () => {
|
|
65
|
+
it('should handle the case for ChildNode', () => {
|
|
66
|
+
// Add your test logic here
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
describe('GrandchildNode', () => {
|
|
73
|
+
it('should handle the case for GrandchildNode', () => {
|
|
74
|
+
// Add your test logic here
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
describe('HttpBridge', () => {
|
|
83
|
+
it('No tests', () => {
|
|
84
|
+
expect(true).toBeTruthy()
|
|
85
|
+
})
|
|
86
|
+
})
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import '@xylabs/vitest-extended'
|
|
2
|
+
|
|
3
|
+
import { asDivinerInstance } from '@xyo-network/diviner-model'
|
|
4
|
+
import { ResolveHelper } from '@xyo-network/module-model'
|
|
5
|
+
import { NameRegistrarTransformer } from '@xyo-network/module-resolver'
|
|
6
|
+
import { MemoryNode } from '@xyo-network/node-memory'
|
|
7
|
+
import { asAttachableNodeInstance } from '@xyo-network/node-model'
|
|
8
|
+
import {
|
|
9
|
+
describe, expect, it,
|
|
10
|
+
} from 'vitest'
|
|
11
|
+
|
|
12
|
+
import { HttpBridgeConfigSchema } from '../HttpBridgeConfig.ts'
|
|
13
|
+
import { HttpBridge } from '../HttpBridgeFull.ts'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @group module
|
|
17
|
+
* @group bridge
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
describe('HttpBridge - Xns', () => {
|
|
21
|
+
it('HttpBridge-Xns: Simple Resolve', async () => {
|
|
22
|
+
const memNode = await MemoryNode.create({ account: 'random' })
|
|
23
|
+
|
|
24
|
+
const bridge = await HttpBridge.create({
|
|
25
|
+
account: 'random',
|
|
26
|
+
config: {
|
|
27
|
+
discoverRoots: 'start',
|
|
28
|
+
name: 'TestBridge',
|
|
29
|
+
nodeUrl: 'https://beta.xns.xyo.network',
|
|
30
|
+
schema: HttpBridgeConfigSchema,
|
|
31
|
+
security: { allowAnonymous: true },
|
|
32
|
+
},
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
await bridge?.start?.()
|
|
36
|
+
await memNode.register(bridge)
|
|
37
|
+
await memNode.attach(bridge?.address, true)
|
|
38
|
+
const resolvedBridge = await memNode.resolve(bridge.id)
|
|
39
|
+
expect(resolvedBridge).toBeDefined()
|
|
40
|
+
|
|
41
|
+
const rootModule = await bridge?.resolve('XNS')
|
|
42
|
+
expect(rootModule).toBeDefined()
|
|
43
|
+
|
|
44
|
+
const remoteNode = asAttachableNodeInstance(rootModule, () => `Failed to resolve correct object type [XYO] [${rootModule?.constructor.name}]`)
|
|
45
|
+
|
|
46
|
+
const registrarDiviner = asDivinerInstance(await remoteNode.resolve('XNS:AddressRecords:AddressRecordIndexDiviner'))
|
|
47
|
+
expect(registrarDiviner).toBeDefined()
|
|
48
|
+
if (registrarDiviner) {
|
|
49
|
+
const transformer = new NameRegistrarTransformer(registrarDiviner, 'xyo')
|
|
50
|
+
ResolveHelper.transformers = [transformer]
|
|
51
|
+
const address = await transformer.transform('nippyflight.xyo')
|
|
52
|
+
expect(address).toBe('c5fa710300a8a43568678d0fe72810e34d880357')
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
})
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-browser.d.ts","sourceRoot":"","sources":["../../src/index-browser.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA"}
|
package/eslint.config.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { config as default } from '@xylabs/eslint-config-flat'
|
package/typedoc.json
DELETED
package/xy.config.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { XyTsupConfig } from '@xylabs/ts-scripts-yarn3'
|
|
2
|
-
const config: XyTsupConfig = {
|
|
3
|
-
compile: {
|
|
4
|
-
browser: { src: { entry: ['./src/index-browser.ts'] } },
|
|
5
|
-
neutral: { src: { entry: ['./src/index-browser.ts'] } },
|
|
6
|
-
node: { src: { entry: ['./src/index.ts'] } },
|
|
7
|
-
},
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default config
|
|
File without changes
|
|
File without changes
|
|
File without changes
|