@clarity-tools/cli 0.1.0 → 0.1.2

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 (3) hide show
  1. package/README.md +27 -0
  2. package/dist/index.js +47 -4
  3. package/package.json +3 -2
package/README.md CHANGED
@@ -4,6 +4,16 @@ Generate beautiful, hand-drawn style architecture diagrams from your Infrastruct
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@clarity-tools/cli.svg)](https://www.npmjs.com/package/@clarity-tools/cli)
6
6
 
7
+ ## Examples
8
+
9
+ ### Temporal
10
+
11
+ ![Temporal architecture](https://raw.githubusercontent.com/BrennerSpear/clarity/main/docs/images/temporal.png)
12
+
13
+ ### Mastodon
14
+
15
+ ![Mastodon architecture](https://raw.githubusercontent.com/BrennerSpear/clarity/main/docs/images/mastodon.png)
16
+
7
17
  ## Features
8
18
 
9
19
  - **Auto-detection**: Finds docker-compose.yml, compose.yml, and Helm charts
@@ -50,6 +60,7 @@ iac-diagrams [path] [options]
50
60
  - `-o, --output <dir>` - Output directory (default: `./docs/diagrams`)
51
61
  - `--no-llm` - Disable LLM enhancement
52
62
  - `--no-png` - Skip PNG rendering (output .excalidraw only)
63
+ - `--artifacts` - Save parsed/enhanced/elk JSON artifacts alongside outputs
53
64
  - `-v, --verbose` - Show detailed output
54
65
 
55
66
  **Examples:**
@@ -108,6 +119,16 @@ docs/diagrams/
108
119
  └── docker-compose.png # Rendered PNG image
109
120
  ```
110
121
 
122
+ With `--artifacts`, additional JSON files are saved:
123
+
124
+ ```
125
+ docs/diagrams/
126
+ ├── docker-compose.parsed.json # Parsed InfraGraph
127
+ ├── docker-compose.enhanced.json # Enhanced InfraGraph (LLM if enabled)
128
+ ├── docker-compose.elk-input.json # ELK input graph
129
+ └── docker-compose.elk-output.json # ELK output graph (with positions)
130
+ ```
131
+
111
132
  The `.excalidraw` file can be opened at [excalidraw.com](https://excalidraw.com) for editing.
112
133
 
113
134
  ## Supported Formats
@@ -153,6 +174,12 @@ iac-diagrams config show
153
174
 
154
175
  The key should start with `sk-or-`.
155
176
 
177
+ ## Appendix: Diagram Conventions
178
+
179
+ - Shapes: rectangles for application services, ellipses for databases/caches, diamonds for message queues
180
+ - Colors: blue=database, red=cache, green=storage, yellow=queue
181
+ - Layering: UI -> API -> worker -> data -> infrastructure
182
+
156
183
  ## License
157
184
 
158
185
  MIT
package/dist/index.js CHANGED
@@ -1596,9 +1596,37 @@ function infraGraphToElk(graph, options = {}) {
1596
1596
  }
1597
1597
 
1598
1598
  // ../core/src/elk/layout.ts
1599
+ import { createRequire } from "module";
1599
1600
  import ELK from "elkjs";
1601
+ var require2 = createRequire(import.meta.url);
1602
+ var loadWorkerModule = () => {
1603
+ const globalSelf = globalThis;
1604
+ const hadSelf = Object.prototype.hasOwnProperty.call(globalSelf, "self");
1605
+ const originalSelf = globalSelf.self;
1606
+ try {
1607
+ globalSelf.self = void 0;
1608
+ return require2("elkjs/lib/elk-worker.js");
1609
+ } finally {
1610
+ if (hadSelf) {
1611
+ globalSelf.self = originalSelf;
1612
+ } else {
1613
+ delete globalSelf.self;
1614
+ }
1615
+ }
1616
+ };
1617
+ var resolveWorkerConstructor = () => {
1618
+ const workerModule = loadWorkerModule();
1619
+ const maybeWorker = workerModule.Worker ?? workerModule.default ?? workerModule;
1620
+ if (typeof maybeWorker === "function") {
1621
+ return maybeWorker;
1622
+ }
1623
+ throw new Error("ELK worker module not available");
1624
+ };
1600
1625
  async function runLayout(graph) {
1601
- const elk = new ELK();
1626
+ const WorkerCtor = resolveWorkerConstructor();
1627
+ const elk = new ELK({
1628
+ workerFactory: (url) => new WorkerCtor(url)
1629
+ });
1602
1630
  const result = await elk.layout(graph);
1603
1631
  return {
1604
1632
  graph: result,
@@ -2507,6 +2535,7 @@ async function generate(inputPath, options = {}) {
2507
2535
  const verbose = options.verbose ?? false;
2508
2536
  const skipPng = options.png === false;
2509
2537
  const skipLlm = options.llm === false;
2538
+ const saveArtifacts = options.artifacts ?? false;
2510
2539
  if (!skipPng) {
2511
2540
  const browserCheck = await checkBrowserAvailability();
2512
2541
  if (!browserCheck.available) {
@@ -2556,12 +2585,21 @@ async function generate(inputPath, options = {}) {
2556
2585
  for (const file of detected) {
2557
2586
  console.log(`
2558
2587
  Generating diagram for: ${file.name}`);
2588
+ const baseName = file.name.replace(/\.(yml|yaml)$/i, "");
2589
+ const writeArtifact = async (suffix, data) => {
2590
+ if (!saveArtifacts) return;
2591
+ const artifactPath = join6(outputDir, `${baseName}.${suffix}.json`);
2592
+ await writeFile2(artifactPath, JSON.stringify(data, null, 2));
2593
+ console.log(` \x1B[32m\u2713\x1B[0m Saved: ${artifactPath}`);
2594
+ };
2559
2595
  if (verbose) console.log(" Step 1: Parsing...");
2560
- let graph = await parseIaC(file, verbose);
2596
+ const parsedGraph = await parseIaC(file, verbose);
2597
+ let graph = parsedGraph;
2561
2598
  if (verbose) {
2562
2599
  console.log(` Found ${graph.nodes.length} services`);
2563
2600
  console.log(` Found ${graph.edges.length} dependencies`);
2564
2601
  }
2602
+ await writeArtifact("parsed", parsedGraph);
2565
2603
  if (llmEnabled && apiKey) {
2566
2604
  if (verbose) console.log(" Step 2: Enhancing with LLM...");
2567
2605
  try {
@@ -2574,12 +2612,14 @@ Generating diagram for: ${file.name}`);
2574
2612
  } else if (verbose) {
2575
2613
  console.log(" Step 2: Skipping LLM enhancement");
2576
2614
  }
2615
+ await writeArtifact("enhanced", graph);
2577
2616
  if (verbose) console.log(" Step 3: Computing layout...");
2578
2617
  const elkConversion = infraGraphToElk(graph);
2579
2618
  const elkLayoutResult = await runLayout(elkConversion.graph);
2619
+ await writeArtifact("elk-input", elkConversion.graph);
2620
+ await writeArtifact("elk-output", elkLayoutResult.graph);
2580
2621
  if (verbose) console.log(" Step 4: Generating Excalidraw...");
2581
2622
  const excalidraw = renderWithElkLayout(graph, elkLayoutResult.graph);
2582
- const baseName = file.name.replace(/\.(yml|yaml)$/i, "");
2583
2623
  const excalidrawPath = join6(outputDir, `${baseName}.excalidraw`);
2584
2624
  await writeFile2(excalidrawPath, JSON.stringify(excalidraw, null, 2));
2585
2625
  console.log(` \x1B[32m\u2713\x1B[0m Saved: ${excalidrawPath}`);
@@ -2601,7 +2641,10 @@ var program = new Command2().name("iac-diagrams").description(
2601
2641
  "[path]",
2602
2642
  "File or directory to process (default: current directory)",
2603
2643
  "."
2604
- ).option("-o, --output <dir>", "Output directory", "./docs/diagrams").option("--no-llm", "Disable LLM enhancement").option("--no-png", "Skip PNG rendering (output .excalidraw only)").option("-v, --verbose", "Show detailed output").action(
2644
+ ).option("-o, --output <dir>", "Output directory", "./docs/diagrams").option("--no-llm", "Disable LLM enhancement").option("--no-png", "Skip PNG rendering (output .excalidraw only)").option(
2645
+ "--artifacts",
2646
+ "Save parsed/enhanced/elk JSON artifacts alongside outputs"
2647
+ ).option("-v, --verbose", "Show detailed output").action(
2605
2648
  async (path, options) => {
2606
2649
  await generate(path, options);
2607
2650
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clarity-tools/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Generate architecture diagrams from Infrastructure-as-Code files (Docker Compose, Helm charts)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -29,7 +29,8 @@
29
29
  },
30
30
  "repository": {
31
31
  "type": "git",
32
- "url": "https://github.com/BrennerSpear/colombo"
32
+ "url": "https://github.com/BrennerSpear/clarity",
33
+ "directory": "packages/cli"
33
34
  },
34
35
  "keywords": [
35
36
  "docker-compose",