@pulse-compute/provider-fastly 0.0.0 → 1.0.0-beta.10
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 +103 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/package.json +88 -5
- package/src/build/canonical-target.js +469 -0
- package/src/build/digest-native.js +25 -0
- package/src/build/effect-invocations.js +49 -0
- package/src/build/embedded-assets.as.ts +32 -0
- package/src/build/entities-native.js +559 -0
- package/src/build/fixed-memory-runtime.as.ts +148 -0
- package/src/build/kv-native.as.ts +331 -0
- package/src/build/kv-native.js +27 -0
- package/src/build/native-application-errors.js +159 -0
- package/src/build/native-binary-resources.js +30 -0
- package/src/build/native-body-forwarding.as.ts +341 -0
- package/src/build/native-body-forwarding.js +69 -0
- package/src/build/native-dynamic-backends.as.ts +115 -0
- package/src/build/native-dynamic-backends.js +52 -0
- package/src/build/native-fetch-deadlines.as.ts +164 -0
- package/src/build/native-fetch-deadlines.js +27 -0
- package/src/build/native-fetch-errors.js +38 -0
- package/src/build/native-handle-ownership.js +127 -0
- package/src/build/native-header-lookup.js +50 -0
- package/src/build/native-http-effects.js +994 -0
- package/src/build/native-http-shell.js +703 -0
- package/src/build/native-platform-capabilities.js +2654 -0
- package/src/build/native-request-body.js +44 -0
- package/src/build/native-request-headers.js +93 -0
- package/src/build/native-send-error-detail.as.ts +12 -0
- package/src/build/native-stdio.js +45 -0
- package/src/build/native-string-values.js +143 -0
- package/src/build/native-transport-details.as.ts +84 -0
- package/src/build/native-value-budget.js +90 -0
- package/src/build/package-native-application.js +114 -0
- package/src/build/request-budget.as.ts +50 -0
- package/src/build/request-budget.js +47 -0
- package/src/build/s3-body.as.ts +97 -0
- package/src/build/s3-native.as.ts +228 -0
- package/src/build/s3-native.js +30 -0
- package/src/build/schema-admission.js +83 -0
- package/src/build/schema-nested-json.js +93 -0
- package/src/build/schema-scalar-record.js +41 -0
- package/src/build/time-native.js +49 -0
- package/src/build/wasm-budget.js +28 -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 +69 -0
- package/src/config-schema.d.ts +13 -0
- package/src/config-schema.js +27 -0
- package/src/config-schema.json +103 -0
- package/src/index.js +3 -0
- package/src/index.ts +143 -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 +147 -0
- package/src/javascript/lifecycle.js +55 -0
- package/src/javascript/local-loader.js +138 -0
- package/src/javascript/logging.js +35 -0
- package/src/javascript/package-effects.js +71 -0
- package/src/javascript/runtime-host.js +112 -0
- package/src/javascript/sha256.js +128 -0
- package/src/javascript/source-package.js +778 -0
- package/src/javascript/support.js +142 -0
- package/src/javascript/target-support-policy.js +277 -0
- package/src/javascript/target.js +89 -0
- package/src/javascript/test-runtime.js +408 -0
- package/src/provider-contract.js +88 -0
- package/src/runtime/assets-provider.js +464 -0
- package/src/runtime/canonical-api-runtime.js +603 -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 +155 -0
- package/src/testing/fastly-cli.js +538 -0
- package/src/testing/native-dynamic-backends-host.js +39 -0
- package/src/testing/native-http-effects-host.js +398 -0
- package/src/testing/native-http-shell-host.js +190 -0
- package/src/testing/native-platform-capabilities-host.js +924 -0
- package/src/toolchain/body-forwarding.js +25 -0
- package/src/toolchain/config.js +144 -0
- package/src/toolchain/index.js +386 -0
- package/src/toolchain/logging.js +18 -0
- package/src/toolchain/native-execution.js +78 -0
- package/src/toolchain/s3.js +26 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { fastlyJavascriptProviderError } = require('./errors.js');
|
|
4
|
+
|
|
5
|
+
const FASTLY_JAVASCRIPT_PACKAGE_EFFECTS_VERSION = 'pulse.fastly-javascript-package-effects.v1';
|
|
6
|
+
|
|
7
|
+
function unavailable(effect = {}) {
|
|
8
|
+
throw fastlyJavascriptProviderError(
|
|
9
|
+
'PULSE_RUNTIME_CAPABILITY_UNAVAILABLE',
|
|
10
|
+
`Pulse capability ${effect.capability || effect.kind || 'package-effect'} is unavailable in the Fastly JavaScript realization.`,
|
|
11
|
+
{ package: effect.package, contractId: effect.contractId, operation: effect.operation }
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function createFastlyJavascriptPackageEffectCapabilities(options = {}) {
|
|
16
|
+
const assetsLookup = options.assetsLookup;
|
|
17
|
+
const gripBroadcast = options.gripBroadcast;
|
|
18
|
+
const digestText = require('@pulse-compute/crypto/provider').createJavascriptTextDigest(options);
|
|
19
|
+
const jwtVerify = options.jwtVerify;
|
|
20
|
+
return Object.freeze({
|
|
21
|
+
version: FASTLY_JAVASCRIPT_PACKAGE_EFFECTS_VERSION,
|
|
22
|
+
effect(effect, execution) {
|
|
23
|
+
if (effect && effect.contractId === 'pulse.crypto' && effect.operation === 'digestText') return digestText(effect, execution);
|
|
24
|
+
if (effect && effect.contractId === 'pulse.assets' && effect.operation === 'lookup') {
|
|
25
|
+
if (typeof assetsLookup !== 'function') return unavailable(effect);
|
|
26
|
+
return assetsLookup(effect.payload, execution);
|
|
27
|
+
}
|
|
28
|
+
if (effect && effect.contractId === 'pulse.grip' && effect.operation === 'broadcast') {
|
|
29
|
+
if (typeof gripBroadcast !== 'function') {
|
|
30
|
+
throw fastlyJavascriptProviderError(
|
|
31
|
+
'PULSE_GRIP_BROADCAST_CAPABILITY_REQUIRED',
|
|
32
|
+
'GRIP broadcast requires a configured Fastly publish capability.',
|
|
33
|
+
{ package: effect.package, operation: 'broadcast', configuration: 'bindings.grip.publishEndpoint' }
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
return gripBroadcast(effect.payload, execution);
|
|
37
|
+
}
|
|
38
|
+
if (effect && effect.contractId === 'pulse.jwt' && ['verify', 'sign'].includes(effect.operation)) {
|
|
39
|
+
if (typeof jwtVerify !== 'function') return unavailable(effect);
|
|
40
|
+
return jwtVerify(effect, execution);
|
|
41
|
+
}
|
|
42
|
+
return unavailable(effect);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function withFastlyPackageEffectCapabilities(capabilities, options = {}) {
|
|
48
|
+
const base = capabilities && typeof capabilities === 'object' ? capabilities : {};
|
|
49
|
+
const configured = createFastlyJavascriptPackageEffectCapabilities(options);
|
|
50
|
+
return Object.freeze({
|
|
51
|
+
...base,
|
|
52
|
+
effect(effect, execution) {
|
|
53
|
+
if (effect && (
|
|
54
|
+
effect.contractId === 'pulse.crypto'
|
|
55
|
+
|| effect.contractId === 'pulse.assets'
|
|
56
|
+
|| effect.contractId === 'pulse.grip'
|
|
57
|
+
|| effect.contractId === 'pulse.jwt'
|
|
58
|
+
)) {
|
|
59
|
+
return configured.effect(effect, execution);
|
|
60
|
+
}
|
|
61
|
+
if (typeof base.effect === 'function') return base.effect(effect, execution);
|
|
62
|
+
return unavailable(effect);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = Object.freeze({
|
|
68
|
+
FASTLY_JAVASCRIPT_PACKAGE_EFFECTS_VERSION,
|
|
69
|
+
createFastlyJavascriptPackageEffectCapabilities,
|
|
70
|
+
withFastlyPackageEffectCapabilities
|
|
71
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
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({ time: () => runtimeHost.readWallTime(options.wallClock === undefined ? () => Date.now() : options.wallClock), ...options.capabilities }, { ...options, bindingCapabilities }),
|
|
49
|
+
{ ...options, fetchImplementation: options.fetchImplementation }
|
|
50
|
+
),
|
|
51
|
+
{ assetsLookup, gripBroadcast, jwtVerify, digestSubtle: options.digestSubtle }
|
|
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
|
+
if (options.maxDurationMs !== undefined || options.requestBudget !== undefined) {
|
|
61
|
+
throw new runtimeHost.PulseRuntimeContractError('PULSE_REQUEST_DURATION_UNSUPPORTED', 'Fastly JavaScript does not implement the request deadline; select Native.');
|
|
62
|
+
}
|
|
63
|
+
const capabilities = options.effectAdapter === undefined
|
|
64
|
+
? createFastlyJavascriptCapabilities(options)
|
|
65
|
+
: undefined;
|
|
66
|
+
return runtimeHost.executeApplication(assertFastlyJavascriptApplication(application), request, {
|
|
67
|
+
capabilities,
|
|
68
|
+
effectAdapter: options.effectAdapter,
|
|
69
|
+
application: options.application,
|
|
70
|
+
requestHeaders: options.requestHeaders || requestHeaderPairs(request),
|
|
71
|
+
signal: options.signal || request.signal,
|
|
72
|
+
maxEffects: options.maxEffects,
|
|
73
|
+
maxRequestBodyBytes: options.maxRequestBodyBytes,
|
|
74
|
+
maxFetchBodyBytes: options.maxFetchBodyBytes,
|
|
75
|
+
maxStructuredBodyBytes: options.maxStructuredBodyBytes,
|
|
76
|
+
maxBindingNameBytes: options.maxBindingNameBytes,
|
|
77
|
+
maxBindingValueBytes: options.maxBindingValueBytes,
|
|
78
|
+
maxKvNamespaceBytes: options.maxKvNamespaceBytes,
|
|
79
|
+
maxKvKeyBytes: options.maxKvKeyBytes,
|
|
80
|
+
maxKvValueBytes: options.maxKvValueBytes,
|
|
81
|
+
maxKvValueDepth: options.maxKvValueDepth,
|
|
82
|
+
maxKvValueEntries: options.maxKvValueEntries,
|
|
83
|
+
binaryResources: options.binaryResources,
|
|
84
|
+
schemaCodecs: options.schemaCodecs,
|
|
85
|
+
strict: options.strict === true,
|
|
86
|
+
target: 'javascript',
|
|
87
|
+
provider: 'fastly',
|
|
88
|
+
reporting: options.reporting,
|
|
89
|
+
log: options.log || createFastlyJavascriptLogEmitter({ console: options.console, logEndpoint: options.bindings?.logEndpoint, Logger: options.apis?.Logger }),
|
|
90
|
+
redactionValues: options.redactionValues,
|
|
91
|
+
onLogObservation: options.onLogObservation,
|
|
92
|
+
onJsonTrace: options.onJsonTrace,
|
|
93
|
+
onEffectObservation: options.onEffectObservation,
|
|
94
|
+
onEffectSummary: options.onEffectSummary
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
module.exports = Object.freeze({
|
|
99
|
+
FASTLY_JAVASCRIPT_RUNTIME_HOST_VERSION,
|
|
100
|
+
PulseRuntimeContractError: runtimeHost.PulseRuntimeContractError,
|
|
101
|
+
createFastlyJavascriptAssetsLookup,
|
|
102
|
+
createFastlyJavascriptBindingCapabilities,
|
|
103
|
+
createFastlyJavascriptCapabilities,
|
|
104
|
+
createFastlyJavascriptFetchCapability,
|
|
105
|
+
createFastlyJavascriptGripBroadcast,
|
|
106
|
+
createFastlyJavascriptJwtVerify,
|
|
107
|
+
createFastlyJavascriptLogEmitter,
|
|
108
|
+
assertFastlyJavascriptApplication,
|
|
109
|
+
executeFastlyJavascriptApplication,
|
|
110
|
+
isFastlyJavascriptApplication,
|
|
111
|
+
requestHeaderPairs
|
|
112
|
+
});
|
|
@@ -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 });
|