@allwright.dev/core 0.0.40 → 0.0.42
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/dist/bootstrap.js +122 -17
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -12,7 +12,7 @@ const ALLWRIGHT_HOME_ENV_VAR = "ALLWRIGHT_HOME";
|
|
|
12
12
|
const ALLWRIGHT_REPOSITORY_ENV_VAR = "ALLWRIGHT_REPOSITORY";
|
|
13
13
|
const ALLWRIGHT_VERSION_ENV_VAR = "ALLWRIGHT_VERSION";
|
|
14
14
|
const DEFAULT_RELEASE_REPOSITORY = "allwright-dev/allwright";
|
|
15
|
-
const DEFAULT_RELEASE_VERSION = "0.0.
|
|
15
|
+
const DEFAULT_RELEASE_VERSION = "0.0.42";
|
|
16
16
|
const STARTUP_TIMEOUT_MS = 20_000;
|
|
17
17
|
const PING_TIMEOUT_MS = 1_000;
|
|
18
18
|
const PROTO_ROOT = fileURLToPath(new URL("../proto/", import.meta.url));
|
|
@@ -20,6 +20,9 @@ const ENGINE_PROTO_PATH = fileURLToPath(new URL("../proto/engine/v1/engine.proto
|
|
|
20
20
|
let managedServer = null;
|
|
21
21
|
let managedServerAddr = null;
|
|
22
22
|
let managedServerBaseAddr = null;
|
|
23
|
+
let managedServerStdout = "";
|
|
24
|
+
let managedServerStderr = "";
|
|
25
|
+
let managedServerSpawnError = null;
|
|
23
26
|
export async function ensureRuntimeReady(serverAddr) {
|
|
24
27
|
const expectedVersion = expectedRuntimeVersion();
|
|
25
28
|
const status = await pingServer(serverAddr);
|
|
@@ -42,6 +45,9 @@ export async function ensureRuntimeReady(serverAddr) {
|
|
|
42
45
|
managedServer = null;
|
|
43
46
|
managedServerAddr = null;
|
|
44
47
|
managedServerBaseAddr = null;
|
|
48
|
+
managedServerStdout = "";
|
|
49
|
+
managedServerStderr = "";
|
|
50
|
+
managedServerSpawnError = null;
|
|
45
51
|
}
|
|
46
52
|
const cliPath = await ensureCliAvailable(expectedVersion);
|
|
47
53
|
ensureWebPlugin(cliPath, expectedVersion);
|
|
@@ -50,7 +56,19 @@ export async function ensureRuntimeReady(serverAddr) {
|
|
|
50
56
|
resolvedServerAddr = await allocateManagedServerAddr(serverAddr);
|
|
51
57
|
}
|
|
52
58
|
managedServer = spawn(cliPath, ["serve", "--listen-addr", cliListenAddr(resolvedServerAddr)], {
|
|
53
|
-
stdio: "ignore",
|
|
59
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
60
|
+
});
|
|
61
|
+
managedServerStdout = "";
|
|
62
|
+
managedServerStderr = "";
|
|
63
|
+
managedServerSpawnError = null;
|
|
64
|
+
managedServer.stdout?.on("data", (chunk) => {
|
|
65
|
+
managedServerStdout = appendManagedServerOutput(managedServerStdout, chunk);
|
|
66
|
+
});
|
|
67
|
+
managedServer.stderr?.on("data", (chunk) => {
|
|
68
|
+
managedServerStderr = appendManagedServerOutput(managedServerStderr, chunk);
|
|
69
|
+
});
|
|
70
|
+
managedServer.on("error", (error) => {
|
|
71
|
+
managedServerSpawnError = error.message;
|
|
54
72
|
});
|
|
55
73
|
managedServerAddr = resolvedServerAddr;
|
|
56
74
|
managedServerBaseAddr = serverAddr;
|
|
@@ -63,18 +81,32 @@ export async function shutdownManagedServer() {
|
|
|
63
81
|
managedServer = null;
|
|
64
82
|
managedServerAddr = null;
|
|
65
83
|
managedServerBaseAddr = null;
|
|
84
|
+
managedServerStdout = "";
|
|
85
|
+
managedServerStderr = "";
|
|
86
|
+
managedServerSpawnError = null;
|
|
66
87
|
}
|
|
67
88
|
async function waitForServer(serverAddr, expectedVersion) {
|
|
68
89
|
const deadline = Date.now() + STARTUP_TIMEOUT_MS;
|
|
69
90
|
while (Date.now() < deadline) {
|
|
91
|
+
if (managedServer && managedServer.exitCode !== null) {
|
|
92
|
+
const details = formatManagedServerFailure(managedServer.exitCode, managedServer.signalCode);
|
|
93
|
+
await shutdownManagedServer();
|
|
94
|
+
throw new Error(`allwright server exited before becoming ready at ${serverAddr}${details}`);
|
|
95
|
+
}
|
|
96
|
+
if (managedServerSpawnError) {
|
|
97
|
+
const details = formatManagedServerFailure(null, null);
|
|
98
|
+
await shutdownManagedServer();
|
|
99
|
+
throw new Error(`failed to start allwright server at ${serverAddr}${details}`);
|
|
100
|
+
}
|
|
70
101
|
const status = await pingServer(serverAddr);
|
|
71
102
|
if (status?.version === expectedVersion) {
|
|
72
103
|
return serverAddr;
|
|
73
104
|
}
|
|
74
105
|
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
75
106
|
}
|
|
107
|
+
const details = formatManagedServerFailure(managedServer?.exitCode ?? null, managedServer?.signalCode ?? null);
|
|
76
108
|
await shutdownManagedServer();
|
|
77
|
-
throw new Error(`timed out waiting for allwright server at ${serverAddr} to become ready with version ${expectedVersion}`);
|
|
109
|
+
throw new Error(`timed out waiting for allwright server at ${serverAddr} to become ready with version ${expectedVersion}${details}`);
|
|
78
110
|
}
|
|
79
111
|
async function pingServer(serverAddr) {
|
|
80
112
|
const loaded = protoLoader.loadSync(ENGINE_PROTO_PATH, {
|
|
@@ -143,10 +175,20 @@ function ensureWebPlugin(cliPath, expectedVersion) {
|
|
|
143
175
|
return;
|
|
144
176
|
}
|
|
145
177
|
const result = spawnSync(cliPath, ["plugin", "install", "web", "--version", expectedVersion], {
|
|
146
|
-
|
|
178
|
+
encoding: "utf8",
|
|
179
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
147
180
|
});
|
|
181
|
+
if (result.error) {
|
|
182
|
+
throw new Error(`failed to install allwright web plugin with ${cliPath}: ${result.error.message}`);
|
|
183
|
+
}
|
|
148
184
|
if (result.status !== 0 || !isFile(pluginPath)) {
|
|
149
|
-
|
|
185
|
+
const details = [result.stdout, result.stderr]
|
|
186
|
+
.map((value) => value?.trim())
|
|
187
|
+
.filter((value) => !!value)
|
|
188
|
+
.join("\n");
|
|
189
|
+
throw new Error(details
|
|
190
|
+
? `allwright attempted to install the \`web\` plugin automatically, but the install did not complete successfully:\n${details}`
|
|
191
|
+
: "allwright attempted to install the `web` plugin automatically, but the install did not complete successfully");
|
|
150
192
|
}
|
|
151
193
|
if (installedPluginVersion("web") !== expectedVersion) {
|
|
152
194
|
throw new Error(`allwright attempted to install the \`web\` plugin automatically, but version ${expectedVersion} is still not active`);
|
|
@@ -170,33 +212,53 @@ async function resolveReleaseTag() {
|
|
|
170
212
|
return payload.tag_name;
|
|
171
213
|
}
|
|
172
214
|
function extractCliArchive(archivePath, cliPath) {
|
|
215
|
+
const extractRoot = fs.mkdtempSync(path.join(os.tmpdir(), "allwright-cli-"));
|
|
173
216
|
if (archivePath.endsWith(".zip")) {
|
|
174
217
|
const result = spawnSync("powershell", [
|
|
175
218
|
"-NoProfile",
|
|
176
219
|
"-Command",
|
|
177
|
-
`Expand-Archive -Path '${archivePath.replaceAll("'", "''")}' -DestinationPath '${
|
|
178
|
-
], { stdio: "ignore" });
|
|
220
|
+
`Expand-Archive -Path '${archivePath.replaceAll("'", "''")}' -DestinationPath '${extractRoot.replaceAll("'", "''")}' -Force`,
|
|
221
|
+
], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
222
|
+
if (result.error) {
|
|
223
|
+
fs.rmSync(extractRoot, { recursive: true, force: true });
|
|
224
|
+
throw new Error(`failed to extract allwright CLI zip archive: ${result.error.message}`);
|
|
225
|
+
}
|
|
179
226
|
if (result.status !== 0) {
|
|
180
|
-
|
|
227
|
+
const details = [result.stdout, result.stderr].map((value) => value?.trim()).filter(Boolean).join("\n");
|
|
228
|
+
fs.rmSync(extractRoot, { recursive: true, force: true });
|
|
229
|
+
throw new Error(details ? `failed to extract allwright CLI zip archive:\n${details}` : "failed to extract allwright CLI zip archive");
|
|
230
|
+
}
|
|
231
|
+
const extracted = findExtractedCli(extractRoot);
|
|
232
|
+
if (!extracted) {
|
|
233
|
+
fs.rmSync(extractRoot, { recursive: true, force: true });
|
|
234
|
+
throw new Error(`allwright CLI zip archive did not contain bin/${cliFilename()}`);
|
|
181
235
|
}
|
|
182
|
-
const extracted = path.join(path.dirname(cliPath), "bin", cliFilename());
|
|
183
236
|
fs.copyFileSync(extracted, cliPath);
|
|
184
|
-
fs.rmSync(
|
|
237
|
+
fs.rmSync(extractRoot, { recursive: true, force: true });
|
|
185
238
|
return;
|
|
186
239
|
}
|
|
187
240
|
const result = spawnSync("tar", [
|
|
188
241
|
"-xzf",
|
|
189
242
|
archivePath,
|
|
190
243
|
"-C",
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
244
|
+
extractRoot,
|
|
245
|
+
], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
246
|
+
if (result.error) {
|
|
247
|
+
fs.rmSync(extractRoot, { recursive: true, force: true });
|
|
248
|
+
throw new Error(`failed to extract allwright CLI tar archive: ${result.error.message}`);
|
|
249
|
+
}
|
|
194
250
|
if (result.status !== 0) {
|
|
195
|
-
|
|
251
|
+
const details = [result.stdout, result.stderr].map((value) => value?.trim()).filter(Boolean).join("\n");
|
|
252
|
+
fs.rmSync(extractRoot, { recursive: true, force: true });
|
|
253
|
+
throw new Error(details ? `failed to extract allwright CLI tar archive:\n${details}` : "failed to extract allwright CLI tar archive");
|
|
254
|
+
}
|
|
255
|
+
const extracted = findExtractedCli(extractRoot);
|
|
256
|
+
if (!extracted) {
|
|
257
|
+
fs.rmSync(extractRoot, { recursive: true, force: true });
|
|
258
|
+
throw new Error(`allwright CLI archive did not contain bin/${cliFilename()}`);
|
|
196
259
|
}
|
|
197
|
-
const extracted = path.join(path.dirname(cliPath), "bin", cliFilename());
|
|
198
260
|
fs.copyFileSync(extracted, cliPath);
|
|
199
|
-
fs.rmSync(
|
|
261
|
+
fs.rmSync(extractRoot, { recursive: true, force: true });
|
|
200
262
|
}
|
|
201
263
|
function cliAssetName(versionTag) {
|
|
202
264
|
const targets = new Map([
|
|
@@ -269,7 +331,7 @@ async function allocateManagedServerAddr(serverAddr) {
|
|
|
269
331
|
});
|
|
270
332
|
});
|
|
271
333
|
});
|
|
272
|
-
return host.includes(":") ? `
|
|
334
|
+
return host.includes(":") ? `[${host}]:${port}` : `${host}:${port}`;
|
|
273
335
|
}
|
|
274
336
|
function localBindingHost(serverAddr) {
|
|
275
337
|
const host = parseServerHost(serverAddr);
|
|
@@ -316,6 +378,49 @@ function allwrightHome() {
|
|
|
316
378
|
function cliFilename() {
|
|
317
379
|
return process.platform === "win32" ? "allwright.exe" : "allwright";
|
|
318
380
|
}
|
|
381
|
+
function appendManagedServerOutput(current, chunk) {
|
|
382
|
+
const next = `${current}${typeof chunk === "string" ? chunk : chunk.toString("utf8")}`;
|
|
383
|
+
return next.length > 8_000 ? next.slice(-8_000) : next;
|
|
384
|
+
}
|
|
385
|
+
function formatManagedServerFailure(exitCode, signalCode) {
|
|
386
|
+
const parts = [];
|
|
387
|
+
if (managedServerSpawnError) {
|
|
388
|
+
parts.push(`spawn error: ${managedServerSpawnError}`);
|
|
389
|
+
}
|
|
390
|
+
if (exitCode !== null) {
|
|
391
|
+
parts.push(`exit code: ${exitCode}`);
|
|
392
|
+
}
|
|
393
|
+
if (signalCode) {
|
|
394
|
+
parts.push(`signal: ${signalCode}`);
|
|
395
|
+
}
|
|
396
|
+
if (managedServerStdout.trim()) {
|
|
397
|
+
parts.push(`stdout:\n${managedServerStdout.trim()}`);
|
|
398
|
+
}
|
|
399
|
+
if (managedServerStderr.trim()) {
|
|
400
|
+
parts.push(`stderr:\n${managedServerStderr.trim()}`);
|
|
401
|
+
}
|
|
402
|
+
return parts.length > 0 ? `\n${parts.join("\n")}` : "";
|
|
403
|
+
}
|
|
404
|
+
function findExtractedCli(extractRoot) {
|
|
405
|
+
const queue = [extractRoot];
|
|
406
|
+
while (queue.length > 0) {
|
|
407
|
+
const current = queue.shift();
|
|
408
|
+
if (!current) {
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
412
|
+
const entryPath = path.join(current, entry.name);
|
|
413
|
+
if (entry.isDirectory()) {
|
|
414
|
+
queue.push(entryPath);
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
if (entry.isFile() && entry.name === cliFilename() && path.basename(path.dirname(entryPath)) === "bin") {
|
|
418
|
+
return entryPath;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
319
424
|
function webPluginFilename() {
|
|
320
425
|
if (process.platform === "darwin") {
|
|
321
426
|
return "liballwright_surface_web.dylib";
|