space-data-module-sdk 0.5.14 → 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 +91 -1
  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 +0 -130
  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 +157 -1
  22. package/src/index.js +1 -0
  23. package/src/invoke/codec.js +10 -8
  24. package/src/manifest/codec.js +1 -1
  25. package/src/runtime-host/flatsqlRuntimeStore.js +217 -0
  26. package/src/runtime-host/index.js +21 -0
  27. package/src/runtime-host/moduleRegistry.js +92 -0
  28. package/src/runtime-host/runtimeRegionStore.js +245 -0
  29. package/src/testing/buildWasmEdgeRunner.js +253 -0
  30. package/src/testing/index.d.ts +311 -0
  31. package/src/testing/index.js +21 -0
  32. package/src/testing/moduleHarness.js +163 -0
  33. package/src/testing/native/wasmedge_emscripten_pthread_runner.c +3111 -0
  34. package/src/testing/processInvoke.js +467 -0
  35. package/src/testing/publicationProtectionDemo.js +271 -0
  36. package/src/testing/streamInvokeCodec.js +175 -0
  37. package/src/transport/records.js +56 -55
@@ -57,10 +57,266 @@ export interface ManifestHarnessPlan {
57
57
  scenarios: Array<HarnessInvokeScenario | HarnessRawScenario>;
58
58
  }
59
59
 
