@absolutejs/absolute 0.19.0-beta.703 → 0.19.0-beta.705
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/angular/components/constants.js +21 -0
- package/dist/angular/index.js +53 -73
- package/dist/angular/index.js.map +9 -9
- package/dist/angular/server.js +52 -72
- package/dist/angular/server.js.map +9 -9
- package/dist/build.js +8 -7
- package/dist/build.js.map +7 -7
- package/dist/cli/index.js +320 -284
- package/dist/client/index.js +4 -3
- package/dist/client/index.js.map +3 -3
- package/dist/index.js +96 -63
- package/dist/index.js.map +15 -15
- package/dist/islands/index.js +5 -4
- package/dist/islands/index.js.map +5 -5
- package/dist/react/index.js +49 -69
- package/dist/react/index.js.map +9 -9
- package/dist/react/jsxDevRuntimeCompat.js +1 -6
- package/dist/react/jsxDevRuntimeCompat.js.map +3 -3
- package/dist/react/server.js +43 -64
- package/dist/react/server.js.map +7 -7
- package/dist/src/angular/components/constants.d.ts +21 -0
- package/dist/src/angular/pageHandler.d.ts +6 -1
- package/dist/src/angular/ssrRender.d.ts +1 -1
- package/dist/src/constants.d.ts +21 -0
- package/dist/src/core/ssrCache.d.ts +1 -1
- package/dist/src/core/wrapPageHandlerWithStreamingSlots.d.ts +1 -1
- package/dist/src/react/jsxDevRuntimeCompat.d.ts +3 -6
- package/dist/src/react/pageHandler.d.ts +2 -1
- package/dist/src/svelte/pageHandler.d.ts +2 -2
- package/dist/src/utils/defineConfig.d.ts +2 -2
- package/dist/src/utils/loadConfig.d.ts +38 -2
- package/dist/src/vue/components/Image.d.ts +2 -2
- package/dist/src/vue/components/index.d.ts +1 -1
- package/dist/src/vue/index.d.ts +1 -1
- package/dist/src/vue/pageHandler.d.ts +2 -1
- package/dist/svelte/index.js +34 -49
- package/dist/svelte/index.js.map +9 -9
- package/dist/svelte/server.js +31 -47
- package/dist/svelte/server.js.map +8 -8
- package/dist/vue/components/Image.js +18 -18
- package/dist/vue/components/Image.js.map +3 -3
- package/dist/vue/components/index.js +77 -62
- package/dist/vue/components/index.js.map +5 -5
- package/dist/vue/index.js +119 -133
- package/dist/vue/index.js.map +12 -12
- package/dist/vue/server.js +40 -70
- package/dist/vue/server.js.map +7 -7
- package/package.json +48 -48
package/dist/cli/index.js
CHANGED
|
@@ -18,7 +18,7 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
|
18
18
|
var __require = import.meta.require;
|
|
19
19
|
|
|
20
20
|
// src/constants.ts
|
|
21
|
-
var ANSI_ESCAPE_LENGTH = 3, ASCII_SPACE = 32, BASE_36_RADIX = 36, BYTES_PER_KILOBYTE = 1024, CLI_ARGS_OFFSET = 3, DEFAULT_PORT = 3000, HOURS_IN_DAY = 24, HOURS_IN_HALF_DAY = 12, MAX_ERROR_LENGTH = 200, MILLISECONDS_IN_A_SECOND = 1000, MINUTES_IN_AN_HOUR = 60, SECONDS_IN_A_MINUTE = 60, MILLISECONDS_IN_A_MINUTE, MILLISECONDS_IN_A_DAY, SIGINT_EXIT_CODE = 130, SIGTERM_EXIT_CODE = 143, TIME_PRECISION = 2, TWO_THIRDS, UNFOUND_INDEX = -1;
|
|
21
|
+
var ANSI_ESCAPE_LENGTH = 3, ASCII_SPACE = 32, BASE_36_RADIX = 36, BYTES_PER_KILOBYTE = 1024, CLI_ARGS_OFFSET = 3, DEFAULT_PORT = 3000, HTTP_STATUS_OK = 200, HOURS_IN_DAY = 24, HOURS_IN_HALF_DAY = 12, MAX_ERROR_LENGTH = 200, MILLISECONDS_IN_A_SECOND = 1000, MINUTES_IN_AN_HOUR = 60, SECONDS_IN_A_MINUTE = 60, MILLISECONDS_IN_A_MINUTE, MILLISECONDS_IN_A_DAY, SIGINT_EXIT_CODE = 130, SIGTERM_EXIT_CODE = 143, TIME_PRECISION = 2, TWO_THIRDS, UNFOUND_INDEX = -1, WORKSPACE_COMMAND_ARGS_OFFSET = 3, WORKSPACE_FAILURE_LOG_PRINT_LIMIT = 30, WORKSPACE_FAILURE_RECENT_LOG_LIMIT = 60, WORKSPACE_READY_ATTEMPT_TIMEOUT_MS = 5000, WORKSPACE_READY_PROBE_INTERVAL_MS = 250, WORKSPACE_READY_TIMEOUT_MS = 30000, WORKSPACE_SHUTDOWN_TIMEOUT_MS = 1e4, WORKSPACE_TUI_DEFAULT_HEIGHT = 28, WORKSPACE_TUI_DEFAULT_WIDTH = 100, WORKSPACE_TUI_ESCAPE_SEQUENCE_TIMEOUT_MS = 30, WORKSPACE_TUI_FOOTER_LINE_COUNT = 3, WORKSPACE_TUI_MIN_LOG_HEIGHT = 3, WORKSPACE_TUI_MIN_SERVICE_NAME_WIDTH = 7, WORKSPACE_TUI_MIN_TARGET_WIDTH = 8, WORKSPACE_TUI_MIN_WRAP_WIDTH = 12, WORKSPACE_TUI_PROMPT_CURSOR_OFFSET = 3, WORKSPACE_TUI_RECENT_LOG_LIMIT = 40, WORKSPACE_TUI_RENDER_DEBOUNCE_MS = 16, WORKSPACE_TUI_STATUS_WIDTH = 10, WORKSPACE_TUI_TARGET_PADDING_WIDTH = 6, WORKSPACE_TUI_VISIBILITY_WIDTH = 8;
|
|
22
22
|
var init_constants = __esm(() => {
|
|
23
23
|
MILLISECONDS_IN_A_MINUTE = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE;
|
|
24
24
|
MILLISECONDS_IN_A_DAY = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE * MINUTES_IN_AN_HOUR * HOURS_IN_DAY;
|
|
@@ -222,7 +222,7 @@ var RESERVED_TOP_LEVEL_KEYS, isObject = (value) => typeof value === "object" &&
|
|
|
222
222
|
return false;
|
|
223
223
|
}
|
|
224
224
|
return entries.every(([, value]) => isServiceCandidate(value));
|
|
225
|
-
}, getWorkspaceServices = (config) => {
|
|
225
|
+
}, isConfigInput = (value) => isObject(value), getWorkspaceServices = (config) => {
|
|
226
226
|
if (!isWorkspaceConfig(config)) {
|
|
227
227
|
throw new Error("absolute.config.ts is not a multi-service config. Define top-level named services with `entry` or `command` before using `absolute workspace dev`.");
|
|
228
228
|
}
|
|
@@ -249,6 +249,16 @@ var RESERVED_TOP_LEVEL_KEYS, isObject = (value) => typeof value === "object" &&
|
|
|
249
249
|
...serviceConfig
|
|
250
250
|
} = service;
|
|
251
251
|
return serviceConfig;
|
|
252
|
+
}, loadConfig = async (configPath2) => {
|
|
253
|
+
const config = await loadRawConfig(configPath2);
|
|
254
|
+
const serviceName = process.env.ABSOLUTE_WORKSPACE_SERVICE_NAME;
|
|
255
|
+
if (typeof serviceName === "string" && serviceName.length > 0) {
|
|
256
|
+
return projectServiceConfig(config, serviceName);
|
|
257
|
+
}
|
|
258
|
+
if (isWorkspaceConfig(config)) {
|
|
259
|
+
throw new Error("absolute.config.ts defines multiple services. Use `absolute workspace dev` or set ABSOLUTE_WORKSPACE_SERVICE_NAME before loading a specific service config.");
|
|
260
|
+
}
|
|
261
|
+
return config;
|
|
252
262
|
}, loadRawConfig = async (configPath2) => {
|
|
253
263
|
const resolved = resolve(configPath2 ?? process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
|
|
254
264
|
const mod = await import(resolved);
|
|
@@ -257,20 +267,10 @@ var RESERVED_TOP_LEVEL_KEYS, isObject = (value) => typeof value === "object" &&
|
|
|
257
267
|
throw new Error(`Config file "${resolved}" does not export a valid configuration.
|
|
258
268
|
Expected: export default defineConfig({ ... })`);
|
|
259
269
|
}
|
|
260
|
-
if (!
|
|
270
|
+
if (!isConfigInput(config)) {
|
|
261
271
|
throw new Error(`Config file "${resolved}" must export an object configuration.`);
|
|
262
272
|
}
|
|
263
273
|
return config;
|
|
264
|
-
}, loadConfig = async (configPath2) => {
|
|
265
|
-
const config = await loadRawConfig(configPath2);
|
|
266
|
-
const serviceName = process.env.ABSOLUTE_WORKSPACE_SERVICE_NAME;
|
|
267
|
-
if (typeof serviceName === "string" && serviceName.length > 0) {
|
|
268
|
-
return projectServiceConfig(config, serviceName);
|
|
269
|
-
}
|
|
270
|
-
if (isWorkspaceConfig(config)) {
|
|
271
|
-
throw new Error("absolute.config.ts defines multiple services. Use `absolute workspace dev` or set ABSOLUTE_WORKSPACE_SERVICE_NAME before loading a specific service config.");
|
|
272
|
-
}
|
|
273
|
-
return config;
|
|
274
274
|
};
|
|
275
275
|
var init_loadConfig = __esm(() => {
|
|
276
276
|
RESERVED_TOP_LEVEL_KEYS = new Set([
|
|
@@ -629,7 +629,7 @@ __export(exports_prerender, {
|
|
|
629
629
|
});
|
|
630
630
|
import { mkdirSync as mkdirSync3, readFileSync as readFileSync6 } from "fs";
|
|
631
631
|
import { join as join5 } from "path";
|
|
632
|
-
var SERVER_OUTPUT_LIMIT = 4000,
|
|
632
|
+
var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_TIMEOUT_MS = 30000, PRERENDER_BYPASS_HEADER = "X-Absolute-Prerender-Bypass", routeToFilename = (route) => route === "/" ? "index.html" : `${route.slice(1).replace(/\//g, "-")}.html`, writeTimestamp = async (htmlPath) => {
|
|
633
633
|
const metaPath = htmlPath.replace(/\.html$/, ".meta");
|
|
634
634
|
await Bun.write(metaPath, String(Date.now()));
|
|
635
635
|
}, readTimestamp = (htmlPath) => {
|
|
@@ -727,14 +727,28 @@ var SERVER_OUTPUT_LIMIT = 4000, MAX_STARTUP_ATTEMPTS = 50, STARTUP_POLL_INTERVAL
|
|
|
727
727
|
await prerenderRoute(baseUrl, route, prerenderDir, result, log);
|
|
728
728
|
}
|
|
729
729
|
return result;
|
|
730
|
+
}, getStartupTimeoutMs = () => {
|
|
731
|
+
const rawTimeout = Bun.env.ABSOLUTE_PRERENDER_STARTUP_TIMEOUT_MS;
|
|
732
|
+
const parsedTimeout = rawTimeout ? Number(rawTimeout) : NaN;
|
|
733
|
+
return Number.isFinite(parsedTimeout) && parsedTimeout > 0 ? parsedTimeout : DEFAULT_STARTUP_TIMEOUT_MS;
|
|
730
734
|
}, waitForServerReady = async (port) => {
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
if (
|
|
735
|
+
const deadline = performance.now() + getStartupTimeoutMs();
|
|
736
|
+
while (performance.now() < deadline) {
|
|
737
|
+
if (await probePrerenderServer(port)) {
|
|
734
738
|
return true;
|
|
739
|
+
}
|
|
735
740
|
await Bun.sleep(STARTUP_POLL_INTERVAL_MS);
|
|
736
741
|
}
|
|
737
742
|
return false;
|
|
743
|
+
}, probePrerenderServer = async (port) => {
|
|
744
|
+
const res = await fetch(`http://localhost:${port}/`).catch(() => null);
|
|
745
|
+
if (!res) {
|
|
746
|
+
return false;
|
|
747
|
+
}
|
|
748
|
+
await res.body?.cancel().catch(() => {
|
|
749
|
+
return;
|
|
750
|
+
});
|
|
751
|
+
return true;
|
|
738
752
|
}, captureStreamOutput = (stream, output) => {
|
|
739
753
|
if (!stream)
|
|
740
754
|
return;
|
|
@@ -813,7 +827,7 @@ var cliTag3 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
813
827
|
result.push(fullPath);
|
|
814
828
|
}
|
|
815
829
|
return result;
|
|
816
|
-
},
|
|
830
|
+
}, readPackageVersion4 = (candidate) => {
|
|
817
831
|
try {
|
|
818
832
|
const pkg = JSON.parse(readFileSync9(candidate, "utf-8"));
|
|
819
833
|
if (pkg.name !== "@absolutejs/absolute")
|
|
@@ -825,7 +839,7 @@ var cliTag3 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
825
839
|
}
|
|
826
840
|
}, resolvePackageVersion3 = (candidates) => {
|
|
827
841
|
for (const candidate of candidates) {
|
|
828
|
-
const version2 =
|
|
842
|
+
const version2 = readPackageVersion4(candidate);
|
|
829
843
|
if (version2)
|
|
830
844
|
return version2;
|
|
831
845
|
}
|
|
@@ -1339,15 +1353,11 @@ Found ${errorCount} error${suffix}.`;
|
|
|
1339
1353
|
await mkdir2(cacheDir, { recursive: true });
|
|
1340
1354
|
const checks = [];
|
|
1341
1355
|
checks.push(hasVue ? buildVueTscCheck(cacheDir) : buildTscCheck(cacheDir));
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
checks.push(buildSvelteCheck(cacheDir, svelteDir));
|
|
1345
|
-
}
|
|
1356
|
+
for (const svelteDir of hasSvelte ? svelteDirs : []) {
|
|
1357
|
+
checks.push(buildSvelteCheck(cacheDir, svelteDir));
|
|
1346
1358
|
}
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
checks.push(buildAngularCheck(cacheDir, angularDir));
|
|
1350
|
-
}
|
|
1359
|
+
for (const angularDir of hasAngular ? angularDirs : []) {
|
|
1360
|
+
checks.push(buildAngularCheck(cacheDir, angularDir));
|
|
1351
1361
|
}
|
|
1352
1362
|
const results = await Promise.all(checks);
|
|
1353
1363
|
const failed = results.filter((res) => res.exitCode !== 0);
|
|
@@ -1990,18 +2000,19 @@ var getAbsoluteVersion = () => {
|
|
|
1990
2000
|
resolve4(import.meta.dir, "..", "..", "package.json"),
|
|
1991
2001
|
resolve4(import.meta.dir, "..", "..", "..", "package.json")
|
|
1992
2002
|
];
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
|
|
1997
|
-
const ver = pkg.version;
|
|
1998
|
-
return ver;
|
|
1999
|
-
}
|
|
2003
|
+
const pkgPath = candidates.find((candidate) => existsSync6(candidate));
|
|
2004
|
+
if (pkgPath)
|
|
2005
|
+
return readPackageVersion(pkgPath);
|
|
2000
2006
|
} catch {
|
|
2001
2007
|
return getPackageVersion("@absolutejs/absolute");
|
|
2002
2008
|
}
|
|
2003
2009
|
return getPackageVersion("@absolutejs/absolute");
|
|
2004
2010
|
};
|
|
2011
|
+
var readPackageVersion = (pkgPath) => {
|
|
2012
|
+
const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
|
|
2013
|
+
const ver = pkg.version;
|
|
2014
|
+
return ver;
|
|
2015
|
+
};
|
|
2005
2016
|
var detectCI = () => {
|
|
2006
2017
|
const { env: env2 } = process;
|
|
2007
2018
|
if (env2.GITHUB_ACTIONS)
|
|
@@ -2249,14 +2260,14 @@ import { basename, resolve as resolve5 } from "path";
|
|
|
2249
2260
|
var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[cli]\x1B[0m ${color}${message}\x1B[0m`;
|
|
2250
2261
|
var resolvePackageVersion = (candidates) => {
|
|
2251
2262
|
for (const candidate of candidates) {
|
|
2252
|
-
const version2 =
|
|
2263
|
+
const version2 = readPackageVersion2(candidate);
|
|
2253
2264
|
if (version2) {
|
|
2254
2265
|
return version2;
|
|
2255
2266
|
}
|
|
2256
2267
|
}
|
|
2257
2268
|
return "";
|
|
2258
2269
|
};
|
|
2259
|
-
var
|
|
2270
|
+
var readPackageVersion2 = (candidate) => {
|
|
2260
2271
|
try {
|
|
2261
2272
|
const pkg = JSON.parse(readFileSync7(candidate, "utf-8"));
|
|
2262
2273
|
if (pkg.name !== "@absolutejs/absolute")
|
|
@@ -2650,54 +2661,49 @@ var appendRightEdge = (value, width, marker) => {
|
|
|
2650
2661
|
}
|
|
2651
2662
|
return `${padLine(value, Math.max(0, width - 1))}${marker}`;
|
|
2652
2663
|
};
|
|
2664
|
+
var splitLongWord = (word, width) => {
|
|
2665
|
+
const parts = [];
|
|
2666
|
+
for (let index = 0;index < word.length; index += width) {
|
|
2667
|
+
parts.push(word.slice(index, index + width));
|
|
2668
|
+
}
|
|
2669
|
+
return parts;
|
|
2670
|
+
};
|
|
2671
|
+
var appendWrappedWord = (lines, current, word, width) => {
|
|
2672
|
+
if (current.length === 0) {
|
|
2673
|
+
if (word.length <= width)
|
|
2674
|
+
return word;
|
|
2675
|
+
lines.push(...splitLongWord(word, width));
|
|
2676
|
+
return "";
|
|
2677
|
+
}
|
|
2678
|
+
const next = `${current} ${word}`;
|
|
2679
|
+
if (next.length <= width)
|
|
2680
|
+
return next;
|
|
2681
|
+
lines.push(current);
|
|
2682
|
+
if (word.length <= width)
|
|
2683
|
+
return word;
|
|
2684
|
+
lines.push(...splitLongWord(word, width));
|
|
2685
|
+
return "";
|
|
2686
|
+
};
|
|
2687
|
+
var wrapLine = (line, width) => {
|
|
2688
|
+
if (line.length === 0)
|
|
2689
|
+
return [""];
|
|
2690
|
+
if (line.length <= width)
|
|
2691
|
+
return [line];
|
|
2692
|
+
const lines = [];
|
|
2693
|
+
let current = "";
|
|
2694
|
+
for (const word of line.split(/\s+/)) {
|
|
2695
|
+
current = appendWrappedWord(lines, current, word, width);
|
|
2696
|
+
}
|
|
2697
|
+
if (current.length > 0)
|
|
2698
|
+
lines.push(current);
|
|
2699
|
+
return lines;
|
|
2700
|
+
};
|
|
2653
2701
|
var wrapText = (value, width) => {
|
|
2654
2702
|
if (width <= 0) {
|
|
2655
2703
|
return [""];
|
|
2656
2704
|
}
|
|
2657
|
-
const lines =
|
|
2658
|
-
|
|
2659
|
-
`)) {
|
|
2660
|
-
const line = rawLine.trimEnd();
|
|
2661
|
-
if (line.length === 0) {
|
|
2662
|
-
lines.push("");
|
|
2663
|
-
continue;
|
|
2664
|
-
}
|
|
2665
|
-
if (line.length <= width) {
|
|
2666
|
-
lines.push(line);
|
|
2667
|
-
continue;
|
|
2668
|
-
}
|
|
2669
|
-
const words = line.split(/\s+/);
|
|
2670
|
-
let current = "";
|
|
2671
|
-
for (const word of words) {
|
|
2672
|
-
if (current.length === 0) {
|
|
2673
|
-
if (word.length <= width) {
|
|
2674
|
-
current = word;
|
|
2675
|
-
continue;
|
|
2676
|
-
}
|
|
2677
|
-
for (let index = 0;index < word.length; index += width) {
|
|
2678
|
-
lines.push(word.slice(index, index + width));
|
|
2679
|
-
}
|
|
2680
|
-
continue;
|
|
2681
|
-
}
|
|
2682
|
-
const next = `${current} ${word}`;
|
|
2683
|
-
if (next.length <= width) {
|
|
2684
|
-
current = next;
|
|
2685
|
-
continue;
|
|
2686
|
-
}
|
|
2687
|
-
lines.push(current);
|
|
2688
|
-
if (word.length <= width) {
|
|
2689
|
-
current = word;
|
|
2690
|
-
continue;
|
|
2691
|
-
}
|
|
2692
|
-
for (let index = 0;index < word.length; index += width) {
|
|
2693
|
-
lines.push(word.slice(index, index + width));
|
|
2694
|
-
}
|
|
2695
|
-
current = "";
|
|
2696
|
-
}
|
|
2697
|
-
if (current.length > 0) {
|
|
2698
|
-
lines.push(current);
|
|
2699
|
-
}
|
|
2700
|
-
}
|
|
2705
|
+
const lines = value.split(`
|
|
2706
|
+
`).flatMap((rawLine) => wrapLine(rawLine.trimEnd(), width));
|
|
2701
2707
|
return lines.length > 0 ? lines : [""];
|
|
2702
2708
|
};
|
|
2703
2709
|
var formatTimestamp2 = () => new Date().toLocaleTimeString([], {
|
|
@@ -2802,7 +2808,7 @@ var createWorkspaceTui = ({
|
|
|
2802
2808
|
renderTimer = setTimeout(() => {
|
|
2803
2809
|
renderTimer = null;
|
|
2804
2810
|
render();
|
|
2805
|
-
},
|
|
2811
|
+
}, WORKSPACE_TUI_RENDER_DEBOUNCE_MS);
|
|
2806
2812
|
};
|
|
2807
2813
|
const clearPendingEscape = () => {
|
|
2808
2814
|
if (!escapeTimer) {
|
|
@@ -2817,7 +2823,7 @@ var createWorkspaceTui = ({
|
|
|
2817
2823
|
escapeTimer = null;
|
|
2818
2824
|
escapeBuffer = "";
|
|
2819
2825
|
exitEscapeMode();
|
|
2820
|
-
},
|
|
2826
|
+
}, WORKSPACE_TUI_ESCAPE_SEQUENCE_TIMEOUT_MS);
|
|
2821
2827
|
};
|
|
2822
2828
|
const resetPrompt = () => {
|
|
2823
2829
|
promptBuffer = "";
|
|
@@ -2839,16 +2845,16 @@ var createWorkspaceTui = ({
|
|
|
2839
2845
|
if (disposed) {
|
|
2840
2846
|
return;
|
|
2841
2847
|
}
|
|
2842
|
-
const width = process.stdout.columns ??
|
|
2843
|
-
const height = process.stdout.rows ??
|
|
2848
|
+
const width = process.stdout.columns ?? WORKSPACE_TUI_DEFAULT_WIDTH;
|
|
2849
|
+
const height = process.stdout.rows ?? WORKSPACE_TUI_DEFAULT_HEIGHT;
|
|
2844
2850
|
const servicesSnapshot = [...serviceStates.values()];
|
|
2845
2851
|
const workspaceStatus = getWorkspaceStatus(servicesSnapshot);
|
|
2846
2852
|
const statusLabel = workspaceStatus === "ready" && readyDurationMs !== null ? `${colors.dim}ready in${colors.reset} ${colors.bold}${getDurationString(readyDurationMs)}${colors.reset}` : `${colors.dim}${workspaceStatus}${colors.reset}`;
|
|
2847
2853
|
const title = `${colors.cyan}${colors.bold}ABSOLUTEJS WORKSPACE${colors.reset} ${colors.dim}v${version2}${colors.reset} ${statusLabel}`;
|
|
2848
2854
|
const divider = `${colors.dim}${"\u2500".repeat(Math.max(width, 1))}${colors.reset}`;
|
|
2849
|
-
const serviceNameWidth = Math.max(
|
|
2850
|
-
const visibilityWidth =
|
|
2851
|
-
const statusWidth =
|
|
2855
|
+
const serviceNameWidth = Math.max(WORKSPACE_TUI_MIN_SERVICE_NAME_WIDTH, ...servicesSnapshot.map((service) => service.name.length));
|
|
2856
|
+
const visibilityWidth = WORKSPACE_TUI_VISIBILITY_WIDTH;
|
|
2857
|
+
const statusWidth = WORKSPACE_TUI_STATUS_WIDTH;
|
|
2852
2858
|
const rows = [];
|
|
2853
2859
|
rows.push(padLine(title, width));
|
|
2854
2860
|
rows.push(divider);
|
|
@@ -2856,21 +2862,21 @@ var createWorkspaceTui = ({
|
|
|
2856
2862
|
for (const service of servicesSnapshot) {
|
|
2857
2863
|
const stateColor = getStatusColor(service.status);
|
|
2858
2864
|
const detail = service.detail ? ` \xB7 ${service.detail}` : "";
|
|
2859
|
-
const targetWidth = Math.max(width - serviceNameWidth - visibilityWidth - statusWidth -
|
|
2865
|
+
const targetWidth = Math.max(width - serviceNameWidth - visibilityWidth - statusWidth - WORKSPACE_TUI_TARGET_PADDING_WIDTH, WORKSPACE_TUI_MIN_TARGET_WIDTH);
|
|
2860
2866
|
const target = truncateText(`${getTargetLabel(service)}${detail}`, targetWidth);
|
|
2861
2867
|
const targetColor = service.visibility === "public" && service.status !== "ready" ? colors.dim : colors.reset;
|
|
2862
2868
|
const row = `${colors.bold}${service.name.padEnd(serviceNameWidth)}${colors.reset} ${colors.dim}${service.visibility.padEnd(visibilityWidth)}${colors.reset} ${stateColor}${service.status.padEnd(statusWidth)}${colors.reset} ${targetColor}${target}${colors.reset}`;
|
|
2863
2869
|
rows.push(padLine(row, width));
|
|
2864
2870
|
}
|
|
2865
2871
|
rows.push(divider);
|
|
2866
|
-
const footerLines =
|
|
2872
|
+
const footerLines = WORKSPACE_TUI_FOOTER_LINE_COUNT;
|
|
2867
2873
|
const fixedHeight = rows.length + footerLines;
|
|
2868
|
-
const logHeight = Math.max(height - fixedHeight,
|
|
2874
|
+
const logHeight = Math.max(height - fixedHeight, WORKSPACE_TUI_MIN_LOG_HEIGHT);
|
|
2869
2875
|
const logWidth = Math.max(width - 1, 1);
|
|
2870
2876
|
const contentLines = helpVisible ? helpLines : logEntries.flatMap((entry) => {
|
|
2871
2877
|
const prefixPlain = `${entry.timestamp} [${entry.source}] `;
|
|
2872
2878
|
const prefixColor = `${colors.dim}${entry.timestamp}${colors.reset} ${getSourceColor(entry.source)}[${entry.source}]${colors.reset} `;
|
|
2873
|
-
const wrapped = wrapText(entry.message, Math.max(logWidth - prefixPlain.length,
|
|
2879
|
+
const wrapped = wrapText(entry.message, Math.max(logWidth - prefixPlain.length, WORKSPACE_TUI_MIN_WRAP_WIDTH));
|
|
2874
2880
|
return wrapped.map((line, index) => {
|
|
2875
2881
|
if (index === 0) {
|
|
2876
2882
|
return `${prefixColor}${getLogColor(entry.level)}${line}${colors.reset}`;
|
|
@@ -2918,7 +2924,7 @@ var createWorkspaceTui = ({
|
|
|
2918
2924
|
`);
|
|
2919
2925
|
process.stdout.write(`\x1B[H${screen}`);
|
|
2920
2926
|
if (shellMode) {
|
|
2921
|
-
const promptColumn = Math.min(promptBuffer.length +
|
|
2927
|
+
const promptColumn = Math.min(promptBuffer.length + WORKSPACE_TUI_PROMPT_CURSOR_OFFSET, width);
|
|
2922
2928
|
const promptRow = Math.min(rows.length, height);
|
|
2923
2929
|
process.stdout.write(`\x1B[${promptRow};${promptColumn}H\x1B[?25h`);
|
|
2924
2930
|
return;
|
|
@@ -2962,7 +2968,7 @@ var createWorkspaceTui = ({
|
|
|
2962
2968
|
logScrollOffset = 0;
|
|
2963
2969
|
scheduleRender();
|
|
2964
2970
|
};
|
|
2965
|
-
const getRecentLogs = (limit =
|
|
2971
|
+
const getRecentLogs = (limit = WORKSPACE_TUI_RECENT_LOG_LIMIT) => logEntries.slice(Math.max(0, logEntries.length - limit));
|
|
2966
2972
|
const getServiceSnapshot = () => [...serviceStates.values()].map((service) => ({
|
|
2967
2973
|
detail: service.detail,
|
|
2968
2974
|
name: service.name,
|
|
@@ -2974,21 +2980,35 @@ var createWorkspaceTui = ({
|
|
|
2974
2980
|
if (!shellMode || shellHistory.length === 0) {
|
|
2975
2981
|
return;
|
|
2976
2982
|
}
|
|
2977
|
-
if (direction === "up") {
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
} else if (shellHistoryIndex <= 0) {
|
|
2983
|
+
if (direction === "up" && shellHistoryIndex < shellHistory.length - 1) {
|
|
2984
|
+
shellHistoryIndex++;
|
|
2985
|
+
}
|
|
2986
|
+
if (direction === "down" && shellHistoryIndex <= 0) {
|
|
2982
2987
|
shellHistoryIndex = UNFOUND_INDEX;
|
|
2983
2988
|
promptBuffer = "";
|
|
2984
2989
|
scheduleRender();
|
|
2985
2990
|
return;
|
|
2986
|
-
}
|
|
2991
|
+
}
|
|
2992
|
+
if (direction === "down") {
|
|
2987
2993
|
shellHistoryIndex--;
|
|
2988
2994
|
}
|
|
2989
2995
|
promptBuffer = shellHistoryIndex === UNFOUND_INDEX ? "" : shellHistory[shellHistory.length - 1 - shellHistoryIndex] ?? "";
|
|
2990
2996
|
scheduleRender();
|
|
2991
2997
|
};
|
|
2998
|
+
const handleArrowEscape = (direction) => {
|
|
2999
|
+
clearPendingEscape();
|
|
3000
|
+
escapeBuffer = "";
|
|
3001
|
+
if (shellMode) {
|
|
3002
|
+
navigateShellHistory(direction);
|
|
3003
|
+
return;
|
|
3004
|
+
}
|
|
3005
|
+
scrollLogs(direction);
|
|
3006
|
+
};
|
|
3007
|
+
const handleScrollEscape = (mode) => {
|
|
3008
|
+
clearPendingEscape();
|
|
3009
|
+
escapeBuffer = "";
|
|
3010
|
+
scrollLogs(mode);
|
|
3011
|
+
};
|
|
2992
3012
|
const scrollLogs = (direction) => {
|
|
2993
3013
|
if (helpVisible) {
|
|
2994
3014
|
return;
|
|
@@ -3043,47 +3063,27 @@ var createWorkspaceTui = ({
|
|
|
3043
3063
|
return;
|
|
3044
3064
|
}
|
|
3045
3065
|
if (escapeBuffer === `${ESCAPE}[A`) {
|
|
3046
|
-
|
|
3047
|
-
escapeBuffer = "";
|
|
3048
|
-
if (shellMode) {
|
|
3049
|
-
navigateShellHistory("up");
|
|
3050
|
-
} else {
|
|
3051
|
-
scrollLogs("up");
|
|
3052
|
-
}
|
|
3066
|
+
handleArrowEscape("up");
|
|
3053
3067
|
return;
|
|
3054
3068
|
}
|
|
3055
3069
|
if (escapeBuffer === `${ESCAPE}[B`) {
|
|
3056
|
-
|
|
3057
|
-
escapeBuffer = "";
|
|
3058
|
-
if (shellMode) {
|
|
3059
|
-
navigateShellHistory("down");
|
|
3060
|
-
} else {
|
|
3061
|
-
scrollLogs("down");
|
|
3062
|
-
}
|
|
3070
|
+
handleArrowEscape("down");
|
|
3063
3071
|
return;
|
|
3064
3072
|
}
|
|
3065
3073
|
if (escapeBuffer === `${ESCAPE}[5~`) {
|
|
3066
|
-
|
|
3067
|
-
escapeBuffer = "";
|
|
3068
|
-
scrollLogs("pageUp");
|
|
3074
|
+
handleScrollEscape("pageUp");
|
|
3069
3075
|
return;
|
|
3070
3076
|
}
|
|
3071
3077
|
if (escapeBuffer === `${ESCAPE}[6~`) {
|
|
3072
|
-
|
|
3073
|
-
escapeBuffer = "";
|
|
3074
|
-
scrollLogs("pageDown");
|
|
3078
|
+
handleScrollEscape("pageDown");
|
|
3075
3079
|
return;
|
|
3076
3080
|
}
|
|
3077
3081
|
if (escapeBuffer === `${ESCAPE}[H` || escapeBuffer === `${ESCAPE}[1~`) {
|
|
3078
|
-
|
|
3079
|
-
escapeBuffer = "";
|
|
3080
|
-
scrollLogs("home");
|
|
3082
|
+
handleScrollEscape("home");
|
|
3081
3083
|
return;
|
|
3082
3084
|
}
|
|
3083
3085
|
if (escapeBuffer === `${ESCAPE}[F` || escapeBuffer === `${ESCAPE}[4~`) {
|
|
3084
|
-
|
|
3085
|
-
escapeBuffer = "";
|
|
3086
|
-
scrollLogs("end");
|
|
3086
|
+
handleScrollEscape("end");
|
|
3087
3087
|
return;
|
|
3088
3088
|
}
|
|
3089
3089
|
if (/^\x1b\[[0-9]*$/.test(escapeBuffer)) {
|
|
@@ -3092,6 +3092,40 @@ var createWorkspaceTui = ({
|
|
|
3092
3092
|
}
|
|
3093
3093
|
exitEscapeMode();
|
|
3094
3094
|
};
|
|
3095
|
+
const handleBackspace = () => {
|
|
3096
|
+
if (!shellMode) {
|
|
3097
|
+
return;
|
|
3098
|
+
}
|
|
3099
|
+
if (promptBuffer.length > 0) {
|
|
3100
|
+
promptBuffer = promptBuffer.slice(0, UNFOUND_INDEX);
|
|
3101
|
+
scheduleRender();
|
|
3102
|
+
return;
|
|
3103
|
+
}
|
|
3104
|
+
resetPrompt();
|
|
3105
|
+
};
|
|
3106
|
+
const handleEnter = async () => {
|
|
3107
|
+
if (!shellMode) {
|
|
3108
|
+
return;
|
|
3109
|
+
}
|
|
3110
|
+
await submitShellCommand();
|
|
3111
|
+
};
|
|
3112
|
+
const handlePrintableChar = async (char) => {
|
|
3113
|
+
if (shellMode) {
|
|
3114
|
+
promptBuffer += char;
|
|
3115
|
+
scheduleRender();
|
|
3116
|
+
return;
|
|
3117
|
+
}
|
|
3118
|
+
if (char === "$") {
|
|
3119
|
+
shellMode = true;
|
|
3120
|
+
promptBuffer = "";
|
|
3121
|
+
scheduleRender();
|
|
3122
|
+
return;
|
|
3123
|
+
}
|
|
3124
|
+
const shortcut = SHORTCUTS2.get(char.toLowerCase());
|
|
3125
|
+
if (shortcut) {
|
|
3126
|
+
await runShortcut(shortcut);
|
|
3127
|
+
}
|
|
3128
|
+
};
|
|
3095
3129
|
const handleChar = async (char) => {
|
|
3096
3130
|
if (char === "\x03") {
|
|
3097
3131
|
await actions.quit();
|
|
@@ -3107,42 +3141,18 @@ var createWorkspaceTui = ({
|
|
|
3107
3141
|
return;
|
|
3108
3142
|
}
|
|
3109
3143
|
if (char === "\x7F" || char === "\b") {
|
|
3110
|
-
|
|
3111
|
-
return;
|
|
3112
|
-
}
|
|
3113
|
-
if (promptBuffer.length > 0) {
|
|
3114
|
-
promptBuffer = promptBuffer.slice(0, UNFOUND_INDEX);
|
|
3115
|
-
scheduleRender();
|
|
3116
|
-
return;
|
|
3117
|
-
}
|
|
3118
|
-
resetPrompt();
|
|
3144
|
+
handleBackspace();
|
|
3119
3145
|
return;
|
|
3120
3146
|
}
|
|
3121
3147
|
if (char === "\r" || char === `
|
|
3122
3148
|
`) {
|
|
3123
|
-
|
|
3124
|
-
await submitShellCommand();
|
|
3125
|
-
}
|
|
3149
|
+
await handleEnter();
|
|
3126
3150
|
return;
|
|
3127
3151
|
}
|
|
3128
3152
|
if (char.charCodeAt(0) < ASCII_SPACE) {
|
|
3129
3153
|
return;
|
|
3130
3154
|
}
|
|
3131
|
-
|
|
3132
|
-
if (char === "$") {
|
|
3133
|
-
shellMode = true;
|
|
3134
|
-
promptBuffer = "";
|
|
3135
|
-
scheduleRender();
|
|
3136
|
-
return;
|
|
3137
|
-
}
|
|
3138
|
-
const shortcut = SHORTCUTS2.get(char.toLowerCase());
|
|
3139
|
-
if (shortcut) {
|
|
3140
|
-
await runShortcut(shortcut);
|
|
3141
|
-
}
|
|
3142
|
-
return;
|
|
3143
|
-
}
|
|
3144
|
-
promptBuffer += char;
|
|
3145
|
-
scheduleRender();
|
|
3155
|
+
await handlePrintableChar(char);
|
|
3146
3156
|
};
|
|
3147
3157
|
const onResize = () => {
|
|
3148
3158
|
scheduleRender();
|
|
@@ -3167,6 +3177,16 @@ var createWorkspaceTui = ({
|
|
|
3167
3177
|
process.stdout.on("resize", onResize);
|
|
3168
3178
|
render();
|
|
3169
3179
|
};
|
|
3180
|
+
const disposeInput = () => {
|
|
3181
|
+
if (!input) {
|
|
3182
|
+
return;
|
|
3183
|
+
}
|
|
3184
|
+
input.off("data", onData);
|
|
3185
|
+
setRawMode(false);
|
|
3186
|
+
if (input !== process.stdin) {
|
|
3187
|
+
input.destroy();
|
|
3188
|
+
}
|
|
3189
|
+
};
|
|
3170
3190
|
const dispose = () => {
|
|
3171
3191
|
if (disposed) {
|
|
3172
3192
|
return;
|
|
@@ -3178,13 +3198,7 @@ var createWorkspaceTui = ({
|
|
|
3178
3198
|
renderTimer = null;
|
|
3179
3199
|
}
|
|
3180
3200
|
process.stdout.off("resize", onResize);
|
|
3181
|
-
|
|
3182
|
-
input.off("data", onData);
|
|
3183
|
-
setRawMode(false);
|
|
3184
|
-
if (input !== process.stdin) {
|
|
3185
|
-
input.destroy();
|
|
3186
|
-
}
|
|
3187
|
-
}
|
|
3201
|
+
disposeInput();
|
|
3188
3202
|
process.stdout.write("\x1B[?25h\x1B[?1049l");
|
|
3189
3203
|
};
|
|
3190
3204
|
return {
|
|
@@ -3208,11 +3222,7 @@ var sanitizeLogFileName = (value) => value.replace(/[^a-zA-Z0-9._-]/g, "_") || "
|
|
|
3208
3222
|
var createWorkspaceLogSink = (appendLog) => {
|
|
3209
3223
|
const logDirectory = resolve6(".absolutejs", "workspace", "logs");
|
|
3210
3224
|
mkdirSync4(logDirectory, { recursive: true });
|
|
3211
|
-
|
|
3212
|
-
if (file.endsWith(".log")) {
|
|
3213
|
-
unlinkSync(resolve6(logDirectory, file));
|
|
3214
|
-
}
|
|
3215
|
-
}
|
|
3225
|
+
readdirSync(logDirectory).filter((file) => file.endsWith(".log")).forEach((file) => unlinkSync(resolve6(logDirectory, file)));
|
|
3216
3226
|
writeFileSync2(resolve6(logDirectory, "all.log"), "");
|
|
3217
3227
|
writeFileSync2(resolve6(logDirectory, "workspace.log"), "");
|
|
3218
3228
|
const initializedSources = new Set(["workspace"]);
|
|
@@ -3240,13 +3250,13 @@ var createWorkspaceLogSink = (appendLog) => {
|
|
|
3240
3250
|
}
|
|
3241
3251
|
};
|
|
3242
3252
|
};
|
|
3243
|
-
var
|
|
3253
|
+
var readPackageVersion3 = (candidate) => {
|
|
3244
3254
|
try {
|
|
3245
3255
|
const pkg = JSON.parse(readFileSync8(candidate, "utf-8"));
|
|
3246
3256
|
if (pkg.name !== "@absolutejs/absolute") {
|
|
3247
3257
|
return null;
|
|
3248
3258
|
}
|
|
3249
|
-
const version2 = pkg
|
|
3259
|
+
const { version: version2 } = pkg;
|
|
3250
3260
|
return version2;
|
|
3251
3261
|
} catch {
|
|
3252
3262
|
return null;
|
|
@@ -3259,7 +3269,7 @@ var resolvePackageVersion2 = () => {
|
|
|
3259
3269
|
resolve6(import.meta.dir, "..", "..", "..", "..", "package.json")
|
|
3260
3270
|
];
|
|
3261
3271
|
for (const candidate of candidates) {
|
|
3262
|
-
const version2 =
|
|
3272
|
+
const version2 = readPackageVersion3(candidate);
|
|
3263
3273
|
if (version2) {
|
|
3264
3274
|
return version2;
|
|
3265
3275
|
}
|
|
@@ -3281,7 +3291,7 @@ var getDefaultReadyConfig = (service) => {
|
|
|
3281
3291
|
}
|
|
3282
3292
|
return;
|
|
3283
3293
|
};
|
|
3284
|
-
var normalizeExpectedStatuses = (value) => Array.isArray(value) ? value : [value ??
|
|
3294
|
+
var normalizeExpectedStatuses = (value) => Array.isArray(value) ? value : [value ?? HTTP_STATUS_OK];
|
|
3285
3295
|
var resolveServiceHttpUrl = (service, path) => {
|
|
3286
3296
|
if (!path.startsWith("/")) {
|
|
3287
3297
|
throw new Error(`ready path must start with "/" for service probes. Received "${path}".`);
|
|
@@ -3298,20 +3308,20 @@ var resolveHttpReadyProbe = (service, ready) => {
|
|
|
3298
3308
|
type: "http",
|
|
3299
3309
|
url: resolveServiceHttpUrl(service, ready),
|
|
3300
3310
|
method: "GET",
|
|
3301
|
-
expectStatus: [
|
|
3311
|
+
expectStatus: [HTTP_STATUS_OK],
|
|
3302
3312
|
headers: {},
|
|
3303
|
-
intervalMs:
|
|
3304
|
-
timeoutMs:
|
|
3313
|
+
intervalMs: WORKSPACE_READY_PROBE_INTERVAL_MS,
|
|
3314
|
+
timeoutMs: WORKSPACE_READY_TIMEOUT_MS
|
|
3305
3315
|
};
|
|
3306
3316
|
}
|
|
3307
3317
|
return {
|
|
3308
|
-
|
|
3309
|
-
url: ready,
|
|
3310
|
-
method: "GET",
|
|
3311
|
-
expectStatus: [200],
|
|
3318
|
+
expectStatus: [HTTP_STATUS_OK],
|
|
3312
3319
|
headers: {},
|
|
3313
|
-
intervalMs:
|
|
3314
|
-
|
|
3320
|
+
intervalMs: WORKSPACE_READY_PROBE_INTERVAL_MS,
|
|
3321
|
+
method: "GET",
|
|
3322
|
+
timeoutMs: WORKSPACE_READY_TIMEOUT_MS,
|
|
3323
|
+
type: "http",
|
|
3324
|
+
url: ready
|
|
3315
3325
|
};
|
|
3316
3326
|
}
|
|
3317
3327
|
if (ready.path && ready.url) {
|
|
@@ -3327,8 +3337,8 @@ var resolveHttpReadyProbe = (service, ready) => {
|
|
|
3327
3337
|
method: ready.method ?? "GET",
|
|
3328
3338
|
expectStatus: normalizeExpectedStatuses(ready.expectStatus),
|
|
3329
3339
|
headers: ready.headers ?? {},
|
|
3330
|
-
intervalMs: ready.intervalMs ??
|
|
3331
|
-
timeoutMs: ready.timeoutMs ??
|
|
3340
|
+
intervalMs: ready.intervalMs ?? WORKSPACE_READY_PROBE_INTERVAL_MS,
|
|
3341
|
+
timeoutMs: ready.timeoutMs ?? WORKSPACE_READY_TIMEOUT_MS
|
|
3332
3342
|
};
|
|
3333
3343
|
};
|
|
3334
3344
|
var resolveReadyProbe = (service, ready = service.ready ?? getDefaultReadyConfig(service)) => {
|
|
@@ -3343,22 +3353,22 @@ var resolveReadyProbe = (service, ready = service.ready ?? getDefaultReadyConfig
|
|
|
3343
3353
|
type: "tcp",
|
|
3344
3354
|
host: ready.host ?? getServicePublicHost(service),
|
|
3345
3355
|
port: ready.port,
|
|
3346
|
-
intervalMs: ready.intervalMs ??
|
|
3347
|
-
timeoutMs: ready.timeoutMs ??
|
|
3356
|
+
intervalMs: ready.intervalMs ?? WORKSPACE_READY_PROBE_INTERVAL_MS,
|
|
3357
|
+
timeoutMs: ready.timeoutMs ?? WORKSPACE_READY_TIMEOUT_MS
|
|
3348
3358
|
};
|
|
3349
3359
|
}
|
|
3350
3360
|
if (ready.type === "command") {
|
|
3351
3361
|
return {
|
|
3352
|
-
type: "command",
|
|
3353
3362
|
command: ready.command,
|
|
3354
|
-
intervalMs: ready.intervalMs ??
|
|
3355
|
-
timeoutMs: ready.timeoutMs ??
|
|
3363
|
+
intervalMs: ready.intervalMs ?? WORKSPACE_READY_PROBE_INTERVAL_MS,
|
|
3364
|
+
timeoutMs: ready.timeoutMs ?? WORKSPACE_READY_TIMEOUT_MS,
|
|
3365
|
+
type: "command"
|
|
3356
3366
|
};
|
|
3357
3367
|
}
|
|
3358
3368
|
if (ready.type === "delay") {
|
|
3359
3369
|
return {
|
|
3360
|
-
|
|
3361
|
-
|
|
3370
|
+
ms: ready.ms,
|
|
3371
|
+
type: "delay"
|
|
3362
3372
|
};
|
|
3363
3373
|
}
|
|
3364
3374
|
return resolveHttpReadyProbe(service, ready);
|
|
@@ -3367,7 +3377,7 @@ var probeHttpReady = async (ready) => {
|
|
|
3367
3377
|
const response = await fetch(ready.url, {
|
|
3368
3378
|
method: ready.method,
|
|
3369
3379
|
headers: ready.headers,
|
|
3370
|
-
signal: AbortSignal.timeout(Math.min(ready.timeoutMs,
|
|
3380
|
+
signal: AbortSignal.timeout(Math.min(ready.timeoutMs, WORKSPACE_READY_ATTEMPT_TIMEOUT_MS))
|
|
3371
3381
|
});
|
|
3372
3382
|
return ready.expectStatus.includes(response.status);
|
|
3373
3383
|
};
|
|
@@ -3379,7 +3389,7 @@ var probeTcpReady = async (ready) => new Promise((resolveProbe) => {
|
|
|
3379
3389
|
const timeout = setTimeout(() => {
|
|
3380
3390
|
socket.destroy();
|
|
3381
3391
|
resolveProbe(false);
|
|
3382
|
-
}, Math.min(ready.timeoutMs,
|
|
3392
|
+
}, Math.min(ready.timeoutMs, WORKSPACE_READY_ATTEMPT_TIMEOUT_MS));
|
|
3383
3393
|
socket.once("connect", () => {
|
|
3384
3394
|
clearTimeout(timeout);
|
|
3385
3395
|
socket.end();
|
|
@@ -3403,7 +3413,7 @@ var probeCommandReady = async (ready, service) => {
|
|
|
3403
3413
|
try {
|
|
3404
3414
|
processHandle.kill();
|
|
3405
3415
|
} catch {}
|
|
3406
|
-
}, Math.min(ready.timeoutMs,
|
|
3416
|
+
}, Math.min(ready.timeoutMs, WORKSPACE_READY_ATTEMPT_TIMEOUT_MS));
|
|
3407
3417
|
try {
|
|
3408
3418
|
const exitCode = await processHandle.exited;
|
|
3409
3419
|
return exitCode === 0;
|
|
@@ -3422,16 +3432,24 @@ var waitForReady = async (service) => {
|
|
|
3422
3432
|
}
|
|
3423
3433
|
const startedAt = Date.now();
|
|
3424
3434
|
while (Date.now() - startedAt < resolved.timeoutMs) {
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
return;
|
|
3429
|
-
}
|
|
3430
|
-
} catch {}
|
|
3435
|
+
if (await probeReady(resolved, service)) {
|
|
3436
|
+
return;
|
|
3437
|
+
}
|
|
3431
3438
|
await sleep(resolved.intervalMs);
|
|
3432
3439
|
}
|
|
3433
3440
|
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(" ")})`);
|
|
3434
3441
|
};
|
|
3442
|
+
var probeReady = async (resolved, service) => {
|
|
3443
|
+
try {
|
|
3444
|
+
if (resolved.type === "http")
|
|
3445
|
+
return probeHttpReady(resolved);
|
|
3446
|
+
if (resolved.type === "tcp")
|
|
3447
|
+
return probeTcpReady(resolved);
|
|
3448
|
+
return probeCommandReady(resolved, service);
|
|
3449
|
+
} catch {
|
|
3450
|
+
return false;
|
|
3451
|
+
}
|
|
3452
|
+
};
|
|
3435
3453
|
var resolveShutdownHook = (shutdown) => {
|
|
3436
3454
|
if (!shutdown) {
|
|
3437
3455
|
return null;
|
|
@@ -3439,12 +3457,12 @@ var resolveShutdownHook = (shutdown) => {
|
|
|
3439
3457
|
if (Array.isArray(shutdown)) {
|
|
3440
3458
|
return {
|
|
3441
3459
|
command: shutdown,
|
|
3442
|
-
timeoutMs:
|
|
3460
|
+
timeoutMs: WORKSPACE_SHUTDOWN_TIMEOUT_MS
|
|
3443
3461
|
};
|
|
3444
3462
|
}
|
|
3445
3463
|
return {
|
|
3446
3464
|
command: shutdown.command,
|
|
3447
|
-
timeoutMs: shutdown.timeoutMs ??
|
|
3465
|
+
timeoutMs: shutdown.timeoutMs ?? WORKSPACE_SHUTDOWN_TIMEOUT_MS
|
|
3448
3466
|
};
|
|
3449
3467
|
};
|
|
3450
3468
|
var runShutdownHook = async (service, onLog) => {
|
|
@@ -3468,11 +3486,7 @@ var runShutdownHook = async (service, onLog) => {
|
|
|
3468
3486
|
}, hook.timeoutMs);
|
|
3469
3487
|
try {
|
|
3470
3488
|
const exitCode = await processHandle.exited;
|
|
3471
|
-
|
|
3472
|
-
onLog("workspace", `${service.name} shutdown hook finished.`, "success");
|
|
3473
|
-
return;
|
|
3474
|
-
}
|
|
3475
|
-
onLog("workspace", `${service.name} shutdown hook exited with code ${exitCode || 1}.`, "warn");
|
|
3489
|
+
onLog("workspace", exitCode === 0 ? `${service.name} shutdown hook finished.` : `${service.name} shutdown hook exited with code ${exitCode || 1}.`, exitCode === 0 ? "success" : "warn");
|
|
3476
3490
|
} finally {
|
|
3477
3491
|
clearTimeout(timeout);
|
|
3478
3492
|
}
|
|
@@ -3512,36 +3526,38 @@ var pipeProcessLogs = (name, processHandle, appendLog) => {
|
|
|
3512
3526
|
const forward = async (stream, level) => {
|
|
3513
3527
|
let buffer = "";
|
|
3514
3528
|
const reader = stream.getReader();
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
break;
|
|
3520
|
-
}
|
|
3521
|
-
if (!value) {
|
|
3522
|
-
continue;
|
|
3523
|
-
}
|
|
3524
|
-
buffer += Buffer.from(value).toString();
|
|
3525
|
-
const lines = buffer.split(`
|
|
3526
|
-
`);
|
|
3527
|
-
buffer = lines.pop() ?? "";
|
|
3528
|
-
for (const line of lines) {
|
|
3529
|
-
if (line.trim().length === 0) {
|
|
3530
|
-
continue;
|
|
3531
|
-
}
|
|
3532
|
-
appendLog(name, line, level);
|
|
3533
|
-
}
|
|
3534
|
-
}
|
|
3535
|
-
} finally {
|
|
3536
|
-
if (buffer.trim().length > 0) {
|
|
3537
|
-
appendLog(name, buffer, level);
|
|
3538
|
-
}
|
|
3539
|
-
reader.releaseLock();
|
|
3529
|
+
let chunk = await readLogChunk(reader);
|
|
3530
|
+
while (chunk !== null) {
|
|
3531
|
+
buffer = appendLogChunk(buffer, chunk, name, level, appendLog);
|
|
3532
|
+
chunk = await readLogChunk(reader);
|
|
3540
3533
|
}
|
|
3534
|
+
appendRemainingLogBuffer(buffer, name, level, appendLog);
|
|
3535
|
+
reader.releaseLock();
|
|
3541
3536
|
};
|
|
3542
3537
|
forward(processHandle.stdout, "info");
|
|
3543
3538
|
forward(processHandle.stderr, "error");
|
|
3544
3539
|
};
|
|
3540
|
+
var readLogChunk = async (reader) => {
|
|
3541
|
+
const { done, value } = await reader.read();
|
|
3542
|
+
if (done)
|
|
3543
|
+
return null;
|
|
3544
|
+
if (!value)
|
|
3545
|
+
return "";
|
|
3546
|
+
return Buffer.from(value).toString();
|
|
3547
|
+
};
|
|
3548
|
+
var appendLogChunk = (buffer, chunk, name, level, appendLog) => {
|
|
3549
|
+
const lines = `${buffer}${chunk}`.split(`
|
|
3550
|
+
`);
|
|
3551
|
+
const nextBuffer = lines.pop() ?? "";
|
|
3552
|
+
lines.filter((line) => line.trim().length > 0).forEach((line) => appendLog(name, line, level));
|
|
3553
|
+
return nextBuffer;
|
|
3554
|
+
};
|
|
3555
|
+
var appendRemainingLogBuffer = (buffer, name, level, appendLog) => {
|
|
3556
|
+
if (buffer.trim().length === 0) {
|
|
3557
|
+
return;
|
|
3558
|
+
}
|
|
3559
|
+
appendLog(name, buffer, level);
|
|
3560
|
+
};
|
|
3545
3561
|
var getServicePublicHost = (service) => {
|
|
3546
3562
|
const host = service.env?.HOST ?? process.env.HOST ?? "localhost";
|
|
3547
3563
|
if (host === "0.0.0.0" || host === "::") {
|
|
@@ -3552,35 +3568,37 @@ var getServicePublicHost = (service) => {
|
|
|
3552
3568
|
var getServiceProtocol = (service) => service.env?.ABSOLUTE_HTTPS === "true" || process.env.ABSOLUTE_HTTPS === "true" ? "https" : "http";
|
|
3553
3569
|
var createWorkspaceServiceEnv = (services) => {
|
|
3554
3570
|
const workspaceEnv = {};
|
|
3555
|
-
for (const [name, service] of Object.entries(services)) {
|
|
3556
|
-
if (!service.port) {
|
|
3557
|
-
continue;
|
|
3558
|
-
}
|
|
3571
|
+
for (const [name, service] of Object.entries(services).filter(([, service2]) => Boolean(service2.port))) {
|
|
3559
3572
|
const envKey = `ABSOLUTE_SERVICE_${name.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_URL`;
|
|
3560
3573
|
workspaceEnv[envKey] = `${getServiceProtocol(service)}://${getServicePublicHost(service)}:${service.port}`;
|
|
3561
3574
|
}
|
|
3562
3575
|
return workspaceEnv;
|
|
3563
3576
|
};
|
|
3577
|
+
var getDefinedProcessEnv = () => Object.fromEntries(Object.entries(process.env).filter((entry) => typeof entry[1] === "string"));
|
|
3578
|
+
var resolveAbsoluteServiceConfigPath = (service, cwd, options) => {
|
|
3579
|
+
if (service.config)
|
|
3580
|
+
return resolve6(cwd, service.config);
|
|
3581
|
+
if (options.configPath)
|
|
3582
|
+
return resolve6(options.configPath);
|
|
3583
|
+
if (process.env.ABSOLUTE_CONFIG)
|
|
3584
|
+
return resolve6(process.env.ABSOLUTE_CONFIG);
|
|
3585
|
+
return;
|
|
3586
|
+
};
|
|
3564
3587
|
var resolveService = (name, service, workspaceEnv, options) => {
|
|
3565
3588
|
const cwd = resolve6(service.cwd ?? ".");
|
|
3566
|
-
const envVars = {
|
|
3567
|
-
...process.env,
|
|
3568
|
-
...workspaceEnv,
|
|
3569
|
-
...service.env,
|
|
3589
|
+
const envVars = Object.assign(getDefinedProcessEnv(), workspaceEnv, service.env, {
|
|
3570
3590
|
ABSOLUTE_WORKSPACE_MANAGED: "1",
|
|
3571
3591
|
ABSOLUTE_WORKSPACE_SERVICE_NAME: name,
|
|
3572
3592
|
ABSOLUTE_WORKSPACE_SERVICE_VISIBILITY: getVisibility(service),
|
|
3573
3593
|
FORCE_COLOR: "1",
|
|
3574
3594
|
NODE_ENV: "development"
|
|
3575
|
-
};
|
|
3595
|
+
});
|
|
3576
3596
|
if (service.port && !envVars.PORT) {
|
|
3577
3597
|
envVars.PORT = String(service.port);
|
|
3578
3598
|
}
|
|
3579
3599
|
if (isAbsoluteService(service)) {
|
|
3580
|
-
const configPath2 = service
|
|
3581
|
-
|
|
3582
|
-
envVars.ABSOLUTE_CONFIG = configPath2;
|
|
3583
|
-
}
|
|
3600
|
+
const configPath2 = resolveAbsoluteServiceConfigPath(service, cwd, options);
|
|
3601
|
+
Object.assign(envVars, configPath2 ? { ABSOLUTE_CONFIG: configPath2 } : {});
|
|
3584
3602
|
const command = [
|
|
3585
3603
|
process.execPath,
|
|
3586
3604
|
"--hot",
|
|
@@ -3647,30 +3665,43 @@ var workspace = async (subcommand, options) => {
|
|
|
3647
3665
|
});
|
|
3648
3666
|
const workspaceLogs = createWorkspaceLogSink(tui.addLog);
|
|
3649
3667
|
const addLog = workspaceLogs.appendLog;
|
|
3668
|
+
const killProcess = (service) => {
|
|
3669
|
+
try {
|
|
3670
|
+
service.process.kill();
|
|
3671
|
+
} catch {}
|
|
3672
|
+
};
|
|
3673
|
+
const runShutdownHookSafely = async (service) => {
|
|
3674
|
+
try {
|
|
3675
|
+
await runShutdownHook(service.resolved, addLog);
|
|
3676
|
+
} catch (error) {
|
|
3677
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3678
|
+
addLog("workspace", `${service.name} shutdown hook failed: ${message}`, "warn");
|
|
3679
|
+
}
|
|
3680
|
+
};
|
|
3650
3681
|
const killProcesses = async () => {
|
|
3651
3682
|
const snapshot = [...running];
|
|
3652
3683
|
running.length = 0;
|
|
3653
|
-
|
|
3654
|
-
try {
|
|
3655
|
-
service.process.kill();
|
|
3656
|
-
} catch {}
|
|
3657
|
-
}
|
|
3684
|
+
snapshot.forEach((service) => killProcess(service));
|
|
3658
3685
|
await Promise.all(snapshot.map((service) => service.process.exited));
|
|
3659
3686
|
for (const service of snapshot.reverse()) {
|
|
3660
|
-
|
|
3661
|
-
await runShutdownHook(service.resolved, addLog);
|
|
3662
|
-
} catch (error) {
|
|
3663
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
3664
|
-
addLog("workspace", `${service.name} shutdown hook failed: ${message}`, "warn");
|
|
3665
|
-
}
|
|
3687
|
+
await runShutdownHookSafely(service);
|
|
3666
3688
|
}
|
|
3667
3689
|
};
|
|
3690
|
+
const appendRecentLogs = (lines, logsToPrint) => {
|
|
3691
|
+
if (logsToPrint.length === 0) {
|
|
3692
|
+
return;
|
|
3693
|
+
}
|
|
3694
|
+
lines.push("", "Recent logs:");
|
|
3695
|
+
logsToPrint.forEach((entry) => {
|
|
3696
|
+
lines.push(` ${entry.timestamp} [${entry.source}] ${entry.message}`);
|
|
3697
|
+
});
|
|
3698
|
+
};
|
|
3668
3699
|
const printFailureSummary = (exitCode) => {
|
|
3669
3700
|
const servicesSnapshot = tui.getServiceSnapshot();
|
|
3670
|
-
const recentLogs = tui.getRecentLogs(
|
|
3701
|
+
const recentLogs = tui.getRecentLogs(WORKSPACE_FAILURE_RECENT_LOG_LIMIT);
|
|
3671
3702
|
const failedServices = servicesSnapshot.filter((service) => service.status === "error");
|
|
3672
3703
|
const relevantLogs = recentLogs.filter((entry) => entry.level === "error" || entry.level === "warn" || entry.source === "workspace" || failedServices.some((service) => service.name === entry.source));
|
|
3673
|
-
const logsToPrint = (relevantLogs.length > 0 ? relevantLogs : recentLogs).slice(-
|
|
3704
|
+
const logsToPrint = (relevantLogs.length > 0 ? relevantLogs : recentLogs).slice(-WORKSPACE_FAILURE_LOG_PRINT_LIMIT);
|
|
3674
3705
|
const lines = [
|
|
3675
3706
|
"",
|
|
3676
3707
|
`\x1B[31mABSOLUTEJS WORKSPACE exited with code ${exitCode}\x1B[0m`,
|
|
@@ -3681,12 +3712,7 @@ var workspace = async (subcommand, options) => {
|
|
|
3681
3712
|
return ` - ${service.name}: ${service.status} \xB7 ${service.target}${detail}`;
|
|
3682
3713
|
})
|
|
3683
3714
|
];
|
|
3684
|
-
|
|
3685
|
-
lines.push("", "Recent logs:");
|
|
3686
|
-
for (const entry of logsToPrint) {
|
|
3687
|
-
lines.push(` ${entry.timestamp} [${entry.source}] ${entry.message}`);
|
|
3688
|
-
}
|
|
3689
|
-
}
|
|
3715
|
+
appendRecentLogs(lines, logsToPrint);
|
|
3690
3716
|
lines.push("");
|
|
3691
3717
|
process.stderr.write(`${lines.join(`
|
|
3692
3718
|
`)}
|
|
@@ -3701,6 +3727,34 @@ var workspace = async (subcommand, options) => {
|
|
|
3701
3727
|
process.kill(processHandle.pid, signal);
|
|
3702
3728
|
} catch {}
|
|
3703
3729
|
};
|
|
3730
|
+
const resumeRunningServices = () => {
|
|
3731
|
+
running.forEach((service) => {
|
|
3732
|
+
sendSignalToService(service.process, "SIGCONT");
|
|
3733
|
+
});
|
|
3734
|
+
paused = false;
|
|
3735
|
+
};
|
|
3736
|
+
const markRunningServicesReady = () => {
|
|
3737
|
+
running.forEach((service) => {
|
|
3738
|
+
readyServiceNames.add(service.name);
|
|
3739
|
+
tui.setServiceStatus(service.name, "ready");
|
|
3740
|
+
});
|
|
3741
|
+
};
|
|
3742
|
+
const pauseRunningServices = () => {
|
|
3743
|
+
running.forEach((service) => {
|
|
3744
|
+
sendSignalToService(service.process, "SIGSTOP");
|
|
3745
|
+
readyServiceNames.delete(service.name);
|
|
3746
|
+
tui.setServiceStatus(service.name, "paused");
|
|
3747
|
+
});
|
|
3748
|
+
paused = true;
|
|
3749
|
+
};
|
|
3750
|
+
const killStaleServicePort = (port) => {
|
|
3751
|
+
if (port <= 0) {
|
|
3752
|
+
return;
|
|
3753
|
+
}
|
|
3754
|
+
killStaleProcesses(port, (message) => {
|
|
3755
|
+
addLog("workspace", message, "warn");
|
|
3756
|
+
});
|
|
3757
|
+
};
|
|
3704
3758
|
const shutdown = async (exitCode = 0) => {
|
|
3705
3759
|
if (shuttingDown) {
|
|
3706
3760
|
return;
|
|
@@ -3712,10 +3766,7 @@ var workspace = async (subcommand, options) => {
|
|
|
3712
3766
|
printFailureSummary(exitCode);
|
|
3713
3767
|
}
|
|
3714
3768
|
if (paused) {
|
|
3715
|
-
|
|
3716
|
-
sendSignalToService(service.process, "SIGCONT");
|
|
3717
|
-
}
|
|
3718
|
-
paused = false;
|
|
3769
|
+
resumeRunningServices();
|
|
3719
3770
|
}
|
|
3720
3771
|
await killProcesses();
|
|
3721
3772
|
process.exit(exitCode);
|
|
@@ -3729,11 +3780,7 @@ var workspace = async (subcommand, options) => {
|
|
|
3729
3780
|
}
|
|
3730
3781
|
const resolved = resolveService(name, service, workspaceEnv, options);
|
|
3731
3782
|
const port = (resolved.service.port ?? Number(resolved.env.PORT ?? "")) || DEFAULT_PORT;
|
|
3732
|
-
|
|
3733
|
-
killStaleProcesses(port, (message) => {
|
|
3734
|
-
addLog("workspace", message, "warn");
|
|
3735
|
-
});
|
|
3736
|
-
}
|
|
3783
|
+
killStaleServicePort(port);
|
|
3737
3784
|
if (isAbsoluteService(resolved.service) && resolved.configPath && !existsSync8(resolved.configPath)) {
|
|
3738
3785
|
throw new Error(`${name} references missing config "${resolved.configPath}"`);
|
|
3739
3786
|
}
|
|
@@ -3779,10 +3826,7 @@ var workspace = async (subcommand, options) => {
|
|
|
3779
3826
|
}
|
|
3780
3827
|
restarting = true;
|
|
3781
3828
|
if (paused) {
|
|
3782
|
-
|
|
3783
|
-
sendSignalToService(service.process, "SIGCONT");
|
|
3784
|
-
}
|
|
3785
|
-
paused = false;
|
|
3829
|
+
resumeRunningServices();
|
|
3786
3830
|
}
|
|
3787
3831
|
addLog("workspace", "Restarting workspace...", "info");
|
|
3788
3832
|
readyServiceNames.clear();
|
|
@@ -3797,20 +3841,12 @@ var workspace = async (subcommand, options) => {
|
|
|
3797
3841
|
};
|
|
3798
3842
|
const togglePause = () => {
|
|
3799
3843
|
if (paused) {
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
readyServiceNames.add(service.name);
|
|
3803
|
-
tui.setServiceStatus(service.name, "ready");
|
|
3804
|
-
}
|
|
3844
|
+
resumeRunningServices();
|
|
3845
|
+
markRunningServicesReady();
|
|
3805
3846
|
paused = false;
|
|
3806
3847
|
addLog("workspace", "Workspace resumed.", "success");
|
|
3807
3848
|
} else {
|
|
3808
|
-
|
|
3809
|
-
sendSignalToService(service.process, "SIGSTOP");
|
|
3810
|
-
readyServiceNames.delete(service.name);
|
|
3811
|
-
tui.setServiceStatus(service.name, "paused");
|
|
3812
|
-
}
|
|
3813
|
-
paused = true;
|
|
3849
|
+
pauseRunningServices();
|
|
3814
3850
|
addLog("workspace", "Workspace paused.", "warn");
|
|
3815
3851
|
}
|
|
3816
3852
|
};
|
|
@@ -3876,7 +3912,7 @@ init_telemetryEvent();
|
|
|
3876
3912
|
init_constants();
|
|
3877
3913
|
init_utils();
|
|
3878
3914
|
var [command] = process.argv.slice(2);
|
|
3879
|
-
var [workspaceCommand] = process.argv.slice(
|
|
3915
|
+
var [workspaceCommand] = process.argv.slice(WORKSPACE_COMMAND_ARGS_OFFSET);
|
|
3880
3916
|
var args = process.argv.slice(CLI_ARGS_OFFSET);
|
|
3881
3917
|
var parseNamedArg = (flag) => {
|
|
3882
3918
|
const idx = args.indexOf(flag);
|