@yoinkingfish/codecarto 0.1.1

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.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/dist/browser/index.d.ts +6 -0
  3. package/dist/browser/index.d.ts.map +1 -0
  4. package/dist/browser/index.js +32 -0
  5. package/dist/browser/index.js.map +1 -0
  6. package/dist/commands/default.d.ts +9 -0
  7. package/dist/commands/default.d.ts.map +1 -0
  8. package/dist/commands/default.js +103 -0
  9. package/dist/commands/default.js.map +1 -0
  10. package/dist/commands/export.d.ts +9 -0
  11. package/dist/commands/export.d.ts.map +1 -0
  12. package/dist/commands/export.js +62 -0
  13. package/dist/commands/export.js.map +1 -0
  14. package/dist/commands/scan.d.ts +8 -0
  15. package/dist/commands/scan.d.ts.map +1 -0
  16. package/dist/commands/scan.js +81 -0
  17. package/dist/commands/scan.js.map +1 -0
  18. package/dist/commands/serve.d.ts +8 -0
  19. package/dist/commands/serve.d.ts.map +1 -0
  20. package/dist/commands/serve.js +47 -0
  21. package/dist/commands/serve.js.map +1 -0
  22. package/dist/index.d.ts +7 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +105 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/server/index.d.ts +18 -0
  27. package/dist/server/index.d.ts.map +1 -0
  28. package/dist/server/index.js +115 -0
  29. package/dist/server/index.js.map +1 -0
  30. package/dist/utils/banner.d.ts +2 -0
  31. package/dist/utils/banner.d.ts.map +1 -0
  32. package/dist/utils/banner.js +17 -0
  33. package/dist/utils/banner.js.map +1 -0
  34. package/dist/utils/logger.d.ts +12 -0
  35. package/dist/utils/logger.d.ts.map +1 -0
  36. package/dist/utils/logger.js +34 -0
  37. package/dist/utils/logger.js.map +1 -0
  38. package/dist/utils/paths.d.ts +6 -0
  39. package/dist/utils/paths.d.ts.map +1 -0
  40. package/dist/utils/paths.js +27 -0
  41. package/dist/utils/paths.js.map +1 -0
  42. package/dist/utils/pipeline.d.ts +28 -0
  43. package/dist/utils/pipeline.d.ts.map +1 -0
  44. package/dist/utils/pipeline.js +234 -0
  45. package/dist/utils/pipeline.js.map +1 -0
  46. package/package.json +62 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CodeCarto Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Browser launcher — uses `open` but waits until server is ready.
