@itsthecsguy/linework 0.1.1 → 0.1.3

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.
@@ -33,7 +33,14 @@ Never fall back to writing SVG or draw.io XML by hand. Tell the user what failed
33
33
  - `er`: database tables, their columns and how they relate.
34
34
 
35
35
  If the doc already has a Mermaid diagram, convert it instead of rewriting it: `linework import doc.md --block 1 -o docs/diagrams/x.drawio.svg`.
36
- 3. **Write the spec** to `/tmp/spec.yaml`, or pipe it on stdin with `-` as the file. Start from the closest file in `examples/` next to this guide: `checkout.yaml` (architecture), `serverless-aws.yaml` (architecture with AWS icons), `refund-flow.yaml` (flow), `payment-state.yaml` (state), `pay-sequence.yaml` (sequence), `billing-er.yaml` (ER). The `.drawio.svg` is the source of truth, so you don't need to keep the YAML.
36
+ 3. **Write the spec** to `/tmp/spec.yaml`, or pipe it on stdin with `-` as the file. Start from the closest file in `examples/` next to this guide:
37
+ - architecture: `checkout.yaml` (small), `platform.yaml` (clients, nested groups, 17 nodes), `serverless-aws.yaml` (AWS icons), `gcp-ingest.yaml` (GCP icons)
38
+ - flow: `refund-flow.yaml` (branches), `deploy-flow.yaml` (a retry loop back to an earlier step)
39
+ - state: `payment-state.yaml`, `job-state.yaml` (pause/resume pairs and a self-transition)
40
+ - sequence: `pay-sequence.yaml` (alt, note), `auth-seq.yaml` (loop with a nested opt)
41
+ - ER: `billing-er.yaml` (small), `shop-er.yaml` (7 tables, composite keys)
42
+
43
+ The `.drawio.svg` is the source of truth, so you don't need to keep the YAML.
37
44
  4. **Build with a preview:**
