space-data-module-sdk 0.5.15 → 0.5.18

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 (37) hide show
  1. package/README.md +24 -0
  2. package/package.json +8 -4
  3. package/schemas/HostStorageAbi.fbs +53 -0
  4. package/src/bundle/codec.js +1 -1
  5. package/src/compliance/pluginCompliance.js +1 -1
  6. package/src/generated/orbpro/invoke/plugin-invoke-request.js +1 -1
  7. package/src/generated/orbpro/invoke/plugin-invoke-response.js +1 -1
  8. package/src/generated/orbpro/manifest/accepted-type-set.js +1 -1
  9. package/src/generated/orbpro/manifest/build-artifact.js +1 -1
  10. package/src/generated/orbpro/manifest/host-capability.js +1 -1
  11. package/src/generated/orbpro/manifest/method-manifest.js +1 -1
  12. package/src/generated/orbpro/manifest/plugin-manifest.js +1 -1
  13. package/src/generated/orbpro/manifest/port-manifest.js +1 -1
  14. package/src/generated/orbpro/manifest/protocol-spec.js +1 -1
  15. package/src/generated/orbpro/manifest/timer-spec.js +1 -1
  16. package/src/generated/orbpro/module/canonicalization-rule.js +1 -1
  17. package/src/generated/orbpro/module/module-bundle-entry.js +1 -1
  18. package/src/generated/orbpro/module/module-bundle.js +1 -1
  19. package/src/generated/orbpro/stream/flat-buffer-type-ref.js +1 -1
  20. package/src/generated/orbpro/stream/typed-arena-buffer.js +1 -1
  21. package/src/index.d.ts +139 -0
  22. package/src/index.js +1 -0
  23. package/src/invoke/codec.js +1 -1
  24. package/src/manifest/codec.js +1 -1
  25. package/src/manifest/typeRefs.js +49 -12
  26. package/src/runtime-host/flatsqlRuntimeStore.js +217 -0
  27. package/src/runtime-host/index.js +21 -0
  28. package/src/runtime-host/moduleRegistry.js +92 -0
  29. package/src/runtime-host/runtimeRegionStore.js +245 -0
  30. package/src/testing/buildWasmEdgeRunner.js +41 -2
  31. package/src/testing/index.d.ts +123 -2
  32. package/src/testing/index.js +1 -0
  33. package/src/testing/moduleHarness.js +102 -1
  34. package/src/testing/native/wasmedge_emscripten_pthread_runner.c +2319 -209
  35. package/src/testing/processInvoke.js +250 -9
  36. package/src/testing/streamInvokeCodec.js +175 -0
  37. package/src/transport/records.js +19 -6
@@ -131,7 +131,55 @@ export interface PluginInvokeProcessLaunchPlan {
131
131
  args: string[];
132
132
  env?: Record<string, string | undefined>;
133
133
  cwd?: string;
134
- wasmPath?: string;
134
+ wasmPath?: string | null;
135
+ hostProfile?: "runtime-host";
136
+ }
137
+
138
+ export interface RuntimeHostTestModuleDefinition {
139
+ moduleId: string;
140
+ wasmPath?: string | null;
141
+ metadata?: unknown;
142
+ [key: string]: unknown;
143
+ }
144
+
145
+ export interface RuntimeHostInstalledModule {
146
+ moduleId: string;
147
+ metadata: unknown;
148
+ methodIds: string[];
149
+ }
150
+
151
+ export interface RuntimeHostRowHandle {
152
+ schemaFileId: string;
153
+ rowId: number;
154
+ }
155
+
156
+ export interface RuntimeHostRowView {
157
+ handle: RuntimeHostRowHandle;
158
+ payload: unknown;
159
+ }
160
+
161
+ export interface RuntimeHostRowQueryResult {
162
+ columns: string[];
163
+ rows: unknown[][];
164
+ rowCount: number;
165
+ }
166
+
167
+ export interface RuntimeHostRegionDescriptor {
168
+ regionId: number;
169
+ layoutId: string;
170
+ recordByteLength: number;
171
+ alignment: number;
172
+ recordCount: number;
173
+ }
174
+
175
+ export interface RuntimeHostRegionRecord {
176
+ regionId: number;
177
+ recordIndex: number;
178
+ layoutId: string;
179
+ recordByteLength: number;
180
+ alignment: number;
181
+ byteLength: number;
182
+ bytes: Uint8Array;
135
183
  }