3
+ */
4
+ export declare function openBrowser(url: string): Promise<void>;
5
+ export declare function waitForServer(url: string, timeoutMs?: number): Promise<void>;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS5D;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAahF"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Browser launcher — uses `open` but waits until server is ready.
3
+ */
4
+ import { logger } from "../utils/logger.js";
5
+ export async function openBrowser(url) {
6
+ try {
7
+ const { default: open } = await import("open");
8
+ await open(url, { wait: false });
9
+ logger.verbose(`Opened browser: ${url}`);
10
+ }
11
+ catch (err) {
12
+ logger.warn(`Could not open browser automatically. Please open ${url} manually.`);
13
+ logger.verbose(String(err));
14
+ }
15
+ }
16
+ export async function waitForServer(url, timeoutMs = 5000) {
17
+ const start = Date.now();
18
+ const healthUrl = new URL("/api/health", url).toString();
19
+ while (Date.now() - start < timeoutMs) {
20
+ try {
21
+ const res = await fetch(healthUrl);
22
+ if (res.ok)
23
+ return;
24
+ }
25
+ catch {
26
+ // retry
27
+ }
28
+ await new Promise((r) => setTimeout(r, 150));
29
+ }
30
+ logger.verbose(`Health check timed out for ${healthUrl}`);
31
+ }
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC3C,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACjC,MAAM,CAAC,OAAO,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,qDAAqD,GAAG,YAAY,CAAC,CAAC;QAClF,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAW,EAAE,SAAS,GAAG,IAAI;IAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;IACzD,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,SAAS,EAAE,CAAC;QACtC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;YACnC,IAAI,GAAG,CAAC,EAAE;gBAAE,OAAO;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ;QACV,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,CAAC,OAAO,CAAC,8BAA8B,SAAS,EAAE,CAAC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface DefaultOptions {
2
+ port: string;
3
+ open: boolean;
4
+ verbose?: boolean;
5
+ ignore?: string[];
6
+ output?: string;
7
+ }
8
+ export declare function defaultCommand(opts: DefaultOptions): Promise<void>;
9
+ //# sourceMappingURL=default.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default.d.ts","sourceRoot":"","sources":["../../src/commands/default.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA+GxE"}
@@ -0,0 +1,103 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import chalk from "chalk";
4
+ import ora from "ora";
5
+ import { runPipeline } from "../utils/pipeline.js";
6
+ import { logger, setLogLevel } from "../utils/logger.js";
7
+ import { resolveRoot } from "../utils/paths.js";
8
+ import { printBanner } from "../utils/banner.js";
9
+ import { startServer } from "../server/index.js";
10
+ import { openBrowser, waitForServer } from "../browser/index.js";
11
+ export async function defaultCommand(opts) {
12
+ setLogLevel(opts.verbose ? "verbose" : "info");
13
+ printBanner();
14
+ const root = resolveRoot("."); // Use current working directory
15
+ const preferredPort = Number(opts.port);
16
+ if (!Number.isFinite(preferredPort) || preferredPort < 1 || preferredPort > 65535) {
17
+ console.error(chalk.red(`\n✗ Invalid port: ${opts.port}\n`));
18
+ process.exit(1);
19
+ }
20
+ try {
21
+ const st = await fs.stat(root);
22
+ if (!st.isDirectory())
23
+ throw new Error(`Not a directory: ${root}`);
24
+ }
25
+ catch (err) {
26
+ console.error(chalk.red(`\n✗ Could not read repository\n\n Path:\n ${root}\n\n Reason:\n ${err.message}\n\n Try:\n codecarto --path <directory>\n`));
27
+ process.exit(1);
28
+ }
29
+ const spinner = ora({ text: "Discovering repository...", color: "cyan" }).start();
30
+ logger.verbose("CodeCarto analyzes your project locally. Your source code is not uploaded.");
31
+ try {
32
+ spinner.text = "Scanning files...";
33
+ const { graph, diagnostics } = await runPipeline({
34
+ root,
35
+ ignore: opts.ignore,
36
+ verbose: opts.verbose,
37
+ });
38
+ spinner.text = `Analyzing ${graph.stats.totalFiles} files...`;
39
+ await new Promise((r) => setTimeout(r, 30));
40
+ spinner.text = "Building architecture graph...";
41
+ spinner.succeed(chalk.green("Repository scanned"));
42
+ console.log(chalk.dim(` Root: ${root}`));
43
+ console.log(chalk.dim(` Files: ${graph.stats.totalFiles} Links: ${graph.stats.totalLinks} Dirs: ${graph.stats.totalDirectories} Isolated: ${graph.stats.isolatedFiles}`));
44
+ if (Object.keys(graph.stats.languages).length) {
45
+ const langStr = Object.entries(graph.stats.languages)
46
+ .sort((a, b) => b[1] - a[1])
47
+ .map(([k, v]) => `${k} ${v}`)
48
+ .join(" · ");
49
+ logger.info(chalk.dim(` Languages: ${langStr}`));
50
+ }
51
+ if (graph.stats.totalFiles > 0) {
52
+ console.log("");
53
+ const langs = Object.entries(graph.stats.languages).sort((a, b) => b[1] - a[1]);
54
+ const maxCount = Math.max(...langs.map(([, c]) => c));
55
+ for (const [lang, count] of langs) {
56
+ const pct = Math.round((count / graph.stats.totalFiles) * 100);
57
+ const width = Math.max(2, Math.round((count / maxCount) * 16));
58
+ const bar = "█".repeat(width);
59
+ const label = lang.padEnd(12);
60
+ console.log(` ${label} ${chalk.cyan(bar)} ${pct}%`);
61
+ }
62
+ console.log("");
63
+ }
64
+ if (diagnostics.parseFailures.length) {
65
+ logger.warn(`${diagnostics.parseFailures.length} parse failures`);
66
+ if (opts.verbose)
67
+ for (const f of diagnostics.parseFailures.slice(0, 5))
68
+ logger.dim(` ! ${f.path}: ${f.reason}`);
69
+ }
70
+ if (opts.output) {
71
+ const outPath = path.resolve(opts.output);
72
+ await fs.mkdir(path.dirname(outPath), { recursive: true });
73
+ await fs.writeFile(outPath, JSON.stringify(graph, null, 2), "utf-8");
74
+ logger.success(`Graph written to ${outPath}`);
75
+ console.log(chalk.dim("\n Tip: codecarto serve --input <file> to visualize the exported graph.\n"));
76
+ return;
77
+ }
78
+ console.log(chalk.dim(" Starting visualization...\n"));
79
+ const { url, server } = await startServer({ graph, preferredPort });
80
+ console.log(chalk.green(`✓ Visualization running\n`));
81
+ console.log(` ${chalk.bold.cyan(url)}\n`);
82
+ console.log(chalk.dim(" Press Ctrl+C to stop.\n"));
83
+ await waitForServer(url);
84
+ if (opts.open)
85
+ await openBrowser(url);
86
+ await new Promise((resolve) => {
87
+ const close = () => server.close(() => resolve());
88
+ process.on("SIGINT", close);
89
+ process.on("SIGTERM", close);
90
+ });
91
+ logger.info("Server stopped.");
92
+ }
93
+ catch (err) {
94
+ spinner.fail(chalk.red("Failed to analyze repository"));
95
+ console.error(chalk.red(err.message));
96
+ if (opts.verbose)
97
+ console.error(err);
98
+ else
99
+ console.error(chalk.dim(" Run with --verbose for details.\n"));
100
+ process.exit(1);
101
+ }
102
+ }
103
+ //# sourceMappingURL=default.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default.js","sourceRoot":"","sources":["../../src/commands/default.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAUjE,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAoB;IACvD,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC/C,WAAW,EAAE,CAAC;IAEd,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,gCAAgC;IAC/D,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAExC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,GAAG,CAAC,IAAI,aAAa,GAAG,KAAK,EAAE,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,qBAAqB,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CACP,+CAA+C,IAAI,oBAAqB,GAAa,CAAC,OAAO,8CAA8C,CAC5I,CACF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,2BAA2B,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAClF,MAAM,CAAC,OAAO,CAAC,4EAA4E,CAAC,CAAC;IAE7F,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,GAAG,mBAAmB,CAAC;QACnC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,WAAW,CAAC;YAC/C,IAAI;YACJ,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,GAAG,aAAa,KAAK,CAAC,KAAK,CAAC,UAAU,WAAW,CAAC;QAC9D,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,GAAG,gCAAgC,CAAC;QAEhD,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CACP,YAAY,KAAK,CAAC,KAAK,CAAC,UAAU,YAAY,KAAK,CAAC,KAAK,CAAC,UAAU,WAAW,KAAK,CAAC,KAAK,CAAC,gBAAgB,eAAe,KAAK,CAAC,KAAK,CAAC,aAAa,EAAE,CACtJ,CACF,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC;YAC9C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,SAAmC,CAAC;iBAC5E,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;iBAC3B,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;iBAC5B,IAAI,CAAC,KAAK,CAAC,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,OAAO,EAAE,CAAC,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,SAAmC,CAAC,CAAC,IAAI,CAChF,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CACtB,CAAC;YACF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACtD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;gBAClC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC;gBAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAC/D,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;YACvD,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,WAAW,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,aAAa,CAAC,MAAM,iBAAiB,CAAC,CAAC;YAClE,IAAI,IAAI,CAAC,OAAO;gBACd,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;oBACnD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1C,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3D,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YACrE,MAAM,CAAC,OAAO,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;YAC9C,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CAAC,4EAA4E,CAAC,CACxF,CAAC;YACF,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC,CAAC;QAExD,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,WAAW,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC,CAAC;QAEpD,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI;YAAE,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;QAEtC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YAClD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC5B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC;QACxD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC,CAAC;QACjD,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;;YAChC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface ExportOptions {
2
+ path: string;
3
+ output: string;
4
+ format: string;
5
+ verbose?: boolean;
6
+ ignore?: string[];
7
+ }
8
+ export declare function exportCommand(opts: ExportOptions): Promise<void>;
9
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDtE"}
@@ -0,0 +1,62 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import chalk from "chalk";
4
+ import ora from "ora";
5
+ import { runPipeline } from "../utils/pipeline.js";
6
+ import { logger, setLogLevel } from "../utils/logger.js";
7
+ import { resolveRoot } from "../utils/paths.js";
8
+ export async function exportCommand(opts) {
9
+ setLogLevel(opts.verbose ? "verbose" : "info");
10
+ const root = resolveRoot(opts.path);
11
+ const format = opts.format.toLowerCase();
12
+ if (!["json", "html"].includes(format)) {
13
+ console.error(chalk.red(`\n✗ Unknown format: ${opts.format} (expected json | html)\n`));
14
+ process.exit(1);
15
+ }
16
+ const spinner = ora("Exporting architecture...").start();
17
+ try {
18
+ await fs.stat(root);
19
+ }
20
+ catch (err) {
21
+ spinner.fail(chalk.red("Could not read repository"));
22
+ console.error(chalk.dim(err.message));
23
+ process.exit(1);
24
+ }
25
+ try {
26
+ const { graph } = await runPipeline({ root, ignore: opts.ignore, verbose: opts.verbose });
27
+ if (format === "json") {
28
+ const json = JSON.stringify(graph, null, 2);
29
+ const outPath = path.resolve(opts.output);
30
+ await fs.mkdir(path.dirname(outPath), { recursive: true });
31
+ await fs.writeFile(outPath, json, "utf-8");
32
+ spinner.succeed(chalk.green(`Exported JSON -> ${outPath}`));
33
+ }
34
+ else {
35
+ const statsLine = `${graph.stats.totalFiles} files · ${graph.stats.totalLinks} links · ${Object.keys(graph.stats.languages).length} languages`;
36
+ const html = `<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>CodeCarto - ${escapeHtml(path.basename(root))}</title><style>body{margin:0;background:#050505;color:#e6e8ec;font-family:system-ui;padding:32px}pre{background:#0f0f12;border:1px solid #1e1e24;padding:16px;border-radius:8px;overflow:auto;max-width:960px}a{color:#00d9ff}</style></head><body><h1 style="color:#00d9ff">CodeCarto</h1><p>Architecture of <strong>${escapeHtml(root)}</strong></p><p>${statsLine}</p><pre>${escapeHtml(JSON.stringify(graph, null, 2))}</pre><p><a href="#" onclick="navigator.clipboard.writeText(document.querySelector('pre').textContent);return false">Copy JSON</a></p></body></html>`;
37
+ const out = opts.output.endsWith(".html")
38
+ ? opts.output
39
+ : opts.output.replace(/\.json$/, "") + ".html";
40
+ const outPath = path.resolve(out);
41
+ await fs.mkdir(path.dirname(outPath), { recursive: true });
42
+ await fs.writeFile(outPath, html, "utf-8");
43
+ spinner.succeed(chalk.green(`Exported HTML -> ${outPath}`));
44
+ }
45
+ logger.dim(" Tip: codecarto serve --input <file> to visualize an exported graph.\n");
46
+ }
47
+ catch (err) {
48
+ spinner.fail(chalk.red("Export failed"));
49
+ console.error(chalk.red(err.message));
50
+ if (opts.verbose)
51
+ console.error(err);
52
+ process.exit(1);
53
+ }
54
+ }
55
+ function escapeHtml(s) {
56
+ return s
57
+ .replaceAll("&", "&amp;")
58
+ .replaceAll("<", "&lt;")
59
+ .replaceAll(">", "&gt;")
60
+ .replaceAll('"', "&quot;");
61
+ }
62
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export interface ScanOptions {
2
+ path: string;
3
+ output?: string;
4
+ verbose?: boolean;
5
+ ignore?: string[];
6
+ }
7
+ export declare function scanCommand(opts: ScanOptions): Promise<void>;
8
+ //# sourceMappingURL=scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAqFlE"}
@@ -0,0 +1,81 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import chalk from "chalk";
4
+ import ora from "ora";
5
+ import { runPipeline } from "../utils/pipeline.js";
6
+ import { logger, setLogLevel } from "../utils/logger.js";
7
+ import { resolveRoot } from "../utils/paths.js";
8
+ export async function scanCommand(opts) {
9
+ setLogLevel(opts.verbose ? "verbose" : "info");
10
+ const root = resolveRoot(opts.path);
11
+ try {
12
+ const st = await fs.stat(root);
13
+ if (!st.isDirectory())
14
+ throw new Error(`Not a directory: ${root}`);
15
+ }
16
+ catch (err) {
17
+ console.error(chalk.red(`\n✗ Could not read repository\n\n Path:\n ${root}\n\n Reason:\n ${err.message}\n\n Try:\n codecarto --path <directory>\n`));
18
+ process.exit(1);
19
+ }
20
+ const spinner = ora({ text: "Discovering repository...", color: "cyan" }).start();
21
+ try {
22
+ spinner.text = "Scanning files...";
23
+ const { graph, diagnostics } = await runPipeline({
24
+ root,
25
+ ignore: opts.ignore,
26
+ verbose: opts.verbose,
27
+ });
28
+ spinner.text = `Analyzing ${graph.stats.totalFiles} files...`;
29
+ await new Promise((r) => setTimeout(r, 50));
30
+ spinner.text = "Building architecture graph...";
31
+ spinner.succeed(chalk.green("Repository scanned"));
32
+ logger.info(chalk.dim(` Root: ${root}`));
33
+ logger.info(chalk.dim(` Files: ${graph.stats.totalFiles} Links: ${graph.stats.totalLinks} Dirs: ${graph.stats.totalDirectories} Isolated: ${graph.stats.isolatedFiles}`));
34
+ if (Object.keys(graph.stats.languages).length) {
35
+ const langStr = Object.entries(graph.stats.languages)
36
+ .sort((a, b) => b[1] - a[1])
37
+ .map(([k, v]) => `${k} ${v}`)
38
+ .join(" · ");
39
+ logger.info(chalk.dim(` Languages: ${langStr}`));
40
+ }
41
+ if (diagnostics.parseFailures.length) {
42
+ logger.warn(`${diagnostics.parseFailures.length} parse failures (see --verbose)`);
43
+ if (opts.verbose) {
44
+ for (const f of diagnostics.parseFailures.slice(0, 10))
45
+ logger.dim(` ! ${f.path}: ${f.reason}`);
46
+ }
47
+ }
48
+ if (diagnostics.unsupported)
49
+ logger.dim(` Unsupported: ${diagnostics.unsupported} files (parser unavailable)`);
50
+ console.log("");
51
+ if (graph.stats.totalFiles > 0) {
52
+ const langs = Object.entries(graph.stats.languages).sort((a, b) => b[1] - a[1]);
53
+ for (const [lang, count] of langs) {
54
+ const pct = Math.round((count / graph.stats.totalFiles) * 100);
55
+ const bar = "█".repeat(Math.max(1, Math.round(pct / 5)));
56
+ logger.info(` ${lang.padEnd(12)} ${bar} ${pct}%`);
57
+ }
58
+ console.log("");
59
+ }
60
+ const json = JSON.stringify(graph, null, 2);
61
+ if (opts.output) {
62
+ const outPath = path.resolve(opts.output);
63
+ await fs.mkdir(path.dirname(outPath), { recursive: true });
64
+ await fs.writeFile(outPath, json, "utf-8");
65
+ logger.success(`Graph written to ${outPath}`);
66
+ }
67
+ else {
68
+ console.log(json);
69
+ }
70
+ }
71
+ catch (err) {
72
+ spinner.fail(chalk.red("Scan failed"));
73
+ console.error(chalk.red(err.message));
74
+ if (opts.verbose)
75
+ console.error(err);
76
+ else
77
+ console.error(chalk.dim(" Run with --verbose for details.\n"));
78
+ process.exit(1);
79
+ }
80
+ }
81
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAShD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAiB;IACjD,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEpC,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CACP,+CAA+C,IAAI,oBAAqB,GAAa,CAAC,OAAO,8CAA8C,CAC5I,CACF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,2BAA2B,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAElF,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,GAAG,mBAAmB,CAAC;QACnC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,WAAW,CAAC;YAC/C,IAAI;YACJ,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,GAAG,aAAa,KAAK,CAAC,KAAK,CAAC,UAAU,WAAW,CAAC;QAC9D,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,GAAG,gCAAgC,CAAC;QAEhD,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;QAEnD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAI,CACT,KAAK,CAAC,GAAG,CACP,YAAY,KAAK,CAAC,KAAK,CAAC,UAAU,YAAY,KAAK,CAAC,KAAK,CAAC,UAAU,WAAW,KAAK,CAAC,KAAK,CAAC,gBAAgB,eAAe,KAAK,CAAC,KAAK,CAAC,aAAa,EAAE,CACtJ,CACF,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC;YAC9C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,SAAmC,CAAC;iBAC5E,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;iBAC3B,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;iBAC5B,IAAI,CAAC,KAAK,CAAC,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,OAAO,EAAE,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,WAAW,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,aAAa,CAAC,MAAM,iCAAiC,CAAC,CAAC;YAClF,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjB,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;oBACpD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;QACD,IAAI,WAAW,CAAC,WAAW;YACzB,MAAM,CAAC,GAAG,CAAC,kBAAkB,WAAW,CAAC,WAAW,6BAA6B,CAAC,CAAC;QACrF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,SAAmC,CAAC,CAAC,IAAI,CAChF,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CACtB,CAAC;YACF,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;gBAClC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC;gBAC/D,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACzD,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC;YACrD,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAE5C,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1C,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3D,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;QACvC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC,CAAC;QACjD,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;;YAChC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface ServeOptions {
2
+ input: string;
3
+ port: string;
4
+ open: boolean;
5
+ verbose?: boolean;
6
+ }
7
+ export declare function serveCommand(opts: ServeOptions): Promise<void>;
8
+ //# sourceMappingURL=serve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA8CpE"}
@@ -0,0 +1,47 @@
1
+ import fs from "node:fs/promises";
2
+ import chalk from "chalk";
3
+ import { parseCodeGraph } from "@yoinkingfish/shared";
4
+ import { logger, setLogLevel } from "../utils/logger.js";
5
+ import { startServer } from "../server/index.js";
6
+ import { openBrowser, waitForServer } from "../browser/index.js";
7
+ export async function serveCommand(opts) {
8
+ setLogLevel(opts.verbose ? "verbose" : "info");
9
+ const port = Number(opts.port);
10
+ if (!Number.isFinite(port) || port < 1 || port > 65535) {
11
+ console.error(chalk.red(`\n✗ Invalid port: ${opts.port}\n`));
12
+ process.exit(1);
13
+ }
14
+ let raw;
15
+ try {
16
+ raw = await fs.readFile(opts.input, "utf-8");
17
+ }
18
+ catch (err) {
19
+ console.error(chalk.red(`\n✗ Could not read graph file\n\n Path: ${opts.input}\n Reason: ${err.message}\n`));
20
+ process.exit(1);
21
+ }
22
+ let graph;
23
+ try {
24
+ graph = parseCodeGraph(JSON.parse(raw));
25
+ }
26
+ catch (err) {
27
+ console.error(chalk.red(`\n✗ Invalid graph JSON: ${err.message}\n`));
28
+ process.exit(1);
29
+ }
30
+ const { url, server } = await startServer({ graph, preferredPort: port });
31
+ console.log(chalk.green(`\n✓ Visualization running\n`));
32
+ console.log(` ${chalk.bold(url)}\n`);
33
+ console.log(chalk.dim(" Press Ctrl+C to stop.\n"));
34
+ await waitForServer(url);
35
+ if (opts.open)
36
+ await openBrowser(url);
37
+ // Keep process alive until SIGINT
38
+ await new Promise((resolve) => {
39
+ const close = () => {
40
+ server.close(() => resolve());
41
+ };
42
+ process.on("SIGINT", close);
43
+ process.on("SIGTERM", close);
44
+ });
45
+ logger.info("Server stopped.");
46
+ }
47
+ //# sourceMappingURL=serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CodeCarto CLI entry point.
4
+ * Local-first, offline-capable. Never executes repository code.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG"}
package/dist/index.js ADDED
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CodeCarto CLI entry point.
4
+ * Local-first, offline-capable. Never executes repository code.
5
+ */
6
+ import { Command } from "commander";
7
+ import chalk from "chalk";
8
+ import { createRequire } from "node:module";
9
+ import { scanCommand } from "./commands/scan.js";
10
+ import { serveCommand } from "./commands/serve.js";
11
+ import { exportCommand } from "./commands/export.js";
12
+ import { defaultCommand } from "./commands/default.js";
13
+ const require = createRequire(import.meta.url);
14
+ // Read version without importing JSON with assertions (Node 18 compat)
15
+ let version = "0.1.0";
16
+ try {
17
+ const pkg = require("../../package.json");
18
+ if (pkg.version)
19
+ version = pkg.version;
20
+ }
21
+ catch {
22
+ // fallback — will be replaced by workspace package version at build time
23
+ try {
24
+ const cliPkg = require("../package.json");
25
+ if (cliPkg.version)
26
+ version = cliPkg.version;
27
+ }
28
+ catch {
29
+ /* noop */
30
+ }
31
+ }
32
+ const program = new Command();
33
+ program
34
+ .name("codecarto")
35
+ .description("See your codebase — local-first 3D architecture visualization")
36
+ .version(version, "-V, --version", "output the version number")
37
+ .helpOption("-h, --help", "display help for command");
38
+ // Default: scan + serve + open browser
39
+ program
40
+ .option("--port <number>", "preferred port (auto-increments if busy)", String(3000))
41
+ .option("--no-open", "do not automatically open browser")
42
+ .option("--verbose", "verbose logging", false)
43
+ .option("--ignore <pattern>", "additional ignore glob (repeatable)", collect, [])
44
+ .option("--output <file>", "write graph JSON to file instead of serving")
45
+ .action(defaultCommand);
46
+ // Subcommands
47
+ program
48
+ .command("scan")
49
+ .description("scan repository and print graph JSON to stdout or file")
50
+ .option("--path <dir>", "repository root", ".")
51
+ .option("--output <file>", "write graph JSON to file")
52
+ .option("--verbose", "verbose logging", false)
53
+ .option("--ignore <pattern>", "additional ignore glob (repeatable)", collect, [])
54
+ .action(scanCommand);
55
+ program
56
+ .command("serve")
57
+ .description("serve an existing graph JSON file in the visualizer")
58
+ .option("--input <file>", "graph JSON file to serve", "codecarto-data.json")
59
+ .option("--port <number>", "preferred port", String(3000))
60
+ .option("--no-open", "do not automatically open browser")
61
+ .option("--verbose", "verbose logging", false)
62
+ .action(serveCommand);
63
+ program
64
+ .command("export")
65
+ .description("export portable architecture artifact (JSON / HTML)")
66
+ .option("--path <dir>", "repository root", ".")
67
+ .option("--output <file>", "output file", "codecarto-data.json")
68
+ .option("--format <format>", "export format: json | html", "json")
69
+ .option("--verbose", "verbose logging", false)
70
+ .option("--ignore <pattern>", "additional ignore glob (repeatable)", collect, [])
71
+ .action(exportCommand);
72
+ function collect(value, previous) {
73
+ return previous.concat([value]);
74
+ }
75
+ // Friendly error handling — never dump stack in normal mode
76
+ program.exitOverride();
77
+ try {
78
+ await program.parseAsync(process.argv);
79
+ }
80
+ catch (err) {
81
+ const e = err;
82
+ // Commander help/version exits with code 0 — pass through
83
+ if (e.code === "commander.helpDisplayed" || e.code === "commander.version") {
84
+ process.exit(0);
85
+ }
86
+ if (e.message) {
87
+ console.error(chalk.red(`\n✗ ${e.message}\n`));
88
+ if (process.argv.includes("--verbose")) {
89
+ console.error(e);
90
+ }
91
+ else {
92
+ console.error(chalk.dim(" Run with --verbose for details. See --help.\n"));
93
+ }
94
+ }
95
+ process.exit(e.exitCode ?? 1);
96
+ }
97
+ // Graceful termination
98
+ process.on("SIGINT", () => {
99
+ console.log(chalk.dim("\n Shutting down…\n"));
100
+ process.exit(0);
101
+ });
102
+ process.on("SIGTERM", () => {
103
+ process.exit(0);
104
+ });
105
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Local HTTP server — serves visualizer static assets + graph JSON.
3
+ * Binds to 127.0.0.1 only. Tries ports incrementally.
4
+ */
5
+ import http from "node:http";
6
+ import type { CodeGraph } from "@yoinkingfish/shared";
7
+ export interface ServeOptions {
8
+ graph: CodeGraph;
9
+ preferredPort?: number;
10
+ verbose?: boolean;
11
+ }
12
+ export interface ServeResult {
13
+ url: string;
14
+ port: number;
15
+ server: http.Server;
16
+ }
17
+ export declare function startServer(options: ServeOptions): Promise<ServeResult>;
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAK7B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAiCtD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,SAAS,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;CACrB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAwF7E"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Local HTTP server — serves visualizer static assets + graph JSON.
3
+ * Binds to 127.0.0.1 only. Tries ports incrementally.
4
+ */
5
+ import http from "node:http";
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ import { DEFAULT_PORT, MAX_PORT_ATTEMPTS } from "@yoinkingfish/shared";
10
+ import { logger } from "../utils/logger.js";
11
+ function findVisualizerDist() {
12
+ const base = path.dirname(fileURLToPath(import.meta.url));
13
+ const candidates = [
14
+ // monorepo dev: packages/cli/dist/server -> apps/visualizer/dist (4 levels up)
15
+ path.resolve(base, "../../../../apps/visualizer/dist"),
16
+ // alternative dev layout
17
+ path.resolve(base, "../../../apps/visualizer/dist"),
18
+ // published npm: node_modules/codecarto/dist/server -> node_modules/codecarto/visualizer
19
+ path.resolve(base, "../../visualizer"),
20
+ path.resolve(base, "../visualizer"),
21
+ path.resolve(base, "../../visualizer/dist"),
22
+ ];
23
+ for (const c of candidates) {
24
+ if (fs.existsSync(c))
25
+ return c;
26
+ }
27
+ return null;
28
+ }
29
+ const MIME = {
30
+ ".html": "text/html; charset=utf-8",
31
+ ".js": "text/javascript; charset=utf-8",
32
+ ".css": "text/css; charset=utf-8",
33
+ ".json": "application/json; charset=utf-8",
34
+ ".svg": "image/svg+xml",
35
+ ".png": "image/png",
36
+ ".ico": "image/x-icon",
37
+ ".woff": "font/woff",
38
+ ".woff2": "font/woff2",
39
+ };
40
+ export async function startServer(options) {
41
+ const { graph, preferredPort = DEFAULT_PORT } = options;
42
+ const graphJson = JSON.stringify(graph);
43
+ // Inline fallback HTML if visualizer not yet built — still proves server works
44
+ const fallbackHtml = `<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>CodeCarto</title><style>body{margin:0;background:#050505;color:#e6e8ec;font-family:ui-monospace,monospace;display:grid;place-items:center;height:100vh}pre{background:#0f0f12;border:1px solid #1e1e24;padding:24px;border-radius:12px;max-width:720px;overflow:auto}a{color:#00d9ff}</style></head><body><div><h1>CodeCarto</h1><p>Visualizer build not found. Run <code>pnpm build</code> in <code>apps/visualizer</code>.</p><p>Graph API: <a href="/api/graph">/api/graph</a></p><pre id="stats"></pre><script>fetch('/api/graph').then(r=>r.json()).then(g=>{document.getElementById('stats').textContent=JSON.stringify(g.stats,null,2)}).catch(e=>{document.getElementById('stats').textContent=String(e)})</script></div></body></html>`;
45
+ const distDir = findVisualizerDist();
46
+ const handler = (req, res) => {
47
+ const url = new URL(req.url ?? "/", `http://127.0.0.1`);
48
+ const pathname = url.pathname;
49
+ // CORS locked to localhost — no wildcard
50
+ res.setHeader("X-Content-Type-Options", "nosniff");
51
+ res.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;");
52
+ if (pathname === "/api/graph") {
53
+ res.writeHead(200, { "Content-Type": MIME[".json"] });
54
+ res.end(graphJson);
55
+ return;
56
+ }
57
+ if (pathname === "/api/health") {
58
+ res.writeHead(200, { "Content-Type": MIME[".json"] });
59
+ res.end(JSON.stringify({ ok: true, version: graph.version }));
60
+ return;
61
+ }
62
+ if (distDir) {
63
+ const filePath = path.join(distDir, pathname === "/" ? "index.html" : pathname.replace(/^\//, ""));
64
+ // Prevent traversal
65
+ if (!filePath.startsWith(distDir)) {
66
+ res.writeHead(403);
67
+ res.end("Forbidden");
68
+ return;
69
+ }
70
+ if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
71
+ const ext = path.extname(filePath);
72
+ res.writeHead(200, { "Content-Type": MIME[ext] ?? "application/octet-stream" });
73
+ fs.createReadStream(filePath).pipe(res);
74
+ return;
75
+ }
76
+ // SPA fallback
77
+ const indexHtml = path.join(distDir, "index.html");
78
+ if (fs.existsSync(indexHtml)) {
79
+ res.writeHead(200, { "Content-Type": MIME[".html"] });
80
+ fs.createReadStream(indexHtml).pipe(res);
81
+ return;
82
+ }
83
+ }
84
+ // Fallback
85
+ res.writeHead(200, { "Content-Type": MIME[".html"] });
86
+ res.end(fallbackHtml);
87
+ };
88
+ let lastError = null;
89
+ for (let attempt = 0; attempt < MAX_PORT_ATTEMPTS; attempt++) {
90
+ const port = preferredPort + attempt;
91
+ const server = http.createServer(handler);
92
+ try {
93
+ await new Promise((resolve, reject) => {
94
+ server.once("error", reject);
95
+ server.listen(port, "127.0.0.1", () => {
96
+ server.off("error", reject);
97
+ resolve();
98
+ });
99
+ });
100
+ const url = `http://localhost:${port}`;
101
+ logger.verbose(`Server listening on ${url} (distDir=${distDir ?? "fallback"})`);
102
+ return { url, port, server };
103
+ }
104
+ catch (err) {
105
+ lastError = err;
106
+ const code = err.code;
107
+ if (code !== "EADDRINUSE" && code !== "EACCES")
108
+ throw err;
109
+ logger.verbose(`Port ${port} unavailable (${code}), trying next…`);
110
+ continue;
111
+ }
112
+ }
113
+ throw new Error(`Could not bind to any port from ${preferredPort} to ${preferredPort + MAX_PORT_ATTEMPTS - 1}. Last error: ${lastError?.message}`);
114
+ }
115
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function printBanner(): void;
2
+ //# sourceMappingURL=banner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner.d.ts","sourceRoot":"","sources":["../../src/utils/banner.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,SAiB1B"}
@@ -0,0 +1,17 @@
1
+ import chalk from "chalk";
2
+ export function printBanner() {
3
+ // CODECARTO — ANSI Shadow figlet, verified spelling (last char is O, not P/D)
4
+ // Generated via `figlet -f 'ANSI Shadow' CODECARTO` — do not edit manually
5
+ const art = `
6
+ ██████╗ ██████╗ ██████╗ ███████╗ ██████╗ █████╗ ██████╗ ████████╗ ██████╗
7
+ ██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔════╝██╔══██╗██╔══██╗╚══██╔══╝██╔═══██╗
8
+ ██║ ██║ ██║██║ ██║█████╗ ██║ ███████║██████╔╝ ██║ ██║ ██║
9
+ ██║ ██║ ██║██║ ██║██╔══╝ ██║ ██╔══██║██╔══██╗ ██║ ██║ ██║
10
+ ╚██████╗╚██████╔╝██████╔╝███████╗╚██████╗██║ ██║██║ ██║ ██║ ╚██████╔╝
11
+ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝`;
12
+ console.log(chalk.cyan(art));
13
+ console.log(chalk.bold(" CodeCarto"));
14
+ console.log(chalk.dim(" See your codebase. ") +
15
+ chalk.dim.italic("Local \u00b7 Fast \u00b7 Private \u00b7 Visual\n"));
16
+ }
17
+ //# sourceMappingURL=banner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner.js","sourceRoot":"","sources":["../../src/utils/banner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,UAAU,WAAW;IACzB,8EAA8E;IAC9E,2EAA2E;IAC3E,MAAM,GAAG,GAAG;;;;;;2EAM6D,CAAC;IAE1E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CAAC,wBAAwB,CAAC;QACjC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,kDAAkD,CAAC,CACvE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ export type LogLevel = "silent" | "info" | "verbose";
2
+ export declare function setLogLevel(l: LogLevel): void;
3
+ export declare function getLogLevel(): LogLevel;
4
+ export declare const logger: {
5
+ info(msg: string): void;
6
+ verbose(msg: string): void;
7
+ success(msg: string): void;
8
+ warn(msg: string): void;
9
+ error(msg: string): void;
10
+ dim(msg: string): void;
11
+ };
12
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAIrD,wBAAgB,WAAW,CAAC,CAAC,EAAE,QAAQ,QAEtC;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAEtC;AAED,eAAO,MAAM,MAAM;cACP,MAAM;iBAGH,MAAM;iBAGN,MAAM;cAGT,MAAM;eAGL,MAAM;aAGR,MAAM;CAGhB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import chalk from "chalk";
2
+ let level = "info";
3
+ export function setLogLevel(l) {
4
+ level = l;
5
+ }
6
+ export function getLogLevel() {
7
+ return level;
8
+ }
9
+ export const logger = {
10
+ info(msg) {
11
+ if (level !== "silent")
12
+ console.log(msg);
13
+ },
14
+ verbose(msg) {
15
+ if (level === "verbose")
16
+ console.log(chalk.dim(msg));
17
+ },
18
+ success(msg) {
19
+ if (level !== "silent")
20
+ console.log(chalk.green(msg));
21
+ },
22
+ warn(msg) {
23
+ if (level !== "silent")
24
+ console.warn(chalk.yellow(`⚠ ${msg}`));
25
+ },
26
+ error(msg) {
27
+ console.error(chalk.red(`✗ ${msg}`));
28
+ },
29
+ dim(msg) {
30
+ if (level !== "silent")
31
+ console.log(chalk.dim(msg));
32
+ },
33
+ };
34
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,IAAI,KAAK,GAAa,MAAM,CAAC;AAE7B,MAAM,UAAU,WAAW,CAAC,CAAW;IACrC,KAAK,GAAG,CAAC,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,CAAC,GAAW;QACd,IAAI,KAAK,KAAK,QAAQ;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,CAAC,GAAW;QACjB,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,CAAC,GAAW;QACjB,IAAI,KAAK,KAAK,QAAQ;YAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,CAAC,GAAW;QACd,IAAI,KAAK,KAAK,QAAQ;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;IACD,KAAK,CAAC,GAAW;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;IACvC,CAAC;IACD,GAAG,CAAC,GAAW;QACb,IAAI,KAAK,KAAK,QAAQ;YAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACtD,CAAC;CACF,CAAC"}
@@ -0,0 +1,6 @@
1
+ /** Normalize to POSIX, prevent traversal outside root */
2
+ export declare function sanitizePath(root: string, p: string): string;
3
+ export declare function ensureDirectoryExists(dir: string): Promise<void>;
4
+ export declare function toPosix(p: string): string;
5
+ export declare function resolveRoot(input: string): string;
6
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAGA,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAM5D;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUtE;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD"}
@@ -0,0 +1,27 @@
1
+ import path from "node:path";
2
+ import fs from "node:fs/promises";
3
+ /** Normalize to POSIX, prevent traversal outside root */
4
+ export function sanitizePath(root, p) {
5
+ const normalized = path.posix.normalize(p.replaceAll("\\", "/"));
6
+ if (normalized.includes("..")) {
7
+ throw new Error(`Invalid path traversal: ${p}`);
8
+ }
9
+ return normalized;
10
+ }
11
+ export async function ensureDirectoryExists(dir) {
12
+ // Validate that parent is accessible and dir is inside allowed root — caller checks existence
13
+ const abs = path.resolve(dir);
14
+ try {
15
+ await fs.access(path.dirname(abs));
16
+ }
17
+ catch {
18
+ throw new Error(`Parent directory does not exist: ${path.dirname(abs)}\n Try: codecarto --path <existing-directory>`);
19
+ }
20
+ }
21
+ export function toPosix(p) {
22
+ return p.split(path.sep).join(path.posix.sep);
23
+ }
24
+ export function resolveRoot(input) {
25
+ return path.resolve(input);
26
+ }
27
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,yDAAyD;AACzD,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,CAAS;IAClD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IACjE,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAW;IACrD,8FAA8F;IAC9F,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,oCAAoC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,gDAAgD,CACtG,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,CAAS;IAC/B,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Pipeline — orchestrates scan → parse → resolve → graph.
3
+ * This is the core that CLI `scan` and `default` commands use.
4
+ */
5
+ import type { CodeGraph } from "@yoinkingfish/shared";
6
+ export interface PipelineOptions {
7
+ root: string;
8
+ ignore?: string[];
9
+ verbose?: boolean;
10
+ maxFileSizeBytes?: number;
11
+ concurrency?: number;
12
+ }
13
+ export interface PipelineResult {
14
+ graph: CodeGraph;
15
+ diagnostics: {
16
+ scanned: number;
17
+ parsed: number;
18
+ unsupported: number;
19
+ parseFailures: Array<{
20
+ path: string;
21
+ reason: string;
22
+ }>;
23
+ unresolvedLocals: number;
24
+ externals: number;
25
+ };
26
+ }
27
+ export declare function runPipeline(options: PipelineOptions): Promise<PipelineResult>;
28
+ //# sourceMappingURL=pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/utils/pipeline.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,sBAAsB,CAAC;AAGhE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,EAAE;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACvD,gBAAgB,EAAE,MAAM,CAAC;QACzB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA+MnF"}
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Pipeline — orchestrates scan → parse → resolve → graph.
3
+ * This is the core that CLI `scan` and `default` commands use.
4
+ */
5
+ import fs from "node:fs/promises";
6
+ import path from "node:path";
7
+ import { scanRepositoryDetailed, getParserForExtension, resolveImport, parseTsconfigPaths, } from "@yoinkingfish/parser";
8
+ import { buildGraph } from "@yoinkingfish/graph";
9
+ import { LANGUAGE_BY_EXTENSION } from "@yoinkingfish/shared";
10
+ export async function runPipeline(options) {
11
+ const root = path.resolve(options.root);
12
+ const ignore = options.ignore ?? [];
13
+ // Load tsconfig paths if present
14
+ const { tsConfigPaths, tsConfigBaseUrl } = await loadTsconfig(root);
15
+ // 1. Scan
16
+ const scan = await scanRepositoryDetailed({
17
+ root,
18
+ ignore,
19
+ maxFileSizeBytes: options.maxFileSizeBytes,
20
+ concurrency: options.concurrency,
21
+ });
22
+ const files = scan.files;
23
+ const existingFilesSet = new Set(files.map((f) => f.relativePath));
24
+ const existingAbsSet = new Set(files.map((f) => f.absolutePath));
25
+ // 2. Parse + build nodes + collect raw dependencies
26
+ const nodes = [];
27
+ const rawEdges = [];
28
+ const parseFailures = [];
29
+ const unsupported = [];
30
+ let externals = 0;
31
+ let unresolvedLocals = 0;
32
+ // Read files concurrently with limit
33
+ const concurrency = options.concurrency ?? 32;
34
+ const queue = [...files];
35
+ const workers = [];
36
+ async function worker() {
37
+ while (queue.length) {
38
+ const file = queue.pop();
39
+ let source;
40
+ try {
41
+ source = await fs.readFile(file.absolutePath, "utf-8");
42
+ }
43
+ catch (err) {
44
+ parseFailures.push({ path: file.relativePath, reason: err.message });
45
+ continue;
46
+ }
47
+ const parser = getParserForExtension(file.extension);
48
+ if (!parser) {
49
+ unsupported.push({ path: file.relativePath, reason: `no parser for .${file.extension}` });
50
+ continue;
51
+ }
52
+ let result;
53
+ try {
54
+ result = await parser.parseFile(source, {
55
+ filePath: file.absolutePath,
56
+ relativePath: file.relativePath,
57
+ root,
58
+ tsConfigPaths,
59
+ });
60
+ }
61
+ catch (err) {
62
+ parseFailures.push({ path: file.relativePath, reason: err.message });
63
+ continue;
64
+ }
65
+ if (result.parseError) {
66
+ parseFailures.push({ path: file.relativePath, reason: result.parseError });
67
+ }
68
+ // Build node
69
+ const dir = path.posix.dirname(file.relativePath);
70
+ const depth = dir === "." ? 0 : dir.split("/").length;
71
+ const lines = source.split("\n").length;
72
+ const category = inferCategory(file.relativePath);
73
+ nodes.push({
74
+ id: file.relativePath,
75
+ type: "file",
76
+ path: file.relativePath,
77
+ name: path.posix.basename(file.relativePath),
78
+ extension: file.extension,
79
+ language: file.language ?? LANGUAGE_BY_EXTENSION[file.extension],
80
+ category,
81
+ sizeBytes: file.sizeBytes,
82
+ linesOfCode: lines,
83
+ directory: dir,
84
+ depth,
85
+ inboundDependencies: 0,
86
+ outboundDependencies: 0,
87
+ });
88
+ // Collect dependencies for later resolution
89
+ for (const dep of result.dependencies) {
90
+ const resolved = resolveImport(dep.specifier, {
91
+ importerPath: file.absolutePath,
92
+ importerRelative: file.relativePath,
93
+ root,
94
+ existingFiles: existingFilesSet,
95
+ existingAbsFiles: existingAbsSet,
96
+ tsConfigPaths,
97
+ tsConfigBaseUrl,
98
+ });
99
+ if (resolved.resolved && resolved.resolvedPath) {
100
+ // Will be added as link after nodes built
101
+ rawEdges.push({
102
+ source: file.relativePath,
103
+ specifier: dep.specifier,
104
+ type: dep.type,
105
+ resolved: false,
106
+ });
107
+ // Store resolved mapping for later
108
+ dep._resolvedPath = resolved.resolvedPath;
109
+ // Keep dep for link creation
110
+ file._deps ??= [];
111
+ file._deps.push({
112
+ ...dep,
113
+ _resolvedPath: resolved.resolvedPath,
114
+ });
115
+ }
116
+ else {
117
+ if (resolved.external)
118
+ externals++;
119
+ else
120
+ unresolvedLocals++;
121
+ // Still track unresolved? MVP omits external nodes, but we could keep meta
122
+ }
123
+ }
124
+ // Attach deps to file object for link phase
125
+ file._rawDeps = result.dependencies;
126
+ }
127
+ }
128
+ const workerCount = Math.min(concurrency, Math.max(1, Math.ceil(files.length / 16)));
129
+ for (let i = 0; i < workerCount; i++)
130
+ workers.push(worker());
131
+ await Promise.all(workers);
132
+ // If any unsupported files from scan, merge
133
+ for (const s of scan.skipped) {
134
+ if (s.reason.startsWith("unsupported"))
135
+ unsupported.push(s);
136
+ }
137
+ // 3. Build links from resolved deps
138
+ // We need to re-derive links from file._rawDeps that had resolved path
139
+ const links = [];
140
+ for (const file of files) {
141
+ const rawDeps = file._rawDeps;
142
+ if (!rawDeps)
143
+ continue;
144
+ for (const dep of rawDeps) {
145
+ const depWithResolved = dep;
146
+ const resolvedPath = depWithResolved._resolvedPath;
147
+ if (!resolvedPath)
148
+ continue;
149
+ // Only include if target exists (we already checked)
150
+ links.push({
151
+ source: file.relativePath,
152
+ target: resolvedPath,
153
+ type: dep.type,
154
+ resolved: true,
155
+ rawSpecifier: dep.specifier,
156
+ weight: 1,
157
+ });
158
+ }
159
+ }
160
+ // Deduplicate links (A->B may appear multiple times via multiple imports)
161
+ const linkMap = new Map();
162
+ for (const l of links) {
163
+ const key = `${l.source}::${l.target}::${l.type}`;
164
+ const existing = linkMap.get(key);
165
+ if (existing) {
166
+ existing.weight = (existing.weight ?? 1) + 1;
167
+ }
168
+ else {
169
+ linkMap.set(key, { ...l });
170
+ }
171
+ }
172
+ const dedupedLinks = [...linkMap.values()];
173
+ // 4. Build graph
174
+ const graph = buildGraph({ root, nodes, links: dedupedLinks });
175
+ // Enrich stats with scan/parse diagnostics
176
+ graph.stats.parseFailures = parseFailures;
177
+ graph.stats.unsupportedFiles = unsupported.map((s) => ({
178
+ path: s.path,
179
+ language: s.reason.includes(".") ? s.reason.split(".").pop() : undefined,
180
+ }));
181
+ // Recompute isolated after dedupe? buildGraph already does
182
+ return {
183
+ graph,
184
+ diagnostics: {
185
+ scanned: scan.stats.totalDiscovered,
186
+ parsed: nodes.length,
187
+ unsupported: unsupported.length,
188
+ parseFailures,
189
+ unresolvedLocals,
190
+ externals,
191
+ },
192
+ };
193
+ }
194
+ async function loadTsconfig(root) {
195
+ const candidates = ["tsconfig.json", "jsconfig.json"];
196
+ for (const name of candidates) {
197
+ const p = path.join(root, name);
198
+ try {
199
+ const content = await fs.readFile(p, "utf-8");
200
+ const parsed = parseTsconfigPaths(content, root);
201
+ if (parsed.paths || parsed.baseUrl)
202
+ return { tsConfigPaths: parsed.paths, tsConfigBaseUrl: parsed.baseUrl };
203
+ }
204
+ catch {
205
+ continue;
206
+ }
207
+ }
208
+ // Also check for tsconfig via workspaces? For monorepo, check root + packages/*/tsconfig
209
+ return {};
210
+ }
211
+ function inferCategory(relPath) {
212
+ const p = relPath.toLowerCase();
213
+ if (p.includes("__tests__") ||
214
+ p.endsWith(".test.ts") ||
215
+ p.endsWith(".test.tsx") ||
216
+ p.endsWith(".spec.ts") ||
217
+ p.includes("/test/"))
218
+ return "test";
219
+ if (p.includes("/components/") || p.includes("/ui/") || p.endsWith(".css") || p.endsWith(".scss"))
220
+ return p.endsWith(".css") || p.endsWith(".scss") ? "style" : "ui";
221
+ if (p.includes("/api/") ||
222
+ p.includes("/routes/") ||
223
+ p.includes("/pages/api/") ||
224
+ p.startsWith("api/"))
225
+ return "api";
226
+ if (p.includes("/config/") || p.endsWith(".config.ts") || p.endsWith(".config.js"))
227
+ return "config";
228
+ if (p.includes("/utils/") || p.includes("/helpers/") || p.includes("/lib/"))
229
+ return "util";
230
+ if (p.includes("/data/") || p.includes("/db/") || p.includes("/models/"))
231
+ return "data";
232
+ return "other";
233
+ }
234
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/utils/pipeline.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@yoinkingfish/codecarto",
3
+ "version": "0.1.1",
4
+ "description": "See your codebase — local-first 3D architecture visualization",
5
+ "type": "module",
6
+ "bin": {
7
+ "codecarto": "./dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.js"
18
+ }
19
+ },
20
+ "dependencies": {
21
+ "chalk": "^5.3.0",
22
+ "commander": "^12.1.0",
23
+ "fast-glob": "^3.3.2",
24
+ "open": "^10.1.0",
25
+ "ora": "^8.0.1",
26
+ "zod": "^3.23.8",
27
+ "@yoinkingfish/graph": "0.1.1",
28
+ "@yoinkingfish/parser": "0.1.1",
29
+ "@yoinkingfish/shared": "0.1.1"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^22.7.4",
33
+ "rimraf": "^6.0.1",
34
+ "typescript": "^5.6.3",
35
+ "vitest": "^2.1.8"
36
+ },
37
+ "engines": {
38
+ "node": ">=18.0.0"
39
+ },
40
+ "keywords": [
41
+ "architecture",
42
+ "visualization",
43
+ "3d",
44
+ "ast",
45
+ "graph",
46
+ "cli",
47
+ "developer-tools"
48
+ ],
49
+ "license": "MIT",
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "https://github.com/OpKnock/codecarto.git"
53
+ },
54
+ "author": "Mehul Wagde <yoinkingfish@gmail.com>",
55
+ "scripts": {
56
+ "build": "tsc -p tsconfig.json",
57
+ "dev": "tsc -p tsconfig.json --watch",
58
+ "typecheck": "tsc --noEmit -p tsconfig.json",
59
+ "clean": "rimraf dist",
60
+ "test": "vitest run"
61
+ }
62
+ }