@m6d/cortex-cli 1.0.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.
@@ -0,0 +1,102 @@
1
+ /**
2
+ * The output grammar, shared by every command that runs against a project.
3
+ * Layout is fixed by `docs/prototypes/cli-output.md`; this file is the only
4
+ * place that knows the box characters.
5
+ */
6
+
7
+ import { inspect } from "node:util";
8
+
9
+ import pc from "picocolors";
10
+
11
+ const BAR = pc.gray("│");
12
+
13
+ function write(stream: NodeJS.WriteStream, lines: string[]) {
14
+ stream.write(`${lines.join("\n")}\n`);
15
+ }
16
+
17
+ /** Every block inside an error sits three spaces in, commands two further. */
18
+ function indent(block: string) {
19
+ return block
20
+ .split("\n")
21
+ .map((line) => ` ${line}`)
22
+ .join("\n");
23
+ }
24
+
25
+ function describe(error: unknown) {
26
+ if (!(error instanceof Error)) return String(error);
27
+ return `${error.name}: ${error.message}`.split("\n")[0] ?? error.name;
28
+ }
29
+
30
+ // An error hugs whatever the run last printed, so it needs to know whether
31
+ // anything opened the box above it.
32
+ let open = false;
33
+
34
+ /** `┌ cortex graph seed` — opens a run. */
35
+ /** `1 node` / `3 nodes` — every count the box prints goes through this. */
36
+ export function plural(count: number, noun: string) {
37
+ return `${count} ${noun}${count === 1 ? "" : "s"}`;
38
+ }
39
+
40
+ export function header(title: string) {
41
+ open = true;
42
+ write(process.stdout, ["", `${pc.gray("┌")} ${title}`, BAR]);
43
+ }
44
+
45
+ /**
46
+ * A resolved input. These double as progress: whatever was printed last says how
47
+ * far the run got, which is most of the diagnosis when the next step fails.
48
+ */
49
+ export function input(label: string, value: string) {
50
+ write(process.stdout, [`${pc.green("◇")} ${label.padEnd(9)} ${value}`]);
51
+ }
52
+
53
+ export function blank() {
54
+ write(process.stdout, [BAR]);
55
+ }
56
+
57
+ /**
58
+ * `│ updated leaves/listLeaves.endpoint.ts` — a row in the body. An empty
59
+ * label indents to the same gutter, for the second line a finding gets. `width`
60
+ * is the label column: findings fit in 10, domain names need 14.
61
+ */
62
+ export function row(label: string, text: string, width = 10) {
63
+ write(process.stdout, [`${BAR} ${label.padEnd(width - 2)} ${text}`]);
64
+ }
65
+
66
+ /** `└ 87 nodes · 124 edges (6.2s)` — closes a run. */
67
+ export function footer(text: string) {
68
+ write(process.stdout, [`${pc.gray("└")} ${text}`, ""]);
69
+ }
70
+
71
+ /** A paragraph below the box, for the one thing the reader has to act on. */
72
+ export function note(text: string) {
73
+ write(process.stdout, [text, ""]);
74
+ }
75
+
76
+ /**
77
+ * One error grammar: what happened → why → a runnable command. One line of the
78
+ * underlying error is kept — it is what gets pasted into a search — and the rest
79
+ * waits behind `--verbose`.
80
+ */
81
+ export function fail(options: {
82
+ what: string;
83
+ blocks?: string[];
84
+ error?: unknown;
85
+ verbose?: boolean;
86
+ }): never {
87
+ const { what, blocks = [], error, verbose = false } = options;
88
+ const parts = [`${pc.red("■")} ${what}`];
89
+
90
+ if (error !== undefined) parts.push(indent(describe(error)));
91
+ parts.push(...blocks.map(indent));
92
+ if (error !== undefined) {
93
+ // `inspect` rather than `error.stack`: a Bun `fetch` failure carries no
94
+ // stack at all, and its `code` is the useful part.
95
+ parts.push(
96
+ indent(verbose ? inspect(error) : "Run with --verbose for the full stack trace."),
97
+ );
98
+ }
99
+
100
+ write(process.stderr, open ? [parts.join("\n\n"), ""] : ["", parts.join("\n\n"), ""]);
101
+ process.exit(1);
102
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "compilerOptions": {
3
+ // Environment setup & latest features
4
+ "lib": ["ESNext"],
5
+ // Named explicitly: auto-inclusion of @types/* is an editor-dependent
6
+ // heuristic, and `Bun`/`Response` come from here. See @cortex/contracts'
7
+ // tsconfig for the same fix.
8
+ "types": ["bun"],
9
+ "target": "ESNext",
10
+ "module": "Preserve",
11
+ "moduleDetection": "force",
12
+ "baseUrl": ".",
13
+
14
+ // Bundler mode
15
+ "moduleResolution": "bundler",
16
+ "verbatimModuleSyntax": true,
17
+ "resolveJsonModule": true,
18
+ "noEmit": true,
19
+ "paths": {
20
+ // The graph contract is @cortex/contracts, a private workspace package
21
+ // that never publishes, so the CLI carries its own copy: `prepack`
22
+ // vendors it into src/contracts, where the first candidate finds it in
23
+ // the published tarball. Inside the repo that copy doesn't exist and
24
+ // resolution falls through to the workspace source.
25
+ "@cortex/contracts/*": ["./src/contracts/*", "../../internal/contracts/*"],
26
+ // Internal-only, and the reason this file ships in package.json `files`:
27
+ // the CLI runs as raw TypeScript from inside node_modules, so Bun has to
28
+ // read this config to resolve `@/`.
29
+ "@/*": ["./src/*"]
30
+ },
31
+
32
+ // Best practices
33
+ "strict": true,
34
+ "skipLibCheck": true,
35
+ "noFallthroughCasesInSwitch": true,
36
+ "noUncheckedIndexedAccess": true,
37
+ "noImplicitOverride": true,
38
+
39
+ // Some stricter flags (disabled by default)
40
+ "noUnusedLocals": false,
41
+ "noUnusedParameters": false,
42
+ "noPropertyAccessFromIndexSignature": false
43
+ },
44
+ "include": ["src/**/*.ts"]
45
+ }