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.
Files changed (65) hide show
  1. package/README.md +22 -2
  2. package/package.json +2 -2
  3. package/schemas/orbpro/BaseTypes.fbs +7 -0
  4. package/schemas/orbpro/CatalogQueryBase.fbs +8 -0
  5. package/schemas/orbpro/CatalogQueryRequest.fbs +14 -0
  6. package/schemas/orbpro/CatalogQueryResult.fbs +17 -0
  7. package/schemas/orbpro/EntityMetadata.fbs +53 -0
  8. package/schemas/orbpro/EntityStandardsLink.fbs +18 -0
  9. package/schemas/orbpro/Plugin.fbs +8 -0
  10. package/schemas/orbpro/Propagator.fbs +89 -0
  11. package/schemas/orbpro/StandardsRecordIndex.fbs +15 -0
  12. package/src/generated/orbpro/entity/entity-kind.js +15 -0
  13. package/src/generated/orbpro/entity/entity-kind.ts +15 -0
  14. package/src/generated/orbpro/entity/entity-metadata.js +322 -0
  15. package/src/generated/orbpro/entity/entity-metadata.ts +426 -0
  16. package/src/generated/orbpro/entity/entity-standards-link.js +143 -0
  17. package/src/generated/orbpro/entity/entity-standards-link.ts +183 -0
  18. package/src/generated/orbpro/entity/standards-record-index.js +115 -0
  19. package/src/generated/orbpro/entity/standards-record-index.ts +147 -0
  20. package/src/generated/orbpro/entity.js +10 -0
  21. package/src/generated/orbpro/entity.ts +5 -0
  22. package/src/generated/orbpro/plugin/raw-data-payload.js +79 -0
  23. package/src/generated/orbpro/plugin/raw-data-payload.ts +92 -0
  24. package/src/generated/orbpro/plugin.js +4 -0
  25. package/src/generated/orbpro/plugin.ts +5 -0
  26. package/src/generated/orbpro/propagator/propagator-describe-sources-batch-request.js +79 -0
  27. package/src/generated/orbpro/propagator/propagator-describe-sources-batch-request.ts +95 -0
  28. package/src/generated/orbpro/propagator/propagator-describe-sources-batch-result.js +70 -0
  29. package/src/generated/orbpro/propagator/propagator-describe-sources-batch-result.ts +78 -0
  30. package/src/generated/orbpro/propagator/propagator-sample-trajectory-states-request.js +97 -0
  31. package/src/generated/orbpro/propagator/propagator-sample-trajectory-states-request.ts +117 -0
  32. package/src/generated/orbpro/propagator/propagator-sample-trajectory-states-result.js +140 -0
  33. package/src/generated/orbpro/propagator/propagator-sample-trajectory-states-result.ts +175 -0
  34. package/src/generated/orbpro/propagator/propagator-source-description.js +208 -0
  35. package/src/generated/orbpro/propagator/propagator-source-description.ts +257 -0
  36. package/src/generated/orbpro/propagator/propagator-source-kind.js +8 -0
  37. package/src/generated/orbpro/propagator/propagator-source-kind.ts +8 -0
  38. package/src/generated/orbpro/propagator/reference-frame.js +12 -0
  39. package/src/generated/orbpro/propagator/reference-frame.ts +12 -0
  40. package/src/generated/orbpro/propagator/state-flags.js +13 -0
  41. package/src/generated/orbpro/propagator/state-flags.ts +13 -0
  42. package/src/generated/orbpro/propagator/state-vector.js +55 -0
  43. package/src/generated/orbpro/propagator/state-vector.ts +61 -0
  44. package/src/generated/orbpro/propagator.js +20 -0
  45. package/src/generated/orbpro/propagator.ts +13 -0
  46. package/src/generated/orbpro/query/catalog-query-kind.js +10 -0
  47. package/src/generated/orbpro/query/catalog-query-kind.ts +10 -0
  48. package/src/generated/orbpro/query/catalog-query-request.js +89 -0
  49. package/src/generated/orbpro/query/catalog-query-request.ts +105 -0
  50. package/src/generated/orbpro/query/catalog-query-result.js +145 -0
  51. package/src/generated/orbpro/query/catalog-query-result.ts +179 -0
  52. package/src/generated/orbpro/query.js +8 -0
  53. package/src/generated/orbpro/query.ts +4 -0
  54. package/src/generated/orbpro/vec3.js +39 -0
  55. package/src/generated/orbpro/vec3.ts +40 -0
  56. package/src/host/abi.js +189 -3
  57. package/src/host/browserEdgeShims.js +17 -0
  58. package/src/host/browserHost.js +486 -40
  59. package/src/host/isomorphicLoader.js +44 -20
  60. package/src/host/nodeHost.js +337 -63
  61. package/src/index.d.ts +99 -3
  62. package/src/runtime-host/index.js +90 -0
  63. package/src/testing/browserModuleHarness.js +22 -3
  64. package/src/testing/index.d.ts +1 -0
  65. 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 createWasmEdgeCommandHarness(options);
193
+ return attachHostDispatch(
194
+ await createWasmEdgeCommandHarness(options),
195
+ options.host ?? null,
196
+ );
179
197
  }
180
198
  }
181
199
 
182
- return createModuleHarness({
183
- runtime: {
184
- kind: "wasmedge",
185
- wasmPath: source,
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
- metadata: options.metadata,
195
- },
196
- });
213
+ metadata: options.metadata,
214
+ },
215
+ }),
216
+ options.host ?? null,
217
+ );
197
218
  }
198
219
 
199
- return createModuleHarness({
200
- runtime: {
201
- kind: runtimeKind,
202
- command: options.command ?? runtimeKind,
203
- args: options.args ?? [source],
204
- env: options.env,
205
- cwd: options.cwd,
206
- hostProfile: options.hostProfile,
207
- modules: options.modules,
208
- defaultModuleId: options.defaultModuleId,
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
  /**
@@ -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
- this.#resolveFilesystemPath(targetPath),
1807
+ filesystem.resolvePath(targetPath),
1605
1808
  ),
1606
1809
  readFile: async (targetPath, options = {}) =>
1607
1810
  this.#withCapability("filesystem", "filesystem.readFile", async () => {
1608
- const resolvedPath = this.#resolveFilesystemPath(targetPath);
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
- const resolvedPath = this.#resolveFilesystemPath(targetPath);
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
- const resolvedPath = this.#resolveFilesystemPath(targetPath);
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
- const resolvedPath = this.#resolveFilesystemPath(targetPath);
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
- const resolvedPath = this.#resolveFilesystemPath(targetPath);
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
- const resolvedPath = this.#resolveFilesystemPath(targetPath);
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
- const resolvedPath = this.#resolveFilesystemPath(targetPath);
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
- const resolvedFrom = this.#resolveFilesystemPath(fromPath);
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
- return this._grantedCapabilities.has(String(capability ?? "").trim());
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 (!this._grantedCapabilities.has(normalized)) {
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":