@absolutejs/absolute 0.19.0-beta.681 → 0.19.0-beta.683
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/cli/index.js +122 -23
- package/dist/types/build.d.ts +6 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1145,17 +1145,17 @@ var isCommandService3 = (service) => service.kind === "command" || Array.isArray
|
|
|
1145
1145
|
}, shellEscape = (value) => `'${value.replaceAll("'", "'\\''")}'`, runShell = async (name, command) => run(name, ["/bin/bash", "-lc", command]), findBin = (name) => {
|
|
1146
1146
|
const local = resolve8("node_modules", ".bin", name);
|
|
1147
1147
|
return existsSync10(local) ? local : null;
|
|
1148
|
-
},
|
|
1148
|
+
}, stripAnsi3 = (str) => str.replace(/\x1b\[[0-9;]*m/g, ""), formatSvelteOutput = (output) => {
|
|
1149
1149
|
const cwd = `${process.cwd()}/`;
|
|
1150
|
-
const summaryMatch =
|
|
1150
|
+
const summaryMatch = stripAnsi3(output).match(/svelte-check found (\d+) error/);
|
|
1151
1151
|
const errorCount = summaryMatch ? parseInt(summaryMatch[1] ?? "0", 10) : 0;
|
|
1152
1152
|
const formatted = output.split(`
|
|
1153
1153
|
`).filter((line) => {
|
|
1154
|
-
const plain =
|
|
1154
|
+
const plain = stripAnsi3(line);
|
|
1155
1155
|
return !plain.startsWith("Loading svelte-check") && !plain.startsWith("Getting Svelte") && !plain.startsWith("====") && !plain.startsWith("svelte-check found") && !/^\d+ (START|COMPLETED)/.test(plain) && plain.trim() !== "";
|
|
1156
1156
|
}).flatMap((line) => {
|
|
1157
1157
|
const result = line.replaceAll(cwd, "");
|
|
1158
|
-
const plain =
|
|
1158
|
+
const plain = stripAnsi3(result);
|
|
1159
1159
|
const pathMatch = plain.match(/^(\S+\.svelte):(\d+:\d+)$/);
|
|
1160
1160
|
if (pathMatch) {
|
|
1161
1161
|
return [
|
|
@@ -1163,9 +1163,9 @@ var isCommandService3 = (service) => service.kind === "command" || Array.isArray
|
|
|
1163
1163
|
];
|
|
1164
1164
|
}
|
|
1165
1165
|
if (result.includes("\x1B[35m")) {
|
|
1166
|
-
const plainLine =
|
|
1167
|
-
const before =
|
|
1168
|
-
const token =
|
|
1166
|
+
const plainLine = stripAnsi3(result);
|
|
1167
|
+
const before = stripAnsi3(result.split("\x1B[35m")[0] ?? "");
|
|
1168
|
+
const token = stripAnsi3((result.split("\x1B[35m")[1] ?? "").split(/\x1b\[3[69]m/)[0] ?? "");
|
|
1169
1169
|
if (!token)
|
|
1170
1170
|
return [result];
|
|
1171
1171
|
const expanded = before.replace(/\t/g, " ");
|
|
@@ -2485,7 +2485,13 @@ var start = async (serverEntry, outdir, configPath2) => {
|
|
|
2485
2485
|
init_constants();
|
|
2486
2486
|
init_loadConfig();
|
|
2487
2487
|
init_getDurationString();
|
|
2488
|
-
import {
|
|
2488
|
+
import {
|
|
2489
|
+
appendFileSync,
|
|
2490
|
+
existsSync as existsSync8,
|
|
2491
|
+
mkdirSync as mkdirSync4,
|
|
2492
|
+
readFileSync as readFileSync8,
|
|
2493
|
+
writeFileSync as writeFileSync2
|
|
2494
|
+
} from "fs";
|
|
2489
2495
|
import { createConnection } from "net";
|
|
2490
2496
|
import { resolve as resolve6 } from "path";
|
|
2491
2497
|
|
|
@@ -3127,7 +3133,44 @@ var createWorkspaceTui = ({
|
|
|
3127
3133
|
|
|
3128
3134
|
// src/cli/scripts/workspace.ts
|
|
3129
3135
|
init_utils();
|
|
3136
|
+
var ANSI_REGEX2 = /\x1B\[[0-?]*[ -/]*[@-~]/g;
|
|
3130
3137
|
var sleep = (ms) => new Promise((resolvePromise) => setTimeout(resolvePromise, ms));
|
|
3138
|
+
var stripAnsi2 = (value) => value.replace(ANSI_REGEX2, "");
|
|
3139
|
+
var sanitizeLogFileName = (value) => value.replace(/[^a-zA-Z0-9._-]/g, "_") || "unknown";
|
|
3140
|
+
var createWorkspaceLogSink = (appendLog) => {
|
|
3141
|
+
const logDirectory = resolve6(".absolutejs", "workspace", "logs");
|
|
3142
|
+
mkdirSync4(logDirectory, { recursive: true });
|
|
3143
|
+
for (const file of ["all.log", "workspace.log"]) {
|
|
3144
|
+
writeFileSync2(resolve6(logDirectory, file), "");
|
|
3145
|
+
}
|
|
3146
|
+
const initializedSources = new Set(["workspace"]);
|
|
3147
|
+
const writeLog = (source, message, level) => {
|
|
3148
|
+
const cleanMessage = stripAnsi2(message).trimEnd();
|
|
3149
|
+
if (!cleanMessage) {
|
|
3150
|
+
return;
|
|
3151
|
+
}
|
|
3152
|
+
const timestamp = new Date().toISOString();
|
|
3153
|
+
const line = `[${timestamp}] [${level}] [${source}] ${cleanMessage}
|
|
3154
|
+
`;
|
|
3155
|
+
const sourceFile = resolve6(logDirectory, `${sanitizeLogFileName(source)}.log`);
|
|
3156
|
+
if (!initializedSources.has(source)) {
|
|
3157
|
+
writeFileSync2(sourceFile, "");
|
|
3158
|
+
initializedSources.add(source);
|
|
3159
|
+
}
|
|
3160
|
+
appendFileSync(sourceFile, line);
|
|
3161
|
+
appendFileSync(resolve6(logDirectory, "all.log"), line);
|
|
3162
|
+
if (source === "workspace") {
|
|
3163
|
+
appendFileSync(resolve6(logDirectory, "workspace.log"), line);
|
|
3164
|
+
}
|
|
3165
|
+
};
|
|
3166
|
+
return {
|
|
3167
|
+
logDirectory,
|
|
3168
|
+
appendLog: (source, message, level = "info") => {
|
|
3169
|
+
writeLog(source, message, level);
|
|
3170
|
+
appendLog(source, message, level);
|
|
3171
|
+
}
|
|
3172
|
+
};
|
|
3173
|
+
};
|
|
3131
3174
|
var readPackageVersion2 = (candidate) => {
|
|
3132
3175
|
try {
|
|
3133
3176
|
const pkg = JSON.parse(readFileSync8(candidate, "utf-8"));
|
|
@@ -3320,6 +3363,51 @@ var waitForReady = async (service) => {
|
|
|
3320
3363
|
}
|
|
3321
3364
|
throw new Error(resolved.type === "http" ? `service did not become ready within ${resolved.timeoutMs}ms (${resolved.url})` : resolved.type === "tcp" ? `service did not become ready within ${resolved.timeoutMs}ms (tcp://${resolved.host}:${resolved.port})` : `service did not become ready within ${resolved.timeoutMs}ms (${resolved.command.join(" ")})`);
|
|
3322
3365
|
};
|
|
3366
|
+
var resolveShutdownHook = (shutdown) => {
|
|
3367
|
+
if (!shutdown) {
|
|
3368
|
+
return null;
|
|
3369
|
+
}
|
|
3370
|
+
if (Array.isArray(shutdown)) {
|
|
3371
|
+
return {
|
|
3372
|
+
command: shutdown,
|
|
3373
|
+
timeoutMs: 1e4
|
|
3374
|
+
};
|
|
3375
|
+
}
|
|
3376
|
+
return {
|
|
3377
|
+
command: shutdown.command,
|
|
3378
|
+
timeoutMs: shutdown.timeoutMs ?? 1e4
|
|
3379
|
+
};
|
|
3380
|
+
};
|
|
3381
|
+
var runShutdownHook = async (service, onLog) => {
|
|
3382
|
+
const hook = resolveShutdownHook(service.service.shutdown);
|
|
3383
|
+
if (!hook) {
|
|
3384
|
+
return;
|
|
3385
|
+
}
|
|
3386
|
+
onLog("workspace", `Running ${service.name} shutdown hook...`, "info");
|
|
3387
|
+
const processHandle = Bun.spawn(hook.command, {
|
|
3388
|
+
cwd: service.cwd,
|
|
3389
|
+
env: service.env,
|
|
3390
|
+
stderr: "pipe",
|
|
3391
|
+
stdin: "ignore",
|
|
3392
|
+
stdout: "pipe"
|
|
3393
|
+
});
|
|
3394
|
+
pipeProcessLogs(service.name, processHandle, onLog);
|
|
3395
|
+
const timeout = setTimeout(() => {
|
|
3396
|
+
try {
|
|
3397
|
+
processHandle.kill();
|
|
3398
|
+
} catch {}
|
|
3399
|
+
}, hook.timeoutMs);
|
|
3400
|
+
try {
|
|
3401
|
+
const exitCode = await processHandle.exited;
|
|
3402
|
+
if (exitCode === 0) {
|
|
3403
|
+
onLog("workspace", `${service.name} shutdown hook finished.`, "success");
|
|
3404
|
+
return;
|
|
3405
|
+
}
|
|
3406
|
+
onLog("workspace", `${service.name} shutdown hook exited with code ${exitCode || 1}.`, "warn");
|
|
3407
|
+
} finally {
|
|
3408
|
+
clearTimeout(timeout);
|
|
3409
|
+
}
|
|
3410
|
+
};
|
|
3323
3411
|
var topologicallySortServices = (services) => {
|
|
3324
3412
|
const ordered = [];
|
|
3325
3413
|
const visiting = new Set;
|
|
@@ -3487,6 +3575,9 @@ var workspace = async (subcommand, options) => {
|
|
|
3487
3575
|
}),
|
|
3488
3576
|
version: absoluteVersion
|
|
3489
3577
|
});
|
|
3578
|
+
const workspaceLogs = createWorkspaceLogSink(tui.addLog);
|
|
3579
|
+
const addLog = workspaceLogs.appendLog;
|
|
3580
|
+
addLog("workspace", `Writing workspace logs to ${workspaceLogs.logDirectory}`, "info");
|
|
3490
3581
|
const killProcesses = async () => {
|
|
3491
3582
|
const snapshot = [...running];
|
|
3492
3583
|
running.length = 0;
|
|
@@ -3496,6 +3587,14 @@ var workspace = async (subcommand, options) => {
|
|
|
3496
3587
|
} catch {}
|
|
3497
3588
|
}
|
|
3498
3589
|
await Promise.all(snapshot.map((service) => service.process.exited));
|
|
3590
|
+
for (const service of snapshot.reverse()) {
|
|
3591
|
+
try {
|
|
3592
|
+
await runShutdownHook(service.resolved, addLog);
|
|
3593
|
+
} catch (error) {
|
|
3594
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3595
|
+
addLog("workspace", `${service.name} shutdown hook failed: ${message}`, "warn");
|
|
3596
|
+
}
|
|
3597
|
+
}
|
|
3499
3598
|
};
|
|
3500
3599
|
const printFailureSummary = (exitCode) => {
|
|
3501
3600
|
const servicesSnapshot = tui.getServiceSnapshot();
|
|
@@ -3563,7 +3662,7 @@ var workspace = async (subcommand, options) => {
|
|
|
3563
3662
|
const port = (resolved.service.port ?? Number(resolved.env.PORT ?? "")) || DEFAULT_PORT;
|
|
3564
3663
|
if (port > 0) {
|
|
3565
3664
|
killStaleProcesses(port, (message) => {
|
|
3566
|
-
|
|
3665
|
+
addLog("workspace", message, "warn");
|
|
3567
3666
|
});
|
|
3568
3667
|
}
|
|
3569
3668
|
if (isAbsoluteService(resolved.service) && resolved.configPath && !existsSync8(resolved.configPath)) {
|
|
@@ -3578,7 +3677,7 @@ var workspace = async (subcommand, options) => {
|
|
|
3578
3677
|
stdin: "ignore",
|
|
3579
3678
|
stdout: "pipe"
|
|
3580
3679
|
});
|
|
3581
|
-
pipeProcessLogs(name, processHandle,
|
|
3680
|
+
pipeProcessLogs(name, processHandle, addLog);
|
|
3582
3681
|
const runningService = {
|
|
3583
3682
|
name,
|
|
3584
3683
|
process: processHandle,
|
|
@@ -3593,7 +3692,7 @@ var workspace = async (subcommand, options) => {
|
|
|
3593
3692
|
return;
|
|
3594
3693
|
}
|
|
3595
3694
|
tui.setServiceStatus(name, "error", `exit code ${exitCode || 1}`);
|
|
3596
|
-
|
|
3695
|
+
addLog("workspace", `${name} exited with code ${exitCode || 1}. Shutting down workspace.`, "error");
|
|
3597
3696
|
shutdown(exitCode || 1);
|
|
3598
3697
|
});
|
|
3599
3698
|
await waitForReady(resolved);
|
|
@@ -3613,7 +3712,7 @@ var workspace = async (subcommand, options) => {
|
|
|
3613
3712
|
}
|
|
3614
3713
|
paused = false;
|
|
3615
3714
|
}
|
|
3616
|
-
|
|
3715
|
+
addLog("workspace", "Restarting workspace...", "info");
|
|
3617
3716
|
for (const name of orderedNames) {
|
|
3618
3717
|
tui.setServiceStatus(name, "restarting");
|
|
3619
3718
|
}
|
|
@@ -3622,7 +3721,7 @@ var workspace = async (subcommand, options) => {
|
|
|
3622
3721
|
workspaceBootStartedAt = performance.now();
|
|
3623
3722
|
await startServices();
|
|
3624
3723
|
tui.setReadyDuration(performance.now() - workspaceBootStartedAt);
|
|
3625
|
-
|
|
3724
|
+
addLog("workspace", "Workspace ready.", "success");
|
|
3626
3725
|
};
|
|
3627
3726
|
const togglePause = () => {
|
|
3628
3727
|
if (paused) {
|
|
@@ -3631,14 +3730,14 @@ var workspace = async (subcommand, options) => {
|
|
|
3631
3730
|
tui.setServiceStatus(service.name, "ready");
|
|
3632
3731
|
}
|
|
3633
3732
|
paused = false;
|
|
3634
|
-
|
|
3733
|
+
addLog("workspace", "Workspace resumed.", "success");
|
|
3635
3734
|
} else {
|
|
3636
3735
|
for (const service of running) {
|
|
3637
3736
|
sendSignalToService(service.process, "SIGSTOP");
|
|
3638
3737
|
tui.setServiceStatus(service.name, "paused");
|
|
3639
3738
|
}
|
|
3640
3739
|
paused = true;
|
|
3641
|
-
|
|
3740
|
+
addLog("workspace", "Workspace paused.", "warn");
|
|
3642
3741
|
}
|
|
3643
3742
|
};
|
|
3644
3743
|
const runShellCommand2 = async (command) => {
|
|
@@ -3647,19 +3746,19 @@ var workspace = async (subcommand, options) => {
|
|
|
3647
3746
|
stderr: "pipe",
|
|
3648
3747
|
stdout: "pipe"
|
|
3649
3748
|
});
|
|
3650
|
-
pipeProcessLogs("shell", processHandle,
|
|
3749
|
+
pipeProcessLogs("shell", processHandle, addLog);
|
|
3651
3750
|
const exitCode = await processHandle.exited;
|
|
3652
3751
|
if (exitCode === 0) {
|
|
3653
|
-
|
|
3752
|
+
addLog("workspace", `Shell command finished: ${command}`, "success");
|
|
3654
3753
|
return;
|
|
3655
3754
|
}
|
|
3656
|
-
|
|
3755
|
+
addLog("workspace", `Shell command failed with exit code ${exitCode}: ${command}`, "error");
|
|
3657
3756
|
};
|
|
3658
3757
|
const openInBrowser = async () => {
|
|
3659
3758
|
const publicService = orderedNames.map((name) => services[name]).find((service) => service && getVisibility(service) === "public");
|
|
3660
3759
|
const url = publicService ? getServiceUrl(publicService) : null;
|
|
3661
3760
|
if (!url) {
|
|
3662
|
-
|
|
3761
|
+
addLog("workspace", "No public service to open.", "warn");
|
|
3663
3762
|
return;
|
|
3664
3763
|
}
|
|
3665
3764
|
const { platform: platform4 } = process;
|
|
@@ -3680,9 +3779,9 @@ var workspace = async (subcommand, options) => {
|
|
|
3680
3779
|
stderr: "ignore",
|
|
3681
3780
|
stdout: "ignore"
|
|
3682
3781
|
});
|
|
3683
|
-
|
|
3782
|
+
addLog("workspace", `Opening ${url}`, "info");
|
|
3684
3783
|
} catch {
|
|
3685
|
-
|
|
3784
|
+
addLog("workspace", `Could not open browser automatically. Visit ${url}`, "warn");
|
|
3686
3785
|
}
|
|
3687
3786
|
};
|
|
3688
3787
|
process.on("SIGINT", () => {
|
|
@@ -3692,10 +3791,10 @@ var workspace = async (subcommand, options) => {
|
|
|
3692
3791
|
shutdown(0);
|
|
3693
3792
|
});
|
|
3694
3793
|
tui.start();
|
|
3695
|
-
|
|
3794
|
+
addLog("workspace", `Workspace booting ${orderedNames.length} services.`, "info");
|
|
3696
3795
|
await startServices();
|
|
3697
3796
|
tui.setReadyDuration(performance.now() - workspaceBootStartedAt);
|
|
3698
|
-
|
|
3797
|
+
addLog("workspace", "Workspace ready.", "success");
|
|
3699
3798
|
await new Promise(() => {});
|
|
3700
3799
|
};
|
|
3701
3800
|
|
package/dist/types/build.d.ts
CHANGED
|
@@ -51,6 +51,10 @@ export type DelayReadyConfig = {
|
|
|
51
51
|
ms: number;
|
|
52
52
|
};
|
|
53
53
|
export type ServiceReadyConfig = false | string | HttpReadyConfig | TcpReadyConfig | CommandReadyConfig | DelayReadyConfig;
|
|
54
|
+
export type ServiceShutdownConfig = false | string[] | {
|
|
55
|
+
command: string[];
|
|
56
|
+
timeoutMs?: number;
|
|
57
|
+
};
|
|
54
58
|
export type ServiceVisibility = 'public' | 'internal';
|
|
55
59
|
export type BaseBuildConfig = {
|
|
56
60
|
buildDirectory?: string;
|
|
@@ -96,6 +100,7 @@ export type AbsoluteServiceConfig = BaseBuildConfig & {
|
|
|
96
100
|
entry?: string;
|
|
97
101
|
env?: Record<string, string>;
|
|
98
102
|
ready?: ServiceReadyConfig;
|
|
103
|
+
shutdown?: ServiceShutdownConfig;
|
|
99
104
|
port?: number;
|
|
100
105
|
visibility?: ServiceVisibility;
|
|
101
106
|
command?: never;
|
|
@@ -107,6 +112,7 @@ export type CommandServiceConfig = {
|
|
|
107
112
|
dependsOn?: string[];
|
|
108
113
|
env?: Record<string, string>;
|
|
109
114
|
ready?: ServiceReadyConfig;
|
|
115
|
+
shutdown?: ServiceShutdownConfig;
|
|
110
116
|
port?: number;
|
|
111
117
|
visibility?: ServiceVisibility;
|
|
112
118
|
entry?: never;
|
package/package.json
CHANGED