@earendil-works/chord 0.0.0
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 +205 -0
- package/dist/api.d.ts +15 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +72 -0
- package/dist/api.js.map +1 -0
- package/dist/bundler.d.ts +6 -0
- package/dist/bundler.d.ts.map +1 -0
- package/dist/bundler.js +3 -0
- package/dist/bundler.js.map +1 -0
- package/dist/context/index.d.ts +24 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +97 -0
- package/dist/context/index.js.map +1 -0
- package/dist/delta/index.d.ts +119 -0
- package/dist/delta/index.d.ts.map +1 -0
- package/dist/delta/index.js +1213 -0
- package/dist/delta/index.js.map +1 -0
- package/dist/facets/host.d.ts +12 -0
- package/dist/facets/host.d.ts.map +1 -0
- package/dist/facets/host.js +763 -0
- package/dist/facets/host.js.map +1 -0
- package/dist/facets/loader.d.ts +3 -0
- package/dist/facets/loader.d.ts.map +1 -0
- package/dist/facets/loader.js +5 -0
- package/dist/facets/loader.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +4 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +57 -0
- package/dist/json.js.map +1 -0
- package/dist/node/bundle-loader.d.ts +30 -0
- package/dist/node/bundle-loader.d.ts.map +1 -0
- package/dist/node/bundle-loader.js +377 -0
- package/dist/node/bundle-loader.js.map +1 -0
- package/dist/node/bundle.d.ts +26 -0
- package/dist/node/bundle.d.ts.map +1 -0
- package/dist/node/bundle.js +183 -0
- package/dist/node/bundle.js.map +1 -0
- package/dist/node/manifest.d.ts +36 -0
- package/dist/node/manifest.d.ts.map +1 -0
- package/dist/node/manifest.js +6 -0
- package/dist/node/manifest.js.map +1 -0
- package/dist/node/package.d.ts +15 -0
- package/dist/node/package.d.ts.map +1 -0
- package/dist/node/package.js +199 -0
- package/dist/node/package.js.map +1 -0
- package/dist/node.d.ts +5 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +3 -0
- package/dist/node.js.map +1 -0
- package/dist/services/consumer.d.ts +11 -0
- package/dist/services/consumer.d.ts.map +1 -0
- package/dist/services/consumer.js +537 -0
- package/dist/services/consumer.js.map +1 -0
- package/dist/services/errors.d.ts +8 -0
- package/dist/services/errors.d.ts.map +1 -0
- package/dist/services/errors.js +22 -0
- package/dist/services/errors.js.map +1 -0
- package/dist/services/handle.d.ts +15 -0
- package/dist/services/handle.d.ts.map +1 -0
- package/dist/services/handle.js +99 -0
- package/dist/services/handle.js.map +1 -0
- package/dist/services/instances.d.ts +25 -0
- package/dist/services/instances.d.ts.map +1 -0
- package/dist/services/instances.js +137 -0
- package/dist/services/instances.js.map +1 -0
- package/dist/services/loopback.d.ts +5 -0
- package/dist/services/loopback.d.ts.map +1 -0
- package/dist/services/loopback.js +15 -0
- package/dist/services/loopback.js.map +1 -0
- package/dist/services/provider.d.ts +37 -0
- package/dist/services/provider.d.ts.map +1 -0
- package/dist/services/provider.js +472 -0
- package/dist/services/provider.js.map +1 -0
- package/dist/services/state-codec.d.ts +15 -0
- package/dist/services/state-codec.d.ts.map +1 -0
- package/dist/services/state-codec.js +115 -0
- package/dist/services/state-codec.js.map +1 -0
- package/dist/services/state-internals.d.ts +11 -0
- package/dist/services/state-internals.d.ts.map +1 -0
- package/dist/services/state-internals.js +10 -0
- package/dist/services/state-internals.js.map +1 -0
- package/dist/services/state.d.ts +23 -0
- package/dist/services/state.d.ts.map +1 -0
- package/dist/services/state.js +124 -0
- package/dist/services/state.js.map +1 -0
- package/dist/services/wire.d.ts +60 -0
- package/dist/services/wire.d.ts.map +1 -0
- package/dist/services/wire.js +173 -0
- package/dist/services/wire.js.map +1 -0
- package/dist/types.d.ts +203 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { createRequire, isBuiltin } from "node:module";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { compileFunction } from "node:vm";
|
|
8
|
+
import { FACET_BUNDLE_ARTIFACT_FORMAT, FACET_BUNDLE_ARTIFACT_FORMAT_VERSION, FACET_BUNDLE_FORMAT, FACET_BUNDLE_FORMAT_VERSION, FACET_BUNDLE_MANIFEST_FILE, } from "./manifest.js";
|
|
9
|
+
/** Read and validate a versioned facet bundle manifest. */
|
|
10
|
+
export async function readFacetBundleManifest(path) {
|
|
11
|
+
const manifestPath = toFilePath(path);
|
|
12
|
+
let parsed;
|
|
13
|
+
try {
|
|
14
|
+
parsed = JSON.parse(await readFile(manifestPath, "utf8"));
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
throw new Error(`Could not read facet bundle manifest ${manifestPath}`, { cause: error });
|
|
18
|
+
}
|
|
19
|
+
return validateManifest(parsed, manifestPath);
|
|
20
|
+
}
|
|
21
|
+
/** Read and verify one transportable entry from a facet bundle on disk. */
|
|
22
|
+
export async function readFacetBundleArtifact(options) {
|
|
23
|
+
if (options.entry.length === 0)
|
|
24
|
+
throw new TypeError("Facet bundle entry name must not be empty");
|
|
25
|
+
const manifestPath = toFilePath(options.manifestPath);
|
|
26
|
+
const manifest = await readFacetBundleManifest(manifestPath);
|
|
27
|
+
const entry = manifest.entries[options.entry];
|
|
28
|
+
if (entry === undefined)
|
|
29
|
+
throw new Error(`Facet bundle ${manifest.plugin.id} has no entry named ${options.entry}`);
|
|
30
|
+
const modulePath = resolveBundleFile(manifestPath, entry.file, "entry");
|
|
31
|
+
const source = await readFile(modulePath, "utf8");
|
|
32
|
+
verifySource(source, entry);
|
|
33
|
+
const sourceMapContents = entry.sourceMap === undefined
|
|
34
|
+
? undefined
|
|
35
|
+
: await readFile(resolveBundleFile(manifestPath, entry.sourceMap, "source map"), "utf8");
|
|
36
|
+
return Object.freeze({
|
|
37
|
+
format: FACET_BUNDLE_ARTIFACT_FORMAT,
|
|
38
|
+
formatVersion: FACET_BUNDLE_ARTIFACT_FORMAT_VERSION,
|
|
39
|
+
plugin: manifest.plugin,
|
|
40
|
+
entryName: options.entry,
|
|
41
|
+
entry,
|
|
42
|
+
source,
|
|
43
|
+
...(sourceMapContents === undefined ? {} : { sourceMapContents }),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/** Materialize a transported artifact and create a fresh VM-compiled CommonJS generation for each load. */
|
|
47
|
+
export function createFacetBundleArtifactLoader(options) {
|
|
48
|
+
const artifact = validateArtifact(options.artifact);
|
|
49
|
+
const temporaryParent = resolve(options.temporaryDirectory ?? tmpdir());
|
|
50
|
+
return {
|
|
51
|
+
async load() {
|
|
52
|
+
await mkdir(temporaryParent, { recursive: true });
|
|
53
|
+
const directory = await mkdtemp(join(temporaryParent, "chord-facet-"));
|
|
54
|
+
try {
|
|
55
|
+
await materializeArtifact(directory, artifact);
|
|
56
|
+
const loaded = await createFacetBundleLoader({
|
|
57
|
+
manifestPath: join(directory, FACET_BUNDLE_MANIFEST_FILE),
|
|
58
|
+
entry: artifact.entryName,
|
|
59
|
+
resolveExternal: options.resolveExternal,
|
|
60
|
+
}).load();
|
|
61
|
+
let disposed = false;
|
|
62
|
+
return {
|
|
63
|
+
get facets() {
|
|
64
|
+
return loaded.facets;
|
|
65
|
+
},
|
|
66
|
+
async dispose() {
|
|
67
|
+
if (disposed)
|
|
68
|
+
return;
|
|
69
|
+
disposed = true;
|
|
70
|
+
const errors = [];
|
|
71
|
+
try {
|
|
72
|
+
await loaded.dispose();
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
errors.push(error);
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
await rm(directory, { force: true, recursive: true });
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
errors.push(error);
|
|
82
|
+
}
|
|
83
|
+
if (errors.length === 1)
|
|
84
|
+
throw errors[0];
|
|
85
|
+
if (errors.length > 1)
|
|
86
|
+
throw new AggregateError(errors, "Failed to dispose facet bundle artifact");
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
try {
|
|
92
|
+
await rm(directory, { force: true, recursive: true });
|
|
93
|
+
}
|
|
94
|
+
catch (cleanupError) {
|
|
95
|
+
throw new AggregateError([error, cleanupError], "Facet bundle artifact loading and cleanup failed");
|
|
96
|
+
}
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** Create a reusable loader for one opaque entry in a facet bundle manifest. */
|
|
103
|
+
export function createFacetBundleLoader(options) {
|
|
104
|
+
if (options.entry.length === 0)
|
|
105
|
+
throw new TypeError("Facet bundle entry name must not be empty");
|
|
106
|
+
const manifestPath = toFilePath(options.manifestPath);
|
|
107
|
+
return {
|
|
108
|
+
async load() {
|
|
109
|
+
const manifest = await readFacetBundleManifest(manifestPath);
|
|
110
|
+
const entry = manifest.entries[options.entry];
|
|
111
|
+
if (entry === undefined) {
|
|
112
|
+
throw new Error(`Facet bundle ${manifest.plugin.id} has no entry named ${options.entry}`);
|
|
113
|
+
}
|
|
114
|
+
const modulePath = resolveBundleFile(manifestPath, entry.file, "entry");
|
|
115
|
+
try {
|
|
116
|
+
const source = await readFile(modulePath, "utf8");
|
|
117
|
+
if (options.verifyIntegrity !== false)
|
|
118
|
+
verifySource(source, entry);
|
|
119
|
+
const exported = executeCommonJsModule(source, modulePath, entry.externalImports, options.resolveExternal);
|
|
120
|
+
let facets = facetsFromModule(exported, manifest.plugin.id, options.entry);
|
|
121
|
+
let disposed = false;
|
|
122
|
+
return {
|
|
123
|
+
get facets() {
|
|
124
|
+
return facets;
|
|
125
|
+
},
|
|
126
|
+
async dispose() {
|
|
127
|
+
if (disposed)
|
|
128
|
+
return;
|
|
129
|
+
disposed = true;
|
|
130
|
+
facets = Object.freeze([]);
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
const detail = error instanceof Error ? `: ${error.message}` : "";
|
|
136
|
+
throw new Error(`Could not load facet bundle entry ${manifest.plugin.id}/${options.entry}${detail}`, {
|
|
137
|
+
cause: error,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function executeCommonJsModule(source, modulePath, externalImports, resolver) {
|
|
144
|
+
const requireFromModule = createRequire(modulePath);
|
|
145
|
+
const externalTargets = new Map();
|
|
146
|
+
for (const specifier of externalImports) {
|
|
147
|
+
if (!isBuiltin(specifier))
|
|
148
|
+
validatePackageSpecifier(specifier);
|
|
149
|
+
externalTargets.set(specifier, toRequireSpecifier(resolveExternalTarget(specifier, resolver)));
|
|
150
|
+
}
|
|
151
|
+
const targetFor = (specifier) => {
|
|
152
|
+
const target = externalTargets.get(specifier);
|
|
153
|
+
if (target === undefined)
|
|
154
|
+
throw new Error(`Facet bundle required undeclared external import: ${specifier}`);
|
|
155
|
+
return target;
|
|
156
|
+
};
|
|
157
|
+
const requireExternal = Object.assign((specifier) => requireFromModule(targetFor(specifier)), {
|
|
158
|
+
resolve: (specifier) => requireFromModule.resolve(targetFor(specifier)),
|
|
159
|
+
});
|
|
160
|
+
const commonJsModule = { exports: Object.create(null) };
|
|
161
|
+
const compiled = compileFunction(source, ["exports", "require", "module", "__filename", "__dirname"], {
|
|
162
|
+
filename: modulePath,
|
|
163
|
+
});
|
|
164
|
+
Reflect.apply(compiled, commonJsModule.exports, [
|
|
165
|
+
commonJsModule.exports,
|
|
166
|
+
requireExternal,
|
|
167
|
+
commonJsModule,
|
|
168
|
+
modulePath,
|
|
169
|
+
dirname(modulePath),
|
|
170
|
+
]);
|
|
171
|
+
return commonJsModule.exports;
|
|
172
|
+
}
|
|
173
|
+
function toRequireSpecifier(target) {
|
|
174
|
+
if (isAbsolute(target) || isBuiltin(target))
|
|
175
|
+
return target;
|
|
176
|
+
let url;
|
|
177
|
+
try {
|
|
178
|
+
url = new URL(target);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return target;
|
|
182
|
+
}
|
|
183
|
+
if (url.protocol === "file:")
|
|
184
|
+
return fileURLToPath(url);
|
|
185
|
+
if (url.protocol === "node:")
|
|
186
|
+
return url.href;
|
|
187
|
+
throw new Error(`Facet bundle external target must be a file, package, or built-in module: ${target}`);
|
|
188
|
+
}
|
|
189
|
+
function toFilePath(path) {
|
|
190
|
+
if (typeof path === "string")
|
|
191
|
+
return resolve(path);
|
|
192
|
+
if (path.protocol !== "file:")
|
|
193
|
+
throw new TypeError(`Facet bundle manifest must be a file URL, not ${path.protocol}`);
|
|
194
|
+
return fileURLToPath(path);
|
|
195
|
+
}
|
|
196
|
+
function resolveBundleFile(manifestPath, file, label) {
|
|
197
|
+
if (file.length === 0 || isAbsolute(file) || basename(file) !== file || file === "." || file === "..") {
|
|
198
|
+
throw new Error(`Facet bundle ${label} must be a filename relative to its manifest`);
|
|
199
|
+
}
|
|
200
|
+
return resolve(dirname(manifestPath), file);
|
|
201
|
+
}
|
|
202
|
+
function verifySource(source, entry) {
|
|
203
|
+
const expected = parseIntegrity(entry.integrity);
|
|
204
|
+
const actual = createHash("sha256").update(source, "utf8").digest("base64");
|
|
205
|
+
if (actual !== expected)
|
|
206
|
+
throw new Error(`Facet bundle integrity check failed for ${entry.file}`);
|
|
207
|
+
}
|
|
208
|
+
function parseIntegrity(integrity) {
|
|
209
|
+
const prefix = "sha256-";
|
|
210
|
+
if (!integrity.startsWith(prefix) || integrity.length === prefix.length) {
|
|
211
|
+
throw new Error("Facet bundle entry has an invalid SHA-256 integrity value");
|
|
212
|
+
}
|
|
213
|
+
return integrity.slice(prefix.length);
|
|
214
|
+
}
|
|
215
|
+
function facetsFromModule(imported, pluginId, entryName) {
|
|
216
|
+
if (!isRecord(imported))
|
|
217
|
+
throw new Error(`Facet bundle entry ${pluginId}/${entryName} did not export a module`);
|
|
218
|
+
const exported = imported.default;
|
|
219
|
+
const candidates = Array.isArray(exported) ? exported : [exported];
|
|
220
|
+
if (candidates.length === 0) {
|
|
221
|
+
throw new Error(`Facet bundle entry ${pluginId}/${entryName} exported no facets`);
|
|
222
|
+
}
|
|
223
|
+
const facets = [];
|
|
224
|
+
for (const candidate of candidates) {
|
|
225
|
+
if (!isRecord(candidate) || typeof candidate.id !== "string" || candidate.id.length === 0) {
|
|
226
|
+
throw new Error(`Facet bundle entry ${pluginId}/${entryName} has a facet with an invalid ID`);
|
|
227
|
+
}
|
|
228
|
+
if (typeof candidate.setup !== "function") {
|
|
229
|
+
throw new Error(`Facet bundle entry ${pluginId}/${entryName} facet ${candidate.id} has no setup function`);
|
|
230
|
+
}
|
|
231
|
+
facets.push(candidate);
|
|
232
|
+
}
|
|
233
|
+
const ids = facets.map(({ id }) => id);
|
|
234
|
+
if (new Set(ids).size !== ids.length) {
|
|
235
|
+
throw new Error(`Facet bundle entry ${pluginId}/${entryName} exports duplicate facet IDs`);
|
|
236
|
+
}
|
|
237
|
+
return Object.freeze(facets);
|
|
238
|
+
}
|
|
239
|
+
function validateArtifact(value) {
|
|
240
|
+
if (!isRecord(value) ||
|
|
241
|
+
value.format !== FACET_BUNDLE_ARTIFACT_FORMAT ||
|
|
242
|
+
value.formatVersion !== FACET_BUNDLE_ARTIFACT_FORMAT_VERSION ||
|
|
243
|
+
typeof value.entryName !== "string" ||
|
|
244
|
+
value.entryName.length === 0 ||
|
|
245
|
+
typeof value.source !== "string") {
|
|
246
|
+
throw new Error("Invalid facet bundle artifact");
|
|
247
|
+
}
|
|
248
|
+
const manifest = validateManifest({
|
|
249
|
+
format: FACET_BUNDLE_FORMAT,
|
|
250
|
+
formatVersion: FACET_BUNDLE_FORMAT_VERSION,
|
|
251
|
+
plugin: value.plugin,
|
|
252
|
+
entries: { [value.entryName]: value.entry },
|
|
253
|
+
}, "facet bundle artifact");
|
|
254
|
+
const entry = manifest.entries[value.entryName];
|
|
255
|
+
if (entry.sourceMap === undefined) {
|
|
256
|
+
if (value.sourceMapContents !== undefined) {
|
|
257
|
+
throw new Error("Facet bundle artifact has source map contents without a source map");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
else if (typeof value.sourceMapContents !== "string") {
|
|
261
|
+
throw new Error("Facet bundle artifact is missing its source map contents");
|
|
262
|
+
}
|
|
263
|
+
verifySource(value.source, entry);
|
|
264
|
+
return Object.freeze({
|
|
265
|
+
format: FACET_BUNDLE_ARTIFACT_FORMAT,
|
|
266
|
+
formatVersion: FACET_BUNDLE_ARTIFACT_FORMAT_VERSION,
|
|
267
|
+
plugin: manifest.plugin,
|
|
268
|
+
entryName: value.entryName,
|
|
269
|
+
entry,
|
|
270
|
+
source: value.source,
|
|
271
|
+
...(value.sourceMapContents === undefined ? {} : { sourceMapContents: value.sourceMapContents }),
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
async function materializeArtifact(directory, artifact) {
|
|
275
|
+
const manifest = {
|
|
276
|
+
format: FACET_BUNDLE_FORMAT,
|
|
277
|
+
formatVersion: FACET_BUNDLE_FORMAT_VERSION,
|
|
278
|
+
plugin: artifact.plugin,
|
|
279
|
+
entries: { [artifact.entryName]: artifact.entry },
|
|
280
|
+
};
|
|
281
|
+
await Promise.all([
|
|
282
|
+
writeFile(join(directory, artifact.entry.file), artifact.source, "utf8"),
|
|
283
|
+
writeFile(join(directory, FACET_BUNDLE_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\n`, "utf8"),
|
|
284
|
+
...(artifact.entry.sourceMap === undefined
|
|
285
|
+
? []
|
|
286
|
+
: [writeFile(join(directory, artifact.entry.sourceMap), artifact.sourceMapContents, "utf8")]),
|
|
287
|
+
]);
|
|
288
|
+
}
|
|
289
|
+
function resolveExternalTarget(specifier, resolver) {
|
|
290
|
+
const resolved = resolver?.(specifier);
|
|
291
|
+
if (resolved !== undefined)
|
|
292
|
+
return typeof resolved === "string" ? resolved : resolved.href;
|
|
293
|
+
const extension = import.meta.url.endsWith(".ts") ? "ts" : "js";
|
|
294
|
+
if (specifier === "@earendil-works/chord")
|
|
295
|
+
return new URL(`../index.${extension}`, import.meta.url).href;
|
|
296
|
+
if (specifier === "@earendil-works/chord/context") {
|
|
297
|
+
return new URL(`../context/index.${extension}`, import.meta.url).href;
|
|
298
|
+
}
|
|
299
|
+
if (specifier === "@earendil-works/chord/node")
|
|
300
|
+
return new URL(`../node.${extension}`, import.meta.url).href;
|
|
301
|
+
return import.meta.resolve(specifier);
|
|
302
|
+
}
|
|
303
|
+
function validatePackageSpecifier(specifier) {
|
|
304
|
+
const segments = specifier.split("/");
|
|
305
|
+
const packageParts = specifier.startsWith("@") ? 2 : 1;
|
|
306
|
+
if (specifier.startsWith(".") ||
|
|
307
|
+
specifier.startsWith("/") ||
|
|
308
|
+
specifier.startsWith("#") ||
|
|
309
|
+
specifier.includes(":") ||
|
|
310
|
+
specifier.includes("\\") ||
|
|
311
|
+
segments.length < packageParts ||
|
|
312
|
+
segments.some((part) => part.length === 0 || part === "." || part === "..")) {
|
|
313
|
+
throw new Error(`Facet bundle artifact has an unsupported external import: ${specifier}`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function validateManifest(value, path) {
|
|
317
|
+
if (!isRecord(value) || value.format !== FACET_BUNDLE_FORMAT) {
|
|
318
|
+
throw new Error(`Invalid facet bundle manifest format in ${path}`);
|
|
319
|
+
}
|
|
320
|
+
if (value.formatVersion !== FACET_BUNDLE_FORMAT_VERSION) {
|
|
321
|
+
throw new Error(`Unsupported facet bundle manifest version in ${path}: ${String(value.formatVersion)}`);
|
|
322
|
+
}
|
|
323
|
+
if (!isRecord(value.plugin) || typeof value.plugin.id !== "string" || value.plugin.id.length === 0) {
|
|
324
|
+
throw new Error(`Facet bundle manifest has an invalid plugin identity in ${path}`);
|
|
325
|
+
}
|
|
326
|
+
if (value.plugin.version !== undefined &&
|
|
327
|
+
(typeof value.plugin.version !== "string" || value.plugin.version.length === 0)) {
|
|
328
|
+
throw new Error(`Facet bundle manifest has an invalid plugin version in ${path}`);
|
|
329
|
+
}
|
|
330
|
+
if (!isRecord(value.entries) || Object.keys(value.entries).length === 0) {
|
|
331
|
+
throw new Error(`Facet bundle manifest has no entries in ${path}`);
|
|
332
|
+
}
|
|
333
|
+
const entries = {};
|
|
334
|
+
for (const [name, candidate] of Object.entries(value.entries)) {
|
|
335
|
+
if (name.length === 0 || !isRecord(candidate)) {
|
|
336
|
+
throw new Error(`Facet bundle manifest has an invalid entry in ${path}`);
|
|
337
|
+
}
|
|
338
|
+
if (typeof candidate.file !== "string")
|
|
339
|
+
throw new Error(`Facet bundle entry ${name} has no file`);
|
|
340
|
+
resolveBundleFile(path, candidate.file, `entry ${name}`);
|
|
341
|
+
if (typeof candidate.integrity !== "string")
|
|
342
|
+
throw new Error(`Facet bundle entry ${name} has no integrity`);
|
|
343
|
+
parseIntegrity(candidate.integrity);
|
|
344
|
+
if (!Array.isArray(candidate.externalImports) ||
|
|
345
|
+
candidate.externalImports.some((item) => typeof item !== "string")) {
|
|
346
|
+
throw new Error(`Facet bundle entry ${name} has invalid external imports`);
|
|
347
|
+
}
|
|
348
|
+
const externalImports = Object.freeze([...candidate.externalImports]);
|
|
349
|
+
if (new Set(externalImports).size !== externalImports.length) {
|
|
350
|
+
throw new Error(`Facet bundle entry ${name} has duplicate external imports`);
|
|
351
|
+
}
|
|
352
|
+
if (candidate.sourceMap !== undefined) {
|
|
353
|
+
if (typeof candidate.sourceMap !== "string")
|
|
354
|
+
throw new Error(`Facet bundle entry ${name} has an invalid source map`);
|
|
355
|
+
resolveBundleFile(path, candidate.sourceMap, `entry ${name} source map`);
|
|
356
|
+
}
|
|
357
|
+
entries[name] = Object.freeze({
|
|
358
|
+
file: candidate.file,
|
|
359
|
+
integrity: candidate.integrity,
|
|
360
|
+
externalImports,
|
|
361
|
+
...(candidate.sourceMap === undefined ? {} : { sourceMap: candidate.sourceMap }),
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
return Object.freeze({
|
|
365
|
+
format: FACET_BUNDLE_FORMAT,
|
|
366
|
+
formatVersion: FACET_BUNDLE_FORMAT_VERSION,
|
|
367
|
+
plugin: Object.freeze({
|
|
368
|
+
id: value.plugin.id,
|
|
369
|
+
...(value.plugin.version === undefined ? {} : { version: value.plugin.version }),
|
|
370
|
+
}),
|
|
371
|
+
entries: Object.freeze(entries),
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
function isRecord(value) {
|
|
375
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
376
|
+
}
|
|
377
|
+
//# sourceMappingURL=bundle-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle-loader.js","sourceRoot":"","sources":["../../src/node/bundle-loader.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { mkdir, mkdtemp, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { createRequire, isBuiltin } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { basename, dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { compileFunction } from \"node:vm\";\nimport type { Facet, FacetLoader, LoadedFacets } from \"../types.ts\";\nimport {\n\tFACET_BUNDLE_ARTIFACT_FORMAT,\n\tFACET_BUNDLE_ARTIFACT_FORMAT_VERSION,\n\tFACET_BUNDLE_FORMAT,\n\tFACET_BUNDLE_FORMAT_VERSION,\n\tFACET_BUNDLE_MANIFEST_FILE,\n\ttype FacetBundleArtifact,\n\ttype FacetBundleEntry,\n\ttype FacetBundleManifest,\n} from \"./manifest.ts\";\n\nexport type FacetBundleExternalResolver = (specifier: string) => string | URL | undefined;\n\nexport interface FacetBundleLoaderOptions {\n\treadonly manifestPath: string | URL;\n\treadonly entry: string;\n\t/** Verify the entry's SHA-256 integrity before evaluating it. Defaults to true. */\n\treadonly verifyIntegrity?: boolean;\n\t/** Resolve host-provided external imports when the bundle is outside the host's package tree. */\n\treadonly resolveExternal?: FacetBundleExternalResolver;\n}\n\nexport interface FacetBundleArtifactLoaderOptions {\n\treadonly artifact: unknown;\n\t/** Resolve host-provided external imports against the receiving application. */\n\treadonly resolveExternal?: FacetBundleExternalResolver;\n\t/** Parent directory for materialized module generations. Defaults to the operating system temp directory. */\n\treadonly temporaryDirectory?: string;\n}\n\ninterface CommonJsModule {\n\texports: unknown;\n}\n\n/** Read and validate a versioned facet bundle manifest. */\nexport async function readFacetBundleManifest(path: string | URL): Promise<FacetBundleManifest> {\n\tconst manifestPath = toFilePath(path);\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(await readFile(manifestPath, \"utf8\"));\n\t} catch (error) {\n\t\tthrow new Error(`Could not read facet bundle manifest ${manifestPath}`, { cause: error });\n\t}\n\treturn validateManifest(parsed, manifestPath);\n}\n\n/** Read and verify one transportable entry from a facet bundle on disk. */\nexport async function readFacetBundleArtifact(options: {\n\treadonly manifestPath: string | URL;\n\treadonly entry: string;\n}): Promise<FacetBundleArtifact> {\n\tif (options.entry.length === 0) throw new TypeError(\"Facet bundle entry name must not be empty\");\n\tconst manifestPath = toFilePath(options.manifestPath);\n\tconst manifest = await readFacetBundleManifest(manifestPath);\n\tconst entry = manifest.entries[options.entry];\n\tif (entry === undefined) throw new Error(`Facet bundle ${manifest.plugin.id} has no entry named ${options.entry}`);\n\tconst modulePath = resolveBundleFile(manifestPath, entry.file, \"entry\");\n\tconst source = await readFile(modulePath, \"utf8\");\n\tverifySource(source, entry);\n\tconst sourceMapContents =\n\t\tentry.sourceMap === undefined\n\t\t\t? undefined\n\t\t\t: await readFile(resolveBundleFile(manifestPath, entry.sourceMap, \"source map\"), \"utf8\");\n\treturn Object.freeze({\n\t\tformat: FACET_BUNDLE_ARTIFACT_FORMAT,\n\t\tformatVersion: FACET_BUNDLE_ARTIFACT_FORMAT_VERSION,\n\t\tplugin: manifest.plugin,\n\t\tentryName: options.entry,\n\t\tentry,\n\t\tsource,\n\t\t...(sourceMapContents === undefined ? {} : { sourceMapContents }),\n\t});\n}\n\n/** Materialize a transported artifact and create a fresh VM-compiled CommonJS generation for each load. */\nexport function createFacetBundleArtifactLoader(options: FacetBundleArtifactLoaderOptions): FacetLoader {\n\tconst artifact = validateArtifact(options.artifact);\n\tconst temporaryParent = resolve(options.temporaryDirectory ?? tmpdir());\n\treturn {\n\t\tasync load(): Promise<LoadedFacets> {\n\t\t\tawait mkdir(temporaryParent, { recursive: true });\n\t\t\tconst directory = await mkdtemp(join(temporaryParent, \"chord-facet-\"));\n\t\t\ttry {\n\t\t\t\tawait materializeArtifact(directory, artifact);\n\t\t\t\tconst loaded = await createFacetBundleLoader({\n\t\t\t\t\tmanifestPath: join(directory, FACET_BUNDLE_MANIFEST_FILE),\n\t\t\t\t\tentry: artifact.entryName,\n\t\t\t\t\tresolveExternal: options.resolveExternal,\n\t\t\t\t}).load();\n\t\t\t\tlet disposed = false;\n\t\t\t\treturn {\n\t\t\t\t\tget facets() {\n\t\t\t\t\t\treturn loaded.facets;\n\t\t\t\t\t},\n\t\t\t\t\tasync dispose() {\n\t\t\t\t\t\tif (disposed) return;\n\t\t\t\t\t\tdisposed = true;\n\t\t\t\t\t\tconst errors: unknown[] = [];\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait loaded.dispose();\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\terrors.push(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait rm(directory, { force: true, recursive: true });\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\terrors.push(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (errors.length === 1) throw errors[0];\n\t\t\t\t\t\tif (errors.length > 1) throw new AggregateError(errors, \"Failed to dispose facet bundle artifact\");\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\ttry {\n\t\t\t\t\tawait rm(directory, { force: true, recursive: true });\n\t\t\t\t} catch (cleanupError) {\n\t\t\t\t\tthrow new AggregateError([error, cleanupError], \"Facet bundle artifact loading and cleanup failed\");\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t};\n}\n\n/** Create a reusable loader for one opaque entry in a facet bundle manifest. */\nexport function createFacetBundleLoader(options: FacetBundleLoaderOptions): FacetLoader {\n\tif (options.entry.length === 0) throw new TypeError(\"Facet bundle entry name must not be empty\");\n\tconst manifestPath = toFilePath(options.manifestPath);\n\treturn {\n\t\tasync load(): Promise<LoadedFacets> {\n\t\t\tconst manifest = await readFacetBundleManifest(manifestPath);\n\t\t\tconst entry = manifest.entries[options.entry];\n\t\t\tif (entry === undefined) {\n\t\t\t\tthrow new Error(`Facet bundle ${manifest.plugin.id} has no entry named ${options.entry}`);\n\t\t\t}\n\t\t\tconst modulePath = resolveBundleFile(manifestPath, entry.file, \"entry\");\n\t\t\ttry {\n\t\t\t\tconst source = await readFile(modulePath, \"utf8\");\n\t\t\t\tif (options.verifyIntegrity !== false) verifySource(source, entry);\n\t\t\t\tconst exported = executeCommonJsModule(source, modulePath, entry.externalImports, options.resolveExternal);\n\t\t\t\tlet facets = facetsFromModule(exported, manifest.plugin.id, options.entry);\n\t\t\t\tlet disposed = false;\n\t\t\t\treturn {\n\t\t\t\t\tget facets() {\n\t\t\t\t\t\treturn facets;\n\t\t\t\t\t},\n\t\t\t\t\tasync dispose() {\n\t\t\t\t\t\tif (disposed) return;\n\t\t\t\t\t\tdisposed = true;\n\t\t\t\t\t\tfacets = Object.freeze([]);\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tconst detail = error instanceof Error ? `: ${error.message}` : \"\";\n\t\t\t\tthrow new Error(`Could not load facet bundle entry ${manifest.plugin.id}/${options.entry}${detail}`, {\n\t\t\t\t\tcause: error,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction executeCommonJsModule(\n\tsource: string,\n\tmodulePath: string,\n\texternalImports: readonly string[],\n\tresolver?: FacetBundleExternalResolver,\n): unknown {\n\tconst requireFromModule = createRequire(modulePath);\n\tconst externalTargets = new Map<string, string>();\n\tfor (const specifier of externalImports) {\n\t\tif (!isBuiltin(specifier)) validatePackageSpecifier(specifier);\n\t\texternalTargets.set(specifier, toRequireSpecifier(resolveExternalTarget(specifier, resolver)));\n\t}\n\tconst targetFor = (specifier: string): string => {\n\t\tconst target = externalTargets.get(specifier);\n\t\tif (target === undefined) throw new Error(`Facet bundle required undeclared external import: ${specifier}`);\n\t\treturn target;\n\t};\n\tconst requireExternal = Object.assign((specifier: string): unknown => requireFromModule(targetFor(specifier)), {\n\t\tresolve: (specifier: string): string => requireFromModule.resolve(targetFor(specifier)),\n\t});\n\tconst commonJsModule: CommonJsModule = { exports: Object.create(null) };\n\tconst compiled = compileFunction(source, [\"exports\", \"require\", \"module\", \"__filename\", \"__dirname\"], {\n\t\tfilename: modulePath,\n\t});\n\tReflect.apply(compiled, commonJsModule.exports, [\n\t\tcommonJsModule.exports,\n\t\trequireExternal,\n\t\tcommonJsModule,\n\t\tmodulePath,\n\t\tdirname(modulePath),\n\t]);\n\treturn commonJsModule.exports;\n}\n\nfunction toRequireSpecifier(target: string): string {\n\tif (isAbsolute(target) || isBuiltin(target)) return target;\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(target);\n\t} catch {\n\t\treturn target;\n\t}\n\tif (url.protocol === \"file:\") return fileURLToPath(url);\n\tif (url.protocol === \"node:\") return url.href;\n\tthrow new Error(`Facet bundle external target must be a file, package, or built-in module: ${target}`);\n}\n\nfunction toFilePath(path: string | URL): string {\n\tif (typeof path === \"string\") return resolve(path);\n\tif (path.protocol !== \"file:\") throw new TypeError(`Facet bundle manifest must be a file URL, not ${path.protocol}`);\n\treturn fileURLToPath(path);\n}\n\nfunction resolveBundleFile(manifestPath: string, file: string, label: string): string {\n\tif (file.length === 0 || isAbsolute(file) || basename(file) !== file || file === \".\" || file === \"..\") {\n\t\tthrow new Error(`Facet bundle ${label} must be a filename relative to its manifest`);\n\t}\n\treturn resolve(dirname(manifestPath), file);\n}\n\nfunction verifySource(source: string, entry: FacetBundleEntry): void {\n\tconst expected = parseIntegrity(entry.integrity);\n\tconst actual = createHash(\"sha256\").update(source, \"utf8\").digest(\"base64\");\n\tif (actual !== expected) throw new Error(`Facet bundle integrity check failed for ${entry.file}`);\n}\n\nfunction parseIntegrity(integrity: string): string {\n\tconst prefix = \"sha256-\";\n\tif (!integrity.startsWith(prefix) || integrity.length === prefix.length) {\n\t\tthrow new Error(\"Facet bundle entry has an invalid SHA-256 integrity value\");\n\t}\n\treturn integrity.slice(prefix.length);\n}\n\nfunction facetsFromModule(imported: unknown, pluginId: string, entryName: string): readonly Facet[] {\n\tif (!isRecord(imported)) throw new Error(`Facet bundle entry ${pluginId}/${entryName} did not export a module`);\n\tconst exported = imported.default;\n\tconst candidates: readonly unknown[] = Array.isArray(exported) ? (exported as readonly unknown[]) : [exported];\n\tif (candidates.length === 0) {\n\t\tthrow new Error(`Facet bundle entry ${pluginId}/${entryName} exported no facets`);\n\t}\n\tconst facets: Facet[] = [];\n\tfor (const candidate of candidates) {\n\t\tif (!isRecord(candidate) || typeof candidate.id !== \"string\" || candidate.id.length === 0) {\n\t\t\tthrow new Error(`Facet bundle entry ${pluginId}/${entryName} has a facet with an invalid ID`);\n\t\t}\n\t\tif (typeof candidate.setup !== \"function\") {\n\t\t\tthrow new Error(`Facet bundle entry ${pluginId}/${entryName} facet ${candidate.id} has no setup function`);\n\t\t}\n\t\tfacets.push(candidate as unknown as Facet);\n\t}\n\tconst ids = facets.map(({ id }) => id);\n\tif (new Set(ids).size !== ids.length) {\n\t\tthrow new Error(`Facet bundle entry ${pluginId}/${entryName} exports duplicate facet IDs`);\n\t}\n\treturn Object.freeze(facets);\n}\n\nfunction validateArtifact(value: unknown): FacetBundleArtifact {\n\tif (\n\t\t!isRecord(value) ||\n\t\tvalue.format !== FACET_BUNDLE_ARTIFACT_FORMAT ||\n\t\tvalue.formatVersion !== FACET_BUNDLE_ARTIFACT_FORMAT_VERSION ||\n\t\ttypeof value.entryName !== \"string\" ||\n\t\tvalue.entryName.length === 0 ||\n\t\ttypeof value.source !== \"string\"\n\t) {\n\t\tthrow new Error(\"Invalid facet bundle artifact\");\n\t}\n\tconst manifest = validateManifest(\n\t\t{\n\t\t\tformat: FACET_BUNDLE_FORMAT,\n\t\t\tformatVersion: FACET_BUNDLE_FORMAT_VERSION,\n\t\t\tplugin: value.plugin,\n\t\t\tentries: { [value.entryName]: value.entry },\n\t\t},\n\t\t\"facet bundle artifact\",\n\t);\n\tconst entry = manifest.entries[value.entryName]!;\n\tif (entry.sourceMap === undefined) {\n\t\tif (value.sourceMapContents !== undefined) {\n\t\t\tthrow new Error(\"Facet bundle artifact has source map contents without a source map\");\n\t\t}\n\t} else if (typeof value.sourceMapContents !== \"string\") {\n\t\tthrow new Error(\"Facet bundle artifact is missing its source map contents\");\n\t}\n\tverifySource(value.source, entry);\n\treturn Object.freeze({\n\t\tformat: FACET_BUNDLE_ARTIFACT_FORMAT,\n\t\tformatVersion: FACET_BUNDLE_ARTIFACT_FORMAT_VERSION,\n\t\tplugin: manifest.plugin,\n\t\tentryName: value.entryName,\n\t\tentry,\n\t\tsource: value.source,\n\t\t...(value.sourceMapContents === undefined ? {} : { sourceMapContents: value.sourceMapContents }),\n\t});\n}\n\nasync function materializeArtifact(directory: string, artifact: FacetBundleArtifact): Promise<void> {\n\tconst manifest: FacetBundleManifest = {\n\t\tformat: FACET_BUNDLE_FORMAT,\n\t\tformatVersion: FACET_BUNDLE_FORMAT_VERSION,\n\t\tplugin: artifact.plugin,\n\t\tentries: { [artifact.entryName]: artifact.entry },\n\t};\n\tawait Promise.all([\n\t\twriteFile(join(directory, artifact.entry.file), artifact.source, \"utf8\"),\n\t\twriteFile(join(directory, FACET_BUNDLE_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\\n`, \"utf8\"),\n\t\t...(artifact.entry.sourceMap === undefined\n\t\t\t? []\n\t\t\t: [writeFile(join(directory, artifact.entry.sourceMap), artifact.sourceMapContents!, \"utf8\")]),\n\t]);\n}\n\nfunction resolveExternalTarget(specifier: string, resolver?: FacetBundleExternalResolver): string {\n\tconst resolved = resolver?.(specifier);\n\tif (resolved !== undefined) return typeof resolved === \"string\" ? resolved : resolved.href;\n\tconst extension = import.meta.url.endsWith(\".ts\") ? \"ts\" : \"js\";\n\tif (specifier === \"@earendil-works/chord\") return new URL(`../index.${extension}`, import.meta.url).href;\n\tif (specifier === \"@earendil-works/chord/context\") {\n\t\treturn new URL(`../context/index.${extension}`, import.meta.url).href;\n\t}\n\tif (specifier === \"@earendil-works/chord/node\") return new URL(`../node.${extension}`, import.meta.url).href;\n\treturn import.meta.resolve(specifier);\n}\n\nfunction validatePackageSpecifier(specifier: string): void {\n\tconst segments = specifier.split(\"/\");\n\tconst packageParts = specifier.startsWith(\"@\") ? 2 : 1;\n\tif (\n\t\tspecifier.startsWith(\".\") ||\n\t\tspecifier.startsWith(\"/\") ||\n\t\tspecifier.startsWith(\"#\") ||\n\t\tspecifier.includes(\":\") ||\n\t\tspecifier.includes(\"\\\\\") ||\n\t\tsegments.length < packageParts ||\n\t\tsegments.some((part) => part.length === 0 || part === \".\" || part === \"..\")\n\t) {\n\t\tthrow new Error(`Facet bundle artifact has an unsupported external import: ${specifier}`);\n\t}\n}\n\nfunction validateManifest(value: unknown, path: string): FacetBundleManifest {\n\tif (!isRecord(value) || value.format !== FACET_BUNDLE_FORMAT) {\n\t\tthrow new Error(`Invalid facet bundle manifest format in ${path}`);\n\t}\n\tif (value.formatVersion !== FACET_BUNDLE_FORMAT_VERSION) {\n\t\tthrow new Error(`Unsupported facet bundle manifest version in ${path}: ${String(value.formatVersion)}`);\n\t}\n\tif (!isRecord(value.plugin) || typeof value.plugin.id !== \"string\" || value.plugin.id.length === 0) {\n\t\tthrow new Error(`Facet bundle manifest has an invalid plugin identity in ${path}`);\n\t}\n\tif (\n\t\tvalue.plugin.version !== undefined &&\n\t\t(typeof value.plugin.version !== \"string\" || value.plugin.version.length === 0)\n\t) {\n\t\tthrow new Error(`Facet bundle manifest has an invalid plugin version in ${path}`);\n\t}\n\tif (!isRecord(value.entries) || Object.keys(value.entries).length === 0) {\n\t\tthrow new Error(`Facet bundle manifest has no entries in ${path}`);\n\t}\n\tconst entries: Record<string, FacetBundleEntry> = {};\n\tfor (const [name, candidate] of Object.entries(value.entries)) {\n\t\tif (name.length === 0 || !isRecord(candidate)) {\n\t\t\tthrow new Error(`Facet bundle manifest has an invalid entry in ${path}`);\n\t\t}\n\t\tif (typeof candidate.file !== \"string\") throw new Error(`Facet bundle entry ${name} has no file`);\n\t\tresolveBundleFile(path, candidate.file, `entry ${name}`);\n\t\tif (typeof candidate.integrity !== \"string\") throw new Error(`Facet bundle entry ${name} has no integrity`);\n\t\tparseIntegrity(candidate.integrity);\n\t\tif (\n\t\t\t!Array.isArray(candidate.externalImports) ||\n\t\t\tcandidate.externalImports.some((item) => typeof item !== \"string\")\n\t\t) {\n\t\t\tthrow new Error(`Facet bundle entry ${name} has invalid external imports`);\n\t\t}\n\t\tconst externalImports = Object.freeze([...(candidate.externalImports as readonly string[])]);\n\t\tif (new Set(externalImports).size !== externalImports.length) {\n\t\t\tthrow new Error(`Facet bundle entry ${name} has duplicate external imports`);\n\t\t}\n\t\tif (candidate.sourceMap !== undefined) {\n\t\t\tif (typeof candidate.sourceMap !== \"string\")\n\t\t\t\tthrow new Error(`Facet bundle entry ${name} has an invalid source map`);\n\t\t\tresolveBundleFile(path, candidate.sourceMap, `entry ${name} source map`);\n\t\t}\n\t\tentries[name] = Object.freeze({\n\t\t\tfile: candidate.file,\n\t\t\tintegrity: candidate.integrity,\n\t\t\texternalImports,\n\t\t\t...(candidate.sourceMap === undefined ? {} : { sourceMap: candidate.sourceMap }),\n\t\t});\n\t}\n\treturn Object.freeze({\n\t\tformat: FACET_BUNDLE_FORMAT,\n\t\tformatVersion: FACET_BUNDLE_FORMAT_VERSION,\n\t\tplugin: Object.freeze({\n\t\t\tid: value.plugin.id,\n\t\t\t...(value.plugin.version === undefined ? {} : { version: value.plugin.version }),\n\t\t}),\n\t\tentries: Object.freeze(entries),\n\t});\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type FacetBundleManifest } from "./manifest.ts";
|
|
2
|
+
export type FacetBundlePlatform = "node" | "browser" | "neutral";
|
|
3
|
+
export interface BundleFacetsOptions {
|
|
4
|
+
readonly plugin: {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly version?: string;
|
|
7
|
+
};
|
|
8
|
+
/** Opaque application-selected entry names mapped to TypeScript or JavaScript source files. */
|
|
9
|
+
readonly entries: Readonly<Record<string, string>>;
|
|
10
|
+
readonly outdir: string;
|
|
11
|
+
readonly workingDirectory?: string;
|
|
12
|
+
/** Additional package imports intentionally left for the loading application to resolve. */
|
|
13
|
+
readonly external?: readonly string[];
|
|
14
|
+
readonly sourceMap?: boolean;
|
|
15
|
+
readonly minify?: boolean;
|
|
16
|
+
readonly define?: Readonly<Record<string, string>>;
|
|
17
|
+
readonly platform?: FacetBundlePlatform;
|
|
18
|
+
readonly target?: string | readonly string[];
|
|
19
|
+
}
|
|
20
|
+
export interface BundleFacetsResult {
|
|
21
|
+
readonly manifest: FacetBundleManifest;
|
|
22
|
+
readonly manifestPath: string;
|
|
23
|
+
}
|
|
24
|
+
/** Bundle each opaque facet entry into an independent content-addressed CommonJS file. */
|
|
25
|
+
export declare function bundleFacets(options: BundleFacetsOptions): Promise<BundleFacetsResult>;
|
|
26
|
+
//# sourceMappingURL=bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../src/node/bundle.ts"],"names":[],"mappings":"AAIA,OAAO,EAKN,KAAK,mBAAmB,EACxB,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,MAAM,EAAE;QAChB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,+FAA+F;IAC/F,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC9B;AAED,0FAA0F;AAC1F,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAwC5F","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, extname, join, relative, resolve, sep } from \"node:path\";\nimport { type BuildOptions, build, type Message } from \"esbuild\";\nimport {\n\tFACET_BUNDLE_FORMAT,\n\tFACET_BUNDLE_FORMAT_VERSION,\n\tFACET_BUNDLE_MANIFEST_FILE,\n\ttype FacetBundleEntry,\n\ttype FacetBundleManifest,\n} from \"./manifest.ts\";\n\nexport type FacetBundlePlatform = \"node\" | \"browser\" | \"neutral\";\n\nexport interface BundleFacetsOptions {\n\treadonly plugin: {\n\t\treadonly id: string;\n\t\treadonly version?: string;\n\t};\n\t/** Opaque application-selected entry names mapped to TypeScript or JavaScript source files. */\n\treadonly entries: Readonly<Record<string, string>>;\n\treadonly outdir: string;\n\treadonly workingDirectory?: string;\n\t/** Additional package imports intentionally left for the loading application to resolve. */\n\treadonly external?: readonly string[];\n\treadonly sourceMap?: boolean;\n\treadonly minify?: boolean;\n\treadonly define?: Readonly<Record<string, string>>;\n\treadonly platform?: FacetBundlePlatform;\n\treadonly target?: string | readonly string[];\n}\n\nexport interface BundleFacetsResult {\n\treadonly manifest: FacetBundleManifest;\n\treadonly manifestPath: string;\n}\n\n/** Bundle each opaque facet entry into an independent content-addressed CommonJS file. */\nexport async function bundleFacets(options: BundleFacetsOptions): Promise<BundleFacetsResult> {\n\tvalidateOptions(options);\n\tconst workingDirectory = resolve(options.workingDirectory ?? process.cwd());\n\tconst outputDirectory = resolve(workingDirectory, options.outdir);\n\tconst outputParent = dirname(outputDirectory);\n\tawait mkdir(outputParent, { recursive: true });\n\tconst temporaryDirectory = join(outputParent, `.${basename(outputDirectory)}.tmp-${randomUUID()}`);\n\tawait mkdir(temporaryDirectory);\n\ttry {\n\t\tconst entries: Record<string, FacetBundleEntry> = {};\n\t\tfor (const [entryName, source] of Object.entries(options.entries).sort(([left], [right]) =>\n\t\t\tleft.localeCompare(right),\n\t\t)) {\n\t\t\tentries[entryName] = await bundleEntry({\n\t\t\t\tentryName,\n\t\t\t\tsource: resolve(workingDirectory, source),\n\t\t\t\ttemporaryDirectory,\n\t\t\t\tworkingDirectory,\n\t\t\t\toptions,\n\t\t\t});\n\t\t}\n\t\tconst manifest: FacetBundleManifest = Object.freeze({\n\t\t\tformat: FACET_BUNDLE_FORMAT,\n\t\t\tformatVersion: FACET_BUNDLE_FORMAT_VERSION,\n\t\t\tplugin: Object.freeze({\n\t\t\t\tid: options.plugin.id,\n\t\t\t\t...(options.plugin.version === undefined ? {} : { version: options.plugin.version }),\n\t\t\t}),\n\t\t\tentries: Object.freeze(entries),\n\t\t});\n\t\tawait writeFile(join(temporaryDirectory, FACET_BUNDLE_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\\n`);\n\t\tawait replaceDirectory(temporaryDirectory, outputDirectory);\n\t\treturn Object.freeze({\n\t\t\tmanifest,\n\t\t\tmanifestPath: join(outputDirectory, FACET_BUNDLE_MANIFEST_FILE),\n\t\t});\n\t} catch (error) {\n\t\tawait rm(temporaryDirectory, { force: true, recursive: true });\n\t\tthrow error;\n\t}\n}\n\nasync function bundleEntry(input: {\n\treadonly entryName: string;\n\treadonly source: string;\n\treadonly temporaryDirectory: string;\n\treadonly workingDirectory: string;\n\treadonly options: BundleFacetsOptions;\n}): Promise<FacetBundleEntry> {\n\tconst entryPrefix = `facet-${shortHash(input.entryName)}`;\n\tconst requestedPlatform = input.options.platform ?? \"node\";\n\tconst buildOptions: BuildOptions = {\n\t\tabsWorkingDir: input.workingDirectory,\n\t\tbanner: { js: '\"use strict\";' },\n\t\tbundle: true,\n\t\tdefine: input.options.define,\n\t\tentryNames: `${entryPrefix}-[hash]`,\n\t\tentryPoints: [input.source],\n\t\texternal: [...new Set([\"@earendil-works/chord\", \"@earendil-works/chord/*\", ...(input.options.external ?? [])])],\n\t\tformat: \"cjs\",\n\t\tlegalComments: \"none\",\n\t\tlogLevel: \"silent\",\n\t\tmetafile: true,\n\t\tminify: input.options.minify ?? false,\n\t\toutdir: input.temporaryDirectory,\n\t\toutExtension: { \".js\": \".cjs\" },\n\t\tplatform: requestedPlatform,\n\t\tsourcemap: input.options.sourceMap === true ? \"external\" : false,\n\t\tsupported: { \"dynamic-import\": false },\n\t\ttarget:\n\t\t\tinput.options.target === undefined\n\t\t\t\t? requestedPlatform === \"node\"\n\t\t\t\t\t? \"node22.19\"\n\t\t\t\t\t: \"es2022\"\n\t\t\t\t: typeof input.options.target === \"string\"\n\t\t\t\t\t? input.options.target\n\t\t\t\t\t: [...input.options.target],\n\t\twrite: true,\n\t};\n\tlet result: Awaited<ReturnType<typeof build>>;\n\ttry {\n\t\tresult = await build(buildOptions);\n\t} catch (error) {\n\t\tconst diagnostics = esbuildMessages(error);\n\t\tconst detail = diagnostics.length === 0 ? \"\" : `\\n${diagnostics.join(\"\\n\")}`;\n\t\tthrow new Error(`Could not bundle facet entry ${input.entryName}${detail}`, { cause: error });\n\t}\n\tconst metafile = result.metafile;\n\tif (metafile === undefined) throw new Error(`Facet entry ${input.entryName} produced no build metadata`);\n\tconst outputs = Object.entries(metafile.outputs).filter(\n\t\t([path, output]) => output.entryPoint !== undefined && extname(path) === \".cjs\",\n\t);\n\tif (outputs.length !== 1)\n\t\tthrow new Error(`Facet entry ${input.entryName} did not produce exactly one JavaScript file`);\n\tconst [outputPath, metadata] = outputs[0]!;\n\tconst absoluteOutputPath = resolve(input.workingDirectory, outputPath);\n\tconst file = relative(input.temporaryDirectory, absoluteOutputPath);\n\tif (file.length === 0 || file.startsWith(`..${sep}`) || basename(file) !== file) {\n\t\tthrow new Error(`Facet entry ${input.entryName} produced an invalid output path`);\n\t}\n\tconst sourceMap = input.options.sourceMap === true ? `${file}.map` : undefined;\n\tconst allowedOutputs = new Set([absoluteOutputPath]);\n\tif (sourceMap !== undefined) allowedOutputs.add(join(input.temporaryDirectory, sourceMap));\n\tconst unexpectedOutputs = Object.keys(metafile.outputs)\n\t\t.map((path) => resolve(input.workingDirectory, path))\n\t\t.filter((path) => !allowedOutputs.has(path));\n\tif (unexpectedOutputs.length > 0) {\n\t\tthrow new Error(`Facet entry ${input.entryName} produced files other than its JavaScript bundle and source map`);\n\t}\n\tconst contents = await readFile(absoluteOutputPath);\n\tif (sourceMap !== undefined) await stat(join(input.temporaryDirectory, sourceMap));\n\treturn Object.freeze({\n\t\tfile,\n\t\tintegrity: `sha256-${createHash(\"sha256\").update(contents).digest(\"base64\")}`,\n\t\texternalImports: Object.freeze(\n\t\t\t[...new Set(metadata.imports.filter(({ external }) => external).map(({ path }) => path))].sort(),\n\t\t),\n\t\t...(sourceMap === undefined ? {} : { sourceMap }),\n\t});\n}\n\nfunction validateOptions(options: BundleFacetsOptions): void {\n\tif (options.plugin.id.length === 0) throw new TypeError(\"Facet bundle plugin ID must not be empty\");\n\tif (options.plugin.version !== undefined && options.plugin.version.length === 0) {\n\t\tthrow new TypeError(\"Facet bundle plugin version must not be empty\");\n\t}\n\tconst entries = Object.entries(options.entries);\n\tif (entries.length === 0) throw new TypeError(\"Facet bundle must contain at least one entry\");\n\tfor (const [name, source] of entries) {\n\t\tif (name.length === 0) throw new TypeError(\"Facet bundle entry name must not be empty\");\n\t\tif (source.length === 0) throw new TypeError(`Facet bundle entry ${name} must have a source path`);\n\t}\n\tfor (const external of options.external ?? []) {\n\t\tif (external.length === 0) throw new TypeError(\"Facet bundle external import must not be empty\");\n\t}\n}\n\nasync function replaceDirectory(temporaryDirectory: string, outputDirectory: string): Promise<void> {\n\tconst backupDirectory = `${outputDirectory}.old-${randomUUID()}`;\n\tlet movedExisting = false;\n\ttry {\n\t\tawait rename(outputDirectory, backupDirectory);\n\t\tmovedExisting = true;\n\t} catch (error) {\n\t\tif (!isMissingPath(error)) throw error;\n\t}\n\ttry {\n\t\tawait rename(temporaryDirectory, outputDirectory);\n\t} catch (error) {\n\t\tif (movedExisting) await rename(backupDirectory, outputDirectory);\n\t\tthrow error;\n\t}\n\tif (movedExisting) await rm(backupDirectory, { force: true, recursive: true });\n}\n\nfunction shortHash(value: string): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\").slice(0, 12);\n}\n\nfunction esbuildMessages(error: unknown): string[] {\n\tif (!isRecord(error) || !Array.isArray(error.errors)) return [];\n\treturn (error.errors as readonly unknown[]).flatMap((candidate) =>\n\t\tisEsbuildMessage(candidate) ? [formatEsbuildMessage(candidate)] : [],\n\t);\n}\n\nfunction formatEsbuildMessage(message: Message): string {\n\tconst location = message.location;\n\treturn location === null\n\t\t? message.text\n\t\t: `${location.file}:${location.line}:${location.column + 1}: ${message.text}`;\n}\n\nfunction isEsbuildMessage(value: unknown): value is Message {\n\treturn isRecord(value) && typeof value.text === \"string\" && (value.location === null || isRecord(value.location));\n}\n\nfunction isMissingPath(error: unknown): boolean {\n\treturn isRecord(error) && error.code === \"ENOENT\";\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
|