@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.
Files changed (63) hide show
  1. package/README.md +52 -1
  2. package/dist/config-schema.json +73 -0
  3. package/dist/index.d.ts +61 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +59 -0
  6. package/dist/index.js.map +1 -0
  7. package/package.json +87 -5
  8. package/src/build/canonical-target.js +436 -0
  9. package/src/build/entities-native.js +564 -0
  10. package/src/build/fixed-memory-runtime.as.ts +148 -0
  11. package/src/build/native-http-effects.js +871 -0
  12. package/src/build/native-http-shell.js +703 -0
  13. package/src/build/native-platform-capabilities.js +2109 -0
  14. package/src/compiler/assets-package-out-parity-proof.js +338 -0
  15. package/src/compiler/assets-provider-proof.js +499 -0
  16. package/src/compiler/config-provider-resolution.js +573 -0
  17. package/src/compiler/fastly-adapter.js +564 -0
  18. package/src/compiler/fastly-command-entry.js +390 -0
  19. package/src/compiler/fastly-config-secret-serve.js +323 -0
  20. package/src/compiler/fastly-hostcall-binding.js +598 -0
  21. package/src/compiler/fastly-readiness.js +477 -0
  22. package/src/compiler/index.js +40 -0
  23. package/src/compiler/lifecycle-parity-contract.js +70 -0
  24. package/src/compiler/lifecycle-parity-proof.js +260 -0
  25. package/src/compiler/route-handler-effect-proof.js +255 -0
  26. package/src/compiler/runtime-provider-kv.js +237 -0
  27. package/src/compiler/runtime-provider-shape.js +109 -0
  28. package/src/config-api.js +63 -0
  29. package/src/config-schema.d.ts +13 -0
  30. package/src/config-schema.js +27 -0
  31. package/src/config-schema.json +73 -0
  32. package/src/index.js +3 -0
  33. package/src/index.ts +118 -0
  34. package/src/javascript/assets-adapter.js +122 -0
  35. package/src/javascript/bindings-adapter.js +237 -0
  36. package/src/javascript/errors.js +26 -0
  37. package/src/javascript/fetch-adapter.js +93 -0
  38. package/src/javascript/grip-broadcast.js +261 -0
  39. package/src/javascript/jwt-verifier.js +137 -0
  40. package/src/javascript/lifecycle.js +55 -0
  41. package/src/javascript/local-loader.js +138 -0
  42. package/src/javascript/logging.js +26 -0
  43. package/src/javascript/package-effects.js +68 -0
  44. package/src/javascript/runtime-host.js +108 -0
  45. package/src/javascript/sha256.js +128 -0
  46. package/src/javascript/source-package.js +776 -0
  47. package/src/javascript/support.js +142 -0
  48. package/src/javascript/target-support-policy.js +260 -0
  49. package/src/javascript/target.js +73 -0
  50. package/src/javascript/test-runtime.js +407 -0
  51. package/src/provider-contract.js +72 -0
  52. package/src/runtime/assets-provider.js +464 -0
  53. package/src/runtime/canonical-api-runtime.js +597 -0
  54. package/src/runtime/index.js +28 -0
  55. package/src/runtime/provider-primitives-contract.js +272 -0
  56. package/src/runtime/provider-primitives.js +82 -0
  57. package/src/runtime/route-handler-effects.js +507 -0
  58. package/src/testing/fastly-cli.js +538 -0
  59. package/src/testing/native-http-effects-host.js +390 -0
  60. package/src/testing/native-http-shell-host.js +190 -0
  61. package/src/testing/native-platform-capabilities-host.js +599 -0
  62. package/src/toolchain/config.js +128 -0
  63. package/src/toolchain/index.js +343 -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 });