@arach/arc 0.4.0 → 0.4.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.
- package/README.md +99 -11
- package/bin/arc-ascii.mjs +118 -0
- package/lib/arc.es.js +13987 -13720
- package/lib/arc.umd.js +76 -76
- package/lib/index.d.ts +4 -4
- package/package.json +22 -13
package/README.md
CHANGED
|
@@ -1,8 +1,62 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
1
3
|
# Arc
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
### Design architecture diagrams visually. Ship them as code.
|
|
6
|
+
|
|
7
|
+
Arc is a React component **and** a visual editor for building clean, themeable
|
|
8
|
+
architecture diagrams — then exporting them as **TypeScript, JSON, SVG, PNG, or
|
|
9
|
+
crisp ASCII**. Design in the canvas, drop the component in your app, or render
|
|
10
|
+
straight to text for a README. Same diagram, everywhere.
|
|
11
|
+
|
|
12
|
+
[](https://www.npmjs.com/package/@arach/arc)
|
|
13
|
+
[](./LICENSE)
|
|
14
|
+
[](./lib/index.d.ts)
|
|
15
|
+
|
|
16
|
+

|
|
17
|
+
|
|
18
|
+
<sub>Not a screenshot of a drawing tool — that's the config in <a href="#example-output">Example Output</a>, rendered live by <code><ArcDiagram /></code>.</sub>
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install @arach/arc
|
|
28
|
+
# or: bun add @arach/arc · pnpm add @arach/arc · yarn add @arach/arc
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`react`, `react-dom`, and `lucide-react` are peer dependencies.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
Render any diagram config as a polished, interactive component:
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { ArcDiagram } from '@arach/arc'
|
|
39
|
+
import type { ArcDiagramData } from '@arach/arc'
|
|
4
40
|
|
|
5
|
-
|
|
41
|
+
export function Architecture() {
|
|
42
|
+
return (
|
|
43
|
+
<ArcDiagram
|
|
44
|
+
data={diagram} // your ArcDiagramData (see below)
|
|
45
|
+
theme="default" // default · warm · cool · mono · ibm · palantir · anduril
|
|
46
|
+
mode="dark" // light · dark
|
|
47
|
+
defaultZoom="fit" // auto-fit to the container
|
|
48
|
+
/>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
You get pan/zoom, hover highlighting, light/dark modes, and seven color themes
|
|
54
|
+
out of the box. Prefer to design visually? Clone the repo and open the editor:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
git clone https://github.com/arach/arc && cd arc
|
|
58
|
+
bun install && bun dev # → http://localhost:5188
|
|
59
|
+
```
|
|
6
60
|
|
|
7
61
|
## Features
|
|
8
62
|
|
|
@@ -10,21 +64,15 @@ A visual diagram editor for creating architecture diagrams. Design visually, exp
|
|
|
10
64
|
- **Multiple Node Sizes** - Large, medium, small
|
|
11
65
|
- **Color Themes** - Violet, emerald, blue, amber, sky, zinc, rose, orange
|
|
12
66
|
- **Connector Styles** - Solid/dashed lines, labels, curved paths
|
|
13
|
-
- **Export Options** - TypeScript, JSON, SVG, PNG, shareable links
|
|
67
|
+
- **Export Options** - TypeScript, JSON, SVG, PNG, ASCII, shareable links
|
|
14
68
|
- **Interactive Canvas** - Infinite pan/zoom, grid snapping
|
|
15
69
|
- **Groups & Images** - Visual grouping, background images
|
|
16
70
|
- **Templates** - Quick-start layouts
|
|
17
71
|
|
|
18
|
-
## Getting Started
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
pnpm install
|
|
22
|
-
pnpm dev
|
|
23
|
-
```
|
|
24
|
-
|
|
25
72
|
## Example Output
|
|
26
73
|
|
|
27
|
-
Arc
|
|
74
|
+
Arc stores diagrams as plain, typed data — the same config that renders the
|
|
75
|
+
diagram at the top of this README:
|
|
28
76
|
|
|
29
77
|
```typescript
|
|
30
78
|
const diagram: ArcDiagramData = {
|
|
@@ -61,6 +109,46 @@ const diagram: ArcDiagramData = {
|
|
|
61
109
|
}
|
|
62
110
|
```
|
|
63
111
|
|
|
112
|
+
## ASCII Renderer
|
|
113
|
+
|
|
114
|
+
The same diagram renders as precise monospace text — for READMEs, CLI output, or anywhere you can't embed a React component:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
┌──────────────────┐
|
|
118
|
+
│ ◆ Auth │
|
|
119
|
+
┌▶│ JWT │
|
|
120
|
+
│ └──────────────────┘
|
|
121
|
+
│
|
|
122
|
+
┌──────────────────┐ ╔═════════════════════════╗ │
|
|
123
|
+
│ ◆ Client │ ║ ◆ API Gateway ║ │ ┌──────────────────┐ ┌──────────────────┐
|
|
124
|
+
│ React App │─┐ ║ Express ║ │ │ ◆ API │ SQL │ ◆ PostgreSQL │
|
|
125
|
+
│ │ └▶║ Load balanced ║─┴▶│ REST │──────▶│ Primary │
|
|
126
|
+
└──────────────────┘ ║ ║╌┐ └──────────────────┘ └──────────────────┘
|
|
127
|
+
╚═════════════════════════╝ ╎
|
|
128
|
+
╎
|
|
129
|
+
╎ ┌───────────┐
|
|
130
|
+
└▶│ ◆ Cache │
|
|
131
|
+
└───────────┘
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Programmatic
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
import { renderAscii } from '@arach/arc'
|
|
138
|
+
|
|
139
|
+
const ascii = renderAscii(diagram) // Unicode box-drawing
|
|
140
|
+
const plain = renderAscii(diagram, { charset: 'ascii' }) // +-- style
|
|
141
|
+
const narrow = renderAscii(diagram, { maxWidth: 80 }) // Auto-scale to 80 cols
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### CLI
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
bunx tsx bin/arc-ascii.mjs diagram.json
|
|
148
|
+
cat diagram.json | bunx tsx bin/arc-ascii.mjs
|
|
149
|
+
bunx tsx bin/arc-ascii.mjs diagram.json --charset ascii --max-width 80
|
|
150
|
+
```
|
|
151
|
+
|
|
64
152
|
## Requirements
|
|
65
153
|
|
|
66
154
|
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
|
+
}
|