136
184
 
137
185
  export interface PluginInvokeProcessClient {
@@ -140,12 +188,42 @@ export interface PluginInvokeProcessClient {
140
188
  invoke(request: {
141
189
  methodId?: string | null;
142
190
  inputs?: HarnessInputFrame[];
191
+ }): Promise<{
192
+ statusCode: number;
193
+ errorCode?: string | null;
194
+ errorMessage?: string | null;
195
+ outputs: HarnessInputFrame[];
196
+ }>;
197
+ installModule(definition: RuntimeHostTestModuleDefinition): Promise<RuntimeHostInstalledModule>;
198
+ listModules(): Promise<RuntimeHostInstalledModule[]>;
199
+ unloadModule(moduleId: string): Promise<boolean>;
200
+ invokeModule(requestModuleId: string, request: {
201
+ methodId?: string | null;
202
+ inputs?: HarnessInputFrame[];
143
203
  }): Promise<{
144
204
  statusCode: number;
145
205
  errorCode?: string | null;
146
206
  errorMessage?: string | null;
147
207
  outputs: HarnessInputFrame[];
148
208
  }>;
209
+ appendRow(options: {
210
+ schemaFileId: string;
211
+ payload?: unknown;
212
+ }): Promise<RuntimeHostRowHandle>;
213
+ listRows(schemaFileId?: string | null): Promise<RuntimeHostRowView[]>;
214
+ resolveRow(handle: RuntimeHostRowHandle): Promise<RuntimeHostRowView | null>;
215
+ queryRows(sql: string): Promise<RuntimeHostRowQueryResult>;
216
+ allocateRegion(options: {
217
+ layoutId: string;
218
+ recordByteLength: number;
219
+ alignment?: number;
220
+ initialRecords?: Array<Uint8Array | ArrayBuffer | ArrayBufferView | null | undefined>;
221
+ }): Promise<RuntimeHostRegionDescriptor>;
222
+ describeRegion(regionId: number): Promise<RuntimeHostRegionDescriptor | null>;
223
+ resolveRecord(query: {
224
+ regionId: number;
225
+ recordIndex: number;
226
+ }): Promise<RuntimeHostRegionRecord | null>;
149
227
  destroy(): Promise<void>;
150
228
  }
151
229
 
@@ -160,6 +238,10 @@ export interface ModuleHarnessRuntimeDescriptor {
160
238
  wasmEdgeBinary?: string;
161
239
  wasmEdgeRunnerBinary?: string;
162
240
  enableThreads?: boolean;
241
+ hostProfile?: "runtime-host";
242
+ modules?: RuntimeHostTestModuleDefinition[];
243
+ defaultModuleId?: string;
244
+ metadata?: unknown;
163
245
  }
164
246
 
165
247
  export interface ModuleHarness {
@@ -169,12 +251,42 @@ export interface ModuleHarness {
169
251
  invoke(request: {
170
252
  methodId?: string | null;
171
253
  inputs?: HarnessInputFrame[];
254
+ }): Promise<{
255
+ statusCode: number;
256
+ errorCode?: string | null;
257
+ errorMessage?: string | null;
258
+ outputs: HarnessInputFrame[];
259
+ }>;
260
+ installModule(definition: RuntimeHostTestModuleDefinition): Promise<RuntimeHostInstalledModule>;
261
+ listModules(): Promise<RuntimeHostInstalledModule[]>;
262
+ unloadModule(moduleId: string): Promise<boolean>;
263
+ invokeModule(moduleId: string, request: {
264
+ methodId?: string | null;
265
+ inputs?: HarnessInputFrame[];
172
266
  }): Promise<{
173
267
  statusCode: number;
174
268
  errorCode?: string | null;
175
269
  errorMessage?: string | null;
176
270
  outputs: HarnessInputFrame[];
177
271
  }>;
272
+ appendRow(options: {
273
+ schemaFileId: string;
274
+ payload?: unknown;
275
+ }): Promise<RuntimeHostRowHandle>;
276
+ listRows(schemaFileId?: string | null): Promise<RuntimeHostRowView[]>;
277
+ resolveRow(handle: RuntimeHostRowHandle): Promise<RuntimeHostRowView | null>;
278
+ queryRows(sql: string): Promise<RuntimeHostRowQueryResult>;
279
+ allocateRegion(options: {
280
+ layoutId: string;
281
+ recordByteLength: number;
282
+ alignment?: number;
283
+ initialRecords?: Array<Uint8Array | ArrayBuffer | ArrayBufferView | null | undefined>;
284
+ }): Promise<RuntimeHostRegionDescriptor>;
285
+ describeRegion(regionId: number): Promise<RuntimeHostRegionDescriptor | null>;
286
+ resolveRecord(query: {
287
+ regionId: number;
288
+ recordIndex: number;
289
+ }): Promise<RuntimeHostRegionRecord | null>;
178
290
  destroy(): Promise<void>;
179
291
  }
180
292
 
@@ -234,12 +346,13 @@ export function buildWasmEdgeSpawnEnv(
234
346
  ): Record<string, string | undefined>;
235
347
 
236
348
  export function resolveWasmEdgePluginLaunchPlan(options: {
237
- wasmPath: string;
349
+ wasmPath?: string;
238
350
  wasmEdgeBinary?: string;
239
351
  wasmEdgeRunnerBinary?: string;
240
352
  enableThreads?: boolean;
241
353
  invokeArgs?: string[];
242
354
  env?: Record<string, string | undefined>;
355
+ hostProfile?: "runtime-host";
243
356
  }): PluginInvokeProcessLaunchPlan;
244
357
 
245
358
  export function createPluginInvokeProcessClient(options: {
@@ -250,6 +363,14 @@ export function createPluginInvokeProcessClient(options: {
250
363
  cwd?: string;
251
364
  }): Promise<PluginInvokeProcessClient>;
252
365
 
366
+ export function createWasmEdgeStreamProcessClient(options: {
367
+ launchPlan?: PluginInvokeProcessLaunchPlan;
368
+ command?: string;
369
+ args?: string[];
370
+ env?: Record<string, string | undefined>;
371
+ cwd?: string;
372
+ }): Promise<PluginInvokeProcessClient>;
373
+
253
374
  export function resolveModuleHarnessLaunchPlan(options: {
254
375
  runtime?: ModuleHarnessRuntimeDescriptor;
255
376
  } | ModuleHarnessRuntimeDescriptor): PluginInvokeProcessLaunchPlan;
@@ -10,6 +10,7 @@ export {
10
10
  export {
11
11
  buildWasmEdgeSpawnEnv,
12
12
  createPluginInvokeProcessClient,
13
+ createWasmEdgeStreamProcessClient,
13
14
  resolveWasmEdgePluginLaunchPlan,
14
15
  } from "./processInvoke.js";
15
16
  export {
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  createPluginInvokeProcessClient,
3
+ createWasmEdgeStreamProcessClient,
3
4
  resolveWasmEdgePluginLaunchPlan,
4
5
  } from "./processInvoke.js";
5
6
 
@@ -10,6 +11,15 @@ function normalizeRuntimeDescriptor(options = {}) {
10
11
  return options;
11
12
  }
12
13
 
14
+ function isRuntimeHostProfile(runtime = {}) {
15
+ return (
16
+ String(runtime.hostProfile ?? "").trim().toLowerCase() === "runtime-host" ||
17
+ Array.isArray(runtime.modules) ||
18
+ (typeof runtime.defaultModuleId === "string" &&
19
+ runtime.defaultModuleId.trim().length > 0)
20
+ );
21
+ }
22
+
13
23
  export function resolveModuleHarnessLaunchPlan(options = {}) {
14
24
  const runtime = normalizeRuntimeDescriptor(options);
15
25
  if (runtime.launchPlan && typeof runtime.launchPlan === "object") {
@@ -41,20 +51,111 @@ export async function createModuleHarness(options = {}) {
41
51
  const runtime = normalizeRuntimeDescriptor(options);
42
52
  const kind = String(runtime.kind ?? "process").trim().toLowerCase();
43
53
  const launchPlan = resolveModuleHarnessLaunchPlan(options);
44
- const processClient = await createPluginInvokeProcessClient({ launchPlan });
54
+ const runtimeHost = isRuntimeHostProfile(runtime);
55
+ const processClient =
56
+ kind === "wasmedge"
57
+ ? await createWasmEdgeStreamProcessClient({ launchPlan })
58
+ : await createPluginInvokeProcessClient({ launchPlan });
59
+ const configuredModules = Array.isArray(runtime.modules) ? [...runtime.modules] : [];
60
+ if (
61
+ kind === "wasmedge" &&
62
+ runtimeHost &&
63
+ configuredModules.length === 0 &&
64
+ typeof runtime.wasmPath === "string" &&
65
+ runtime.wasmPath.trim().length > 0
66
+ ) {
67
+ configuredModules.push({
68
+ moduleId:
69
+ typeof runtime.defaultModuleId === "string" &&
70
+ runtime.defaultModuleId.trim().length > 0
71
+ ? runtime.defaultModuleId.trim()
72
+ : "default",
73
+ wasmPath: runtime.wasmPath,
74
+ metadata: runtime.metadata ?? null,
75
+ });
76
+ }
77
+
78
+ for (const moduleDefinition of configuredModules) {
79
+ await processClient.installModule(moduleDefinition);
80
+ }
81
+
82
+ let defaultModuleId =
83
+ typeof runtime.defaultModuleId === "string" && runtime.defaultModuleId.trim().length > 0
84
+ ? runtime.defaultModuleId.trim()
85
+ : configuredModules[0]?.moduleId ?? null;
45
86
 
46
87
  return {
47
88
  runtime: {
48
89
  ...runtime,
49
90
  kind,
91
+ hostProfile: runtimeHost ? "runtime-host" : runtime.hostProfile,
50
92
  },
51
93
  launchPlan,
52
94
  invokeRaw(requestBytes) {
53
95
  return processClient.invokeRaw(requestBytes);
54
96
  },
55
97
  invoke(request) {
98
+ if (runtimeHost) {
99
+ if (!defaultModuleId) {
100
+ throw new Error(
101
+ "Runtime-host invoke() requires an installed defaultModuleId.",
102
+ );
103
+ }
104
+ return processClient.invokeModule(defaultModuleId, request);
105
+ }
56
106
  return processClient.invoke(request);
57
107
  },
108
+ async installModule(definition) {
109
+ const installed = await processClient.installModule(definition);
110
+ if (
111
+ runtimeHost &&
112
+ (!defaultModuleId || defaultModuleId.trim().length === 0) &&
113
+ typeof installed?.moduleId === "string" &&
114
+ installed.moduleId.trim().length > 0
115
+ ) {
116
+ defaultModuleId = installed.moduleId.trim();
117
+ }
118
+ return installed;
119
+ },
120
+ listModules() {
121
+ return processClient.listModules();
122
+ },
123
+ async unloadModule(moduleId) {
124
+ const unloaded = await processClient.unloadModule(moduleId);
125
+ if (unloaded && moduleId === defaultModuleId) {
126
+ if (runtimeHost) {
127
+ const remainingModules = await processClient.listModules();
128
+ defaultModuleId = remainingModules[0]?.moduleId ?? null;
129
+ } else {
130
+ defaultModuleId = null;
131
+ }
132
+ }
133
+ return unloaded;
134
+ },
135
+ invokeModule(moduleId, request) {
136
+ return processClient.invokeModule(moduleId, request);
137
+ },
138
+ appendRow(options) {
139
+ return processClient.appendRow(options);
140
+ },
141
+ listRows(schemaFileId = null) {
142
+ return processClient.listRows(schemaFileId);
143
+ },
144
+ resolveRow(handle) {
145
+ return processClient.resolveRow(handle);
146
+ },
147
+ queryRows(sql) {
148
+ return processClient.queryRows(sql);
149
+ },
150
+ allocateRegion(options) {
151
+ return processClient.allocateRegion(options);
152
+ },
153
+ describeRegion(regionId) {
154
+ return processClient.describeRegion(regionId);
155
+ },
156
+ resolveRecord(query) {
157
+ return processClient.resolveRecord(query);
158
+ },
58
159
  destroy() {
59
160
  return processClient.destroy();
60
161
  },