seedcord 0.16.0-next.8 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as SEEDCORD_CONFIG_FILENAMES, t as version } from "./src-
|
|
1
|
+
import { n as SEEDCORD_CONFIG_FILENAMES, t as version } from "./src-pMIoZiL7.mjs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { Command } from "@commander-js/extra-typings";
|
|
4
4
|
import { LEVEL_COLOR, Logger, LoggerChannelRegistry } from "@seedcord/logger";
|
|
@@ -6,7 +6,7 @@ import { formatBody, installNodeDefaults } from "@seedcord/logger/node";
|
|
|
6
6
|
import { SeedcordErrorCode, isSeedcordError } from "@seedcord/errors";
|
|
7
7
|
import { existsSync } from "node:fs";
|
|
8
8
|
import { SeedcordError, validateDiscordToken } from "@seedcord/errors/internal";
|
|
9
|
-
import { dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
9
|
+
import { dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
10
10
|
import { pathToFileURL } from "node:url";
|
|
11
11
|
import { createJiti } from "jiti";
|
|
12
12
|
import { tsImport } from "tsx/esm/api";
|
|
@@ -22,7 +22,7 @@ import chalk from "chalk";
|
|
|
22
22
|
import { autocompleteMultiselect, cancel, confirm, intro, isCancel, log, multiselect, note, outro, select, spinner } from "@clack/prompts";
|
|
23
23
|
import { createInterface } from "node:readline";
|
|
24
24
|
import { Box, Text, measureElement, render, useAnimation, useInput, useWindowSize } from "ink";
|
|
25
|
-
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
25
|
+
import React, { Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
26
26
|
import { TypedEventEmitter } from "@seedcord/event-emitter";
|
|
27
27
|
import Spinner from "ink-spinner";
|
|
28
28
|
import { assertNever } from "@seedcord/utils";
|
|
@@ -36,10 +36,10 @@ var BaseCommand = class {
|
|
|
36
36
|
name;
|
|
37
37
|
description;
|
|
38
38
|
logger;
|
|
39
|
-
constructor(name, description,
|
|
39
|
+
constructor(name, description, label) {
|
|
40
40
|
this.name = name;
|
|
41
41
|
this.description = description;
|
|
42
|
-
this.logger = new Logger(
|
|
42
|
+
this.logger = new Logger(label, { channel: "cli" });
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
45
|
|
|
@@ -461,7 +461,7 @@ var BuildRunner = class BuildRunner {
|
|
|
461
461
|
var BuildCommand = class extends BaseCommand {
|
|
462
462
|
runner;
|
|
463
463
|
constructor() {
|
|
464
|
-
super("build", "Compile a Seedcord project from the config file", "
|
|
464
|
+
super("build", "Compile a Seedcord project from the config file", "Build");
|
|
465
465
|
this.runner = BuildRunner.create(this.logger);
|
|
466
466
|
}
|
|
467
467
|
register(program) {
|
|
@@ -589,11 +589,19 @@ var AugmentationBuilder = class {
|
|
|
589
589
|
//#region src/commands/codegen/renderAugmentation.ts
|
|
590
590
|
const BANNER = `// Generated by \`seedcord codegen\`. Do not edit by hand.
|
|
591
591
|
// Run \`seedcord codegen\` after changing your commands or emoji config.`;
|
|
592
|
+
const BOT_BINDING = "Bot";
|
|
592
593
|
const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
593
594
|
const CONTROL_CHAR = 32;
|
|
594
595
|
const HEX_RADIX = 16;
|
|
595
|
-
function renderAugmentation(registry, target) {
|
|
596
|
-
|
|
596
|
+
function renderAugmentation(registry, target, plugins) {
|
|
597
|
+
const keys = [...plugins?.keys ?? []].sort(compare);
|
|
598
|
+
const attached = plugins !== void 0 && keys.length > 0;
|
|
599
|
+
const botImport = attached ? `import type ${BOT_BINDING} from '${escapeLiteral(plugins.specifier)}';\n\n` : "";
|
|
600
|
+
const coreRows = attached ? ` interface Core {\n${renderPluginRows(keys)}\n }\n` : "";
|
|
601
|
+
return `${`${BANNER}\n\n${botImport}// prettier-ignore\ndeclare module '${target}' {\n` + coreRows} interface SlashOptionRegistry {\n${renderSlashRows(registry.slash)}\n }\n interface UserContextMenuRegistry {\n${renderContextMenuRows(registry.userContextMenus)}\n }\n interface MessageContextMenuRegistry {\n${renderContextMenuRows(registry.messageContextMenus)}\n }\n interface EmojiMap {\n${renderEmojiRows(registry.emojis)}\n }\n}\n\nexport {};\n`;
|
|
602
|
+
}
|
|
603
|
+
function renderPluginRows(keys) {
|
|
604
|
+
return keys.map((key) => ` ${renderKey(key)}: (typeof ${BOT_BINDING})['${escapeLiteral(key)}'];`).join("\n");
|
|
597
605
|
}
|
|
598
606
|
function renderSlashRows(tables) {
|
|
599
607
|
return Object.entries(tables).sort(([first], [second]) => compare(first, second)).map(([route, options]) => ` ${renderKey(route)}: ${renderRow(options)};`).join("\n");
|
|
@@ -660,6 +668,11 @@ function compare(first, second) {
|
|
|
660
668
|
//#endregion
|
|
661
669
|
//#region src/commands/codegen/CodegenRunner.ts
|
|
662
670
|
const OUTPUT_FILENAME = "seedcord-gen.d.ts";
|
|
671
|
+
const ENTRY_EXTENSION = /\.[mc]?[jt]sx?$/;
|
|
672
|
+
function botSpecifier(root, instance) {
|
|
673
|
+
const posix = relative(root, instance).split(sep).join("/").replace(ENTRY_EXTENSION, "");
|
|
674
|
+
return posix.startsWith(".") ? posix : `./${posix}`;
|
|
675
|
+
}
|
|
663
676
|
/**
|
|
664
677
|
* Orchestrates `seedcord codegen`. Locates and loads the CLI config, imports the user's Seedcord instance to
|
|
665
678
|
* read its commands directory and emoji config, scans and instantiates each command for its `toJSON()`, then
|
|
@@ -684,8 +697,11 @@ var CodegenRunner = class CodegenRunner {
|
|
|
684
697
|
}
|
|
685
698
|
async run(check) {
|
|
686
699
|
const config = await this.loadConfig();
|
|
687
|
-
const { commands, emojis, augmentTarget } = await this.scan(config);
|
|
688
|
-
const rendered = renderAugmentation(this.generator.generate(commands, emojis), augmentTarget
|
|
700
|
+
const { commands, emojis, augmentTarget, pluginKeys } = await this.scan(config);
|
|
701
|
+
const rendered = renderAugmentation(this.generator.generate(commands, emojis), augmentTarget, {
|
|
702
|
+
specifier: botSpecifier(config.root, config.instance),
|
|
703
|
+
keys: pluginKeys
|
|
704
|
+
});
|
|
689
705
|
const outputPath = resolve(config.root, OUTPUT_FILENAME);
|
|
690
706
|
if (check) {
|
|
691
707
|
await this.check(rendered, outputPath);
|
|
@@ -697,13 +713,14 @@ var CodegenRunner = class CodegenRunner {
|
|
|
697
713
|
return this.configLoader.load(this.locator.locate());
|
|
698
714
|
}
|
|
699
715
|
async scan(config) {
|
|
700
|
-
const { commandsDir, emojis, augmentTarget } = await this.resolveInstance(config);
|
|
716
|
+
const { commandsDir, emojis, augmentTarget, pluginKeys } = await this.resolveInstance(config);
|
|
701
717
|
const commands = [];
|
|
702
718
|
if (commandsDir) for await (const command of this.walk(commandsDir, /* @__PURE__ */ new Set(), true)) commands.push(command);
|
|
703
719
|
return {
|
|
704
720
|
commands,
|
|
705
721
|
emojis,
|
|
706
|
-
augmentTarget
|
|
722
|
+
augmentTarget,
|
|
723
|
+
pluginKeys
|
|
707
724
|
};
|
|
708
725
|
}
|
|
709
726
|
async *walk(dir, seen, isRoot) {
|
|
@@ -741,7 +758,8 @@ var CodegenRunner = class CodegenRunner {
|
|
|
741
758
|
return {
|
|
742
759
|
commandsDir: commandsPath ? resolve(process.cwd(), commandsPath) : void 0,
|
|
743
760
|
emojis: instance.config.bot.emojis ?? {},
|
|
744
|
-
augmentTarget: instance.augmentTarget
|
|
761
|
+
augmentTarget: instance.augmentTarget,
|
|
762
|
+
pluginKeys: instance.pluginKeys
|
|
745
763
|
};
|
|
746
764
|
}
|
|
747
765
|
commandJsonOf(exported) {
|
|
@@ -788,7 +806,7 @@ var CodegenRunner = class CodegenRunner {
|
|
|
788
806
|
var CodegenCommand = class extends BaseCommand {
|
|
789
807
|
runner;
|
|
790
808
|
constructor() {
|
|
791
|
-
super("codegen", "Generate typed augmentations
|
|
809
|
+
super("codegen", "Generate typed augmentations from your commands and config", "Codegen");
|
|
792
810
|
this.runner = CodegenRunner.create(this.logger);
|
|
793
811
|
}
|
|
794
812
|
register(program) {
|
|
@@ -1358,7 +1376,7 @@ function hasCleanFlags(options) {
|
|
|
1358
1376
|
var CommandsCommand = class extends BaseCommand {
|
|
1359
1377
|
cleanRunner;
|
|
1360
1378
|
constructor() {
|
|
1361
|
-
super("commands", "Inspect and clean deployed guild commands", "
|
|
1379
|
+
super("commands", "Inspect and clean deployed guild commands", "Commands");
|
|
1362
1380
|
this.cleanRunner = CleanRunner.create();
|
|
1363
1381
|
}
|
|
1364
1382
|
register(program) {
|
|
@@ -1411,7 +1429,7 @@ const INITIAL_CURSOR = {
|
|
|
1411
1429
|
levels: 0
|
|
1412
1430
|
};
|
|
1413
1431
|
function moveCursor(cursor, move, channelCount, levelCount) {
|
|
1414
|
-
if (move === "
|
|
1432
|
+
if (move === "switch") return {
|
|
1415
1433
|
...cursor,
|
|
1416
1434
|
group: cursor.group === "channels" ? "levels" : "channels"
|
|
1417
1435
|
};
|
|
@@ -1554,6 +1572,25 @@ function useLogs(channels, levels) {
|
|
|
1554
1572
|
]);
|
|
1555
1573
|
}
|
|
1556
1574
|
|
|
1575
|
+
//#endregion
|
|
1576
|
+
//#region src/ui/hooks/useMeasuredHeight.ts
|
|
1577
|
+
/**
|
|
1578
|
+
* The rendered height of a box, 0 until the first measurement lands.
|
|
1579
|
+
*
|
|
1580
|
+
* No dep array. A box moves for reasons its caller cannot enumerate, and one of them can be derived from the
|
|
1581
|
+
* height itself, which rules out a dependency list. The equality bail is what keeps the per-render measurement
|
|
1582
|
+
* from forming an update chain.
|
|
1583
|
+
*/
|
|
1584
|
+
function useMeasuredHeight(ref) {
|
|
1585
|
+
const [height, setHeight] = useState(0);
|
|
1586
|
+
useLayoutEffect(() => {
|
|
1587
|
+
if (!ref.current) return;
|
|
1588
|
+
const next = measureElement(ref.current).height;
|
|
1589
|
+
setHeight((prev) => prev === next ? prev : next);
|
|
1590
|
+
});
|
|
1591
|
+
return height;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1557
1594
|
//#endregion
|
|
1558
1595
|
//#region src/ui/hooks/useRailWidth.ts
|
|
1559
1596
|
function useRailWidth(railRef, phase, rows, columns) {
|
|
@@ -1640,7 +1677,6 @@ function useScroll(items, viewportHeight, getKey) {
|
|
|
1640
1677
|
//#endregion
|
|
1641
1678
|
//#region src/ui/palette.ts
|
|
1642
1679
|
const ui = {
|
|
1643
|
-
heading: "#7aa2f7",
|
|
1644
1680
|
accent: "#7dcfff",
|
|
1645
1681
|
muted: "#9aa0b3",
|
|
1646
1682
|
faint: "#565c6b",
|
|
@@ -1684,7 +1720,7 @@ const PHASE_META = {
|
|
|
1684
1720
|
},
|
|
1685
1721
|
error: {
|
|
1686
1722
|
label: "error",
|
|
1687
|
-
icon: "
|
|
1723
|
+
icon: "✘",
|
|
1688
1724
|
color: ui.bad,
|
|
1689
1725
|
kind: "static"
|
|
1690
1726
|
},
|
|
@@ -1753,6 +1789,12 @@ const FILTER_LEVELS = [
|
|
|
1753
1789
|
"debug",
|
|
1754
1790
|
"trace"
|
|
1755
1791
|
];
|
|
1792
|
+
function Heading({ label, open }) {
|
|
1793
|
+
return /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, {
|
|
1794
|
+
color: ui.accent,
|
|
1795
|
+
bold: true
|
|
1796
|
+
}, open ? "▾" : "▸"), /* @__PURE__ */ React.createElement(Text, { color: ui.muted }, " ", label));
|
|
1797
|
+
}
|
|
1756
1798
|
function Chip$1({ label, on, color, focused }) {
|
|
1757
1799
|
return /* @__PURE__ */ React.createElement(Box, { marginRight: 1 }, on ? /* @__PURE__ */ React.createElement(Text, {
|
|
1758
1800
|
color,
|
|
@@ -1764,15 +1806,18 @@ function Chip$1({ label, on, color, focused }) {
|
|
|
1764
1806
|
underline: focused
|
|
1765
1807
|
}, label));
|
|
1766
1808
|
}
|
|
1767
|
-
function FilterChips({ channels, enabledChannels, enabledLevels, cursor }) {
|
|
1809
|
+
function FilterChips({ channels, enabledChannels, enabledLevels, cursor, open }) {
|
|
1768
1810
|
const allChannels = enabledChannels.size === 0;
|
|
1769
1811
|
const allLevels = enabledLevels.size === 0;
|
|
1770
1812
|
const channelFocus = focusedIn(cursor, "channels", channels.length);
|
|
1771
1813
|
const levelFocus = focusedIn(cursor, "levels", FILTER_LEVELS.length);
|
|
1772
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, {
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
}, "
|
|
1814
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, open ? null : /* @__PURE__ */ React.createElement(Text, {
|
|
1815
|
+
dimColor: true,
|
|
1816
|
+
wrap: "truncate"
|
|
1817
|
+
}, "↕ resize to see filters"), /* @__PURE__ */ React.createElement(Heading, {
|
|
1818
|
+
label: "channels",
|
|
1819
|
+
open
|
|
1820
|
+
}), open ? /* @__PURE__ */ React.createElement(Box, {
|
|
1776
1821
|
marginLeft: 2,
|
|
1777
1822
|
flexWrap: "wrap"
|
|
1778
1823
|
}, channels.map((channel, index) => /* @__PURE__ */ React.createElement(Chip$1, {
|
|
@@ -1781,10 +1826,10 @@ function FilterChips({ channels, enabledChannels, enabledLevels, cursor }) {
|
|
|
1781
1826
|
on: allChannels || enabledChannels.has(channel),
|
|
1782
1827
|
color: channelColor(channel),
|
|
1783
1828
|
focused: channelFocus === index
|
|
1784
|
-
}))), /* @__PURE__ */ React.createElement(
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
},
|
|
1829
|
+
}))) : null, /* @__PURE__ */ React.createElement(Heading, {
|
|
1830
|
+
label: "levels",
|
|
1831
|
+
open
|
|
1832
|
+
}), open ? /* @__PURE__ */ React.createElement(Box, {
|
|
1788
1833
|
marginLeft: 2,
|
|
1789
1834
|
flexWrap: "wrap"
|
|
1790
1835
|
}, FILTER_LEVELS.map((level, index) => /* @__PURE__ */ React.createElement(Chip$1, {
|
|
@@ -1793,7 +1838,7 @@ function FilterChips({ channels, enabledChannels, enabledLevels, cursor }) {
|
|
|
1793
1838
|
on: allLevels || enabledLevels.has(level),
|
|
1794
1839
|
color: LEVEL_COLOR[level],
|
|
1795
1840
|
focused: levelFocus === index
|
|
1796
|
-
}))));
|
|
1841
|
+
}))) : null);
|
|
1797
1842
|
}
|
|
1798
1843
|
|
|
1799
1844
|
//#endregion
|
|
@@ -1849,17 +1894,16 @@ function applyAtCursor(ctx, channels, onChannel, onLevel) {
|
|
|
1849
1894
|
const level = index === null ? void 0 : FILTER_LEVELS[index];
|
|
1850
1895
|
if (level !== void 0) ctx.setEnabledLevels(onLevel(ctx.enabledLevels, level));
|
|
1851
1896
|
}
|
|
1852
|
-
function
|
|
1853
|
-
if (!ctx.
|
|
1897
|
+
function handleFilters(ctx) {
|
|
1898
|
+
if (!ctx.filtersOpen) return false;
|
|
1854
1899
|
const channels = LogStore.instance.getChannels();
|
|
1855
1900
|
const move = (dir) => ctx.setCursor(moveCursor(ctx.cursor, dir, channels.length, FILTER_LEVELS.length));
|
|
1856
|
-
if (ctx.key.
|
|
1857
|
-
else if (ctx.key.leftArrow) move("left");
|
|
1901
|
+
if (ctx.key.leftArrow) move("left");
|
|
1858
1902
|
else if (ctx.key.rightArrow) move("right");
|
|
1859
|
-
else if (ctx.key.
|
|
1860
|
-
else if (ctx.key.downArrow) move("down");
|
|
1903
|
+
else if (ctx.key.tab) move("switch");
|
|
1861
1904
|
else if (ctx.input === " ") applyAtCursor(ctx, channels, soloChannel, soloLevel);
|
|
1862
|
-
else if (ctx.input === "
|
|
1905
|
+
else if (ctx.input === "o") applyAtCursor(ctx, channels, toggleChannel, toggleLevel);
|
|
1906
|
+
else return false;
|
|
1863
1907
|
return true;
|
|
1864
1908
|
}
|
|
1865
1909
|
function handleScroll(ctx) {
|
|
@@ -1890,10 +1934,6 @@ function handleActions(ctx) {
|
|
|
1890
1934
|
store.beginRestart();
|
|
1891
1935
|
ctx.onRestart?.();
|
|
1892
1936
|
break;
|
|
1893
|
-
case "f":
|
|
1894
|
-
ctx.setCursor(INITIAL_CURSOR);
|
|
1895
|
-
ctx.setShowToggles(true);
|
|
1896
|
-
break;
|
|
1897
1937
|
case "l":
|
|
1898
1938
|
LogStore.instance.clear();
|
|
1899
1939
|
ctx.scroll.toBottom();
|
|
@@ -1903,7 +1943,7 @@ function handleActions(ctx) {
|
|
|
1903
1943
|
function dispatchHotkey(ctx) {
|
|
1904
1944
|
if (handleQuitSignal(ctx)) return;
|
|
1905
1945
|
if (handlePrompt(ctx)) return;
|
|
1906
|
-
if (
|
|
1946
|
+
if (handleFilters(ctx)) return;
|
|
1907
1947
|
if (handleScroll(ctx)) return;
|
|
1908
1948
|
handleActions(ctx);
|
|
1909
1949
|
}
|
|
@@ -1919,75 +1959,27 @@ function LogHeader({ following, below }) {
|
|
|
1919
1959
|
}
|
|
1920
1960
|
|
|
1921
1961
|
//#endregion
|
|
1922
|
-
//#region src/ui/components/
|
|
1923
|
-
function
|
|
1924
|
-
|
|
1925
|
-
borderStyle: "round",
|
|
1926
|
-
borderColor: ui.warn,
|
|
1927
|
-
flexDirection: "column",
|
|
1928
|
-
paddingX: 1
|
|
1929
|
-
}, /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, {
|
|
1930
|
-
color: ui.warn,
|
|
1931
|
-
bold: true
|
|
1932
|
-
}, "Commands updated:")), files.map((file) => /* @__PURE__ */ React.createElement(Text, {
|
|
1933
|
-
key: file,
|
|
1934
|
-
color: ui.accent
|
|
1935
|
-
}, "- ", file)), /* @__PURE__ */ React.createElement(Text, null, "Refresh commands? (y/n)"));
|
|
1936
|
-
}
|
|
1937
|
-
|
|
1938
|
-
//#endregion
|
|
1939
|
-
//#region src/ui/components/ErrorDisplay.tsx
|
|
1940
|
-
const STACK_PREVIEW_LINES = 6;
|
|
1941
|
-
function ErrorDisplay({ error }) {
|
|
1942
|
-
const frames = (error.stack?.split("\n") ?? []).slice(1);
|
|
1943
|
-
const preview = frames.slice(0, STACK_PREVIEW_LINES);
|
|
1944
|
-
const hidden = frames.length - preview.length;
|
|
1962
|
+
//#region src/ui/components/primitives/NotificationStack.tsx
|
|
1963
|
+
function NotificationStack({ notices }) {
|
|
1964
|
+
if (notices.length === 0) return null;
|
|
1945
1965
|
return /* @__PURE__ */ React.createElement(Box, {
|
|
1946
|
-
|
|
1947
|
-
borderStyle: "round",
|
|
1948
|
-
borderColor: ui.bad,
|
|
1949
|
-
padding: 1
|
|
1950
|
-
}, /* @__PURE__ */ React.createElement(Box, { marginTop: -1 }, /* @__PURE__ */ React.createElement(Text, {
|
|
1951
|
-
color: ui.bad,
|
|
1952
|
-
bold: true
|
|
1953
|
-
}, "Error: ", error.name)), /* @__PURE__ */ React.createElement(Text, null, error.message), preview.length > 0 && /* @__PURE__ */ React.createElement(Box, {
|
|
1954
|
-
marginTop: 1,
|
|
1966
|
+
flexShrink: 0,
|
|
1955
1967
|
flexDirection: "column"
|
|
1956
|
-
},
|
|
1957
|
-
key: line,
|
|
1958
|
-
dimColor: true,
|
|
1959
|
-
wrap: "truncate"
|
|
1960
|
-
}, line)), hidden > 0 && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, `… ${hidden} more line${hidden === 1 ? "" : "s"}`)), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, "press", " ", /* @__PURE__ */ React.createElement(Text, {
|
|
1961
|
-
color: ui.warn,
|
|
1962
|
-
bold: true
|
|
1963
|
-
}, "r"), " ", "to restart")));
|
|
1964
|
-
}
|
|
1965
|
-
|
|
1966
|
-
//#endregion
|
|
1967
|
-
//#region src/ui/components/RestartRequiredCard.tsx
|
|
1968
|
-
function RestartRequiredCard() {
|
|
1969
|
-
return /* @__PURE__ */ React.createElement(Box, {
|
|
1970
|
-
borderStyle: "round",
|
|
1971
|
-
borderColor: ui.warn,
|
|
1972
|
-
flexDirection: "column",
|
|
1973
|
-
paddingX: 1
|
|
1974
|
-
}, /* @__PURE__ */ React.createElement(Text, {
|
|
1975
|
-
color: ui.warn,
|
|
1976
|
-
bold: true
|
|
1977
|
-
}, "Restart required"), /* @__PURE__ */ React.createElement(Text, null, "A change needs a full restart. press", " ", /* @__PURE__ */ React.createElement(Text, {
|
|
1978
|
-
color: ui.warn,
|
|
1979
|
-
bold: true
|
|
1980
|
-
}, "r"), " ", "to restart"));
|
|
1968
|
+
}, notices.map((notice) => /* @__PURE__ */ React.createElement(Fragment, { key: notice.key }, notice.card)));
|
|
1981
1969
|
}
|
|
1982
1970
|
|
|
1983
1971
|
//#endregion
|
|
1984
|
-
//#region src/ui/components/primitives/
|
|
1985
|
-
function
|
|
1986
|
-
if (!error && !restartRequired && !prompt) return null;
|
|
1972
|
+
//#region src/ui/components/primitives/Rule.tsx
|
|
1973
|
+
function Rule() {
|
|
1987
1974
|
return /* @__PURE__ */ React.createElement(Box, {
|
|
1988
1975
|
flexShrink: 0,
|
|
1989
|
-
|
|
1990
|
-
|
|
1976
|
+
borderStyle: "single",
|
|
1977
|
+
borderTop: true,
|
|
1978
|
+
borderBottom: false,
|
|
1979
|
+
borderLeft: false,
|
|
1980
|
+
borderRight: false,
|
|
1981
|
+
borderDimColor: true
|
|
1982
|
+
});
|
|
1991
1983
|
}
|
|
1992
1984
|
|
|
1993
1985
|
//#endregion
|
|
@@ -2015,7 +2007,8 @@ function formatClock(ts) {
|
|
|
2015
2007
|
|
|
2016
2008
|
//#endregion
|
|
2017
2009
|
//#region src/ui/components/primitives/ScrollableLogView.tsx
|
|
2018
|
-
const MIN_LOG_LINES =
|
|
2010
|
+
const MIN_LOG_LINES = 5;
|
|
2011
|
+
const NO_ROOM = "Need more room for logs.";
|
|
2019
2012
|
const DOT = "⏺";
|
|
2020
2013
|
const BAR = "▌";
|
|
2021
2014
|
const GUIDE = "│";
|
|
@@ -2066,23 +2059,18 @@ function ContinuationLine({ log, labelWidth }) {
|
|
|
2066
2059
|
}, BAR), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, log.text));
|
|
2067
2060
|
return /* @__PURE__ */ React.createElement(Text, { wrap: "truncate" }, " ".repeat(messageColumn(labelWidth) - 2), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, GUIDE), " ", log.text);
|
|
2068
2061
|
}
|
|
2069
|
-
function Rule() {
|
|
2070
|
-
return /* @__PURE__ */ React.createElement(Box, {
|
|
2071
|
-
flexShrink: 0,
|
|
2072
|
-
borderStyle: "single",
|
|
2073
|
-
borderTop: true,
|
|
2074
|
-
borderBottom: false,
|
|
2075
|
-
borderLeft: false,
|
|
2076
|
-
borderRight: false,
|
|
2077
|
-
borderDimColor: true
|
|
2078
|
-
});
|
|
2079
|
-
}
|
|
2080
2062
|
function ScrollableLogView({ visible, viewportHeight, measured }) {
|
|
2081
2063
|
if (!measured) return null;
|
|
2082
|
-
if (viewportHeight < MIN_LOG_LINES) return /* @__PURE__ */ React.createElement(
|
|
2083
|
-
|
|
2064
|
+
if (viewportHeight < MIN_LOG_LINES) return /* @__PURE__ */ React.createElement(Box, {
|
|
2065
|
+
flexGrow: 1,
|
|
2066
|
+
alignItems: "center",
|
|
2067
|
+
justifyContent: "center",
|
|
2068
|
+
overflow: "hidden"
|
|
2069
|
+
}, /* @__PURE__ */ React.createElement(Text, {
|
|
2070
|
+
color: ui.warn,
|
|
2071
|
+
bold: true,
|
|
2084
2072
|
wrap: "truncate"
|
|
2085
|
-
},
|
|
2073
|
+
}, NO_ROOM));
|
|
2086
2074
|
const labelWidth = Math.max(1, LogStore.instance.getLabelWidth());
|
|
2087
2075
|
return /* @__PURE__ */ React.createElement(Box, {
|
|
2088
2076
|
flexDirection: "column",
|
|
@@ -2115,24 +2103,36 @@ function Banner({ version }) {
|
|
|
2115
2103
|
}, "cord"), version === null ? null : /* @__PURE__ */ React.createElement(Text, { color: VERSION_COLOR }, " • v", version));
|
|
2116
2104
|
}
|
|
2117
2105
|
|
|
2106
|
+
//#endregion
|
|
2107
|
+
//#region src/ui/components/primitives/BlinkDot.tsx
|
|
2108
|
+
const BLINK_MS = 530;
|
|
2109
|
+
function BlinkDot() {
|
|
2110
|
+
const { frame } = useAnimation({ interval: BLINK_MS });
|
|
2111
|
+
return /* @__PURE__ */ React.createElement(Text, { color: ui.bad }, frame % 2 === 0 ? "●" : " ");
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2118
2114
|
//#endregion
|
|
2119
2115
|
//#region src/ui/components/StatusBadge.tsx
|
|
2120
|
-
function Glyph({ phase }) {
|
|
2116
|
+
function Glyph({ phase, glyph }) {
|
|
2121
2117
|
const meta = PHASE_META[phase];
|
|
2118
|
+
if (glyph === "live") return isStreaming(phase) ? /* @__PURE__ */ React.createElement(BlinkDot, null) : /* @__PURE__ */ React.createElement(Text, null, meta.icon);
|
|
2122
2119
|
if (meta.kind === "spinner") return /* @__PURE__ */ React.createElement(Spinner, { type: "balloon2" });
|
|
2123
2120
|
if (meta.kind === "arc") return /* @__PURE__ */ React.createElement(Spinner, { type: "toggle4" });
|
|
2124
2121
|
return /* @__PURE__ */ React.createElement(Text, null, meta.icon);
|
|
2125
2122
|
}
|
|
2126
|
-
function StatusBadge({ phase }) {
|
|
2123
|
+
function StatusBadge({ phase, glyph = "phase" }) {
|
|
2127
2124
|
const meta = PHASE_META[phase];
|
|
2128
2125
|
return /* @__PURE__ */ React.createElement(Text, {
|
|
2129
2126
|
color: meta.color,
|
|
2130
2127
|
bold: true
|
|
2131
|
-
}, /* @__PURE__ */ React.createElement(Glyph, {
|
|
2128
|
+
}, /* @__PURE__ */ React.createElement(Glyph, {
|
|
2129
|
+
phase,
|
|
2130
|
+
glyph
|
|
2131
|
+
}), " ", meta.label);
|
|
2132
2132
|
}
|
|
2133
2133
|
|
|
2134
2134
|
//#endregion
|
|
2135
|
-
//#region src/ui/components/primitives/
|
|
2135
|
+
//#region src/ui/components/primitives/Hotkeys.tsx
|
|
2136
2136
|
function Hotkey({ keyLabel, action, enabled = true, highlight = false }) {
|
|
2137
2137
|
const keyColor = !enabled ? ui.faint : highlight ? ui.warn : ui.accent;
|
|
2138
2138
|
const actionColor = enabled ? ui.muted : ui.faint;
|
|
@@ -2146,8 +2146,8 @@ const RESTART_HINT_PHASES = new Set([
|
|
|
2146
2146
|
"disconnected",
|
|
2147
2147
|
"error"
|
|
2148
2148
|
]);
|
|
2149
|
-
function
|
|
2150
|
-
return /* @__PURE__ */ React.createElement(
|
|
2149
|
+
function SessionKeys({ phase, interactive, following }) {
|
|
2150
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Hotkey, {
|
|
2151
2151
|
keyLabel: "q",
|
|
2152
2152
|
action: "quit"
|
|
2153
2153
|
}), /* @__PURE__ */ React.createElement(Hotkey, {
|
|
@@ -2159,10 +2159,6 @@ function DefaultKeys({ phase, interactive, following }) {
|
|
|
2159
2159
|
keyLabel: "d",
|
|
2160
2160
|
action: "disconnect",
|
|
2161
2161
|
enabled: interactive && isSessionLive(phase)
|
|
2162
|
-
}), /* @__PURE__ */ React.createElement(Hotkey, {
|
|
2163
|
-
keyLabel: "f",
|
|
2164
|
-
action: "filters",
|
|
2165
|
-
enabled: interactive
|
|
2166
2162
|
}), /* @__PURE__ */ React.createElement(Hotkey, {
|
|
2167
2163
|
keyLabel: "l",
|
|
2168
2164
|
action: "clear",
|
|
@@ -2176,29 +2172,19 @@ function DefaultKeys({ phase, interactive, following }) {
|
|
|
2176
2172
|
highlight: !following
|
|
2177
2173
|
}));
|
|
2178
2174
|
}
|
|
2179
|
-
function
|
|
2180
|
-
return /* @__PURE__ */ React.createElement(Box, {
|
|
2181
|
-
flexDirection: "column",
|
|
2182
|
-
flexWrap: "wrap"
|
|
2183
|
-
}, mode === "toggles" && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Hotkey, {
|
|
2175
|
+
function FilterKeys() {
|
|
2176
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Hotkey, {
|
|
2184
2177
|
keyLabel: "←→",
|
|
2185
|
-
action: "
|
|
2178
|
+
action: "select"
|
|
2186
2179
|
}), /* @__PURE__ */ React.createElement(Hotkey, {
|
|
2187
|
-
keyLabel: "
|
|
2180
|
+
keyLabel: "tab",
|
|
2188
2181
|
action: "group"
|
|
2189
2182
|
}), /* @__PURE__ */ React.createElement(Hotkey, {
|
|
2190
2183
|
keyLabel: "space",
|
|
2191
|
-
action: "
|
|
2184
|
+
action: "filter"
|
|
2192
2185
|
}), /* @__PURE__ */ React.createElement(Hotkey, {
|
|
2193
|
-
keyLabel: "
|
|
2186
|
+
keyLabel: "o",
|
|
2194
2187
|
action: "toggle"
|
|
2195
|
-
}), /* @__PURE__ */ React.createElement(Hotkey, {
|
|
2196
|
-
keyLabel: "↵/esc",
|
|
2197
|
-
action: "done"
|
|
2198
|
-
})), mode === "default" && /* @__PURE__ */ React.createElement(DefaultKeys, {
|
|
2199
|
-
phase,
|
|
2200
|
-
interactive,
|
|
2201
|
-
following
|
|
2202
2188
|
}));
|
|
2203
2189
|
}
|
|
2204
2190
|
|
|
@@ -2207,11 +2193,6 @@ function HotkeyBar({ phase, interactive, mode, following }) {
|
|
|
2207
2193
|
const MAX_RAIL = 40;
|
|
2208
2194
|
const META_LABEL_WIDTH = 5;
|
|
2209
2195
|
const LOG_DIR = "logs/";
|
|
2210
|
-
const BLINK_MS = 530;
|
|
2211
|
-
function LiveDot() {
|
|
2212
|
-
const { frame } = useAnimation({ interval: BLINK_MS });
|
|
2213
|
-
return /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { color: ui.bad }, frame % 2 === 0 ? "●" : " "), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " live"));
|
|
2214
|
-
}
|
|
2215
2196
|
function Meta({ label, value }) {
|
|
2216
2197
|
return /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, label.padEnd(META_LABEL_WIDTH)), value);
|
|
2217
2198
|
}
|
|
@@ -2224,12 +2205,12 @@ function StatusBlock({ state, uptimeMs }) {
|
|
|
2224
2205
|
value: LOG_DIR
|
|
2225
2206
|
}));
|
|
2226
2207
|
}
|
|
2227
|
-
function Sidebar({ state, enabled, enabledLevels, uptimeMs, following, interactive,
|
|
2208
|
+
function Sidebar({ state, enabled, enabledLevels, uptimeMs, following, interactive, cursor, width, filtersOpen, ref }) {
|
|
2228
2209
|
return /* @__PURE__ */ React.createElement(Box, {
|
|
2229
2210
|
ref,
|
|
2230
2211
|
flexDirection: "column",
|
|
2231
2212
|
width: width ?? void 0,
|
|
2232
|
-
maxWidth:
|
|
2213
|
+
maxWidth: 40,
|
|
2233
2214
|
flexShrink: 0,
|
|
2234
2215
|
paddingX: 1,
|
|
2235
2216
|
overflow: "hidden"
|
|
@@ -2247,27 +2228,57 @@ function Sidebar({ state, enabled, enabledLevels, uptimeMs, following, interacti
|
|
|
2247
2228
|
channels: LogStore.instance.getChannels(),
|
|
2248
2229
|
enabledChannels: enabled,
|
|
2249
2230
|
enabledLevels,
|
|
2250
|
-
cursor
|
|
2251
|
-
|
|
2231
|
+
cursor,
|
|
2232
|
+
open: filtersOpen
|
|
2233
|
+
})), filtersOpen ? /* @__PURE__ */ React.createElement(Box, {
|
|
2252
2234
|
flexShrink: 0,
|
|
2253
|
-
marginTop: 1
|
|
2254
|
-
|
|
2235
|
+
marginTop: 1,
|
|
2236
|
+
flexDirection: "column"
|
|
2237
|
+
}, /* @__PURE__ */ React.createElement(FilterKeys, null), /* @__PURE__ */ React.createElement(Rule, null)) : null, /* @__PURE__ */ React.createElement(Box, {
|
|
2238
|
+
flexShrink: 0,
|
|
2239
|
+
marginTop: filtersOpen ? 0 : 1
|
|
2240
|
+
}, /* @__PURE__ */ React.createElement(SessionKeys, {
|
|
2255
2241
|
phase: state.phase,
|
|
2256
2242
|
interactive,
|
|
2257
|
-
mode: showToggles ? "toggles" : "default",
|
|
2258
2243
|
following
|
|
2259
2244
|
})), /* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }), /* @__PURE__ */ React.createElement(Box, {
|
|
2260
2245
|
flexShrink: 0,
|
|
2261
2246
|
justifyContent: "flex-end"
|
|
2262
|
-
}, isStreaming(state.phase) ? /* @__PURE__ */ React.createElement(
|
|
2247
|
+
}, isStreaming(state.phase) ? /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(BlinkDot, null), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " live")) : /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "○ idle")));
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
//#endregion
|
|
2251
|
+
//#region src/ui/components/primitives/StatusLine.tsx
|
|
2252
|
+
const HINT = "↕ resize for full ui";
|
|
2253
|
+
const HINT_COLUMNS = 64;
|
|
2254
|
+
/** The single row standing in for the rail once the terminal is too small to hold it. */
|
|
2255
|
+
function StatusLine({ state, notices, columns }) {
|
|
2256
|
+
const [top, ...rest] = notices;
|
|
2257
|
+
return /* @__PURE__ */ React.createElement(Box, {
|
|
2258
|
+
flexShrink: 0,
|
|
2259
|
+
justifyContent: "space-between"
|
|
2260
|
+
}, /* @__PURE__ */ React.createElement(Box, {
|
|
2261
|
+
flexShrink: 1,
|
|
2262
|
+
overflow: "hidden"
|
|
2263
|
+
}, /* @__PURE__ */ React.createElement(Text, { wrap: "truncate" }, /* @__PURE__ */ React.createElement(Banner, { version: null }), " ", /* @__PURE__ */ React.createElement(StatusBadge, {
|
|
2264
|
+
phase: state.phase,
|
|
2265
|
+
glyph: "live"
|
|
2266
|
+
}), top?.summary ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " · ") : null, top?.summary ? /* @__PURE__ */ React.createElement(Text, { color: ui.warn }, top.summary) : null, rest.length > 0 ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " · +", rest.length) : null)), /* @__PURE__ */ React.createElement(Box, {
|
|
2267
|
+
flexShrink: 0,
|
|
2268
|
+
marginLeft: 2
|
|
2269
|
+
}, top ? /* @__PURE__ */ React.createElement(Text, {
|
|
2270
|
+
bold: true,
|
|
2271
|
+
color: ui.accent
|
|
2272
|
+
}, top.action) : null, !top && columns >= HINT_COLUMNS ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, HINT) : null));
|
|
2263
2273
|
}
|
|
2264
2274
|
|
|
2265
2275
|
//#endregion
|
|
2266
2276
|
//#region src/ui/layout/DevLayout.tsx
|
|
2267
2277
|
function DevLayout(props) {
|
|
2268
|
-
const { state, railRef, railWidth, logBoxRef, scroll, viewportHeight, measured } = props;
|
|
2269
|
-
const { enabled, enabledLevels,
|
|
2270
|
-
|
|
2278
|
+
const { state, tier, notices, railRef, railWidth, logBoxRef, scroll, viewportHeight, measured } = props;
|
|
2279
|
+
const { columns, enabled, enabledLevels, cursor, interactive, uptimeMs } = props;
|
|
2280
|
+
const railed = tier === "full" || tier === "compact";
|
|
2281
|
+
return /* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }, railed ? /* @__PURE__ */ React.createElement(Sidebar, {
|
|
2271
2282
|
ref: railRef,
|
|
2272
2283
|
state,
|
|
2273
2284
|
enabled,
|
|
@@ -2275,10 +2286,10 @@ function DevLayout(props) {
|
|
|
2275
2286
|
uptimeMs,
|
|
2276
2287
|
following: scroll.following,
|
|
2277
2288
|
interactive,
|
|
2278
|
-
showToggles,
|
|
2279
2289
|
cursor,
|
|
2280
|
-
width: railWidth
|
|
2281
|
-
|
|
2290
|
+
width: railWidth,
|
|
2291
|
+
filtersOpen: tier === "full"
|
|
2292
|
+
}) : null, /* @__PURE__ */ React.createElement(Box, {
|
|
2282
2293
|
flexDirection: "column",
|
|
2283
2294
|
flexGrow: 1,
|
|
2284
2295
|
minWidth: 0,
|
|
@@ -2287,24 +2298,26 @@ function DevLayout(props) {
|
|
|
2287
2298
|
borderTop: false,
|
|
2288
2299
|
borderRight: false,
|
|
2289
2300
|
borderBottom: false,
|
|
2290
|
-
|
|
2301
|
+
borderLeft: railed,
|
|
2302
|
+
paddingLeft: railed ? 1 : 0,
|
|
2291
2303
|
overflow: "hidden"
|
|
2292
|
-
}, /* @__PURE__ */ React.createElement(
|
|
2304
|
+
}, railed ? null : /* @__PURE__ */ React.createElement(StatusLine, {
|
|
2305
|
+
state,
|
|
2306
|
+
notices,
|
|
2307
|
+
columns
|
|
2308
|
+
}), railed ? null : /* @__PURE__ */ React.createElement(Rule, null), /* @__PURE__ */ React.createElement(LogHeader, {
|
|
2293
2309
|
following: scroll.following,
|
|
2294
2310
|
below: scroll.below
|
|
2295
2311
|
}), /* @__PURE__ */ React.createElement(Box, {
|
|
2296
2312
|
ref: logBoxRef,
|
|
2297
2313
|
flexGrow: 1,
|
|
2314
|
+
minHeight: 1,
|
|
2298
2315
|
overflow: "hidden"
|
|
2299
2316
|
}, /* @__PURE__ */ React.createElement(ScrollableLogView, {
|
|
2300
2317
|
visible: scroll.visible,
|
|
2301
2318
|
viewportHeight,
|
|
2302
2319
|
measured
|
|
2303
|
-
})), /* @__PURE__ */ React.createElement(NotificationStack, {
|
|
2304
|
-
error: state.error,
|
|
2305
|
-
restartRequired: state.restartRequired,
|
|
2306
|
-
prompt: state.commandUpdatePrompt
|
|
2307
|
-
})));
|
|
2320
|
+
})), railed ? /* @__PURE__ */ React.createElement(NotificationStack, { notices }) : null));
|
|
2308
2321
|
}
|
|
2309
2322
|
|
|
2310
2323
|
//#endregion
|
|
@@ -2349,6 +2362,110 @@ function rowKey(row) {
|
|
|
2349
2362
|
return row.key;
|
|
2350
2363
|
}
|
|
2351
2364
|
|
|
2365
|
+
//#endregion
|
|
2366
|
+
//#region src/ui/components/CommandRefreshPrompt.tsx
|
|
2367
|
+
function CommandRefreshPrompt({ files }) {
|
|
2368
|
+
return /* @__PURE__ */ React.createElement(Box, {
|
|
2369
|
+
borderStyle: "round",
|
|
2370
|
+
borderColor: ui.warn,
|
|
2371
|
+
flexDirection: "column",
|
|
2372
|
+
paddingX: 1
|
|
2373
|
+
}, /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, {
|
|
2374
|
+
color: ui.warn,
|
|
2375
|
+
bold: true
|
|
2376
|
+
}, "Commands updated:")), files.map((file) => /* @__PURE__ */ React.createElement(Text, {
|
|
2377
|
+
key: file,
|
|
2378
|
+
color: ui.accent
|
|
2379
|
+
}, "- ", file)), /* @__PURE__ */ React.createElement(Text, null, "Refresh commands? (y/n)"));
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2382
|
+
//#endregion
|
|
2383
|
+
//#region src/ui/components/ErrorDisplay.tsx
|
|
2384
|
+
const STACK_PREVIEW_LINES = 6;
|
|
2385
|
+
function ErrorDisplay({ error }) {
|
|
2386
|
+
const frames = (error.stack?.split("\n") ?? []).slice(1);
|
|
2387
|
+
const preview = frames.slice(0, STACK_PREVIEW_LINES);
|
|
2388
|
+
const hidden = frames.length - preview.length;
|
|
2389
|
+
return /* @__PURE__ */ React.createElement(Box, {
|
|
2390
|
+
flexDirection: "column",
|
|
2391
|
+
borderStyle: "round",
|
|
2392
|
+
borderColor: ui.bad,
|
|
2393
|
+
paddingX: 1
|
|
2394
|
+
}, /* @__PURE__ */ React.createElement(Text, {
|
|
2395
|
+
color: ui.bad,
|
|
2396
|
+
bold: true
|
|
2397
|
+
}, "Error: ", error.name), /* @__PURE__ */ React.createElement(Text, null, error.message), preview.length > 0 && /* @__PURE__ */ React.createElement(Box, {
|
|
2398
|
+
marginTop: 1,
|
|
2399
|
+
flexDirection: "column"
|
|
2400
|
+
}, preview.map((line) => /* @__PURE__ */ React.createElement(Text, {
|
|
2401
|
+
key: line,
|
|
2402
|
+
dimColor: true,
|
|
2403
|
+
wrap: "truncate"
|
|
2404
|
+
}, line)), hidden > 0 && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, `… ${hidden} more line${hidden === 1 ? "" : "s"}`)), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, "press", " ", /* @__PURE__ */ React.createElement(Text, {
|
|
2405
|
+
color: ui.warn,
|
|
2406
|
+
bold: true
|
|
2407
|
+
}, "r"), " ", "to restart")));
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
//#endregion
|
|
2411
|
+
//#region src/ui/components/RestartRequiredCard.tsx
|
|
2412
|
+
function RestartRequiredCard() {
|
|
2413
|
+
return /* @__PURE__ */ React.createElement(Box, {
|
|
2414
|
+
borderStyle: "round",
|
|
2415
|
+
borderColor: ui.warn,
|
|
2416
|
+
flexDirection: "column",
|
|
2417
|
+
paddingX: 1
|
|
2418
|
+
}, /* @__PURE__ */ React.createElement(Text, {
|
|
2419
|
+
color: ui.warn,
|
|
2420
|
+
bold: true
|
|
2421
|
+
}, "Restart required"), /* @__PURE__ */ React.createElement(Text, null, "A change needs a full restart. press", " ", /* @__PURE__ */ React.createElement(Text, {
|
|
2422
|
+
color: ui.warn,
|
|
2423
|
+
bold: true
|
|
2424
|
+
}, "r"), " ", "to restart"));
|
|
2425
|
+
}
|
|
2426
|
+
|
|
2427
|
+
//#endregion
|
|
2428
|
+
//#region src/ui/notices.tsx
|
|
2429
|
+
const RESTART = "press r to restart";
|
|
2430
|
+
/** Every pending notice, ranked with the one that blocks a decision first. */
|
|
2431
|
+
function noticesOf(state) {
|
|
2432
|
+
const notices = [];
|
|
2433
|
+
if (state.commandUpdatePrompt) {
|
|
2434
|
+
const count = state.commandUpdatePrompt.length;
|
|
2435
|
+
notices.push({
|
|
2436
|
+
key: "commands",
|
|
2437
|
+
summary: `${count} command${count === 1 ? "" : "s"} updated`,
|
|
2438
|
+
action: "refresh? y/n",
|
|
2439
|
+
card: /* @__PURE__ */ React.createElement(CommandRefreshPrompt, { files: [...state.commandUpdatePrompt] })
|
|
2440
|
+
});
|
|
2441
|
+
}
|
|
2442
|
+
if (state.error) notices.push({
|
|
2443
|
+
key: "error",
|
|
2444
|
+
summary: state.error.message,
|
|
2445
|
+
action: RESTART,
|
|
2446
|
+
card: /* @__PURE__ */ React.createElement(ErrorDisplay, { error: state.error })
|
|
2447
|
+
});
|
|
2448
|
+
if (state.restartRequired) notices.push({
|
|
2449
|
+
key: "restart",
|
|
2450
|
+
summary: "",
|
|
2451
|
+
action: RESTART,
|
|
2452
|
+
card: /* @__PURE__ */ React.createElement(RestartRequiredCard, null)
|
|
2453
|
+
});
|
|
2454
|
+
return notices;
|
|
2455
|
+
}
|
|
2456
|
+
|
|
2457
|
+
//#endregion
|
|
2458
|
+
//#region src/ui/tier.ts
|
|
2459
|
+
const FULL_ROWS = 29;
|
|
2460
|
+
const COMPACT_ROWS = 20;
|
|
2461
|
+
const RAIL_COLUMNS = 80;
|
|
2462
|
+
function tierFor(rows, columns) {
|
|
2463
|
+
if (columns < 80) return "logs";
|
|
2464
|
+
if (rows >= 29) return "full";
|
|
2465
|
+
if (rows >= 20) return "compact";
|
|
2466
|
+
return "logs";
|
|
2467
|
+
}
|
|
2468
|
+
|
|
2352
2469
|
//#endregion
|
|
2353
2470
|
//#region src/ui/DevApp.tsx
|
|
2354
2471
|
function DevApp(props) {
|
|
@@ -2357,30 +2474,19 @@ function DevApp(props) {
|
|
|
2357
2474
|
const { rows, columns } = useWindowSize();
|
|
2358
2475
|
const [enabled, setEnabled] = useState(() => /* @__PURE__ */ new Set());
|
|
2359
2476
|
const [enabledLevels, setEnabledLevels] = useState(() => /* @__PURE__ */ new Set());
|
|
2360
|
-
const [showToggles, setShowToggles] = useState(false);
|
|
2361
2477
|
const [cursor, setCursor] = useState(INITIAL_CURSOR);
|
|
2362
2478
|
const logBoxRef = useRef(null);
|
|
2363
|
-
const
|
|
2479
|
+
const logBoxHeight = useMeasuredHeight(logBoxRef);
|
|
2364
2480
|
const railRef = useRef(null);
|
|
2365
2481
|
const railWidth = useRailWidth(railRef, state.phase, rows, columns);
|
|
2482
|
+
const tier = tierFor(rows, columns);
|
|
2483
|
+
const notices = noticesOf(state);
|
|
2366
2484
|
const logs = useLogs(enabled, enabledLevels);
|
|
2367
2485
|
const logRows = useMemo(() => expandRows(logs), [logs]);
|
|
2368
2486
|
const viewportHeight = Math.max(1, logBoxHeight);
|
|
2369
2487
|
const scroll = useScroll(logRows, viewportHeight, rowKey);
|
|
2370
2488
|
const uptimeMs = useUptime(state);
|
|
2371
2489
|
const interactive = !state.isBusy || state.restartRequired;
|
|
2372
|
-
useLayoutEffect(() => {
|
|
2373
|
-
if (!logBoxRef.current) return;
|
|
2374
|
-
const measured = measureElement(logBoxRef.current).height;
|
|
2375
|
-
setLogBoxHeight((prev) => prev === measured ? prev : measured);
|
|
2376
|
-
}, [
|
|
2377
|
-
rows,
|
|
2378
|
-
columns,
|
|
2379
|
-
state.error,
|
|
2380
|
-
state.restartRequired,
|
|
2381
|
-
state.commandUpdatePrompt,
|
|
2382
|
-
scroll.following
|
|
2383
|
-
]);
|
|
2384
2490
|
useInput((input, key) => {
|
|
2385
2491
|
dispatchHotkey({
|
|
2386
2492
|
input,
|
|
@@ -2393,10 +2499,9 @@ function DevApp(props) {
|
|
|
2393
2499
|
setEnabled,
|
|
2394
2500
|
enabledLevels,
|
|
2395
2501
|
setEnabledLevels,
|
|
2396
|
-
showToggles,
|
|
2397
|
-
setShowToggles,
|
|
2398
2502
|
cursor,
|
|
2399
2503
|
setCursor,
|
|
2504
|
+
filtersOpen: tier === "full",
|
|
2400
2505
|
onQuit: props.onQuit,
|
|
2401
2506
|
onDisconnect: props.onDisconnect,
|
|
2402
2507
|
onRestart: props.onRestart,
|
|
@@ -2421,15 +2526,17 @@ function DevApp(props) {
|
|
|
2421
2526
|
overflow: "hidden"
|
|
2422
2527
|
}, /* @__PURE__ */ React.createElement(DevLayout, {
|
|
2423
2528
|
state,
|
|
2529
|
+
tier,
|
|
2530
|
+
notices,
|
|
2424
2531
|
railRef,
|
|
2425
2532
|
railWidth,
|
|
2426
2533
|
logBoxRef,
|
|
2427
2534
|
scroll,
|
|
2428
2535
|
viewportHeight,
|
|
2429
2536
|
measured: logBoxHeight > 0,
|
|
2537
|
+
columns,
|
|
2430
2538
|
enabled,
|
|
2431
2539
|
enabledLevels,
|
|
2432
|
-
showToggles,
|
|
2433
2540
|
cursor,
|
|
2434
2541
|
interactive,
|
|
2435
2542
|
uptimeMs
|
|
@@ -2524,16 +2631,6 @@ var DevStore = class extends TypedEventEmitter {
|
|
|
2524
2631
|
}
|
|
2525
2632
|
};
|
|
2526
2633
|
|
|
2527
|
-
//#endregion
|
|
2528
|
-
//#region src/utils/SilentLogger.ts
|
|
2529
|
-
const silentLogger = {
|
|
2530
|
-
error: () => void 0,
|
|
2531
|
-
warn: () => void 0,
|
|
2532
|
-
info: () => void 0,
|
|
2533
|
-
debug: () => void 0,
|
|
2534
|
-
trace: () => void 0
|
|
2535
|
-
};
|
|
2536
|
-
|
|
2537
2634
|
//#endregion
|
|
2538
2635
|
//#region src/commands/dev/runtime/HmrPlugin.ts
|
|
2539
2636
|
const DEBOUNCE_MS = 250;
|
|
@@ -2992,10 +3089,8 @@ var DevRunner = class DevRunner {
|
|
|
2992
3089
|
}
|
|
2993
3090
|
static create(logger, store) {
|
|
2994
3091
|
const moduleLoader = new RuntimeModuleLoader();
|
|
2995
|
-
const
|
|
2996
|
-
|
|
2997
|
-
const codegenLogger = new Logger("CLI:Codegen");
|
|
2998
|
-
return new DevRunner(locator, configLoader, store, CodegenRunner.create(codegenLogger), codegenLogger);
|
|
3092
|
+
const codegenLogger = new Logger("Codegen", { channel: "cli" });
|
|
3093
|
+
return new DevRunner(new ConfigLocator(logger), new ConfigLoader(moduleLoader, logger), store, CodegenRunner.create(codegenLogger), codegenLogger);
|
|
2999
3094
|
}
|
|
3000
3095
|
async run() {
|
|
3001
3096
|
if (this.isRunning) return;
|
|
@@ -3043,7 +3138,7 @@ var DevRunner = class DevRunner {
|
|
|
3043
3138
|
async handleError(error) {
|
|
3044
3139
|
this.store.setPhase("error");
|
|
3045
3140
|
this.store.setError(Error.isError(error) ? error : new Error(String(error)));
|
|
3046
|
-
this.store.setStatus("
|
|
3141
|
+
this.store.setStatus("Press r to restart.");
|
|
3047
3142
|
this.store.setBusy(false);
|
|
3048
3143
|
await this.waitForSignal();
|
|
3049
3144
|
this.store.setBusy(true);
|
|
@@ -3097,9 +3192,9 @@ var DevCommand = class extends BaseCommand {
|
|
|
3097
3192
|
runner;
|
|
3098
3193
|
store;
|
|
3099
3194
|
constructor() {
|
|
3100
|
-
super("dev", "Run a Seedcord instance from the config file", "
|
|
3195
|
+
super("dev", "Run a Seedcord instance from the config file", "Dev");
|
|
3101
3196
|
this.store = new DevStore();
|
|
3102
|
-
this.runner = DevRunner.create(
|
|
3197
|
+
this.runner = DevRunner.create(this.logger, this.store);
|
|
3103
3198
|
}
|
|
3104
3199
|
register(program) {
|
|
3105
3200
|
program.command(this.name).description(this.description).action(async () => {
|
|
@@ -3149,7 +3244,6 @@ var DevCommand = class extends BaseCommand {
|
|
|
3149
3244
|
|
|
3150
3245
|
//#endregion
|
|
3151
3246
|
//#region src/cli.ts
|
|
3152
|
-
const LOGGER_LABEL = "seedcord CLI";
|
|
3153
3247
|
async function main() {
|
|
3154
3248
|
if (!process.env.ENV && !process.env.ENVIRONMENT && !process.env.NODE_ENV) process.env.NODE_ENV = "development";
|
|
3155
3249
|
installNodeDefaults();
|
|
@@ -3161,7 +3255,7 @@ async function main() {
|
|
|
3161
3255
|
await program.parseAsync(process.argv);
|
|
3162
3256
|
}
|
|
3163
3257
|
main().catch((error) => {
|
|
3164
|
-
new Logger(
|
|
3258
|
+
new Logger("CLI", { channel: "cli" }).error("Unexpected CLI error", error);
|
|
3165
3259
|
process.exit(1);
|
|
3166
3260
|
});
|
|
3167
3261
|
|