60
+ export interface PublicationProtectionDemoAlignedType {
61
+ methodId: string | null;
62
+ portId: string | null;
63
+ setId: string | null;
64
+ schemaName: string | null;
65
+ fileIdentifier: string | null;
66
+ rootTypeName: string | null;
67
+ byteLength: number | null;
68
+ requiredAlignment: number | null;
69
+ hasFlatbufferFallback: boolean;
70
+ }
71
+
72
+ export interface PublicationProtectionDemoSummary {
73
+ manifest: PluginManifest;
74
+ recTrailer: {
75
+ fileIdentifier: string;
76
+ version: string | null;
77
+ recordCount: number;
78
+ recordStandards: Array<string | null>;
79
+ usesStandardsFlatbuffers: boolean;
80
+ records: Array<Record<string, unknown>>;
81
+ };
82
+ alignedBinaryContract: PublicationProtectionDemoAlignedType[];
83
+ signedOnly: {
84
+ artifactId: string;
85
+ encrypted: boolean;
86
+ trailer: PublicationProtectionDemoSummary["recTrailer"];
87
+ recordStandards: Array<string | null>;
88
+ pnm: {
89
+ fileName: string | null;
90
+ fileId: string | null;
91
+ cid: string | null;
92
+ hasSignature: boolean;
93
+ signatureType: string | null;
94
+ publishTimestamp: string | null;
95
+ } | null;
96
+ enc: null;
97
+ envelope: null;
98
+ };
99
+ encryptedDelivery: {
100
+ artifactId: string;
101
+ encrypted: boolean;
102
+ trailer: PublicationProtectionDemoSummary["recTrailer"];
103
+ recordStandards: Array<string | null>;
104
+ pnm: {
105
+ fileName: string | null;
106
+ fileId: string | null;
107
+ cid: string | null;
108
+ hasSignature: boolean;
109
+ signatureType: string | null;
110
+ publishTimestamp: string | null;
111
+ } | null;
112
+ enc: {
113
+ context: string | null;
114
+ rootType: string | null;
115
+ keyExchange: string | null;
116
+ symmetric: string | null;
117
+ keyDerivation: string | null;
118
+ nonceLength: number;
119
+ ephemeralPublicKeyLength: number;
120
+ } | null;
121
+ envelope: {
122
+ scheme: string | null;
123
+ hasEncRecord: boolean;
124
+ hasPnmRecord: boolean;
125
+ } | null;
126
+ };
127
+ }
128
+
129
+ export interface PluginInvokeProcessLaunchPlan {
130
+ command: string;
131
+ args: string[];
132
+ env?: Record<string, string | undefined>;
133
+ cwd?: 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;
183
+ }
184
+
185
+ export interface PluginInvokeProcessClient {
186
+ launchPlan: PluginInvokeProcessLaunchPlan;
187
+ invokeRaw(requestBytes: Uint8Array | ArrayBuffer | ArrayBufferView): Promise<Uint8Array>;
188
+ invoke(request: {
189
+ methodId?: string | null;
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[];
203
+ }): Promise<{
204
+ statusCode: number;
205
+ errorCode?: string | null;
206
+ errorMessage?: string | null;
207
+ outputs: HarnessInputFrame[];
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>;
227
+ destroy(): Promise<void>;
228
+ }
229
+
230
+ export interface ModuleHarnessRuntimeDescriptor {
231
+ kind?: "process" | "wasmedge";
232
+ launchPlan?: PluginInvokeProcessLaunchPlan;
233
+ command?: string;
234
+ args?: string[];
235
+ env?: Record<string, string | undefined>;
236
+ cwd?: string;
237
+ wasmPath?: string;
238
+ wasmEdgeBinary?: string;
239
+ wasmEdgeRunnerBinary?: string;
240
+ enableThreads?: boolean;
241
+ hostProfile?: "runtime-host";
242
+ modules?: RuntimeHostTestModuleDefinition[];
243
+ defaultModuleId?: string;
244
+ metadata?: unknown;
245
+ }
246
+
247
+ export interface ModuleHarness {
248
+ runtime: ModuleHarnessRuntimeDescriptor & { kind: "process" | "wasmedge" };
249
+ launchPlan: PluginInvokeProcessLaunchPlan;
250
+ invokeRaw(requestBytes: Uint8Array | ArrayBuffer | ArrayBufferView): Promise<Uint8Array>;
251
+ invoke(request: {
252
+ methodId?: string | null;
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[];
266
+ }): Promise<{
267
+ statusCode: number;
268
+ errorCode?: string | null;
269
+ errorMessage?: string | null;
270
+ outputs: HarnessInputFrame[];
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>;
290
+ destroy(): Promise<void>;
291
+ }
292
+
293
+ export interface WasmEdgeRunnerBuildPlan {
294
+ runnerSourcePath: string;
295
+ requestedIncludeDir: string;
296
+ wasmedgeIncludeDir: string;
297
+ wasmedgeLibDir: string;
298
+ wasmedgeSharedLibraryPath: string;
299
+ outputPath: string;
300
+ compilerCommand: string;
301
+ compilerArgs: string[];
302
+ }
303
+
60
304
  export function describeCapabilityRuntimeSurface(
61
305
  capability: string,
62
306
  ): CapabilityRuntimeSurface;
63
307
 
308
+ export function createPublicationProtectionDemoManifest(): PluginManifest;
309
+
310
+ export function createPublicationProtectionDemoSummary(options?: {
311
+ manifest?: PluginManifest;
312
+ wasmBytes?: Uint8Array;
313
+ mnemonic?: string | null;
314
+ recipient?: {
315
+ publicKeyHex: string;
316
+ privateKeyHex: string;
317
+ };
318
+ }): Promise<PublicationProtectionDemoSummary>;
319
+
64
320
  export function generateManifestHarnessPlan(options: {
65
321
  manifest: PluginManifest;
66
322
  includeOptionalInputs?: boolean;
@@ -84,3 +340,58 @@ export function materializeHarnessScenario(
84
340
  };
85
341
 
86
342
  export function serializeHarnessPlan(plan: ManifestHarnessPlan): unknown;
343
+
344
+ export function buildWasmEdgeSpawnEnv(
345
+ baseEnv?: Record<string, string | undefined>,
346
+ ): Record<string, string | undefined>;
347
+
348
+ export function resolveWasmEdgePluginLaunchPlan(options: {
349
+ wasmPath?: string;
350
+ wasmEdgeBinary?: string;
351
+ wasmEdgeRunnerBinary?: string;
352
+ enableThreads?: boolean;
353
+ invokeArgs?: string[];
354
+ env?: Record<string, string | undefined>;
355
+ hostProfile?: "runtime-host";
356
+ }): PluginInvokeProcessLaunchPlan;
357
+
358
+ export function createPluginInvokeProcessClient(options: {
359
+ launchPlan?: PluginInvokeProcessLaunchPlan;
360
+ command?: string;
361
+ args?: string[];
362
+ env?: Record<string, string | undefined>;
363
+ cwd?: string;
364
+ }): Promise<PluginInvokeProcessClient>;
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
+
374
+ export function resolveModuleHarnessLaunchPlan(options: {
375
+ runtime?: ModuleHarnessRuntimeDescriptor;
376
+ } | ModuleHarnessRuntimeDescriptor): PluginInvokeProcessLaunchPlan;
377
+
378
+ export function createModuleHarness(options: {
379
+ runtime?: ModuleHarnessRuntimeDescriptor;
380
+ } | ModuleHarnessRuntimeDescriptor): Promise<ModuleHarness>;
381
+
382
+ export function resolveWasmEdgeRunnerSourcePath(): string;
383
+
384
+ export function resolveWasmEdgeRunnerBuildPlan(options: {
385
+ outputPath: string;
386
+ wasmedgeIncludeDir?: string;
387
+ wasmedgeLibDir?: string;
388
+ output?: string;
389
+ }): WasmEdgeRunnerBuildPlan;
390
+
391
+ export function buildWasmEdgeEmscriptenPthreadRunner(options: {
392
+ outputPath: string;
393
+ wasmedgeIncludeDir?: string;
394
+ wasmedgeLibDir?: string;
395
+ output?: string;
396
+ cwd?: string;
397
+ }): Promise<string>;
@@ -1,6 +1,27 @@
1
+ import { Buffer } from "node:buffer";
2
+
1
3
  import { encodePluginInvokeRequest } from "../invoke/codec.js";
2
4
  import { normalizeInvokeSurfaces } from "../invoke/index.js";
3
5
  import { selectPreferredPayloadTypeRef } from "../manifest/typeRefs.js";
6
+ export {
7
+ createPublicationProtectionDemoManifest,
8
+ createPublicationProtectionDemoSummary,
9
+ } from "./publicationProtectionDemo.js";
10
+ export {
11
+ buildWasmEdgeSpawnEnv,
12
+ createPluginInvokeProcessClient,
13
+ createWasmEdgeStreamProcessClient,
14
+ resolveWasmEdgePluginLaunchPlan,
15
+ } from "./processInvoke.js";
16
+ export {
17
+ buildWasmEdgeEmscriptenPthreadRunner,
18
+ resolveWasmEdgeRunnerBuildPlan,
19
+ resolveWasmEdgeRunnerSourcePath,
20
+ } from "./buildWasmEdgeRunner.js";
21
+ export {
22
+ createModuleHarness,
23
+ resolveModuleHarnessLaunchPlan,
24
+ } from "./moduleHarness.js";
4
25
 
5
26
  const CapabilitySurfaceMatrix = Object.freeze({
6
27
  logging: Object.freeze({
@@ -0,0 +1,163 @@
1
+ import {
2
+ createPluginInvokeProcessClient,
3
+ createWasmEdgeStreamProcessClient,
4
+ resolveWasmEdgePluginLaunchPlan,
5
+ } from "./processInvoke.js";
6
+
7
+ function normalizeRuntimeDescriptor(options = {}) {
8
+ if (options.runtime && typeof options.runtime === "object") {
9
+ return options.runtime;
10
+ }
11
+ return options;
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
+
23
+ export function resolveModuleHarnessLaunchPlan(options = {}) {
24
+ const runtime = normalizeRuntimeDescriptor(options);
25
+ if (runtime.launchPlan && typeof runtime.launchPlan === "object") {
26
+ return runtime.launchPlan;
27
+ }
28
+
29
+ const kind = String(runtime.kind ?? "process").trim().toLowerCase();
30
+ if (kind === "wasmedge") {
31
+ return resolveWasmEdgePluginLaunchPlan(runtime);
32
+ }
33
+ if (kind === "process") {
34
+ if (typeof runtime.command !== "string" || runtime.command.trim().length === 0) {
35
+ throw new Error(
36
+ "resolveModuleHarnessLaunchPlan requires runtime.command for process runtimes.",
37
+ );
38
+ }
39
+ return {
40
+ command: runtime.command,
41
+ args: Array.isArray(runtime.args) ? runtime.args : [],
42
+ env: runtime.env,
43
+ cwd: runtime.cwd,
44
+ };
45
+ }
46
+
47
+ throw new Error(`Unsupported module harness runtime kind: ${kind}`);
48
+ }
49
+
50
+ export async function createModuleHarness(options = {}) {
51
+ const runtime = normalizeRuntimeDescriptor(options);
52
+ const kind = String(runtime.kind ?? "process").trim().toLowerCase();
53
+ const launchPlan = resolveModuleHarnessLaunchPlan(options);
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;
86
+
87
+ return {
88
+ runtime: {
89
+ ...runtime,
90
+ kind,
91
+ hostProfile: runtimeHost ? "runtime-host" : runtime.hostProfile,
92
+ },
93
+ launchPlan,
94
+ invokeRaw(requestBytes) {
95
+ return processClient.invokeRaw(requestBytes);
96
+ },
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
+ }
106
+ return processClient.invoke(request);
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
+ },
159
+ destroy() {
160
+ return processClient.destroy();
161
+ },
162
+ };
163
+ }