@absolutejs/absolute 0.19.0-beta.1029 → 0.19.0-beta.1030
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/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/cli/index.js +278 -82
- package/dist/index.js.map +1 -1
- package/dist/src/cli/psTui.d.ts +1 -0
- package/dist/src/cli/scripts/ls.d.ts +1 -0
- package/dist/src/cli/scripts/ps.d.ts +1 -0
- package/package.json +1 -1
- package/dist/src/cli/listTui.d.ts +0 -1
- package/dist/src/cli/scripts/list.d.ts +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
var __require = import.meta.require;
|
|
3
3
|
|
|
4
|
-
// .angular-partial-tmp-
|
|
4
|
+
// .angular-partial-tmp-IJqg0M/src/core/streamingSlotRegistrar.ts
|
|
5
5
|
var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
|
|
6
6
|
var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
|
|
7
7
|
var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
var __require = import.meta.require;
|
|
3
3
|
|
|
4
|
-
// .angular-partial-tmp-
|
|
4
|
+
// .angular-partial-tmp-IJqg0M/src/core/streamingSlotRegistrar.ts
|
|
5
5
|
var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
|
|
6
6
|
var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
|
|
7
7
|
var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
|
|
@@ -48,7 +48,7 @@ var warnMissingStreamingSlotCollector = (primitiveName) => {
|
|
|
48
48
|
getWarningController()?.maybeWarn(primitiveName);
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
-
// .angular-partial-tmp-
|
|
51
|
+
// .angular-partial-tmp-IJqg0M/src/core/streamingSlotRegistry.ts
|
|
52
52
|
var STREAMING_SLOT_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotAsyncLocalStorage");
|
|
53
53
|
var isObjectRecord2 = (value) => Boolean(value) && typeof value === "object";
|
|
54
54
|
var isAsyncLocalStorage = (value) => isObjectRecord2(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
|
package/dist/cli/index.js
CHANGED
|
@@ -170858,6 +170858,197 @@ var init_build = __esm(() => {
|
|
|
170858
170858
|
init_telemetryEvent();
|
|
170859
170859
|
});
|
|
170860
170860
|
|
|
170861
|
+
// src/cli/scripts/ls.ts
|
|
170862
|
+
var exports_ls = {};
|
|
170863
|
+
__export(exports_ls, {
|
|
170864
|
+
runLs: () => runLs
|
|
170865
|
+
});
|
|
170866
|
+
import { existsSync as existsSync10, readFileSync as readFileSync13, statSync } from "fs";
|
|
170867
|
+
import { join as join11, relative as relative2 } from "path";
|
|
170868
|
+
var DEFAULT_BUILD_DIR = "build", FRAMEWORK_SEGMENTS, FRAMEWORK_ORDER, FRAMEWORK_LABELS, KIND_LABELS, KIND_RANK, KIND_RULES, parseConfigArg = (args) => {
|
|
170869
|
+
const index = args.indexOf("--config");
|
|
170870
|
+
if (index === UNFOUND_INDEX)
|
|
170871
|
+
return;
|
|
170872
|
+
return args[index + 1];
|
|
170873
|
+
}, resolveBuildDir = async (configPath2) => {
|
|
170874
|
+
try {
|
|
170875
|
+
const config = await loadConfig(configPath2);
|
|
170876
|
+
return typeof config.buildDirectory === "string" ? config.buildDirectory : DEFAULT_BUILD_DIR;
|
|
170877
|
+
} catch {
|
|
170878
|
+
return DEFAULT_BUILD_DIR;
|
|
170879
|
+
}
|
|
170880
|
+
}, readManifest = (manifestPath) => {
|
|
170881
|
+
const parsed = JSON.parse(readFileSync13(manifestPath, "utf-8"));
|
|
170882
|
+
return parsed;
|
|
170883
|
+
}, detectFramework = (path) => {
|
|
170884
|
+
const segments = path.toLowerCase().split("/");
|
|
170885
|
+
const found = FRAMEWORK_SEGMENTS.find((framework) => segments.includes(framework));
|
|
170886
|
+
return found ?? "shared";
|
|
170887
|
+
}, detectKind = (id, path) => {
|
|
170888
|
+
const rule = KIND_RULES.find((entry) => entry.matches({ id, path }));
|
|
170889
|
+
return rule?.kind ?? "page";
|
|
170890
|
+
}, resolveDiskPath = (buildDir, value) => {
|
|
170891
|
+
if (existsSync10(value))
|
|
170892
|
+
return value;
|
|
170893
|
+
const underBuild = join11(buildDir, value);
|
|
170894
|
+
if (existsSync10(underBuild))
|
|
170895
|
+
return underBuild;
|
|
170896
|
+
return join11(process.cwd(), value);
|
|
170897
|
+
}, fileSize = (diskPath) => {
|
|
170898
|
+
try {
|
|
170899
|
+
return statSync(diskPath).size;
|
|
170900
|
+
} catch {
|
|
170901
|
+
return 0;
|
|
170902
|
+
}
|
|
170903
|
+
}, buildEntries = (manifest, buildDir) => Object.entries(manifest).map(([id, value]) => ({
|
|
170904
|
+
framework: detectFramework(value),
|
|
170905
|
+
id,
|
|
170906
|
+
kind: detectKind(id, value),
|
|
170907
|
+
path: value,
|
|
170908
|
+
sizeBytes: fileSize(resolveDiskPath(buildDir, value))
|
|
170909
|
+
})), sortEntries = (entries) => [...entries].sort((left, right) => KIND_RANK[left.kind] - KIND_RANK[right.kind] || left.id.localeCompare(right.id)), groupByFramework = (entries) => FRAMEWORK_ORDER.map((framework) => ({
|
|
170910
|
+
entries: sortEntries(entries.filter((entry) => entry.framework === framework)),
|
|
170911
|
+
framework
|
|
170912
|
+
})).filter((group) => group.entries.length > 0), formatSize = (bytes) => {
|
|
170913
|
+
if (bytes === 0)
|
|
170914
|
+
return "-";
|
|
170915
|
+
if (bytes < BYTES_PER_KILOBYTE)
|
|
170916
|
+
return `${bytes} B`;
|
|
170917
|
+
const kilobytes = bytes / BYTES_PER_KILOBYTE;
|
|
170918
|
+
if (kilobytes < BYTES_PER_KILOBYTE)
|
|
170919
|
+
return `${kilobytes.toFixed(1)} KB`;
|
|
170920
|
+
return `${(kilobytes / BYTES_PER_KILOBYTE).toFixed(1)} MB`;
|
|
170921
|
+
}, padStart = (value, width) => {
|
|
170922
|
+
const padding = width - visibleLength(value);
|
|
170923
|
+
if (padding <= 0)
|
|
170924
|
+
return value;
|
|
170925
|
+
return `${" ".repeat(padding)}${value}`;
|
|
170926
|
+
}, columnWidths = (entries) => ({
|
|
170927
|
+
id: Math.max(...entries.map((entry) => entry.id.length)),
|
|
170928
|
+
kind: Math.max(...entries.map((entry) => KIND_LABELS[entry.kind].length)),
|
|
170929
|
+
size: Math.max(...entries.map((entry) => formatSize(entry.sizeBytes).length))
|
|
170930
|
+
}), sumSizes = (entries) => entries.reduce((total, entry) => total + entry.sizeBytes, 0), pluralFiles = (count) => count === 1 ? "file" : "files", renderGroupHeader = (group) => {
|
|
170931
|
+
const label = FRAMEWORK_LABELS[group.framework];
|
|
170932
|
+
const count = group.entries.length;
|
|
170933
|
+
const size = formatSize(sumSizes(group.entries));
|
|
170934
|
+
return `
|
|
170935
|
+
${colors.bold}${label}${colors.reset}${colors.dim} \xB7 ${count} ${pluralFiles(count)} \xB7 ${size}${colors.reset}`;
|
|
170936
|
+
}, renderEntryLine = (entry, widths) => {
|
|
170937
|
+
const id = padLine(entry.id, widths.id);
|
|
170938
|
+
const kind = padLine(KIND_LABELS[entry.kind], widths.kind);
|
|
170939
|
+
const size = padStart(formatSize(entry.sizeBytes), widths.size);
|
|
170940
|
+
return ` ${id} ${colors.dim}${kind}${colors.reset} ${size}`;
|
|
170941
|
+
}, visibleEntries = (entries, showAll) => showAll ? entries : entries.filter((entry) => entry.kind !== "chunk"), renderChunkSummary = (entries, showAll) => {
|
|
170942
|
+
const chunks = entries.filter((entry) => entry.kind === "chunk");
|
|
170943
|
+
if (showAll || chunks.length === 0)
|
|
170944
|
+
return [];
|
|
170945
|
+
return [
|
|
170946
|
+
` ${colors.dim}+ ${chunks.length} shared ${chunks.length === 1 ? "chunk" : "chunks"} \xB7 ${formatSize(sumSizes(chunks))} (--all to list)${colors.reset}`
|
|
170947
|
+
];
|
|
170948
|
+
}, renderGroup = (group, widths, showAll) => [
|
|
170949
|
+
renderGroupHeader(group),
|
|
170950
|
+
...visibleEntries(group.entries, showAll).map((entry) => renderEntryLine(entry, widths)),
|
|
170951
|
+
...renderChunkSummary(group.entries, showAll)
|
|
170952
|
+
], renderFooter = (entries, groupCount, manifestLabel) => `
|
|
170953
|
+
${colors.dim}${groupCount} ${groupCount === 1 ? "framework" : "frameworks"} \xB7 ${entries.length} ${pluralFiles(entries.length)} \xB7 ${formatSize(sumSizes(entries))} \xB7 ${manifestLabel}${colors.reset}`, printInventory = (entries, manifestLabel, showAll) => {
|
|
170954
|
+
const groups = groupByFramework(entries);
|
|
170955
|
+
const widths = columnWidths(entries);
|
|
170956
|
+
const lines = [
|
|
170957
|
+
...groups.flatMap((group) => renderGroup(group, widths, showAll)),
|
|
170958
|
+
renderFooter(entries, groups.length, manifestLabel)
|
|
170959
|
+
];
|
|
170960
|
+
process.stdout.write(`${lines.join(`
|
|
170961
|
+
`)}
|
|
170962
|
+
`);
|
|
170963
|
+
}, printNoBuild = (manifestPath) => {
|
|
170964
|
+
process.stdout.write(`${colors.dim}No build found at ${manifestPath}. Run \`absolute build\` (or \`absolute dev\`) first.${colors.reset}
|
|
170965
|
+
`);
|
|
170966
|
+
}, runLs = async (args) => {
|
|
170967
|
+
process.stdout.on("error", (error) => {
|
|
170968
|
+
if (error instanceof Error && "code" in error && error.code === "EPIPE") {
|
|
170969
|
+
process.exit(0);
|
|
170970
|
+
}
|
|
170971
|
+
});
|
|
170972
|
+
const buildDir = await resolveBuildDir(parseConfigArg(args));
|
|
170973
|
+
const manifestPath = join11(buildDir, "manifest.json");
|
|
170974
|
+
const manifestLabel = relative2(process.cwd(), manifestPath) || manifestPath;
|
|
170975
|
+
if (!existsSync10(manifestPath)) {
|
|
170976
|
+
printNoBuild(manifestLabel);
|
|
170977
|
+
return;
|
|
170978
|
+
}
|
|
170979
|
+
const entries = buildEntries(readManifest(manifestPath), buildDir);
|
|
170980
|
+
if (args.includes("--json")) {
|
|
170981
|
+
process.stdout.write(`${JSON.stringify(entries, null, 2)}
|
|
170982
|
+
`);
|
|
170983
|
+
return;
|
|
170984
|
+
}
|
|
170985
|
+
if (entries.length === 0) {
|
|
170986
|
+
process.stdout.write(`${colors.dim}${manifestLabel} is empty \u2014 nothing built yet.${colors.reset}
|
|
170987
|
+
`);
|
|
170988
|
+
return;
|
|
170989
|
+
}
|
|
170990
|
+
printInventory(entries, manifestLabel, args.includes("--all"));
|
|
170991
|
+
};
|
|
170992
|
+
var init_ls = __esm(() => {
|
|
170993
|
+
init_constants();
|
|
170994
|
+
init_loadConfig();
|
|
170995
|
+
init_tuiPrimitives();
|
|
170996
|
+
FRAMEWORK_SEGMENTS = [
|
|
170997
|
+
"angular",
|
|
170998
|
+
"html",
|
|
170999
|
+
"htmx",
|
|
171000
|
+
"react",
|
|
171001
|
+
"svelte",
|
|
171002
|
+
"vue"
|
|
171003
|
+
];
|
|
171004
|
+
FRAMEWORK_ORDER = [
|
|
171005
|
+
"react",
|
|
171006
|
+
"vue",
|
|
171007
|
+
"svelte",
|
|
171008
|
+
"angular",
|
|
171009
|
+
"html",
|
|
171010
|
+
"htmx",
|
|
171011
|
+
"shared"
|
|
171012
|
+
];
|
|
171013
|
+
FRAMEWORK_LABELS = {
|
|
171014
|
+
angular: "Angular",
|
|
171015
|
+
html: "HTML",
|
|
171016
|
+
htmx: "HTMX",
|
|
171017
|
+
react: "React",
|
|
171018
|
+
shared: "Shared",
|
|
171019
|
+
svelte: "Svelte",
|
|
171020
|
+
vue: "Vue"
|
|
171021
|
+
};
|
|
171022
|
+
KIND_LABELS = {
|
|
171023
|
+
chunk: "chunk",
|
|
171024
|
+
client: "client",
|
|
171025
|
+
css: "css",
|
|
171026
|
+
index: "index",
|
|
171027
|
+
island: "island",
|
|
171028
|
+
page: "page",
|
|
171029
|
+
script: "script"
|
|
171030
|
+
};
|
|
171031
|
+
KIND_RANK = {
|
|
171032
|
+
chunk: 6,
|
|
171033
|
+
client: 2,
|
|
171034
|
+
css: 4,
|
|
171035
|
+
index: 1,
|
|
171036
|
+
island: 3,
|
|
171037
|
+
page: 0,
|
|
171038
|
+
script: 5
|
|
171039
|
+
};
|
|
171040
|
+
KIND_RULES = [
|
|
171041
|
+
{ kind: "chunk", matches: (probe) => probe.id.startsWith("Chunk") },
|
|
171042
|
+
{ kind: "css", matches: (probe) => probe.path.endsWith(".css") },
|
|
171043
|
+
{ kind: "page", matches: (probe) => probe.path.endsWith(".html") },
|
|
171044
|
+
{ kind: "island", matches: (probe) => probe.id.startsWith("Island") },
|
|
171045
|
+
{ kind: "index", matches: (probe) => probe.id.endsWith("Index") },
|
|
171046
|
+
{ kind: "client", matches: (probe) => probe.id.endsWith("Client") },
|
|
171047
|
+
{ kind: "page", matches: (probe) => probe.path.includes("/server/") },
|
|
171048
|
+
{ kind: "script", matches: (probe) => probe.path.includes("/scripts/") }
|
|
171049
|
+
];
|
|
171050
|
+
});
|
|
171051
|
+
|
|
170861
171052
|
// src/cli/discoverInstances.ts
|
|
170862
171053
|
var MS_PER_SECOND = 1000, isJsRuntime = (command) => /\b(bun|deno|node)\b/.test(command), untrackedName = (command) => {
|
|
170863
171054
|
const entry = command.split(/\s+/).find((token) => /\.(cjs|js|mjs|ts)$/.test(token));
|
|
@@ -170958,10 +171149,10 @@ var init_instanceStatus = __esm(() => {
|
|
|
170958
171149
|
init_constants();
|
|
170959
171150
|
});
|
|
170960
171151
|
|
|
170961
|
-
// src/cli/
|
|
170962
|
-
var
|
|
170963
|
-
__export(
|
|
170964
|
-
|
|
171152
|
+
// src/cli/psTui.ts
|
|
171153
|
+
var exports_psTui = {};
|
|
171154
|
+
__export(exports_psTui, {
|
|
171155
|
+
runPsTui: () => runPsTui
|
|
170965
171156
|
});
|
|
170966
171157
|
import { spawn } from "child_process";
|
|
170967
171158
|
import { closeSync, fstatSync, openSync as openSync3, readSync } from "fs";
|
|
@@ -170987,8 +171178,8 @@ var TUI_HEADERS, STATUS_INDEX = 5, URL_INDEX = 6, helpLines2, statusLevelColor =
|
|
|
170987
171178
|
getDurationString(instance.uptimeMs),
|
|
170988
171179
|
instance.status,
|
|
170989
171180
|
instance.url ?? "-"
|
|
170990
|
-
],
|
|
170991
|
-
const natural =
|
|
171181
|
+
], columnWidths2 = (allCells) => TUI_HEADERS.map((header, index) => Math.max(visibleLength(header), ...allCells.map((cells) => visibleLength(cells[index] ?? "")))), layoutWidths = (allCells, width) => {
|
|
171182
|
+
const natural = columnWidths2(allCells);
|
|
170992
171183
|
const gaps = (TUI_HEADERS.length - 1) * LIST_TUI_COLUMN_GAP;
|
|
170993
171184
|
const available = width - LIST_TUI_MARKER_WIDTH - gaps;
|
|
170994
171185
|
const fixed = natural.reduce((sum, value, index) => index === URL_INDEX ? sum : sum + value, 0);
|
|
@@ -171445,15 +171636,15 @@ var TUI_HEADERS, STATUS_INDEX = 5, URL_INDEX = 6, helpLines2, statusLevelColor =
|
|
|
171445
171636
|
await refresh();
|
|
171446
171637
|
render();
|
|
171447
171638
|
await promise;
|
|
171448
|
-
},
|
|
171639
|
+
}, runPsTui = async () => {
|
|
171449
171640
|
const input = openTtyStream2();
|
|
171450
171641
|
if (!input) {
|
|
171451
|
-
process.stdout.write("Interactive
|
|
171642
|
+
process.stdout.write("Interactive ps requires a TTY. Run `absolute ps` for a snapshot.\n");
|
|
171452
171643
|
return;
|
|
171453
171644
|
}
|
|
171454
171645
|
await driveListTui(input);
|
|
171455
171646
|
};
|
|
171456
|
-
var
|
|
171647
|
+
var init_psTui = __esm(() => {
|
|
171457
171648
|
init_constants();
|
|
171458
171649
|
init_getDurationString();
|
|
171459
171650
|
init_discoverInstances();
|
|
@@ -171483,10 +171674,10 @@ var init_listTui = __esm(() => {
|
|
|
171483
171674
|
];
|
|
171484
171675
|
});
|
|
171485
171676
|
|
|
171486
|
-
// src/cli/scripts/
|
|
171487
|
-
var
|
|
171488
|
-
__export(
|
|
171489
|
-
|
|
171677
|
+
// src/cli/scripts/ps.ts
|
|
171678
|
+
var exports_ps = {};
|
|
171679
|
+
__export(exports_ps, {
|
|
171680
|
+
runPs: () => runPs
|
|
171490
171681
|
});
|
|
171491
171682
|
var killPid = (pid) => {
|
|
171492
171683
|
try {
|
|
@@ -171509,29 +171700,29 @@ var killPid = (pid) => {
|
|
|
171509
171700
|
getDurationString(instance.uptimeMs),
|
|
171510
171701
|
`${statusColor2(instance.status)}${instance.status}${colors.reset}`,
|
|
171511
171702
|
instance.url ?? "-"
|
|
171512
|
-
],
|
|
171703
|
+
], columnWidths3 = (rows) => TABLE_HEADERS.map((header, index) => Math.max(visibleLength(header), ...rows.map((cells) => visibleLength(cells[index] ?? "")))), renderRow = (cells, widths) => cells.map((cell, index) => padLine(cell, widths[index] ?? 0)).join(" ".repeat(LIST_TUI_COLUMN_GAP)), printInstanceTable = (instances) => {
|
|
171513
171704
|
if (instances.length === 0) {
|
|
171514
171705
|
process.stdout.write(`${colors.dim}No AbsoluteJS servers are running. Start one with \`absolute dev\`.${colors.reset}
|
|
171515
171706
|
`);
|
|
171516
171707
|
return;
|
|
171517
171708
|
}
|
|
171518
171709
|
const rows = instances.map(instanceCells);
|
|
171519
|
-
const widths =
|
|
171710
|
+
const widths = columnWidths3(rows);
|
|
171520
171711
|
process.stdout.write(`${colors.dim}${renderRow(TABLE_HEADERS, widths)}${colors.reset}
|
|
171521
171712
|
`);
|
|
171522
171713
|
for (const cells of rows) {
|
|
171523
171714
|
process.stdout.write(`${renderRow(cells, widths)}
|
|
171524
171715
|
`);
|
|
171525
171716
|
}
|
|
171526
|
-
},
|
|
171717
|
+
}, runPs = async (args) => {
|
|
171527
171718
|
process.stdout.on("error", (error) => {
|
|
171528
171719
|
if (error instanceof Error && "code" in error && error.code === "EPIPE") {
|
|
171529
171720
|
process.exit(0);
|
|
171530
171721
|
}
|
|
171531
171722
|
});
|
|
171532
171723
|
if (args.includes("--watch") || args.includes("-w")) {
|
|
171533
|
-
const {
|
|
171534
|
-
await
|
|
171724
|
+
const { runPsTui: runPsTui2 } = await Promise.resolve().then(() => (init_psTui(), exports_psTui));
|
|
171725
|
+
await runPsTui2();
|
|
171535
171726
|
return;
|
|
171536
171727
|
}
|
|
171537
171728
|
const instances = await enrichInstances(await discoverInstances());
|
|
@@ -171559,7 +171750,7 @@ var killPid = (pid) => {
|
|
|
171559
171750
|
}
|
|
171560
171751
|
printInstanceTable(instances);
|
|
171561
171752
|
};
|
|
171562
|
-
var
|
|
171753
|
+
var init_ps = __esm(() => {
|
|
171563
171754
|
init_constants();
|
|
171564
171755
|
init_getDurationString();
|
|
171565
171756
|
init_discoverInstances();
|
|
@@ -171577,8 +171768,8 @@ var init_list = __esm(() => {
|
|
|
171577
171768
|
});
|
|
171578
171769
|
|
|
171579
171770
|
// src/build/externalAssetPlugin.ts
|
|
171580
|
-
import { copyFileSync as copyFileSync2, existsSync as
|
|
171581
|
-
import { basename as basename4, dirname as dirname4, join as
|
|
171771
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync11, mkdirSync as mkdirSync7, statSync as statSync2 } from "fs";
|
|
171772
|
+
import { basename as basename4, dirname as dirname4, join as join12, resolve as resolve11 } from "path";
|
|
171582
171773
|
var createExternalAssetPlugin = (outDir, userSourceRoots = []) => ({
|
|
171583
171774
|
name: "absolute-external-asset",
|
|
171584
171775
|
setup(bld) {
|
|
@@ -171599,12 +171790,12 @@ var createExternalAssetPlugin = (outDir, userSourceRoots = []) => ({
|
|
|
171599
171790
|
if (!relPath)
|
|
171600
171791
|
continue;
|
|
171601
171792
|
const assetPath = resolve11(sourceDir, relPath);
|
|
171602
|
-
if (!
|
|
171793
|
+
if (!existsSync11(assetPath))
|
|
171603
171794
|
continue;
|
|
171604
|
-
if (!
|
|
171795
|
+
if (!statSync2(assetPath).isFile())
|
|
171605
171796
|
continue;
|
|
171606
|
-
const targetPath =
|
|
171607
|
-
if (
|
|
171797
|
+
const targetPath = join12(outDir, basename4(assetPath));
|
|
171798
|
+
if (existsSync11(targetPath))
|
|
171608
171799
|
continue;
|
|
171609
171800
|
mkdirSync7(dirname4(targetPath), { recursive: true });
|
|
171610
171801
|
copyFileSync2(assetPath, targetPath);
|
|
@@ -171624,16 +171815,16 @@ __export(exports_compile, {
|
|
|
171624
171815
|
var {env: env3 } = globalThis.Bun;
|
|
171625
171816
|
import {
|
|
171626
171817
|
cpSync,
|
|
171627
|
-
existsSync as
|
|
171818
|
+
existsSync as existsSync12,
|
|
171628
171819
|
mkdirSync as mkdirSync8,
|
|
171629
171820
|
readdirSync as readdirSync3,
|
|
171630
|
-
readFileSync as
|
|
171821
|
+
readFileSync as readFileSync14,
|
|
171631
171822
|
rmSync as rmSync4,
|
|
171632
|
-
statSync as
|
|
171823
|
+
statSync as statSync3,
|
|
171633
171824
|
unlinkSync as unlinkSync4,
|
|
171634
171825
|
writeFileSync as writeFileSync5
|
|
171635
171826
|
} from "fs";
|
|
171636
|
-
import { basename as basename5, dirname as dirname5, join as
|
|
171827
|
+
import { basename as basename5, dirname as dirname5, join as join13, relative as relative3, resolve as resolve12 } from "path";
|
|
171637
171828
|
var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[cli]\x1B[0m ${color}${message}\x1B[0m`, compileBanner = (version2) => {
|
|
171638
171829
|
const resolvedVersion = version2 || "unknown";
|
|
171639
171830
|
console.log("");
|
|
@@ -171646,7 +171837,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171646
171837
|
const entry = pending.pop();
|
|
171647
171838
|
if (!entry)
|
|
171648
171839
|
continue;
|
|
171649
|
-
const fullPath =
|
|
171840
|
+
const fullPath = join13(entry.parentPath, entry.name);
|
|
171650
171841
|
if (entry.isDirectory())
|
|
171651
171842
|
pending = pending.concat(readdirSync3(fullPath, { withFileTypes: true }));
|
|
171652
171843
|
else
|
|
@@ -171666,7 +171857,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171666
171857
|
const entry = pending.pop();
|
|
171667
171858
|
if (!entry)
|
|
171668
171859
|
continue;
|
|
171669
|
-
const fullPath =
|
|
171860
|
+
const fullPath = join13(entry.parentPath, entry.name);
|
|
171670
171861
|
if (entry.isDirectory()) {
|
|
171671
171862
|
if (SERVER_RUNTIME_SCAN_SKIP_DIRS.has(entry.name))
|
|
171672
171863
|
continue;
|
|
@@ -171681,7 +171872,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171681
171872
|
const normalizedOutdir = resolve12(outdir);
|
|
171682
171873
|
const copyReference = (filePath, relPath) => {
|
|
171683
171874
|
const assetSource = resolve12(dirname5(filePath), relPath);
|
|
171684
|
-
if (!
|
|
171875
|
+
if (!existsSync12(assetSource) || !statSync3(assetSource).isFile())
|
|
171685
171876
|
return;
|
|
171686
171877
|
const assetTarget = resolve12(normalizedOutdir, relPath.replace(/^\.\//, ""));
|
|
171687
171878
|
if (assetTarget !== normalizedOutdir && !assetTarget.startsWith(`${normalizedOutdir}/`))
|
|
@@ -171693,7 +171884,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171693
171884
|
cpSync(assetSource, assetTarget, { force: true });
|
|
171694
171885
|
};
|
|
171695
171886
|
for (const filePath of collectProjectSourceFiles(process.cwd())) {
|
|
171696
|
-
const source =
|
|
171887
|
+
const source = readFileSync14(filePath, "utf-8");
|
|
171697
171888
|
SERVER_RUNTIME_ASSET_RE.lastIndex = 0;
|
|
171698
171889
|
let match;
|
|
171699
171890
|
while ((match = SERVER_RUNTIME_ASSET_RE.exec(source)) !== null) {
|
|
@@ -171722,7 +171913,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171722
171913
|
}
|
|
171723
171914
|
}, readPackageVersion4 = (candidate) => {
|
|
171724
171915
|
try {
|
|
171725
|
-
const pkg = JSON.parse(
|
|
171916
|
+
const pkg = JSON.parse(readFileSync14(candidate, "utf-8"));
|
|
171726
171917
|
if (pkg.name !== "@absolutejs/absolute")
|
|
171727
171918
|
return null;
|
|
171728
171919
|
const ver = pkg.version;
|
|
@@ -171765,7 +171956,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171765
171956
|
resolve12(import.meta.dir, "..", "..", "..", "src", "react", "jsxDevRuntimeCompat.ts")
|
|
171766
171957
|
];
|
|
171767
171958
|
for (const candidate of candidates) {
|
|
171768
|
-
if (
|
|
171959
|
+
if (existsSync12(candidate))
|
|
171769
171960
|
return candidate;
|
|
171770
171961
|
}
|
|
171771
171962
|
return resolve12(import.meta.dir, "..", "..", "react", "jsxDevRuntimeCompat.js");
|
|
@@ -171781,7 +171972,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171781
171972
|
return true;
|
|
171782
171973
|
}, tryReadNodePackageJson = (packageDir) => {
|
|
171783
171974
|
try {
|
|
171784
|
-
return JSON.parse(
|
|
171975
|
+
return JSON.parse(readFileSync14(join13(packageDir, "package.json"), "utf-8"));
|
|
171785
171976
|
} catch {
|
|
171786
171977
|
return null;
|
|
171787
171978
|
}
|
|
@@ -171793,11 +171984,11 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171793
171984
|
if (!pkg)
|
|
171794
171985
|
return;
|
|
171795
171986
|
seen.add(specifier);
|
|
171796
|
-
const destDir =
|
|
171987
|
+
const destDir = join13(outdir, "node_modules", ...specifier.split("/"));
|
|
171797
171988
|
rmSync4(destDir, { force: true, recursive: true });
|
|
171798
171989
|
cpSync(srcDir, destDir, {
|
|
171799
171990
|
filter(source) {
|
|
171800
|
-
const rel =
|
|
171991
|
+
const rel = relative3(srcDir, source);
|
|
171801
171992
|
const [firstSegment] = rel.split(/[\\/]/);
|
|
171802
171993
|
return firstSegment !== "node_modules" && firstSegment !== ".git";
|
|
171803
171994
|
},
|
|
@@ -171816,7 +172007,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171816
172007
|
if (!buildConfig.angularDirectory)
|
|
171817
172008
|
return;
|
|
171818
172009
|
const angularScopeDir = resolve12(process.cwd(), "node_modules", "@angular");
|
|
171819
|
-
const angularPackages =
|
|
172010
|
+
const angularPackages = existsSync12(angularScopeDir) ? readdirSync3(angularScopeDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => entry.name !== "compiler-cli").map((entry) => `@angular/${entry.name}`) : [];
|
|
171820
172011
|
const roots = new Set([...angularPackages, "rxjs", "tslib", "typescript"]);
|
|
171821
172012
|
const seen = new Set;
|
|
171822
172013
|
for (const specifier of roots) {
|
|
@@ -171833,15 +172024,15 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171833
172024
|
}
|
|
171834
172025
|
copyAngularRuntimePackages(buildConfig, outdir);
|
|
171835
172026
|
}, collectRuntimePackageSpecifiers = (distDir) => {
|
|
171836
|
-
const nodeModulesDir =
|
|
171837
|
-
if (!
|
|
172027
|
+
const nodeModulesDir = join13(distDir, "node_modules");
|
|
172028
|
+
if (!existsSync12(nodeModulesDir))
|
|
171838
172029
|
return [];
|
|
171839
172030
|
const specifiers = [];
|
|
171840
172031
|
for (const entry of readdirSync3(nodeModulesDir, { withFileTypes: true })) {
|
|
171841
172032
|
if (!entry.isDirectory())
|
|
171842
172033
|
continue;
|
|
171843
172034
|
if (entry.name.startsWith("@")) {
|
|
171844
|
-
const scopeDir =
|
|
172035
|
+
const scopeDir = join13(nodeModulesDir, entry.name);
|
|
171845
172036
|
for (const scopedEntry of readdirSync3(scopeDir, {
|
|
171846
172037
|
withFileTypes: true
|
|
171847
172038
|
})) {
|
|
@@ -171855,7 +172046,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171855
172046
|
}
|
|
171856
172047
|
return specifiers.sort((a, b) => b.length - a.length);
|
|
171857
172048
|
}, ensureRelativeModuleSpecifier = (fromFile, toFile) => {
|
|
171858
|
-
const rel =
|
|
172049
|
+
const rel = relative3(dirname5(fromFile), toFile).replace(/\\/g, "/");
|
|
171859
172050
|
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
171860
172051
|
}, pickExportEntry = (value) => {
|
|
171861
172052
|
if (typeof value === "string")
|
|
@@ -171873,21 +172064,21 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171873
172064
|
const packageSpecifier = packageSpecifiers.find((root) => specifier === root || specifier.startsWith(`${root}/`));
|
|
171874
172065
|
if (!packageSpecifier)
|
|
171875
172066
|
return null;
|
|
171876
|
-
const packageDir =
|
|
172067
|
+
const packageDir = join13(distDir, "node_modules", ...packageSpecifier.split("/"));
|
|
171877
172068
|
const subpath = specifier.slice(packageSpecifier.length);
|
|
171878
|
-
const subPackageDir = subpath ?
|
|
171879
|
-
const resolvedPackageDir = subPackageDir &&
|
|
171880
|
-
const packageJsonPath =
|
|
171881
|
-
if (!
|
|
172069
|
+
const subPackageDir = subpath ? join13(packageDir, ...subpath.slice(1).split("/")) : null;
|
|
172070
|
+
const resolvedPackageDir = subPackageDir && existsSync12(join13(subPackageDir, "package.json")) ? subPackageDir : packageDir;
|
|
172071
|
+
const packageJsonPath = join13(resolvedPackageDir, "package.json");
|
|
172072
|
+
if (!existsSync12(packageJsonPath))
|
|
171882
172073
|
return null;
|
|
171883
|
-
const pkg = JSON.parse(
|
|
172074
|
+
const pkg = JSON.parse(readFileSync14(packageJsonPath, "utf-8"));
|
|
171884
172075
|
const exportKey = resolvedPackageDir === subPackageDir ? "." : subpath ? `.${subpath}` : ".";
|
|
171885
172076
|
const rootExport = pkg.exports?.[exportKey];
|
|
171886
172077
|
const entry = pickExportEntry(rootExport) ?? (resolvedPackageDir === subPackageDir || !subpath ? pkg.module ?? pkg.main ?? "index.js" : `.${subpath}`);
|
|
171887
|
-
return
|
|
172078
|
+
return join13(resolvedPackageDir, entry);
|
|
171888
172079
|
}, RUNTIME_JS_EXTENSIONS, MODULE_SPECIFIER_RE, isRuntimeJsFile = (filePath) => RUNTIME_JS_EXTENSIONS.some((extension) => filePath.endsWith(extension)), isNodeModulesPath = (filePath) => filePath.split(/[\\/]/).includes("node_modules"), isFile = (filePath) => {
|
|
171889
172080
|
try {
|
|
171890
|
-
return
|
|
172081
|
+
return statSync3(filePath).isFile();
|
|
171891
172082
|
} catch {
|
|
171892
172083
|
return false;
|
|
171893
172084
|
}
|
|
@@ -171897,13 +172088,13 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171897
172088
|
const candidates = [
|
|
171898
172089
|
candidate,
|
|
171899
172090
|
...RUNTIME_JS_EXTENSIONS.map((extension) => `${candidate}${extension}`),
|
|
171900
|
-
...RUNTIME_JS_EXTENSIONS.map((extension) =>
|
|
172091
|
+
...RUNTIME_JS_EXTENSIONS.map((extension) => join13(candidate, `index${extension}`))
|
|
171901
172092
|
];
|
|
171902
172093
|
return candidates.find((filePath) => isRuntimeJsFile(filePath) && isFile(filePath)) ?? null;
|
|
171903
172094
|
}, findContainingRuntimePackageDir = (filePath) => {
|
|
171904
172095
|
let dir = dirname5(filePath);
|
|
171905
172096
|
while (dir !== dirname5(dir)) {
|
|
171906
|
-
if (isNodeModulesPath(dir) &&
|
|
172097
|
+
if (isNodeModulesPath(dir) && existsSync12(join13(dir, "package.json"))) {
|
|
171907
172098
|
return dir;
|
|
171908
172099
|
}
|
|
171909
172100
|
dir = dirname5(dir);
|
|
@@ -171919,7 +172110,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171919
172110
|
const entry = pickExportEntry(pkg?.imports?.[specifier]);
|
|
171920
172111
|
if (!entry)
|
|
171921
172112
|
return null;
|
|
171922
|
-
return
|
|
172113
|
+
return join13(packageDir, entry);
|
|
171923
172114
|
}, collectRuntimeRewriteRoots = (distDir) => collectFiles2(distDir).filter((filePath) => isRuntimeJsFile(filePath) && !isNodeModulesPath(filePath)), rewriteRuntimeModuleSpecifiers = (distDir) => {
|
|
171924
172115
|
const packageSpecifiers = collectRuntimePackageSpecifiers(distDir);
|
|
171925
172116
|
if (packageSpecifiers.length === 0)
|
|
@@ -171938,7 +172129,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171938
172129
|
if (!filePath || seen.has(filePath))
|
|
171939
172130
|
continue;
|
|
171940
172131
|
seen.add(filePath);
|
|
171941
|
-
const source =
|
|
172132
|
+
const source = readFileSync14(filePath, "utf-8");
|
|
171942
172133
|
const rewritten = source.replace(MODULE_SPECIFIER_RE, (match, prefix, quote, specifier) => {
|
|
171943
172134
|
if (typeof specifier === "string" && specifier.startsWith(".")) {
|
|
171944
172135
|
enqueue(resolveRuntimeJsFile(resolve12(dirname5(filePath), specifier)));
|
|
@@ -171969,25 +172160,25 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
171969
172160
|
"_compile_entrypoint.ts"
|
|
171970
172161
|
]);
|
|
171971
172162
|
const embeddedFiles = allFiles.filter((file) => {
|
|
171972
|
-
const rel =
|
|
172163
|
+
const rel = relative3(distDir, file);
|
|
171973
172164
|
if (embeddedSkip.has(rel))
|
|
171974
172165
|
return false;
|
|
171975
172166
|
return true;
|
|
171976
172167
|
});
|
|
171977
|
-
const clientFiles = embeddedFiles.filter((file) => shouldEmbedCompiledAsset(
|
|
172168
|
+
const clientFiles = embeddedFiles.filter((file) => shouldEmbedCompiledAsset(relative3(distDir, file), assetSkip));
|
|
171978
172169
|
const imports = [];
|
|
171979
172170
|
const embeddedMappings = [];
|
|
171980
172171
|
const mappings = [];
|
|
171981
172172
|
const embeddedVarMap = new Map;
|
|
171982
172173
|
embeddedFiles.forEach((filePath, idx) => {
|
|
171983
|
-
const rel =
|
|
172174
|
+
const rel = relative3(distDir, filePath).replace(/\\/g, "/");
|
|
171984
172175
|
const varName = `__a${idx}`;
|
|
171985
172176
|
embeddedVarMap.set(rel, varName);
|
|
171986
172177
|
imports.push(`import ${varName} from "./${rel}" with { type: "file" };`);
|
|
171987
172178
|
embeddedMappings.push(` ["${rel}", ${varName}],`);
|
|
171988
172179
|
});
|
|
171989
172180
|
clientFiles.forEach((filePath) => {
|
|
171990
|
-
const rel =
|
|
172181
|
+
const rel = relative3(distDir, filePath).replace(/\\/g, "/");
|
|
171991
172182
|
const varName = embeddedVarMap.get(rel);
|
|
171992
172183
|
if (!varName)
|
|
171993
172184
|
return;
|
|
@@ -172001,7 +172192,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
172001
172192
|
const pageVarMap = new Map;
|
|
172002
172193
|
const prerenderEntries = Array.from(prerenderMap.entries());
|
|
172003
172194
|
prerenderEntries.forEach(([route, filePath]) => {
|
|
172004
|
-
const rel =
|
|
172195
|
+
const rel = relative3(distDir, filePath).replace(/\\/g, "/");
|
|
172005
172196
|
const varName = embeddedVarMap.get(rel);
|
|
172006
172197
|
if (varName)
|
|
172007
172198
|
pageVarMap.set(route, varName);
|
|
@@ -172231,7 +172422,7 @@ const server = Bun.serve({
|
|
|
172231
172422
|
},
|
|
172232
172423
|
});
|
|
172233
172424
|
|
|
172234
|
-
// Register in the global instance registry so 'absolute
|
|
172425
|
+
// Register in the global instance registry so 'absolute ps' can see this
|
|
172235
172426
|
// compiled binary. Best-effort; never blocks startup. Dead entries are pruned
|
|
172236
172427
|
// on read, so a hard kill that skips the exit handler is harmless.
|
|
172237
172428
|
try {
|
|
@@ -172466,11 +172657,11 @@ console.log(\`
|
|
|
172466
172657
|
process.exit(1);
|
|
172467
172658
|
}
|
|
172468
172659
|
const outputPath = resolve12(resolvedOutdir, `${entryName}.js`);
|
|
172469
|
-
if (!
|
|
172660
|
+
if (!existsSync12(outputPath)) {
|
|
172470
172661
|
console.error(cliTag4("\x1B[31m", `Expected output not found: ${outputPath}`));
|
|
172471
172662
|
process.exit(1);
|
|
172472
172663
|
}
|
|
172473
|
-
if (
|
|
172664
|
+
if (existsSync12(resolve12(resolvedOutdir, "angular", "vendor", "server"))) {
|
|
172474
172665
|
const vendorDir = resolve12(resolvedOutdir, "angular", "vendor", "server");
|
|
172475
172666
|
const vendorEntries = readdirSync3(vendorDir).filter((f) => f.endsWith(".js"));
|
|
172476
172667
|
const angularServerVendorPaths = {};
|
|
@@ -172480,7 +172671,7 @@ console.log(\`
|
|
|
172480
172671
|
if (scope !== "angular" || rest.length === 0)
|
|
172481
172672
|
continue;
|
|
172482
172673
|
const specifier = `@angular/${rest.join("/")}`;
|
|
172483
|
-
const relPath =
|
|
172674
|
+
const relPath = relative3(dirname5(outputPath), resolve12(vendorDir, file));
|
|
172484
172675
|
angularServerVendorPaths[specifier] = relPath.startsWith(".") ? relPath : `./${relPath}`;
|
|
172485
172676
|
}
|
|
172486
172677
|
if (Object.keys(angularServerVendorPaths).length > 0) {
|
|
@@ -172492,7 +172683,7 @@ console.log(\`
|
|
|
172492
172683
|
copyServerRuntimeAssetReferences(resolvedOutdir);
|
|
172493
172684
|
const prerenderStart = performance.now();
|
|
172494
172685
|
process.stdout.write(cliTag4("\x1B[36m", "Pre-rendering pages"));
|
|
172495
|
-
rmSync4(
|
|
172686
|
+
rmSync4(join13(resolvedOutdir, "_prerendered"), {
|
|
172496
172687
|
force: true,
|
|
172497
172688
|
recursive: true
|
|
172498
172689
|
});
|
|
@@ -172511,7 +172702,7 @@ console.log(\`
|
|
|
172511
172702
|
const compileStart = performance.now();
|
|
172512
172703
|
process.stdout.write(cliTag4("\x1B[36m", "Compiling standalone executable"));
|
|
172513
172704
|
const entrypointCode = generateEntrypoint(resolvedOutdir, serverEntry, prerenderMap, absoluteVersion, buildConfig);
|
|
172514
|
-
const entrypointPath =
|
|
172705
|
+
const entrypointPath = join13(resolvedOutdir, "_compile_entrypoint.ts");
|
|
172515
172706
|
await Bun.write(entrypointPath, entrypointCode);
|
|
172516
172707
|
mkdirSync8(dirname5(resolvedOutfile), { recursive: true });
|
|
172517
172708
|
const result = await Bun.build({
|
|
@@ -172607,11 +172798,11 @@ var exports_typecheck = {};
|
|
|
172607
172798
|
__export(exports_typecheck, {
|
|
172608
172799
|
typecheck: () => typecheck
|
|
172609
172800
|
});
|
|
172610
|
-
import { resolve as resolve13, join as
|
|
172611
|
-
import { existsSync as
|
|
172801
|
+
import { resolve as resolve13, join as join14 } from "path";
|
|
172802
|
+
import { existsSync as existsSync13, readFileSync as readFileSync15 } from "fs";
|
|
172612
172803
|
import { mkdir as mkdir2, writeFile } from "fs/promises";
|
|
172613
172804
|
var isCommandService3 = (service) => service.kind === "command" || Array.isArray(service.command), resolveConfigPath = (configPath2) => resolve13(configPath2 ?? process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts"), getTypecheckTargets = async (configPath2) => {
|
|
172614
|
-
if (!
|
|
172805
|
+
if (!existsSync13(resolveConfigPath(configPath2))) {
|
|
172615
172806
|
return [{}];
|
|
172616
172807
|
}
|
|
172617
172808
|
const rawConfig = await loadRawConfig(configPath2);
|
|
@@ -172632,7 +172823,7 @@ var isCommandService3 = (service) => service.kind === "command" || Array.isArray
|
|
|
172632
172823
|
return { exitCode, name, output: (stdout + stderr).trim() };
|
|
172633
172824
|
}, shellEscape = (value) => `'${value.replaceAll("'", "'\\''")}'`, runShell = async (name, command) => run(name, ["/bin/bash", "-lc", command]), findBin = (name) => {
|
|
172634
172825
|
const local = resolve13("node_modules", ".bin", name);
|
|
172635
|
-
return
|
|
172826
|
+
return existsSync13(local) ? local : null;
|
|
172636
172827
|
}, ANSI_COLOR_REGEX, ANSI_PURPLE_REGEX, ANSI_CYAN_REGEX, ANSI_TOKEN_END_REGEX, stripAnsi3 = (str) => str.replace(ANSI_COLOR_REGEX, ""), formatSvelteOutput = (output) => {
|
|
172637
172828
|
const cwd = `${process.cwd()}/`;
|
|
172638
172829
|
const summaryMatch = stripAnsi3(output).match(/svelte-check found (\d+) error/);
|
|
@@ -172684,10 +172875,10 @@ Found ${errorCount} error${suffix}.`;
|
|
|
172684
172875
|
resolve13(import.meta.dir, "../../types", fileName),
|
|
172685
172876
|
resolve13(import.meta.dir, "../../../types", fileName)
|
|
172686
172877
|
];
|
|
172687
|
-
return candidates.find((candidate) =>
|
|
172878
|
+
return candidates.find((candidate) => existsSync13(candidate)) ?? candidates[0];
|
|
172688
172879
|
}, ABSOLUTE_TYPECHECK_FILES, readProjectTsconfig = () => {
|
|
172689
172880
|
try {
|
|
172690
|
-
return JSON.parse(
|
|
172881
|
+
return JSON.parse(readFileSync15(resolve13("tsconfig.json"), "utf-8"));
|
|
172691
172882
|
} catch {
|
|
172692
172883
|
return {};
|
|
172693
172884
|
}
|
|
@@ -172715,7 +172906,7 @@ Found ${errorCount} error${suffix}.`;
|
|
|
172715
172906
|
console.error("\x1B[31m\u2717\x1B[0m vue-tsc is required for Vue type checking. Install it: bun add -d vue-tsc");
|
|
172716
172907
|
process.exit(1);
|
|
172717
172908
|
}
|
|
172718
|
-
const vueTsconfigPath =
|
|
172909
|
+
const vueTsconfigPath = join14(cacheDir, "tsconfig.vue-check.json");
|
|
172719
172910
|
return writeFile(vueTsconfigPath, JSON.stringify({
|
|
172720
172911
|
compilerOptions: {
|
|
172721
172912
|
rootDir: ".."
|
|
@@ -172730,7 +172921,7 @@ Found ${errorCount} error${suffix}.`;
|
|
|
172730
172921
|
resolve13(vueTsconfigPath),
|
|
172731
172922
|
"--incremental",
|
|
172732
172923
|
"--tsBuildInfoFile",
|
|
172733
|
-
|
|
172924
|
+
join14(cacheDir, "vue-tsc.tsbuildinfo"),
|
|
172734
172925
|
"--pretty"
|
|
172735
172926
|
]));
|
|
172736
172927
|
}, buildAngularCheck = async (cacheDir, angularDir) => {
|
|
@@ -172739,7 +172930,7 @@ Found ${errorCount} error${suffix}.`;
|
|
|
172739
172930
|
console.error("\x1B[31m\u2717\x1B[0m @angular/compiler-cli is required for Angular type checking. Install it: bun add -d @angular/compiler-cli");
|
|
172740
172931
|
process.exit(1);
|
|
172741
172932
|
}
|
|
172742
|
-
const angularTsconfigPath =
|
|
172933
|
+
const angularTsconfigPath = join14(cacheDir, "tsconfig.angular-check.json");
|
|
172743
172934
|
await writeFile(angularTsconfigPath, JSON.stringify({
|
|
172744
172935
|
angularCompilerOptions: {
|
|
172745
172936
|
strictTemplates: true
|
|
@@ -172759,7 +172950,7 @@ Found ${errorCount} error${suffix}.`;
|
|
|
172759
172950
|
console.error("\x1B[31m\u2717\x1B[0m typescript is required for type checking. Install it: bun add -d typescript");
|
|
172760
172951
|
process.exit(1);
|
|
172761
172952
|
}
|
|
172762
|
-
const tscConfigPath =
|
|
172953
|
+
const tscConfigPath = join14(cacheDir, "tsconfig.typecheck.json");
|
|
172763
172954
|
return writeFile(tscConfigPath, JSON.stringify({
|
|
172764
172955
|
compilerOptions: {
|
|
172765
172956
|
rootDir: ".."
|
|
@@ -172774,7 +172965,7 @@ Found ${errorCount} error${suffix}.`;
|
|
|
172774
172965
|
resolve13(tscConfigPath),
|
|
172775
172966
|
"--incremental",
|
|
172776
172967
|
"--tsBuildInfoFile",
|
|
172777
|
-
|
|
172968
|
+
join14(cacheDir, "tsc.tsbuildinfo"),
|
|
172778
172969
|
"--pretty"
|
|
172779
172970
|
]));
|
|
172780
172971
|
}, buildSvelteCheck = async (cacheDir, svelteDir) => {
|
|
@@ -172783,7 +172974,7 @@ Found ${errorCount} error${suffix}.`;
|
|
|
172783
172974
|
console.error("\x1B[31m\u2717\x1B[0m svelte-check is required for Svelte type checking. Install it: bun add -d svelte-check");
|
|
172784
172975
|
process.exit(1);
|
|
172785
172976
|
}
|
|
172786
|
-
const svelteTsconfigPath =
|
|
172977
|
+
const svelteTsconfigPath = join14(cacheDir, "tsconfig.svelte-check.json");
|
|
172787
172978
|
await writeFile(svelteTsconfigPath, JSON.stringify({
|
|
172788
172979
|
extends: resolve13("tsconfig.json"),
|
|
172789
172980
|
files: ABSOLUTE_TYPECHECK_FILES,
|
|
@@ -176419,10 +176610,14 @@ if (command === "dev") {
|
|
|
176419
176610
|
} else if (command === "prettier") {
|
|
176420
176611
|
sendTelemetryEvent("cli:command", { command });
|
|
176421
176612
|
await prettier(args);
|
|
176422
|
-
} else if (command === "ls"
|
|
176613
|
+
} else if (command === "ls") {
|
|
176423
176614
|
sendTelemetryEvent("cli:command", { command: "ls" });
|
|
176424
|
-
const {
|
|
176425
|
-
await
|
|
176615
|
+
const { runLs: runLs2 } = await Promise.resolve().then(() => (init_ls(), exports_ls));
|
|
176616
|
+
await runLs2(args);
|
|
176617
|
+
} else if (command === "ps") {
|
|
176618
|
+
sendTelemetryEvent("cli:command", { command: "ps" });
|
|
176619
|
+
const { runPs: runPs2 } = await Promise.resolve().then(() => (init_ps(), exports_ps));
|
|
176620
|
+
await runPs2(args);
|
|
176426
176621
|
} else if (command === "info") {
|
|
176427
176622
|
sendTelemetryEvent("cli:command", { command });
|
|
176428
176623
|
info();
|
|
@@ -176464,7 +176659,8 @@ if (command === "dev") {
|
|
|
176464
176659
|
console.error(" config [--port n] Open the unified config UI (ESLint, tsconfig, Prettier)");
|
|
176465
176660
|
console.error(" eslint Run ESLint (cached)");
|
|
176466
176661
|
console.error(" info Print system info for bug reports");
|
|
176467
|
-
console.error(" ls [--
|
|
176662
|
+
console.error(" ls [--all] [--json] List the project's built pages, islands, and assets");
|
|
176663
|
+
console.error(" ps [--watch] [--json] [--kill <pid|port>] [--kill-all] List/manage running servers");
|
|
176468
176664
|
console.error(" prettier Run Prettier check (cached)");
|
|
176469
176665
|
console.error(" typecheck Run type checkers for all frameworks");
|
|
176470
176666
|
console.error(" telemetry Manage anonymous telemetry");
|
package/dist/index.js.map
CHANGED
|
@@ -159,7 +159,7 @@
|
|
|
159
159
|
"import { resolve } from 'node:path';\nimport type { IslandRegistryInput } from '../../types/island';\nimport { loadIslandRegistryBuildInfo } from '../build/islandEntries';\n\ntype RegistryModuleExport = {\n\tdefault?: unknown;\n\tislandRegistry?: unknown;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n\ttypeof value === 'object' && value !== null;\n\nconst resolveRegistryExport = (mod: RegistryModuleExport) => {\n\tif (isRecord(mod.islandRegistry)) return mod.islandRegistry;\n\tif (isRecord(mod.default)) return mod.default;\n\n\tthrow new Error(\n\t\t'Island registry module must export `islandRegistry` or a default registry object.'\n\t);\n};\n\nconst isRegistryModuleExport = (\n\tvalue: unknown\n): value is RegistryModuleExport => isRecord(value);\n\nconst isIslandRegistryInput = (value: unknown): value is IslandRegistryInput =>\n\tisRecord(value);\n\nexport const loadIslandRegistry = async (registryPath: string) => {\n\tconst resolvedRegistryPath = resolve(registryPath);\n\tconst buildInfo = await loadIslandRegistryBuildInfo(resolvedRegistryPath);\n\tif (buildInfo.definitions.length > 0) {\n\t\treturn buildInfo.registry;\n\t}\n\n\tconst importedModule: unknown = await import(resolvedRegistryPath);\n\tif (!isRegistryModuleExport(importedModule)) {\n\t\tthrow new Error(\n\t\t\t'Island registry module must export an object namespace.'\n\t\t);\n\t}\n\n\tconst registryExport = resolveRegistryExport(importedModule);\n\tif (!isIslandRegistryInput(registryExport)) {\n\t\tthrow new Error('Resolved island registry export is not an object.');\n\t}\n\n\treturn registryExport;\n};\n",
|
|
160
160
|
"import { basename } from 'node:path';\nimport type { ConventionsMap, ErrorPageProps } from '../../types/conventions';\nimport { toPascal } from './stringModifiers';\n\n// Use globalThis so the conventions map is shared across all bundles.\n// The main bundle (dist/index.js) calls setConventions, but framework\n// bundles (dist/svelte/index.js, etc.) need to read the same map.\nconst CONVENTIONS_KEY = '__absoluteConventions';\n\nconst isConventionsMap = (value: unknown): value is ConventionsMap =>\n\tBoolean(value) && typeof value === 'object';\n\nconst getMap = () => {\n\tconst value: unknown = Reflect.get(globalThis, CONVENTIONS_KEY);\n\tif (isConventionsMap(value)) return value;\n\n\tconst empty: ConventionsMap = {};\n\n\treturn empty;\n};\n\nexport const derivePageName = (pagePath: string) => {\n\tconst base = basename(pagePath);\n\t// Strip hash and extension: \"SvelteExample.abc123.js\" → \"SvelteExample\"\n\tconst dotIndex = base.indexOf('.');\n\tconst name = dotIndex > 0 ? base.slice(0, dotIndex) : base;\n\n\treturn toPascal(name);\n};\nexport const getConventions = () => getMap();\n\nconst normalizeConventionPageName = (name: string) =>\n\ttoPascal(name).replace(/\\d+$/, '');\n\nexport const resolveErrorConventionPath = (\n\tframework: keyof ConventionsMap,\n\tpageName: string\n) => {\n\tconst conventions = getMap()[framework];\n\tif (!conventions) return undefined;\n\n\tconst exact = conventions.pages?.[pageName]?.error;\n\tif (exact) return exact;\n\n\tconst normalizedPageName = normalizeConventionPageName(pageName);\n\tfor (const [candidate, page] of Object.entries(conventions.pages ?? {})) {\n\t\tif (normalizeConventionPageName(candidate) === normalizedPageName) {\n\t\t\treturn page.error ?? conventions.defaults?.error;\n\t\t}\n\t}\n\n\treturn conventions.defaults?.error;\n};\nexport const resolveNotFoundConventionPath = (\n\tframework: keyof ConventionsMap\n) => getMap()[framework]?.defaults?.notFound;\n\nexport const hasErrorConvention = (framework: keyof ConventionsMap) => {\n\tconst conventions = getMap()[framework];\n\tif (!conventions) return false;\n\tif (conventions.defaults?.error) return true;\n\n\treturn Object.values(conventions.pages ?? {}).some((page) =>\n\t\tBoolean(page.error)\n\t);\n};\n\nexport const setConventions = (map: ConventionsMap) => {\n\tReflect.set(globalThis, CONVENTIONS_KEY, map);\n};\n\nconst isDev = () => process.env.NODE_ENV === 'development';\n\nconst buildErrorProps = (error: unknown): ErrorPageProps => {\n\tif (error instanceof Error) {\n\t\treturn {\n\t\t\tname: error.name,\n\t\t\tmessage: error.message,\n\t\t\t...(isDev() && error.stack ? { stack: error.stack } : {})\n\t\t};\n\t}\n\n\treturn { name: 'Error', message: String(error) };\n};\n\nconst renderReactError = async (\n\tconventionPath: string,\n\terrorProps: ErrorPageProps\n) => {\n\tconst { createElement } = await import('react');\n\tconst { renderToReadableStream } = await import('react-dom/server');\n\tconst mod = await import(conventionPath);\n\tconst ErrorComponent = mod.default;\n\tif (typeof ErrorComponent !== 'function') return null;\n\n\tconst element = createElement(ErrorComponent, errorProps);\n\tconst stream = await renderToReadableStream(element);\n\n\treturn new Response(stream, {\n\t\theaders: { 'Content-Type': 'text/html' },\n\t\tstatus: 500\n\t});\n};\n\nconst renderSvelteError = async (\n\tconventionPath: string,\n\terrorProps: ErrorPageProps\n) => {\n\tconst { render } = await import('svelte/server');\n\tconst mod = await import(conventionPath);\n\tconst ErrorComponent = mod.default;\n\tif (!ErrorComponent) return null;\n\n\tconst { head, body } = render(ErrorComponent, {\n\t\tprops: errorProps\n\t});\n\tconst html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;\n\n\treturn new Response(html, {\n\t\theaders: { 'Content-Type': 'text/html' },\n\t\tstatus: 500\n\t});\n};\n\nconst unescapeVueStyles = (ssrBody: string) => {\n\tlet styles = '';\n\tconst body = ssrBody.replace(\n\t\t/<style>([\\s\\S]*?)<\\/style>/g,\n\t\t(_, css: string) => {\n\t\t\tstyles += `<style>${css\n\t\t\t\t.replace(/"/g, '\"')\n\t\t\t\t.replace(/&/g, '&')\n\t\t\t\t.replace(/</g, '<')\n\t\t\t\t.replace(/>/g, '>')}</style>`;\n\n\t\t\treturn '';\n\t\t}\n\t);\n\n\treturn { body, styles };\n};\n\nconst renderVueError = async (\n\tconventionPath: string,\n\terrorProps: ErrorPageProps\n) => {\n\tconst { createSSRApp, h } = await import('vue');\n\tconst { renderToString } = await import('vue/server-renderer');\n\tconst mod = await import(conventionPath);\n\tconst ErrorComponent = mod.default;\n\tif (!ErrorComponent) return null;\n\n\tconst app = createSSRApp({\n\t\trender: () => h(ErrorComponent, errorProps)\n\t});\n\tconst rawBody = await renderToString(app);\n\n\t// Vue SSR escapes quotes inside <component is=\"style\"> tags.\n\t// Extract style content, unescape it, and move to <head>.\n\tconst { styles, body } = unescapeVueStyles(rawBody);\n\tconst html = `<!DOCTYPE html><html><head>${styles}</head><body><div id=\"root\">${body}</div></body></html>`;\n\n\treturn new Response(html, {\n\t\theaders: { 'Content-Type': 'text/html' },\n\t\tstatus: 500\n\t});\n};\n\nconst renderAngularError = async (\n\tconventionPath: string,\n\terrorProps: ErrorPageProps\n) => {\n\t// Angular convention error pages use the simple function-style renderer.\n\t// Class-style components (templateUrl/styleUrl trio) routed through the\n\t// full Angular SSR pipeline are tracked separately — see CLAUDE.md.\n\tconst mod = await import(conventionPath);\n\tconst renderFn = mod.default;\n\tif (typeof renderFn !== 'function') return null;\n\n\tconst html = renderFn(errorProps);\n\n\treturn new Response(html, {\n\t\theaders: { 'Content-Type': 'text/html' },\n\t\tstatus: 500\n\t});\n};\n\nconst escapeHtml = (value: string) =>\n\tvalue\n\t\t.replace(/&/g, '&')\n\t\t.replace(/</g, '<')\n\t\t.replace(/>/g, '>')\n\t\t.replace(/\"/g, '"')\n\t\t.replace(/'/g, ''');\n\nconst replaceErrorTokens = (template: string, errorProps: ErrorPageProps) =>\n\ttemplate\n\t\t.replace(/\\{\\{\\s*name\\s*\\}\\}/g, escapeHtml(errorProps.name))\n\t\t.replace(/\\{\\{\\s*message\\s*\\}\\}/g, escapeHtml(errorProps.message))\n\t\t.replace(\n\t\t\t/\\{\\{\\s*stack\\s*\\}\\}/g,\n\t\t\terrorProps.stack ? escapeHtml(errorProps.stack) : ''\n\t\t);\n\nconst renderHtmlError = async (\n\tconventionPath: string,\n\terrorProps: ErrorPageProps\n) => {\n\tconst template = await Bun.file(conventionPath).text();\n\tconst html = replaceErrorTokens(template, errorProps);\n\n\treturn new Response(html, {\n\t\theaders: { 'Content-Type': 'text/html' },\n\t\tstatus: 500\n\t});\n};\n\nconst logConventionRenderError = (\n\tframework: keyof ConventionsMap,\n\tlabel: string,\n\trenderError: unknown\n) => {\n\tconst message = renderError instanceof Error ? renderError.message : '';\n\tif (\n\t\tmessage.includes('Cannot find module') ||\n\t\tmessage.includes('Cannot find package') ||\n\t\tmessage.includes('not found in module')\n\t) {\n\t\tconsole.error(\n\t\t\t`[SSR] Convention ${label} page for ${framework} failed: missing framework package. ` +\n\t\t\t\t`Ensure the ${framework} runtime is installed (e.g. bun add ${framework === 'react' ? 'react react-dom' : framework}).`\n\t\t);\n\n\t\treturn;\n\t}\n\n\tconsole.error(\n\t\t`[SSR] Failed to render ${framework} convention ${label} page:`,\n\t\trenderError\n\t);\n};\n\n// Phase 1 Ember adapter: convention pages aren't wired yet (no\n// renderEmberError analog ships in v1). Returning null falls through to\n// the generic ssrErrorPage. Phase 1.5 replaces this stub with a real\n// renderer once the convention scanner knows about .gjs/.gts files.\nconst renderEmberError = async () => null;\nconst renderEmberNotFound = async () => null;\n\nconst ERROR_RENDERERS: Record<\n\tkeyof ConventionsMap,\n\t(\n\t\tconventionPath: string,\n\t\terrorProps: ErrorPageProps\n\t) => Promise<Response | null>\n> = {\n\tangular: renderAngularError,\n\tember: renderEmberError,\n\thtml: renderHtmlError,\n\treact: renderReactError,\n\tsvelte: renderSvelteError,\n\tvue: renderVueError\n};\n\nconst tryFrameworkErrorConvention = async (\n\tframework: keyof ConventionsMap,\n\tpageName: string,\n\terrorProps: ErrorPageProps,\n\terror: unknown\n) => {\n\tlet conventionPath = resolveErrorConventionPath(framework, pageName);\n\tif (!conventionPath && error instanceof Error && error.stack) {\n\t\tfor (const match of error.stack.matchAll(\n\t\t\t/^\\s*at\\s+([A-Za-z_$][\\w$]*)/gm\n\t\t)) {\n\t\t\tconst candidate = match[1];\n\t\t\tif (!candidate) continue;\n\n\t\t\tconventionPath = resolveErrorConventionPath(framework, candidate);\n\t\t\tif (conventionPath) break;\n\t\t}\n\t}\n\tif (!conventionPath) return null;\n\n\tconst renderer = ERROR_RENDERERS[framework];\n\tif (!renderer) return null;\n\n\ttry {\n\t\treturn await renderer(conventionPath, errorProps);\n\t} catch (renderError) {\n\t\tlogConventionRenderError(framework, 'error', renderError);\n\t}\n\n\treturn null;\n};\n\nexport const renderConventionError = async (\n\tframework: keyof ConventionsMap,\n\tpageName: string,\n\terror: unknown\n) => {\n\tconst errorProps = buildErrorProps(error);\n\n\tconst frameworkResponse = await tryFrameworkErrorConvention(\n\t\tframework,\n\t\tpageName,\n\t\terrorProps,\n\t\terror\n\t);\n\tif (frameworkResponse) return frameworkResponse;\n\n\t// Universal fallback: any project can ship a plain `error.html` in\n\t// the html pages dir as the last-resort branded error page before\n\t// the inline ssrErrorPage() takes over.\n\tif (framework !== 'html') {\n\t\tconst htmlResponse = await tryFrameworkErrorConvention(\n\t\t\t'html',\n\t\t\tpageName,\n\t\t\terrorProps,\n\t\t\terror\n\t\t);\n\t\tif (htmlResponse) return htmlResponse;\n\t}\n\n\treturn null;\n};\n\nconst renderReactNotFound = async (conventionPath: string) => {\n\tconst { createElement } = await import('react');\n\tconst { renderToReadableStream } = await import('react-dom/server');\n\tconst mod = await import(conventionPath);\n\tconst NotFoundComponent = mod.default;\n\tif (typeof NotFoundComponent !== 'function') return null;\n\n\tconst element = createElement(NotFoundComponent);\n\tconst stream = await renderToReadableStream(element);\n\n\treturn new Response(stream, {\n\t\theaders: { 'Content-Type': 'text/html' },\n\t\tstatus: 404\n\t});\n};\n\nconst renderSvelteNotFound = async (conventionPath: string) => {\n\tconst { render } = await import('svelte/server');\n\tconst mod = await import(conventionPath);\n\tconst NotFoundComponent = mod.default;\n\tif (!NotFoundComponent) return null;\n\n\tconst { head, body } = render(NotFoundComponent);\n\tconst html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;\n\n\treturn new Response(html, {\n\t\theaders: { 'Content-Type': 'text/html' },\n\t\tstatus: 404\n\t});\n};\n\nconst renderVueNotFound = async (conventionPath: string) => {\n\tconst { createSSRApp, h } = await import('vue');\n\tconst { renderToString } = await import('vue/server-renderer');\n\tconst mod = await import(conventionPath);\n\tconst NotFoundComponent = mod.default;\n\tif (!NotFoundComponent) return null;\n\n\tconst app = createSSRApp({\n\t\trender: () => h(NotFoundComponent)\n\t});\n\tconst rawBody = await renderToString(app);\n\n\tconst { styles, body } = unescapeVueStyles(rawBody);\n\tconst html = `<!DOCTYPE html><html><head>${styles}</head><body><div id=\"root\">${body}</div></body></html>`;\n\n\treturn new Response(html, {\n\t\theaders: { 'Content-Type': 'text/html' },\n\t\tstatus: 404\n\t});\n};\n\nconst renderAngularNotFound = async (conventionPath: string) => {\n\tconst mod = await import(conventionPath);\n\tconst renderFn = mod.default;\n\tif (typeof renderFn !== 'function') return null;\n\n\tconst html = renderFn();\n\n\treturn new Response(html, {\n\t\theaders: { 'Content-Type': 'text/html' },\n\t\tstatus: 404\n\t});\n};\n\nconst renderHtmlNotFound = async (conventionPath: string) => {\n\tconst html = await Bun.file(conventionPath).text();\n\n\treturn new Response(html, {\n\t\theaders: { 'Content-Type': 'text/html' },\n\t\tstatus: 404\n\t});\n};\n\nconst NOT_FOUND_RENDERERS: Record<\n\tkeyof ConventionsMap,\n\t(conventionPath: string) => Promise<Response | null>\n> = {\n\tangular: renderAngularNotFound,\n\tember: renderEmberNotFound,\n\thtml: renderHtmlNotFound,\n\treact: renderReactNotFound,\n\tsvelte: renderSvelteNotFound,\n\tvue: renderVueNotFound\n};\n\nexport const renderConventionNotFound = async (\n\tframework: keyof ConventionsMap\n) => {\n\tconst conventionPath = resolveNotFoundConventionPath(framework);\n\tif (!conventionPath) return null;\n\n\tconst renderer = NOT_FOUND_RENDERERS[framework];\n\tif (!renderer) return null;\n\n\ttry {\n\t\treturn await renderer(conventionPath);\n\t} catch (renderError) {\n\t\tlogConventionRenderError(framework, 'not-found', renderError);\n\t}\n\n\treturn null;\n};\n\nconst NOT_FOUND_PRIORITY: (keyof ConventionsMap)[] = [\n\t'react',\n\t'svelte',\n\t'vue',\n\t'angular',\n\t'html'\n];\n\nexport const renderFirstNotFound = async () => {\n\tconst renderNext = async (frameworks: (keyof ConventionsMap)[]) => {\n\t\tconst [framework, ...remaining] = frameworks;\n\t\tif (!framework) {\n\t\t\treturn null;\n\t\t}\n\t\tif (!getMap()[framework]?.defaults?.notFound) {\n\t\t\treturn renderNext(remaining);\n\t\t}\n\n\t\tconst response = await renderConventionNotFound(framework);\n\t\tif (response) {\n\t\t\treturn response;\n\t\t}\n\n\t\treturn renderNext(remaining);\n\t};\n\n\treturn renderNext(NOT_FOUND_PRIORITY);\n};\n",
|
|
161
161
|
"import { withRegisteredStreamingSlots } from './responseEnhancers';\n\nexport const wrapPageHandlerWithStreamingSlots = <\n\tT extends (...args: unknown[]) => Response | Promise<Response>\n>(\n\thandler: T,\n\toptions?: Parameters<typeof withRegisteredStreamingSlots>[1]\n) => {\n\tconst wrapped = (...args: Parameters<T>) =>\n\t\twithRegisteredStreamingSlots(() => handler(...args), options);\n\n\treturn wrapped;\n};\n",
|
|
162
|
-
"import { argv } from 'node:process';\nimport { env } from 'bun';\nimport { Elysia } from 'elysia';\nimport { DEFAULT_PORT, MILLISECONDS_IN_A_SECOND } from '../constants';\nimport { loadDevCert } from '../dev/devCert';\nimport {\n\tregisterInstance,\n\tresolveProjectName\n} from '../utils/instanceRegistry';\nimport { getLocalIPAddress } from '../utils/networking';\nimport { startupBanner } from '../utils/startupBanner';\n\n// Env-var precedence: ABSOLUTE_HOST/ABSOLUTE_PORT (set by `bun dev` after\n// resolving config-file values + Vite-style port fallback) → legacy\n// HOST/PORT → defaults.\nlet host = env.ABSOLUTE_HOST ?? env.HOST ?? 'localhost';\nconst port = env.ABSOLUTE_PORT ?? env.PORT ?? DEFAULT_PORT;\nconst visibility = env.ABSOLUTE_WORKSPACE_SERVICE_VISIBILITY ?? 'public';\nconst managedByWorkspace = env.ABSOLUTE_WORKSPACE_MANAGED === '1';\nlet localIP: string | undefined;\n\nconst args = argv;\nconst hostFlag = args.includes('--host');\n\nif (hostFlag) {\n\tlocalIP = getLocalIPAddress();\n\thost = '0.0.0.0';\n}\n\n// TLS is enabled via ABSOLUTE_HTTPS env var set by the config loader\nconst loadTls = () => {\n\tif (env.NODE_ENV !== 'development') return undefined;\n\tif (env.ABSOLUTE_HTTPS !== 'true') return undefined;\n\n\ttry {\n\t\treturn loadDevCert();\n\t} catch {\n\t\treturn undefined;\n\t}\n};\nconst tls = loadTls();\nconst protocol = tls ? 'https' : 'http';\n\n// Publish this server to the global instance registry so `absolute
|
|
162
|
+
"import { argv } from 'node:process';\nimport { env } from 'bun';\nimport { Elysia } from 'elysia';\nimport { DEFAULT_PORT, MILLISECONDS_IN_A_SECOND } from '../constants';\nimport { loadDevCert } from '../dev/devCert';\nimport {\n\tregisterInstance,\n\tresolveProjectName\n} from '../utils/instanceRegistry';\nimport { getLocalIPAddress } from '../utils/networking';\nimport { startupBanner } from '../utils/startupBanner';\n\n// Env-var precedence: ABSOLUTE_HOST/ABSOLUTE_PORT (set by `bun dev` after\n// resolving config-file values + Vite-style port fallback) → legacy\n// HOST/PORT → defaults.\nlet host = env.ABSOLUTE_HOST ?? env.HOST ?? 'localhost';\nconst port = env.ABSOLUTE_PORT ?? env.PORT ?? DEFAULT_PORT;\nconst visibility = env.ABSOLUTE_WORKSPACE_SERVICE_VISIBILITY ?? 'public';\nconst managedByWorkspace = env.ABSOLUTE_WORKSPACE_MANAGED === '1';\nlet localIP: string | undefined;\n\nconst args = argv;\nconst hostFlag = args.includes('--host');\n\nif (hostFlag) {\n\tlocalIP = getLocalIPAddress();\n\thost = '0.0.0.0';\n}\n\n// TLS is enabled via ABSOLUTE_HTTPS env var set by the config loader\nconst loadTls = () => {\n\tif (env.NODE_ENV !== 'development') return undefined;\n\tif (env.ABSOLUTE_HTTPS !== 'true') return undefined;\n\n\ttry {\n\t\treturn loadDevCert();\n\t} catch {\n\t\treturn undefined;\n\t}\n};\nconst tls = loadTls();\nconst protocol = tls ? 'https' : 'http';\n\n// Publish this server to the global instance registry so `absolute ps` can see\n// it. Skipped when an outer `absolute` CLI/orchestrator already owns the entry\n// (ABSOLUTE_INSTANCE_MANAGED) — this branch is the catch-all for servers\n// started outside the CLI: a manually-run `bun server.ts` or any standalone\n// process. registerInstance handles its own exit cleanup.\nconst selfRegisterInstance = () => {\n\tif (env.ABSOLUTE_INSTANCE_MANAGED === '1') return;\n\n\tregisterInstance({\n\t\tcommand: [...process.argv],\n\t\tconfigPath: env.ABSOLUTE_CONFIG ?? null,\n\t\tcontrollerPid: process.pid,\n\t\tcwd: process.cwd(),\n\t\tframeworks: [],\n\t\thost,\n\t\thttps: protocol === 'https',\n\t\tlogFile: null,\n\t\tname: resolveProjectName(process.cwd()),\n\t\tpid: process.pid,\n\t\tport: Number(port) || null,\n\t\tppid: process.ppid,\n\t\tsource: 'standalone',\n\t\tstartedAt: new Date().toISOString()\n\t});\n};\n\nexport const networking = <A extends Elysia>(app: A) => {\n\tif (env.ABSOLUTE_COMPILED_RUNTIME === '1') return app;\n\n\t// Path B (in-place backend HMR): if a previous evaluation of this\n\t// entry already started a Bun.serve, swap its handler in place\n\t// instead of re-binding the port. The new Elysia instance becomes\n\t// the live handler atomically; the listening socket persists, so\n\t// in-flight requests, WebSocket sessions, DB pools, and module-\n\t// level globals carry across edits.\n\t//\n\t// Activation: the dev runtime sets `globalThis.__absoluteBunServer`\n\t// after the first `app.listen(...)` call; it triggers re-evaluation\n\t// of the entry via cache-busted dynamic import on file change.\n\t// Outside dev, this branch never runs (the global is unset).\n\tconst liveServer = globalThis.__absoluteBunServer;\n\tif (liveServer && typeof liveServer.reload === 'function') {\n\t\t// Backend state HMR: restore the previous Elysia instance's\n\t\t// `app.store` values for keys the new app also declares.\n\t\t// `app.store` holds anything the user (or a plugin like\n\t\t// `elysia-scoped-state`) put there via `.state(...)` — which\n\t\t// in dev was just `.state({scoped: {}})` initial values, so\n\t\t// without this every entry edit reset all per-session data.\n\t\t//\n\t\t// Behavior, mirroring frontend HMR semantics:\n\t\t// - Same key in both: restore previous live value (preserves\n\t\t// per-user state, request counters, etc. across edits).\n\t\t// - Key only in the new app: keep its fresh initial (added\n\t\t// state plugins or new `.state(...)` calls).\n\t\t// - Key only in the previous app: drop it (state the user\n\t\t// removed; new code shouldn't see it).\n\t\t//\n\t\t// Captured in the listen branch below as\n\t\t// `globalThis.__absolutePreviousAppStore`. The first reload\n\t\t// after server start finds the initial store there.\n\t\tconst prevStore = globalThis.__absolutePreviousAppStore;\n\t\tif (prevStore && app.store && typeof app.store === 'object') {\n\t\t\tconst newStore = app.store as Record<string, unknown>;\n\t\t\tconst oldStore = prevStore as Record<string, unknown>;\n\t\t\tfor (const key of Object.keys(newStore)) {\n\t\t\t\tif (key in oldStore) {\n\t\t\t\t\tnewStore[key] = oldStore[key];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tglobalThis.__absolutePreviousAppStore = app.store as Record<\n\t\t\tstring,\n\t\t\tunknown\n\t\t>;\n\t\ttry {\n\t\t\tapp.compile();\n\t\t} catch {\n\t\t\t/* compile is best-effort; some Elysia configs skip it */\n\t\t}\n\t\t// Elysia compiles routes into Bun.serve's `routes` static map\n\t\t// at .listen() time for performance. `Bun.serve.reload({fetch})`\n\t\t// only swaps the fetch fallback — the OLD static `routes` map\n\t\t// keeps serving original handlers. Clear it on reload so every\n\t\t// request falls through to our new app's fetch.\n\t\tliveServer.reload({\n\t\t\tfetch: (request: Request) => app.fetch(request),\n\t\t\troutes: {}\n\t\t});\n\n\t\treturn app;\n\t}\n\n\tconst listened = app.listen(\n\t\t{\n\t\t\thostname: host,\n\t\t\tport: port,\n\t\t\t...(tls\n\t\t\t\t? {\n\t\t\t\t\t\ttls: {\n\t\t\t\t\t\t\tcert: tls.cert,\n\t\t\t\t\t\t\tkey: tls.key\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t: {})\n\t\t},\n\t\t() => {\n\t\t\tselfRegisterInstance();\n\n\t\t\tif (visibility === 'internal' || managedByWorkspace) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Skip logging on Bun --hot reloads (HMR handles its own output)\n\t\t\tconst isHotReload = Boolean(globalThis.__hmrServerStartup);\n\t\t\tglobalThis.__hmrServerStartup = true;\n\t\t\tif (isHotReload) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst buildDuration =\n\t\t\t\tglobalThis.__hmrBuildDuration ??\n\t\t\t\tNumber(env.ABSOLUTE_BUILD_DURATION || 0);\n\t\t\tconst readyDuration = process.uptime() * MILLISECONDS_IN_A_SECOND;\n\n\t\t\tconst version =\n\t\t\t\tglobalThis.__absoluteVersion || env.ABSOLUTE_VERSION || '';\n\n\t\t\tstartupBanner({\n\t\t\t\tbuildDuration,\n\t\t\t\thost,\n\t\t\t\tnetworkUrl: hostFlag\n\t\t\t\t\t? `${protocol}://${localIP}:${port}/`\n\t\t\t\t\t: undefined,\n\t\t\t\tport,\n\t\t\t\tprotocol,\n\t\t\t\treadyDuration,\n\t\t\t\tversion\n\t\t\t});\n\t\t}\n\t);\n\n\t// Capture the underlying Bun.serve instance synchronously after\n\t// `.listen()` returns. Elysia sets `app.server = Bun.serve(...)`\n\t// inline, so the assignment is observable here without waiting for\n\t// any lifecycle hook. Subsequent re-evaluations of the entry hit\n\t// the reload-aware branch above and never reach this point.\n\tif (app.server) {\n\t\tglobalThis.__absoluteBunServer = app.server;\n\t\tglobalThis.__absolutePreviousAppStore = app.store as Record<\n\t\t\tstring,\n\t\t\tunknown\n\t\t>;\n\t\t// Path B: start the entry-file watcher now that the server is\n\t\t// bound. The watcher triggers cache-busted dynamic re-imports\n\t\t// on entry edits, which hit the reload-aware branch instead of\n\t\t// re-binding. Only runs in dev mode (compiled runtime returned\n\t\t// early at the top).\n\t\tif (env.NODE_ENV === 'development') {\n\t\t\tvoid import('../dev/serverEntryWatcher')\n\t\t\t\t.then(({ startServerEntryWatcher }) => {\n\t\t\t\t\tstartServerEntryWatcher();\n\t\t\t\t})\n\t\t\t\t.catch((err) => {\n\t\t\t\t\t/* dev-only feature; never break the server */\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`[hmr] entry watcher setup failed: ${\n\t\t\t\t\t\t\terr instanceof Error ? err.message : String(err)\n\t\t\t\t\t\t}`\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t}\n\t}\n\n\treturn listened;\n};\n",
|
|
163
163
|
"import {\n\tcopyFileSync,\n\texistsSync,\n\tmkdirSync,\n\treadFileSync,\n\trmSync\n} from 'node:fs';\nimport { platform } from 'node:os';\nimport { join } from 'node:path';\n\nconst CERT_DIR = join(process.cwd(), '.absolutejs');\nconst CERT_PATH = join(CERT_DIR, 'cert.pem');\nconst KEY_PATH = join(CERT_DIR, 'key.pem');\nconst CERT_VALIDITY_DAYS = 365;\n\n// Neutral log that doesn't use [hmr] tag\nconst devLog = (msg: string) =>\n\tconsole.log(\n\t\t`\\x1b[2m${new Date().toLocaleTimeString()}\\x1b[0m \\x1b[36m[dev]\\x1b[0m ${msg}`\n\t);\n\nconst devWarn = (msg: string) =>\n\tconsole.log(\n\t\t`\\x1b[2m${new Date().toLocaleTimeString()}\\x1b[0m \\x1b[33m[dev]\\x1b[0m \\x1b[33m${msg}\\x1b[0m`\n\t);\n\nconst certFilesExist = () => existsSync(CERT_PATH) && existsSync(KEY_PATH);\n\nconst isCertExpired = () => {\n\ttry {\n\t\tconst certPem = readFileSync(CERT_PATH, 'utf-8');\n\t\tconst proc = Bun.spawnSync(['openssl', 'x509', '-enddate', '-noout'], {\n\t\t\tstdin: new TextEncoder().encode(certPem)\n\t\t});\n\t\tconst output = new TextDecoder().decode(proc.stdout).trim();\n\t\tconst dateStr = output.replace('notAfter=', '');\n\t\tconst expiryDate = new Date(dateStr);\n\n\t\treturn expiryDate.getTime() < Date.now();\n\t} catch {\n\t\treturn true;\n\t}\n};\n\nexport const hasMkcert = () => {\n\ttry {\n\t\tconst result = Bun.spawnSync(['mkcert', '-version'], {\n\t\t\tstderr: 'pipe',\n\t\t\tstdout: 'pipe'\n\t\t});\n\n\t\treturn result.exitCode === 0;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\nconst generateWithMkcert = () => {\n\tconst result = Bun.spawnSync(\n\t\t[\n\t\t\t'mkcert',\n\t\t\t'-cert-file',\n\t\t\tCERT_PATH,\n\t\t\t'-key-file',\n\t\t\tKEY_PATH,\n\t\t\t'localhost',\n\t\t\t'127.0.0.1',\n\t\t\t'::1'\n\t\t],\n\t\t{ stderr: 'pipe', stdout: 'pipe' }\n\t);\n\n\tif (result.exitCode !== 0) {\n\t\tconst err = new TextDecoder().decode(result.stderr);\n\t\tthrow new Error(`mkcert failed: ${err}`);\n\t}\n};\n\nconst generateSelfSigned = () => {\n\tconst proc = Bun.spawnSync(\n\t\t[\n\t\t\t'openssl',\n\t\t\t'req',\n\t\t\t'-x509',\n\t\t\t'-newkey',\n\t\t\t'ec',\n\t\t\t'-pkeyopt',\n\t\t\t'ec_paramgen_curve:prime256v1',\n\t\t\t'-days',\n\t\t\tString(CERT_VALIDITY_DAYS),\n\t\t\t'-nodes',\n\t\t\t'-keyout',\n\t\t\tKEY_PATH,\n\t\t\t'-out',\n\t\t\tCERT_PATH,\n\t\t\t'-subj',\n\t\t\t'/CN=localhost',\n\t\t\t'-addext',\n\t\t\t'subjectAltName=DNS:localhost,IP:127.0.0.1,IP:::1'\n\t\t],\n\t\t{ stderr: 'pipe', stdout: 'pipe' }\n\t);\n\n\tif (proc.exitCode !== 0) {\n\t\tconst err = new TextDecoder().decode(proc.stderr);\n\t\tthrow new Error(`openssl failed: ${err}`);\n\t}\n\n\tdevLog(\n\t\t'Using self-signed certificate — browser will show a one-time warning'\n\t);\n};\n\nconst generateCert = () => {\n\tif (hasMkcert()) {\n\t\tgenerateWithMkcert();\n\t} else {\n\t\tgenerateSelfSigned();\n\t}\n};\n\nexport const ensureDevCert = () => {\n\tmkdirSync(CERT_DIR, { recursive: true });\n\n\t// Cert exists and valid — reuse silently\n\tif (hasCert()) {\n\t\treturn { cert: CERT_PATH, key: KEY_PATH };\n\t}\n\n\t// Expired — regenerate silently\n\tif (certFilesExist()) {\n\t\tdevLog('Certificate expired, regenerating...');\n\t}\n\n\ttry {\n\t\tgenerateCert();\n\t} catch (err) {\n\t\tdevWarn(\n\t\t\t`Failed to generate certificate: ${err instanceof Error ? err.message : err}`\n\t\t);\n\n\t\treturn null;\n\t}\n\n\treturn { cert: CERT_PATH, key: KEY_PATH };\n};\nexport const hasCert = () => certFilesExist() && !isCertExpired();\nexport const loadDevCert = () => {\n\tconst paths = ensureDevCert();\n\tif (!paths) return null;\n\n\ttry {\n\t\treturn {\n\t\t\tcert: readFileSync(paths.cert, 'utf-8'),\n\t\t\tkey: readFileSync(paths.key, 'utf-8')\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nconst commandExists = (cmd: string) => {\n\ttry {\n\t\tconst check = platform() === 'win32' ? ['where', cmd] : ['which', cmd];\n\t\tconst result = Bun.spawnSync(check, {\n\t\t\tstderr: 'pipe',\n\t\t\tstdout: 'pipe'\n\t\t});\n\n\t\treturn result.exitCode === 0;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\nconst installMkcertDarwin = () => {\n\tif (!commandExists('brew')) {\n\t\tdevWarn('Install Homebrew first: https://brew.sh');\n\n\t\treturn false;\n\t}\n\n\tdevLog('Installing mkcert with Homebrew...');\n\tconst result = Bun.spawnSync(['brew', 'install', 'mkcert'], {\n\t\tstderr: 'pipe',\n\t\tstdout: 'pipe'\n\t});\n\n\treturn result.exitCode === 0;\n};\n\nconst installMkcertLinux = () => {\n\t// stdin + stderr inherit for password prompt, stdout piped to hide package logs\n\tconst sudoOpts: { stderr: 'inherit'; stdin: 'inherit'; stdout: 'pipe' } = {\n\t\tstderr: 'inherit',\n\t\tstdin: 'inherit',\n\t\tstdout: 'pipe'\n\t};\n\n\tif (commandExists('apt-get')) {\n\t\tdevLog('Installing mkcert (may prompt for password)...');\n\t\t// Install mkcert + libnss3-tools (certutil) together\n\t\t// so mkcert -install can add the CA to browser trust stores\n\t\tconst result = Bun.spawnSync(\n\t\t\t['sudo', 'apt-get', 'install', '-y', 'mkcert', 'libnss3-tools'],\n\t\t\tsudoOpts\n\t\t);\n\t\tif (result.exitCode === 0) return true;\n\t}\n\n\tif (commandExists('dnf')) {\n\t\tdevLog('Installing mkcert (may prompt for password)...');\n\t\tconst result = Bun.spawnSync(\n\t\t\t['sudo', 'dnf', 'install', '-y', 'mkcert'],\n\t\t\tsudoOpts\n\t\t);\n\t\tif (result.exitCode === 0) return true;\n\t}\n\n\tif (commandExists('pacman')) {\n\t\tdevLog('Installing mkcert (may prompt for password)...');\n\t\tconst result = Bun.spawnSync(\n\t\t\t['sudo', 'pacman', '-S', '--noconfirm', 'mkcert'],\n\t\t\tsudoOpts\n\t\t);\n\t\tif (result.exitCode === 0) return true;\n\t}\n\n\tdevWarn('Could not install mkcert automatically.');\n\tconsole.log(' See: https://github.com/FiloSottile/mkcert#installation');\n\n\treturn false;\n};\n\nconst installMkcertWin32 = () => {\n\tif (commandExists('choco')) {\n\t\tdevLog('Installing mkcert with Chocolatey...');\n\t\tconst result = Bun.spawnSync(['choco', 'install', '-y', 'mkcert'], {\n\t\t\tstderr: 'pipe',\n\t\t\tstdout: 'pipe'\n\t\t});\n\t\tif (result.exitCode === 0) return true;\n\t}\n\n\tif (commandExists('winget')) {\n\t\tdevLog('Installing mkcert with winget...');\n\t\tconst result = Bun.spawnSync(\n\t\t\t['winget', 'install', '--id', 'FiloSottile.mkcert', '-e'],\n\t\t\t{ stderr: 'pipe', stdout: 'pipe' }\n\t\t);\n\t\tif (result.exitCode === 0) return true;\n\t}\n\n\tdevWarn('Could not install mkcert automatically.');\n\tconsole.log(' See: https://github.com/FiloSottile/mkcert#installation');\n\n\treturn false;\n};\n\nconst installMkcert = () => {\n\tconst osPlatform = platform();\n\n\tif (osPlatform === 'darwin') return installMkcertDarwin();\n\tif (osPlatform === 'linux') return installMkcertLinux();\n\tif (osPlatform === 'win32') return installMkcertWin32();\n\n\treturn false;\n};\n\nconst ensureMkcert = () => {\n\tif (hasMkcert()) return true;\n\tif (!installMkcert()) return false;\n\n\t// Verify it installed\n\tif (!hasMkcert()) {\n\t\tdevWarn(\n\t\t\t'mkcert installed but not found in PATH. Restart your terminal and try again.'\n\t\t);\n\n\t\treturn false;\n\t}\n\n\treturn true;\n};\n\nconst isWSL = () => {\n\tif (platform() !== 'linux') return false;\n\ttry {\n\t\treturn /microsoft|wsl/i.test(readFileSync('/proc/version', 'utf-8'));\n\t} catch {\n\t\treturn false;\n\t}\n};\n\nconst runCapture = (cmd: string[]) => {\n\ttry {\n\t\tconst result = Bun.spawnSync(cmd, { stderr: 'pipe', stdout: 'pipe' });\n\t\tif (result.exitCode !== 0) return null;\n\t\tconst out = new TextDecoder().decode(result.stdout).trim();\n\n\t\treturn out || null;\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nconst mkcertCaRoot = () => runCapture(['mkcert', '-CAROOT']);\nconst toWindowsPath = (linuxPath: string) =>\n\trunCapture(['wslpath', '-w', linuxPath]);\nconst windowsTempDir = () => {\n\tconst winTemp = runCapture(['cmd.exe', '/c', 'echo %TEMP%']);\n\tif (!winTemp) return null;\n\n\treturn runCapture(['wslpath', '-u', winTemp]);\n};\n\n/**\n * Under WSL the browser runs on Windows, whose trust store never receives the\n * CA that `mkcert -install` added on the Linux side — so dev HTTPS shows as\n * untrusted there. Stage mkcert's rootCA in a Windows-visible temp dir and\n * import it into the current user's Root store via PowerShell (no admin, no GUI\n * prompt, idempotent). Returns true when the CA is trusted on Windows.\n */\nconst trustCaOnWindows = () => {\n\tconst caRoot = mkcertCaRoot();\n\tif (!caRoot) return false;\n\tconst rootCa = join(caRoot, 'rootCA.pem');\n\tif (!existsSync(rootCa)) return false;\n\n\tconst winTemp = windowsTempDir();\n\tif (!winTemp) return false;\n\n\tconst staged = join(winTemp, 'absolutejs-mkcert-rootCA.crt');\n\ttry {\n\t\tcopyFileSync(rootCa, staged);\n\t} catch {\n\t\treturn false;\n\t}\n\n\tconst stagedWin = toWindowsPath(staged);\n\tif (!stagedWin) {\n\t\trmSync(staged, { force: true });\n\n\t\treturn false;\n\t}\n\n\tconst result = Bun.spawnSync(\n\t\t[\n\t\t\t'powershell.exe',\n\t\t\t'-NoProfile',\n\t\t\t'-Command',\n\t\t\t`Import-Certificate -FilePath '${stagedWin}' -CertStoreLocation Cert:\\\\CurrentUser\\\\Root`\n\t\t],\n\t\t{ stderr: 'pipe', stdout: 'pipe' }\n\t);\n\trmSync(staged, { force: true });\n\n\treturn result.exitCode === 0;\n};\n\n// CLI command: install mkcert, set up CA, regenerate cert\nexport const setupMkcert = () => {\n\tif (!ensureMkcert()) return false;\n\n\t// Install the local CA (adds to system trust store)\n\tconst installResult = Bun.spawnSync(['mkcert', '-install'], {\n\t\tstderr: 'pipe',\n\t\tstdin: 'inherit',\n\t\tstdout: 'pipe'\n\t});\n\n\tif (installResult.exitCode !== 0) {\n\t\tdevWarn('Failed to install local CA');\n\n\t\treturn false;\n\t}\n\n\t// On WSL the Linux trust store the step above wrote to is invisible to the\n\t// Windows browser; mirror the CA into the Windows store so HTTPS is trusted.\n\tif (isWSL()) {\n\t\tif (trustCaOnWindows()) {\n\t\t\tdevLog(\n\t\t\t\t'Trusted the local CA in the Windows store — Chrome/Edge on Windows now accept dev HTTPS'\n\t\t\t);\n\t\t} else {\n\t\t\tconst caRoot = mkcertCaRoot();\n\t\t\tconst hint = caRoot\n\t\t\t\t? toWindowsPath(join(caRoot, 'rootCA.pem'))\n\t\t\t\t: null;\n\t\t\tdevWarn(\n\t\t\t\t'Could not auto-trust the local CA on Windows; Windows browsers may warn.'\n\t\t\t);\n\t\t\tif (hint) {\n\t\t\t\tconsole.log(\n\t\t\t\t\t` Run in PowerShell: Import-Certificate -FilePath \"${hint}\" -CertStoreLocation Cert:\\\\CurrentUser\\\\Root`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove old cert to force regeneration with mkcert\n\trmSync(CERT_PATH, { force: true });\n\trmSync(KEY_PATH, { force: true });\n\n\t// Generate new trusted cert\n\tmkdirSync(CERT_DIR, { recursive: true });\n\tgenerateWithMkcert();\n\tconsole.log('');\n\tdevLog('mkcert installed — HTTPS certificates are now locally trusted');\n\n\treturn true;\n};\n",
|
|
164
164
|
"import {\n\tmkdirSync,\n\treadFileSync,\n\treaddirSync,\n\tunlinkSync,\n\twriteFileSync\n} from 'node:fs';\nimport { homedir } from 'node:os';\nimport { basename, join } from 'node:path';\nimport type { InstanceRecord, InstanceSource } from '../../types/cli';\n\n// Each running `absolute dev` writes one `<pid>.json` here on boot and a\n// sibling `<pid>.log` for its tee'd output. Living under the user's home\n// (not the project's `.absolutejs/`) is what lets `absolute ps` aggregate\n// every dev server on the machine regardless of which project launched it.\nconst registeredPids = new Set<number>();\nlet exitHandlerRegistered = false;\n\nexport const instanceFilePath = (pid: number) =>\n\tjoin(instanceRegistryDir(), `${pid}.json`);\n\nexport const instanceLogPath = (pid: number) =>\n\tjoin(instanceRegistryDir(), `${pid}.log`);\n\nexport const instanceRegistryDir = () =>\n\tjoin(homedir(), '.absolutejs', 'instances');\n\nconst removeInstanceFilesSync = (pid: number) => {\n\ttry {\n\t\tunlinkSync(instanceFilePath(pid));\n\t} catch {\n\t\t/* already gone */\n\t}\n\ttry {\n\t\tunlinkSync(instanceLogPath(pid));\n\t} catch {\n\t\t/* already gone */\n\t}\n};\n\nconst registerExitHandlerOnce = () => {\n\tif (exitHandlerRegistered) return;\n\texitHandlerRegistered = true;\n\n\t// Safety net only: a graceful `absolute dev` shutdown calls\n\t// `deregisterInstance` itself. This catches hard exits so a crashed\n\t// process doesn't leave a phantom row — `listLiveInstances` also prunes\n\t// dead pids on read as a second line of defense.\n\tprocess.on('exit', () => {\n\t\tfor (const pid of registeredPids) {\n\t\t\tremoveInstanceFilesSync(pid);\n\t\t}\n\t\tregisteredPids.clear();\n\t});\n};\n\nconst isProcessAlive = (pid: number) => {\n\ttry {\n\t\t// Signal 0 is a no-op liveness probe.\n\t\tprocess.kill(pid, 0);\n\n\t\treturn true;\n\t} catch (error) {\n\t\tconst code =\n\t\t\terror instanceof Error && 'code' in error ? error.code : undefined;\n\t\tif (code === 'ESRCH') return false;\n\n\t\t// EPERM → alive but owned by another user; anything else → assume alive.\n\t\treturn true;\n\t}\n};\n\nconst readJsonFile = (path: string) => {\n\ttry {\n\t\treturn JSON.parse(readFileSync(path, 'utf-8'));\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nconst SOURCES: InstanceSource[] = [\n\t'compiled',\n\t'dev',\n\t'standalone',\n\t'start',\n\t'workspace'\n];\n\nconst toStringArray = (value: unknown) =>\n\tArray.isArray(value)\n\t\t? value.filter((item): item is string => typeof item === 'string')\n\t\t: [];\n\nconst coerceSource = (value: unknown) =>\n\tSOURCES.find((item) => item === value) ?? 'standalone';\n\nconst coerceRecord = (parsed: ReturnType<typeof readJsonFile>) => {\n\tif (typeof parsed !== 'object' || parsed === null) return null;\n\tif (typeof parsed.pid !== 'number') return null;\n\n\treturn {\n\t\tcommand: toStringArray(parsed.command),\n\t\tconfigPath:\n\t\t\ttypeof parsed.configPath === 'string' ? parsed.configPath : null,\n\t\tcontrollerPid:\n\t\t\ttypeof parsed.controllerPid === 'number'\n\t\t\t\t? parsed.controllerPid\n\t\t\t\t: parsed.pid,\n\t\tcwd: typeof parsed.cwd === 'string' ? parsed.cwd : '',\n\t\tframeworks: toStringArray(parsed.frameworks),\n\t\thost: typeof parsed.host === 'string' ? parsed.host : 'localhost',\n\t\thttps: parsed.https === true,\n\t\tlogFile: typeof parsed.logFile === 'string' ? parsed.logFile : null,\n\t\tname: typeof parsed.name === 'string' ? parsed.name : 'unknown',\n\t\tpid: parsed.pid,\n\t\tport: typeof parsed.port === 'number' ? parsed.port : null,\n\t\tppid: typeof parsed.ppid === 'number' ? parsed.ppid : 0,\n\t\tsource: coerceSource(parsed.source),\n\t\tstartedAt:\n\t\t\ttypeof parsed.startedAt === 'string'\n\t\t\t\t? parsed.startedAt\n\t\t\t\t: new Date().toISOString()\n\t} satisfies InstanceRecord;\n};\n\nconst readRecordFile = (path: string) => coerceRecord(readJsonFile(path));\n\nconst compareInstances = (left: InstanceRecord, right: InstanceRecord) => {\n\tconst leftPort = left.port ?? Number.MAX_SAFE_INTEGER;\n\tconst rightPort = right.port ?? Number.MAX_SAFE_INTEGER;\n\tif (leftPort !== rightPort) return leftPort - rightPort;\n\n\treturn left.name.localeCompare(right.name);\n};\n\nexport const deregisterInstance = (pid: number) => {\n\tregisteredPids.delete(pid);\n\tremoveInstanceFilesSync(pid);\n};\n\n/** Read every registered instance, pruning any whose process has died, and\n * return the survivors sorted by port then name. */\nexport const listLiveInstances = () => {\n\tconst directory = instanceRegistryDir();\n\tlet entries: string[];\n\ttry {\n\t\tentries = readdirSync(directory);\n\t} catch {\n\t\treturn [];\n\t}\n\n\tconst live = entries\n\t\t.filter((entry) => entry.endsWith('.json'))\n\t\t.map((entry) => readRecordFile(join(directory, entry)))\n\t\t.filter((record): record is InstanceRecord => record !== null)\n\t\t.filter((record) => {\n\t\t\tif (isProcessAlive(record.pid)) return true;\n\t\t\tremoveInstanceFilesSync(record.pid);\n\n\t\t\treturn false;\n\t\t});\n\n\treturn live.sort(compareInstances);\n};\n\nexport const registerInstance = (record: InstanceRecord) => {\n\tmkdirSync(instanceRegistryDir(), { recursive: true });\n\twriteFileSync(\n\t\tinstanceFilePath(record.pid),\n\t\tJSON.stringify(record, null, 2)\n\t);\n\tregisteredPids.add(record.pid);\n\tregisterExitHandlerOnce();\n\n\treturn record;\n};\n\n/** Read the project label without a config flag: package.json `name`, falling\n * back to the directory name. */\nexport const resolveProjectName = (cwd: string) => {\n\tconst parsed = readJsonFile(join(cwd, 'package.json'));\n\tif (\n\t\tparsed !== null &&\n\t\ttypeof parsed === 'object' &&\n\t\ttypeof parsed.name === 'string' &&\n\t\tparsed.name.trim().length > 0\n\t) {\n\t\treturn parsed.name;\n\t}\n\n\treturn basename(cwd) || 'unknown';\n};\n\nexport const updateInstance = (\n\tpid: number,\n\tupdates: Partial<InstanceRecord>\n) => {\n\tconst current = readRecordFile(instanceFilePath(pid));\n\tif (!current) return;\n\n\tconst next = { ...current, ...updates } satisfies InstanceRecord;\n\ttry {\n\t\twriteFileSync(instanceFilePath(pid), JSON.stringify(next, null, 2));\n\t} catch {\n\t\t/* best effort */\n\t}\n};\n",
|
|
165
165
|
"import os from 'os';\n\n/* Get all network IP addresses (IPv4 only)\n This handles the \"detect all network interfaces\" problem */\nexport const getAllNetworkIPs = () => {\n\tconst interfaces = os.networkInterfaces();\n\tconst addresses = Object.values(interfaces)\n\t\t.flat()\n\t\t.filter(\n\t\t\t(iface): iface is os.NetworkInterfaceInfo => iface !== undefined\n\t\t);\n\n\t// Only collect IPv4 addresses\n\tconst ipv4Addresses: string[] = [];\n\n\taddresses\n\t\t.filter((addr) => !addr.internal && addr.family === 'IPv4')\n\t\t.forEach((addr) => ipv4Addresses.push(addr.address));\n\n\treturn ipv4Addresses;\n};\n\n/* Get the first network IP address (for backward compatibility)\n This maintains compatibility with existing code that expects a single IP */\nexport const getLocalIPAddress = () => {\n\tconst allIPs = getAllNetworkIPs();\n\n\tif (allIPs.length > 0 && allIPs[0]) {\n\t\treturn allIPs[0]; // Return first IPv4 address (or first available)\n\t}\n\n\tconsole.warn('No IP address found, falling back to localhost');\n\n\treturn 'localhost'; // Fallback to localhost if no IP found\n};\n",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const runPsTui: () => Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const runLs: (args: string[]) => Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const runPs: (args: string[]) => Promise<void>;
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const runListTui: () => Promise<void>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const runList: (args: string[]) => Promise<void>;
|