sdn-flow 0.2.0

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 (69) hide show
  1. package/.claude/SKILLS.md +7 -0
  2. package/.claude/skills/sdn-plugin-abi-compliance/SKILL.md +56 -0
  3. package/.claude/todo/001-js-host-startup-and-deno.md +85 -0
  4. package/LICENSE +21 -0
  5. package/README.md +223 -0
  6. package/bin/sdn-flow-host.js +169 -0
  7. package/docs/.nojekyll +0 -0
  8. package/docs/ARCHITECTURE.md +200 -0
  9. package/docs/HOST_CAPABILITY_MODEL.md +317 -0
  10. package/docs/PLUGIN_ARCHITECTURE.md +145 -0
  11. package/docs/PLUGIN_COMPATIBILITY.md +61 -0
  12. package/docs/PLUGIN_COMPLIANCE_CHECKS.md +82 -0
  13. package/docs/PLUGIN_MANIFEST.md +94 -0
  14. package/docs/css/style.css +465 -0
  15. package/docs/index.html +218 -0
  16. package/docs/js/app.mjs +751 -0
  17. package/docs/js/editor-panel.mjs +203 -0
  18. package/docs/js/flow-canvas.mjs +515 -0
  19. package/docs/js/flow-model.mjs +391 -0
  20. package/docs/js/workers/emception.worker.js +146 -0
  21. package/docs/js/workers/pyodide.worker.js +134 -0
  22. package/native/flow_source_generator.cpp +1958 -0
  23. package/package.json +67 -0
  24. package/schemas/FlowRuntimeAbi.fbs +91 -0
  25. package/src/auth/canonicalize.js +5 -0
  26. package/src/auth/index.js +11 -0
  27. package/src/auth/permissions.js +8 -0
  28. package/src/compiler/CppFlowSourceGenerator.js +475 -0
  29. package/src/compiler/EmceptionCompilerAdapter.js +244 -0
  30. package/src/compiler/SignedArtifactCatalog.js +152 -0
  31. package/src/compiler/index.js +8 -0
  32. package/src/compiler/nativeFlowSourceGeneratorTool.js +144 -0
  33. package/src/compliance/index.js +13 -0
  34. package/src/compliance/pluginCompliance.js +11 -0
  35. package/src/deploy/FlowDeploymentClient.js +532 -0
  36. package/src/deploy/index.js +8 -0
  37. package/src/designer/FlowDesignerSession.js +158 -0
  38. package/src/designer/index.js +2 -0
  39. package/src/designer/requirements.js +184 -0
  40. package/src/generated/runtimeAbiLayouts.js +544 -0
  41. package/src/host/appHost.js +105 -0
  42. package/src/host/autoHost.js +113 -0
  43. package/src/host/browserHostAdapters.js +108 -0
  44. package/src/host/compiledFlowRuntimeHost.js +703 -0
  45. package/src/host/constants.js +55 -0
  46. package/src/host/dependencyRuntime.js +227 -0
  47. package/src/host/descriptorAbi.js +351 -0
  48. package/src/host/fetchService.js +237 -0
  49. package/src/host/httpHostAdapters.js +280 -0
  50. package/src/host/index.js +91 -0
  51. package/src/host/installedFlowHost.js +885 -0
  52. package/src/host/invocationAbi.js +440 -0
  53. package/src/host/normalize.js +372 -0
  54. package/src/host/packageManagers.js +369 -0
  55. package/src/host/profile.js +134 -0
  56. package/src/host/runtimeAbi.js +106 -0
  57. package/src/host/workspace.js +895 -0
  58. package/src/index.js +8 -0
  59. package/src/runtime/FlowRuntime.js +273 -0
  60. package/src/runtime/MethodRegistry.js +295 -0
  61. package/src/runtime/constants.js +44 -0
  62. package/src/runtime/index.js +19 -0
  63. package/src/runtime/normalize.js +377 -0
  64. package/src/transport/index.js +7 -0
  65. package/src/transport/pki.js +7 -0
  66. package/src/utils/crypto.js +7 -0
  67. package/src/utils/encoding.js +65 -0
  68. package/src/utils/wasmCrypto.js +69 -0
  69. package/tools/run-plugin-compliance-check.mjs +153 -0
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "sdn-flow",
3
+ "version": "0.2.0",
4
+ "description": "Isomorphic flow authoring, runtime, authorization, and deployment tooling for schema-driven WASM systems.",
5
+ "type": "module",
6
+ "bin": {
7
+ "sdn-flow-host": "./bin/sdn-flow-host.js"
8
+ },
9
+ "exports": {
10
+ ".": "./src/index.js",
11
+ "./runtime": "./src/runtime/index.js",
12
+ "./designer": "./src/designer/index.js",
13
+ "./auth": "./src/auth/index.js",
14
+ "./host": "./src/host/index.js",
15
+ "./transport": "./src/transport/index.js",
16
+ "./deploy": "./src/deploy/index.js",
17
+ "./compiler": "./src/compiler/index.js",
18
+ "./compliance": "./src/compliance/index.js",
19
+ "./schemas/*": "./schemas/*"
20
+ },
21
+ "files": [
22
+ "src/",
23
+ "native/",
24
+ "schemas/",
25
+ "docs/",
26
+ ".claude/",
27
+ "tools/",
28
+ "README.md",
29
+ "LICENSE"
30
+ ],
31
+ "scripts": {
32
+ "build:runtime-abi": "node scripts/build-runtime-abi.mjs",
33
+ "test": "npm run check:plugin-compliance && node --test",
34
+ "check:plugin-compliance": "node scripts/check-shared-module-compliance.mjs"
35
+ },
36
+ "keywords": [
37
+ "flow",
38
+ "wasm",
39
+ "sdn",
40
+ "space-data-network",
41
+ "orchestration",
42
+ "flatbuffers"
43
+ ],
44
+ "author": {
45
+ "name": "DigitalArsenal.io, Inc.",
46
+ "url": "https://digitalarsenal.io"
47
+ },
48
+ "license": "MIT",
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "https://github.com/DigitalArsenal/sdn-flow.git"
52
+ },
53
+ "homepage": "https://github.com/DigitalArsenal/sdn-flow",
54
+ "publishConfig": {
55
+ "access": "public"
56
+ },
57
+ "dependencies": {
58
+ "hd-wallet-wasm": "^1.5.4",
59
+ "space-data-module-sdk": "file:../space-data-module-sdk"
60
+ },
61
+ "devDependencies": {
62
+ "flatbuffers": "^25.9.23"
63
+ },
64
+ "engines": {
65
+ "node": ">=20.0.0"
66
+ }
67
+ }
@@ -0,0 +1,91 @@
1
+ // SDN Flow - Canonical Runtime Invocation ABI
2
+ //
3
+ // Fixed-layout aligned structs exchanged between the compiled flow runtime and
4
+ // a host launcher. These are host-binding records only; flow execution remains
5
+ // inside the compiled WASM runtime.
6
+
7
+ namespace sdn.flow.abi;
8
+
9
+ /// One aligned input frame staged for a node ingress queue.
10
+ struct FlowFrameDescriptor {
11
+ ingress_index:uint32;
12
+ type_descriptor_index:uint32;
13
+ port_id_pointer:uint32;
14
+ alignment:uint32;
15
+ offset:uint32;
16
+ size:uint32;
17
+ stream_id:uint32;
18
+ sequence:uint32;
19
+ trace_token:uint64;
20
+ end_of_stream:bool;
21
+ occupied:bool;
22
+ }
23
+
24
+ /// One prepared node invocation exported by the compiled runtime.
25
+ struct FlowInvocationDescriptor {
26
+ node_index:uint32;
27
+ dispatch_descriptor_index:uint32;
28
+ plugin_id_pointer:uint32;
29
+ method_id_pointer:uint32;
30
+ frames_pointer:uint32;
31
+ frame_count:uint32;
32
+ }
33
+
34
+ /// One node-to-dependency dispatch entry exported by the compiled runtime.
35
+ struct FlowNodeDispatchDescriptor {
36
+ node_id_pointer:uint32;
37
+ node_index:uint32;
38
+ dependency_id_pointer:uint32;
39
+ dependency_index:uint32;
40
+ plugin_id_pointer:uint32;
41
+ method_id_pointer:uint32;
42
+ dispatch_model_pointer:uint32;
43
+ entrypoint_pointer:uint32;
44
+ manifest_bytes_symbol_pointer:uint32;
45
+ manifest_size_symbol_pointer:uint32;
46
+ init_symbol_pointer:uint32;
47
+ destroy_symbol_pointer:uint32;
48
+ malloc_symbol_pointer:uint32;
49
+ free_symbol_pointer:uint32;
50
+ stream_invoke_symbol_pointer:uint32;
51
+ }
52
+
53
+ /// One embedded signed dependency exported by the compiled runtime.
54
+ struct SignedArtifactDependencyDescriptor {
55
+ dependency_id_pointer:uint32;
56
+ plugin_id_pointer:uint32;
57
+ version_pointer:uint32;
58
+ sha256_pointer:uint32;
59
+ signature_pointer:uint32;
60
+ signer_public_key_pointer:uint32;
61
+ entrypoint_pointer:uint32;
62
+ manifest_bytes_symbol_pointer:uint32;
63
+ manifest_size_symbol_pointer:uint32;
64
+ init_symbol_pointer:uint32;
65
+ destroy_symbol_pointer:uint32;
66
+ malloc_symbol_pointer:uint32;
67
+ free_symbol_pointer:uint32;
68
+ stream_invoke_symbol_pointer:uint32;
69
+ wasm_bytes_pointer:uint32;
70
+ wasm_size:uint32;
71
+ manifest_bytes_pointer:uint32;
72
+ manifest_size:uint32;
73
+ }
74
+
75
+ /// Mutable runtime counters for one ingress queue.
76
+ struct FlowIngressRuntimeState {
77
+ total_received:uint64;
78
+ total_dropped:uint64;
79
+ queued_frames:uint32;
80
+ }
81
+
82
+ /// Mutable runtime counters for one node.
83
+ struct FlowNodeRuntimeState {
84
+ invocation_count:uint64;
85
+ consumed_frames:uint64;
86
+ queued_frames:uint32;
87
+ backlog_remaining:uint32;
88
+ last_status:uint32;
89
+ ready:bool;
90
+ yielded:bool;
91
+ }
@@ -0,0 +1,5 @@
1
+ export {
2
+ canonicalBytes,
3
+ hashCanonicalValue,
4
+ stableStringify,
5
+ } from "space-data-module-sdk/auth";
@@ -0,0 +1,11 @@
1
+ export {
2
+ canonicalBytes,
3
+ hashCanonicalValue,
4
+ stableStringify,
5
+ assertDeploymentAuthorization,
6
+ createDeploymentAuthorization,
7
+ createHdWalletSigner,
8
+ createHdWalletVerifier,
9
+ signAuthorization,
10
+ verifyAuthorization,
11
+ } from "space-data-module-sdk/auth";
@@ -0,0 +1,8 @@
1
+ export {
2
+ assertDeploymentAuthorization,
3
+ createDeploymentAuthorization,
4
+ createHdWalletSigner,
5
+ createHdWalletVerifier,
6
+ signAuthorization,
7
+ verifyAuthorization,
8
+ } from "space-data-module-sdk/auth";
@@ -0,0 +1,475 @@
1
+ import { normalizeProgram } from "../runtime/index.js";
2
+ import { toUint8Array } from "../utils/encoding.js";
3
+ import { runNativeFlowSourceGenerator } from "./nativeFlowSourceGeneratorTool.js";
4
+
5
+ const INVALID_INDEX = 0xffffffff;
6
+ const REQUEST_MAGIC = "SDNFLOWCPPGEN1";
7
+
8
+ function normalizeTypeDescriptor(typeRef = {}) {
9
+ return {
10
+ schemaName: typeRef.schemaName ?? "",
11
+ fileIdentifier: typeRef.fileIdentifier ?? "",
12
+ schemaHashHex: Array.from(typeRef.schemaHash ?? [], (byte) =>
13
+ Number(byte).toString(16).padStart(2, "0"),
14
+ ).join(""),
15
+ acceptsAnyFlatbuffer: typeRef.acceptsAnyFlatbuffer ?? false,
16
+ };
17
+ }
18
+
19
+ function createTypeIndexRegistry() {
20
+ const descriptors = [];
21
+ const indices = [];
22
+ const descriptorIndexByKey = new Map();
23
+
24
+ function registerTypeRef(typeRef) {
25
+ const normalized = normalizeTypeDescriptor(typeRef);
26
+ const key = JSON.stringify([
27
+ normalized.schemaName,
28
+ normalized.fileIdentifier,
29
+ normalized.schemaHashHex,
30
+ normalized.acceptsAnyFlatbuffer,
31
+ ]);
32
+ if (!descriptorIndexByKey.has(key)) {
33
+ descriptorIndexByKey.set(key, descriptors.length);
34
+ descriptors.push(normalized);
35
+ }
36
+ return descriptorIndexByKey.get(key);
37
+ }
38
+
39
+ function reserveTypeRefs(typeRefs = []) {
40
+ const offset = indices.length;
41
+ for (const typeRef of typeRefs) {
42
+ indices.push(registerTypeRef(typeRef));
43
+ }
44
+ return {
45
+ offset,
46
+ count: typeRefs.length,
47
+ };
48
+ }
49
+
50
+ return {
51
+ descriptors,
52
+ indices,
53
+ reserveTypeRefs,
54
+ };
55
+ }
56
+
57
+ function getMapIndex(indexMap, key) {
58
+ if (!indexMap.has(key)) {
59
+ return INVALID_INDEX;
60
+ }
61
+ return indexMap.get(key);
62
+ }
63
+
64
+ function createIngressTopology(
65
+ normalizedProgram,
66
+ nodeIndexById,
67
+ triggerIndexById,
68
+ ) {
69
+ const ingressDescriptors = [];
70
+ const edgeIngressIndexByEdgeIndex = new Map();
71
+ const triggerBindingIngressIndexByBindingIndex = new Map();
72
+ const nodeIngressIndexMap = new Map(
73
+ normalizedProgram.nodes.map((node) => [node.nodeId, []]),
74
+ );
75
+
76
+ normalizedProgram.triggerBindings.forEach((binding, bindingIndex) => {
77
+ const targetNodeIndex = getMapIndex(nodeIndexById, binding.targetNodeId);
78
+ const ingressIndex = ingressDescriptors.length;
79
+ ingressDescriptors.push({
80
+ ingressId: `trigger:${binding.triggerId}->${binding.targetNodeId}:${binding.targetPortId}`,
81
+ sourceKind: "trigger",
82
+ sourceIndex: getMapIndex(triggerIndexById, binding.triggerId),
83
+ sourceNodeIndex: INVALID_INDEX,
84
+ sourcePortId: "",
85
+ targetNodeIndex,
86
+ targetNodeId: binding.targetNodeId,
87
+ targetPortId: binding.targetPortId,
88
+ backpressurePolicy: binding.backpressurePolicy ?? "queue",
89
+ queueDepth: binding.queueDepth ?? 0,
90
+ });
91
+ triggerBindingIngressIndexByBindingIndex.set(bindingIndex, ingressIndex);
92
+ if (targetNodeIndex !== INVALID_INDEX) {
93
+ nodeIngressIndexMap.get(binding.targetNodeId).push(ingressIndex);
94
+ }
95
+ });
96
+
97
+ normalizedProgram.edges.forEach((edge, edgeIndex) => {
98
+ const targetNodeIndex = getMapIndex(nodeIndexById, edge.toNodeId);
99
+ const sourceNodeIndex = getMapIndex(nodeIndexById, edge.fromNodeId);
100
+ const ingressIndex = ingressDescriptors.length;
101
+ ingressDescriptors.push({
102
+ ingressId: `edge:${edge.edgeId}`,
103
+ sourceKind: "edge",
104
+ sourceIndex: edgeIndex,
105
+ sourceNodeIndex,
106
+ sourcePortId: edge.fromPortId,
107
+ targetNodeIndex,
108
+ targetNodeId: edge.toNodeId,
109
+ targetPortId: edge.toPortId,
110
+ backpressurePolicy: edge.backpressurePolicy ?? "queue",
111
+ queueDepth: edge.queueDepth ?? 0,
112
+ });
113
+ edgeIngressIndexByEdgeIndex.set(edgeIndex, ingressIndex);
114
+ if (targetNodeIndex !== INVALID_INDEX) {
115
+ nodeIngressIndexMap.get(edge.toNodeId).push(ingressIndex);
116
+ }
117
+ });
118
+
119
+ const flattenedNodeIngressIndices = [];
120
+ const nodeIngressRanges = normalizedProgram.nodes.map((node) => {
121
+ const ingressIndices = nodeIngressIndexMap.get(node.nodeId) ?? [];
122
+ const offset = flattenedNodeIngressIndices.length;
123
+ flattenedNodeIngressIndices.push(...ingressIndices);
124
+ return {
125
+ offset,
126
+ count: ingressIndices.length,
127
+ };
128
+ });
129
+
130
+ return {
131
+ ingressDescriptors,
132
+ edgeIngressIndexByEdgeIndex,
133
+ triggerBindingIngressIndexByBindingIndex,
134
+ nodeIngressRanges,
135
+ flattenedNodeIngressIndices,
136
+ };
137
+ }
138
+
139
+ function createBinaryWriter() {
140
+ const chunks = [];
141
+
142
+ function pushBytes(value) {
143
+ const bytes = toUint8Array(value);
144
+ const size = new Uint8Array(4);
145
+ new DataView(size.buffer).setUint32(0, bytes.length, true);
146
+ chunks.push(size, bytes);
147
+ }
148
+
149
+ function pushString(value) {
150
+ pushBytes(new TextEncoder().encode(String(value ?? "")));
151
+ }
152
+
153
+ function pushU8(value) {
154
+ chunks.push(Uint8Array.of(value ? 1 : 0));
155
+ }
156
+
157
+ function pushU32(value) {
158
+ const bytes = new Uint8Array(4);
159
+ new DataView(bytes.buffer).setUint32(0, Number(value ?? 0) >>> 0, true);
160
+ chunks.push(bytes);
161
+ }
162
+
163
+ function finish() {
164
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
165
+ const output = new Uint8Array(totalLength);
166
+ let offset = 0;
167
+ for (const chunk of chunks) {
168
+ output.set(chunk, offset);
169
+ offset += chunk.length;
170
+ }
171
+ return output;
172
+ }
173
+
174
+ return {
175
+ pushBytes,
176
+ pushString,
177
+ pushU8,
178
+ pushU32,
179
+ finish,
180
+ };
181
+ }
182
+
183
+ function createGeneratorRequest({
184
+ program,
185
+ manifestBuffer,
186
+ dependencies = [],
187
+ namespace = "sdn_flow_generated",
188
+ } = {}) {
189
+ const normalizedProgram = normalizeProgram(program);
190
+ const normalizedManifestBuffer = toUint8Array(manifestBuffer);
191
+
192
+ if (normalizedManifestBuffer.length === 0) {
193
+ throw new Error(
194
+ "generateCppFlowRuntimeSource requires manifestBuffer bytes.",
195
+ );
196
+ }
197
+
198
+ const typeRegistry = createTypeIndexRegistry();
199
+ const nodeIndexById = new Map(
200
+ normalizedProgram.nodes.map((node, index) => [node.nodeId, index]),
201
+ );
202
+ const triggerIndexById = new Map(
203
+ normalizedProgram.triggers.map((trigger, index) => [
204
+ trigger.triggerId,
205
+ index,
206
+ ]),
207
+ );
208
+ const ingressTopology = createIngressTopology(
209
+ normalizedProgram,
210
+ nodeIndexById,
211
+ triggerIndexById,
212
+ );
213
+
214
+ return {
215
+ namespace,
216
+ manifestBuffer: normalizedManifestBuffer,
217
+ programId: normalizedProgram.programId,
218
+ programName: normalizedProgram.name ?? normalizedProgram.programId,
219
+ programVersion: normalizedProgram.version ?? "0.1.0",
220
+ programDescription: normalizedProgram.description ?? "",
221
+ requiredPlugins: normalizedProgram.requiredPlugins.map((pluginId) =>
222
+ String(pluginId),
223
+ ),
224
+ typeDescriptors: typeRegistry.descriptors,
225
+ acceptedTypeIndices: typeRegistry.indices,
226
+ triggers: normalizedProgram.triggers.map((trigger) => {
227
+ const acceptedTypes = typeRegistry.reserveTypeRefs(trigger.acceptedTypes);
228
+ return {
229
+ triggerId: trigger.triggerId,
230
+ kind: trigger.kind,
231
+ source: trigger.source ?? "",
232
+ protocolId: trigger.protocolId ?? "",
233
+ defaultIntervalMs: trigger.defaultIntervalMs,
234
+ acceptedTypeIndexOffset: acceptedTypes.offset,
235
+ acceptedTypeIndexCount: acceptedTypes.count,
236
+ description: trigger.description ?? "",
237
+ };
238
+ }),
239
+ nodes: normalizedProgram.nodes.map((node, nodeIndex) => {
240
+ const ingressRange = ingressTopology.nodeIngressRanges[nodeIndex];
241
+ return {
242
+ nodeId: node.nodeId,
243
+ pluginId: node.pluginId,
244
+ methodId: node.methodId,
245
+ kind: node.kind,
246
+ drainPolicy: node.drainPolicy ?? "",
247
+ timeSliceMicros: node.timeSliceMicros,
248
+ ingressIndexOffset: ingressRange.offset,
249
+ ingressIndexCount: ingressRange.count,
250
+ };
251
+ }),
252
+ edges: normalizedProgram.edges.map((edge, edgeIndex) => {
253
+ const acceptedTypes = typeRegistry.reserveTypeRefs(edge.acceptedTypes);
254
+ return {
255
+ edgeId: edge.edgeId,
256
+ fromNodeId: edge.fromNodeId,
257
+ fromNodeIndex: getMapIndex(nodeIndexById, edge.fromNodeId),
258
+ fromPortId: edge.fromPortId,
259
+ toNodeId: edge.toNodeId,
260
+ toNodeIndex: getMapIndex(nodeIndexById, edge.toNodeId),
261
+ toPortId: edge.toPortId,
262
+ backpressurePolicy: edge.backpressurePolicy ?? "",
263
+ queueDepth: edge.queueDepth,
264
+ acceptedTypeIndexOffset: acceptedTypes.offset,
265
+ acceptedTypeIndexCount: acceptedTypes.count,
266
+ targetIngressIndex:
267
+ ingressTopology.edgeIngressIndexByEdgeIndex.get(edgeIndex) ??
268
+ INVALID_INDEX,
269
+ };
270
+ }),
271
+ triggerBindings: normalizedProgram.triggerBindings.map(
272
+ (binding, bindingIndex) => ({
273
+ triggerId: binding.triggerId,
274
+ triggerIndex: getMapIndex(triggerIndexById, binding.triggerId),
275
+ targetNodeId: binding.targetNodeId,
276
+ targetNodeIndex: getMapIndex(nodeIndexById, binding.targetNodeId),
277
+ targetPortId: binding.targetPortId,
278
+ backpressurePolicy: binding.backpressurePolicy ?? "",
279
+ queueDepth: binding.queueDepth,
280
+ targetIngressIndex:
281
+ ingressTopology.triggerBindingIngressIndexByBindingIndex.get(
282
+ bindingIndex,
283
+ ) ?? INVALID_INDEX,
284
+ }),
285
+ ),
286
+ ingressDescriptors: ingressTopology.ingressDescriptors,
287
+ externalInterfaces: normalizedProgram.externalInterfaces.map(
288
+ (externalInterface) => {
289
+ const acceptedTypes = typeRegistry.reserveTypeRefs(
290
+ externalInterface.acceptedTypes,
291
+ );
292
+ return {
293
+ interfaceId: externalInterface.interfaceId,
294
+ kind: externalInterface.kind ?? "",
295
+ direction: externalInterface.direction ?? "",
296
+ capability: externalInterface.capability ?? "",
297
+ resource: externalInterface.resource ?? "",
298
+ protocolId: externalInterface.protocolId ?? "",
299
+ topic: externalInterface.topic ?? "",
300
+ path: externalInterface.path ?? "",
301
+ required: externalInterface.required !== false,
302
+ acceptedTypeIndexOffset: acceptedTypes.offset,
303
+ acceptedTypeIndexCount: acceptedTypes.count,
304
+ description: externalInterface.description ?? "",
305
+ };
306
+ },
307
+ ),
308
+ dependencies: dependencies.map((dependency) => ({
309
+ dependencyId: dependency.dependencyId ?? "",
310
+ pluginId: dependency.pluginId ?? "",
311
+ version: dependency.version ?? "",
312
+ sha256: dependency.sha256 ?? "",
313
+ signature: dependency.signature ?? "",
314
+ signerPublicKey: dependency.signerPublicKey ?? "",
315
+ entrypoint: dependency.entrypoint ?? "",
316
+ manifestExports: {
317
+ bytesSymbol: dependency.manifestExports?.bytesSymbol ?? "",
318
+ sizeSymbol: dependency.manifestExports?.sizeSymbol ?? "",
319
+ },
320
+ runtimeExports: {
321
+ initSymbol: dependency.runtimeExports?.initSymbol ?? "",
322
+ destroySymbol: dependency.runtimeExports?.destroySymbol ?? "",
323
+ mallocSymbol: dependency.runtimeExports?.mallocSymbol ?? "",
324
+ freeSymbol: dependency.runtimeExports?.freeSymbol ?? "",
325
+ streamInvokeSymbol: dependency.runtimeExports?.streamInvokeSymbol ?? "",
326
+ },
327
+ wasm: toUint8Array(dependency.wasm),
328
+ manifestBuffer: dependency.manifestBuffer
329
+ ? toUint8Array(dependency.manifestBuffer)
330
+ : new Uint8Array(),
331
+ })),
332
+ nodeIngressIndices: ingressTopology.flattenedNodeIngressIndices,
333
+ };
334
+ }
335
+
336
+ function encodeGeneratorRequest(request) {
337
+ const writer = createBinaryWriter();
338
+ writer.pushString(REQUEST_MAGIC);
339
+ writer.pushString(request.namespace);
340
+ writer.pushBytes(request.manifestBuffer);
341
+ writer.pushString(request.programId);
342
+ writer.pushString(request.programName);
343
+ writer.pushString(request.programVersion);
344
+ writer.pushString(request.programDescription);
345
+
346
+ writer.pushU32(request.requiredPlugins.length);
347
+ request.requiredPlugins.forEach((value) => writer.pushString(value));
348
+
349
+ writer.pushU32(request.typeDescriptors.length);
350
+ request.typeDescriptors.forEach((descriptor) => {
351
+ writer.pushString(descriptor.schemaName);
352
+ writer.pushString(descriptor.fileIdentifier);
353
+ writer.pushString(descriptor.schemaHashHex);
354
+ writer.pushU8(descriptor.acceptsAnyFlatbuffer);
355
+ });
356
+
357
+ writer.pushU32(request.acceptedTypeIndices.length);
358
+ request.acceptedTypeIndices.forEach((value) => writer.pushU32(value));
359
+
360
+ writer.pushU32(request.triggers.length);
361
+ request.triggers.forEach((trigger) => {
362
+ writer.pushString(trigger.triggerId);
363
+ writer.pushString(trigger.kind);
364
+ writer.pushString(trigger.source);
365
+ writer.pushString(trigger.protocolId);
366
+ writer.pushU32(trigger.defaultIntervalMs);
367
+ writer.pushU32(trigger.acceptedTypeIndexOffset);
368
+ writer.pushU32(trigger.acceptedTypeIndexCount);
369
+ writer.pushString(trigger.description);
370
+ });
371
+
372
+ writer.pushU32(request.nodes.length);
373
+ request.nodes.forEach((node) => {
374
+ writer.pushString(node.nodeId);
375
+ writer.pushString(node.pluginId);
376
+ writer.pushString(node.methodId);
377
+ writer.pushString(node.kind);
378
+ writer.pushString(node.drainPolicy);
379
+ writer.pushU32(node.timeSliceMicros);
380
+ writer.pushU32(node.ingressIndexOffset);
381
+ writer.pushU32(node.ingressIndexCount);
382
+ });
383
+
384
+ writer.pushU32(request.edges.length);
385
+ request.edges.forEach((edge) => {
386
+ writer.pushString(edge.edgeId);
387
+ writer.pushString(edge.fromNodeId);
388
+ writer.pushU32(edge.fromNodeIndex);
389
+ writer.pushString(edge.fromPortId);
390
+ writer.pushString(edge.toNodeId);
391
+ writer.pushU32(edge.toNodeIndex);
392
+ writer.pushString(edge.toPortId);
393
+ writer.pushString(edge.backpressurePolicy);
394
+ writer.pushU32(edge.queueDepth);
395
+ writer.pushU32(edge.acceptedTypeIndexOffset);
396
+ writer.pushU32(edge.acceptedTypeIndexCount);
397
+ writer.pushU32(edge.targetIngressIndex);
398
+ });
399
+
400
+ writer.pushU32(request.triggerBindings.length);
401
+ request.triggerBindings.forEach((binding) => {
402
+ writer.pushString(binding.triggerId);
403
+ writer.pushU32(binding.triggerIndex);
404
+ writer.pushString(binding.targetNodeId);
405
+ writer.pushU32(binding.targetNodeIndex);
406
+ writer.pushString(binding.targetPortId);
407
+ writer.pushString(binding.backpressurePolicy);
408
+ writer.pushU32(binding.queueDepth);
409
+ writer.pushU32(binding.targetIngressIndex);
410
+ });
411
+
412
+ writer.pushU32(request.ingressDescriptors.length);
413
+ request.ingressDescriptors.forEach((ingress) => {
414
+ writer.pushString(ingress.ingressId);
415
+ writer.pushString(ingress.sourceKind);
416
+ writer.pushU32(ingress.sourceIndex);
417
+ writer.pushU32(ingress.sourceNodeIndex);
418
+ writer.pushString(ingress.sourcePortId ?? "");
419
+ writer.pushU32(ingress.targetNodeIndex);
420
+ writer.pushString(ingress.targetNodeId);
421
+ writer.pushString(ingress.targetPortId);
422
+ writer.pushString(ingress.backpressurePolicy);
423
+ writer.pushU32(ingress.queueDepth);
424
+ });
425
+
426
+ writer.pushU32(request.externalInterfaces.length);
427
+ request.externalInterfaces.forEach((externalInterface) => {
428
+ writer.pushString(externalInterface.interfaceId);
429
+ writer.pushString(externalInterface.kind);
430
+ writer.pushString(externalInterface.direction);
431
+ writer.pushString(externalInterface.capability);
432
+ writer.pushString(externalInterface.resource);
433
+ writer.pushString(externalInterface.protocolId);
434
+ writer.pushString(externalInterface.topic);
435
+ writer.pushString(externalInterface.path);
436
+ writer.pushU8(externalInterface.required);
437
+ writer.pushU32(externalInterface.acceptedTypeIndexOffset);
438
+ writer.pushU32(externalInterface.acceptedTypeIndexCount);
439
+ writer.pushString(externalInterface.description);
440
+ });
441
+
442
+ writer.pushU32(request.dependencies.length);
443
+ request.dependencies.forEach((dependency) => {
444
+ writer.pushString(dependency.dependencyId);
445
+ writer.pushString(dependency.pluginId);
446
+ writer.pushString(dependency.version);
447
+ writer.pushString(dependency.sha256);
448
+ writer.pushString(dependency.signature);
449
+ writer.pushString(dependency.signerPublicKey);
450
+ writer.pushString(dependency.entrypoint);
451
+ writer.pushString(dependency.manifestExports.bytesSymbol);
452
+ writer.pushString(dependency.manifestExports.sizeSymbol);
453
+ writer.pushString(dependency.runtimeExports.initSymbol);
454
+ writer.pushString(dependency.runtimeExports.destroySymbol);
455
+ writer.pushString(dependency.runtimeExports.mallocSymbol);
456
+ writer.pushString(dependency.runtimeExports.freeSymbol);
457
+ writer.pushString(dependency.runtimeExports.streamInvokeSymbol);
458
+ writer.pushBytes(dependency.wasm);
459
+ writer.pushBytes(dependency.manifestBuffer);
460
+ });
461
+
462
+ writer.pushU32(request.nodeIngressIndices.length);
463
+ request.nodeIngressIndices.forEach((value) => writer.pushU32(value));
464
+
465
+ return writer.finish();
466
+ }
467
+
468
+ export async function generateCppFlowRuntimeSource(options = {}) {
469
+ const request = createGeneratorRequest(options);
470
+ const encodedRequest = encodeGeneratorRequest(request);
471
+ const result = await runNativeFlowSourceGenerator(encodedRequest);
472
+ return result.source;
473
+ }
474
+
475
+ export default generateCppFlowRuntimeSource;