38
45
  ```bash
39
46
  linework build /tmp/spec.yaml -o docs/diagrams/checkout.drawio.svg --png /tmp/checkout.png
@@ -78,7 +85,7 @@ edges: # "from ARROW to: label"
78
85
  - `soft`: borderless pastel cards, tinted by kind. For slides and docs that want color coding.
79
86
  - `dark`: for dark-mode docs and slides.
80
87
  - `sketch`: hand-drawn lines and handwriting. For early proposals ("this is a draft") and whiteboard-style explainers.
81
- - `blueprint`: light lines on deep blue, monospace. For technical deep dives that want a distinct look.
88
+ - `blueprint`: blue ink on pale drafting paper, monospace. For technical deep dives that want a distinct look.
82
89
  - `c4`: C4-model conventions; labels each box with its element type.
83
90
  - Color is for meaning, so most nodes stay neutral:
84
91
  - `highlight: true` on a node, group or participant, or `==>` on an edge or message, makes it the first thing a reader sees. Highlight the one path or component the surrounding text is about: often one node and the 2 or 3 edges into and out of it. `build` warns when you highlight so much that nothing stands out.
@@ -0,0 +1,35 @@
1
+ type: sequence
2
+ title: OAuth login with refresh
3
+ participants:
4
+ user: { label: User, kind: person }
5
+ app: { label: SPA, kind: client }
6
+ bff: { label: BFF, tech: Node.js }
7
+ idp: { label: Identity provider, kind: external }
8
+ api: { label: Resource API }
9
+ cache: { label: Token cache, kind: cache }
10
+ messages:
11
+ - user -> app: Sign in
12
+ - app -> bff: GET /login
13
+ - bff --> app: 302 to /authorize
14
+ - app -> idp: /authorize?code_challenge=...
15
+ - idp -> user: Login form
16
+ - user -> idp: Credentials + MFA
17
+ - idp --> app: redirect with code
18
+ - app -> bff: GET /callback?code
19
+ - bff ==> idp: POST /token (code, verifier)
20
+ - idp --> bff: access + refresh tokens
21
+ - bff -> cache: store refresh token
22
+ - note right of bff: tokens never reach the browser
23
+ - bff --> app: Set-Cookie session
24
+ - loop: every API call
25
+ do:
26
+ - app -> bff: GET /orders
27
+ - opt: access token expired
28
+ do:
29
+ - bff -> cache: read refresh token
30
+ - bff -> idp: POST /token (refresh)
31
+ - idp --> bff: new access token
32
+ - bff -> api: GET /orders + Bearer
33
+ - api -> api: validate JWT
34
+ - api --> bff: 200 orders
35
+ - bff --> app: orders
@@ -0,0 +1,32 @@
1
+ type: flow
2
+ title: Deploy pipeline
3
+ nodes:
4
+ push: { label: Push to main, kind: terminal }
5
+ build: { label: Build and unit test }
6
+ ok: { label: Tests pass?, kind: decision }
7
+ fix: { label: Notify author, kind: error }
8
+ stage: { label: Deploy to staging }
9
+ smoke: { label: Run smoke tests against staging }
10
+ smokeok: { label: Healthy?, kind: decision }
11
+ canary: { label: Canary 5% of traffic }
12
+ metrics: { label: Error rate under 0.1%?, kind: decision }
13
+ roll: { label: Roll back canary, kind: error }
14
+ full: { label: Promote to 100% }
15
+ done: { label: Released, kind: terminal }
16
+ artifact: { label: Container image, kind: data }
17
+ edges:
18
+ - push -> build
19
+ - build -> ok
20
+ - ok -> fix: "no"
21
+ - ok -> artifact: "yes"
22
+ - artifact -> stage
23
+ - stage -> smoke
24
+ - smoke -> smokeok
25
+ - smokeok -> canary: "yes"
26
+ - smokeok -> roll: "no"
27
+ - canary -> metrics
28
+ - metrics -> full: "yes"
29
+ - metrics -> roll: "no"
30
+ - roll -> fix
31
+ - fix -> build: retry after fix
32
+ - full -> done
@@ -0,0 +1,21 @@
1
+ type: architecture
2
+ title: Ingest pipeline on GCP
3
+ groups:
4
+ gcp: { label: Google Cloud project }
5
+ nodes:
6
+ devices: { label: Sensors, kind: client, tech: MQTT }
7
+ lb: { label: Load balancer, icon: gcp.cloud_load_balancing, in: gcp }
8
+ run: { label: Ingest API, icon: gcp.cloud_run, tech: Cloud Run, in: gcp }
9
+ ps: { label: telemetry, kind: queue, icon: gcp.pubsub, tech: Pub/Sub, in: gcp }
10
+ df: { label: Stream job, icon: gcp.dataflow, tech: Dataflow, in: gcp }
11
+ bq: { label: Warehouse, kind: database, icon: gcp.bigquery, tech: BigQuery, in: gcp }
12
+ gcs: { label: Raw archive, kind: storage, icon: gcp.cloud_storage, tech: GCS, in: gcp }
13
+ looker: { label: Looker, kind: external, tech: Dashboards }
14
+ edges:
15
+ - devices -> lb: HTTPS
16
+ - lb -> run
17
+ - run -.-> ps: publish
18
+ - ps -.-> df: subscribe
19
+ - df -> bq: stream insert
20
+ - df -> gcs: write Avro
21
+ - looker -> bq: SQL
@@ -0,0 +1,25 @@
1
+ type: state
2
+ title: Background job
3
+ nodes:
4
+ queued: {}
5
+ running: {}
6
+ paused: {}
7
+ retrying: { label: Waiting to retry }
8
+ succeeded: { kind: success }
9
+ failed: { kind: error }
10
+ cancelled: {}
11
+ edges:
12
+ - "[*] -> queued"
13
+ - queued -> running: worker picks up
14
+ - running -> succeeded: exit 0
15
+ - running -> retrying: error, attempts < 5
16
+ - retrying -> queued: backoff elapsed
17
+ - running -> failed: error, attempts = 5
18
+ - running -> paused: pause
19
+ - paused -> running: resume
20
+ - queued -> cancelled: cancel
21
+ - paused -> cancelled: cancel
22
+ - running -> running: heartbeat
23
+ - "succeeded -> [*]"
24
+ - "failed -> [*]"
25
+ - "cancelled -> [*]"
@@ -0,0 +1,45 @@
1
+ type: architecture
2
+ title: Platform
3
+ groups:
4
+ edge: { label: Edge }
5
+ cluster: { label: Kubernetes cluster }
6
+ core: { label: Core services, in: cluster }
7
+ data: { label: Data tier }
8
+ nodes:
9
+ user: { label: Customer, kind: person }
10
+ admin: { label: Support agent, kind: person }
11
+ mobile: { label: Mobile app, kind: client, tech: Swift }
12
+ web: { label: Web dashboard, kind: client, tech: React }
13
+ cdn: { label: CDN, kind: cache, tech: CloudFront, in: edge }
14
+ gw: { label: API gateway, tech: Kong, in: edge }
15
+ auth: { label: Auth service, tech: Go, in: core }
16
+ orders: { label: Orders service, tech: Kotlin, in: core, highlight: true }
17
+ search: { label: Search service, tech: Rust, in: core }
18
+ notify: { label: Notification worker, kind: function, tech: Node.js, in: cluster }
19
+ bus: { label: domain-events, kind: queue, tech: Kafka, in: cluster }
20
+ pg: { label: Orders DB, kind: database, tech: Postgres 16, in: data }
21
+ es: { label: Search index, kind: database, tech: OpenSearch, in: data }
22
+ redis: { label: Session store, kind: cache, tech: Redis, in: data }
23
+ s3: { label: Media bucket, kind: storage, tech: S3, in: data }
24
+ twilio: { label: Twilio, kind: external, tech: SMS }
25
+ idp: { label: Okta, kind: external, tech: OIDC }
26
+ edges:
27
+ - user -> mobile
28
+ - user -> web
29
+ - admin -> web
30
+ - mobile -> cdn: assets
31
+ - web -> cdn: assets
32
+ - mobile ==> gw: HTTPS
33
+ - web ==> gw: HTTPS
34
+ - cdn -> s3: origin fetch
35
+ - gw -> auth: verify token
36
+ - auth -> idp: OIDC
37
+ - auth -> redis: sessions
38
+ - gw ==> orders: gRPC
39
+ - gw -> search: gRPC
40
+ - orders ==> pg: SQL
41
+ - orders -.-> bus: OrderPlaced
42
+ - bus -.-> search: reindex
43
+ - bus -.-> notify: consume
44
+ - search -> es: query
45
+ - notify -> twilio: send SMS
@@ -0,0 +1,26 @@
1
+ type: er
2
+ title: Storefront schema
3
+ nodes:
4
+ customers:
5
+ fields: [id: uuid pk, email: text unique, name: text, created_at: timestamptz]
6
+ addresses:
7
+ fields: [id: uuid pk, customer_id: uuid fk, line1: text, city: text, country: char(2)]
8
+ orders:
9
+ fields: [id: uuid pk, customer_id: uuid fk, shipping_address_id: uuid fk, status: order_status, total_cents: bigint, placed_at: timestamptz null]
10
+ order_items:
11
+ fields: [order_id: uuid pk fk, product_id: uuid pk fk, quantity: int, unit_price_cents: bigint]
12
+ products:
13
+ fields: [id: uuid pk, sku: text unique, title: text, price_cents: bigint]
14
+ inventory:
15
+ fields: [product_id: uuid pk fk, warehouse: text pk, on_hand: int]
16
+ payments:
17
+ kind: external
18
+ fields: [id: text pk, order_id: uuid fk, provider: text]
19
+ edges:
20
+ - addresses }o--|| customers: has
21
+ - orders }o--|| customers: placed by
22
+ - orders }o--|| addresses: ships to
23
+ - order_items }|--|| orders: contains
24
+ - order_items }o--|| products: of
25
+ - inventory }o--|| products: stocks
26
+ - payments |o..|| orders: pays
@@ -40,9 +40,9 @@ nodes:
40
40
  | `clean` | white boxes with hairline borders, groups drawn as gray grounds, cobalt accent. Nodes are neutral unless the kind means something (error, success). | IBM Plex Sans |
41
41
  | `soft` | borderless pastel cards, each kind its own tint | IBM Plex Sans |
42
42
  | `dark` | `clean` in GitHub's dark colors, so it sits flush on a dark README | IBM Plex Sans |
43
- | `sketch` | hand-drawn strokes, pastel fills, red accent | Kalam (handwriting) |
44
- | `blueprint` | light lines on deep blue, yellow accent, drafting capitals for group titles | IBM Plex Mono |
45
- | `c4` | C4-PlantUML colors; each box says its element type | IBM Plex Sans |
43
+ | `sketch` | hand-drawn strokes, pastel fills, blue accent | Kalam (handwriting) |
44
+ | `blueprint` | blue ink on pale drafting paper, drafting capitals for group titles | IBM Plex Mono |
45
+ | `c4` | C4's colors (dark person, blue containers, gray external systems) in quiet tones; each box says its element type | IBM Plex Sans |
46
46
 
47
47
  The "drawn as" columns below describe `soft`. In `clean`, `dark` and `blueprint`, kinds differ by shape and dash only, and color comes from `highlight`, `color` and the error/success kinds.
48
48
 
@@ -38,9 +38,17 @@ Linework handles the layout and the look. These rules are about content, which i
38
38
  - **Keep error and success kinds for real errors and successes.** They're red and green in every style.
39
39
  - **Pick the style for the medium**: `clean` for docs and READMEs, `dark` for dark-mode pages, `soft` for slides, `sketch` for early drafts, `blueprint` for technical deep dives. Use one style across all the diagrams in a doc.
40
40
 
41
+ ## Order
42
+
43
+ Layout reads the spec top to bottom, so the order you write things in shows up in the picture.
44
+
45
+ - **List nodes and edges in reading order**: the entry point first, then each step as the request or flow reaches it. A flow's main path then runs straight down, and an edge back to an earlier node (a retry, a resume) is drawn as the loop it is.
46
+ - **Write a reply after its call** (`api -> stripe`, then `stripe -.-> api`). The pair is drawn side by side.
47
+ - **In ER, name foreign keys after the table they point at**: `customer_id` for `customers`, `shipping_address_id` for `addresses`. The relationship line then attaches to that row and to the other table's primary key. A key named anything else attaches to the table as a whole.
48
+
41
49
  ## Direction
42
50
 
43
- - Leave out `direction` on the first build. `auto` tries both and keeps the one that fits a doc page, which is about 800px wide.
51
+ - Leave out `direction` on the first build. `auto` tries both and keeps the one that fits a doc page, which is about 800px wide. ER diagrams always run left to right, since relationships attach to the sides of the key rows.
44
52
  - Set it only after looking at the result, and only if it reads wrong. A short linear pipeline of 5 or fewer steps can read better as LR.
45
53
  - Don't force LR on a diagram with more than about 6 nodes in a row. It comes out 1,500px or more wide, and embedded in a doc its text shrinks to unreadable. `check` warns about this as `too-wide`.
46
54