flowchart-sequence-designer 1.0.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.
@@ -0,0 +1,398 @@
1
+ /**
2
+ * Top-level kind of diagram. `flowchart` uses `nodes` + `edges`; `sequence`
3
+ * uses `actors` + `messages`. The two are rendered by different editors and
4
+ * serialized differently in every exporter.
5
+ */
6
+ type DiagramType = 'flowchart' | 'sequence';
7
+ /**
8
+ * UI variant for flowchart-type models. `flowchart` is the default linear
9
+ * graph; `question` is a decision-tree variant whose nodes carry
10
+ * `metadata.answers`; `journey` is a horizontal user-journey style. The
11
+ * variant selects styling and a few interactions inside `DiagramEditor`.
12
+ */
13
+ type DiagramVariant = 'flowchart' | 'question' | 'journey';
14
+ /**
15
+ * Visual shape of a flowchart node. Defaults to `rectangle`. `diamond` is
16
+ * conventional for decisions, `circle` for start/end terminators, and
17
+ * `parallelogram` for I/O.
18
+ */
19
+ type NodeShape = 'rectangle' | 'diamond' | 'circle' | 'parallelogram';
20
+ /**
21
+ * Supported export targets.
22
+ * - `mermaid` / `plantuml` / `json` / `svg` produce a `string`.
23
+ * - `png` produces a `Blob` (browser-only — uses the Canvas API).
24
+ */
25
+ type ExportFormat = 'mermaid' | 'plantuml' | 'json' | 'svg' | 'png';
26
+ /**
27
+ * A flowchart node.
28
+ *
29
+ * @property id Stable, unique-within-model identifier. Used by edges.
30
+ * @property label Visible text. Multi-line input is wrapped by the renderer.
31
+ * @property shape Visual shape; defaults to `rectangle` when omitted.
32
+ * @property x Optional canvas x-coordinate. When omitted, the renderer
33
+ * auto-positions on first paint.
34
+ * @property y Optional canvas y-coordinate. Same defaulting as `x`.
35
+ * @property metadata Free-form bag for variant-specific data (e.g.
36
+ * `metadata.group` for journey columns, `metadata.answers`
37
+ * for question branches). Round-trips through JSON only.
38
+ */
39
+ interface DiagramNode {
40
+ id: string;
41
+ label: string;
42
+ shape?: NodeShape;
43
+ x?: number;
44
+ y?: number;
45
+ metadata?: Record<string, unknown>;
46
+ }
47
+ /**
48
+ * A directed edge between two flowchart nodes.
49
+ *
50
+ * @property id Stable, unique-within-model identifier.
51
+ * @property from Source node id. Must match an existing `DiagramNode.id`.
52
+ * @property to Target node id. Must match an existing `DiagramNode.id`.
53
+ * @property label Optional edge label rendered at the midpoint.
54
+ * @property style Line style. `solid` is default; `dashed` maps to
55
+ * Mermaid `-.->` and PlantUML `-[dashed]->`; `dotted`
56
+ * maps to Mermaid `-..->` and PlantUML `-[dotted]->`.
57
+ * @property arrowhead Arrow style at the target end. `arrow` is default.
58
+ * @property waypoint Optional manual waypoint in canvas coordinates. When
59
+ * set, the edge is routed as two cubic segments meeting
60
+ * at this point. Persisted in JSON exports; ignored by
61
+ * Mermaid/PlantUML serializers (those formats don't
62
+ * encode routing).
63
+ */
64
+ interface DiagramEdge {
65
+ id: string;
66
+ from: string;
67
+ to: string;
68
+ label?: string;
69
+ style?: 'solid' | 'dashed' | 'dotted';
70
+ arrowhead?: 'arrow' | 'none' | 'open';
71
+ waypoint?: {
72
+ x: number;
73
+ y: number;
74
+ };
75
+ }
76
+ /**
77
+ * A single message in a sequence diagram.
78
+ *
79
+ * @property id Stable, unique-within-model identifier.
80
+ * @property from Source actor name. Must appear in the model's `actors` list.
81
+ * @property to Target actor name. Must appear in the model's `actors` list.
82
+ * @property label Message text rendered above the arrow.
83
+ * @property style Arrow style. `solid` is default; `dashed` is conventional
84
+ * for asynchronous or return messages.
85
+ */
86
+ interface SequenceMessage {
87
+ id: string;
88
+ from: string;
89
+ to: string;
90
+ label: string;
91
+ style?: 'solid' | 'dashed';
92
+ }
93
+ /**
94
+ * The serialized shape of any diagram. Flowchart-type models populate
95
+ * `nodes`/`edges`; sequence-type models populate `actors`/`messages`. Both
96
+ * sub-shapes coexist on a single union to keep the JSON exporter / importer
97
+ * straightforward.
98
+ *
99
+ * @property type Discriminator — selects which sub-shape is active.
100
+ * @property variant UI variant. Only meaningful when `type === 'flowchart'`.
101
+ * @property title Optional human-readable diagram title.
102
+ * @property nodes Flowchart nodes. Always present (empty for sequence
103
+ * models) so the type stays uniform.
104
+ * @property edges Flowchart edges. Always present (empty for sequence
105
+ * models).
106
+ * @property actors Ordered list of actor names. Sequence models only.
107
+ * @property messages Ordered list of messages between actors. Sequence
108
+ * models only.
109
+ */
110
+ interface DiagramModel {
111
+ type: DiagramType;
112
+ variant?: DiagramVariant;
113
+ title?: string;
114
+ nodes: DiagramNode[];
115
+ edges: DiagramEdge[];
116
+ actors?: string[];
117
+ messages?: SequenceMessage[];
118
+ }
119
+ /**
120
+ * A single problem found by `Model.validate()`.
121
+ *
122
+ * @property kind Category of the problem:
123
+ * - `dangling-from`: edge `from` references a missing node.
124
+ * - `dangling-to`: edge `to` references a missing node.
125
+ * - `duplicate-node-id`: two nodes share an `id`.
126
+ * - `duplicate-edge-id`: two edges share an `id`.
127
+ * @property id Identifier of the offending node or edge.
128
+ * @property message Human-readable description suitable for surfacing in UI.
129
+ */
130
+ interface ValidationError {
131
+ kind: 'dangling-from' | 'dangling-to' | 'duplicate-node-id' | 'duplicate-edge-id';
132
+ id: string;
133
+ message: string;
134
+ }
135
+
136
+ /**
137
+ * Mutable builder around a `DiagramModel`. Every public mutator returns
138
+ * `this` so callers can chain (`new Model('flowchart').addNode(...).addEdge(...)`).
139
+ * Call `.toJSON()` to extract a deep-cloned plain model suitable for
140
+ * serialization or for handing to the editor components.
141
+ *
142
+ * All add/update operations validate immediately and throw on collisions or
143
+ * dangling references. For non-throwing, batch-style structural checks call
144
+ * `.validate()` instead.
145
+ */
146
+ declare class Model {
147
+ private data;
148
+ /**
149
+ * Create an empty model.
150
+ *
151
+ * @param type Top-level kind — `flowchart` or `sequence`.
152
+ * @param title Optional human-readable title.
153
+ * @param variant Optional UI variant (flowchart models only).
154
+ */
155
+ constructor(type: DiagramType, title?: string, variant?: DiagramVariant);
156
+ /**
157
+ * Rehydrate a `Model` from a previously serialized `DiagramModel`. The
158
+ * incoming data is deep-cloned, so future mutations on the returned `Model`
159
+ * do not affect the caller's object.
160
+ */
161
+ static fromData(data: DiagramModel): Model;
162
+ /** Set the UI variant. No-op semantics for sequence models. */
163
+ setVariant(variant: DiagramVariant): this;
164
+ /**
165
+ * Append a node. Throws if a node with the same id already exists. The
166
+ * input is shallow-cloned, so later mutations of the caller's object do
167
+ * not leak in.
168
+ */
169
+ addNode(node: DiagramNode): this;
170
+ /**
171
+ * Patch an existing node in place. Throws if the id is not found. The id
172
+ * field itself cannot be patched — to rename, remove + re-add.
173
+ */
174
+ updateNode(id: string, patch: Partial<Omit<DiagramNode, 'id'>>): this;
175
+ /**
176
+ * Remove a node and every edge that referenced it as `from` or `to`. Safe
177
+ * to call on a missing id (no-op).
178
+ */
179
+ removeNode(id: string): this;
180
+ /**
181
+ * Append an edge. Throws on duplicate id or if either endpoint references
182
+ * an unknown node — the model never holds dangling edges from this entry
183
+ * point. (Importers can still construct dangling edges; call `validate()`
184
+ * to detect them.)
185
+ */
186
+ addEdge(edge: DiagramEdge): this;
187
+ /**
188
+ * Surface structural problems without throwing. Returns an array of
189
+ * `ValidationError`s; empty array means the model is well-formed. Used by
190
+ * the editor's status banner and by external tooling.
191
+ */
192
+ validate(): ValidationError[];
193
+ /** Remove an edge by id. Safe to call on a missing id (no-op). */
194
+ removeEdge(id: string): this;
195
+ /** Append a sequence actor. Duplicate names are silently ignored. */
196
+ addActor(name: string): this;
197
+ /**
198
+ * Append a sequence message. The actors referenced by `from`/`to` are not
199
+ * validated here — callers are expected to register them via `addActor()`
200
+ * first.
201
+ */
202
+ addMessage(message: SequenceMessage): this;
203
+ /**
204
+ * Return a deep-cloned plain `DiagramModel`. Safe to mutate by the caller;
205
+ * mutations do not flow back into this `Model`.
206
+ */
207
+ toJSON(): DiagramModel;
208
+ }
209
+
210
+ /**
211
+ * Fluent builder for flowchart-type diagrams. Wraps `Model` with shorter
212
+ * method names tuned for one-shot construction in tests and scripts, and
213
+ * with convenience exporters for every supported `ExportFormat`.
214
+ *
215
+ * @example
216
+ * ```ts
217
+ * const svg = flowchart('Login')
218
+ * .node('start', 'Begin', { shape: 'circle' })
219
+ * .node('check', 'Authenticated?', { shape: 'diamond' })
220
+ * .edge('start', 'check')
221
+ * .toSVG();
222
+ * ```
223
+ */
224
+ declare class FlowchartBuilder {
225
+ private model;
226
+ /** @param title Optional human-readable diagram title. */
227
+ constructor(title?: string);
228
+ /**
229
+ * Append a node. Defaults `shape` to `rectangle` when omitted from `options`.
230
+ * Throws on duplicate id.
231
+ */
232
+ node(id: string, label: string, options?: Partial<Omit<DiagramNode, 'id' | 'label'>>): this;
233
+ /**
234
+ * Append an edge with an auto-generated id. The id is derived from the
235
+ * current edge list to avoid collisions with imported models.
236
+ */
237
+ edge(from: string, to: string, options?: Partial<Omit<DiagramEdge, 'id' | 'from' | 'to'>>): this;
238
+ /** Remove a node and every edge that references it. */
239
+ removeNode(id: string): this;
240
+ /** Remove an edge by id. */
241
+ removeEdge(id: string): this;
242
+ /** Patch an existing node. See `Model.updateNode`. */
243
+ updateNode(id: string, patch: Partial<Omit<DiagramNode, 'id'>>): this;
244
+ /** Return the underlying `Model` for advanced operations or validation. */
245
+ getModel(): Model;
246
+ /** Serialize as Mermaid `flowchart TD` source. */
247
+ toMermaid(): string;
248
+ /** Serialize as PlantUML activity-diagram source. */
249
+ toPlantUML(): string;
250
+ /** Serialize as the package's JSON shape (full round-trip fidelity). */
251
+ toJSON(): string;
252
+ /** Render to a standalone SVG string. */
253
+ toSVG(): string;
254
+ /** Render to a PNG `Blob`. Browser-only (uses the Canvas API). */
255
+ toPNG(): Promise<Blob>;
256
+ }
257
+ /** Convenience constructor — `flowchart('My Diagram')` is `new FlowchartBuilder('My Diagram')`. */
258
+ declare function flowchart(title?: string): FlowchartBuilder;
259
+
260
+ /**
261
+ * Fluent builder for sequence-type diagrams. Mirrors `FlowchartBuilder` but
262
+ * over `actors`/`messages` instead of `nodes`/`edges`.
263
+ *
264
+ * @example
265
+ * ```ts
266
+ * const puml = sequence('Checkout')
267
+ * .actor('User')
268
+ * .message('User', 'Server', 'POST /pay')
269
+ * .replyMessage('Server', 'User', '200 OK')
270
+ * .toPlantUML();
271
+ * ```
272
+ */
273
+ declare class SequenceBuilder {
274
+ private model;
275
+ /** @param title Optional human-readable diagram title. */
276
+ constructor(title?: string);
277
+ /** Register an actor. Duplicates are silently ignored. */
278
+ actor(name: string): this;
279
+ /**
280
+ * Append a message. Both endpoints are auto-registered as actors if not
281
+ * already present. The id is derived from the current message list.
282
+ */
283
+ message(from: string, to: string, label: string, options?: Partial<Pick<SequenceMessage, 'style'>>): this;
284
+ /** Convenience for a `dashed`-style return message. */
285
+ replyMessage(from: string, to: string, label: string): this;
286
+ /** Return the underlying `Model` for advanced operations or validation. */
287
+ getModel(): Model;
288
+ /** Serialize as Mermaid `sequenceDiagram` source. */
289
+ toMermaid(): string;
290
+ /** Serialize as PlantUML sequence-diagram source. */
291
+ toPlantUML(): string;
292
+ /** Serialize as the package's JSON shape (full round-trip fidelity). */
293
+ toJSON(): string;
294
+ }
295
+ /** Convenience constructor — `sequence('My Diagram')` is `new SequenceBuilder('My Diagram')`. */
296
+ declare function sequence(title?: string): SequenceBuilder;
297
+
298
+ /**
299
+ * Serialize a `DiagramModel` to Mermaid source. Dispatches between
300
+ * `graph TD` (flowchart) and `sequenceDiagram` based on `model.type`.
301
+ *
302
+ * **Round-trip notes (flowchart):**
303
+ * - Node shapes `rectangle`, `diamond`, `circle`, `parallelogram` map to
304
+ * `[ ]`, `{ }`, `(( ))`, `[/ /]` respectively.
305
+ * - Edge style `solid` → `-->`, `dashed` and `dotted` → `-.->` (Mermaid
306
+ * collapses dotted to dashed). `arrowhead: 'none'` strips the head.
307
+ * - `waypoint`, `metadata`, and `variant` are **dropped** — Mermaid has no
308
+ * way to encode routing or arbitrary metadata.
309
+ *
310
+ * **Round-trip notes (sequence):**
311
+ * - Message style `solid` → `->>`, `dashed` → `-->>`.
312
+ */
313
+ declare function toMermaid(model: DiagramModel): string;
314
+
315
+ /**
316
+ * Serialize a `DiagramModel` to PlantUML source. Dispatches between the
317
+ * state-diagram form (flowchart) and the sequence-diagram form based on
318
+ * `model.type`.
319
+ *
320
+ * **Round-trip notes (flowchart):**
321
+ * - Edge style maps `solid` → `-->`, `dashed` → `-[dashed]->`,
322
+ * `dotted` → `-[dotted]->`.
323
+ * - Node shapes are emitted via the `state ".." as id < >` syntax; some
324
+ * shape information is lossy (PlantUML state diagrams don't distinguish
325
+ * every shape this package supports).
326
+ * - `waypoint`, `metadata`, and `variant` are **dropped**.
327
+ *
328
+ * **Round-trip notes (sequence):**
329
+ * - Actor order is preserved; message style `solid` → `->`, `dashed` → `-->`.
330
+ */
331
+ declare function toPlantUML(model: DiagramModel): string;
332
+
333
+ /**
334
+ * Serialize a `DiagramModel` to pretty-printed JSON. This is the canonical
335
+ * round-trip format: every field — including `variant`, `waypoint`,
336
+ * `metadata.group`, and `metadata.answers` — survives a round trip through
337
+ * `toJSON` + `fromJSON` unchanged.
338
+ */
339
+ declare function toJSON(model: DiagramModel): string;
340
+
341
+ /**
342
+ * Render a `DiagramModel` to a standalone SVG string. The output mirrors the
343
+ * editor canvas: dot-grid background, soft drop-shadowed nodes, smooth
344
+ * cubic-bezier edges. No external assets — the result is fully inline and
345
+ * pasteable into HTML, README files, or PR descriptions.
346
+ *
347
+ * Layout is computed identically to the editor's hit-test pass (same width
348
+ * estimation, padding, and question-card sizing), so an exported SVG matches
349
+ * what you see on screen.
350
+ *
351
+ * Works in Node, Bun, and the browser (no DOM APIs needed).
352
+ */
353
+ declare function toSVG(model: DiagramModel): string;
354
+ /**
355
+ * Render a `DiagramModel` to a PNG `Blob`. Routes the SVG output through an
356
+ * `<img>` and a `<canvas>` at `devicePixelRatio` scale, so the result is
357
+ * crisp on hi-DPI displays.
358
+ *
359
+ * **Browser-only.** Throws if called in a Node/Bun environment (the Canvas
360
+ * API is not available). For server-side PNG rendering, pipe `toSVG()` output
361
+ * through a library like `@resvg/resvg-js`.
362
+ */
363
+ declare function toPNG(model: DiagramModel): Promise<Blob>;
364
+
365
+ /**
366
+ * Parse Mermaid source into a `Model`. Auto-detects `flowchart` /
367
+ * `sequenceDiagram` from the directive line and dispatches accordingly.
368
+ *
369
+ * **What is preserved:**
370
+ * - Flowcharts: node shapes (`[]` / `{}` / `(())` / `[/]`), node labels,
371
+ * edge connectors (`-->`, `-.->`, `---`, `-.-`), edge labels, and
372
+ * `subgraph` grouping (stored on `node.metadata.group`).
373
+ * - Sequence: actor declarations, message arrows (`->>`, `-->>`), labels.
374
+ * - Frontmatter `title: ...` blocks are lifted into `model.title`.
375
+ *
376
+ * **What is dropped or normalized:**
377
+ * - `mermaid.initialize(...)` blocks, `%%{init: ...}%%` directives, and
378
+ * click handlers — stripped before parsing.
379
+ * - Dotted edges collapse to `dashed` (Mermaid's dot/dash style is lossy).
380
+ * - Node positions, `waypoint`, and any package-specific metadata other
381
+ * than `group` are not present in Mermaid and so cannot round-trip.
382
+ */
383
+ declare function fromMermaid(mermaid: string): Model;
384
+
385
+ /**
386
+ * Rehydrate a `Model` from the package's JSON shape. Accepts either the raw
387
+ * JSON string or an already-parsed `DiagramModel` (handy when the caller has
388
+ * received the data from a typed source).
389
+ *
390
+ * Validation here is minimal — only the structural fields needed by the
391
+ * downstream renderer (`type`, `nodes`, `edges`) are checked. For deeper
392
+ * checks call `model.validate()` after import.
393
+ *
394
+ * @throws If `json` is not a valid `DiagramModel` shape.
395
+ */
396
+ declare function fromJSON(json: string | DiagramModel): Model;
397
+
398
+ export { type DiagramEdge, type DiagramModel, type DiagramNode, type DiagramType, type DiagramVariant, type DiagramEdge as Edge, type ExportFormat, FlowchartBuilder, Model, type DiagramNode as Node, type NodeShape, SequenceBuilder, type SequenceMessage, flowchart, fromJSON, fromMermaid, sequence, toJSON, toMermaid, toPNG, toPlantUML, toSVG };