create-idocs 0.4.0 → 0.6.0
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/package.json +2 -2
- package/template/.claude/skills/idocs/SKILL.md +1 -1
- package/template/.claude/skills/idocs/assets/examples/shop.diagram.yaml +1 -1
- package/template/.claude/skills/idocs/references/format.md +54 -6
- package/template/diagrams/diagram.schema.json +93 -0
- package/template/package.json +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-idocs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Scaffold a docs site with interactive diagrams: npm create idocs@latest my-docs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@the-package-labs/idocs-core": "^0.
|
|
28
|
+
"@the-package-labs/idocs-core": "^0.6.0"
|
|
29
29
|
},
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"scripts": {
|
|
@@ -69,7 +69,7 @@ scenarios:
|
|
|
69
69
|
- api -> browser: 200 OK
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
Click-through documentation for a box goes in `diagrams/<name>/nodes/<id>.md` (markdown, tables and code fences work). Long scenarios can live in `diagrams/<name>/scenarios/<id>.yaml`.
|
|
72
|
+
Click-through documentation for a box goes in `diagrams/<name>/nodes/<id>.md` (markdown, tables and code fences work). Every code fence gets a Copy button, and in a shell, text or config fence a `{name}` or `<name>` is a value the reader fills in before copying (`\{name}` writes the braces literally; `vars` and `novars` after the language turn it on or off for other languages). Long scenarios can live in `diagrams/<name>/scenarios/<id>.yaml`.
|
|
73
73
|
|
|
74
74
|
On a page (`src/content/docs/*.mdx`):
|
|
75
75
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
title: Online store
|
|
4
4
|
description: |
|
|
5
5
|
How a shopper's request reaches the store and what the backend does with it.
|
|
6
|
-
Pick a scenario
|
|
6
|
+
Pick a scenario on the bar under the diagram and press play.
|
|
7
7
|
|
|
8
8
|
groups:
|
|
9
9
|
backend:
|
|
@@ -11,7 +11,7 @@ diagrams/
|
|
|
11
11
|
scenarios/<id>.yaml optional: a long scenario in its own file; the file name is its id
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
Top-level keys: `title` (required), `description`, `nodes` (required), `groups`, `edges`, `views`, `scenarios`, `kinds`, `edgeKinds`. Unknown keys are errors with a "did you mean" hint.
|
|
14
|
+
Top-level keys: `title` (required), `description`, `nodes` (required), `groups`, `edges`, `views`, `scenarios`, `defaults`, `kinds`, `edgeKinds`. Unknown keys are errors with a "did you mean" hint.
|
|
15
15
|
|
|
16
16
|
## Nodes
|
|
17
17
|
|
|
@@ -21,7 +21,9 @@ Top-level keys: `title` (required), `description`, `nodes` (required), `groups`,
|
|
|
21
21
|
|---|---|
|
|
22
22
|
| `title` | Display name. Defaults to the id. |
|
|
23
23
|
| `sub` | One mono line under the title: port, stack, version. |
|
|
24
|
+
| `pill` | Short label in the card header: `TABLE`, `ES INDEX`. |
|
|
24
25
|
| `lines` | List of short body lines in the card. |
|
|
26
|
+
| `fields` | Makes the card an entity: one row per field. `- id: { type: uuid, key: true }`, `- email: text`, `- customer_id: { type: uuid, ref: customers.id }`, or just `- name`. See "Entities" below. |
|
|
25
27
|
| `icon` | `postgresql` (looks in brand logos, then monochrome brand marks, then Lucide), `logos:redis`, `simple-icons:keycloak`, `lucide:server`, or a path to your own SVG relative to the diagram folder. |
|
|
26
28
|
| `kind` | Gives a default icon and colour family (list below). |
|
|
27
29
|
| `family` | Accent colour: `blue amber violet green teal red slate`. Overrides the kind's. |
|
|
@@ -30,7 +32,7 @@ Top-level keys: `title` (required), `description`, `nodes` (required), `groups`,
|
|
|
30
32
|
| `badge` | A number or short string shown on the card corner. |
|
|
31
33
|
| `uses` | List of short tags drawn as "uses: a · b". Entries that match a node id become links in the drawer. |
|
|
32
34
|
| `chips` | Small boxes inside the card, such as virtual hosts: `- { label: app.*, sub: "→ backend :9100" }`. |
|
|
33
|
-
| `w` | Card width in px (default 178). Narrow it in dense rows. |
|
|
35
|
+
| `w` | Card width in px (default 178, or 280 with `fields`). Narrow it in dense rows. |
|
|
34
36
|
| `description` | Markdown for the detail drawer, inline. |
|
|
35
37
|
| `doc` | Path to a markdown file for the drawer. Defaults to `nodes/<id>.md` when that file exists. |
|
|
36
38
|
| `links` | `- { label: Runbook, url: https://... }` |
|
|
@@ -38,7 +40,37 @@ Top-level keys: `title` (required), `description`, `nodes` (required), `groups`,
|
|
|
38
40
|
| `tags` | Free-form tags. |
|
|
39
41
|
| `diagram` | Name of another diagram (its folder under `diagrams/`) that shows the inside of this node: `diagram: payments`. The card gets **Expand** (show it in place, as a group around the whole inner diagram) and **Open** (move into it, with a trail and Back button). Clicking the node shows the inner diagram as a picture in the drawer. Long form: `diagram: { name: payments, view: refunds, scenario: pay, mode: both, expanded: false }`. See "Nested diagrams" below. |
|
|
40
42
|
|
|
41
|
-
Node kinds: `client user ui external service gateway worker container function database cache storage queue agent network vm auth monitor`. Add or override your own with a top-level `kinds:` map: `ledger: { icon: lucide:book-open, family: amber }`.
|
|
43
|
+
Node kinds: `client user ui external service gateway worker container function database cache storage queue agent network vm auth monitor entity`. Add or override your own with a top-level `kinds:` map: `ledger: { icon: lucide:book-open, family: amber }`.
|
|
44
|
+
|
|
45
|
+
## Entities
|
|
46
|
+
|
|
47
|
+
A node with `fields` is an entity: a table, a collection, an index. Use `kind: entity` (blue, a table icon); the card is wider by default.
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
nodes:
|
|
51
|
+
orders:
|
|
52
|
+
kind: entity
|
|
53
|
+
title: orders
|
|
54
|
+
pill: TABLE
|
|
55
|
+
lines: [One row per checkout.]
|
|
56
|
+
fields:
|
|
57
|
+
- id: { type: uuid, key: true } # `#` in front
|
|
58
|
+
- customer_id: { type: uuid, ref: customers.id } # blue, with an arrow; draws the relation
|
|
59
|
+
- status: pending | paid | shipped
|
|
60
|
+
- total_cents: { type: integer, note: In the smallest currency unit. }
|
|
61
|
+
- placed_at: timestamp
|
|
62
|
+
- notes # a field with no type
|
|
63
|
+
customers: { kind: entity, title: customers, fields: [{ id: { type: uuid, key: true } }] }
|
|
64
|
+
edges:
|
|
65
|
+
- orders.customer_id -> customers.id: N:1 # the same edge by hand, to give it a label
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- **One field per list item**: `- name`, `- name: type` or `- name: { type, key, ref, note }`. A field is never written as `{ name: id, type: uuid }`, because a field called `name` would be ambiguous.
|
|
69
|
+
- **`ref`** is a node id or `node.field`. Each one draws a `relation` edge from this entity to that one, unless you write the same edge by hand (then yours wins, which is how you add a label such as `N:1`). A field that points at its own entity is marked but draws nothing.
|
|
70
|
+
- **Edges** may name a field on either end: `orders.customer_id -> customers.id`. Names with dots (`meta.version`) work; a node id always wins over a split. Names with spaces need the `{ from: ..., to: ... }` form.
|
|
71
|
+
- An edge between two entities is a `relation` unless it has another `kind`.
|
|
72
|
+
- The line runs between the two cards. The field names say which columns the relation is about.
|
|
73
|
+
- Entities are plain nodes: `in:`, `status`, `uses`, `description` and scenarios all work. A dashed look for something you do not own is `status: optional`.
|
|
42
74
|
|
|
43
75
|
## Groups
|
|
44
76
|
|
|
@@ -71,9 +103,9 @@ edges:
|
|
|
71
103
|
|
|
72
104
|
| Field | Meaning |
|
|
73
105
|
|---|---|
|
|
74
|
-
| `from`, `to` | Node ids (required in the object form). |
|
|
106
|
+
| `from`, `to` | Node ids (required in the object form). For an entity, `node.field` names the field the relation is about. |
|
|
75
107
|
| `label` | Short: a protocol, route or event name. |
|
|
76
|
-
| `kind` | Line style: `http` (default), `channel` (persistent: websocket, gRPC), `tunnel`, `queue`, `ws`, `data`, or one you define in `edgeKinds:`. |
|
|
108
|
+
| `kind` | Line style: `http` (default), `channel` (persistent: websocket, gRPC), `tunnel`, `queue`, `ws`, `data`, `relation` (between entities), or one you define in `edgeKinds:`. |
|
|
77
109
|
| `both` | Arrow at both ends (same as `<->`). |
|
|
78
110
|
| `hidden` | Not drawn and not in the legend, but scenarios can fly along it. Use it for relationships a scenario needs and the picture does not. |
|
|
79
111
|
| `status` | As for nodes. |
|
|
@@ -95,7 +127,7 @@ views:
|
|
|
95
127
|
overview:
|
|
96
128
|
title: Overview
|
|
97
129
|
keys: true # letter keys on edges
|
|
98
|
-
interfaces: true # table of every edge under the diagram (key, from → to, kind, auth, payload)
|
|
130
|
+
interfaces: true # table of every edge under the diagram (key, from → to, kind, auth, payload), folded until opened
|
|
99
131
|
summary: Markdown shown above the diagram.
|
|
100
132
|
backend:
|
|
101
133
|
title: Backend only
|
|
@@ -106,6 +138,22 @@ views:
|
|
|
106
138
|
|
|
107
139
|
Edges whose two ends are both in the view are included. A scenario plays on the first view unless it sets `view:`; every node it uses must be in that view.
|
|
108
140
|
|
|
141
|
+
## Defaults
|
|
142
|
+
|
|
143
|
+
By default a diagram opens on its first view, on its overview, with every scenario waiting to be chosen. `defaults:` changes how this one opens; every field is optional.
|
|
144
|
+
|
|
145
|
+
```yaml
|
|
146
|
+
defaults:
|
|
147
|
+
scenario: sign-in # selected first; its view comes with it. It waits for play unless autoplay is on
|
|
148
|
+
view: overview # shown first (when it names a scenario too, that scenario must play on this view)
|
|
149
|
+
mode: sequence # flow, sequence or story: how a scenario with no `mode:` of its own is drawn
|
|
150
|
+
sidebar: false # the panel over the picture (outline, views) starts folded to a button
|
|
151
|
+
subtitles: false # the bar under the picture shows no title and description for the step
|
|
152
|
+
autoplay: true # play `scenario` once the diagram is on screen (needs `scenario`)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
A page's own props on `<Diagram>` (`view`, `scenario`, `mode`, `autoplay`, `sidebar`, `subtitles`) win over these, and a scenario's own `mode:` wins over `defaults.mode`. Use it for the way a diagram nearly always opens, not to hide anything: the reader can still reach every view and scenario.
|
|
156
|
+
|
|
109
157
|
## Nested diagrams
|
|
110
158
|
|
|
111
159
|
A node can hold a whole diagram of its own. Write the inside as an ordinary diagram in its own folder, then point the node at it:
|
|
@@ -13,6 +13,44 @@
|
|
|
13
13
|
"description": "Markdown shown above the first view.",
|
|
14
14
|
"type": "string"
|
|
15
15
|
},
|
|
16
|
+
"defaults": {
|
|
17
|
+
"description": "How the diagram opens: its view, scenario and mode, and whether the panel and subtitles show. A page can still choose otherwise with the props of `<Diagram>`.",
|
|
18
|
+
"type": "object",
|
|
19
|
+
"properties": {
|
|
20
|
+
"view": {
|
|
21
|
+
"description": "View shown first. Defaults to the view of `scenario`, or else the first view.",
|
|
22
|
+
"type": "string",
|
|
23
|
+
"pattern": "^[A-Za-z0-9_.-]+$"
|
|
24
|
+
},
|
|
25
|
+
"scenario": {
|
|
26
|
+
"description": "Scenario selected first. Without it the diagram opens on its overview. It does not play until a reader presses play, unless `autoplay` is on.",
|
|
27
|
+
"type": "string",
|
|
28
|
+
"pattern": "^[A-Za-z0-9_.-]+$"
|
|
29
|
+
},
|
|
30
|
+
"mode": {
|
|
31
|
+
"description": "How a scenario is drawn when it has no `mode` of its own: packets over the diagram, a sequence diagram, or a swimlane story.",
|
|
32
|
+
"type": "string",
|
|
33
|
+
"enum": [
|
|
34
|
+
"flow",
|
|
35
|
+
"sequence",
|
|
36
|
+
"story"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
"sidebar": {
|
|
40
|
+
"description": "Whether the panel over the picture starts open. By default it does when there is a scenario or another view to choose, and the frame is wide enough.",
|
|
41
|
+
"type": "boolean"
|
|
42
|
+
},
|
|
43
|
+
"subtitles": {
|
|
44
|
+
"description": "Words over the picture saying what the scenario is doing. On by default.",
|
|
45
|
+
"type": "boolean"
|
|
46
|
+
},
|
|
47
|
+
"autoplay": {
|
|
48
|
+
"description": "Play `scenario` as soon as the diagram is on screen. Needs `scenario`, and is ignored when the system asks for reduced motion.",
|
|
49
|
+
"type": "boolean"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"additionalProperties": false
|
|
53
|
+
},
|
|
16
54
|
"kinds": {
|
|
17
55
|
"type": "object",
|
|
18
56
|
"propertyNames": {
|
|
@@ -185,6 +223,10 @@
|
|
|
185
223
|
"description": "One line under the title, rendered in mono (ports, stack, version).",
|
|
186
224
|
"type": "string"
|
|
187
225
|
},
|
|
226
|
+
"pill": {
|
|
227
|
+
"description": "Short label in the card header, like `TABLE` or `ES INDEX`.",
|
|
228
|
+
"type": "string"
|
|
229
|
+
},
|
|
188
230
|
"lines": {
|
|
189
231
|
"description": "Short body lines inside the card.",
|
|
190
232
|
"type": "array",
|
|
@@ -192,6 +234,57 @@
|
|
|
192
234
|
"type": "string"
|
|
193
235
|
}
|
|
194
236
|
},
|
|
237
|
+
"fields": {
|
|
238
|
+
"description": "Makes the card an entity: a table of fields, each `name: type`. `ref` points a field at another entity.",
|
|
239
|
+
"type": "array",
|
|
240
|
+
"items": {
|
|
241
|
+
"anyOf": [
|
|
242
|
+
{
|
|
243
|
+
"type": "string",
|
|
244
|
+
"minLength": 1
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"type": "object",
|
|
248
|
+
"propertyNames": {
|
|
249
|
+
"type": "string",
|
|
250
|
+
"minLength": 1
|
|
251
|
+
},
|
|
252
|
+
"additionalProperties": {
|
|
253
|
+
"anyOf": [
|
|
254
|
+
{
|
|
255
|
+
"type": "string"
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"type": "null"
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"type": "object",
|
|
262
|
+
"properties": {
|
|
263
|
+
"type": {
|
|
264
|
+
"description": "Its type: `keyword`, `uuid`, `string[]`.",
|
|
265
|
+
"type": "string"
|
|
266
|
+
},
|
|
267
|
+
"key": {
|
|
268
|
+
"description": "Part of the primary key. Shown with a `#` in front.",
|
|
269
|
+
"type": "boolean"
|
|
270
|
+
},
|
|
271
|
+
"ref": {
|
|
272
|
+
"description": "The `node` or `node.field` this one points at, like a foreign key. Draws a relation between the two cards.",
|
|
273
|
+
"type": "string"
|
|
274
|
+
},
|
|
275
|
+
"note": {
|
|
276
|
+
"description": "Shown on hover and in the drawer.",
|
|
277
|
+
"type": "string"
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
"additionalProperties": false
|
|
281
|
+
}
|
|
282
|
+
]
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
]
|
|
286
|
+
}
|
|
287
|
+
},
|
|
195
288
|
"icon": {
|
|
196
289
|
"description": "`postgresql`, `logos:redis`, `lucide:server` or ./path/to.svg.",
|
|
197
290
|
"type": "string"
|
package/template/package.json
CHANGED
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
"@astrojs/starlight": "^0.42.0",
|
|
15
15
|
"@fontsource/ibm-plex-mono": "^5.3.0",
|
|
16
16
|
"@fontsource/ibm-plex-sans": "^5.3.0",
|
|
17
|
-
"@the-package-labs/idocs-astro": "^0.
|
|
18
|
-
"@the-package-labs/idocs-react": "^0.
|
|
17
|
+
"@the-package-labs/idocs-astro": "^0.6.0",
|
|
18
|
+
"@the-package-labs/idocs-react": "^0.6.0",
|
|
19
19
|
"astro": "^7.0.0",
|
|
20
20
|
"react": "^19.3.0",
|
|
21
21
|
"react-dom": "^19.3.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@the-package-labs/idocs": "^0.
|
|
24
|
+
"@the-package-labs/idocs": "^0.6.0",
|
|
25
25
|
"@types/react": "^19.2.0",
|
|
26
26
|
"@types/react-dom": "^19.2.0"
|
|
27
27
|
},
|