dx-devkit 0.0.0-stage → 1.1.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/CHANGELOG.md +81 -0
- package/LICENSE +21 -0
- package/README.md +475 -2
- package/bin/dx-mcp.js +2 -0
- package/dist/command.d.ts +9 -0
- package/dist/command.d.ts.map +1 -0
- package/dist/command.js +2 -0
- package/dist/command.js.map +1 -0
- package/dist/commands/ai.d.ts +7 -0
- package/dist/commands/ai.d.ts.map +1 -0
- package/dist/commands/ai.js +148 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/clean.d.ts +3 -0
- package/dist/commands/clean.d.ts.map +1 -0
- package/dist/commands/clean.js +72 -0
- package/dist/commands/clean.js.map +1 -0
- package/dist/commands/deps.d.ts +3 -0
- package/dist/commands/deps.d.ts.map +1 -0
- package/dist/commands/deps.js +98 -0
- package/dist/commands/deps.js.map +1 -0
- package/dist/commands/go.d.ts +3 -0
- package/dist/commands/go.d.ts.map +1 -0
- package/dist/commands/go.js +202 -0
- package/dist/commands/go.js.map +1 -0
- package/dist/commands/log.d.ts +3 -0
- package/dist/commands/log.d.ts.map +1 -0
- package/dist/commands/log.js +51 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/new.d.ts +3 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +117 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/port.d.ts +4 -0
- package/dist/commands/port.d.ts.map +1 -0
- package/dist/commands/port.js +106 -0
- package/dist/commands/port.js.map +1 -0
- package/dist/commands/projects.d.ts +5 -0
- package/dist/commands/projects.d.ts.map +1 -0
- package/dist/commands/projects.js +46 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/stack.d.ts +34 -0
- package/dist/commands/stack.d.ts.map +1 -0
- package/dist/commands/stack.js +140 -0
- package/dist/commands/stack.js.map +1 -0
- package/dist/commands/summary.d.ts +3 -0
- package/dist/commands/summary.d.ts.map +1 -0
- package/dist/commands/summary.js +88 -0
- package/dist/commands/summary.js.map +1 -0
- package/dist/commands/system.d.ts +5 -0
- package/dist/commands/system.d.ts.map +1 -0
- package/dist/commands/system.js +104 -0
- package/dist/commands/system.js.map +1 -0
- package/dist/commands/ui.d.ts +3 -0
- package/dist/commands/ui.d.ts.map +1 -0
- package/dist/commands/ui.js +96 -0
- package/dist/commands/ui.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +103 -0
- package/dist/index.js.map +1 -0
- package/dist/ui.d.ts +27 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +104 -0
- package/dist/ui.js.map +1 -0
- package/node_modules/@dx/core/dist/config.d.ts +46 -0
- package/node_modules/@dx/core/dist/config.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/config.js +131 -0
- package/node_modules/@dx/core/dist/config.js.map +1 -0
- package/node_modules/@dx/core/dist/fuzzy.d.ts +15 -0
- package/node_modules/@dx/core/dist/fuzzy.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/fuzzy.js +63 -0
- package/node_modules/@dx/core/dist/fuzzy.js.map +1 -0
- package/node_modules/@dx/core/dist/index.d.ts +17 -0
- package/node_modules/@dx/core/dist/index.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/index.js +19 -0
- package/node_modules/@dx/core/dist/index.js.map +1 -0
- package/node_modules/@dx/core/dist/runs.d.ts +19 -0
- package/node_modules/@dx/core/dist/runs.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/runs.js +41 -0
- package/node_modules/@dx/core/dist/runs.js.map +1 -0
- package/node_modules/@dx/core/dist/tools/aiSetup.d.ts +58 -0
- package/node_modules/@dx/core/dist/tools/aiSetup.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/tools/aiSetup.js +243 -0
- package/node_modules/@dx/core/dist/tools/aiSetup.js.map +1 -0
- package/node_modules/@dx/core/dist/tools/cleanup.d.ts +61 -0
- package/node_modules/@dx/core/dist/tools/cleanup.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/tools/cleanup.js +171 -0
- package/node_modules/@dx/core/dist/tools/cleanup.js.map +1 -0
- package/node_modules/@dx/core/dist/tools/deps.d.ts +57 -0
- package/node_modules/@dx/core/dist/tools/deps.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/tools/deps.js +151 -0
- package/node_modules/@dx/core/dist/tools/deps.js.map +1 -0
- package/node_modules/@dx/core/dist/tools/devErrors.d.ts +74 -0
- package/node_modules/@dx/core/dist/tools/devErrors.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/tools/devErrors.js +261 -0
- package/node_modules/@dx/core/dist/tools/devErrors.js.map +1 -0
- package/node_modules/@dx/core/dist/tools/doctor.d.ts +12 -0
- package/node_modules/@dx/core/dist/tools/doctor.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/tools/doctor.js +176 -0
- package/node_modules/@dx/core/dist/tools/doctor.js.map +1 -0
- package/node_modules/@dx/core/dist/tools/github.d.ts +31 -0
- package/node_modules/@dx/core/dist/tools/github.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/tools/github.js +80 -0
- package/node_modules/@dx/core/dist/tools/github.js.map +1 -0
- package/node_modules/@dx/core/dist/tools/journal.d.ts +23 -0
- package/node_modules/@dx/core/dist/tools/journal.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/tools/journal.js +80 -0
- package/node_modules/@dx/core/dist/tools/journal.js.map +1 -0
- package/node_modules/@dx/core/dist/tools/launch.d.ts +24 -0
- package/node_modules/@dx/core/dist/tools/launch.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/tools/launch.js +137 -0
- package/node_modules/@dx/core/dist/tools/launch.js.map +1 -0
- package/node_modules/@dx/core/dist/tools/ports.d.ts +42 -0
- package/node_modules/@dx/core/dist/tools/ports.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/tools/ports.js +220 -0
- package/node_modules/@dx/core/dist/tools/ports.js.map +1 -0
- package/node_modules/@dx/core/dist/tools/projects.d.ts +58 -0
- package/node_modules/@dx/core/dist/tools/projects.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/tools/projects.js +208 -0
- package/node_modules/@dx/core/dist/tools/projects.js.map +1 -0
- package/node_modules/@dx/core/dist/tools/scaffold.d.ts +40 -0
- package/node_modules/@dx/core/dist/tools/scaffold.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/tools/scaffold.js +188 -0
- package/node_modules/@dx/core/dist/tools/scaffold.js.map +1 -0
- package/node_modules/@dx/core/dist/tools/stacks.d.ts +119 -0
- package/node_modules/@dx/core/dist/tools/stacks.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/tools/stacks.js +386 -0
- package/node_modules/@dx/core/dist/tools/stacks.js.map +1 -0
- package/node_modules/@dx/core/dist/tools/summary.d.ts +87 -0
- package/node_modules/@dx/core/dist/tools/summary.d.ts.map +1 -0
- package/node_modules/@dx/core/dist/tools/summary.js +331 -0
- package/node_modules/@dx/core/dist/tools/summary.js.map +1 -0
- package/node_modules/@dx/core/package.json +20 -0
- package/node_modules/@dx/mcp/dist/index.d.ts +3 -0
- package/node_modules/@dx/mcp/dist/index.d.ts.map +1 -0
- package/node_modules/@dx/mcp/dist/index.js +540 -0
- package/node_modules/@dx/mcp/dist/index.js.map +1 -0
- package/node_modules/@dx/mcp/package.json +8 -0
- package/node_modules/@dx/web/dist/api.d.ts +13 -0
- package/node_modules/@dx/web/dist/api.d.ts.map +1 -0
- package/node_modules/@dx/web/dist/api.js +351 -0
- package/node_modules/@dx/web/dist/api.js.map +1 -0
- package/node_modules/@dx/web/dist/background.d.ts +2 -0
- package/node_modules/@dx/web/dist/background.d.ts.map +1 -0
- package/node_modules/@dx/web/dist/background.js +24 -0
- package/node_modules/@dx/web/dist/background.js.map +1 -0
- package/node_modules/@dx/web/dist/check.d.ts +39 -0
- package/node_modules/@dx/web/dist/check.d.ts.map +1 -0
- package/node_modules/@dx/web/dist/check.js +97 -0
- package/node_modules/@dx/web/dist/check.js.map +1 -0
- package/node_modules/@dx/web/dist/dev.d.ts +109 -0
- package/node_modules/@dx/web/dist/dev.d.ts.map +1 -0
- package/node_modules/@dx/web/dist/dev.js +645 -0
- package/node_modules/@dx/web/dist/dev.js.map +1 -0
- package/node_modules/@dx/web/dist/link.d.ts +45 -0
- package/node_modules/@dx/web/dist/link.d.ts.map +1 -0
- package/node_modules/@dx/web/dist/link.js +150 -0
- package/node_modules/@dx/web/dist/link.js.map +1 -0
- package/node_modules/@dx/web/dist/proxy.d.ts +21 -0
- package/node_modules/@dx/web/dist/proxy.d.ts.map +1 -0
- package/node_modules/@dx/web/dist/proxy.js +140 -0
- package/node_modules/@dx/web/dist/proxy.js.map +1 -0
- package/node_modules/@dx/web/dist/server.d.ts +33 -0
- package/node_modules/@dx/web/dist/server.d.ts.map +1 -0
- package/node_modules/@dx/web/dist/server.js +184 -0
- package/node_modules/@dx/web/dist/server.js.map +1 -0
- package/node_modules/@dx/web/package.json +26 -0
- package/node_modules/@dx/web/public/app.js +1553 -0
- package/node_modules/@dx/web/public/icon.svg +1 -0
- package/node_modules/@dx/web/public/index.html +47 -0
- package/node_modules/@dx/web/public/styles.css +1124 -0
- package/package.json +52 -4
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { parseArgs } from "node:util";
|
|
3
|
+
import { buildSummary, formatSummary, loadConfig, openInEditor, recordRun, saveSummary } from "@dx/core";
|
|
4
|
+
import { c, ok, tildify, UsageError, warn } from "../ui.js";
|
|
5
|
+
export const summaryCommand = {
|
|
6
|
+
name: "summary",
|
|
7
|
+
aliases: ["week"],
|
|
8
|
+
summary: "Your commits across all projects plus your journal, as a ready-to-send update",
|
|
9
|
+
usage: [
|
|
10
|
+
"dx summary the last 7 days, printed as markdown",
|
|
11
|
+
"dx summary --days 1 just today (handy for a standup)",
|
|
12
|
+
"dx summary --copy also copy it to the clipboard",
|
|
13
|
+
"dx summary --save also save it to ~/.dx/summaries/<date>.md",
|
|
14
|
+
"dx summary --save --open save it and open the file in your editor",
|
|
15
|
+
"dx summary --all-authors count everyone's commits, not only yours",
|
|
16
|
+
"dx summary --no-github skip pull requests from GitHub (works offline)",
|
|
17
|
+
"dx summary --json the raw data",
|
|
18
|
+
].join("\n"),
|
|
19
|
+
async run(argv) {
|
|
20
|
+
const { values } = parseArgs({
|
|
21
|
+
args: argv,
|
|
22
|
+
allowNegative: true,
|
|
23
|
+
options: {
|
|
24
|
+
days: { type: "string", short: "d" },
|
|
25
|
+
copy: { type: "boolean", short: "c" },
|
|
26
|
+
save: { type: "boolean", short: "s" },
|
|
27
|
+
open: { type: "boolean", short: "o" },
|
|
28
|
+
"all-authors": { type: "boolean", short: "a" },
|
|
29
|
+
json: { type: "boolean" },
|
|
30
|
+
github: { type: "boolean", default: true },
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
const days = values.days === undefined ? 7 : Number(values.days);
|
|
34
|
+
if (!Number.isInteger(days) || days < 1 || days > 366)
|
|
35
|
+
throw new UsageError("--days must be a whole number from 1 to 366.");
|
|
36
|
+
const config = loadConfig();
|
|
37
|
+
const summary = await buildSummary({ days, config, allAuthors: values["all-authors"], github: values.github });
|
|
38
|
+
if (values.json) {
|
|
39
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const markdown = formatSummary(summary);
|
|
43
|
+
console.log(markdown);
|
|
44
|
+
for (const s of summary.skipped)
|
|
45
|
+
warn(`Skipped ${s.project}: ${s.reason}`);
|
|
46
|
+
if (summary.github && "error" in summary.github)
|
|
47
|
+
warn(`No pull requests: ${summary.github.error}`);
|
|
48
|
+
if (!summary.projects.length && !summary.journal.length) {
|
|
49
|
+
console.log(c.dim('Log what you do with: dx log "what you did"'));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
console.log(c.dim(`Commits by ${summary.author}. Everyone's: dx summary --all-authors`));
|
|
53
|
+
}
|
|
54
|
+
if (values.copy) {
|
|
55
|
+
try {
|
|
56
|
+
await copyToClipboard(markdown);
|
|
57
|
+
ok("Copied to the clipboard");
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
warn(`Couldn't copy to the clipboard: ${err.message}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (values.save || values.open) {
|
|
64
|
+
const file = saveSummary(markdown, summary);
|
|
65
|
+
ok(`Saved ${tildify(file)}`);
|
|
66
|
+
if (values.open)
|
|
67
|
+
await openInEditor(file, config.editor);
|
|
68
|
+
}
|
|
69
|
+
const commits = summary.projects.reduce((n, p) => n + p.commits.length, 0);
|
|
70
|
+
recordRun("summary", true, `${days}d: ${commits} commit(s), ${summary.journal.length} journal entr${summary.journal.length === 1 ? "y" : "ies"}`);
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
/** Copies text to the system clipboard, keeping accents and symbols intact. */
|
|
74
|
+
function copyToClipboard(text) {
|
|
75
|
+
// clip.exe garbles non-ASCII text sent as UTF-8; UTF-16 works. No byte order mark: clip.exe would paste it.
|
|
76
|
+
const [command, args, input] = process.platform === "win32"
|
|
77
|
+
? ["clip.exe", [], Buffer.from(text, "utf16le")]
|
|
78
|
+
: process.platform === "darwin"
|
|
79
|
+
? ["pbcopy", [], Buffer.from(text, "utf8")]
|
|
80
|
+
: ["sh", ["-c", "wl-copy 2>/dev/null || xclip -selection clipboard"], Buffer.from(text, "utf8")];
|
|
81
|
+
return new Promise((resolve, reject) => {
|
|
82
|
+
const child = spawn(command, args, { stdio: ["pipe", "ignore", "ignore"], windowsHide: true });
|
|
83
|
+
child.once("error", reject);
|
|
84
|
+
child.once("close", (code) => (code === 0 ? resolve() : reject(new Error(`${command} exited with ${code}`))));
|
|
85
|
+
child.stdin.end(input);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary.js","sourceRoot":"","sources":["../../src/commands/summary.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../src/commands/system.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,eAAO,MAAM,aAAa,EAAE,OAmD3B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,OAc3B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,OA2BzB,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { parseArgs } from "node:util";
|
|
4
|
+
import { configPath, loadConfig, openInEditor, readRuns, runDoctor, saveConfig } from "@dx/core";
|
|
5
|
+
import { c, ok, table, tildify, UsageError } from "../ui.js";
|
|
6
|
+
export const configCommand = {
|
|
7
|
+
name: "config",
|
|
8
|
+
summary: "Show or change dx settings",
|
|
9
|
+
usage: [
|
|
10
|
+
"dx config show the settings file",
|
|
11
|
+
"dx config edit open it in your editor",
|
|
12
|
+
"dx config add-root <path> scan another folder for projects",
|
|
13
|
+
"dx config editor <command> set the editor command, e.g. cursor",
|
|
14
|
+
"dx config github <username> your GitHub username, for pull requests in dx summary",
|
|
15
|
+
].join("\n"),
|
|
16
|
+
async run(argv) {
|
|
17
|
+
const [action, ...rest] = argv;
|
|
18
|
+
const config = loadConfig();
|
|
19
|
+
if (!action) {
|
|
20
|
+
console.log(c.dim(configPath()));
|
|
21
|
+
console.log(JSON.stringify(config, null, 2));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (action === "edit") {
|
|
25
|
+
await openInEditor(configPath(), config.editor);
|
|
26
|
+
ok(`Opened ${tildify(configPath())}`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (action === "add-root") {
|
|
30
|
+
const target = rest.join(" ").trim();
|
|
31
|
+
if (!target)
|
|
32
|
+
throw new UsageError("Which folder? e.g. dx config add-root C:\\code");
|
|
33
|
+
const abs = path.resolve(target);
|
|
34
|
+
if (!fs.existsSync(abs))
|
|
35
|
+
throw new UsageError(`Folder not found: ${abs}`);
|
|
36
|
+
if (!config.projectsRoots.some((r) => r.toLowerCase() === abs.toLowerCase()))
|
|
37
|
+
config.projectsRoots.push(abs);
|
|
38
|
+
saveConfig(config);
|
|
39
|
+
ok(`Projects roots: ${config.projectsRoots.map(tildify).join(", ")}`);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (action === "editor") {
|
|
43
|
+
const editor = rest.join(" ").trim();
|
|
44
|
+
if (!editor)
|
|
45
|
+
throw new UsageError("Which command? e.g. dx config editor cursor");
|
|
46
|
+
config.editor = editor;
|
|
47
|
+
saveConfig(config);
|
|
48
|
+
ok(`Editor set to ${editor}`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (action === "github") {
|
|
52
|
+
const user = rest.join(" ").trim().replace(/^@/, "");
|
|
53
|
+
if (!/^[A-Za-z0-9-]{1,39}$/.test(user))
|
|
54
|
+
throw new UsageError("Which GitHub username? e.g. dx config github octocat");
|
|
55
|
+
config.githubUser = user;
|
|
56
|
+
saveConfig(config);
|
|
57
|
+
ok(`GitHub username set to ${user}`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
throw new UsageError(`Unknown config action: ${action}`);
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
export const doctorCommand = {
|
|
64
|
+
name: "doctor",
|
|
65
|
+
summary: "Check that dx works on this machine",
|
|
66
|
+
usage: "dx doctor",
|
|
67
|
+
async run() {
|
|
68
|
+
const checks = await runDoctor();
|
|
69
|
+
const icon = { ok: c.green("✓"), warn: c.yellow("!"), fail: c.red("✗") };
|
|
70
|
+
for (const check of checks) {
|
|
71
|
+
console.log(`${icon[check.status]} ${c.bold(check.name.padEnd(17))} ${check.detail}`);
|
|
72
|
+
if (check.fix)
|
|
73
|
+
console.log(` ${" ".repeat(17)} ${c.dim("fix:")} ${c.cyan(check.fix)}`);
|
|
74
|
+
}
|
|
75
|
+
if (checks.some((x) => x.fix))
|
|
76
|
+
console.log(c.dim("\nYour AI tool can apply these fixes: ask it to check dx's setup."));
|
|
77
|
+
return checks.some((x) => x.status === "fail") ? 1 : 0;
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
export const runsCommand = {
|
|
81
|
+
name: "runs",
|
|
82
|
+
summary: "Recent tool runs, so failures are never silent",
|
|
83
|
+
usage: "dx runs [--limit 30] [--failed]",
|
|
84
|
+
async run(argv) {
|
|
85
|
+
const { values } = parseArgs({
|
|
86
|
+
args: argv,
|
|
87
|
+
options: { limit: { type: "string", short: "n" }, failed: { type: "boolean", short: "f" } },
|
|
88
|
+
});
|
|
89
|
+
let runs = readRuns(Math.max(1, Number(values.limit) || 30));
|
|
90
|
+
if (values.failed)
|
|
91
|
+
runs = runs.filter((r) => !r.ok);
|
|
92
|
+
if (runs.length === 0) {
|
|
93
|
+
console.log(values.failed ? "No failed runs." : "No runs recorded yet.");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
console.log(table(["WHEN", "TOOL", "FROM", "RESULT"], runs.map((r) => [
|
|
97
|
+
new Date(r.at).toLocaleString(),
|
|
98
|
+
r.tool,
|
|
99
|
+
c.dim(r.source ?? ""),
|
|
100
|
+
r.ok ? c.green("ok") + (r.detail ? c.dim(` ${r.detail}`) : "") : c.red("failed") + ` ${r.detail ?? ""}`,
|
|
101
|
+
])));
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
//# sourceMappingURL=system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.js","sourceRoot":"","sources":["../../src/commands/system.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/commands/ui.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,eAAO,MAAM,SAAS,EAAE,OAgFvB,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
import { autoConnectAiTools, openUrl, recordRun } from "@dx/core";
|
|
3
|
+
import { startDashboard } from "@dx/web";
|
|
4
|
+
import { ensureDashboard, findDashboard } from "@dx/web/link";
|
|
5
|
+
import { c, info, ok, UsageError, warn } from "../ui.js";
|
|
6
|
+
export const uiCommand = {
|
|
7
|
+
name: "ui",
|
|
8
|
+
aliases: ["dashboard"],
|
|
9
|
+
summary: "Open the dx dashboard in your browser: every dx tool, with buttons",
|
|
10
|
+
usage: [
|
|
11
|
+
"dx ui open the dashboard (starting it here if it isn't running)",
|
|
12
|
+
"dx ui --background start it without a terminal; it stops itself when idle for 30 minutes",
|
|
13
|
+
"dx ui --stop stop the running dashboard and the dev servers it runs",
|
|
14
|
+
"dx ui --port 5000 use another port (default 4646)",
|
|
15
|
+
"dx ui --no-open don't open the browser",
|
|
16
|
+
"",
|
|
17
|
+
"It runs on this computer only (127.0.0.1). AI tools connected to dx start it in the background",
|
|
18
|
+
"when they need a dev server, and `dx ui` then just opens that one.",
|
|
19
|
+
].join("\n"),
|
|
20
|
+
async run(argv) {
|
|
21
|
+
const { values } = parseArgs({
|
|
22
|
+
args: argv,
|
|
23
|
+
allowNegative: true,
|
|
24
|
+
options: {
|
|
25
|
+
port: { type: "string", short: "p" },
|
|
26
|
+
open: { type: "boolean", default: true },
|
|
27
|
+
background: { type: "boolean" },
|
|
28
|
+
stop: { type: "boolean" },
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
const port = values.port === undefined ? undefined : Number(values.port);
|
|
32
|
+
if (port !== undefined && (!Number.isInteger(port) || port < 0 || port > 65535))
|
|
33
|
+
throw new UsageError("--port must be a port number.");
|
|
34
|
+
const running = await findDashboard();
|
|
35
|
+
if (values.stop) {
|
|
36
|
+
if (!running) {
|
|
37
|
+
info("The dashboard isn't running.");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
await running.post("/api/shutdown");
|
|
41
|
+
ok("Dashboard stopped");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (running) {
|
|
45
|
+
ok(`The dx dashboard is already running at ${c.cyan(running.url)}${running.info.background ? c.dim(" (in the background)") : ""}`);
|
|
46
|
+
if (values.open)
|
|
47
|
+
await openBrowser(running.url);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (values.background) {
|
|
51
|
+
const client = await ensureDashboard();
|
|
52
|
+
ok(`dx dashboard running in the background at ${c.cyan(client.url)}`);
|
|
53
|
+
info(c.dim("It stops itself after 30 minutes with no dev servers and nobody using it. dx ui --stop stops it now."));
|
|
54
|
+
if (values.open)
|
|
55
|
+
await openBrowser(client.url);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const dashboard = await startDashboard({ port });
|
|
59
|
+
ok(`dx dashboard running at ${c.cyan(dashboard.url)}`);
|
|
60
|
+
info(c.dim("Ctrl+C to stop. Dev servers started from the dashboard stop with it."));
|
|
61
|
+
recordRun("ui", true, dashboard.url);
|
|
62
|
+
void autoConnectAiTools()
|
|
63
|
+
.then((results) => {
|
|
64
|
+
const done = results.filter((r) => r.ok);
|
|
65
|
+
if (done.length)
|
|
66
|
+
info(c.dim(`Connected dx to ${done.map((r) => r.name).join(", ")}.`));
|
|
67
|
+
})
|
|
68
|
+
.catch(() => undefined);
|
|
69
|
+
if (values.open)
|
|
70
|
+
await openBrowser(dashboard.url);
|
|
71
|
+
await new Promise((resolve) => {
|
|
72
|
+
let stopping = false;
|
|
73
|
+
const stop = () => {
|
|
74
|
+
if (stopping)
|
|
75
|
+
return;
|
|
76
|
+
stopping = true;
|
|
77
|
+
console.log("");
|
|
78
|
+
info("Stopping the dashboard…");
|
|
79
|
+
void dashboard.close().then(resolve, resolve);
|
|
80
|
+
};
|
|
81
|
+
process.on("SIGINT", stop);
|
|
82
|
+
process.on("SIGTERM", stop);
|
|
83
|
+
void dashboard.closed.then(resolve);
|
|
84
|
+
});
|
|
85
|
+
ok("Dashboard stopped");
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
async function openBrowser(url) {
|
|
89
|
+
try {
|
|
90
|
+
await openUrl(url);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
warn(`Couldn't open the browser: ${err.message}. Open ${url} yourself.`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/commands/ui.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { recordRun } from "@dx/core";
|
|
4
|
+
import { errorsCommand, firstRunSetup, logsCommand, setupCommand } from "./commands/ai.js";
|
|
5
|
+
import { cleanCommand } from "./commands/clean.js";
|
|
6
|
+
import { depsCommand } from "./commands/deps.js";
|
|
7
|
+
import { goCommand } from "./commands/go.js";
|
|
8
|
+
import { logCommand } from "./commands/log.js";
|
|
9
|
+
import { newCommand } from "./commands/new.js";
|
|
10
|
+
import { killCommand, portCommand } from "./commands/port.js";
|
|
11
|
+
import { projectsCommand } from "./commands/projects.js";
|
|
12
|
+
import { downCommand, upCommand } from "./commands/stack.js";
|
|
13
|
+
import { summaryCommand } from "./commands/summary.js";
|
|
14
|
+
import { configCommand, doctorCommand, runsCommand } from "./commands/system.js";
|
|
15
|
+
import { uiCommand } from "./commands/ui.js";
|
|
16
|
+
import { c, UsageError } from "./ui.js";
|
|
17
|
+
// To add a tool: write packages/cli/src/commands/<tool>.ts and add it to this list.
|
|
18
|
+
const commands = [
|
|
19
|
+
uiCommand,
|
|
20
|
+
goCommand,
|
|
21
|
+
upCommand,
|
|
22
|
+
downCommand,
|
|
23
|
+
newCommand,
|
|
24
|
+
projectsCommand,
|
|
25
|
+
portCommand,
|
|
26
|
+
killCommand,
|
|
27
|
+
logCommand,
|
|
28
|
+
summaryCommand,
|
|
29
|
+
cleanCommand,
|
|
30
|
+
depsCommand,
|
|
31
|
+
logsCommand,
|
|
32
|
+
errorsCommand,
|
|
33
|
+
setupCommand,
|
|
34
|
+
configCommand,
|
|
35
|
+
runsCommand,
|
|
36
|
+
doctorCommand,
|
|
37
|
+
];
|
|
38
|
+
function version() {
|
|
39
|
+
try {
|
|
40
|
+
const pkg = JSON.parse(fs.readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
41
|
+
return pkg.version;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return "unknown";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function help() {
|
|
48
|
+
console.log(`${c.bold("dx")} ${c.dim(version())} your developer toolkit\n`);
|
|
49
|
+
const width = Math.max(...commands.map((cmd) => cmd.name.length));
|
|
50
|
+
for (const cmd of commands)
|
|
51
|
+
console.log(` ${c.cyan(cmd.name.padEnd(width))} ${cmd.summary}`);
|
|
52
|
+
console.log(`\n${c.dim("Details for one command: dx help <command>")}`);
|
|
53
|
+
}
|
|
54
|
+
function find(name) {
|
|
55
|
+
return commands.find((cmd) => cmd.name === name || cmd.aliases?.includes(name));
|
|
56
|
+
}
|
|
57
|
+
async function main(argv) {
|
|
58
|
+
const [name, ...rest] = argv;
|
|
59
|
+
if (!name || name === "help" || name === "--help" || name === "-h") {
|
|
60
|
+
const target = rest[0] && find(rest[0]);
|
|
61
|
+
if (target) {
|
|
62
|
+
console.log(`${c.bold(target.summary)}\n\n${target.usage}`);
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
help();
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
if (name === "--version" || name === "-v") {
|
|
69
|
+
console.log(version());
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
const command = find(name);
|
|
73
|
+
if (!command) {
|
|
74
|
+
console.error(`${c.red("Unknown command:")} ${name}\n`);
|
|
75
|
+
help();
|
|
76
|
+
return 1;
|
|
77
|
+
}
|
|
78
|
+
if (rest.includes("--help") || rest.includes("-h")) {
|
|
79
|
+
console.log(`${c.bold(command.summary)}\n\n${command.usage}`);
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
if (command !== setupCommand)
|
|
84
|
+
await firstRunSetup();
|
|
85
|
+
return (await command.run(rest)) ?? 0;
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
const e = err;
|
|
89
|
+
if (err instanceof UsageError || e.code?.startsWith("ERR_PARSE_ARGS")) {
|
|
90
|
+
console.error(`${c.red("✗")} ${e.message}\n\n${c.dim("Usage:")}\n${command.usage}`);
|
|
91
|
+
return 2;
|
|
92
|
+
}
|
|
93
|
+
recordRun(command.name, false, e.message);
|
|
94
|
+
console.error(`${c.red("✗")} ${e.message}`);
|
|
95
|
+
if (process.env.DX_DEBUG)
|
|
96
|
+
console.error(e.stack);
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
main(process.argv.slice(2)).then((code) => {
|
|
101
|
+
process.exitCode = code;
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/ui.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare const c: {
|
|
2
|
+
bold: (s: string) => string;
|
|
3
|
+
dim: (s: string) => string;
|
|
4
|
+
red: (s: string) => string;
|
|
5
|
+
green: (s: string) => string;
|
|
6
|
+
yellow: (s: string) => string;
|
|
7
|
+
blue: (s: string) => string;
|
|
8
|
+
magenta: (s: string) => string;
|
|
9
|
+
cyan: (s: string) => string;
|
|
10
|
+
};
|
|
11
|
+
export declare class UsageError extends Error {
|
|
12
|
+
}
|
|
13
|
+
/** Left-aligned columns. The last column is cut to fit the terminal width. */
|
|
14
|
+
export declare function table(header: string[], rows: string[][]): string;
|
|
15
|
+
export declare function truncate(s: string, max: number): string;
|
|
16
|
+
/** "C:\Users\you\projects\todo-app" → "~\projects\todo-app" */
|
|
17
|
+
export declare function tildify(p: string): string;
|
|
18
|
+
export declare function relativeTime(ms: number, now?: number): string;
|
|
19
|
+
export declare function ask(question: string): Promise<string>;
|
|
20
|
+
/** Yes/no question. Without a terminal to ask in, the answer is no. */
|
|
21
|
+
export declare function confirm(question: string): Promise<boolean>;
|
|
22
|
+
/** Numbered pick list. Returns undefined if the user enters nothing or there is no terminal. */
|
|
23
|
+
export declare function pick<T>(items: T[], label: (item: T) => string, prompt?: string): Promise<T | undefined>;
|
|
24
|
+
export declare function ok(msg: string): void;
|
|
25
|
+
export declare function warn(msg: string): void;
|
|
26
|
+
export declare function info(msg: string): void;
|
|
27
|
+
//# sourceMappingURL=ui.d.ts.map
|
package/dist/ui.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,CAAC;cAFoC,MAAM;aAAN,MAAM;aAAN,MAAM;eAAN,MAAM;gBAAN,MAAM;cAAN,MAAM;iBAAN,MAAM;cAAN,MAAM;CAWvD,CAAC;AAEF,qBAAa,UAAW,SAAQ,KAAK;CAAG;AAKxC,8EAA8E;AAC9E,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,CAiBhE;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIvD;AAED,+DAA+D;AAC/D,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAGzC;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,MAAM,CAajE;AAED,wBAAsB,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO3D;AAED,uEAAuE;AACvE,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAIhE;AAED,gGAAgG;AAChG,wBAAsB,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,EAAE,MAAM,SAAa,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAOjH;AAED,wBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEpC;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtC;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtC"}
|
package/dist/ui.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import { createInterface } from "node:readline/promises";
|
|
3
|
+
const color = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;
|
|
4
|
+
const wrap = (open, close) => (s) => (color ? `\x1b[${open}m${s}\x1b[${close}m` : s);
|
|
5
|
+
export const c = {
|
|
6
|
+
bold: wrap(1, 22),
|
|
7
|
+
dim: wrap(2, 22),
|
|
8
|
+
red: wrap(31, 39),
|
|
9
|
+
green: wrap(32, 39),
|
|
10
|
+
yellow: wrap(33, 39),
|
|
11
|
+
blue: wrap(34, 39),
|
|
12
|
+
magenta: wrap(35, 39),
|
|
13
|
+
cyan: wrap(36, 39),
|
|
14
|
+
};
|
|
15
|
+
export class UsageError extends Error {
|
|
16
|
+
}
|
|
17
|
+
const ANSI = /\x1b\[[0-9;]*m/g;
|
|
18
|
+
const visible = (s) => s.replace(ANSI, "").length;
|
|
19
|
+
/** Left-aligned columns. The last column is cut to fit the terminal width. */
|
|
20
|
+
export function table(header, rows) {
|
|
21
|
+
const all = [header.map((h) => c.dim(h)), ...rows];
|
|
22
|
+
const widths = header.map((_, i) => Math.max(...all.map((r) => visible(r[i] ?? ""))));
|
|
23
|
+
const termWidth = process.stdout.columns ?? 120;
|
|
24
|
+
const fixed = widths.slice(0, -1).reduce((a, w) => a + w + 2, 0);
|
|
25
|
+
const lastMax = Math.max(20, termWidth - fixed - 1);
|
|
26
|
+
return all
|
|
27
|
+
.map((r) => r
|
|
28
|
+
.map((cell, i) => {
|
|
29
|
+
const isLast = i === r.length - 1;
|
|
30
|
+
if (isLast)
|
|
31
|
+
return truncate(cell ?? "", lastMax);
|
|
32
|
+
return (cell ?? "") + " ".repeat(widths[i] - visible(cell ?? "") + 2);
|
|
33
|
+
})
|
|
34
|
+
.join(""))
|
|
35
|
+
.join("\n");
|
|
36
|
+
}
|
|
37
|
+
export function truncate(s, max) {
|
|
38
|
+
if (visible(s) <= max)
|
|
39
|
+
return s;
|
|
40
|
+
const plain = s.replace(ANSI, "");
|
|
41
|
+
return plain.slice(0, Math.max(0, max - 1)) + "…";
|
|
42
|
+
}
|
|
43
|
+
/** "C:\Users\you\projects\todo-app" → "~\projects\todo-app" */
|
|
44
|
+
export function tildify(p) {
|
|
45
|
+
const home = os.homedir();
|
|
46
|
+
return p.toLowerCase().startsWith(home.toLowerCase()) ? "~" + p.slice(home.length) : p;
|
|
47
|
+
}
|
|
48
|
+
export function relativeTime(ms, now = Date.now()) {
|
|
49
|
+
if (!ms)
|
|
50
|
+
return "—";
|
|
51
|
+
const s = Math.round((now - ms) / 1000);
|
|
52
|
+
if (s < 60)
|
|
53
|
+
return "just now";
|
|
54
|
+
const m = Math.round(s / 60);
|
|
55
|
+
if (m < 60)
|
|
56
|
+
return `${m}m ago`;
|
|
57
|
+
const h = Math.round(m / 60);
|
|
58
|
+
if (h < 24)
|
|
59
|
+
return `${h}h ago`;
|
|
60
|
+
const d = Math.round(h / 24);
|
|
61
|
+
if (d < 30)
|
|
62
|
+
return `${d}d ago`;
|
|
63
|
+
const mo = Math.round(d / 30);
|
|
64
|
+
if (mo < 12)
|
|
65
|
+
return `${mo}mo ago`;
|
|
66
|
+
return `${Math.round(mo / 12)}y ago`;
|
|
67
|
+
}
|
|
68
|
+
export async function ask(question) {
|
|
69
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
70
|
+
try {
|
|
71
|
+
return (await rl.question(question)).trim();
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
rl.close();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** Yes/no question. Without a terminal to ask in, the answer is no. */
|
|
78
|
+
export async function confirm(question) {
|
|
79
|
+
if (!process.stdin.isTTY)
|
|
80
|
+
return false;
|
|
81
|
+
const answer = await ask(`${question} ${c.dim("[y/N]")} `);
|
|
82
|
+
return /^y(es)?$/i.test(answer);
|
|
83
|
+
}
|
|
84
|
+
/** Numbered pick list. Returns undefined if the user enters nothing or there is no terminal. */
|
|
85
|
+
export async function pick(items, label, prompt = "Pick one") {
|
|
86
|
+
if (items.length === 0)
|
|
87
|
+
return undefined;
|
|
88
|
+
items.forEach((item, i) => console.log(` ${c.cyan(String(i + 1).padStart(2))} ${label(item)}`));
|
|
89
|
+
if (!process.stdin.isTTY)
|
|
90
|
+
return undefined;
|
|
91
|
+
const answer = await ask(`${prompt} ${c.dim(`(1-${items.length}, Enter to cancel)`)}: `);
|
|
92
|
+
const n = Number(answer);
|
|
93
|
+
return Number.isInteger(n) && n >= 1 && n <= items.length ? items[n - 1] : undefined;
|
|
94
|
+
}
|
|
95
|
+
export function ok(msg) {
|
|
96
|
+
console.log(`${c.green("✓")} ${msg}`);
|
|
97
|
+
}
|
|
98
|
+
export function warn(msg) {
|
|
99
|
+
console.log(`${c.yellow("!")} ${msg}`);
|
|
100
|
+
}
|
|
101
|
+
export function info(msg) {
|
|
102
|
+
console.log(`${c.dim("·")} ${msg}`);
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=ui.js.map
|
package/dist/ui.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}
|