space-data-module-sdk 0.5.22 → 0.6.1
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/README.md +22 -2
- package/package.json +2 -2
- package/schemas/orbpro/BaseTypes.fbs +7 -0
- package/schemas/orbpro/CatalogQueryBase.fbs +8 -0
- package/schemas/orbpro/CatalogQueryRequest.fbs +14 -0
- package/schemas/orbpro/CatalogQueryResult.fbs +17 -0
- package/schemas/orbpro/EntityMetadata.fbs +53 -0
- package/schemas/orbpro/EntityStandardsLink.fbs +18 -0
- package/schemas/orbpro/Plugin.fbs +8 -0
- package/schemas/orbpro/Propagator.fbs +89 -0
- package/schemas/orbpro/StandardsRecordIndex.fbs +15 -0
- package/src/generated/orbpro/entity/entity-kind.js +15 -0
- package/src/generated/orbpro/entity/entity-kind.ts +15 -0
- package/src/generated/orbpro/entity/entity-metadata.js +322 -0
- package/src/generated/orbpro/entity/entity-metadata.ts +426 -0
- package/src/generated/orbpro/entity/entity-standards-link.js +143 -0
- package/src/generated/orbpro/entity/entity-standards-link.ts +183 -0
- package/src/generated/orbpro/entity/standards-record-index.js +115 -0
- package/src/generated/orbpro/entity/standards-record-index.ts +147 -0
- package/src/generated/orbpro/entity.js +10 -0
- package/src/generated/orbpro/entity.ts +5 -0
- package/src/generated/orbpro/plugin/raw-data-payload.js +79 -0
- package/src/generated/orbpro/plugin/raw-data-payload.ts +92 -0
- package/src/generated/orbpro/plugin.js +4 -0
- package/src/generated/orbpro/plugin.ts +5 -0
- package/src/generated/orbpro/propagator/propagator-describe-sources-batch-request.js +79 -0
- package/src/generated/orbpro/propagator/propagator-describe-sources-batch-request.ts +95 -0
- package/src/generated/orbpro/propagator/propagator-describe-sources-batch-result.js +70 -0
- package/src/generated/orbpro/propagator/propagator-describe-sources-batch-result.ts +78 -0
- package/src/generated/orbpro/propagator/propagator-sample-trajectory-states-request.js +97 -0
- package/src/generated/orbpro/propagator/propagator-sample-trajectory-states-request.ts +117 -0
- package/src/generated/orbpro/propagator/propagator-sample-trajectory-states-result.js +140 -0
- package/src/generated/orbpro/propagator/propagator-sample-trajectory-states-result.ts +175 -0
- package/src/generated/orbpro/propagator/propagator-source-description.js +208 -0
- package/src/generated/orbpro/propagator/propagator-source-description.ts +257 -0
- package/src/generated/orbpro/propagator/propagator-source-kind.js +8 -0
- package/src/generated/orbpro/propagator/propagator-source-kind.ts +8 -0
- package/src/generated/orbpro/propagator/reference-frame.js +12 -0
- package/src/generated/orbpro/propagator/reference-frame.ts +12 -0
- package/src/generated/orbpro/propagator/state-flags.js +13 -0
- package/src/generated/orbpro/propagator/state-flags.ts +13 -0
- package/src/generated/orbpro/propagator/state-vector.js +55 -0
- package/src/generated/orbpro/propagator/state-vector.ts +61 -0
- package/src/generated/orbpro/propagator.js +20 -0
- package/src/generated/orbpro/propagator.ts +13 -0
- package/src/generated/orbpro/query/catalog-query-kind.js +10 -0
- package/src/generated/orbpro/query/catalog-query-kind.ts +10 -0
- package/src/generated/orbpro/query/catalog-query-request.js +89 -0
- package/src/generated/orbpro/query/catalog-query-request.ts +105 -0
- package/src/generated/orbpro/query/catalog-query-result.js +145 -0
- package/src/generated/orbpro/query/catalog-query-result.ts +179 -0
- package/src/generated/orbpro/query.js +8 -0
- package/src/generated/orbpro/query.ts +4 -0
- package/src/generated/orbpro/vec3.js +39 -0
- package/src/generated/orbpro/vec3.ts +40 -0
- package/src/host/abi.js +189 -3
- package/src/host/browserEdgeShims.js +17 -0
- package/src/host/browserHost.js +486 -40
- package/src/host/isomorphicLoader.js +44 -20
- package/src/host/nodeHost.js +337 -63
- package/src/index.d.ts +99 -3
- package/src/runtime-host/index.js +90 -0
- package/src/testing/browserModuleHarness.js +22 -3
- package/src/testing/index.d.ts +1 -0
- package/src/testing/index.js +39 -1
|
@@ -13,11 +13,26 @@ import {
|
|
|
13
13
|
createBrowserModuleHarness,
|
|
14
14
|
detectArtifactProfile,
|
|
15
15
|
} from "../testing/browserModuleHarness.js";
|
|
16
|
+
import { createAsyncHostDispatcher } from "./abi.js";
|
|
16
17
|
|
|
17
18
|
const isBrowser =
|
|
18
19
|
typeof globalThis.window !== "undefined" &&
|
|
19
20
|
typeof globalThis.document !== "undefined";
|
|
20
21
|
|
|
22
|
+
function attachHostDispatch(harness, host) {
|
|
23
|
+
if (!host || typeof host !== "object") {
|
|
24
|
+
return harness;
|
|
25
|
+
}
|
|
26
|
+
const dispatchHost = createAsyncHostDispatcher(host);
|
|
27
|
+
return {
|
|
28
|
+
...harness,
|
|
29
|
+
host,
|
|
30
|
+
async callHost(operation, params = {}) {
|
|
31
|
+
return dispatchHost(operation, params);
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
21
36
|
async function createWasmEdgeCommandHarness(options = {}) {
|
|
22
37
|
const [
|
|
23
38
|
{ spawn },
|
|
@@ -175,14 +190,18 @@ export async function loadModule(options = {}) {
|
|
|
175
190
|
(inspection.profile === "standalone" || inspection.profile === "sdn-abi") &&
|
|
176
191
|
inspection.exports.includes("_start")
|
|
177
192
|
) {
|
|
178
|
-
return
|
|
193
|
+
return attachHostDispatch(
|
|
194
|
+
await createWasmEdgeCommandHarness(options),
|
|
195
|
+
options.host ?? null,
|
|
196
|
+
);
|
|
179
197
|
}
|
|
180
198
|
}
|
|
181
199
|
|
|
182
|
-
return
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
200
|
+
return attachHostDispatch(
|
|
201
|
+
await createModuleHarness({
|
|
202
|
+
runtime: {
|
|
203
|
+
kind: "wasmedge",
|
|
204
|
+
wasmPath: source,
|
|
186
205
|
wasmEdgeBinary: options.wasmEdgeBinary,
|
|
187
206
|
wasmEdgeRunnerBinary: options.wasmEdgeRunnerBinary,
|
|
188
207
|
enableThreads: options.enableThreads,
|
|
@@ -191,23 +210,28 @@ export async function loadModule(options = {}) {
|
|
|
191
210
|
hostProfile: options.hostProfile,
|
|
192
211
|
modules: options.modules,
|
|
193
212
|
defaultModuleId: options.defaultModuleId,
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
213
|
+
metadata: options.metadata,
|
|
214
|
+
},
|
|
215
|
+
}),
|
|
216
|
+
options.host ?? null,
|
|
217
|
+
);
|
|
197
218
|
}
|
|
198
219
|
|
|
199
|
-
return
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
220
|
+
return attachHostDispatch(
|
|
221
|
+
await createModuleHarness({
|
|
222
|
+
runtime: {
|
|
223
|
+
kind: runtimeKind,
|
|
224
|
+
command: options.command ?? runtimeKind,
|
|
225
|
+
args: options.args ?? [source],
|
|
226
|
+
env: options.env,
|
|
227
|
+
cwd: options.cwd,
|
|
228
|
+
hostProfile: options.hostProfile,
|
|
229
|
+
modules: options.modules,
|
|
230
|
+
defaultModuleId: options.defaultModuleId,
|
|
231
|
+
},
|
|
232
|
+
}),
|
|
233
|
+
options.host ?? null,
|
|
234
|
+
);
|
|
211
235
|
}
|
|
212
236
|
|
|
213
237
|
/**
|
package/src/host/nodeHost.js
CHANGED
|
@@ -46,10 +46,14 @@ export const NodeHostSupportedCapabilities = Object.freeze([
|
|
|
46
46
|
"http",
|
|
47
47
|
"websocket",
|
|
48
48
|
"mqtt",
|
|
49
|
+
"network",
|
|
49
50
|
"filesystem",
|
|
50
51
|
"tcp",
|
|
51
52
|
"udp",
|
|
52
53
|
"tls",
|
|
54
|
+
"ipfs",
|
|
55
|
+
"protocol_handle",
|
|
56
|
+
"protocol_dial",
|
|
53
57
|
"context_read",
|
|
54
58
|
"context_write",
|
|
55
59
|
"crypto_hash",
|
|
@@ -59,6 +63,7 @@ export const NodeHostSupportedCapabilities = Object.freeze([
|
|
|
59
63
|
"crypto_decrypt",
|
|
60
64
|
"crypto_key_agreement",
|
|
61
65
|
"crypto_kdf",
|
|
66
|
+
"wallet_sign",
|
|
62
67
|
"process_exec",
|
|
63
68
|
]);
|
|
64
69
|
|
|
@@ -75,6 +80,7 @@ export const NodeHostSupportedOperations = Object.freeze([
|
|
|
75
80
|
"websocket.exchange",
|
|
76
81
|
"mqtt.publish",
|
|
77
82
|
"mqtt.subscribeOnce",
|
|
83
|
+
"network.request",
|
|
78
84
|
"filesystem.resolvePath",
|
|
79
85
|
"filesystem.readFile",
|
|
80
86
|
"filesystem.writeFile",
|
|
@@ -87,6 +93,14 @@ export const NodeHostSupportedOperations = Object.freeze([
|
|
|
87
93
|
"tcp.request",
|
|
88
94
|
"udp.request",
|
|
89
95
|
"tls.request",
|
|
96
|
+
"ipfs.invoke",
|
|
97
|
+
"ipfs.add",
|
|
98
|
+
"ipfs.cat",
|
|
99
|
+
"protocol_handle.register",
|
|
100
|
+
"protocol_handle.unregister",
|
|
101
|
+
"protocol_dial.dial",
|
|
102
|
+
"protocol.request",
|
|
103
|
+
"keyslot.get",
|
|
90
104
|
"exec.execFile",
|
|
91
105
|
"context.get",
|
|
92
106
|
"context.set",
|
|
@@ -151,6 +165,34 @@ function normalizeGrantedCapabilities(options) {
|
|
|
151
165
|
return normalized;
|
|
152
166
|
}
|
|
153
167
|
|
|
168
|
+
function resolveCapabilityAdapters(options = {}) {
|
|
169
|
+
const adapters =
|
|
170
|
+
options.capabilityAdapters && typeof options.capabilityAdapters === "object"
|
|
171
|
+
? options.capabilityAdapters
|
|
172
|
+
: {};
|
|
173
|
+
return {
|
|
174
|
+
filesystem: options.filesystem ?? adapters.filesystem ?? null,
|
|
175
|
+
network: options.network ?? adapters.network ?? null,
|
|
176
|
+
ipfs: options.ipfs ?? adapters.ipfs ?? null,
|
|
177
|
+
walletSign:
|
|
178
|
+
options.walletSign ??
|
|
179
|
+
adapters.walletSign ??
|
|
180
|
+
adapters.wallet_sign ??
|
|
181
|
+
adapters.keyslot ??
|
|
182
|
+
null,
|
|
183
|
+
protocolHandle:
|
|
184
|
+
options.protocolHandle ??
|
|
185
|
+
adapters.protocolHandle ??
|
|
186
|
+
adapters.protocol_handle ??
|
|
187
|
+
null,
|
|
188
|
+
protocolDial:
|
|
189
|
+
options.protocolDial ??
|
|
190
|
+
adapters.protocolDial ??
|
|
191
|
+
adapters.protocol_dial ??
|
|
192
|
+
null,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
154
196
|
function normalizeAllowedOrigins(origins) {
|
|
155
197
|
if (origins === undefined || origins === null) {
|
|
156
198
|
return null;
|
|
@@ -229,6 +271,45 @@ function normalizeAllowedPorts(ports, label, { allowZero = false } = {}) {
|
|
|
229
271
|
return normalized;
|
|
230
272
|
}
|
|
231
273
|
|
|
274
|
+
function normalizeNetworkTransport(params = {}) {
|
|
275
|
+
const explicit = String(
|
|
276
|
+
params.transport ?? params.kind ?? params.request?.transport ?? "",
|
|
277
|
+
)
|
|
278
|
+
.trim()
|
|
279
|
+
.toLowerCase();
|
|
280
|
+
if (explicit) {
|
|
281
|
+
return explicit;
|
|
282
|
+
}
|
|
283
|
+
const candidateUrl = params.url ?? params.request?.url ?? null;
|
|
284
|
+
if (candidateUrl) {
|
|
285
|
+
const protocol = new URL(candidateUrl).protocol.toLowerCase();
|
|
286
|
+
if (protocol === "http:" || protocol === "https:") {
|
|
287
|
+
return "http";
|
|
288
|
+
}
|
|
289
|
+
if (protocol === "ws:" || protocol === "wss:") {
|
|
290
|
+
return "websocket";
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
throw new Error(
|
|
294
|
+
'network.request requires a transport value such as "http", "tcp", or "websocket".',
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
async function invokeAdapterMethod(adapter, methodName, params, label) {
|
|
299
|
+
if (!adapter || typeof adapter !== "object") {
|
|
300
|
+
throw new Error(`${label} adapter is not configured for this host.`);
|
|
301
|
+
}
|
|
302
|
+
if (typeof adapter[methodName] === "function") {
|
|
303
|
+
return adapter[methodName](params);
|
|
304
|
+
}
|
|
305
|
+
if (typeof adapter.invoke === "function") {
|
|
306
|
+
return adapter.invoke(methodName, params);
|
|
307
|
+
}
|
|
308
|
+
throw new Error(
|
|
309
|
+
`${label} adapter does not implement "${methodName}" or invoke().`,
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
232
313
|
function normalizeFilesystemRoot(rootPath) {
|
|
233
314
|
return path.resolve(String(rootPath ?? process.cwd()));
|
|
234
315
|
}
|
|
@@ -1397,6 +1478,13 @@ export class NodeHost {
|
|
|
1397
1478
|
);
|
|
1398
1479
|
this.fetch = options.fetch ?? globalThis.fetch;
|
|
1399
1480
|
this.WebSocket = options.WebSocket ?? globalThis.WebSocket;
|
|
1481
|
+
const capabilityAdapters = resolveCapabilityAdapters(options);
|
|
1482
|
+
this._filesystemAdapter = capabilityAdapters.filesystem;
|
|
1483
|
+
this._networkAdapter = capabilityAdapters.network;
|
|
1484
|
+
this._ipfsAdapter = capabilityAdapters.ipfs;
|
|
1485
|
+
this._walletSignAdapter = capabilityAdapters.walletSign;
|
|
1486
|
+
this._protocolHandleAdapter = capabilityAdapters.protocolHandle;
|
|
1487
|
+
this._protocolDialAdapter = capabilityAdapters.protocolDial;
|
|
1400
1488
|
if (typeof this.fetch !== "function") {
|
|
1401
1489
|
throw new TypeError(
|
|
1402
1490
|
"A fetch implementation is required to create a Node host.",
|
|
@@ -1550,6 +1638,121 @@ export class NodeHost {
|
|
|
1550
1638
|
}),
|
|
1551
1639
|
});
|
|
1552
1640
|
|
|
1641
|
+
this.network = Object.freeze({
|
|
1642
|
+
request: async (params = {}) =>
|
|
1643
|
+
this.#withCapability("network", "network.request", async () => {
|
|
1644
|
+
const transport = normalizeNetworkTransport(params);
|
|
1645
|
+
const request = params.request ?? params;
|
|
1646
|
+
if (this._networkAdapter) {
|
|
1647
|
+
return invokeAdapterMethod(this._networkAdapter, "request", {
|
|
1648
|
+
...request,
|
|
1649
|
+
transport,
|
|
1650
|
+
}, "network");
|
|
1651
|
+
}
|
|
1652
|
+
switch (transport) {
|
|
1653
|
+
case "http":
|
|
1654
|
+
return this.http.request(request);
|
|
1655
|
+
case "websocket":
|
|
1656
|
+
return this.websocket.exchange(request);
|
|
1657
|
+
case "mqtt":
|
|
1658
|
+
return request.subscribe === true
|
|
1659
|
+
? this.mqtt.subscribeOnce(request)
|
|
1660
|
+
: this.mqtt.publish(request);
|
|
1661
|
+
case "tcp":
|
|
1662
|
+
return this.tcp.request(request);
|
|
1663
|
+
case "udp":
|
|
1664
|
+
return this.udp.request(request);
|
|
1665
|
+
case "tls":
|
|
1666
|
+
return this.tls.request(request);
|
|
1667
|
+
default:
|
|
1668
|
+
throw new Error(
|
|
1669
|
+
`Node host does not support network transport "${transport}".`,
|
|
1670
|
+
);
|
|
1671
|
+
}
|
|
1672
|
+
}),
|
|
1673
|
+
});
|
|
1674
|
+
|
|
1675
|
+
const builtinFilesystem = {
|
|
1676
|
+
resolvePath: (targetPath) => this.#resolveFilesystemPath(targetPath),
|
|
1677
|
+
readFile: async (targetPath, options = {}) => {
|
|
1678
|
+
const resolvedPath = this.#resolveFilesystemPath(targetPath);
|
|
1679
|
+
const file = await readFile(resolvedPath);
|
|
1680
|
+
if (options.encoding) {
|
|
1681
|
+
return file.toString(options.encoding);
|
|
1682
|
+
}
|
|
1683
|
+
return new Uint8Array(file);
|
|
1684
|
+
},
|
|
1685
|
+
writeFile: async (targetPath, value, options = {}) => {
|
|
1686
|
+
const resolvedPath = this.#resolveFilesystemPath(targetPath);
|
|
1687
|
+
await mkdir(path.dirname(resolvedPath), { recursive: true });
|
|
1688
|
+
await writeFile(
|
|
1689
|
+
resolvedPath,
|
|
1690
|
+
typeof value === "string" ? value : Buffer.from(toUint8Array(value)),
|
|
1691
|
+
options.encoding && typeof value === "string" ? options.encoding : undefined,
|
|
1692
|
+
);
|
|
1693
|
+
return { path: resolvedPath };
|
|
1694
|
+
},
|
|
1695
|
+
appendFile: async (targetPath, value, options = {}) => {
|
|
1696
|
+
const resolvedPath = this.#resolveFilesystemPath(targetPath);
|
|
1697
|
+
await mkdir(path.dirname(resolvedPath), { recursive: true });
|
|
1698
|
+
const existing = await readFile(resolvedPath).catch((error) => {
|
|
1699
|
+
if (error?.code === "ENOENT") {
|
|
1700
|
+
return Buffer.alloc(0);
|
|
1701
|
+
}
|
|
1702
|
+
throw error;
|
|
1703
|
+
});
|
|
1704
|
+
const nextChunk =
|
|
1705
|
+
typeof value === "string"
|
|
1706
|
+
? Buffer.from(value, options.encoding ?? "utf8")
|
|
1707
|
+
: Buffer.from(toUint8Array(value));
|
|
1708
|
+
await writeFile(resolvedPath, Buffer.concat([existing, nextChunk]));
|
|
1709
|
+
return { path: resolvedPath };
|
|
1710
|
+
},
|
|
1711
|
+
deleteFile: async (targetPath) => {
|
|
1712
|
+
const resolvedPath = this.#resolveFilesystemPath(targetPath);
|
|
1713
|
+
await rm(resolvedPath, { force: true });
|
|
1714
|
+
return { path: resolvedPath };
|
|
1715
|
+
},
|
|
1716
|
+
mkdir: async (targetPath, options = {}) => {
|
|
1717
|
+
const resolvedPath = this.#resolveFilesystemPath(targetPath);
|
|
1718
|
+
await mkdir(resolvedPath, {
|
|
1719
|
+
recursive: options.recursive ?? true,
|
|
1720
|
+
});
|
|
1721
|
+
return { path: resolvedPath };
|
|
1722
|
+
},
|
|
1723
|
+
readdir: async (targetPath = ".") => {
|
|
1724
|
+
const resolvedPath = this.#resolveFilesystemPath(targetPath);
|
|
1725
|
+
const entries = await readdir(resolvedPath, { withFileTypes: true });
|
|
1726
|
+
return entries
|
|
1727
|
+
.map((entry) => ({
|
|
1728
|
+
name: entry.name,
|
|
1729
|
+
isFile: entry.isFile(),
|
|
1730
|
+
isDirectory: entry.isDirectory(),
|
|
1731
|
+
}))
|
|
1732
|
+
.sort((left, right) => left.name.localeCompare(right.name));
|
|
1733
|
+
},
|
|
1734
|
+
stat: async (targetPath) => {
|
|
1735
|
+
const resolvedPath = this.#resolveFilesystemPath(targetPath);
|
|
1736
|
+
const metadata = await stat(resolvedPath);
|
|
1737
|
+
return {
|
|
1738
|
+
path: resolvedPath,
|
|
1739
|
+
size: metadata.size,
|
|
1740
|
+
isFile: metadata.isFile(),
|
|
1741
|
+
isDirectory: metadata.isDirectory(),
|
|
1742
|
+
ctimeMs: metadata.ctimeMs,
|
|
1743
|
+
mtimeMs: metadata.mtimeMs,
|
|
1744
|
+
};
|
|
1745
|
+
},
|
|
1746
|
+
rename: async (fromPath, toPath) => {
|
|
1747
|
+
const resolvedFrom = this.#resolveFilesystemPath(fromPath);
|
|
1748
|
+
const resolvedTo = this.#resolveFilesystemPath(toPath);
|
|
1749
|
+
await mkdir(path.dirname(resolvedTo), { recursive: true });
|
|
1750
|
+
await rename(resolvedFrom, resolvedTo);
|
|
1751
|
+
return { from: resolvedFrom, to: resolvedTo };
|
|
1752
|
+
},
|
|
1753
|
+
};
|
|
1754
|
+
const filesystem = this._filesystemAdapter ?? builtinFilesystem;
|
|
1755
|
+
|
|
1553
1756
|
this.mqtt = Object.freeze({
|
|
1554
1757
|
publish: async (mqttOptions = {}) =>
|
|
1555
1758
|
this.#withCapability("mqtt", "mqtt.publish", async () => {
|
|
@@ -1601,91 +1804,39 @@ export class NodeHost {
|
|
|
1601
1804
|
this.filesystem = Object.freeze({
|
|
1602
1805
|
resolvePath: (targetPath) =>
|
|
1603
1806
|
this.#withCapability("filesystem", "filesystem.resolvePath", () =>
|
|
1604
|
-
|
|
1807
|
+
filesystem.resolvePath(targetPath),
|
|
1605
1808
|
),
|
|
1606
1809
|
readFile: async (targetPath, options = {}) =>
|
|
1607
1810
|
this.#withCapability("filesystem", "filesystem.readFile", async () => {
|
|
1608
|
-
|
|
1609
|
-
const file = await readFile(resolvedPath);
|
|
1610
|
-
if (options.encoding) {
|
|
1611
|
-
return file.toString(options.encoding);
|
|
1612
|
-
}
|
|
1613
|
-
return new Uint8Array(file);
|
|
1811
|
+
return filesystem.readFile(targetPath, options);
|
|
1614
1812
|
}),
|
|
1615
1813
|
writeFile: async (targetPath, value, options = {}) =>
|
|
1616
1814
|
this.#withCapability("filesystem", "filesystem.writeFile", async () => {
|
|
1617
|
-
|
|
1618
|
-
await mkdir(path.dirname(resolvedPath), { recursive: true });
|
|
1619
|
-
await writeFile(
|
|
1620
|
-
resolvedPath,
|
|
1621
|
-
typeof value === "string" ? value : Buffer.from(toUint8Array(value)),
|
|
1622
|
-
options.encoding && typeof value === "string" ? options.encoding : undefined,
|
|
1623
|
-
);
|
|
1624
|
-
return { path: resolvedPath };
|
|
1815
|
+
return filesystem.writeFile(targetPath, value, options);
|
|
1625
1816
|
}),
|
|
1626
1817
|
appendFile: async (targetPath, value, options = {}) =>
|
|
1627
1818
|
this.#withCapability("filesystem", "filesystem.appendFile", async () => {
|
|
1628
|
-
|
|
1629
|
-
await mkdir(path.dirname(resolvedPath), { recursive: true });
|
|
1630
|
-
const existing = await readFile(resolvedPath).catch((error) => {
|
|
1631
|
-
if (error?.code === "ENOENT") {
|
|
1632
|
-
return Buffer.alloc(0);
|
|
1633
|
-
}
|
|
1634
|
-
throw error;
|
|
1635
|
-
});
|
|
1636
|
-
const nextChunk =
|
|
1637
|
-
typeof value === "string"
|
|
1638
|
-
? Buffer.from(value, options.encoding ?? "utf8")
|
|
1639
|
-
: Buffer.from(toUint8Array(value));
|
|
1640
|
-
await writeFile(resolvedPath, Buffer.concat([existing, nextChunk]));
|
|
1641
|
-
return { path: resolvedPath };
|
|
1819
|
+
return filesystem.appendFile(targetPath, value, options);
|
|
1642
1820
|
}),
|
|
1643
1821
|
deleteFile: async (targetPath) =>
|
|
1644
1822
|
this.#withCapability("filesystem", "filesystem.deleteFile", async () => {
|
|
1645
|
-
|
|
1646
|
-
await rm(resolvedPath, { force: true });
|
|
1647
|
-
return { path: resolvedPath };
|
|
1823
|
+
return filesystem.deleteFile(targetPath);
|
|
1648
1824
|
}),
|
|
1649
1825
|
mkdir: async (targetPath, options = {}) =>
|
|
1650
1826
|
this.#withCapability("filesystem", "filesystem.mkdir", async () => {
|
|
1651
|
-
|
|
1652
|
-
await mkdir(resolvedPath, {
|
|
1653
|
-
recursive: options.recursive ?? true,
|
|
1654
|
-
});
|
|
1655
|
-
return { path: resolvedPath };
|
|
1827
|
+
return filesystem.mkdir(targetPath, options);
|
|
1656
1828
|
}),
|
|
1657
1829
|
readdir: async (targetPath = ".") =>
|
|
1658
1830
|
this.#withCapability("filesystem", "filesystem.readdir", async () => {
|
|
1659
|
-
|
|
1660
|
-
const entries = await readdir(resolvedPath, { withFileTypes: true });
|
|
1661
|
-
return entries
|
|
1662
|
-
.map((entry) => ({
|
|
1663
|
-
name: entry.name,
|
|
1664
|
-
isFile: entry.isFile(),
|
|
1665
|
-
isDirectory: entry.isDirectory(),
|
|
1666
|
-
}))
|
|
1667
|
-
.sort((left, right) => left.name.localeCompare(right.name));
|
|
1831
|
+
return filesystem.readdir(targetPath);
|
|
1668
1832
|
}),
|
|
1669
1833
|
stat: async (targetPath) =>
|
|
1670
1834
|
this.#withCapability("filesystem", "filesystem.stat", async () => {
|
|
1671
|
-
|
|
1672
|
-
const metadata = await stat(resolvedPath);
|
|
1673
|
-
return {
|
|
1674
|
-
path: resolvedPath,
|
|
1675
|
-
size: metadata.size,
|
|
1676
|
-
isFile: metadata.isFile(),
|
|
1677
|
-
isDirectory: metadata.isDirectory(),
|
|
1678
|
-
ctimeMs: metadata.ctimeMs,
|
|
1679
|
-
mtimeMs: metadata.mtimeMs,
|
|
1680
|
-
};
|
|
1835
|
+
return filesystem.stat(targetPath);
|
|
1681
1836
|
}),
|
|
1682
1837
|
rename: async (fromPath, toPath) =>
|
|
1683
1838
|
this.#withCapability("filesystem", "filesystem.rename", async () => {
|
|
1684
|
-
|
|
1685
|
-
const resolvedTo = this.#resolveFilesystemPath(toPath);
|
|
1686
|
-
await mkdir(path.dirname(resolvedTo), { recursive: true });
|
|
1687
|
-
await rename(resolvedFrom, resolvedTo);
|
|
1688
|
-
return { from: resolvedFrom, to: resolvedTo };
|
|
1839
|
+
return filesystem.rename(fromPath, toPath);
|
|
1689
1840
|
}),
|
|
1690
1841
|
});
|
|
1691
1842
|
|
|
@@ -1825,6 +1976,80 @@ export class NodeHost {
|
|
|
1825
1976
|
this._contextStore.listScopes(),
|
|
1826
1977
|
),
|
|
1827
1978
|
});
|
|
1979
|
+
|
|
1980
|
+
this.ipfs = Object.freeze({
|
|
1981
|
+
invoke: async (params = {}) =>
|
|
1982
|
+
this.#withCapability("ipfs", "ipfs.invoke", async () => {
|
|
1983
|
+
const operation = String(params.operation ?? "invoke").trim();
|
|
1984
|
+
if (!operation) {
|
|
1985
|
+
throw new Error("ipfs.invoke requires a non-empty operation.");
|
|
1986
|
+
}
|
|
1987
|
+
return invokeAdapterMethod(this._ipfsAdapter, operation, params, "ipfs");
|
|
1988
|
+
}),
|
|
1989
|
+
add: async (params = {}) =>
|
|
1990
|
+
this.#withCapability("ipfs", "ipfs.add", async () =>
|
|
1991
|
+
invokeAdapterMethod(this._ipfsAdapter, "add", params, "ipfs"),
|
|
1992
|
+
),
|
|
1993
|
+
cat: async (params = {}) =>
|
|
1994
|
+
this.#withCapability("ipfs", "ipfs.cat", async () =>
|
|
1995
|
+
invokeAdapterMethod(this._ipfsAdapter, "cat", params, "ipfs"),
|
|
1996
|
+
),
|
|
1997
|
+
});
|
|
1998
|
+
|
|
1999
|
+
this.protocolHandle = Object.freeze({
|
|
2000
|
+
register: async (params = {}) =>
|
|
2001
|
+
this.#withCapability(
|
|
2002
|
+
"protocol_handle",
|
|
2003
|
+
"protocol_handle.register",
|
|
2004
|
+
async () =>
|
|
2005
|
+
invokeAdapterMethod(
|
|
2006
|
+
this._protocolHandleAdapter,
|
|
2007
|
+
"register",
|
|
2008
|
+
params,
|
|
2009
|
+
"protocol_handle",
|
|
2010
|
+
),
|
|
2011
|
+
),
|
|
2012
|
+
unregister: async (params = {}) =>
|
|
2013
|
+
this.#withCapability(
|
|
2014
|
+
"protocol_handle",
|
|
2015
|
+
"protocol_handle.unregister",
|
|
2016
|
+
async () =>
|
|
2017
|
+
invokeAdapterMethod(
|
|
2018
|
+
this._protocolHandleAdapter,
|
|
2019
|
+
"unregister",
|
|
2020
|
+
params,
|
|
2021
|
+
"protocol_handle",
|
|
2022
|
+
),
|
|
2023
|
+
),
|
|
2024
|
+
});
|
|
2025
|
+
|
|
2026
|
+
this.protocolDial = Object.freeze({
|
|
2027
|
+
dial: async (params = {}) =>
|
|
2028
|
+
this.#withCapability("protocol_dial", "protocol_dial.dial", async () =>
|
|
2029
|
+
invokeAdapterMethod(
|
|
2030
|
+
this._protocolDialAdapter,
|
|
2031
|
+
"dial",
|
|
2032
|
+
params,
|
|
2033
|
+
"protocol_dial",
|
|
2034
|
+
),
|
|
2035
|
+
),
|
|
2036
|
+
request: async (params = {}) =>
|
|
2037
|
+
this.#withCapability("protocol_dial", "protocol.request", async () =>
|
|
2038
|
+
invokeAdapterMethod(
|
|
2039
|
+
this._protocolDialAdapter,
|
|
2040
|
+
"request",
|
|
2041
|
+
params,
|
|
2042
|
+
"protocol_dial",
|
|
2043
|
+
),
|
|
2044
|
+
),
|
|
2045
|
+
});
|
|
2046
|
+
|
|
2047
|
+
this.keyslot = Object.freeze({
|
|
2048
|
+
get: async (params = {}) =>
|
|
2049
|
+
this.#withCapability("wallet_sign", "keyslot.get", async () =>
|
|
2050
|
+
invokeAdapterMethod(this._walletSignAdapter, "get", params, "wallet_sign"),
|
|
2051
|
+
),
|
|
2052
|
+
});
|
|
1828
2053
|
}
|
|
1829
2054
|
|
|
1830
2055
|
listCapabilities() {
|
|
@@ -1840,11 +2065,26 @@ export class NodeHost {
|
|
|
1840
2065
|
}
|
|
1841
2066
|
|
|
1842
2067
|
hasCapability(capability) {
|
|
1843
|
-
|
|
2068
|
+
const normalized = String(capability ?? "").trim();
|
|
2069
|
+
return (
|
|
2070
|
+
this._grantedCapabilities.has(normalized) ||
|
|
2071
|
+
(this._grantedCapabilities.has("network") &&
|
|
2072
|
+
["http", "websocket", "mqtt", "tcp", "udp", "tls"].includes(
|
|
2073
|
+
normalized,
|
|
2074
|
+
))
|
|
2075
|
+
);
|
|
1844
2076
|
}
|
|
1845
2077
|
|
|
1846
2078
|
assertCapability(capability, operation = null) {
|
|
1847
2079
|
const normalized = assertNonEmptyString(capability, "Capability id");
|
|
2080
|
+
const networkBackedCapabilities = new Set([
|
|
2081
|
+
"http",
|
|
2082
|
+
"websocket",
|
|
2083
|
+
"mqtt",
|
|
2084
|
+
"tcp",
|
|
2085
|
+
"udp",
|
|
2086
|
+
"tls",
|
|
2087
|
+
]);
|
|
1848
2088
|
if (!this._supportedCapabilities.has(normalized)) {
|
|
1849
2089
|
throw new HostCapabilityError(
|
|
1850
2090
|
`Capability "${normalized}" is not supported by the reference Node host.`,
|
|
@@ -1855,7 +2095,13 @@ export class NodeHost {
|
|
|
1855
2095
|
},
|
|
1856
2096
|
);
|
|
1857
2097
|
}
|
|
1858
|
-
if (
|
|
2098
|
+
if (
|
|
2099
|
+
!this._grantedCapabilities.has(normalized) &&
|
|
2100
|
+
!(
|
|
2101
|
+
this._grantedCapabilities.has("network") &&
|
|
2102
|
+
networkBackedCapabilities.has(normalized)
|
|
2103
|
+
)
|
|
2104
|
+
) {
|
|
1859
2105
|
throw new HostCapabilityError(
|
|
1860
2106
|
`Capability "${normalized}" is not granted for this Node host.`,
|
|
1861
2107
|
{
|
|
@@ -1871,6 +2117,16 @@ export class NodeHost {
|
|
|
1871
2117
|
async invoke(operation, params = {}) {
|
|
1872
2118
|
const normalized = assertNonEmptyString(operation, "Host operation");
|
|
1873
2119
|
switch (normalized) {
|
|
2120
|
+
case "host.runtimeTarget":
|
|
2121
|
+
return this.runtimeTarget;
|
|
2122
|
+
case "host.listCapabilities":
|
|
2123
|
+
return this.listCapabilities();
|
|
2124
|
+
case "host.listSupportedCapabilities":
|
|
2125
|
+
return this.listSupportedCapabilities();
|
|
2126
|
+
case "host.listOperations":
|
|
2127
|
+
return this.listOperations();
|
|
2128
|
+
case "host.hasCapability":
|
|
2129
|
+
return this.hasCapability(params.capability);
|
|
1874
2130
|
case "clock.now":
|
|
1875
2131
|
return this.clock.now();
|
|
1876
2132
|
case "clock.monotonicNow":
|
|
@@ -1897,6 +2153,8 @@ export class NodeHost {
|
|
|
1897
2153
|
return this.mqtt.publish(params);
|
|
1898
2154
|
case "mqtt.subscribeOnce":
|
|
1899
2155
|
return this.mqtt.subscribeOnce(params);
|
|
2156
|
+
case "network.request":
|
|
2157
|
+
return this.network.request(params);
|
|
1900
2158
|
case "filesystem.resolvePath":
|
|
1901
2159
|
return this.filesystem.resolvePath(params.path);
|
|
1902
2160
|
case "filesystem.readFile":
|
|
@@ -1929,6 +2187,22 @@ export class NodeHost {
|
|
|
1929
2187
|
return this.udp.request(params);
|
|
1930
2188
|
case "tls.request":
|
|
1931
2189
|
return this.tls.request(params);
|
|
2190
|
+
case "ipfs.invoke":
|
|
2191
|
+
return this.ipfs.invoke(params);
|
|
2192
|
+
case "ipfs.add":
|
|
2193
|
+
return this.ipfs.add(params);
|
|
2194
|
+
case "ipfs.cat":
|
|
2195
|
+
return this.ipfs.cat(params);
|
|
2196
|
+
case "protocol_handle.register":
|
|
2197
|
+
return this.protocolHandle.register(params);
|
|
2198
|
+
case "protocol_handle.unregister":
|
|
2199
|
+
return this.protocolHandle.unregister(params);
|
|
2200
|
+
case "protocol_dial.dial":
|
|
2201
|
+
return this.protocolDial.dial(params);
|
|
2202
|
+
case "protocol.request":
|
|
2203
|
+
return this.protocolDial.request(params);
|
|
2204
|
+
case "keyslot.get":
|
|
2205
|
+
return this.keyslot.get(params);
|
|
1932
2206
|
case "exec.execFile":
|
|
1933
2207
|
return this.exec.execFile(params);
|
|
1934
2208
|
case "context.get":
|