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
@@ -0,0 +1,369 @@
1
+ import { spawn } from "node:child_process";
2
+ import path from "node:path";
3
+
4
+ function normalizeString(value, fallback = null) {
5
+ if (typeof value !== "string") {
6
+ return fallback;
7
+ }
8
+ const normalized = value.trim();
9
+ return normalized.length > 0 ? normalized : fallback;
10
+ }
11
+
12
+ function isObject(value) {
13
+ return value !== null && typeof value === "object" && !Array.isArray(value);
14
+ }
15
+
16
+ function normalizeCommandArgs(args) {
17
+ if (!Array.isArray(args)) {
18
+ return [];
19
+ }
20
+ return args
21
+ .map((value) => {
22
+ if (value === undefined || value === null) {
23
+ return null;
24
+ }
25
+ return String(value);
26
+ })
27
+ .filter((value) => value !== null);
28
+ }
29
+
30
+ function normalizeCommandSpec(commandSpec, defaults = {}) {
31
+ const input =
32
+ typeof commandSpec === "string"
33
+ ? { command: commandSpec }
34
+ : isObject(commandSpec)
35
+ ? commandSpec
36
+ : null;
37
+ const command = normalizeString(input?.command ?? input?.cmd, null);
38
+ if (!command) {
39
+ throw new Error(
40
+ "Command-backed package-manager operations require a command string.",
41
+ );
42
+ }
43
+ return {
44
+ command,
45
+ args: normalizeCommandArgs(input.args),
46
+ cwd: path.resolve(
47
+ normalizeString(input.cwd ?? defaults.cwd, null) ?? process.cwd(),
48
+ ),
49
+ env: isObject(input.env)
50
+ ? {
51
+ ...(isObject(defaults.env) ? defaults.env : process.env),
52
+ ...input.env,
53
+ }
54
+ : defaults.env,
55
+ input:
56
+ typeof input.input === "string" || input.input instanceof Uint8Array
57
+ ? input.input
58
+ : null,
59
+ allowedExitCodes: Array.isArray(input.allowedExitCodes)
60
+ ? input.allowedExitCodes
61
+ : Array.isArray(defaults.allowedExitCodes)
62
+ ? defaults.allowedExitCodes
63
+ : [0],
64
+ };
65
+ }
66
+
67
+ function createCommandError(commandResult) {
68
+ const commandLine = [commandResult.command, ...commandResult.args].join(" ");
69
+ const stderr =
70
+ normalizeString(commandResult.stderr, null) ?? "Command exited without stderr.";
71
+ return new Error(
72
+ `Package-manager command failed (${commandResult.exitCode}): ${commandLine}\n${stderr}`,
73
+ );
74
+ }
75
+
76
+ function formatPackageInstallSpecifier(packageReference = {}) {
77
+ const sourceRef = normalizeString(packageReference.sourceRef, null);
78
+ if (sourceRef) {
79
+ return sourceRef;
80
+ }
81
+ const packageId = normalizeString(packageReference.packageId, null);
82
+ if (!packageId) {
83
+ throw new Error(
84
+ "Package references require packageId or sourceRef for installation.",
85
+ );
86
+ }
87
+ const version = normalizeString(packageReference.version, null);
88
+ return version ? `${packageId}@${version}` : packageId;
89
+ }
90
+
91
+ function formatPackageUpdateSpecifier(packageReference = {}) {
92
+ const sourceRef = normalizeString(packageReference.sourceRef, null);
93
+ if (sourceRef) {
94
+ return sourceRef;
95
+ }
96
+ const packageId = normalizeString(packageReference.packageId, null);
97
+ if (!packageId) {
98
+ throw new Error(
99
+ "Package references require packageId or sourceRef for updates.",
100
+ );
101
+ }
102
+ return packageId;
103
+ }
104
+
105
+ function resolvePackageReferenceCwd(packageReference, workspace, options = {}) {
106
+ return path.resolve(
107
+ normalizeString(
108
+ options.cwd ??
109
+ options.baseDirectory ??
110
+ workspace?.baseDirectory ??
111
+ process.cwd(),
112
+ process.cwd(),
113
+ ),
114
+ );
115
+ }
116
+
117
+ function resolveNodeModulesInstallPath(installRoot, packageId) {
118
+ const normalizedPackageId = normalizeString(packageId, null);
119
+ if (!normalizedPackageId) {
120
+ return null;
121
+ }
122
+ return path.resolve(installRoot, "node_modules", ...normalizedPackageId.split("/"));
123
+ }
124
+
125
+ export function createNodeCommandRunner(defaultOptions = {}) {
126
+ return async function runCommand(commandSpec, context = {}) {
127
+ const normalizedCommand = normalizeCommandSpec(commandSpec, defaultOptions);
128
+ const {
129
+ command,
130
+ args,
131
+ cwd,
132
+ env,
133
+ input,
134
+ allowedExitCodes,
135
+ } = normalizedCommand;
136
+
137
+ return new Promise((resolve, reject) => {
138
+ const child = spawn(command, args, {
139
+ cwd,
140
+ env,
141
+ stdio: "pipe",
142
+ });
143
+ let stdout = "";
144
+ let stderr = "";
145
+
146
+ child.stdout.on("data", (chunk) => {
147
+ stdout += chunk.toString();
148
+ });
149
+ child.stderr.on("data", (chunk) => {
150
+ stderr += chunk.toString();
151
+ });
152
+ child.on("error", reject);
153
+ child.on("close", (exitCode) => {
154
+ const commandResult = {
155
+ phase: context.phase ?? null,
156
+ command,
157
+ args,
158
+ cwd,
159
+ exitCode: Number.isInteger(exitCode) ? exitCode : -1,
160
+ stdout,
161
+ stderr,
162
+ };
163
+ if (!allowedExitCodes.includes(commandResult.exitCode)) {
164
+ reject(createCommandError(commandResult));
165
+ return;
166
+ }
167
+ resolve(commandResult);
168
+ });
169
+
170
+ if (input instanceof Uint8Array || typeof input === "string") {
171
+ child.stdin.write(input);
172
+ }
173
+ child.stdin.end();
174
+ });
175
+ };
176
+ }
177
+
178
+ export function createCommandPackageManager(options = {}) {
179
+ const runCommand =
180
+ typeof options.runCommand === "function"
181
+ ? options.runCommand
182
+ : createNodeCommandRunner(options.runnerOptions);
183
+ const installCommand =
184
+ typeof options.installCommand === "function"
185
+ ? options.installCommand
186
+ : null;
187
+ const updateCommand =
188
+ typeof options.updateCommand === "function"
189
+ ? options.updateCommand
190
+ : null;
191
+ const removeCommand =
192
+ typeof options.removeCommand === "function"
193
+ ? options.removeCommand
194
+ : null;
195
+ const resolveInstallRecord =
196
+ typeof options.resolveInstallRecord === "function"
197
+ ? options.resolveInstallRecord
198
+ : null;
199
+
200
+ if (!installCommand || !updateCommand || !resolveInstallRecord) {
201
+ throw new Error(
202
+ "Command-backed package managers require installCommand, updateCommand, and resolveInstallRecord callbacks.",
203
+ );
204
+ }
205
+
206
+ async function executePhase(phase, packageReference, workspace, operationOptions) {
207
+ const commandFactory =
208
+ phase === "install"
209
+ ? installCommand
210
+ : phase === "update"
211
+ ? updateCommand
212
+ : removeCommand;
213
+ if (typeof commandFactory !== "function") {
214
+ return null;
215
+ }
216
+ const commandSpec = commandFactory(
217
+ packageReference,
218
+ workspace,
219
+ operationOptions,
220
+ );
221
+ return runCommand(commandSpec, {
222
+ phase,
223
+ packageReference,
224
+ workspace,
225
+ options: operationOptions,
226
+ });
227
+ }
228
+
229
+ return {
230
+ async install(packageReference, workspace, operationOptions = {}) {
231
+ const commandResult = await executePhase(
232
+ "install",
233
+ packageReference,
234
+ workspace,
235
+ operationOptions,
236
+ );
237
+ return resolveInstallRecord({
238
+ phase: "install",
239
+ packageReference,
240
+ workspace,
241
+ commandResult,
242
+ options: operationOptions,
243
+ });
244
+ },
245
+ async update(packageReference, workspace, operationOptions = {}) {
246
+ const commandResult = await executePhase(
247
+ "update",
248
+ packageReference,
249
+ workspace,
250
+ operationOptions,
251
+ );
252
+ return resolveInstallRecord({
253
+ phase: "update",
254
+ packageReference,
255
+ workspace,
256
+ commandResult,
257
+ options: operationOptions,
258
+ });
259
+ },
260
+ async remove(packageReference, workspace, operationOptions = {}) {
261
+ return executePhase(
262
+ "remove",
263
+ packageReference,
264
+ workspace,
265
+ operationOptions,
266
+ );
267
+ },
268
+ };
269
+ }
270
+
271
+ export function createNpmPackageManager(options = {}) {
272
+ const packageManagerCommand = normalizeString(
273
+ options.packageManagerCommand ?? options.command,
274
+ "npm",
275
+ );
276
+ const resolveCwd =
277
+ typeof options.resolveCwd === "function"
278
+ ? options.resolveCwd
279
+ : (packageReference, workspace) =>
280
+ resolvePackageReferenceCwd(packageReference, workspace, options);
281
+ const resolvePluginPackage =
282
+ typeof options.resolvePluginPackage === "function"
283
+ ? options.resolvePluginPackage
284
+ : null;
285
+
286
+ return createCommandPackageManager({
287
+ ...options,
288
+ installCommand(packageReference, workspace, operationOptions = {}) {
289
+ const cwd = resolveCwd(packageReference, workspace, operationOptions);
290
+ return {
291
+ command: packageManagerCommand,
292
+ args: [
293
+ "install",
294
+ "--no-save",
295
+ formatPackageInstallSpecifier(packageReference),
296
+ ],
297
+ cwd,
298
+ };
299
+ },
300
+ updateCommand(packageReference, workspace, operationOptions = {}) {
301
+ const cwd = resolveCwd(packageReference, workspace, operationOptions);
302
+ return {
303
+ command: packageManagerCommand,
304
+ args: [
305
+ "install",
306
+ "--no-save",
307
+ formatPackageUpdateSpecifier(packageReference),
308
+ ],
309
+ cwd,
310
+ };
311
+ },
312
+ removeCommand(packageReference, workspace, operationOptions = {}) {
313
+ const cwd = resolveCwd(packageReference, workspace, operationOptions);
314
+ const packageId = normalizeString(packageReference.packageId, null);
315
+ if (!packageId) {
316
+ throw new Error(
317
+ "npm package-manager removal requires packageId on the workspace package reference.",
318
+ );
319
+ }
320
+ return {
321
+ command: packageManagerCommand,
322
+ args: ["uninstall", "--no-save", packageId],
323
+ cwd,
324
+ };
325
+ },
326
+ async resolveInstallRecord({
327
+ packageReference,
328
+ workspace,
329
+ commandResult,
330
+ options: operationOptions = {},
331
+ }) {
332
+ const cwd = resolveCwd(packageReference, workspace, operationOptions);
333
+ const explicitSourceRef = normalizeString(packageReference.sourceRef, null);
334
+ const installPath =
335
+ normalizeString(packageReference.installPath, null) ??
336
+ resolveNodeModulesInstallPath(cwd, packageReference.packageId);
337
+ const pluginPackage = resolvePluginPackage
338
+ ? await resolvePluginPackage(
339
+ packageReference,
340
+ workspace,
341
+ commandResult,
342
+ operationOptions,
343
+ )
344
+ : undefined;
345
+ return {
346
+ packageId: normalizeString(packageReference.packageId, null),
347
+ pluginId: normalizeString(packageReference.pluginId, null),
348
+ version: normalizeString(packageReference.version, null),
349
+ sourceType:
350
+ normalizeString(packageReference.sourceType, null) ?? "npm",
351
+ sourceRef: explicitSourceRef,
352
+ installPath,
353
+ metadata: {
354
+ packageManager: packageManagerCommand,
355
+ requestedSpecifier:
356
+ explicitSourceRef ?? formatPackageInstallSpecifier(packageReference),
357
+ ...(isObject(packageReference.metadata) ? packageReference.metadata : {}),
358
+ },
359
+ ...(pluginPackage ? { pluginPackage } : {}),
360
+ };
361
+ },
362
+ });
363
+ }
364
+
365
+ export default {
366
+ createCommandPackageManager,
367
+ createNodeCommandRunner,
368
+ createNpmPackageManager,
369
+ };
@@ -0,0 +1,134 @@
1
+ import { RecommendedCapabilityIds } from "../compliance/index.js";
2
+ import { HostedRuntimeAdapter, HostedRuntimeEngine } from "./constants.js";
3
+
4
+ function normalizeString(value, fallback = null) {
5
+ if (typeof value !== "string") {
6
+ return fallback;
7
+ }
8
+ const normalized = value.trim().toLowerCase();
9
+ return normalized.length > 0 ? normalized : fallback;
10
+ }
11
+
12
+ function normalizeStringArray(values) {
13
+ if (!Array.isArray(values)) {
14
+ return [];
15
+ }
16
+ return values
17
+ .map((value) => normalizeString(value, null))
18
+ .filter((value) => value !== null);
19
+ }
20
+
21
+ const AllKnownCapabilities = Object.freeze(
22
+ Array.from(new Set(RecommendedCapabilityIds)).sort(),
23
+ );
24
+
25
+ const BrowserCapabilityProfile = Object.freeze([
26
+ "clock",
27
+ "random",
28
+ "logging",
29
+ "timers",
30
+ "schedule_cron",
31
+ "http",
32
+ "websocket",
33
+ "pubsub",
34
+ "protocol_dial",
35
+ "storage_query",
36
+ "context_read",
37
+ "context_write",
38
+ "crypto_hash",
39
+ "crypto_sign",
40
+ "crypto_verify",
41
+ "crypto_encrypt",
42
+ "crypto_decrypt",
43
+ "crypto_key_agreement",
44
+ "crypto_kdf",
45
+ "scene_access",
46
+ "entity_access",
47
+ "render_hooks",
48
+ ]);
49
+
50
+ const WasiCapabilityProfile = Object.freeze([
51
+ "clock",
52
+ "random",
53
+ "pipe",
54
+ "filesystem",
55
+ "storage_query",
56
+ "context_read",
57
+ "crypto_hash",
58
+ ]);
59
+
60
+ const EngineCapabilityProfiles = Object.freeze({
61
+ [HostedRuntimeEngine.NODE]: AllKnownCapabilities,
62
+ [HostedRuntimeEngine.DENO]: AllKnownCapabilities,
63
+ [HostedRuntimeEngine.BUN]: AllKnownCapabilities,
64
+ [HostedRuntimeEngine.BROWSER]: BrowserCapabilityProfile,
65
+ [HostedRuntimeEngine.WASI]: WasiCapabilityProfile,
66
+ [HostedRuntimeEngine.GO]: AllKnownCapabilities,
67
+ });
68
+
69
+ export function normalizeHostedRuntimeEngine(value, fallback = null) {
70
+ const normalized = normalizeString(value, null);
71
+ if (!normalized) {
72
+ return fallback;
73
+ }
74
+ return Object.values(HostedRuntimeEngine).includes(normalized)
75
+ ? normalized
76
+ : fallback;
77
+ }
78
+
79
+ export function listHostedRuntimeCapabilities({ adapter = null, engine = null } = {}) {
80
+ const normalizedAdapter = normalizeString(adapter, null);
81
+ const normalizedEngine = normalizeHostedRuntimeEngine(engine, null);
82
+
83
+ if (normalizedAdapter === HostedRuntimeAdapter.GO_SDN) {
84
+ return [...AllKnownCapabilities];
85
+ }
86
+
87
+ if (
88
+ normalizedAdapter === HostedRuntimeAdapter.SDN_JS ||
89
+ normalizedEngine !== null
90
+ ) {
91
+ return [
92
+ ...(
93
+ EngineCapabilityProfiles[
94
+ normalizedEngine ?? HostedRuntimeEngine.NODE
95
+ ] ?? AllKnownCapabilities
96
+ ),
97
+ ];
98
+ }
99
+
100
+ return [...AllKnownCapabilities];
101
+ }
102
+
103
+ export function evaluateHostedCapabilitySupport({
104
+ adapter = null,
105
+ engine = null,
106
+ requiredCapabilities = [],
107
+ } = {}) {
108
+ const supportedCapabilities = listHostedRuntimeCapabilities({
109
+ adapter,
110
+ engine,
111
+ });
112
+ const supportedSet = new Set(supportedCapabilities);
113
+ const normalizedRequired = Array.from(
114
+ new Set(normalizeStringArray(requiredCapabilities)),
115
+ ).sort();
116
+ const unsupportedCapabilities = normalizedRequired.filter(
117
+ (capability) => !supportedSet.has(capability),
118
+ );
119
+
120
+ return {
121
+ adapter: normalizeString(adapter, null),
122
+ engine: normalizeHostedRuntimeEngine(engine, null),
123
+ supportedCapabilities,
124
+ requiredCapabilities: normalizedRequired,
125
+ unsupportedCapabilities,
126
+ ok: unsupportedCapabilities.length === 0,
127
+ };
128
+ }
129
+
130
+ export default {
131
+ evaluateHostedCapabilitySupport,
132
+ listHostedRuntimeCapabilities,
133
+ normalizeHostedRuntimeEngine,
134
+ };
@@ -0,0 +1,106 @@
1
+ import { normalizeCompiledArtifact } from "../deploy/FlowDeploymentClient.js";
2
+
3
+ export const DefaultRequiredRuntimeExportRoles = Object.freeze([
4
+ "descriptorSymbol",
5
+ "resetStateSymbol",
6
+ "enqueueTriggerSymbol",
7
+ "enqueueEdgeSymbol",
8
+ "readyNodeSymbol",
9
+ "beginInvocationSymbol",
10
+ "completeInvocationSymbol",
11
+ "applyInvocationResultSymbol",
12
+ ]);
13
+
14
+ function getWasmExports(target = null) {
15
+ if (target && typeof target === "object") {
16
+ if (
17
+ target.instance?.exports &&
18
+ typeof target.instance.exports === "object"
19
+ ) {
20
+ return target.instance.exports;
21
+ }
22
+ if (target.exports && typeof target.exports === "object") {
23
+ return target.exports;
24
+ }
25
+ return target;
26
+ }
27
+ return null;
28
+ }
29
+
30
+ function resolveRuntimeExport({ role, symbol, wasmExports, requiredRoles }) {
31
+ const required = requiredRoles.has(role);
32
+ if (!symbol) {
33
+ if (required) {
34
+ throw new Error(
35
+ `Compiled runtime ABI is missing the symbol name for ${role}.`,
36
+ );
37
+ }
38
+ return null;
39
+ }
40
+ const candidateSymbols = [symbol, `_${symbol}`];
41
+ const resolvedSymbol = candidateSymbols.find(
42
+ (candidate) => candidate in wasmExports,
43
+ );
44
+ if (!resolvedSymbol) {
45
+ throw new Error(
46
+ `Compiled runtime ABI export "${symbol}" for ${role} is not present on the wasm instance.`,
47
+ );
48
+ }
49
+ return {
50
+ role,
51
+ symbol,
52
+ resolvedSymbol,
53
+ value: wasmExports[resolvedSymbol],
54
+ };
55
+ }
56
+
57
+ export async function bindCompiledRuntimeAbi({
58
+ artifact,
59
+ instance = null,
60
+ wasmExports = null,
61
+ requiredRoles = DefaultRequiredRuntimeExportRoles,
62
+ } = {}) {
63
+ const normalizedArtifact = await normalizeCompiledArtifact(artifact);
64
+ const resolvedWasmExports = getWasmExports(wasmExports ?? instance);
65
+
66
+ if (!resolvedWasmExports || typeof resolvedWasmExports !== "object") {
67
+ throw new Error(
68
+ "bindCompiledRuntimeAbi requires a WebAssembly instance or exports object.",
69
+ );
70
+ }
71
+
72
+ const requiredRoleSet = new Set(
73
+ Array.isArray(requiredRoles)
74
+ ? requiredRoles
75
+ : DefaultRequiredRuntimeExportRoles,
76
+ );
77
+ const resolvedByRole = {};
78
+ const resolvedBySymbol = {};
79
+
80
+ for (const [role, symbol] of Object.entries(
81
+ normalizedArtifact.runtimeExports,
82
+ )) {
83
+ const binding = resolveRuntimeExport({
84
+ role,
85
+ symbol,
86
+ wasmExports: resolvedWasmExports,
87
+ requiredRoles: requiredRoleSet,
88
+ });
89
+ resolvedByRole[role] = binding?.value ?? null;
90
+ if (binding) {
91
+ resolvedBySymbol[binding.symbol] = binding.value;
92
+ resolvedBySymbol[binding.resolvedSymbol] = binding.value;
93
+ }
94
+ }
95
+
96
+ return {
97
+ artifact: normalizedArtifact,
98
+ runtimeExports: normalizedArtifact.runtimeExports,
99
+ requiredRoles: Array.from(requiredRoleSet),
100
+ wasmExports: resolvedWasmExports,
101
+ resolvedByRole,
102
+ resolvedBySymbol,
103
+ };
104
+ }
105
+
106
+ export default bindCompiledRuntimeAbi;