@pulse-compute/wasm-compiler 0.0.0 → 1.0.0-beta.2

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 (104) hide show
  1. package/README.md +53 -1
  2. package/bin/provider-proof-composition.js +34 -0
  3. package/bin/pulsewasm-extract.js +20 -0
  4. package/package.json +60 -5
  5. package/src/artifacts-dir.js +13 -0
  6. package/src/ast-json.js +52 -0
  7. package/src/build-manifest.js +354 -0
  8. package/src/canonical-api-compiler.js +269 -0
  9. package/src/canonical-native-compiler.js +411 -0
  10. package/src/canonical-native-plan.js +1478 -0
  11. package/src/canonical-project-compiler.js +1224 -0
  12. package/src/canonical-router-compiler.js +25 -0
  13. package/src/cli-intents.js +1235 -0
  14. package/src/cli.js +1927 -0
  15. package/src/codegen/assemblyscript-compile.js +3 -0
  16. package/src/codegen/assemblyscript-core.js +3 -0
  17. package/src/codegen/assemblyscript-shape.js +3 -0
  18. package/src/codegen/assemblyscript-wasm-smoke.js +3 -0
  19. package/src/codegen/backend-capabilities.js +3 -0
  20. package/src/codegen/channel-broadcaster.js +3 -0
  21. package/src/codegen/compiled-handlers.js +3 -0
  22. package/src/codegen/compiled-wasm-runtime.js +3 -0
  23. package/src/codegen/config-references.js +248 -0
  24. package/src/codegen/dispatch-ts.js +145 -0
  25. package/src/codegen/effect-composition.js +331 -0
  26. package/src/codegen/effect-runtime.js +418 -0
  27. package/src/codegen/execution-harness-ts.js +467 -0
  28. package/src/codegen/handler-bindings-ts.js +298 -0
  29. package/src/codegen/handler-library-contracts.js +3 -0
  30. package/src/codegen/host-capabilities.js +3 -0
  31. package/src/codegen/host-runtime-kernel.js +3 -0
  32. package/src/codegen/integrated-compiled-app.js +3 -0
  33. package/src/codegen/json-body.js +3 -0
  34. package/src/codegen/library-sidecars.js +3 -0
  35. package/src/codegen/local-harness-ts.js +453 -0
  36. package/src/codegen/pulse-wrapper.js +217 -0
  37. package/src/codegen/request-result-headers.js +3 -0
  38. package/src/codegen/schema-json-compile.js +3 -0
  39. package/src/codegen/schema-json-sidecar-v2.js +3 -0
  40. package/src/codegen/schema-json-sidecar.js +3 -0
  41. package/src/codegen/streaming-passthrough.js +3 -0
  42. package/src/codegen/wasm-host-abi.js +3 -0
  43. package/src/codegen/wasm-host-bridge.js +3 -0
  44. package/src/compiled-wasm-host-runtime-kv.js +3 -0
  45. package/src/config-resolver.js +813 -0
  46. package/src/crypto-requirement-planner.js +89 -0
  47. package/src/definitions/config-schema.js +14 -0
  48. package/src/definitions/handler-roles.js +14 -0
  49. package/src/definitions/path-grammar.js +14 -0
  50. package/src/definitions/router-api.js +14 -0
  51. package/src/diagnostics/codes.js +14 -0
  52. package/src/diagnostics/reporter.js +14 -0
  53. package/src/diagnostics.js +14 -0
  54. package/src/dispatch-table.js +400 -0
  55. package/src/events/event-emit.js +265 -0
  56. package/src/events/event-topology.js +127 -0
  57. package/src/execution-plan.js +463 -0
  58. package/src/extractor.js +2816 -0
  59. package/src/handler-eval.js +1154 -0
  60. package/src/handler-table.js +326 -0
  61. package/src/index.js +19 -0
  62. package/src/javascript-application-plan.js +181 -0
  63. package/src/kv-provider.js +3 -0
  64. package/src/path-table.js +60 -0
  65. package/src/path.js +14 -0
  66. package/src/patterns/config-define.js +30 -0
  67. package/src/patterns/dependency-call.js +18 -0
  68. package/src/patterns/env-lookup.js +13 -0
  69. package/src/patterns/handler-reference.js +29 -0
  70. package/src/patterns/path-literal.js +35 -0
  71. package/src/patterns/result.js +15 -0
  72. package/src/patterns/router-chain-call.js +50 -0
  73. package/src/patterns/router-construction.js +19 -0
  74. package/src/project/package-reachability.js +782 -0
  75. package/src/project/reachable-graph-builder.js +992 -0
  76. package/src/project/reachable-graph-contract.js +54 -0
  77. package/src/project/reachable-graph-implementation.js +36 -0
  78. package/src/project/router-module-linker.js +710 -0
  79. package/src/project-config-compiler.js +222 -0
  80. package/src/project-target-support.js +500 -0
  81. package/src/provider-toolchain.js +299 -0
  82. package/src/spine/async-surface-normalizer.js +328 -0
  83. package/src/spine/canonical-handler-ir.js +336 -0
  84. package/src/spine/canonical-native-module.js +87 -0
  85. package/src/spine/canonical-native-plan.js +89 -0
  86. package/src/spine/canonical-project.js +76 -0
  87. package/src/spine/canonical-router.js +155 -0
  88. package/src/spine/canonical-source.js +165 -0
  89. package/src/spine/diagnostic-authority.js +290 -0
  90. package/src/spine/equivalence.js +262 -0
  91. package/src/spine/guest-unit-stage.js +87 -0
  92. package/src/spine/handler-ir-emitter.js +455 -0
  93. package/src/spine/handler-ir-managed.js +1598 -0
  94. package/src/spine/handler-ir.js +797 -0
  95. package/src/spine/handler-surface-authority.js +588 -0
  96. package/src/spine/package-operation-seam.js +1015 -0
  97. package/src/spine/pipeline.js +202 -0
  98. package/src/spine/plain-handler-frontend.js +545 -0
  99. package/src/spine/provider-requirement-authority.js +208 -0
  100. package/src/spine/router-control-contract.js +17 -0
  101. package/src/spine/router-handler-frontend.js +514 -0
  102. package/src/spine/router-handler-ir.js +372 -0
  103. package/src/spine/router-topology-frontend.js +638 -0
  104. package/src/stable-id.js +14 -0
