@pulse-compute/provider-fastly 0.0.0 → 1.0.0-beta.1
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.
- package/README.md +52 -1
- package/dist/config-schema.json +73 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/package.json +87 -5
- package/src/build/canonical-target.js +436 -0
- package/src/build/entities-native.js +564 -0
- package/src/build/fixed-memory-runtime.as.ts +148 -0
- package/src/build/native-http-effects.js +871 -0
- package/src/build/native-http-shell.js +703 -0
- package/src/build/native-platform-capabilities.js +2109 -0
- package/src/compiler/assets-package-out-parity-proof.js +338 -0
- package/src/compiler/assets-provider-proof.js +499 -0
- package/src/compiler/config-provider-resolution.js +573 -0
- package/src/compiler/fastly-adapter.js +564 -0
- package/src/compiler/fastly-command-entry.js +390 -0
- package/src/compiler/fastly-config-secret-serve.js +323 -0
- package/src/compiler/fastly-hostcall-binding.js +598 -0
- package/src/compiler/fastly-readiness.js +477 -0
- package/src/compiler/index.js +40 -0
- package/src/compiler/lifecycle-parity-contract.js +70 -0
- package/src/compiler/lifecycle-parity-proof.js +260 -0
- package/src/compiler/route-handler-effect-proof.js +255 -0
- package/src/compiler/runtime-provider-kv.js +237 -0
- package/src/compiler/runtime-provider-shape.js +109 -0
- package/src/config-api.js +63 -0
- package/src/config-schema.d.ts +13 -0
- package/src/config-schema.js +27 -0
- package/src/config-schema.json +73 -0
- package/src/index.js +3 -0
- package/src/index.ts +118 -0
- package/src/javascript/assets-adapter.js +122 -0
- package/src/javascript/bindings-adapter.js +237 -0
- package/src/javascript/errors.js +26 -0
- package/src/javascript/fetch-adapter.js +93 -0
- package/src/javascript/grip-broadcast.js +261 -0
- package/src/javascript/jwt-verifier.js +137 -0
- package/src/javascript/lifecycle.js +55 -0
- package/src/javascript/local-loader.js +138 -0
- package/src/javascript/logging.js +26 -0
- package/src/javascript/package-effects.js +68 -0
- package/src/javascript/runtime-host.js +108 -0
- package/src/javascript/sha256.js +128 -0
- package/src/javascript/source-package.js +776 -0
- package/src/javascript/support.js +142 -0
- package/src/javascript/target-support-policy.js +260 -0
- package/src/javascript/target.js +73 -0
- package/src/javascript/test-runtime.js +407 -0
- package/src/provider-contract.js +72 -0
- package/src/runtime/assets-provider.js +464 -0
- package/src/runtime/canonical-api-runtime.js +597 -0
- package/src/runtime/index.js +28 -0
- package/src/runtime/provider-primitives-contract.js +272 -0
- package/src/runtime/provider-primitives.js +82 -0
- package/src/runtime/route-handler-effects.js +507 -0
- package/src/testing/fastly-cli.js +538 -0
- package/src/testing/native-http-effects-host.js +390 -0
- package/src/testing/native-http-shell-host.js +190 -0
- package/src/testing/native-platform-capabilities-host.js +599 -0
- package/src/toolchain/config.js +128 -0
- package/src/toolchain/index.js +343 -0
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const crypto = require('node:crypto');
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
const { CANONICAL_NATIVE_PLAN_VERSION } = require('@pulse-compute/wasm-contracts/handler/canonical-native-plan');
|
|
7
|
+
const {
|
|
8
|
+
FASTLY_NATIVE_PLATFORM_CAPABILITIES_VERSION,
|
|
9
|
+
compileFastlyNativePlatformCapabilitiesPlan,
|
|
10
|
+
writeFastlyNativePlatformCapabilitiesModule
|
|
11
|
+
} = require('./native-platform-capabilities.js');
|
|
12
|
+
|
|
13
|
+
const FASTLY_CANONICAL_BUILD_VERSION = 'pulse.fastly-canonical-build.v6';
|
|
14
|
+
const FASTLY_CANONICAL_TARGET = 'fastly-compute-native';
|
|
15
|
+
|
|
16
|
+
function stableJson(value) { return `${JSON.stringify(value, null, 2)}\n`; }
|
|
17
|
+
function sha256(value) { return crypto.createHash('sha256').update(value).digest('hex'); }
|
|
18
|
+
|
|
19
|
+
function isFastlyNativeArtifact(native) {
|
|
20
|
+
return Boolean(
|
|
21
|
+
native
|
|
22
|
+
&& native.version === FASTLY_NATIVE_PLATFORM_CAPABILITIES_VERSION
|
|
23
|
+
&& Buffer.isBuffer(native.wasm)
|
|
24
|
+
&& native.manifest
|
|
25
|
+
&& native.manifest.wasm
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function providerBuildError(code, message, detail = {}) {
|
|
30
|
+
const error = new Error(message);
|
|
31
|
+
error.name = 'FastlyCanonicalBuildError';
|
|
32
|
+
error.code = code;
|
|
33
|
+
error.detail = Object.freeze({ ...detail });
|
|
34
|
+
return error;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function assertFastlyProviderPlan(providerPlan) {
|
|
38
|
+
if (
|
|
39
|
+
!providerPlan
|
|
40
|
+
|| providerPlan.version !== 'pulse.canonical-provider-plan.v1'
|
|
41
|
+
|| providerPlan.provider !== 'fastly'
|
|
42
|
+
|| !Array.isArray(providerPlan.operations)
|
|
43
|
+
) {
|
|
44
|
+
throw new TypeError('Fastly canonical target requires the canonical Fastly provider plan.');
|
|
45
|
+
}
|
|
46
|
+
return providerPlan;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function metadataFromCanonicalPlans(plan, providerPlan) {
|
|
50
|
+
const lowering = assertFastlyProviderPlan(providerPlan);
|
|
51
|
+
return Object.freeze({
|
|
52
|
+
sourceHash: plan.source.sourceHash,
|
|
53
|
+
projectSourceHash: plan.source.projectSourceHash || plan.source.sourceHash,
|
|
54
|
+
capabilities: plan.capabilities,
|
|
55
|
+
providerOperations: lowering.operations,
|
|
56
|
+
packageEffects: plan.packages && plan.packages.effects || Object.freeze([]),
|
|
57
|
+
schemaIds: plan.schemas && plan.schemas.ids || Object.freeze([]),
|
|
58
|
+
schemaReferences: plan.schemas && plan.schemas.references || Object.freeze([]),
|
|
59
|
+
schemaSourceHash: plan.schemas && plan.schemas.sourceHash
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function assertExactProviderNative(native) {
|
|
64
|
+
if (!isFastlyNativeArtifact(native)) {
|
|
65
|
+
throw providerBuildError(
|
|
66
|
+
'PULSE_FASTLY_NATIVE_ARTIFACT_INVALID',
|
|
67
|
+
'Fastly packaging requires a Fastly provider-native artifact.',
|
|
68
|
+
{ automaticFallback: false }
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const observedSha256 = sha256(native.wasm);
|
|
72
|
+
if (native.manifest.wasm.sha256 !== observedSha256) {
|
|
73
|
+
throw providerBuildError(
|
|
74
|
+
'PULSE_FASTLY_NATIVE_ARTIFACT_HASH_MISMATCH',
|
|
75
|
+
'Fastly provider-native bytes do not match their compiler manifest.',
|
|
76
|
+
{
|
|
77
|
+
expectedSha256: native.manifest.wasm.sha256,
|
|
78
|
+
observedSha256,
|
|
79
|
+
automaticFallback: false
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
if (native.guestLink) {
|
|
84
|
+
const audit = native.guestLink.audit;
|
|
85
|
+
if (
|
|
86
|
+
!audit
|
|
87
|
+
|| audit.status !== 'passed'
|
|
88
|
+
|| audit.providerPackaging && audit.providerPackaging.authorized !== true
|
|
89
|
+
|| !audit.artifact
|
|
90
|
+
|| audit.artifact.sha256 !== observedSha256
|
|
91
|
+
|| native.guestLink.providerPackaging
|
|
92
|
+
&& native.guestLink.providerPackaging.authorized !== true
|
|
93
|
+
) {
|
|
94
|
+
throw providerBuildError(
|
|
95
|
+
'PULSE_GUEST_FINAL_AUDIT_FAILED',
|
|
96
|
+
'Fastly packaging requires exact bytes authorized by the final guest-link audit.',
|
|
97
|
+
{ observedSha256, automaticFallback: false }
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return native;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function validateGripBindings(metadata = {}, bindings = {}) {
|
|
105
|
+
const operations = (metadata.providerOperations || []).filter((operation) => operation && operation.kind === 'grip');
|
|
106
|
+
if (operations.length === 0) return Object.freeze({ active: false, operations: Object.freeze([]) });
|
|
107
|
+
const grip = bindings.grip && typeof bindings.grip === 'object' ? bindings.grip : {};
|
|
108
|
+
const publish = operations.filter((operation) => operation.operation === 'publish');
|
|
109
|
+
const broadcast = operations.filter((operation) => operation.operation === 'broadcast');
|
|
110
|
+
const hold = operations.filter((operation) => operation.operation === 'hold');
|
|
111
|
+
if (broadcast.length > 0 && !String(grip.publishEndpoint || '').trim()) {
|
|
112
|
+
throw providerBuildError(
|
|
113
|
+
'PULSE_FASTLY_GRIP_PUBLISH_BINDING_REQUIRED',
|
|
114
|
+
'Fastly GRIP broadcast operations require provider.grip.publishEndpoint.',
|
|
115
|
+
{ operations: broadcast.map((operation) => operation.id) }
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
if (broadcast.length > 0) {
|
|
119
|
+
try {
|
|
120
|
+
const endpoint = new URL(String(grip.publishEndpoint));
|
|
121
|
+
if (!['http:', 'https:'].includes(endpoint.protocol)) throw new TypeError('unsupported protocol');
|
|
122
|
+
} catch {
|
|
123
|
+
throw providerBuildError(
|
|
124
|
+
'PULSE_FASTLY_GRIP_PUBLISH_BINDING_REQUIRED',
|
|
125
|
+
'Fastly GRIP publishEndpoint must be an absolute HTTP or HTTPS URL.',
|
|
126
|
+
{ operations: broadcast.map((operation) => operation.id) }
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
if (grip.authentication !== undefined) {
|
|
130
|
+
const authentication = grip.authentication && typeof grip.authentication === 'object' ? grip.authentication : {};
|
|
131
|
+
if (String(authentication.scheme || 'bearer').toLowerCase() !== 'bearer') {
|
|
132
|
+
throw providerBuildError(
|
|
133
|
+
'PULSE_FASTLY_NATIVE_GRIP_AUTH_SCHEME_UNSUPPORTED',
|
|
134
|
+
'Fastly GRIP broadcast supports only bearer authentication.',
|
|
135
|
+
{ operations: broadcast.map((operation) => operation.id) }
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
if (!String(authentication.secretRef || '').trim()) {
|
|
139
|
+
throw providerBuildError(
|
|
140
|
+
'PULSE_FASTLY_NATIVE_GRIP_SECRET_REFERENCE_MISSING',
|
|
141
|
+
'Fastly GRIP bearer authentication requires a named secret reference.',
|
|
142
|
+
{ operations: broadcast.map((operation) => operation.id) }
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (publish.length > 0 && !String(grip.publishUrl || '').trim()) {
|
|
148
|
+
throw providerBuildError(
|
|
149
|
+
'PULSE_FASTLY_GRIP_PUBLISH_BINDING_REQUIRED',
|
|
150
|
+
'Fastly GRIP publish operations require provider.grip.publishUrl.',
|
|
151
|
+
{ operations: publish.map((operation) => operation.id) }
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
if (hold.length > 0 && grip.directHold === false && !String(grip.fanoutBackend || '').trim()) {
|
|
155
|
+
throw providerBuildError(
|
|
156
|
+
'PULSE_FASTLY_GRIP_FANOUT_BACKEND_REQUIRED',
|
|
157
|
+
'Fastly GRIP Fanout handoff requires provider.grip.fanoutBackend when directHold is disabled.',
|
|
158
|
+
{ operations: hold.map((operation) => operation.id) }
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
const endpoint = broadcast.length > 0 ? grip.publishEndpoint : grip.publishUrl;
|
|
162
|
+
if ((publish.length > 0 || broadcast.length > 0) && String(endpoint || '').trim() && !String(grip.publishBackend || '').trim() && bindings.dynamicBackends !== true) {
|
|
163
|
+
const origin = new URL(String(endpoint)).origin;
|
|
164
|
+
if (!(bindings.backends && bindings.backends[origin])) {
|
|
165
|
+
throw providerBuildError(
|
|
166
|
+
'PULSE_FASTLY_GRIP_PUBLISH_BACKEND_REQUIRED',
|
|
167
|
+
`No Fastly backend binding is configured for the GRIP publish origin ${origin}.`,
|
|
168
|
+
{ origin, operations: [...publish, ...broadcast].map((operation) => operation.id) }
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return Object.freeze({
|
|
173
|
+
active: true,
|
|
174
|
+
operations: Object.freeze(operations.map((operation) => Object.freeze({ id: operation.id, operation: operation.operation, result: operation.result }))),
|
|
175
|
+
directHold: grip.directHold !== false,
|
|
176
|
+
fanoutBackend: grip.fanoutBackend === undefined ? undefined : String(grip.fanoutBackend),
|
|
177
|
+
publishEndpoint: grip.publishEndpoint === undefined ? undefined : String(grip.publishEndpoint),
|
|
178
|
+
publishUrl: grip.publishUrl === undefined ? undefined : String(grip.publishUrl),
|
|
179
|
+
publishBackend: grip.publishBackend === undefined ? undefined : String(grip.publishBackend),
|
|
180
|
+
authentication: grip.authentication === undefined ? undefined : Object.freeze({
|
|
181
|
+
scheme: String(grip.authentication.scheme || 'bearer'),
|
|
182
|
+
secretRef: String(grip.authentication.secretRef || '')
|
|
183
|
+
})
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function cleanName(value) { return String(value || 'pulse-app').toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '') || 'pulse-app'; }
|
|
188
|
+
function tomlString(value) { return JSON.stringify(String(value)); }
|
|
189
|
+
|
|
190
|
+
function normalizedBuildConfig(providerConfig = {}) {
|
|
191
|
+
const input = providerConfig.build && typeof providerConfig.build === 'object' ? providerConfig.build : {};
|
|
192
|
+
return Object.freeze({
|
|
193
|
+
name: cleanName(input.name),
|
|
194
|
+
description: String(input.description || 'Pulse application'),
|
|
195
|
+
authors: Object.freeze(Array.isArray(input.authors) ? input.authors.map(String) : []),
|
|
196
|
+
language: 'other'
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function nativeBuildCheckCommand() {
|
|
201
|
+
return "node -e \"const fs=require('node:fs');const f='bin/main.wasm';if(!fs.existsSync(f)){console.error('Run pulse build before Fastly packaging.');process.exit(1)}\"";
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function renderFastlyToml(build) {
|
|
205
|
+
return [
|
|
206
|
+
'manifest_version = 3',
|
|
207
|
+
`name = ${tomlString(build.name)}`,
|
|
208
|
+
`description = ${tomlString(build.description)}`,
|
|
209
|
+
`authors = [${build.authors.map(tomlString).join(', ')}]`,
|
|
210
|
+
'language = "other"',
|
|
211
|
+
'',
|
|
212
|
+
'[scripts]',
|
|
213
|
+
`build = ${tomlString(nativeBuildCheckCommand())}`,
|
|
214
|
+
''
|
|
215
|
+
].join('\n');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function inspectFastlyCanonicalTarget(options = {}) {
|
|
219
|
+
const plan = options.plan;
|
|
220
|
+
if (!plan || plan.version !== CANONICAL_NATIVE_PLAN_VERSION) {
|
|
221
|
+
throw new TypeError(`Fastly canonical target inspection requires ${CANONICAL_NATIVE_PLAN_VERSION}.`);
|
|
222
|
+
}
|
|
223
|
+
const providerConfig = options.providerConfig || {};
|
|
224
|
+
const bindings = options.bindings || providerConfig.bindings || {};
|
|
225
|
+
const native = isFastlyNativeArtifact(options.native)
|
|
226
|
+
? assertExactProviderNative(options.native)
|
|
227
|
+
: compileFastlyNativePlatformCapabilitiesPlan(plan, {
|
|
228
|
+
cwd: options.cwd || options.projectRoot || process.cwd(),
|
|
229
|
+
projectRoot: options.projectRoot,
|
|
230
|
+
profile: options.profile,
|
|
231
|
+
bindings,
|
|
232
|
+
requirePlatformCapability: false,
|
|
233
|
+
canonicalBuild: true,
|
|
234
|
+
targetDescriptor: options.targetDescriptor,
|
|
235
|
+
synchronizedPackages: options.synchronizedPackages,
|
|
236
|
+
realizationArtifacts: options.realizationArtifacts
|
|
237
|
+
|| (options.native && options.native.realizationArtifacts),
|
|
238
|
+
guestUnits: options.guestUnits
|
|
239
|
+
|| (options.native && options.native.guestUnits),
|
|
240
|
+
nativeOptimization: options.nativeOptimization
|
|
241
|
+
|| (options.experimentalNativeSize === true ? 'experimental-native-size' : undefined),
|
|
242
|
+
timeoutMs: options.compileTimeoutMs
|
|
243
|
+
});
|
|
244
|
+
return Object.freeze({
|
|
245
|
+
target: FASTLY_CANONICAL_TARGET,
|
|
246
|
+
provider: 'fastly',
|
|
247
|
+
providerNeutralInput: true,
|
|
248
|
+
nativeWasm: true,
|
|
249
|
+
javascriptRuntime: false,
|
|
250
|
+
jsComputeRuntime: false,
|
|
251
|
+
planHash: plan.planHash,
|
|
252
|
+
compilerVersion: native.compilerVersion,
|
|
253
|
+
compiler: native.manifest.assemblyScript,
|
|
254
|
+
wasm: native.manifest.wasm,
|
|
255
|
+
wat: native.manifest.wat,
|
|
256
|
+
importModules: native.manifest.importModules,
|
|
257
|
+
imports: native.manifest.imports,
|
|
258
|
+
exports: native.manifest.exports,
|
|
259
|
+
policy: native.manifest.policy,
|
|
260
|
+
native
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function writeFastlyCanonicalTarget(options = {}) {
|
|
265
|
+
if (options.sourceOnly === true) {
|
|
266
|
+
throw providerBuildError(
|
|
267
|
+
'PULSE_SOURCE_ONLY_REMOVED',
|
|
268
|
+
'Fastly source-only JavaScript packaging was removed. pulse build emits generated native source and bin/main.wasm together.',
|
|
269
|
+
{ replacement: 'pulse build' }
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
const outDir = path.resolve(options.outDir || '.');
|
|
273
|
+
const plan = options.plan;
|
|
274
|
+
if (!plan || plan.version !== CANONICAL_NATIVE_PLAN_VERSION) {
|
|
275
|
+
throw new TypeError(`Fastly canonical target requires ${CANONICAL_NATIVE_PLAN_VERSION}.`);
|
|
276
|
+
}
|
|
277
|
+
const lowering = assertFastlyProviderPlan(options.providerPlan);
|
|
278
|
+
const metadata = metadataFromCanonicalPlans(plan, lowering);
|
|
279
|
+
const providerConfig = options.providerConfig || {};
|
|
280
|
+
const bindings = options.bindings || providerConfig.bindings || {};
|
|
281
|
+
const buildConfig = normalizedBuildConfig(providerConfig);
|
|
282
|
+
const grip = validateGripBindings(metadata, bindings);
|
|
283
|
+
|
|
284
|
+
const srcDir = path.join(outDir, 'src');
|
|
285
|
+
const binDir = path.join(outDir, 'bin');
|
|
286
|
+
fs.mkdirSync(srcDir, { recursive: true });
|
|
287
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
288
|
+
|
|
289
|
+
let native;
|
|
290
|
+
const auditedNative = isFastlyNativeArtifact(options.native)
|
|
291
|
+
? assertExactProviderNative(options.native)
|
|
292
|
+
: null;
|
|
293
|
+
if (auditedNative) {
|
|
294
|
+
native = auditedNative;
|
|
295
|
+
} else {
|
|
296
|
+
const realization = inspectFastlyCanonicalTarget({
|
|
297
|
+
plan,
|
|
298
|
+
providerConfig,
|
|
299
|
+
bindings,
|
|
300
|
+
cwd: options.cwd || options.projectRoot || outDir,
|
|
301
|
+
projectRoot: options.projectRoot,
|
|
302
|
+
profile: options.profile,
|
|
303
|
+
targetDescriptor: options.targetDescriptor,
|
|
304
|
+
synchronizedPackages: options.synchronizedPackages,
|
|
305
|
+
realizationArtifacts: options.realizationArtifacts
|
|
306
|
+
|| (options.native && options.native.realizationArtifacts),
|
|
307
|
+
guestUnits: options.guestUnits
|
|
308
|
+
|| (options.native && options.native.guestUnits),
|
|
309
|
+
nativeOptimization: options.nativeOptimization
|
|
310
|
+
|| (options.experimentalNativeSize === true ? 'experimental-native-size' : undefined),
|
|
311
|
+
compileTimeoutMs: options.compileTimeoutMs
|
|
312
|
+
});
|
|
313
|
+
native = realization.native;
|
|
314
|
+
}
|
|
315
|
+
const written = writeFastlyNativePlatformCapabilitiesModule(native, outDir, {
|
|
316
|
+
sourceFile: 'src/main.as.ts',
|
|
317
|
+
wasmFile: 'bin/main.wasm',
|
|
318
|
+
watFile: 'bin/main.wat',
|
|
319
|
+
planFile: 'fastly-native-plan.json',
|
|
320
|
+
manifestFile: 'fastly-native-manifest.json'
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
const files = {
|
|
324
|
+
providerFile: path.join(outDir, 'fastly-provider.json'),
|
|
325
|
+
entryFile: path.join(outDir, 'fastly-entry.cjs'),
|
|
326
|
+
buildFile: path.join(outDir, 'fastly-build.json'),
|
|
327
|
+
fastlyTomlFile: path.join(outDir, 'fastly.toml'),
|
|
328
|
+
packageFile: path.join(outDir, 'package.json'),
|
|
329
|
+
sourceEntryFile: written.sourceFile,
|
|
330
|
+
sourceHandlerFile: undefined,
|
|
331
|
+
wasmFile: written.wasmFile,
|
|
332
|
+
watFile: written.watFile,
|
|
333
|
+
nativePlanFile: written.planFile,
|
|
334
|
+
nativeManifestFile: written.manifestFile
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
fs.writeFileSync(files.providerFile, stableJson(lowering));
|
|
338
|
+
fs.writeFileSync(files.fastlyTomlFile, renderFastlyToml(buildConfig));
|
|
339
|
+
fs.writeFileSync(files.packageFile, stableJson({
|
|
340
|
+
name: buildConfig.name,
|
|
341
|
+
version: '0.0.0',
|
|
342
|
+
private: true,
|
|
343
|
+
scripts: {
|
|
344
|
+
build: nativeBuildCheckCommand(),
|
|
345
|
+
start: 'fastly compute serve'
|
|
346
|
+
}
|
|
347
|
+
}));
|
|
348
|
+
fs.writeFileSync(files.entryFile, `'use strict';\n\nconst program = require('./canonical-handler.cjs');\nconst { createCanonicalFastlyRuntime } = require('@pulse-compute/provider-fastly/runtime/canonical-api-runtime');\nconst bindings = Object.freeze(${JSON.stringify(bindings)});\nmodule.exports = Object.freeze({\n version: ${JSON.stringify(FASTLY_CANONICAL_BUILD_VERSION)},\n provider: 'fastly',\n deployable: true,\n deploymentValidated: false,\n nativeWasm: true,\n localConformanceRuntime: true,\n createRuntime(options = {}) { return createCanonicalFastlyRuntime({ ...options, bindings }); },\n execute(options = {}) { return createCanonicalFastlyRuntime({ ...options, bindings }).execute(program, options); }\n});\n`);
|
|
349
|
+
|
|
350
|
+
const build = Object.freeze({
|
|
351
|
+
version: FASTLY_CANONICAL_BUILD_VERSION,
|
|
352
|
+
status: 'built',
|
|
353
|
+
provider: 'fastly',
|
|
354
|
+
target: FASTLY_CANONICAL_TARGET,
|
|
355
|
+
sourceHash: metadata.sourceHash,
|
|
356
|
+
projectSourceHash: metadata.projectSourceHash || metadata.sourceHash,
|
|
357
|
+
handlerSourceHash: metadata.sourceHash,
|
|
358
|
+
planVersion: plan.version,
|
|
359
|
+
planHash: plan.planHash,
|
|
360
|
+
deployable: true,
|
|
361
|
+
sourcePackage: true,
|
|
362
|
+
sourceOnly: false,
|
|
363
|
+
compiledWasmPresent: true,
|
|
364
|
+
deploymentValidated: false,
|
|
365
|
+
compileCommand: 'pulse build',
|
|
366
|
+
outputWasm: 'bin/main.wasm',
|
|
367
|
+
compiler: Object.freeze({
|
|
368
|
+
package: native.manifest.assemblyScript.package,
|
|
369
|
+
version: native.manifest.assemblyScript.version,
|
|
370
|
+
target: FASTLY_NATIVE_PLATFORM_CAPABILITIES_VERSION,
|
|
371
|
+
targetCompilerVersion: native.compilerVersion,
|
|
372
|
+
invoked: auditedNative === null
|
|
373
|
+
}),
|
|
374
|
+
optimization: native.manifest.optimization,
|
|
375
|
+
wasm: Object.freeze({ file: 'bin/main.wasm', ...native.manifest.wasm }),
|
|
376
|
+
wat: Object.freeze({ file: 'bin/main.wat', ...native.manifest.wat }),
|
|
377
|
+
imports: native.manifest.imports,
|
|
378
|
+
importModules: native.manifest.importModules,
|
|
379
|
+
exports: native.manifest.exports,
|
|
380
|
+
crypto: native.manifest.crypto,
|
|
381
|
+
...(native.guestLink ? {
|
|
382
|
+
guestLink: Object.freeze({
|
|
383
|
+
version: native.guestLink.report.version,
|
|
384
|
+
units: native.guestLink.report.units,
|
|
385
|
+
finalArtifact: native.guestLink.report.finalArtifact,
|
|
386
|
+
fallback: false,
|
|
387
|
+
packagedBytesMatchAudit: sha256(fs.readFileSync(written.wasmFile)) === native.guestLink.audit.artifact.sha256
|
|
388
|
+
})
|
|
389
|
+
} : {}),
|
|
390
|
+
localConformanceRuntime: true,
|
|
391
|
+
providerSpecificUserland: false,
|
|
392
|
+
providerSdkUserland: false,
|
|
393
|
+
javascriptRuntime: false,
|
|
394
|
+
jsComputeRuntime: false,
|
|
395
|
+
build: buildConfig,
|
|
396
|
+
files: Object.freeze({
|
|
397
|
+
handler: 'canonical-handler.cjs',
|
|
398
|
+
program: 'canonical-program.json',
|
|
399
|
+
portableWasm: 'canonical-native.wasm',
|
|
400
|
+
portableManifest: 'canonical-native-manifest.json',
|
|
401
|
+
providerPlan: 'fastly-provider.json',
|
|
402
|
+
localEntry: 'fastly-entry.cjs',
|
|
403
|
+
sourceEntry: 'src/main.as.ts',
|
|
404
|
+
wasm: 'bin/main.wasm',
|
|
405
|
+
wat: 'bin/main.wat',
|
|
406
|
+
nativePlan: 'fastly-native-plan.json',
|
|
407
|
+
nativeManifest: 'fastly-native-manifest.json',
|
|
408
|
+
fastlyToml: 'fastly.toml',
|
|
409
|
+
package: 'package.json',
|
|
410
|
+
schemaRegistry: metadata.schemaIds && metadata.schemaIds.length > 0 ? 'schema-json-registry.json' : undefined,
|
|
411
|
+
schemaCodecs: metadata.schemaIds && metadata.schemaIds.length > 0 ? 'schema-json-codecs.cjs' : undefined
|
|
412
|
+
}),
|
|
413
|
+
grip,
|
|
414
|
+
schemas: Object.freeze({
|
|
415
|
+
active: Boolean(metadata.schemaIds && metadata.schemaIds.length > 0),
|
|
416
|
+
ids: Object.freeze([...(metadata.schemaIds || [])]),
|
|
417
|
+
references: Object.freeze([...(metadata.schemaReferences || [])]),
|
|
418
|
+
sourceHash: metadata.schemaSourceHash
|
|
419
|
+
}),
|
|
420
|
+
lowering
|
|
421
|
+
});
|
|
422
|
+
fs.writeFileSync(files.buildFile, stableJson(build));
|
|
423
|
+
return Object.freeze({ ...files, build, lowering, compilation: native, native });
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
module.exports = Object.freeze({
|
|
427
|
+
FASTLY_CANONICAL_BUILD_VERSION,
|
|
428
|
+
FASTLY_CANONICAL_TARGET,
|
|
429
|
+
normalizedBuildConfig,
|
|
430
|
+
renderFastlyToml,
|
|
431
|
+
validateGripBindings,
|
|
432
|
+
isFastlyNativeArtifact,
|
|
433
|
+
assertExactProviderNative,
|
|
434
|
+
inspectFastlyCanonicalTarget,
|
|
435
|
+
writeFastlyCanonicalTarget
|
|
436
|
+
});
|