@pulse-compute/provider-node 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 +61 -1
- package/package.json +62 -6
- package/src/capabilities.js +65 -0
- package/src/compiler/assets-provider-proof.js +434 -0
- package/src/compiler/backend-json-request-body-proof.js +90 -0
- package/src/compiler/index.js +38 -0
- package/src/compiler/node-adapter.js +452 -0
- package/src/compiler/node-compiled-wasm-assets-lifecycle-proof.js +435 -0
- package/src/compiler/request-json-body-proof.js +181 -0
- package/src/compiler/route-handler-compiled-wasm-bridge.js +323 -0
- package/src/compiler/route-handler-effect-proof.js +215 -0
- package/src/compiler/route-handler-live-origin-proof.js +372 -0
- package/src/compiler/schema-decode-result-proof.js +180 -0
- package/src/compiler/schema-response-codec-proof.js +149 -0
- package/src/config/s3.js +20 -0
- package/src/events/reference-adapter.js +145 -0
- package/src/index.js +57 -0
- package/src/javascript/assets-adapter.js +68 -0
- package/src/javascript/bindings-adapter.js +90 -0
- package/src/javascript/fetch-adapter.js +187 -0
- package/src/javascript/grip-broadcast.js +243 -0
- package/src/javascript/jwt-verifier.js +137 -0
- package/src/javascript/lifecycle.js +69 -0
- package/src/javascript/node-adapter.js +284 -0
- package/src/javascript/package-effects.js +84 -0
- package/src/javascript/runtime-host.js +170 -0
- package/src/javascript/s3.js +21 -0
- package/src/javascript/source-package.js +439 -0
- package/src/javascript/support.js +205 -0
- package/src/javascript/target-support-policy.js +136 -0
- package/src/javascript/target.js +37 -0
- package/src/javascript/test-runtime.js +112 -0
- package/src/native/target.js +78 -0
- package/src/runtime/assets-provider.js +776 -0
- package/src/runtime/canonical-api-runtime.js +604 -0
- package/src/runtime/compiled-wasm-node-adapter-kv.js +15 -0
- package/src/runtime/conditional-kv.js +93 -0
- package/src/runtime/index.js +18 -0
- package/src/runtime/jwt-verifier.js +264 -0
- package/src/runtime/route-handler-effects.js +757 -0
- package/src/runtime/s3-reader.js +131 -0
- package/src/toolchain.js +269 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const https = require('node:https');
|
|
3
|
+
const { Readable } = require('node:stream');
|
|
4
|
+
const { performance } = require('node:perf_hooks');
|
|
5
|
+
const protocol = require('@pulse-compute/s3/provider');
|
|
6
|
+
|
|
7
|
+
function originRequest(request, signal) {
|
|
8
|
+
return new Promise((resolve, reject) => {
|
|
9
|
+
const req = https.request(request.url, { method: request.method, headers: request.headers, signal, maxHeaderSize: 16384 }, (response) => {
|
|
10
|
+
let headers = [];
|
|
11
|
+
try {
|
|
12
|
+
const decoder = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
|
|
13
|
+
// Node exposes HTTP header octets as Latin-1 strings. Interpret the
|
|
14
|
+
// bounded protocol metadata as UTF-8, matching the Native host ABI.
|
|
15
|
+
for (let i = 0; i < response.rawHeaders.length; i += 2) headers.push([response.rawHeaders[i], decoder.decode(Buffer.from(response.rawHeaders[i + 1], 'latin1'))]);
|
|
16
|
+
} catch { headers = null; }
|
|
17
|
+
resolve({ status: response.statusCode, headers, body: response, close: () => response.destroy() });
|
|
18
|
+
});
|
|
19
|
+
req.once('error', reject);
|
|
20
|
+
req.end(request.body);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
async function fetchFixture(fetch, request, signal) {
|
|
24
|
+
const pending = Promise.resolve().then(() => fetch(request.url, { method: request.method, headers: request.headers, ...(request.body === undefined ? {} : { body: request.body }), redirect: 'manual', cache: 'no-store', signal }));
|
|
25
|
+
pending.then((response) => { if (signal.aborted && response.body) void response.body.cancel().catch(() => {}); }, () => {});
|
|
26
|
+
const response = await abortable(pending, signal);
|
|
27
|
+
const body = response.body ? Readable.fromWeb(response.body, { signal }) : null;
|
|
28
|
+
// A deadline can fire before iteration begins; always observe the stream error.
|
|
29
|
+
if (body) body.on('error', () => {});
|
|
30
|
+
return { status: response.status, headers: [...response.headers], body, close: () => { if (body) body.destroy(); } };
|
|
31
|
+
}
|
|
32
|
+
function abortable(promise, signal) {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const abort = () => reject(signal.reason);
|
|
35
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
36
|
+
promise.then(resolve, reject).finally(() => signal.removeEventListener('abort', abort));
|
|
37
|
+
if (signal.aborted) abort();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async function readS3(effect, options, lookup) {
|
|
41
|
+
const operation = effect.operation, put = operation === 'putText';
|
|
42
|
+
const payload = effect.payload || {};
|
|
43
|
+
if (!['head', 'getText', 'putText'].includes(operation) || effect.kind !== `s3.${operation}` || effect.capability !== effect.kind
|
|
44
|
+
|| effect.package !== '@pulse-compute/s3' || effect.contractId !== 'pulse.s3' || effect.providerKind !== 's3') throw new TypeError('Invalid S3 package effect authority.');
|
|
45
|
+
let dispatched = false, status;
|
|
46
|
+
const failure = (reason) => put ? protocol.putFailure(reason, dispatched, status) : protocol.failure(reason, status);
|
|
47
|
+
if (options.signal && options.signal.aborted) throw options.signal.reason || new Error('Request cancelled.');
|
|
48
|
+
const configured = typeof payload.binding === 'string' && options.s3 && Object.hasOwn(options.s3, payload.binding) && options.s3[payload.binding];
|
|
49
|
+
let binding;
|
|
50
|
+
try { binding = protocol.normalizeBinding(configured); } catch { return failure('configuration'); }
|
|
51
|
+
const controller = new AbortController();
|
|
52
|
+
const onAbort = () => controller.abort(options.signal.reason);
|
|
53
|
+
if (options.signal) options.signal.addEventListener('abort', onAbort, { once: true });
|
|
54
|
+
let timedOut = false;
|
|
55
|
+
const deadline = performance.now() + binding.timeoutMs;
|
|
56
|
+
const check = () => {
|
|
57
|
+
if (performance.now() >= deadline) { timedOut = true; controller.abort(); }
|
|
58
|
+
if (controller.signal.aborted) throw controller.signal.reason || new Error('S3 deadline expired.');
|
|
59
|
+
};
|
|
60
|
+
const timer = setTimeout(() => { timedOut = true; controller.abort(); }, binding.timeoutMs);
|
|
61
|
+
const wait = async (value) => { const result = await abortable(Promise.resolve(value), controller.signal); check(); return result; };
|
|
62
|
+
let response;
|
|
63
|
+
try {
|
|
64
|
+
const key = protocol.encodeKey(payload.key);
|
|
65
|
+
if (key === null) return failure('invalid-key');
|
|
66
|
+
let body, contentType;
|
|
67
|
+
if (put) {
|
|
68
|
+
if (typeof payload.text !== 'string' || !payload.text.isWellFormed()) return failure('invalid-text');
|
|
69
|
+
body = protocol.bytes(payload.text);
|
|
70
|
+
if (body.length > binding.maxTextBytes) return failure('too-large');
|
|
71
|
+
try { contentType = protocol.normalizePutOptions({ contentType: payload.contentType }).contentType; }
|
|
72
|
+
catch { return failure('configuration'); }
|
|
73
|
+
}
|
|
74
|
+
let accessId, secret, token;
|
|
75
|
+
try {
|
|
76
|
+
accessId = await wait(lookup(binding.accessKeyIdSecret));
|
|
77
|
+
secret = await wait(lookup(binding.secretAccessKeySecret));
|
|
78
|
+
token = binding.sessionTokenSecret === undefined ? undefined : await wait(lookup(binding.sessionTokenSecret));
|
|
79
|
+
} catch (error) { check(); return failure('credentials'); }
|
|
80
|
+
if (!protocol.credentialsValid(accessId, secret, token)) return failure('credentials');
|
|
81
|
+
for (const value of [accessId, secret, token]) if (typeof options.registerRedactionValue === 'function' && typeof value === 'string') options.registerRedactionValue(value);
|
|
82
|
+
const crypto = options.cryptoVerifier && options.cryptoVerifier.bytes;
|
|
83
|
+
const algorithms = options.cryptoRealization && options.cryptoRealization.algorithms;
|
|
84
|
+
const realization = options.cryptoTarget === 'javascript' ? 'runtime-builtin' : 'guest-source:pulse-hmac-as';
|
|
85
|
+
if (!crypto || !Array.isArray(algorithms) || ['SHA-256', 'HMAC-SHA256'].some((algorithm) => !algorithms.some((entry) => entry.algorithm === algorithm && entry.available && entry.realization === realization))) return failure('configuration');
|
|
86
|
+
let request;
|
|
87
|
+
try {
|
|
88
|
+
request = await wait(protocol.signRequest({ binding, method: put ? 'PUT' : operation === 'head' ? 'HEAD' : 'GET', encodedKey: key, accessId, secret, token, now: Date.now(), body, contentType }, crypto));
|
|
89
|
+
} catch (error) { check(); return failure('configuration'); }
|
|
90
|
+
check();
|
|
91
|
+
// The send primitive may have side effects even if it throws synchronously.
|
|
92
|
+
dispatched = true;
|
|
93
|
+
response = options.fetchImplementation
|
|
94
|
+
? await fetchFixture(options.fetchImplementation, request, controller.signal)
|
|
95
|
+
: await originRequest(request, controller.signal);
|
|
96
|
+
status = response.status;
|
|
97
|
+
check();
|
|
98
|
+
const rejected = put ? protocol.putStatusResult(status) : protocol.statusResult(status);
|
|
99
|
+
if (rejected && (!put || rejected.status === 'unknown')) return rejected;
|
|
100
|
+
const metadata = protocol.metadataFromHeaders(response.headers, operation === 'head');
|
|
101
|
+
if (!metadata) return failure('protocol');
|
|
102
|
+
if (operation === 'head') return protocol.normalizeResult(operation, { status: 'found', ...metadata });
|
|
103
|
+
const maximum = put ? rejected ? binding.maxTextBytes : 0 : binding.maxTextBytes;
|
|
104
|
+
if (metadata.byteLength > maximum) return failure(put ? 'protocol' : 'too-large');
|
|
105
|
+
const chunks = []; let total = 0;
|
|
106
|
+
if (response.body) for await (const chunk of response.body) {
|
|
107
|
+
check(); total += chunk.length;
|
|
108
|
+
if (total > maximum) return failure(put ? 'protocol' : 'too-large');
|
|
109
|
+
if (!put) chunks.push(Buffer.from(chunk));
|
|
110
|
+
}
|
|
111
|
+
check();
|
|
112
|
+
if (metadata.byteLength !== undefined && metadata.byteLength !== total) return failure('protocol');
|
|
113
|
+
if (put) return rejected || protocol.normalizeResult(operation, { status: 'stored', byteLength: body.length, sha256: request.headers['x-amz-content-sha256'], ...(metadata.etag === undefined ? {} : { etag: metadata.etag }) });
|
|
114
|
+
const raw = Buffer.concat(chunks, total);
|
|
115
|
+
const digest = protocol.hex(await wait(crypto.sha256(raw)));
|
|
116
|
+
let text;
|
|
117
|
+
try { text = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(raw); }
|
|
118
|
+
catch { return failure('invalid-utf8'); }
|
|
119
|
+
check();
|
|
120
|
+
return protocol.normalizeResult(operation, { status: 'found', ...metadata, byteLength: total, text, sha256: digest });
|
|
121
|
+
} catch (error) {
|
|
122
|
+
if (options.signal && options.signal.aborted) throw options.signal.reason || error;
|
|
123
|
+
return failure(timedOut ? 'timeout' : status === undefined ? 'transport' : 'protocol');
|
|
124
|
+
} finally {
|
|
125
|
+
clearTimeout(timer);
|
|
126
|
+
if (options.signal) options.signal.removeEventListener('abort', onAbort);
|
|
127
|
+
controller.abort();
|
|
128
|
+
if (response) { try { await response.close(); } catch {} }
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
module.exports = { readS3, originRequest };
|
package/src/toolchain.js
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const {
|
|
5
|
+
PROVIDER_DRIVER_VERSION,
|
|
6
|
+
PROVIDER_TARGET_RESULT_VERSION,
|
|
7
|
+
PROVIDER_PACKAGING_AUDIT_VERSION,
|
|
8
|
+
defineProviderToolchain,
|
|
9
|
+
defineProviderDriver,
|
|
10
|
+
normalizeProviderTargetResult,
|
|
11
|
+
normalizeProviderJavascriptPackageResult
|
|
12
|
+
} = require('@pulse-compute/wasm-contracts/provider/toolchain');
|
|
13
|
+
const canonicalProvider = require('@pulse-compute/wasm-contracts/provider/canonical-provider');
|
|
14
|
+
const nodeRuntime = require('./runtime/canonical-api-runtime.js');
|
|
15
|
+
const { NODE_NATIVE_TARGET_DESCRIPTOR } = require('./native/target.js');
|
|
16
|
+
const { NODE_JAVASCRIPT_TARGET_DESCRIPTOR } = require('./javascript/target.js');
|
|
17
|
+
const { NODE_JAVASCRIPT_TARGET_SUPPORT_DECLARATION } = require('./javascript/support.js');
|
|
18
|
+
const {
|
|
19
|
+
classifyNodeJavascriptCapability,
|
|
20
|
+
classifyNodeJavascriptProviderRequirement
|
|
21
|
+
} = require('./javascript/target-support-policy.js');
|
|
22
|
+
const nodeJavascriptHost = require('./javascript/runtime-host.js');
|
|
23
|
+
const nodeJavascriptLifecycle = require('./javascript/lifecycle.js');
|
|
24
|
+
const nodeJavascriptTestRuntime = require('./javascript/test-runtime.js');
|
|
25
|
+
const { createNodeEventReferenceAdapter } = require('./events/reference-adapter.js');
|
|
26
|
+
const { writeNodeJavascriptSourcePackage } = require('./javascript/source-package.js');
|
|
27
|
+
const packageManifest = require('../package.json');
|
|
28
|
+
|
|
29
|
+
const reportingTargetCapability = Object.freeze({
|
|
30
|
+
supported: true,
|
|
31
|
+
default: 'info',
|
|
32
|
+
levels: Object.freeze(['off', 'error', 'warn', 'info', 'debug'])
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
function genericProviderConfig(value) {
|
|
36
|
+
const input = value && typeof value === 'object' ? value : {};
|
|
37
|
+
const bindings = input.bindings || {};
|
|
38
|
+
if (Object.keys(bindings).some((key) => key !== 's3')) throw new TypeError('Unknown Node binding field.');
|
|
39
|
+
return Object.freeze({ kind: 'node', bindings: Object.freeze({ s3: require('./config/s3.js').normalizeNodeS3(bindings.s3) }), local: Object.freeze({}) });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function nodeRealization(nativeArtifact) {
|
|
43
|
+
return Object.freeze({
|
|
44
|
+
target: 'node-native-host',
|
|
45
|
+
provider: 'node',
|
|
46
|
+
providerNeutralWasm: true,
|
|
47
|
+
nativeWasm: true,
|
|
48
|
+
compiledWasmPresent: true,
|
|
49
|
+
sourceOnly: false,
|
|
50
|
+
sourceOnlySupported: false,
|
|
51
|
+
javascriptRuntime: false,
|
|
52
|
+
jsComputeRuntime: false,
|
|
53
|
+
wasm: nativeArtifact.manifest.wasm,
|
|
54
|
+
wat: nativeArtifact.manifest.wat,
|
|
55
|
+
importModules: nativeArtifact.manifest.importModules,
|
|
56
|
+
imports: nativeArtifact.manifest.imports,
|
|
57
|
+
exports: nativeArtifact.manifest.exports,
|
|
58
|
+
packageRealizationArtifacts: nativeArtifact.manifest.packageRealizationArtifacts,
|
|
59
|
+
compiler: Object.freeze({
|
|
60
|
+
package: nativeArtifact.manifest.assemblyScript.package,
|
|
61
|
+
version: nativeArtifact.manifest.assemblyScript.version,
|
|
62
|
+
targetCompilerVersion: nativeArtifact.compilerVersion
|
|
63
|
+
}),
|
|
64
|
+
optimization: nativeArtifact.manifest.optimization
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function targetSupportContext(_compiled, _project, declaration) {
|
|
69
|
+
const gates = declaration.availability && declaration.availability.gates || [];
|
|
70
|
+
return Object.freeze({
|
|
71
|
+
bindingsRedaction: gates.some((entry) => entry.id === 'bindings-redaction' && entry.status === 'satisfied'),
|
|
72
|
+
gripRealized: gates.some((entry) => entry.id === 'grip-readiness' && entry.evidence && entry.evidence.status === 'passed')
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function executeNodeEventTestCase(invocation = {}) {
|
|
77
|
+
const target = String(invocation.target || '');
|
|
78
|
+
if (!['javascript', 'native'].includes(target)) {
|
|
79
|
+
throw new TypeError(`Node event test execution does not support target ${JSON.stringify(target)}.`);
|
|
80
|
+
}
|
|
81
|
+
const testCase = invocation.testCase || {};
|
|
82
|
+
const options = invocation.options || {};
|
|
83
|
+
const adapter = createNodeEventReferenceAdapter({
|
|
84
|
+
id: `pulse-test-${target}`,
|
|
85
|
+
maxQueueDepth: 1024
|
|
86
|
+
});
|
|
87
|
+
let executionEvidence = null;
|
|
88
|
+
const common = {
|
|
89
|
+
application: options.application,
|
|
90
|
+
config: testCase.config || {},
|
|
91
|
+
secrets: testCase.secrets || {},
|
|
92
|
+
kv: testCase.kv || {},
|
|
93
|
+
grip: testCase.grip || {},
|
|
94
|
+
fetches: testCase.fetches || {},
|
|
95
|
+
eventAdapter: adapter,
|
|
96
|
+
schemaCodecs: options.schemaCodecs,
|
|
97
|
+
reporting: options.reporting,
|
|
98
|
+
maxEffects: options.maxEffects,
|
|
99
|
+
maxBindingNameBytes: options.maxBindingNameBytes,
|
|
100
|
+
maxBindingValueBytes: options.maxBindingValueBytes,
|
|
101
|
+
maxKvNamespaceBytes: options.maxKvNamespaceBytes,
|
|
102
|
+
maxKvKeyBytes: options.maxKvKeyBytes,
|
|
103
|
+
maxKvValueBytes: options.maxKvValueBytes,
|
|
104
|
+
maxKvValueDepth: options.maxKvValueDepth,
|
|
105
|
+
maxKvValueEntries: options.maxKvValueEntries
|
|
106
|
+
};
|
|
107
|
+
const result = target === 'javascript'
|
|
108
|
+
? await nodeJavascriptHost.executeNodeJavascriptEvent(invocation.application, testCase.event, {
|
|
109
|
+
...common,
|
|
110
|
+
fetchImplementation: nodeJavascriptHost.createNodeJavascriptFixtureFetch(
|
|
111
|
+
testCase.fetches || {},
|
|
112
|
+
options.networkFetch === true ? globalThis.fetch : undefined
|
|
113
|
+
),
|
|
114
|
+
onEffectSummary(value) { executionEvidence = value; }
|
|
115
|
+
})
|
|
116
|
+
: await nodeRuntime.executeNodeNativeEvent(invocation.application, testCase.event, {
|
|
117
|
+
...common,
|
|
118
|
+
onEventExecutionEvidence(value) { executionEvidence = value; }
|
|
119
|
+
});
|
|
120
|
+
return Object.freeze({
|
|
121
|
+
version: 'pulse.provider-event-test-result.v1',
|
|
122
|
+
target,
|
|
123
|
+
result,
|
|
124
|
+
emittedFrames: adapter.acceptedFrames(),
|
|
125
|
+
adapter: adapter.summary(),
|
|
126
|
+
executionEvidence
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function createDriver() {
|
|
131
|
+
return defineProviderDriver({
|
|
132
|
+
version: PROVIDER_DRIVER_VERSION,
|
|
133
|
+
id: 'node',
|
|
134
|
+
descriptor: nodeRuntime.NODE_PROVIDER_DESCRIPTOR,
|
|
135
|
+
executable: true,
|
|
136
|
+
localExecution: true,
|
|
137
|
+
deployable: true,
|
|
138
|
+
deploymentValidated: false,
|
|
139
|
+
sourcePackage: false,
|
|
140
|
+
compiledWasm: true,
|
|
141
|
+
defaultBuildMode: 'native-provider',
|
|
142
|
+
sourceOnlySupported: false,
|
|
143
|
+
targetSupport: Object.freeze({ javascript: NODE_JAVASCRIPT_TARGET_SUPPORT_DECLARATION }),
|
|
144
|
+
normalizeConfig: genericProviderConfig,
|
|
145
|
+
configReference: Object.freeze({
|
|
146
|
+
sections: [{ id: 'node', title: 'Node provider options', description: 'Provider-owned Node profile configuration.' }],
|
|
147
|
+
fields: [{ section: 'node', path: 'node.bindings.s3', type: 'Readonly<Record<string, S3Binding>>', default: '`{}`', scope: 'Node Native and JavaScript S3',
|
|
148
|
+
description: 'Maps literal logical names to fixed HTTPS endpoint, bucket, region, accessKeyIdSecret, secretAccessKeySecret, optional sessionTokenSecret, maxTextBytes (1–32768, default 32768) and timeoutMs (1–30000, default 10000).',
|
|
149
|
+
security: 'Only named credential references are configuration. Runtime keys cannot override authority.' }]
|
|
150
|
+
}),
|
|
151
|
+
defaultLocalNetworkFetch: true,
|
|
152
|
+
projectConfigDocument(config) { return Object.keys(config.bindings.s3).length ? config : undefined; },
|
|
153
|
+
initTemplate() {
|
|
154
|
+
return Object.freeze({ profileFragment: '', dependencies: Object.freeze({}) });
|
|
155
|
+
},
|
|
156
|
+
executionOptions(config, values) {
|
|
157
|
+
return Object.freeze({
|
|
158
|
+
...values,
|
|
159
|
+
s3: config.bindings.s3,
|
|
160
|
+
providerAdapter: nodeRuntime.createNodeProviderAdapter()
|
|
161
|
+
});
|
|
162
|
+
},
|
|
163
|
+
javascript: Object.freeze({
|
|
164
|
+
kind: 'reference-node',
|
|
165
|
+
localEmulation: false,
|
|
166
|
+
buildTimeLoader: false,
|
|
167
|
+
validateApplication: nodeJavascriptHost.assertNodeJavascriptApplication,
|
|
168
|
+
targetSupportPolicy: Object.freeze({
|
|
169
|
+
providerId: 'node',
|
|
170
|
+
declaration: NODE_JAVASCRIPT_TARGET_SUPPORT_DECLARATION,
|
|
171
|
+
context: targetSupportContext,
|
|
172
|
+
classifyCapability: classifyNodeJavascriptCapability,
|
|
173
|
+
classifyProviderRequirement: classifyNodeJavascriptProviderRequirement
|
|
174
|
+
}),
|
|
175
|
+
writeSourcePackage(invocation) {
|
|
176
|
+
return normalizeProviderJavascriptPackageResult(writeNodeJavascriptSourcePackage({
|
|
177
|
+
plan: invocation.applicationPlan,
|
|
178
|
+
projectRoot: invocation.project.root,
|
|
179
|
+
outDir: invocation.project.outDir,
|
|
180
|
+
schemaBundle: invocation.javascript.schemaBundle
|
|
181
|
+
}), { provider: 'node' });
|
|
182
|
+
},
|
|
183
|
+
describeSourcePackage(sourcePackage) {
|
|
184
|
+
return Object.freeze({
|
|
185
|
+
deploymentCandidate: false,
|
|
186
|
+
downstreamJavascriptRuntimeWasm: false,
|
|
187
|
+
application: Object.freeze({
|
|
188
|
+
entry: path.basename(sourcePackage.paths.entry),
|
|
189
|
+
modules: sourcePackage.manifest.summary.modules
|
|
190
|
+
}),
|
|
191
|
+
files: Object.freeze({})
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
executeTestCase(application, testCase, options) {
|
|
195
|
+
return nodeJavascriptTestRuntime.executeNodeJavascriptTestCase(application, testCase, options);
|
|
196
|
+
},
|
|
197
|
+
createServer: nodeJavascriptLifecycle.createNodeJavascriptServer,
|
|
198
|
+
createFixtureFetch: nodeJavascriptHost.createNodeJavascriptFixtureFetch
|
|
199
|
+
}),
|
|
200
|
+
events: Object.freeze({
|
|
201
|
+
targets: Object.freeze(['javascript', 'native']),
|
|
202
|
+
executeTestCase: executeNodeEventTestCase
|
|
203
|
+
}),
|
|
204
|
+
targets: Object.freeze({
|
|
205
|
+
native: Object.freeze({
|
|
206
|
+
...NODE_NATIVE_TARGET_DESCRIPTOR,
|
|
207
|
+
target: 'native',
|
|
208
|
+
targetId: 'node-native-host',
|
|
209
|
+
runtimeClass: 'native',
|
|
210
|
+
status: 'supported',
|
|
211
|
+
automaticFallback: false,
|
|
212
|
+
reporting: reportingTargetCapability,
|
|
213
|
+
commands: Object.freeze({ compile: true, inspect: true, doctor: true, build: true, test: true, dev: true })
|
|
214
|
+
}),
|
|
215
|
+
javascript: NODE_JAVASCRIPT_TARGET_DESCRIPTOR
|
|
216
|
+
}),
|
|
217
|
+
execute: nodeRuntime.executeCanonicalProgram,
|
|
218
|
+
createLoweringPlan(metadata, config = {}) {
|
|
219
|
+
require('./config/s3.js').validateNodeS3Operations(metadata, config.bindings || {});
|
|
220
|
+
return canonicalProvider.createProviderLoweringPlan(metadata, nodeRuntime.NODE_PROVIDER_DESCRIPTOR, {
|
|
221
|
+
grip: 'node-reference-broadcaster'
|
|
222
|
+
});
|
|
223
|
+
},
|
|
224
|
+
inspectRealization(invocation) {
|
|
225
|
+
const realization = nodeRealization(invocation.nativeArtifact);
|
|
226
|
+
return normalizeProviderTargetResult({
|
|
227
|
+
version: PROVIDER_TARGET_RESULT_VERSION,
|
|
228
|
+
action: 'inspect-native',
|
|
229
|
+
provider: 'node',
|
|
230
|
+
target: 'native',
|
|
231
|
+
status: 'inspected',
|
|
232
|
+
automaticFallback: false,
|
|
233
|
+
files: Object.freeze({}),
|
|
234
|
+
build: null,
|
|
235
|
+
realization,
|
|
236
|
+
packaging: null
|
|
237
|
+
});
|
|
238
|
+
},
|
|
239
|
+
writeTarget(invocation) {
|
|
240
|
+
const realization = nodeRealization(invocation.nativeArtifact);
|
|
241
|
+
const audit = invocation.nativeArtifact.guestAudit;
|
|
242
|
+
return normalizeProviderTargetResult({
|
|
243
|
+
version: PROVIDER_TARGET_RESULT_VERSION,
|
|
244
|
+
action: 'write-native',
|
|
245
|
+
provider: 'node',
|
|
246
|
+
target: 'native',
|
|
247
|
+
status: 'built',
|
|
248
|
+
automaticFallback: false,
|
|
249
|
+
files: Object.freeze({}),
|
|
250
|
+
build: realization,
|
|
251
|
+
realization,
|
|
252
|
+
packaging: audit ? Object.freeze({
|
|
253
|
+
version: PROVIDER_PACKAGING_AUDIT_VERSION,
|
|
254
|
+
artifactSha256: invocation.nativeArtifact.finalArtifact.sha256,
|
|
255
|
+
auditedSha256: audit.finalArtifact.sha256,
|
|
256
|
+
authorized: audit.providerPackaging.authorized === true
|
|
257
|
+
}) : null
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
module.exports = defineProviderToolchain({
|
|
264
|
+
version: 'pulse.provider-toolchain.v1',
|
|
265
|
+
id: 'node',
|
|
266
|
+
packageName: packageManifest.name,
|
|
267
|
+
packageVersion: packageManifest.version,
|
|
268
|
+
createDriver
|
|
269
|
+
});
|