@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.
- package/README.md +135 -0
- package/bin/cortex.js +52 -0
- package/package.json +37 -0
- package/src/cli.ts +63 -0
- package/src/commands/graph.ts +253 -0
- package/src/commands/new.ts +333 -0
- package/src/commands/swagger.ts +285 -0
- package/src/config/load.ts +76 -0
- package/src/config/validate.ts +46 -0
- package/src/contracts/README.md +23 -0
- package/src/contracts/graph/embed.ts +50 -0
- package/src/contracts/graph/helpers.ts +63 -0
- package/src/contracts/graph/neo4j.ts +97 -0
- package/src/contracts/graph/schema.ts +65 -0
- package/src/contracts/graph/types.ts +131 -0
- package/src/contracts/graph.ts +36 -0
- package/src/contracts/runtime.ts +208 -0
- package/src/contracts/wire.ts +143 -0
- package/src/graph/expand-domains.ts +288 -0
- package/src/graph/generate-cypher.ts +201 -0
- package/src/graph/seed.ts +227 -0
- package/src/graph/validate.ts +78 -0
- package/src/scaffold/features.ts +189 -0
- package/src/scaffold/files.ts +568 -0
- package/src/scaffold/ports.ts +86 -0
- package/src/swagger/extract-endpoints.ts +258 -0
- package/src/swagger/generated-block.ts +74 -0
- package/src/swagger/openapi-schema.ts +149 -0
- package/src/swagger/parse-response.ts +88 -0
- package/src/swagger/types.ts +25 -0
- package/src/ui/prompts.ts +102 -0
- package/src/ui/report.ts +102 -0
- package/tsconfig.json +45 -0
package/src/ui/report.ts
ADDED
|
@@ -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
|
+
}
|