@pulse-compute/provider-fastly 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.
- package/README.md +53 -1
- package/dist/config-schema.json +77 -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 +88 -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/kv-native.as.ts +229 -0
- package/src/build/kv-native.js +20 -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 +2196 -0
- package/src/build/s3-native.as.ts +215 -0
- package/src/build/s3-native.js +30 -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 +77 -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 +264 -0
- package/src/javascript/target.js +73 -0
- package/src/javascript/test-runtime.js +407 -0
- package/src/provider-contract.js +79 -0
- package/src/runtime/assets-provider.js +464 -0
- package/src/runtime/canonical-api-runtime.js +601 -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/conditional-kv-host.js +109 -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 +676 -0
- package/src/toolchain/config.js +131 -0
- package/src/toolchain/index.js +345 -0
- package/src/toolchain/s3.js +26 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const runtimeHost = require('@pulse-compute/runtime/host');
|
|
4
|
+
const {
|
|
5
|
+
createFastlyJavascriptBindingCapabilities,
|
|
6
|
+
withFastlyBindingCapabilities
|
|
7
|
+
} = require('./bindings-adapter.js');
|
|
8
|
+
const { createFastlyJavascriptFetchCapability, withFastlyFetchCapability } = require('./fetch-adapter.js');
|
|
9
|
+
const { createFastlyJavascriptAssetsLookup } = require('./assets-adapter.js');
|
|
10
|
+
const { createFastlyJavascriptGripBroadcast } = require('./grip-broadcast.js');
|
|
11
|
+
const { createFastlyJavascriptJwtVerify } = require('./jwt-verifier.js');
|
|
12
|
+
const { withFastlyPackageEffectCapabilities } = require('./package-effects.js');
|
|
13
|
+
const { createFastlyJavascriptLogEmitter } = require('./logging.js');
|
|
14
|
+
|
|
15
|
+
const FASTLY_JAVASCRIPT_RUNTIME_HOST_VERSION = 'pulse.fastly-javascript-runtime-host.v1';
|
|
16
|
+
|
|
17
|
+
function isFastlyJavascriptApplication(value) {
|
|
18
|
+
return runtimeHost.isRouterApplication(value) || typeof value === 'function';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function assertFastlyJavascriptApplication(value) {
|
|
22
|
+
return runtimeHost.normalizeApplication(value);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function createFastlyJavascriptCapabilities(options = {}) {
|
|
26
|
+
const bindingCapabilities = createFastlyJavascriptBindingCapabilities(options);
|
|
27
|
+
const assetsLookup = createFastlyJavascriptAssetsLookup(options);
|
|
28
|
+
const jwtVerify = createFastlyJavascriptJwtVerify({
|
|
29
|
+
captureWallClock: options.jwtCaptureWallClock,
|
|
30
|
+
secretLookup: bindingCapabilities.secret
|
|
31
|
+
});
|
|
32
|
+
const grip = options.bindings && options.bindings.grip;
|
|
33
|
+
let configuredGripBroadcast;
|
|
34
|
+
const gripBroadcast = grip && (grip.publishEndpoint || grip.publishUrl)
|
|
35
|
+
? (payload, execution) => {
|
|
36
|
+
if (!configuredGripBroadcast) {
|
|
37
|
+
configuredGripBroadcast = createFastlyJavascriptGripBroadcast({
|
|
38
|
+
...options,
|
|
39
|
+
grip,
|
|
40
|
+
secretLookup: bindingCapabilities.secret
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return configuredGripBroadcast(payload, execution);
|
|
44
|
+
}
|
|
45
|
+
: undefined;
|
|
46
|
+
return withFastlyPackageEffectCapabilities(
|
|
47
|
+
withFastlyFetchCapability(
|
|
48
|
+
withFastlyBindingCapabilities(options.capabilities, { ...options, bindingCapabilities }),
|
|
49
|
+
{ ...options, fetchImplementation: options.fetchImplementation }
|
|
50
|
+
),
|
|
51
|
+
{ assetsLookup, gripBroadcast, jwtVerify }
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function requestHeaderPairs(request) {
|
|
56
|
+
return Object.freeze(Array.from(request.headers.entries(), ([name, value]) => Object.freeze([name, value])));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function executeFastlyJavascriptApplication(application, request, options = {}) {
|
|
60
|
+
const capabilities = options.effectAdapter === undefined
|
|
61
|
+
? createFastlyJavascriptCapabilities(options)
|
|
62
|
+
: undefined;
|
|
63
|
+
return runtimeHost.executeApplication(assertFastlyJavascriptApplication(application), request, {
|
|
64
|
+
capabilities,
|
|
65
|
+
effectAdapter: options.effectAdapter,
|
|
66
|
+
application: options.application,
|
|
67
|
+
requestHeaders: options.requestHeaders || requestHeaderPairs(request),
|
|
68
|
+
signal: options.signal || request.signal,
|
|
69
|
+
maxEffects: options.maxEffects,
|
|
70
|
+
maxRequestBodyBytes: options.maxRequestBodyBytes,
|
|
71
|
+
maxFetchBodyBytes: options.maxFetchBodyBytes,
|
|
72
|
+
maxStructuredBodyBytes: options.maxStructuredBodyBytes,
|
|
73
|
+
maxBindingNameBytes: options.maxBindingNameBytes,
|
|
74
|
+
maxBindingValueBytes: options.maxBindingValueBytes,
|
|
75
|
+
maxKvNamespaceBytes: options.maxKvNamespaceBytes,
|
|
76
|
+
maxKvKeyBytes: options.maxKvKeyBytes,
|
|
77
|
+
maxKvValueBytes: options.maxKvValueBytes,
|
|
78
|
+
maxKvValueDepth: options.maxKvValueDepth,
|
|
79
|
+
maxKvValueEntries: options.maxKvValueEntries,
|
|
80
|
+
schemaCodecs: options.schemaCodecs,
|
|
81
|
+
strict: options.strict === true,
|
|
82
|
+
target: 'javascript',
|
|
83
|
+
provider: 'fastly',
|
|
84
|
+
reporting: options.reporting,
|
|
85
|
+
log: options.log || createFastlyJavascriptLogEmitter({ console: options.console }),
|
|
86
|
+
redactionValues: options.redactionValues,
|
|
87
|
+
onLogObservation: options.onLogObservation,
|
|
88
|
+
onJsonTrace: options.onJsonTrace,
|
|
89
|
+
onEffectObservation: options.onEffectObservation,
|
|
90
|
+
onEffectSummary: options.onEffectSummary
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = Object.freeze({
|
|
95
|
+
FASTLY_JAVASCRIPT_RUNTIME_HOST_VERSION,
|
|
96
|
+
PulseRuntimeContractError: runtimeHost.PulseRuntimeContractError,
|
|
97
|
+
createFastlyJavascriptAssetsLookup,
|
|
98
|
+
createFastlyJavascriptBindingCapabilities,
|
|
99
|
+
createFastlyJavascriptCapabilities,
|
|
100
|
+
createFastlyJavascriptFetchCapability,
|
|
101
|
+
createFastlyJavascriptGripBroadcast,
|
|
102
|
+
createFastlyJavascriptJwtVerify,
|
|
103
|
+
createFastlyJavascriptLogEmitter,
|
|
104
|
+
assertFastlyJavascriptApplication,
|
|
105
|
+
executeFastlyJavascriptApplication,
|
|
106
|
+
isFastlyJavascriptApplication,
|
|
107
|
+
requestHeaderPairs
|
|
108
|
+
});
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// A small synchronous SHA-256 bridge used only by generated schema semantic
|
|
4
|
+
// traces. Fastly exposes Web Crypto asynchronously, while the shared trace
|
|
5
|
+
// contract intentionally computes deterministic digests synchronously.
|
|
6
|
+
const K = Object.freeze([
|
|
7
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
8
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
9
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
10
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
11
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
12
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
13
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
14
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
function rotateRight(value, amount) {
|
|
18
|
+
return (value >>> amount) | (value << (32 - amount));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function inputBytes(value) {
|
|
22
|
+
if (typeof value === 'string') return new TextEncoder().encode(value);
|
|
23
|
+
if (value instanceof Uint8Array) return value;
|
|
24
|
+
if (value instanceof ArrayBuffer) return new Uint8Array(value);
|
|
25
|
+
if (ArrayBuffer.isView(value)) return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
|
26
|
+
return new TextEncoder().encode(String(value));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function sha256Bytes(input) {
|
|
30
|
+
const bytes = inputBytes(input);
|
|
31
|
+
const paddedLength = Math.ceil((bytes.byteLength + 9) / 64) * 64;
|
|
32
|
+
const message = new Uint8Array(paddedLength);
|
|
33
|
+
message.set(bytes);
|
|
34
|
+
message[bytes.byteLength] = 0x80;
|
|
35
|
+
const bitLength = BigInt(bytes.byteLength) * 8n;
|
|
36
|
+
for (let index = 0; index < 8; index += 1) {
|
|
37
|
+
message[paddedLength - 1 - index] = Number((bitLength >> BigInt(index * 8)) & 0xffn);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const state = new Uint32Array([
|
|
41
|
+
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
|
42
|
+
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
|
43
|
+
]);
|
|
44
|
+
const words = new Uint32Array(64);
|
|
45
|
+
for (let offset = 0; offset < message.byteLength; offset += 64) {
|
|
46
|
+
for (let index = 0; index < 16; index += 1) {
|
|
47
|
+
const position = offset + index * 4;
|
|
48
|
+
words[index] = (
|
|
49
|
+
(message[position] << 24)
|
|
50
|
+
| (message[position + 1] << 16)
|
|
51
|
+
| (message[position + 2] << 8)
|
|
52
|
+
| message[position + 3]
|
|
53
|
+
) >>> 0;
|
|
54
|
+
}
|
|
55
|
+
for (let index = 16; index < 64; index += 1) {
|
|
56
|
+
const left = words[index - 15];
|
|
57
|
+
const right = words[index - 2];
|
|
58
|
+
const s0 = rotateRight(left, 7) ^ rotateRight(left, 18) ^ (left >>> 3);
|
|
59
|
+
const s1 = rotateRight(right, 17) ^ rotateRight(right, 19) ^ (right >>> 10);
|
|
60
|
+
words[index] = (words[index - 16] + s0 + words[index - 7] + s1) >>> 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let [a, b, c, d, e, f, g, h] = state;
|
|
64
|
+
for (let index = 0; index < 64; index += 1) {
|
|
65
|
+
const sum1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
|
|
66
|
+
const choice = (e & f) ^ (~e & g);
|
|
67
|
+
const temporary1 = (h + sum1 + choice + K[index] + words[index]) >>> 0;
|
|
68
|
+
const sum0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22);
|
|
69
|
+
const majority = (a & b) ^ (a & c) ^ (b & c);
|
|
70
|
+
const temporary2 = (sum0 + majority) >>> 0;
|
|
71
|
+
h = g;
|
|
72
|
+
g = f;
|
|
73
|
+
f = e;
|
|
74
|
+
e = (d + temporary1) >>> 0;
|
|
75
|
+
d = c;
|
|
76
|
+
c = b;
|
|
77
|
+
b = a;
|
|
78
|
+
a = (temporary1 + temporary2) >>> 0;
|
|
79
|
+
}
|
|
80
|
+
state[0] = (state[0] + a) >>> 0;
|
|
81
|
+
state[1] = (state[1] + b) >>> 0;
|
|
82
|
+
state[2] = (state[2] + c) >>> 0;
|
|
83
|
+
state[3] = (state[3] + d) >>> 0;
|
|
84
|
+
state[4] = (state[4] + e) >>> 0;
|
|
85
|
+
state[5] = (state[5] + f) >>> 0;
|
|
86
|
+
state[6] = (state[6] + g) >>> 0;
|
|
87
|
+
state[7] = (state[7] + h) >>> 0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const digest = new Uint8Array(32);
|
|
91
|
+
for (let index = 0; index < state.length; index += 1) {
|
|
92
|
+
digest[index * 4] = state[index] >>> 24;
|
|
93
|
+
digest[index * 4 + 1] = state[index] >>> 16;
|
|
94
|
+
digest[index * 4 + 2] = state[index] >>> 8;
|
|
95
|
+
digest[index * 4 + 3] = state[index];
|
|
96
|
+
}
|
|
97
|
+
return digest;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function createHash(algorithm) {
|
|
101
|
+
if (String(algorithm).toLowerCase().replace('-', '') !== 'sha256') {
|
|
102
|
+
throw new TypeError('Pulse Fastly JavaScript supports SHA-256 digests only.');
|
|
103
|
+
}
|
|
104
|
+
const chunks = [];
|
|
105
|
+
return {
|
|
106
|
+
update(value) {
|
|
107
|
+
chunks.push(inputBytes(value));
|
|
108
|
+
return this;
|
|
109
|
+
},
|
|
110
|
+
digest(encoding) {
|
|
111
|
+
const length = chunks.reduce((sum, entry) => sum + entry.byteLength, 0);
|
|
112
|
+
const input = new Uint8Array(length);
|
|
113
|
+
let offset = 0;
|
|
114
|
+
for (const chunk of chunks) {
|
|
115
|
+
input.set(chunk, offset);
|
|
116
|
+
offset += chunk.byteLength;
|
|
117
|
+
}
|
|
118
|
+
const output = sha256Bytes(input);
|
|
119
|
+
if (encoding === undefined) return output;
|
|
120
|
+
if (String(encoding).toLowerCase() !== 'hex') {
|
|
121
|
+
throw new TypeError('Pulse Fastly JavaScript SHA-256 bridge supports hex output only.');
|
|
122
|
+
}
|
|
123
|
+
return Array.from(output, (byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
module.exports = Object.freeze({ createHash, sha256Bytes });
|