@@ -0,0 +1,269 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+ const vm = require('node:vm');
6
+ const ts = require('typescript');
7
+ const { executeCanonicalSourceSpine } = require('./spine/canonical-source.js');
8
+ const {
9
+ extractFetchChain,
10
+ extractProviderCall,
11
+ extractKvNamespaceDeclaration
12
+ } = require('./spine/handler-surface-authority.js');
13
+ const {
14
+ payloadForCanonicalHandlerIr
15
+ } = require('./spine/canonical-handler-ir.js');
16
+ const {
17
+ emitCanonicalHandlerGenerator
18
+ } = require('./spine/handler-ir-emitter.js');
19
+ const {
20
+ SUPPORTED_FETCH_DECODERS,
21
+ ALLOWED_IMPORTS,
22
+ CanonicalCompileError
23
+ } = require('./spine/plain-handler-frontend.js');
24
+
25
+ function loadCanonicalRuntimeContract() {
26
+ try { return require('@pulse-compute/wasm-contracts/handler/canonical-runtime'); }
27
+ catch (error) {
28
+ if (error && ['MODULE_NOT_FOUND', 'ERR_PACKAGE_PATH_NOT_EXPORTED'].includes(error.code)) return require('../../contracts/src/handler/canonical-runtime.js');
29
+ throw error;
30
+ }
31
+ }
32
+
33
+ const canonicalRuntimeContract = loadCanonicalRuntimeContract();
34
+
35
+ const CANONICAL_API_COMPILER_VERSION = 'pulse.canonical-api-compiler.v7';
36
+
37
+ function findSourceRoot(start) {
38
+ let current = path.resolve(start);
39
+ for (;;) {
40
+ if (fs.existsSync(path.join(current, 'package.json'))) return current;
41
+ const parent = path.dirname(current);
42
+ if (parent === current) return path.resolve(start);
43
+ current = parent;
44
+ }
45
+ }
46
+
47
+ function stableSourceName(file, options = {}) {
48
+ if (options.fileName) return String(options.fileName).replace(/\\/g, '/');
49
+ const absolute = path.resolve(file);
50
+ const root = path.resolve(options.rootDir || findSourceRoot(path.dirname(absolute)));
51
+ const relative = path.relative(root, absolute).replace(/\\/g, '/');
52
+ return relative && !relative.startsWith('../') ? relative : path.basename(absolute);
53
+ }
54
+
55
+ function emitCanonicalProgramFromHandlerIr(ir, options = {}) {
56
+ const payload = payloadForCanonicalHandlerIr(ir);
57
+ const sourceFile = payload.sourceFile;
58
+ const schemaBundle = payload.schemaBundle;
59
+ const explicitParallelCount = ir.continuationSites.filter((site) => site.kind === 'parallel-group').length;
60
+ const metadata = Object.freeze({
61
+ version: ir.programVersion,
62
+ compilerVersion: ir.compilerVersion,
63
+ runtimeProtocolVersion: ir.runtimeProtocolVersion,
64
+ file: ir.file,
65
+ sourceHash: ir.sourceHash,
66
+ loweredSourceHash: ir.loweredSourceHash,
67
+ projectSourceHash: ir.projectSourceHash,
68
+ handler: 'default',
69
+ ctxParameter: ir.handler.ctxParameter,
70
+ capabilities: ir.capabilities,
71
+ providerOperations: ir.providerOperations,
72
+ effectSites: ir.effectSites,
73
+ continuationSites: ir.continuationSites,
74
+ effectCount: ir.effectSites.length,
75
+ continuationCount: ir.continuationSites.length,
76
+ groupedContinuationCount: ir.continuationSites.filter((site) => site.kind === 'fetch-group' || site.kind === 'parallel-group').length,
77
+ ...(explicitParallelCount > 0 ? { explicitParallelCount } : {}),
78
+ opaqueReturnCount: ir.continuationSites.filter((site) => site.kind === 'opaque-fetch-return').length,
79
+ schemaRegistry: ir.schema.registry,
80
+ schemaIds: ir.schema.ids,
81
+ responseCaseIds: ir.schema.responseCaseIds,
82
+ schemaSourceHash: ir.schema.sourceHash,
83
+ schemaRegistryHash: ir.schema.registryHash,
84
+ schemaCodecTableHash: ir.schema.codecTableHash,
85
+ schemaFullCodecRealization: ir.schema.fullCodecRealization,
86
+ schemaReferences: ir.schemaReferences,
87
+ schemaReferenceCount: ir.schemaReferences.length,
88
+ packageEffects: ir.packageEffects,
89
+ packageEffectCount: ir.packageEffects.length,
90
+ ...(ir.json ? { json: ir.json } : {}),
91
+ ...(ir.warnings ? { warnings: ir.warnings, warningCount: ir.warnings.length } : {}),
92
+ authoring: ir.authoring,
93
+ ...(ir.application ? { application: ir.application } : {}),
94
+ ...(ir.applicationEntries ? { applicationEntries: ir.applicationEntries } : {}),
95
+ ...(ir.events ? { events: ir.events } : {}),
96
+ router: ir.router,
97
+ compilerOwnedCalls: ir.compilerOwnedCalls,
98
+ compilerOwnedIntrinsics: ir.compilerOwnedIntrinsics,
99
+ compilerPreludeHash: ir.compilerPreludeHash,
100
+ userAuthoredAsync: ir.invariants.userAuthoredAsync,
101
+ promiseSemantics: ir.invariants.promiseSemantics,
102
+ asyncify: ir.invariants.asyncify,
103
+ ...(options.target === 'javascript' ? { target: 'javascript', promiseSemantics: true } : {})
104
+ });
105
+
106
+ // JavaScript executes the original module graph through its provider. The
107
+ // normalized IR describes recognized Pulse behavior only; erased awaits and
108
+ // source-runtime imports must never become an executable generator.
109
+ if (options.target === 'javascript') return Object.freeze({
110
+ ok: true,
111
+ version: CANONICAL_API_COMPILER_VERSION,
112
+ target: 'javascript',
113
+ metadata,
114
+ schemaBundle,
115
+ diagnostics: Object.freeze([])
116
+ });
117
+
118
+ const emitted = emitCanonicalHandlerGenerator(payload.operationIr);
119
+ const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
120
+ const generatorText = printer.printNode(ts.EmitHint.Unspecified, emitted.generator, sourceFile);
121
+ const metadataSource = JSON.stringify(metadata, null, 2);
122
+ const generatedTypeScript = [
123
+ schemaBundle.declarationSource,
124
+ payload.compilerPrelude,
125
+ generatorText,
126
+ `const __pulse_metadata = ${metadataSource};`,
127
+ 'module.exports = Object.freeze({',
128
+ ` version: ${JSON.stringify(canonicalRuntimeContract.CANONICAL_PROGRAM_VERSION)},`,
129
+ ' metadata: Object.freeze(__pulse_metadata),',
130
+ ' schemaCodecs: __pulse_schema_codecs,',
131
+ ' createHandler() { return __pulse_handler; }',
132
+ '});',
133
+ ''
134
+ ].join('\n');
135
+ const transpiled = ts.transpileModule(generatedTypeScript, {
136
+ fileName: `${ir.file}.generated.ts`,
137
+ compilerOptions: {
138
+ target: ts.ScriptTarget.ES2022,
139
+ module: ts.ModuleKind.CommonJS,
140
+ strict: true,
141
+ removeComments: false,
142
+ esModuleInterop: false
143
+ },
144
+ reportDiagnostics: true
145
+ });
146
+ const generatedSource = transpiled.outputText;
147
+ const generatedEsmTypeScript = [
148
+ schemaBundle.declarationSource,
149
+ payload.compilerPrelude,
150
+ generatorText,
151
+ `export const version = ${JSON.stringify(canonicalRuntimeContract.CANONICAL_PROGRAM_VERSION)};`,
152
+ `export const metadata = Object.freeze(${metadataSource});`,
153
+ 'export const schemaCodecs = __pulse_schema_codecs;',
154
+ 'export function createHandler() { return __pulse_handler; }',
155
+ ''
156
+ ].join('\n');
157
+ const esmTranspiled = ts.transpileModule(generatedEsmTypeScript, {
158
+ fileName: `${ir.file}.generated.mts`,
159
+ compilerOptions: {
160
+ target: ts.ScriptTarget.ES2022,
161
+ module: ts.ModuleKind.ES2022,
162
+ strict: true,
163
+ removeComments: false
164
+ },
165
+ reportDiagnostics: true
166
+ });
167
+ const generatedEsmSource = esmTranspiled.outputText;
168
+
169
+ return Object.freeze({
170
+ ok: true,
171
+ version: CANONICAL_API_COMPILER_VERSION,
172
+ metadata,
173
+ schemaBundle,
174
+ generatedSource,
175
+ generatedEsmSource,
176
+ diagnostics: Object.freeze([])
177
+ });
178
+ }
179
+
180
+ const PLAIN_HANDLER_IMPLEMENTATION = Object.freeze({
181
+ compilerVersion: CANONICAL_API_COMPILER_VERSION,
182
+ programVersion: canonicalRuntimeContract.CANONICAL_PROGRAM_VERSION,
183
+ runtimeProtocolVersion: canonicalRuntimeContract.CANONICAL_RUNTIME_PROTOCOL_VERSION,
184
+ emitCanonicalProgram: emitCanonicalProgramFromHandlerIr
185
+ });
186
+
187
+ const JAVASCRIPT_HANDLER_INSPECTION = Object.freeze({
188
+ ...PLAIN_HANDLER_IMPLEMENTATION,
189
+ emitCanonicalProgram: (ir) => emitCanonicalProgramFromHandlerIr(ir, { target: 'javascript' })
190
+ });
191
+
192
+ function compileCanonicalSource(sourceText, options = {}) {
193
+ if (options.target !== undefined && !['native', 'javascript'].includes(options.target)) throw new TypeError('target must be native or javascript.');
194
+ return executeCanonicalSourceSpine(sourceText, options, options.target === 'javascript'
195
+ ? JAVASCRIPT_HANDLER_INSPECTION
196
+ : PLAIN_HANDLER_IMPLEMENTATION);
197
+ }
198
+
199
+ function compileCanonicalFile(file, options = {}) {
200
+ const absolute = path.resolve(file);
201
+ return compileCanonicalSource(fs.readFileSync(absolute, 'utf8'), { ...options, fileName: stableSourceName(absolute, options) });
202
+ }
203
+
204
+ function loadCanonicalModule(compiled, options = {}) {
205
+ if (!compiled || compiled.ok !== true || typeof compiled.generatedSource !== 'string') throw new TypeError('loadCanonicalModule requires a successful canonical compilation.');
206
+ const filename = options.fileName || `${compiled.metadata.file}.generated.cjs`;
207
+ const module = { exports: {} };
208
+ const script = new vm.Script(`(function(module, exports, require, __filename, __dirname) {\n${compiled.generatedSource}\n})`, { filename });
209
+ const fn = script.runInThisContext();
210
+ fn(module, module.exports, require, filename, path.dirname(filename));
211
+ return module.exports;
212
+ }
213
+
214
+ function writeCanonicalBuild(compiled, outDir, options = {}) {
215
+ if (!compiled || compiled.ok !== true || typeof compiled.generatedSource !== 'string') {
216
+ throw new TypeError('writeCanonicalBuild requires an executable canonical compilation; JavaScript projects use provider source packaging.');
217
+ }
218
+ const target = path.resolve(outDir);
219
+ fs.mkdirSync(target, { recursive: true });
220
+ const handlerFile = path.join(target, options.handlerFile || 'canonical-handler.cjs');
221
+ const programFile = path.join(target, options.programFile || 'canonical-program.json');
222
+ const esmHandlerFile = options.esmHandlerFile ? path.join(target, options.esmHandlerFile) : undefined;
223
+ const schemaActive = Boolean(compiled.schemaBundle && compiled.schemaBundle.active);
224
+ const schemaRegistryFile = schemaActive ? path.join(target, options.schemaRegistryFile || 'schema-json-registry.json') : undefined;
225
+ const schemaCodecsFile = schemaActive ? path.join(target, options.schemaCodecsFile || 'schema-json-codecs.cjs') : undefined;
226
+ fs.writeFileSync(handlerFile, compiled.generatedSource);
227
+ if (esmHandlerFile) fs.writeFileSync(esmHandlerFile, compiled.generatedEsmSource);
228
+ if (schemaRegistryFile) fs.writeFileSync(schemaRegistryFile, `${JSON.stringify(compiled.schemaBundle.registry, null, 2)}\n`);
229
+ if (schemaCodecsFile) fs.writeFileSync(schemaCodecsFile, compiled.schemaBundle.moduleSource);
230
+ const packageInspectionArtifacts = Object.freeze((compiled.packageInspection && compiled.packageInspection.artifacts || []).map((artifact) => {
231
+ const relativeFile = String(artifact.file || '').replace(/\\/g, '/');
232
+ const artifactFile = path.resolve(target, relativeFile);
233
+ const relativeArtifact = path.relative(target, artifactFile);
234
+ if (!relativeFile || relativeArtifact.startsWith('..') || path.isAbsolute(relativeArtifact)) {
235
+ const error = new Error(`Package inspection artifact ${artifact.id || '<unknown>'} must remain inside the canonical build output.`);
236
+ error.code = 'PULSE_PACKAGE_INSPECTION_ARTIFACT_UNSAFE';
237
+ error.detail = Object.freeze({ id: artifact.id, file: relativeFile });
238
+ throw error;
239
+ }
240
+ fs.mkdirSync(path.dirname(artifactFile), { recursive: true });
241
+ fs.writeFileSync(artifactFile, `${JSON.stringify(artifact.data, null, 2)}\n`);
242
+ return Object.freeze({ id: artifact.id, contractId: artifact.contractId, file: artifactFile });
243
+ }));
244
+ fs.writeFileSync(programFile, `${JSON.stringify({
245
+ ...compiled.metadata,
246
+ generatedHandler: path.basename(handlerFile),
247
+ generatedEsmHandler: esmHandlerFile ? path.basename(esmHandlerFile) : undefined,
248
+ generatedSchemaRegistry: schemaRegistryFile ? path.basename(schemaRegistryFile) : undefined,
249
+ generatedSchemaCodecs: schemaCodecsFile ? path.basename(schemaCodecsFile) : undefined
250
+ }, null, 2)}\n`);
251
+ return Object.freeze({ outDir: target, handlerFile, esmHandlerFile, programFile, schemaRegistryFile, schemaCodecsFile, packageInspectionArtifacts, metadata: compiled.metadata });
252
+ }
253
+
254
+ module.exports = {
255
+ CANONICAL_API_COMPILER_VERSION,
256
+ CANONICAL_PROGRAM_VERSION: canonicalRuntimeContract.CANONICAL_PROGRAM_VERSION,
257
+ CANONICAL_RUNTIME_PROTOCOL_VERSION: canonicalRuntimeContract.CANONICAL_RUNTIME_PROTOCOL_VERSION,
258
+ SUPPORTED_FETCH_DECODERS,
259
+ ALLOWED_IMPORTS,
260
+ CanonicalCompileError,
261
+ compileCanonicalSource,
262
+ compileCanonicalFile,
263
+ loadCanonicalModule,
264
+ writeCanonicalBuild,
265
+ extractFetchChain,
266
+ extractProviderCall,
267
+ extractKvNamespaceDeclaration,
268
+ stableSourceName
269
+ };
@@ -0,0 +1,411 @@
1
+ 'use strict';
2
+
3
+ const crypto = require('node:crypto');
4
+ const fs = require('node:fs');
5
+ const os = require('node:os');
6
+ const path = require('node:path');
7
+ const { spawnSync } = require('node:child_process');
8
+ const { executeCanonicalNativeModuleSpine } = require('./spine/canonical-native-module.js');
9
+ const {
10
+ packageLoweringForCanonicalNativePlan,
11
+ providerRequirementsForCanonicalNativePlan
12
+ } = require('./spine/canonical-native-plan.js');
13
+ const { packageOperationRecognitionFromEffects, lowerCanonicalPackageOperations } = require('./spine/package-operation-seam.js');
14
+ const { collectProviderRequirements, assertProviderRequirementsForPlan } = require('./spine/provider-requirement-authority.js');
15
+ const { realizeSelectedGuestUnits } = require('./spine/guest-unit-stage.js');
16
+ const {
17
+ PACKAGE_REALIZATION_ARTIFACT_SET_VERSION
18
+ } = require('@pulse-compute/wasm-contracts/package/package-contract');
19
+
20
+ function loadNativePlanCompiler() {
21
+ try { return require('@pulse-compute/wasm-compiler/canonical-native-plan'); }
22
+ catch (error) {
23
+ if (error && ['MODULE_NOT_FOUND', 'ERR_PACKAGE_PATH_NOT_EXPORTED'].includes(error.code)) return require('./canonical-native-plan.js');
24
+ throw error;
25
+ }
26
+ }
27
+
28
+ function loadRuntimeCore() {
29
+ try { return require('@pulse-compute/wasm-runtime-core-as/compiler/canonical-native'); }
30
+ catch (error) {
31
+ if (error && ['MODULE_NOT_FOUND', 'ERR_PACKAGE_PATH_NOT_EXPORTED'].includes(error.code)) return require('../../runtime-core-as/src/compiler/canonical-native.js');
32
+ throw error;
33
+ }
34
+ }
35
+
36
+ function loadRuntimeContract() {
37
+ try { return require('@pulse-compute/wasm-contracts/handler/canonical-native-runtime'); }
38
+ catch (error) {
39
+ if (error && ['MODULE_NOT_FOUND', 'ERR_PACKAGE_PATH_NOT_EXPORTED'].includes(error.code)) return require('../../contracts/src/handler/canonical-native-runtime.js');
40
+ throw error;
41
+ }
42
+ }
43
+
44
+ function loadEventContract() {
45
+ try { return require('@pulse-compute/wasm-contracts/events'); }
46
+ catch (error) {
47
+ if (error && ['MODULE_NOT_FOUND', 'ERR_PACKAGE_PATH_NOT_EXPORTED'].includes(error.code)) return require('../../contracts/src/events/contracts.js');
48
+ throw error;
49
+ }
50
+ }
51
+
52
+ function loadBuildSupport() {
53
+ try { return require('@pulse-compute/wasm-build-support/assemblyscript-compile'); }
54
+ catch (error) {
55
+ if (error && ['MODULE_NOT_FOUND', 'ERR_PACKAGE_PATH_NOT_EXPORTED'].includes(error.code)) return require('../../build-support/src/assemblyscript-compile.js');
56
+ throw error;
57
+ }
58
+ }
59
+
60
+ const nativePlanCompiler = loadNativePlanCompiler();
61
+ const runtimeCore = loadRuntimeCore();
62
+ const runtimeContract = loadRuntimeContract();
63
+ const eventContract = loadEventContract();
64
+ const { resolveAsc } = loadBuildSupport();
65
+ const { memoryAbi } = (() => {
66
+ try {
67
+ return require('@pulse-compute/wasm-guest-link');
68
+ } catch (error) {
69
+ if (error && error.code === 'MODULE_NOT_FOUND') return require('../../wasm-guest-link/src/index.js');
70
+ throw error;
71
+ }
72
+ })();
73
+ const {
74
+ appendAssemblyScriptOptimizationArgs,
75
+ resolveNativeOptimization
76
+ } = require('@pulse-compute/wasm-build-support/native-optimization');
77
+
78
+ class CanonicalNativeCompileError extends Error {
79
+ constructor(message, detail = {}) {
80
+ super(message);
81
+ this.name = 'CanonicalNativeCompileError';
82
+ this.code = 'PULSE_CANONICAL_NATIVE_COMPILE_FAILED';
83
+ this.detail = Object.freeze({ ...detail });
84
+ }
85
+ }
86
+
87
+ function sha256(value) {
88
+ return crypto.createHash('sha256').update(value).digest('hex');
89
+ }
90
+
91
+ function stableObject(value) {
92
+ if (Array.isArray(value)) return value.map(stableObject);
93
+ if (!value || typeof value !== 'object') return value;
94
+ const out = {};
95
+ for (const key of Object.keys(value).sort()) if (value[key] !== undefined) out[key] = stableObject(value[key]);
96
+ return out;
97
+ }
98
+
99
+ function deepFreeze(value) {
100
+ if (!value || typeof value !== 'object' || Object.isFrozen(value)) return value;
101
+ for (const child of Object.values(value)) deepFreeze(child);
102
+ return Object.freeze(value);
103
+ }
104
+
105
+ function stableStringify(value, space = 0) {
106
+ return JSON.stringify(stableObject(value), null, space);
107
+ }
108
+
109
+ function inspectCanonicalNativeWasm(input, options = {}) {
110
+ const bytes = Buffer.isBuffer(input) ? input : fs.readFileSync(path.resolve(input));
111
+ if (!WebAssembly.validate(bytes)) throw new CanonicalNativeCompileError('Generated canonical native Wasm is not valid WebAssembly.');
112
+ const module = new WebAssembly.Module(bytes);
113
+ const imports = WebAssembly.Module.imports(module).map((entry) => Object.freeze({ module: entry.module, name: entry.name, kind: entry.kind }));
114
+ const exports = WebAssembly.Module.exports(module).map((entry) => Object.freeze({ name: entry.name, kind: entry.kind }));
115
+ const unexpectedModules = [...new Set(imports.map((entry) => entry.module).filter((name) => !['pulse_host', 'env'].includes(name)))];
116
+ if (unexpectedModules.length > 0) throw new CanonicalNativeCompileError('Canonical native Wasm imports an unsupported module.', { unexpectedModules, imports });
117
+
118
+ const allowedPulseImports = new Set(runtimeContract.CANONICAL_NATIVE_IMPORT_NAMES);
119
+ const pulseImports = imports.filter((entry) => entry.module === 'pulse_host').map((entry) => entry.name).sort();
120
+ const unexpectedPulseImports = pulseImports.filter((name) => !allowedPulseImports.has(name));
121
+ if (unexpectedPulseImports.length > 0) {
122
+ throw new CanonicalNativeCompileError('Canonical native Wasm imports a function outside the versioned pulse_host ABI.', { unexpectedPulseImports, pulseImports });
123
+ }
124
+
125
+ const allowedEnvImports = new Set(runtimeContract.CANONICAL_NATIVE_ALLOWED_ENV_IMPORTS);
126
+ const unexpectedEnvImports = imports.filter((entry) => entry.module === 'env' && !allowedEnvImports.has(entry.name));
127
+ if (unexpectedEnvImports.length > 0) {
128
+ throw new CanonicalNativeCompileError('Canonical native Wasm imports an unsupported AssemblyScript environment function.', { unexpectedEnvImports });
129
+ }
130
+
131
+ const exportNames = new Set(exports.map((entry) => entry.name));
132
+ const missingExports = runtimeContract.CANONICAL_NATIVE_EXPORT_NAMES.filter((name) => !exportNames.has(name));
133
+ if (missingExports.length > 0) throw new CanonicalNativeCompileError('Canonical native Wasm is missing required ABI exports.', { missingExports, exports });
134
+ const plan = options.plan;
135
+ const eventReachable = Boolean(plan && plan.events && plan.events.catalog && plan.events.catalog.events.length > 0);
136
+ const eventExportNames = eventContract.EVENT_NATIVE_ABI_EXTENSION.exports.map((entry) => entry.name);
137
+ const presentEventExports = eventExportNames.filter((name) => exportNames.has(name));
138
+ if (eventReachable && presentEventExports.length !== eventExportNames.length) {
139
+ throw new CanonicalNativeCompileError('Event-reachable canonical native Wasm is missing its conditional event ABI exports.', {
140
+ missingEventExports: eventExportNames.filter((name) => !exportNames.has(name)),
141
+ exports
142
+ });
143
+ }
144
+ if (plan && !eventReachable && presentEventExports.length > 0) {
145
+ throw new CanonicalNativeCompileError('HTTP-only canonical native Wasm unexpectedly exposes the conditional event ABI.', { presentEventExports });
146
+ }
147
+ return Object.freeze({
148
+ valid: true,
149
+ bytes: bytes.length,
150
+ sha256: sha256(bytes),
151
+ magic: bytes.subarray(0, 8).toString('hex'),
152
+ imports: Object.freeze(imports),
153
+ exports: Object.freeze(exports),
154
+ importModules: Object.freeze([...new Set(imports.map((entry) => entry.module))].sort())
155
+ });
156
+ }
157
+
158
+ function resolveProviderRequirements(plan) {
159
+ const attached = providerRequirementsForCanonicalNativePlan(plan);
160
+ if (attached) return attached;
161
+ const recognition = packageOperationRecognitionFromEffects((plan.packages && plan.packages.effects) || []);
162
+ return collectProviderRequirements(plan, lowerCanonicalPackageOperations(recognition));
163
+ }
164
+
165
+ function realizeCanonicalNativePlan(plan, options = {}, providerRequirements) {
166
+ try {
167
+ assertProviderRequirementsForPlan(providerRequirements, plan);
168
+ } catch (error) {
169
+ throw new CanonicalNativeCompileError('Canonical native realization requires the matching provider-neutral requirement record.', {
170
+ causeCode: error && error.code,
171
+ cause: error && error.message,
172
+ causeDetail: error && error.detail
173
+ });
174
+ }
175
+ const validation = nativePlanCompiler.validateCanonicalNativePlan(plan);
176
+ const packageLowering = packageLoweringForCanonicalNativePlan(plan);
177
+ const realizationArtifacts = Object.freeze((packageLowering && packageLowering.realizationArtifacts || [])
178
+ .map((artifact) => deepFreeze(stableObject(artifact))));
179
+ const guestUnits = Object.freeze((packageLowering && packageLowering.guestUnits || [])
180
+ .map((unit) => deepFreeze(stableObject(unit))));
181
+ const cwd = path.resolve(options.cwd || process.cwd());
182
+ const compilerPackageRoot = path.resolve(__dirname, '..');
183
+ const asc = resolveAsc(cwd) || resolveAsc(compilerPackageRoot);
184
+ if (!asc) throw new CanonicalNativeCompileError('AssemblyScript compiler dependency was not found.', { cwd, remediation: 'Install the lockfile-pinned AssemblyScript dependency before compiling native Wasm.' });
185
+ const generated = runtimeCore.generateCanonicalNativeAssemblyScript(plan, options);
186
+ const schemaCodecsActive = generated.manifest.schemaCodecs && generated.manifest.schemaCodecs.active === true;
187
+ let jsonAs;
188
+ if (schemaCodecsActive) {
189
+ let transform;
190
+ try {
191
+ transform = require.resolve('json-as', { paths: [compilerPackageRoot, cwd] });
192
+ } catch (error) {
193
+ throw new CanonicalNativeCompileError('The lockfile-pinned json-as transform was not found for Native schema codec compilation.', {
194
+ cwd,
195
+ package: 'json-as',
196
+ version: '1.5.0',
197
+ cause: error && error.message
198
+ });
199
+ }
200
+ const packageRoot = path.resolve(transform, '..', '..', '..');
201
+ const dependencyRoot = path.dirname(packageRoot);
202
+ const packageJson = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
203
+ if (packageJson.version !== '1.5.0') {
204
+ throw new CanonicalNativeCompileError('Native schema codec compilation requires json-as 1.5.0 exactly.', {
205
+ expected: '1.5.0',
206
+ actual: packageJson.version,
207
+ packageRoot
208
+ });
209
+ }
210
+ jsonAs = Object.freeze({ transform, packageRoot, dependencyRoot, version: packageJson.version });
211
+ }
212
+ const stagingDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pulse-canonical-native-'));
213
+ const requestedOutDir = options.outDir ? path.resolve(options.outDir) : undefined;
214
+ const outputDir = requestedOutDir || stagingDir;
215
+ fs.mkdirSync(outputDir, { recursive: true });
216
+ const sourceFile = path.join(stagingDir, 'canonical-native.as.ts');
217
+ const wasmFile = path.join(outputDir, options.wasmFile || 'canonical-native.wasm');
218
+ const watFile = path.join(outputDir, options.watFile || 'canonical-native.wat');
219
+ try {
220
+ fs.writeFileSync(sourceFile, generated.source, 'utf8');
221
+ // Compile from a stable, relative entry name so AssemblyScript's name section and
222
+ // text output do not capture the random staging directory.
223
+ const args = [
224
+ asc.script,
225
+ path.basename(sourceFile),
226
+ '--outFile', wasmFile,
227
+ '--textFile', watFile,
228
+ '--runtime', schemaCodecsActive ? 'incremental' : 'stub',
229
+ '--noAssert',
230
+ '--optimize'
231
+ ];
232
+ const optimization = appendAssemblyScriptOptimizationArgs(args, options.nativeOptimization);
233
+ if (guestUnits.length > 0) {
234
+ args.push(
235
+ '--importMemory',
236
+ '--noExportMemory',
237
+ '--initialMemory', String(memoryAbi.minimumPages),
238
+ '--maximumMemory', String(memoryAbi.maximumPages),
239
+ '--memoryBase', String(memoryAbi.layout.primaryStatic.start)
240
+ );
241
+ }
242
+ if (schemaCodecsActive) {
243
+ args.push(
244
+ '--exportRuntime',
245
+ '--transform', jsonAs.transform,
246
+ '--path', path.join(compilerPackageRoot, 'node_modules'),
247
+ '--path', jsonAs.dependencyRoot
248
+ );
249
+ }
250
+ const startedAt = Date.now();
251
+ const result = spawnSync(asc.executable, args, {
252
+ cwd: stagingDir,
253
+ encoding: 'utf8',
254
+ maxBuffer: 16 * 1024 * 1024,
255
+ timeout: Number(options.timeoutMs || 120000),
256
+ env: schemaCodecsActive
257
+ ? { ...process.env, JSON_STRICT: 'true', JSON_USE_FAST_PATH: '0' }
258
+ : process.env
259
+ });
260
+ const durationMs = Date.now() - startedAt;
261
+ if (result.error || result.status !== 0 || !fs.existsSync(wasmFile)) {
262
+ throw new CanonicalNativeCompileError('AssemblyScript failed to compile the canonical native plan.', {
263
+ status: result.status,
264
+ signal: result.signal,
265
+ error: result.error && result.error.message,
266
+ stdout: String(result.stdout || '').slice(-12000),
267
+ stderr: String(result.stderr || '').slice(-12000),
268
+ source: generated.source,
269
+ durationMs
270
+ });
271
+ }
272
+ return Object.freeze({
273
+ plan,
274
+ validation,
275
+ realizationArtifacts,
276
+ guestUnits,
277
+ generated,
278
+ wasm: fs.readFileSync(wasmFile),
279
+ wat: fs.existsSync(watFile) ? fs.readFileSync(watFile, 'utf8') : '',
280
+ assemblyScriptVersion: require(path.join(asc.packageRoot, 'package.json')).version,
281
+ jsonAsVersion: jsonAs && jsonAs.version,
282
+ optimization,
283
+ durationMs,
284
+ output: requestedOutDir ? Object.freeze({ outDir: outputDir, wasmFile, watFile }) : undefined
285
+ });
286
+ } finally {
287
+ fs.rmSync(stagingDir, { recursive: true, force: true });
288
+ }
289
+ }
290
+
291
+ function realizeCanonicalNativeGuestUnits(realization, plan, options = {}) {
292
+ return realizeSelectedGuestUnits(realization, realization.guestUnits, options);
293
+ }
294
+
295
+ function verifyCanonicalNativeRealization(realization) {
296
+ const inspection = inspectCanonicalNativeWasm(realization.wasm, { plan: realization.plan });
297
+ const artifactBytes = Buffer.from(stableStringify(realization.realizationArtifacts), 'utf8');
298
+ const packageRealizationArtifacts = Object.freeze({
299
+ version: PACKAGE_REALIZATION_ARTIFACT_SET_VERSION,
300
+ count: realization.realizationArtifacts.length,
301
+ ids: Object.freeze(realization.realizationArtifacts.map((artifact) => String(artifact.id)).sort()),
302
+ bytes: artifactBytes.length,
303
+ sha256: sha256(artifactBytes)
304
+ });
305
+ const manifest = Object.freeze({
306
+ ...realization.generated.manifest,
307
+ compilerVersion: runtimeContract.CANONICAL_NATIVE_COMPILER_VERSION,
308
+ assemblyScript: Object.freeze({ package: 'assemblyscript', version: realization.assemblyScriptVersion }),
309
+ optimization: resolveNativeOptimization(realization.optimization),
310
+ jsonAs: realization.jsonAsVersion
311
+ ? Object.freeze({ package: 'json-as', version: realization.jsonAsVersion, transform: true, strict: true })
312
+ : null,
313
+ wasm: Object.freeze({ bytes: inspection.bytes, sha256: inspection.sha256, magic: inspection.magic }),
314
+ wat: Object.freeze({ bytes: Buffer.byteLength(realization.wat), sha256: sha256(realization.wat) }),
315
+ importModules: inspection.importModules,
316
+ imports: inspection.imports,
317
+ exports: inspection.exports,
318
+ packageRealizationArtifacts,
319
+ ...(realization.guestLink ? {
320
+ guestUnitPlan: realization.guestLink.plan,
321
+ guestLinkReport: realization.guestLink.report,
322
+ finalWasmAudit: realization.guestLink.audit,
323
+ providerPackaging: realization.guestLink.providerPackaging
324
+ } : {}),
325
+ policy: runtimeContract.CANONICAL_NATIVE_POLICY
326
+ });
327
+ return Object.freeze({
328
+ version: runtimeContract.CANONICAL_NATIVE_WASM_VERSION,
329
+ compilerVersion: runtimeContract.CANONICAL_NATIVE_COMPILER_VERSION,
330
+ plan: realization.plan,
331
+ validation: realization.validation,
332
+ generated: realization.generated,
333
+ source: realization.generated.source,
334
+ sourceHash: realization.generated.sourceHash,
335
+ realizationArtifacts: realization.realizationArtifacts,
336
+ guestUnits: realization.guestUnits,
337
+ guestLink: realization.guestLink,
338
+ wasm: realization.wasm,
339
+ wat: realization.wat,
340
+ inspection,
341
+ manifest,
342
+ durationMs: realization.durationMs,
343
+ output: realization.output
344
+ });
345
+ }
346
+
347
+ function compileCanonicalNativePlan(plan, options = {}) {
348
+ return executeCanonicalNativeModuleSpine(plan, options, {
349
+ resolveProviderRequirements,
350
+ realize: realizeCanonicalNativePlan,
351
+ realizeGuests: realizeCanonicalNativeGuestUnits,
352
+ verify: verifyCanonicalNativeRealization
353
+ });
354
+ }
355
+
356
+ function writeCanonicalNativeModule(compiled, outDir, options = {}) {
357
+ if (!compiled || !Buffer.isBuffer(compiled.wasm) || !compiled.manifest) throw new TypeError('writeCanonicalNativeModule requires a compiled canonical native module.');
358
+ const target = path.resolve(outDir);
359
+ fs.mkdirSync(target, { recursive: true });
360
+ const sourceFile = path.join(target, options.sourceFile || 'canonical-native.as.ts');
361
+ const wasmFile = path.join(target, options.wasmFile || 'canonical-native.wasm');
362
+ const watFile = path.join(target, options.watFile || 'canonical-native.wat');
363
+ const planFile = path.join(target, options.planFile || 'canonical-native-plan.json');
364
+ const manifestFile = path.join(target, options.manifestFile || 'canonical-native-manifest.json');
365
+ const realizationArtifactsFile = compiled.realizationArtifacts.length > 0
366
+ ? path.join(target, options.realizationArtifactsFile || 'package-artifacts.json')
367
+ : undefined;
368
+ const guestUnitPlanFile = compiled.guestLink
369
+ ? path.join(target, options.guestUnitPlanFile || 'guest-unit-plan.json')
370
+ : undefined;
371
+ const guestLinkReportFile = compiled.guestLink
372
+ ? path.join(target, options.guestLinkReportFile || 'guest-link-report.json')
373
+ : undefined;
374
+ const finalWasmAuditFile = compiled.guestLink
375
+ ? path.join(target, options.finalWasmAuditFile || 'final-wasm-audit.json')
376
+ : undefined;
377
+ fs.writeFileSync(sourceFile, compiled.source, 'utf8');
378
+ fs.writeFileSync(wasmFile, compiled.wasm);
379
+ fs.writeFileSync(watFile, compiled.wat, 'utf8');
380
+ fs.writeFileSync(planFile, `${nativePlanCompiler.stableStringify(compiled.plan, 2)}\n`, 'utf8');
381
+ fs.writeFileSync(manifestFile, `${stableStringify(compiled.manifest, 2)}\n`, 'utf8');
382
+ if (realizationArtifactsFile) {
383
+ fs.writeFileSync(realizationArtifactsFile, `${stableStringify(compiled.realizationArtifacts, 2)}\n`, 'utf8');
384
+ }
385
+ if (guestUnitPlanFile) fs.writeFileSync(guestUnitPlanFile, `${stableStringify(compiled.guestLink.plan, 2)}\n`, 'utf8');
386
+ if (guestLinkReportFile) fs.writeFileSync(guestLinkReportFile, `${stableStringify(compiled.guestLink.report, 2)}\n`, 'utf8');
387
+ if (finalWasmAuditFile) fs.writeFileSync(finalWasmAuditFile, `${stableStringify(compiled.guestLink.audit, 2)}\n`, 'utf8');
388
+ return Object.freeze({
389
+ target,
390
+ sourceFile,
391
+ wasmFile,
392
+ watFile,
393
+ planFile,
394
+ manifestFile,
395
+ realizationArtifactsFile,
396
+ guestUnitPlanFile,
397
+ guestLinkReportFile,
398
+ finalWasmAuditFile,
399
+ manifest: compiled.manifest
400
+ });
401
+ }
402
+
403
+ module.exports = Object.freeze({
404
+ CANONICAL_NATIVE_WASM_VERSION: runtimeContract.CANONICAL_NATIVE_WASM_VERSION,
405
+ CANONICAL_NATIVE_COMPILER_VERSION: runtimeContract.CANONICAL_NATIVE_COMPILER_VERSION,
406
+ CanonicalNativeCompileError,
407
+ compileCanonicalNativePlan,
408
+ inspectCanonicalNativeWasm,
409
+ writeCanonicalNativeModule,
410
+ stableStringify
411
+ });