@pulse-compute/wasm-library-kit 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 +42 -1
- package/package.json +34 -6
- package/src/compiler/assets-lowering.js +160 -0
- package/src/compiler/handler-library-contracts.js +752 -0
- package/src/compiler/host-capabilities.js +297 -0
- package/src/compiler/index.js +30 -0
- package/src/compiler/library-sidecars.js +522 -0
- package/src/compiler/package-contracts.js +243 -0
- package/src/compiler/package-lowering.js +47 -0
- package/src/index.js +8 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { PACKAGE_VERSION, normalizeArtifact, normalizeDiagnostic } = loadContractsDiagnostics();
|
|
4
|
+
|
|
5
|
+
const PHASE = '11E';
|
|
6
|
+
|
|
7
|
+
function loadContractsDiagnostics() {
|
|
8
|
+
try {
|
|
9
|
+
return require('@pulse-compute/wasm-contracts/diagnostics');
|
|
10
|
+
} catch (error) {
|
|
11
|
+
if (error && error.code === 'MODULE_NOT_FOUND' && String(error.message).includes('@pulse-compute/wasm-contracts')) {
|
|
12
|
+
return require('../../../contracts/src/diagnostics.js');
|
|
13
|
+
}
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const {
|
|
19
|
+
HOST_CAPABILITIES_VERSION,
|
|
20
|
+
WASI_PROVIDER_MAP_VERSION,
|
|
21
|
+
CAPABILITY_PROVIDER_REPORT_VERSION,
|
|
22
|
+
HOST_CAPABILITY_CONTRACT_VERSION,
|
|
23
|
+
CAPABILITY_DEFINITIONS,
|
|
24
|
+
PROVIDER_DEFINITIONS,
|
|
25
|
+
knownHostCapabilities,
|
|
26
|
+
isKnownHostCapability
|
|
27
|
+
} = loadContractsHostCapabilities();
|
|
28
|
+
|
|
29
|
+
function loadContractsHostCapabilities() {
|
|
30
|
+
try {
|
|
31
|
+
return require('@pulse-compute/wasm-contracts/host/capabilities');
|
|
32
|
+
} catch (error) {
|
|
33
|
+
if (error && error.code === 'MODULE_NOT_FOUND' && String(error.message).includes('@pulse-compute/wasm-contracts')) {
|
|
34
|
+
return require('../../../contracts/src/host/capabilities.js');
|
|
35
|
+
}
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function sortedUnique(values) {
|
|
41
|
+
return Array.from(new Set((values || []).filter(Boolean))).sort();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function makeDiagnostic(code, message, hint, details) {
|
|
45
|
+
return normalizeDiagnostic({
|
|
46
|
+
phase: 'host-capabilities',
|
|
47
|
+
severity: 'error',
|
|
48
|
+
code,
|
|
49
|
+
message,
|
|
50
|
+
hint,
|
|
51
|
+
details,
|
|
52
|
+
loc: { file: '<host-capabilities>' }
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function capabilitiesFromLibraries(handlerLibraryContracts) {
|
|
57
|
+
const libraries = handlerLibraryContracts?.libraryCapabilities?.libraries
|
|
58
|
+
|| handlerLibraryContracts?.libraryCapabilities?.artifact?.libraries
|
|
59
|
+
|| handlerLibraryContracts?.libraryCapabilities?.libraries
|
|
60
|
+
|| [];
|
|
61
|
+
const capabilities = [];
|
|
62
|
+
for (const library of libraries) {
|
|
63
|
+
capabilities.push(...(library.hostCapabilities || []));
|
|
64
|
+
for (const lowering of library.lowerings || []) {
|
|
65
|
+
capabilities.push(...(lowering.hostCapabilities || []));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return sortedUnique(capabilities);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function buildHostCapabilityContract(requiredCapabilities) {
|
|
72
|
+
return {
|
|
73
|
+
version: HOST_CAPABILITY_CONTRACT_VERSION,
|
|
74
|
+
generatedBy: PACKAGE_VERSION,
|
|
75
|
+
phase: PHASE,
|
|
76
|
+
status: 'ok',
|
|
77
|
+
policy: {
|
|
78
|
+
pulseCapabilitiesArePublicContract: true,
|
|
79
|
+
providersAreImplementationChoices: true,
|
|
80
|
+
wasiIsProviderNotAppApi: true,
|
|
81
|
+
noDirectWasiInHandlers: true,
|
|
82
|
+
noPlatformTargetIn11E: true,
|
|
83
|
+
effectRuntimeDeferredTo11F: true,
|
|
84
|
+
asyncIsExplicitEffectsNotLanguageAsync: true
|
|
85
|
+
},
|
|
86
|
+
requiredCapabilities,
|
|
87
|
+
allowedCapabilities: knownHostCapabilities(),
|
|
88
|
+
providerKinds: sortedUnique(PROVIDER_DEFINITIONS.map((provider) => provider.kind)),
|
|
89
|
+
diagnostics: []
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function buildWasiProviderMap(requiredCapabilities) {
|
|
94
|
+
const wasiCapabilities = CAPABILITY_DEFINITIONS
|
|
95
|
+
.filter((capability) => capability.provider?.kind === 'wasi-provider' || (capability.providerCandidates || []).some((candidate) => candidate.kind === 'wasi-provider'))
|
|
96
|
+
.map((capability) => ({
|
|
97
|
+
pulseCapability: capability.capability,
|
|
98
|
+
requiredByCurrentArtifacts: requiredCapabilities.includes(capability.capability),
|
|
99
|
+
status: capability.status,
|
|
100
|
+
primaryProvider: capability.provider,
|
|
101
|
+
fallbackProvider: capability.providerFallback,
|
|
102
|
+
candidates: capability.providerCandidates || [],
|
|
103
|
+
effectRuntimeRequired: Boolean(capability.effectRuntimeRequired),
|
|
104
|
+
publicAppApi: false,
|
|
105
|
+
notes: capability.notes
|
|
106
|
+
}));
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
version: WASI_PROVIDER_MAP_VERSION,
|
|
110
|
+
generatedBy: PACKAGE_VERSION,
|
|
111
|
+
phase: PHASE,
|
|
112
|
+
status: 'ok',
|
|
113
|
+
policy: {
|
|
114
|
+
wasiIsProviderNotHandlerApi: true,
|
|
115
|
+
pulseCapabilitiesWrapWasi: true,
|
|
116
|
+
clocksUseMonotonicForDeadlines: true,
|
|
117
|
+
wallClockIsNotDeadlineProvider: true,
|
|
118
|
+
wasiHttpIsCandidateOnly: true,
|
|
119
|
+
componentWiringDeferred: true,
|
|
120
|
+
noWitDefinedIn11E: true
|
|
121
|
+
},
|
|
122
|
+
summary: {
|
|
123
|
+
mappedPulseCapabilities: wasiCapabilities.length,
|
|
124
|
+
requiredMappedPulseCapabilities: wasiCapabilities.filter((entry) => entry.requiredByCurrentArtifacts).length,
|
|
125
|
+
wiredProviders: 0,
|
|
126
|
+
deferredProviders: wasiCapabilities.length
|
|
127
|
+
},
|
|
128
|
+
providers: PROVIDER_DEFINITIONS.filter((provider) => provider.kind.includes('wasi')),
|
|
129
|
+
mappings: wasiCapabilities
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function buildCapabilityProviderReport(requiredCapabilities, diagnostics) {
|
|
134
|
+
const capabilities = CAPABILITY_DEFINITIONS.map((capability) => ({
|
|
135
|
+
...capability,
|
|
136
|
+
requiredByCurrentArtifacts: requiredCapabilities.includes(capability.capability),
|
|
137
|
+
providerResolved: Boolean(capability.provider),
|
|
138
|
+
providerStatus: capability.provider ? capability.status : 'missing-provider'
|
|
139
|
+
}));
|
|
140
|
+
|
|
141
|
+
const required = capabilities.filter((capability) => capability.requiredByCurrentArtifacts);
|
|
142
|
+
const effectRequired = capabilities.filter((capability) => capability.effectRuntimeRequired);
|
|
143
|
+
const providerMapped = capabilities.filter((capability) => capability.providerResolved);
|
|
144
|
+
const wiredNow = capabilities.filter((capability) => ['implemented', 'implemented-proof', 'contract-implemented-lazy-text', 'contract-implemented-generic-default'].includes(capability.status));
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
version: CAPABILITY_PROVIDER_REPORT_VERSION,
|
|
148
|
+
generatedBy: PACKAGE_VERSION,
|
|
149
|
+
phase: PHASE,
|
|
150
|
+
status: diagnostics.length === 0 ? 'ok' : 'error',
|
|
151
|
+
summary: {
|
|
152
|
+
capabilities: capabilities.length,
|
|
153
|
+
requiredCapabilities: required.length,
|
|
154
|
+
providerMapped: providerMapped.length,
|
|
155
|
+
wiredNow: wiredNow.length,
|
|
156
|
+
effectRuntimeRequired: effectRequired.length,
|
|
157
|
+
diagnostics: diagnostics.length,
|
|
158
|
+
readyFor11F: diagnostics.length === 0,
|
|
159
|
+
readyForFastly: false
|
|
160
|
+
},
|
|
161
|
+
capabilities,
|
|
162
|
+
providers: PROVIDER_DEFINITIONS,
|
|
163
|
+
diagnostics
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function markdownForHostCapabilities(artifact, wasiProviderMap, report) {
|
|
168
|
+
const lines = [];
|
|
169
|
+
lines.push('# PulseWasm Phase 11E Host Capability / WASI Provider Mapping');
|
|
170
|
+
lines.push('');
|
|
171
|
+
lines.push('## Status');
|
|
172
|
+
lines.push('Locked as a contract/artifact phase. No runtime behavior, platform adapter, effect runtime, or WIT surface is implemented here.');
|
|
173
|
+
lines.push('');
|
|
174
|
+
lines.push('## Core Rule');
|
|
175
|
+
lines.push('Pulse capabilities are the public runtime contract. Providers, including WASI, are implementation choices beneath that contract.');
|
|
176
|
+
lines.push('');
|
|
177
|
+
lines.push('## Summary');
|
|
178
|
+
lines.push('');
|
|
179
|
+
lines.push(`- capabilities: ${artifact.summary.capabilities}`);
|
|
180
|
+
lines.push(`- required by current artifacts: ${artifact.summary.requiredCapabilities}`);
|
|
181
|
+
lines.push(`- WASI-mapped capabilities: ${wasiProviderMap.summary.mappedPulseCapabilities}`);
|
|
182
|
+
lines.push(`- effect-runtime-required capabilities: ${artifact.summary.effectRuntimeRequired}`);
|
|
183
|
+
lines.push(`- diagnostics: ${artifact.summary.diagnostics}`);
|
|
184
|
+
lines.push('');
|
|
185
|
+
lines.push('## Required Capabilities');
|
|
186
|
+
lines.push('');
|
|
187
|
+
for (const capability of report.capabilities.filter((entry) => entry.requiredByCurrentArtifacts)) {
|
|
188
|
+
lines.push(`- \`${capability.capability}\` — ${capability.status} via ${capability.provider?.name || '<missing>'}`);
|
|
189
|
+
}
|
|
190
|
+
lines.push('');
|
|
191
|
+
lines.push('## WASI Provider Map');
|
|
192
|
+
lines.push('');
|
|
193
|
+
for (const mapping of wasiProviderMap.mappings) {
|
|
194
|
+
lines.push(`- \`${mapping.pulseCapability}\`: ${mapping.primaryProvider?.name || 'candidate'} (${mapping.status})`);
|
|
195
|
+
}
|
|
196
|
+
lines.push('');
|
|
197
|
+
lines.push('## Non-goals');
|
|
198
|
+
lines.push('');
|
|
199
|
+
lines.push('- no WIT definition');
|
|
200
|
+
lines.push('- no platform adapter');
|
|
201
|
+
lines.push('- no effect runtime');
|
|
202
|
+
lines.push('- no language async');
|
|
203
|
+
lines.push('- no direct WASI app API');
|
|
204
|
+
lines.push('');
|
|
205
|
+
return `${lines.join('\n')}\n`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function buildHostCapabilities(inputs = {}) {
|
|
209
|
+
const cwd = inputs.cwd || process.cwd();
|
|
210
|
+
const diagnostics = [];
|
|
211
|
+
const generatedBy = inputs.generatedBy || PACKAGE_VERSION;
|
|
212
|
+
const requiredFromLibraries = capabilitiesFromLibraries(inputs.handlerLibraryContracts);
|
|
213
|
+
const requiredFromArtifacts = sortedUnique([
|
|
214
|
+
...requiredFromLibraries,
|
|
215
|
+
...(inputs.requestResultHeaders ? ['headers', 'result'] : []),
|
|
216
|
+
...(inputs.channelBroadcaster ? ['channel', 'broadcaster'] : []),
|
|
217
|
+
...(inputs.jsonBody ? ['json', 'body', 'result', 'headers'] : []),
|
|
218
|
+
...(inputs.backendCapabilities ? ['backend-fetch'] : []),
|
|
219
|
+
...(inputs.wasmHostAbi ? ['headers', 'result', 'params', 'state', 'error', 'lifecycle'] : [])
|
|
220
|
+
]);
|
|
221
|
+
|
|
222
|
+
const knownCapabilities = new Set(knownHostCapabilities());
|
|
223
|
+
for (const capability of requiredFromArtifacts) {
|
|
224
|
+
if (!isKnownHostCapability(capability)) {
|
|
225
|
+
diagnostics.push(makeDiagnostic(
|
|
226
|
+
'PULSEWASM_HOST_CAPABILITY_UNKNOWN',
|
|
227
|
+
`Unknown host capability ${JSON.stringify(capability)} was required by an artifact or library contract.`,
|
|
228
|
+
'Add the capability to the locked Phase 11E capability registry before relying on it.',
|
|
229
|
+
{ capability }
|
|
230
|
+
));
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const requiredCapabilities = requiredFromArtifacts.filter((capability) => knownCapabilities.has(capability));
|
|
235
|
+
const hostCapabilityContract = buildHostCapabilityContract(requiredCapabilities);
|
|
236
|
+
const wasiProviderMap = buildWasiProviderMap(requiredCapabilities);
|
|
237
|
+
const capabilityProviderReport = buildCapabilityProviderReport(requiredCapabilities, diagnostics);
|
|
238
|
+
const artifact = normalizeArtifact({
|
|
239
|
+
version: HOST_CAPABILITIES_VERSION,
|
|
240
|
+
generatedBy,
|
|
241
|
+
phase: PHASE,
|
|
242
|
+
status: diagnostics.length === 0 ? 'ok' : 'error',
|
|
243
|
+
scope: {
|
|
244
|
+
semanticsChanged: false,
|
|
245
|
+
runtimeBehaviorChanged: false,
|
|
246
|
+
wasiWired: false,
|
|
247
|
+
witDefined: false,
|
|
248
|
+
effectRuntimeImplemented: false,
|
|
249
|
+
platformAdapterImplemented: false
|
|
250
|
+
},
|
|
251
|
+
policy: {
|
|
252
|
+
pulseCapabilitiesArePublicSurface: true,
|
|
253
|
+
providersArePrivateImplementationChoices: true,
|
|
254
|
+
wasiIsProviderNotAppApi: true,
|
|
255
|
+
noDirectWasiInHandlers: true,
|
|
256
|
+
noPlatformTargetIn11E: true,
|
|
257
|
+
effectRuntimeDeferredTo11F: true,
|
|
258
|
+
asyncIsEffectsNotLanguageAsync: true,
|
|
259
|
+
clockUsesMonotonicForDeadlines: true,
|
|
260
|
+
wallClockReservedForTimestamps: true
|
|
261
|
+
},
|
|
262
|
+
summary: capabilityProviderReport.summary,
|
|
263
|
+
requiredCapabilities,
|
|
264
|
+
capabilities: capabilityProviderReport.capabilities,
|
|
265
|
+
providerMap: capabilityProviderReport.providers,
|
|
266
|
+
next: {
|
|
267
|
+
phase: '11F',
|
|
268
|
+
name: 'Effect Runtime Contract',
|
|
269
|
+
reason: 'Timer, ctx.fetch, and future body-read effects need explicit effect records/resume tokens; assets remain a host capability/payload streaming surface.'
|
|
270
|
+
},
|
|
271
|
+
diagnostics
|
|
272
|
+
}, cwd);
|
|
273
|
+
|
|
274
|
+
return {
|
|
275
|
+
artifact,
|
|
276
|
+
hostCapabilityContract: normalizeArtifact(hostCapabilityContract, cwd),
|
|
277
|
+
wasiProviderMap: normalizeArtifact(wasiProviderMap, cwd),
|
|
278
|
+
capabilityProviderReport: normalizeArtifact(capabilityProviderReport, cwd),
|
|
279
|
+
files: [
|
|
280
|
+
{
|
|
281
|
+
file: 'generated/host/host-capabilities.md',
|
|
282
|
+
text: markdownForHostCapabilities(artifact, wasiProviderMap, capabilityProviderReport)
|
|
283
|
+
}
|
|
284
|
+
],
|
|
285
|
+
diagnostics
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
module.exports = {
|
|
290
|
+
HOST_CAPABILITIES_VERSION,
|
|
291
|
+
WASI_PROVIDER_MAP_VERSION,
|
|
292
|
+
CAPABILITY_PROVIDER_REPORT_VERSION,
|
|
293
|
+
HOST_CAPABILITY_CONTRACT_VERSION,
|
|
294
|
+
CAPABILITY_DEFINITIONS,
|
|
295
|
+
PROVIDER_DEFINITIONS,
|
|
296
|
+
buildHostCapabilities
|
|
297
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const handlerLibraryContracts = require('./handler-library-contracts.js');
|
|
4
|
+
const librarySidecars = require('./library-sidecars.js');
|
|
5
|
+
const hostCapabilities = require('./host-capabilities.js');
|
|
6
|
+
const assetsLowering = require('./assets-lowering.js');
|
|
7
|
+
const packageLowering = require('./package-lowering.js');
|
|
8
|
+
const packageContracts = require('./package-contracts.js');
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
handlerLibraryContracts,
|
|
12
|
+
librarySidecars,
|
|
13
|
+
hostCapabilities,
|
|
14
|
+
assetsLowering,
|
|
15
|
+
packageLowering,
|
|
16
|
+
packageContracts,
|
|
17
|
+
buildHandlerLibraryContracts: handlerLibraryContracts.buildHandlerLibraryContracts,
|
|
18
|
+
discoverLowerableLibraryManifests: handlerLibraryContracts.discoverLowerableLibraryManifests,
|
|
19
|
+
resolveLowerableCompilerBuilder: handlerLibraryContracts.resolveLowerableCompilerBuilder,
|
|
20
|
+
loadLowerableCompilerBuilder: handlerLibraryContracts.loadLowerableCompilerBuilder,
|
|
21
|
+
resolveDefaultLibraryContracts: handlerLibraryContracts.resolveDefaultLibraryContracts,
|
|
22
|
+
buildLibrarySidecarConsumption: librarySidecars.buildLibrarySidecarConsumption,
|
|
23
|
+
buildHostCapabilities: hostCapabilities.buildHostCapabilities,
|
|
24
|
+
buildAssetsLoweringPlan: assetsLowering.buildAssetsLoweringPlan,
|
|
25
|
+
buildAssetsCompiledWasmSidecarPlan: assetsLowering.buildAssetsCompiledWasmSidecarPlan,
|
|
26
|
+
buildAssetsSidecarCompileLinkProof: assetsLowering.buildAssetsSidecarCompileLinkProof,
|
|
27
|
+
findLowerableManifestRecord: packageLowering.findLowerableManifestRecord,
|
|
28
|
+
buildPackageOwnedLoweringPlan: packageLowering.buildPackageOwnedLoweringPlan,
|
|
29
|
+
discoverPulsePackageContracts: packageContracts.discoverPulsePackageContracts
|
|
30
|
+
};
|