@arach/arc 0.3.1 → 0.4.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.
package/README.md CHANGED
@@ -61,6 +61,46 @@ const diagram: ArcDiagramData = {
61
61
  }
62
62
  ```
63
63
 
64
+ ## ASCII Renderer
65
+
66
+ The same diagram renders as precise monospace text — for READMEs, CLI output, or anywhere you can't embed a React component:
67
+
68
+ ```
69
+ ┌──────────────────┐
70
+ │ ◆ Auth │
71
+ ┌▶│ JWT │
72
+ │ └──────────────────┘
73
+
74
+ ┌──────────────────┐ ╔═════════════════════════╗ │
75
+ │ ◆ Client │ ║ ◆ API Gateway ║ │ ┌──────────────────┐ ┌──────────────────┐
76
+ │ React App │─┐ ║ Express ║ │ │ ◆ API │ SQL │ ◆ PostgreSQL │
77
+ │ │ └▶║ Load balanced ║─┴▶│ REST │──────▶│ Primary │
78
+ └──────────────────┘ ║ ║╌┐ └──────────────────┘ └──────────────────┘
79
+ ╚═════════════════════════╝ ╎
80
+
81
+ ╎ ┌───────────┐
82
+ └▶│ ◆ Cache │
83
+ └───────────┘
84
+ ```
85
+
86
+ ### Programmatic
87
+
88
+ ```typescript
89
+ import { renderAscii } from '@arach/arc'
90
+
91
+ const ascii = renderAscii(diagram) // Unicode box-drawing
92
+ const plain = renderAscii(diagram, { charset: 'ascii' }) // +-- style
93
+ const narrow = renderAscii(diagram, { maxWidth: 80 }) // Auto-scale to 80 cols
94
+ ```
95
+
96
+ ### CLI
97
+
98
+ ```bash
99
+ bunx tsx bin/arc-ascii.mjs diagram.json
100
+ cat diagram.json | bunx tsx bin/arc-ascii.mjs
101
+ bunx tsx bin/arc-ascii.mjs diagram.json --charset ascii --max-width 80
102
+ ```
103
+
64
104
  ## Requirements
65
105
 
66
106
  The `ArcDiagram` player component requires:
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * arc-ascii — Render Arc diagram JSON as monospace ASCII art.
5
+ *
6
+ * Usage:
7
+ * bunx @arach/arc diagram.json
8
+ * cat diagram.json | bunx @arach/arc
9
+ * bunx @arach/arc diagram.json --charset ascii
10
+ * bunx @arach/arc diagram.json --max-width 80
11
+ */
12
+
13
+ import { readFileSync } from 'node:fs'
14
+ import { createRequire } from 'node:module'
15
+ import { dirname, resolve } from 'node:path'
16
+ import { fileURLToPath } from 'node:url'
17
+
18
+ const __dirname = dirname(fileURLToPath(import.meta.url))
19
+
20
+ // Import renderAscii from the built lib (works when installed from npm)
21
+ // or from source (works during local dev with tsx)
22
+ let renderAscii
23
+ try {
24
+ const lib = await import(resolve(__dirname, '..', 'lib', 'arc.es.js'))
25
+ renderAscii = lib.renderAscii
26
+ } catch {
27
+ const src = await import(resolve(__dirname, '..', 'src', 'utils', 'asciiRenderer.ts'))
28
+ renderAscii = src.renderAscii
29
+ }
30
+
31
+ // ── Parse args ──────────────────────────────
32
+
33
+ const args = process.argv.slice(2)
34
+ let filePath = null
35
+ const opts = {}
36
+
37
+ for (let i = 0; i < args.length; i++) {
38
+ const a = args[i]
39
+ if (a === '--charset' || a === '-c') { opts.charset = args[++i]; continue }
40
+ if (a === '--max-width' || a === '-w') { opts.maxWidth = Number(args[++i]); continue }
41
+ if (a === '--no-labels') { opts.showLabels = false; continue }
42
+ if (a === '--scale-x') { opts.scaleX = Number(args[++i]); continue }
43
+ if (a === '--scale-y') { opts.scaleY = Number(args[++i]); continue }
44
+ if (a === '--help' || a === '-h') { printHelp(); process.exit(0) }
45
+ if (!a.startsWith('-')) filePath = a
46
+ }
47
+
48
+ // ── Read input ──────────────────────────────
49
+
50
+ let json
51
+ try {
52
+ if (filePath) {
53
+ json = readFileSync(filePath, 'utf-8')
54
+ } else if (!process.stdin.isTTY) {
55
+ const chunks = []
56
+ for await (const chunk of process.stdin) chunks.push(chunk)
57
+ json = Buffer.concat(chunks).toString('utf-8')
58
+ } else {
59
+ printHelp()
60
+ process.exit(1)
61
+ }
62
+ } catch (err) {
63
+ console.error(`Error reading input: ${err.message}`)
64
+ process.exit(1)
65
+ }
66
+
67
+ // ── Parse & render ──────────────────────────
68
+
69
+ let data
70
+ try {
71
+ data = JSON.parse(json)
72
+ } catch {
73
+ const match = json.match(/(?:export\s+default\s+|(?:const|let|var)\s+\w+(?::\s*\S+)?\s*=\s*)(\{[\s\S]*\})/)
74
+ if (match) {
75
+ try {
76
+ const normalized = match[1]
77
+ .replace(/'/g, '"')
78
+ .replace(/,(\s*[}\]])/g, '$1')
79
+ .replace(/([{,]\s*)(\w+)(\s*:)/g, '$1"$2"$3')
80
+ data = JSON.parse(normalized)
81
+ } catch {
82
+ console.error('Error: Could not parse diagram data.')
83
+ process.exit(1)
84
+ }
85
+ } else {
86
+ console.error('Error: Input is not valid JSON or a recognizable diagram module.')
87
+ process.exit(1)
88
+ }
89
+ }
90
+
91
+ if (!data.layout || !data.nodes || !data.nodeData) {
92
+ console.error('Error: Input does not look like ArcDiagramData (missing layout, nodes, or nodeData).')
93
+ process.exit(1)
94
+ }
95
+
96
+ if (!data.connectorStyles) data.connectorStyles = {}
97
+
98
+ console.log(renderAscii(data, opts))
99
+
100
+ // ── Help ────────────────────────────────────
101
+
102
+ function printHelp() {
103
+ console.log(`
104
+ arc-ascii — Render Arc diagrams as ASCII art
105
+
106
+ Usage:
107
+ bunx @arach/arc <file.json> Read diagram from file
108
+ cat diagram.json | bunx @arach/arc Read from stdin
109
+
110
+ Options:
111
+ -c, --charset <unicode|ascii> Character set (default: unicode)
112
+ -w, --max-width <cols> Max output width in columns
113
+ --no-labels Hide connector labels
114
+ --scale-x <n> Pixels per char horizontally (default: 8)
115
+ --scale-y <n> Pixels per char vertically (default: 16)
116
+ -h, --help Show this help
117
+ `.trim())
118
+ }