@miragon/team-topologies-schema-model 0.13.2 → 0.15.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/README.md +35 -28
- package/dist/index.cjs +42 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +42 -13
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# @miragon/team-topologies-schema-model
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@miragon/team-topologies-schema-model)
|
|
4
|
-
[](https://github.com/Miragon/modeler-suite/blob/main/modelers/team-topologies/LICENSE)
|
|
5
5
|
|
|
6
6
|
The **DOM-free core** of the [Team Topologies Modeler](../../README.md): the data model, the notation
|
|
7
7
|
specification, runtime validation, version migrations and deterministic JSON serialization for
|
|
8
8
|
[Team Topologies](https://teamtopologies.com/) diagrams.
|
|
9
9
|
|
|
10
|
-
This package has **no view, no DOM and no diagram-js
|
|
10
|
+
This package has **no view, no DOM and no diagram-js**: it is plain TypeScript that runs anywhere
|
|
11
11
|
(browser, Node, an edge function, a CLI). The browser renderer
|
|
12
12
|
([`@miragon/team-topologies-renderer`](../renderer)), the web app and the VS Code extension all build
|
|
13
13
|
on top of it. The DOM-freedom is enforced in CI (ESLint `no-restricted-imports` /
|
|
@@ -22,23 +22,23 @@ npm install @miragon/team-topologies-schema-model
|
|
|
22
22
|
|
|
23
23
|
## What's inside
|
|
24
24
|
|
|
25
|
-
- **The notation spec
|
|
25
|
+
- **The notation spec:** the four team types and three interaction modes, with their official
|
|
26
26
|
shapes, colours and stroke styles as plain data you can read and render against.
|
|
27
|
-
- **The document model
|
|
27
|
+
- **The document model:** a small, stable shape (`TtDocument`) with `version`, `title`, `nodes`,
|
|
28
28
|
`interactions`, `flows` and `annotations`.
|
|
29
|
-
- **Runtime validation
|
|
29
|
+
- **Runtime validation:** Zod schemas + `parseDocument()` for everything that comes from a file, a
|
|
30
30
|
URL or `localStorage`.
|
|
31
|
-
- **Forward migrations
|
|
31
|
+
- **Forward migrations:** `parseDocument()` migrates older documents up to the current version
|
|
32
32
|
before validating, keyed by the document `version`.
|
|
33
|
-
- **Deterministic serialization
|
|
33
|
+
- **Deterministic serialization:** sorted, rounded and version-stamped output, so `.tt` /
|
|
34
34
|
`.ttm.json` files diff cleanly and share URLs stay stable.
|
|
35
|
-
- **Factories & a sample
|
|
35
|
+
- **Factories & a sample:** helpers that create well-formed elements and documents, plus a complete
|
|
36
36
|
example topology.
|
|
37
37
|
|
|
38
38
|
## The document format
|
|
39
39
|
|
|
40
40
|
A diagram is a single JSON object. Interactions are **placed shapes** that overlap the teams they
|
|
41
|
-
relate to (spatial overlap, the Team Topologies convention)
|
|
41
|
+
relate to (spatial overlap, the Team Topologies convention); there is no source/target reference.
|
|
42
42
|
|
|
43
43
|
```jsonc
|
|
44
44
|
{
|
|
@@ -86,12 +86,13 @@ relate to (spatial overlap, the Team Topologies convention) — there is no sour
|
|
|
86
86
|
## Notation
|
|
87
87
|
|
|
88
88
|
The single source of truth for the visual notation. Shapes and colours follow the official
|
|
89
|
-
[Team-Shape-Templates](https://github.com/TeamTopologies/Team-Shape-Templates)
|
|
89
|
+
[Team-Shape-Templates](https://github.com/TeamTopologies/Team-Shape-Templates): every element is
|
|
90
90
|
distinguished by shape **and** colour, so diagrams survive colour-vision deficiency and greyscale
|
|
91
|
-
printing. Team shapes are **solid** (long-lived); interaction shapes are **dashed
|
|
92
|
-
(
|
|
91
|
+
printing. Team shapes are **solid** (long-lived); interaction shapes are **dashed** (short-lived).
|
|
92
|
+
An interaction spec carries the templates' fill opacity (`opacity: 0.5`); the renderer premixes the
|
|
93
|
+
fill over white at that opacity and draws it opaque.
|
|
93
94
|
|
|
94
|
-
### Team types
|
|
95
|
+
### Team types: `TEAM_TYPE_SPECS`
|
|
95
96
|
|
|
96
97
|
| `type` | Label | Shape | Fill / Stroke |
|
|
97
98
|
| ----------------------- | --------------------- | ---------------------------- | --------------------- |
|
|
@@ -100,7 +101,7 @@ printing. Team shapes are **solid** (long-lived); interaction shapes are **dashe
|
|
|
100
101
|
| `complicated-subsystem` | Complicated Subsystem | octagon | `#FFC08B` / `#E88814` |
|
|
101
102
|
| `platform` | Platform | square-cornered rectangle | `#B7CDF1` / `#6D9EEB` |
|
|
102
103
|
|
|
103
|
-
### Interaction modes
|
|
104
|
+
### Interaction modes: `INTERACTION_MODE_SPECS`
|
|
104
105
|
|
|
105
106
|
| `mode` | Label | Glyph | Fill / Stroke |
|
|
106
107
|
| ---------------- | -------------- | ------------------------------------- | --------------------- |
|
|
@@ -109,7 +110,7 @@ printing. Team shapes are **solid** (long-lived); interaction shapes are **dashe
|
|
|
109
110
|
| `facilitating` | Facilitating | circle | `#C9DFBE` / `#78996B` |
|
|
110
111
|
|
|
111
112
|
The **flow of change** is described separately by `FLOW_SPEC` (a left-to-right dashed band), and
|
|
112
|
-
text annotations by `ANNOTATION_SPEC` (default and minimum size
|
|
113
|
+
text annotations by `ANNOTATION_SPEC` (default and minimum size; they are not part of the official
|
|
113
114
|
notation, so they carry no notation colours).
|
|
114
115
|
|
|
115
116
|
## Usage
|
|
@@ -129,7 +130,7 @@ const doc = emptyDocument("Online shop");
|
|
|
129
130
|
doc.nodes.push(createTeamNode("stream-aligned", { x: 560, y: 202 }));
|
|
130
131
|
doc.interactions.push(createInteractionShape("x-as-a-service", { x: 636, y: 286 }));
|
|
131
132
|
|
|
132
|
-
// Serialize deterministically (sorted, rounded, version-stamped)
|
|
133
|
+
// Serialize deterministically (sorted, rounded, version-stamped): diff- and URL-stable
|
|
133
134
|
const json = serializeDocument(doc);
|
|
134
135
|
|
|
135
136
|
// Validate + migrate anything untrusted (file / URL / localStorage)
|
|
@@ -152,7 +153,7 @@ console.log(SAMPLE_DOCUMENT.title);
|
|
|
152
153
|
| `TeamType`, `InteractionMode`, `TEAM_TYPES`, `INTERACTION_MODES` | The notation's discriminator unions + their value lists. |
|
|
153
154
|
| `TEAM_TYPE_SPECS`, `INTERACTION_MODE_SPECS`, `FLOW_SPEC`, `ANNOTATION_SPEC`, `dashArray()` | The visual notation spec (shapes, colours, strokes) as data. |
|
|
154
155
|
| `documentSchema`, `teamNodeSchema`, `interactionSchema`, `flowSchema`, `annotationSchema` | Zod schemas for each shape. |
|
|
155
|
-
| `parseDocument()`, `ParseResult`, `DocumentIssue`
|
|
156
|
+
| `parseDocument()`, `ParseResult`, `DocumentIssue`, `MAX_NESTING_DEPTH` | Validate **and migrate** unknown input into a `TtDocument`; a failure lists each issue with its path. |
|
|
156
157
|
| `serializeDocument()`, `canonicalize()` | Deterministic JSON serialization (sorted, rounded, fixed key order). |
|
|
157
158
|
| `foreignFields()`, `withForeignFields()`, `DOCUMENT_FIELDS`, `TEAM_NODE_FIELDS`, … | The fields a document carries beyond the known ones. |
|
|
158
159
|
| `documentIdProblems()`, `DIAGRAM_ROOT_ID`, `associationId()` | The id rules (unique, not reserved). |
|
|
@@ -162,38 +163,44 @@ console.log(SAMPLE_DOCUMENT.title);
|
|
|
162
163
|
|
|
163
164
|
## Determinism & migrations
|
|
164
165
|
|
|
165
|
-
- **Determinism
|
|
166
|
+
- **Determinism:** `serializeDocument()` runs `canonicalize()` first: arrays are sorted by `id`,
|
|
166
167
|
coordinates are rounded to two decimals, optional fields with no value are dropped, and keys are
|
|
167
168
|
written in a fixed order. The same logical diagram always produces byte-identical JSON, which is
|
|
168
169
|
what makes Git diffs small and share URLs stable. The pretty form (the default) is the file on
|
|
169
170
|
disk and ends with a line break; the compact form (`serializeDocument(doc, false)`) has none.
|
|
170
|
-
- **Unknown fields
|
|
171
|
+
- **Unknown fields:** fields a document carries that this package does not know (a vendor's
|
|
171
172
|
`"x-vendor"` on the root or on an element) pass `parseDocument()` untouched and are written after
|
|
172
|
-
the known fields, sorted by name (nested keys too), so another tool's data survives a save.
|
|
173
|
-
|
|
173
|
+
the known fields, sorted by name (nested keys too), so another tool's data survives a save. Only
|
|
174
|
+
they can nest deeper than the four levels of the known fields, and objects and arrays nest at
|
|
175
|
+
most 100 levels deep (`MAX_NESTING_DEPTH`), the document itself counting as the first:
|
|
176
|
+
`parseDocument()` refuses a deeper document with an issue at each first level too deep, checked
|
|
177
|
+
without recursion, because the serializer and JSON tools overflow the stack a few thousand
|
|
178
|
+
levels down.
|
|
179
|
+
- **Ids:** `parseDocument()` rejects a document whose ids would collide on the canvas: an id used
|
|
174
180
|
twice, the diagram's own id `tt-root` (`DIAGRAM_ROOT_ID`), ids starting with `__implicitroot`,
|
|
175
181
|
`assoc_<annotation id>` (`associationId()`), the id of that annotation's connector, and the names
|
|
176
182
|
of JavaScript's built-in object properties (`constructor`, `toString`, `__proto__`, …), which the
|
|
177
183
|
canvas's element registry, a plain object, already resolves. `documentIdProblems()` lists them
|
|
178
184
|
with their path.
|
|
179
|
-
- **Migrations
|
|
185
|
+
- **Migrations:** `parseDocument()` upgrades older documents before validating (keyed by `version`).
|
|
180
186
|
The `1 → 2` step drops the legacy `showFlowOfChange` flag and the old edge-based interactions,
|
|
181
187
|
keeping only interactions that carry geometry (the placed-shape model). Only a version 1 file
|
|
182
188
|
loses interactions this way: from version 2 on, an interaction without `position` or `size` is
|
|
183
189
|
refused at its path like any other missing field, so it never vanishes on the next save. The
|
|
184
|
-
`2 → 3` step adds an empty `annotations` list
|
|
190
|
+
`2 → 3` step adds an empty `annotations` list, and because an empty list is not written back,
|
|
185
191
|
re-saving a v2 file changes nothing but its `version`. Issue paths always count in the input: an
|
|
186
192
|
invalid interaction after a dropped one is reported at its index in the file.
|
|
187
193
|
|
|
188
194
|
## Development
|
|
189
195
|
|
|
190
|
-
This package is part of the [Team Topologies Modeler](../../README.md)
|
|
191
|
-
|
|
196
|
+
This package is part of the [Team Topologies Modeler](../../README.md) in the
|
|
197
|
+
[Miragon modeler suite](https://github.com/Miragon/modeler-suite) and is normally consumed from
|
|
198
|
+
source. From the suite's root:
|
|
192
199
|
|
|
193
200
|
```bash
|
|
194
|
-
npm run build -w
|
|
195
|
-
npm test
|
|
196
|
-
npm run typecheck # tsc, compiled WITHOUT the DOM lib
|
|
201
|
+
npm run build -w @miragon/team-topologies-schema-model # tsup → dist/ (publish build)
|
|
202
|
+
npm run team-topologies test # Vitest unit tests
|
|
203
|
+
npm run team-topologies typecheck # tsc, compiled WITHOUT the DOM lib
|
|
197
204
|
```
|
|
198
205
|
|
|
199
206
|
## License
|
package/dist/index.cjs
CHANGED
|
@@ -249,25 +249,54 @@ var documentSchema = zod.z.looseObject({
|
|
|
249
249
|
context.addIssue({ code: "custom", path, message });
|
|
250
250
|
}
|
|
251
251
|
});
|
|
252
|
+
var MAX_NESTING_DEPTH = 100;
|
|
252
253
|
function parseDocument(input) {
|
|
254
|
+
const tooDeep = nestingIssues(input);
|
|
255
|
+
if (tooDeep.length > 0) return refused(tooDeep);
|
|
253
256
|
const { document: migrated, interactionFileIndexes } = migrate(input);
|
|
254
257
|
const result = documentSchema.safeParse(migrated);
|
|
255
258
|
if (!result.success) {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
error: issues.map((i2) => `${i2.path.join(".") || "(root)"}: ${i2.message}`).join("; "),
|
|
266
|
-
issues
|
|
267
|
-
};
|
|
259
|
+
return refused(
|
|
260
|
+
result.error.issues.map((issue) => ({
|
|
261
|
+
path: pathInFile(
|
|
262
|
+
issue.path.filter((key) => typeof key !== "symbol"),
|
|
263
|
+
interactionFileIndexes
|
|
264
|
+
),
|
|
265
|
+
message: issue.message
|
|
266
|
+
}))
|
|
267
|
+
);
|
|
268
268
|
}
|
|
269
269
|
return { ok: true, document: result.data };
|
|
270
270
|
}
|
|
271
|
+
function refused(issues) {
|
|
272
|
+
return {
|
|
273
|
+
ok: false,
|
|
274
|
+
error: issues.map((i2) => `${i2.path.join(".") || "(root)"}: ${i2.message}`).join("; "),
|
|
275
|
+
issues
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function nestingIssues(input) {
|
|
279
|
+
const issues = [];
|
|
280
|
+
const pending = [{ value: input, path: [] }];
|
|
281
|
+
while (pending.length > 0) {
|
|
282
|
+
const { value, path } = pending.pop();
|
|
283
|
+
if (typeof value !== "object" || value === null) continue;
|
|
284
|
+
if (path.length >= MAX_NESTING_DEPTH) {
|
|
285
|
+
issues.push({
|
|
286
|
+
path,
|
|
287
|
+
message: `objects and arrays may nest at most ${MAX_NESTING_DEPTH} levels deep`
|
|
288
|
+
});
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
const entries = Array.isArray(value) ? Array.from(value, (entry, index) => [index, entry]) : Object.entries(value);
|
|
292
|
+
for (const [key, entry] of entries.reverse()) {
|
|
293
|
+
if (typeof entry === "object" && entry !== null) {
|
|
294
|
+
pending.push({ value: entry, path: [...path, key] });
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return issues;
|
|
299
|
+
}
|
|
271
300
|
var EDGE_INTERACTIONS_VERSION = 1;
|
|
272
301
|
function migrate(input) {
|
|
273
302
|
if (input == null || typeof input !== "object") {
|
|
@@ -596,6 +625,7 @@ exports.FLOW_SPEC = FLOW_SPEC;
|
|
|
596
625
|
exports.INTERACTION_FIELDS = INTERACTION_FIELDS;
|
|
597
626
|
exports.INTERACTION_MODES = INTERACTION_MODES;
|
|
598
627
|
exports.INTERACTION_MODE_SPECS = INTERACTION_MODE_SPECS;
|
|
628
|
+
exports.MAX_NESTING_DEPTH = MAX_NESTING_DEPTH;
|
|
599
629
|
exports.SAMPLE_DOCUMENT = SAMPLE_DOCUMENT;
|
|
600
630
|
exports.TEAM_NODE_FIELDS = TEAM_NODE_FIELDS;
|
|
601
631
|
exports.TEAM_TYPES = TEAM_TYPES;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/notation.ts","../src/ids.ts","../src/schema.ts","../src/foreign.ts","../src/serialize.ts","../src/factory.ts","../src/sample.ts"],"names":["z","i","s","nanoid"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Pure (DOM-free) domain types for the Team Topologies model.\n *\n * This module is the canonical representation of a diagram and must never\n * import from the rendering layer (`@xyflow/react`) or touch the DOM, so it\n * can be unit-tested in isolation and reused across views / exporters.\n */\n\n/** MIME type used when dragging a team type from the palette onto the canvas. */\nexport const DND_MIME = \"application/x-tt-team-type\";\n\n/** The four fundamental team types in Team Topologies. */\nexport type TeamType = \"stream-aligned\" | \"enabling\" | \"complicated-subsystem\" | \"platform\";\n\nexport const TEAM_TYPES: readonly TeamType[] = [\n \"stream-aligned\",\n \"enabling\",\n \"complicated-subsystem\",\n \"platform\",\n] as const;\n\n/** The three core team interaction modes in Team Topologies. */\nexport type InteractionMode = \"collaboration\" | \"x-as-a-service\" | \"facilitating\";\n\nexport const INTERACTION_MODES: readonly InteractionMode[] = [\n \"collaboration\",\n \"x-as-a-service\",\n \"facilitating\",\n] as const;\n\n/** Geometric size of a node in canvas units (px). Encodes cognitive load. */\nexport interface Size {\n width: number;\n height: number;\n}\n\n/** Position of a node on the canvas in canvas units (px). */\nexport interface Position {\n x: number;\n y: number;\n}\n\n/** A team node in the canonical document model. */\nexport interface TeamNode {\n id: string;\n type: TeamType;\n label: string;\n description?: string;\n position: Position;\n size: Size;\n fill?: string;\n stroke?: string;\n}\n\n/**\n * An interaction in the canonical document model.\n *\n * Per the official Team Topologies notation, an interaction is a placed,\n * resizable SHAPE (parallelogram / triangle / circle) overlaid on the boundary\n * between the teams it relates to — not a connecting line. The relationship is\n * therefore spatial (overlap), so there is no source/target reference.\n */\nexport interface InteractionShape {\n id: string;\n mode: InteractionMode;\n label?: string;\n position: Position;\n size: Size;\n fill?: string;\n stroke?: string;\n}\n\n/**\n * A \"flow of change\" guide: a placed, resizable arrow element. Lets you anchor\n * the implied left-to-right flow, and visualise several team groupings on one\n * canvas.\n */\nexport interface FlowShape {\n id: string;\n label?: string;\n position: Position;\n size: Size;\n}\n\n/**\n * A free-text note beside the diagram (like a BPMN text annotation). It either\n * stands alone or is attached to exactly one team, interaction or flow, which\n * its dashed connector points at.\n */\nexport interface TextAnnotation {\n id: string;\n text: string;\n position: Position;\n size: Size;\n /** Id of the team, interaction or flow this annotation is attached to. */\n attachedTo?: string;\n}\n\n/** Current document schema version. Bump + add a migration when shape changes. */\nexport const DOCUMENT_VERSION = 3 as const;\n\n/**\n * A complete Team Topologies diagram. This is what gets serialised to JSON,\n * embedded into exported images, and encoded into share URLs.\n */\nexport interface TtDocument {\n version: typeof DOCUMENT_VERSION;\n title: string;\n nodes: TeamNode[];\n interactions: InteractionShape[];\n flows: FlowShape[];\n annotations: TextAnnotation[];\n}\n","/**\n * The Team Topologies visual notation, encoded as data.\n *\n * Colours, shapes and stroke styles follow the official\n * \"Team-Shape-Templates\" specification published by Team Topologies\n * (https://github.com/TeamTopologies/Team-Shape-Templates):\n *\n * - Team shapes are SOLID outlines (long-lived structures).\n * - Interaction-mode shapes are 50% transparent with DASHED outlines\n * (short-lived interactions).\n * - Each element is distinguished by SHAPE as well as colour, so the\n * notation stays readable for people with colour-vision deficiency.\n *\n * This module is pure data — it must not import the rendering layer.\n */\n\nimport type { InteractionMode, Size, TeamType } from \"./types\";\n\nexport type TeamShape = \"rounded-rect-horizontal\" | \"rounded-rect-vertical\" | \"octagon\" | \"rect\";\n\nexport type InteractionGlyph = \"parallelogram\" | \"triangle\" | \"circle\";\n\nexport type StrokeStyle = \"solid\" | \"dashed\" | \"dotted\";\n\nexport interface TeamTypeSpec {\n type: TeamType;\n /** Short display name. */\n label: string;\n /** One-line purpose, shown in the palette and inspector. */\n description: string;\n shape: TeamShape;\n fill: string;\n stroke: string;\n strokeStyle: StrokeStyle;\n strokeWidth: number;\n /** Default size when a node of this type is created. */\n defaultSize: Size;\n /** Minimum size enforced by the resizer. */\n minSize: Size;\n}\n\nexport interface InteractionModeSpec {\n mode: InteractionMode;\n label: string;\n description: string;\n shape: InteractionGlyph;\n fill: string;\n stroke: string;\n strokeStyle: StrokeStyle;\n strokeWidth: number;\n /** Opacity for the interaction shape (short-lived → translucent). */\n opacity: number;\n /** Whether direction is semantically meaningful (the X-as-a-Service triangle). */\n directional: boolean;\n /** Default size when a shape of this mode is created. */\n defaultSize: Size;\n /** Minimum size enforced by the resizer. */\n minSize: Size;\n}\n\n/** The left-to-right \"flow of change\" guide, a placeable annotation element. */\nexport interface FlowSpec {\n label: string;\n fill: string;\n stroke: string;\n strokeStyle: StrokeStyle;\n strokeWidth: number;\n defaultSize: Size;\n minSize: Size;\n}\n\nexport const TEAM_TYPE_SPECS: Record<TeamType, TeamTypeSpec> = {\n \"stream-aligned\": {\n type: \"stream-aligned\",\n label: \"Stream-aligned\",\n description: \"Aligned to a single, valuable stream of work; owns it end-to-end.\",\n shape: \"rounded-rect-horizontal\",\n fill: \"#FFEDB8\",\n stroke: \"#FFD966\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 240, height: 96 },\n minSize: { width: 140, height: 64 },\n },\n enabling: {\n type: \"enabling\",\n label: \"Enabling\",\n description:\n \"Helps stream-aligned teams acquire missing capabilities; coaches, then steps back.\",\n shape: \"rounded-rect-vertical\",\n fill: \"#DFBDCF\",\n stroke: \"#D09CB7\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 120, height: 200 },\n minSize: { width: 80, height: 120 },\n },\n \"complicated-subsystem\": {\n type: \"complicated-subsystem\",\n label: \"Complicated Subsystem\",\n description:\n \"Owns a part of the system needing deep specialist knowledge, reducing others' cognitive load.\",\n shape: \"octagon\",\n fill: \"#FFC08B\",\n stroke: \"#E88814\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 170, height: 150 },\n minSize: { width: 110, height: 100 },\n },\n platform: {\n type: \"platform\",\n label: \"Platform\",\n description:\n \"Provides internal self-service capabilities to reduce cognitive load for stream-aligned teams.\",\n shape: \"rect\",\n fill: \"#B7CDF1\",\n stroke: \"#6D9EEB\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 380, height: 130 },\n minSize: { width: 200, height: 90 },\n },\n};\n\nexport const INTERACTION_MODE_SPECS: Record<InteractionMode, InteractionModeSpec> = {\n collaboration: {\n mode: \"collaboration\",\n label: \"Collaboration\",\n description:\n \"Two teams work closely together for a defined period; high overhead, high discovery.\",\n shape: \"parallelogram\",\n fill: \"#C6BEDF\",\n stroke: \"#967EE2\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n opacity: 0.5,\n directional: false,\n defaultSize: { width: 112, height: 72 },\n minSize: { width: 60, height: 44 },\n },\n \"x-as-a-service\": {\n mode: \"x-as-a-service\",\n label: \"X-as-a-Service\",\n description:\n \"One team consumes something the other provides 'as a service'; minimal collaboration.\",\n shape: \"triangle\",\n fill: \"#B4B4B4\",\n stroke: \"#999696\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n opacity: 0.5,\n directional: true,\n defaultSize: { width: 88, height: 78 },\n minSize: { width: 54, height: 48 },\n },\n facilitating: {\n mode: \"facilitating\",\n label: \"Facilitating\",\n description:\n \"One team helps/coaches another to clear impediments and learn; sensing and discovery.\",\n shape: \"circle\",\n fill: \"#C9DFBE\",\n stroke: \"#78996B\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n opacity: 0.5,\n directional: false,\n defaultSize: { width: 84, height: 84 },\n minSize: { width: 48, height: 48 },\n },\n};\n\n/**\n * The \"flow of change\" guide — a placeable dashed arrow (left-to-right).\n * Not a team or interaction: a standalone annotation element.\n */\nexport const FLOW_SPEC: FlowSpec = {\n label: \"Flow of change\",\n fill: \"transparent\",\n stroke: \"#6b6459\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n defaultSize: { width: 520, height: 64 },\n minSize: { width: 160, height: 36 },\n};\n\n/**\n * A text annotation — not part of the Team Topologies notation, so it carries\n * no colours here; the renderer draws it in the neutral brand ink.\n */\nexport interface AnnotationSpec {\n label: string;\n defaultSize: Size;\n minSize: Size;\n}\n\nexport const ANNOTATION_SPEC: AnnotationSpec = {\n label: \"Annotation\",\n defaultSize: { width: 200, height: 64 },\n minSize: { width: 60, height: 30 },\n};\n\n/** Maps a stroke style to an SVG/CSS dash array (empty string = solid). */\nexport function dashArray(style: StrokeStyle, strokeWidth = 2): string {\n switch (style) {\n case \"dashed\":\n return `${strokeWidth * 3} ${strokeWidth * 2}`;\n case \"dotted\":\n return `${strokeWidth} ${strokeWidth * 1.5}`;\n case \"solid\":\n default:\n return \"\";\n }\n}\n\nexport const ALL_TEAM_SPECS: readonly TeamTypeSpec[] = Object.values(TEAM_TYPE_SPECS);\nexport const ALL_INTERACTION_SPECS: readonly InteractionModeSpec[] =\n Object.values(INTERACTION_MODE_SPECS);\n","/**\n * The id rules of a Team Topologies document. Besides the elements a document lists, a diagram\n * holds parts it never writes down: the diagram itself and the connector of every annotation. They\n * take ids of their own, so no element may use one of them; otherwise opening the file would fail\n * halfway, with the previous diagram already gone. The canvas also keeps its elements in a plain\n * object, where the names of JavaScript's built-in object properties already resolve.\n */\n\n/** The id of the diagram itself (the canvas root of the renderer). */\nexport const DIAGRAM_ROOT_ID = \"tt-root\";\n\n/** diagram-js names the roots it creates on its own `__implicitroot_<n>`. */\nconst ENGINE_ROOT_ID_PREFIX = \"__implicitroot\";\n\n/** Connectors are not stored: an annotation's connector derives its id from the annotation. */\nexport function associationId(annotationId: string): string {\n return `assoc_${annotationId}`;\n}\n\nexport interface DocumentIdProblem {\n /** Where the offending id sits, e.g. `[\"nodes\", 2, \"id\"]`. */\n path: (string | number)[];\n message: string;\n}\n\nconst COLLECTIONS = [\"nodes\", \"interactions\", \"flows\", \"annotations\"] as const;\n\ntype DocumentElements = Record<(typeof COLLECTIONS)[number], readonly { id: string }[]>;\n\n/** Ids such as `constructor`, `toString` or `__proto__`, which every plain object already has. */\nfunction isBuiltInPropertyId(id: string): boolean {\n return Object.hasOwn(Object.prototype, id);\n}\n\n/**\n * Every id of the document that would collide on the canvas: a duplicate, the diagram's own id, a\n * diagram-js root id, the name of a built-in object property, or the id of an annotation's\n * connector.\n */\nexport function documentIdProblems(doc: DocumentElements): DocumentIdProblem[] {\n const problems: DocumentIdProblem[] = [];\n const connectorIds = new Map(\n doc.annotations.map((annotation) => [associationId(annotation.id), annotation.id]),\n );\n const seen = new Set<string>();\n for (const collection of COLLECTIONS) {\n doc[collection].forEach((element, index) => {\n const path = [collection, index, \"id\"];\n const { id } = element;\n if (seen.has(id)) {\n problems.push({\n path,\n message: `duplicate id \"${id}\"; ids must be unique across nodes, interactions, flows and annotations`,\n });\n }\n seen.add(id);\n if (id === DIAGRAM_ROOT_ID) {\n problems.push({ path, message: `\"${id}\" is reserved for the diagram itself` });\n } else if (id.startsWith(ENGINE_ROOT_ID_PREFIX)) {\n problems.push({\n path,\n message: `ids starting with \"${ENGINE_ROOT_ID_PREFIX}\" are reserved`,\n });\n } else if (isBuiltInPropertyId(id)) {\n problems.push({\n path,\n message: `\"${id}\" is reserved: it names a built-in property of JavaScript objects`,\n });\n }\n const annotationId = connectorIds.get(id);\n if (annotationId !== undefined) {\n problems.push({\n path,\n message: `\"${id}\" is reserved for the connector of annotation \"${annotationId}\"`,\n });\n }\n });\n }\n return problems;\n}\n","/**\n * Runtime validation for the document model using Zod.\n *\n * Anything entering the app from the outside world (imported files, share\n * URLs, localStorage) is parsed through {@link parseDocument} so malformed or\n * tampered data can never corrupt the editor state. Fields the schema does not\n * know pass through untouched (see `foreign.ts`), so another tool's data\n * survives a save.\n */\n\nimport { z } from \"zod\";\nimport { documentIdProblems } from \"./ids\";\nimport { DOCUMENT_VERSION, INTERACTION_MODES, TEAM_TYPES } from \"./types\";\nimport type { TtDocument } from \"./types\";\n\nconst teamTypeSchema = z.enum(TEAM_TYPES as unknown as [string, ...string[]]);\nconst interactionModeSchema = z.enum(INTERACTION_MODES as unknown as [string, ...string[]]);\n\nconst sizeSchema = z.object({\n width: z.number().finite().positive(),\n height: z.number().finite().positive(),\n});\n\nconst positionSchema = z.object({\n x: z.number().finite(),\n y: z.number().finite(),\n});\n\nconst hexColor = z.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/, \"expected a hex colour\");\n\nexport const teamNodeSchema = z.looseObject({\n id: z.string().min(1),\n type: teamTypeSchema,\n label: z.string(),\n description: z.string().optional(),\n position: positionSchema,\n size: sizeSchema,\n fill: hexColor.optional(),\n stroke: hexColor.optional(),\n});\n\nexport const interactionSchema = z.looseObject({\n id: z.string().min(1),\n mode: interactionModeSchema,\n label: z.string().optional(),\n position: positionSchema,\n size: sizeSchema,\n fill: hexColor.optional(),\n stroke: hexColor.optional(),\n});\n\nexport const flowSchema = z.looseObject({\n id: z.string().min(1),\n label: z.string().optional(),\n position: positionSchema,\n size: sizeSchema,\n});\n\nexport const annotationSchema = z.looseObject({\n id: z.string().min(1),\n text: z.string(),\n position: positionSchema,\n size: sizeSchema,\n attachedTo: z.string().min(1).optional(),\n});\n\nexport const documentSchema = z\n .looseObject({\n version: z.literal(DOCUMENT_VERSION),\n title: z.string(),\n nodes: z.array(teamNodeSchema),\n interactions: z.array(interactionSchema),\n flows: z.array(flowSchema),\n annotations: z.array(annotationSchema),\n })\n .superRefine((document, context) => {\n for (const { path, message } of documentIdProblems(document)) {\n context.addIssue({ code: \"custom\", path, message });\n }\n });\n\n/** One reason a document is invalid, at the path of the offending value. */\nexport interface DocumentIssue {\n path: (string | number)[];\n message: string;\n}\n\nexport type ParseResult =\n { ok: true; document: TtDocument } | { ok: false; error: string; issues: DocumentIssue[] };\n\n/**\n * Validates and (if necessary) migrates unknown data into a {@link TtDocument}.\n * Returns a discriminated result rather than throwing so callers can show a\n * friendly message, or point at each offending value (`issues`).\n */\nexport function parseDocument(input: unknown): ParseResult {\n const { document: migrated, interactionFileIndexes } = migrate(input);\n const result = documentSchema.safeParse(migrated);\n if (!result.success) {\n const issues = result.error.issues.map((issue) => ({\n path: pathInFile(\n issue.path.filter((key): key is string | number => typeof key !== \"symbol\"),\n interactionFileIndexes,\n ),\n message: issue.message,\n }));\n return {\n ok: false,\n error: issues.map((i) => `${i.path.join(\".\") || \"(root)\"}: ${i.message}`).join(\"; \"),\n issues,\n };\n }\n return { ok: true, document: result.data as TtDocument };\n}\n\n/** The last document version that modelled interactions as edges without geometry. */\nconst EDGE_INTERACTIONS_VERSION = 1;\n\ninterface Migration {\n document: unknown;\n /** For each interaction the migrated document keeps, its index in the input. */\n interactionFileIndexes: readonly number[];\n}\n\n/**\n * Forward-migrates older document shapes to the current version. v1 modelled\n * interactions as edges (source/target, no geometry) and carried a\n * `showFlowOfChange` flag; v2 makes interactions placed shapes and adds `flows`;\n * v3 adds `annotations`. The edge-interactions of a v1 file can't be placed\n * meaningfully, so they're dropped. From v2 on, an interaction without position\n * or size is refused like any other missing field: dropped, it would vanish from\n * the file on the next save without a word.\n */\nfunction migrate(input: unknown): Migration {\n if (input == null || typeof input !== \"object\") {\n return { document: input, interactionFileIndexes: [] };\n }\n const doc = input as Record<string, unknown>;\n const next: Record<string, unknown> = { ...doc };\n delete next.showFlowOfChange; // v1 flag, gone in v2\n next.version = DOCUMENT_VERSION;\n if (typeof next.title !== \"string\") next.title = \"Untitled team topology\";\n if (!Array.isArray(next.nodes)) next.nodes = [];\n const dropsEdgeInteractions = doc.version === EDGE_INTERACTIONS_VERSION;\n const keptInteractions = Array.isArray(next.interactions)\n ? next.interactions\n .map((interaction: unknown, fileIndex) => ({ interaction, fileIndex }))\n .filter(({ interaction }) => !dropsEdgeInteractions || isPlacedShape(interaction))\n : [];\n next.interactions = keptInteractions.map(({ interaction }) => interaction);\n if (!Array.isArray(next.flows)) next.flows = [];\n if (!Array.isArray(next.annotations)) next.annotations = [];\n return {\n document: next,\n interactionFileIndexes: keptInteractions.map(({ fileIndex }) => fileIndex),\n };\n}\n\nfunction isPlacedShape(value: unknown): boolean {\n return value != null && typeof value === \"object\" && \"position\" in value && \"size\" in value;\n}\n\n/**\n * An issue's path in the input rather than in the migrated document: an editor points at the\n * file, and every legacy interaction dropped before an invalid one would shift its index.\n */\nfunction pathInFile(\n path: (string | number)[],\n interactionFileIndexes: readonly number[],\n): (string | number)[] {\n const [collection, index, ...rest] = path;\n if (collection !== \"interactions\" || typeof index !== \"number\") return path;\n const fileIndex = interactionFileIndexes[index];\n return fileIndex === undefined ? path : [collection, fileIndex, ...rest];\n}\n","/**\n * Fields a document carries that this modeler does not know, such as a vendor's `\"x-vendor\"` on a\n * team. They are kept through open and save, written after the known fields and sorted, so another\n * tool's data survives an edit in the modeler and the output stays deterministic.\n */\n\nexport const DOCUMENT_FIELDS = [\n \"version\",\n \"title\",\n \"nodes\",\n \"interactions\",\n \"flows\",\n \"annotations\",\n] as const;\nexport const TEAM_NODE_FIELDS = [\n \"id\",\n \"type\",\n \"label\",\n \"description\",\n \"position\",\n \"size\",\n \"fill\",\n \"stroke\",\n] as const;\nexport const INTERACTION_FIELDS = [\n \"id\",\n \"mode\",\n \"label\",\n \"position\",\n \"size\",\n \"fill\",\n \"stroke\",\n] as const;\nexport const FLOW_FIELDS = [\"id\", \"label\", \"position\", \"size\"] as const;\nexport const ANNOTATION_FIELDS = [\"id\", \"text\", \"position\", \"size\", \"attachedTo\"] as const;\n\n/** Unknown fields by name, sorted, with their values in canonical form. */\nexport type ForeignFields = Readonly<Record<string, unknown>>;\n\n/** JSON objects have no key order, so nested keys are sorted too: equal data, equal bytes. */\nfunction canonicalValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalValue);\n if (value === null || typeof value !== \"object\") return value;\n const record = value as Record<string, unknown>;\n return Object.fromEntries(\n Object.keys(record)\n .filter((key) => record[key] !== undefined)\n .sort()\n .map((key) => [key, canonicalValue(record[key])]),\n );\n}\n\n/** The fields of `value` outside `knownFields`, or undefined when there are none. */\nexport function foreignFields(\n value: object,\n knownFields: readonly string[],\n): ForeignFields | undefined {\n const record = value as Record<string, unknown>;\n const names = Object.keys(record)\n .filter((name) => !knownFields.includes(name) && record[name] !== undefined)\n .sort();\n if (names.length === 0) return undefined;\n return Object.fromEntries(names.map((name) => [name, canonicalValue(record[name])]));\n}\n\n/**\n * `known` followed by the foreign fields of `source`. Built from entries, never by assignment, so\n * a field named `__proto__` stays a field instead of replacing the prototype.\n */\nexport function withForeignFields<T extends object>(\n known: T,\n source: object | undefined,\n knownFields: readonly string[],\n): T {\n const foreign = source ? foreignFields(source, knownFields) : undefined;\n if (!foreign) return known;\n return Object.fromEntries([...Object.entries(known), ...Object.entries(foreign)]) as T;\n}\n","/**\n * Deterministic serialisation of the document model.\n *\n * Producing byte-stable JSON (sorted arrays, fixed key order, rounded\n * coordinates) makes diagrams diff-friendly in version control and gives\n * stable share URLs / embedded payloads.\n */\n\nimport {\n ANNOTATION_FIELDS,\n DOCUMENT_FIELDS,\n FLOW_FIELDS,\n INTERACTION_FIELDS,\n TEAM_NODE_FIELDS,\n withForeignFields,\n} from \"./foreign\";\nimport { DOCUMENT_VERSION } from \"./types\";\nimport type {\n FlowShape,\n InteractionShape,\n Position,\n Size,\n TeamNode,\n TextAnnotation,\n TtDocument,\n} from \"./types\";\n\n/** Round to 2 decimals to strip floating-point drift from drag operations. */\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nfunction normPosition(p: Position): Position {\n return { x: round(p.x), y: round(p.y) };\n}\n\nfunction normSize(s: Size): Size {\n return { width: round(s.width), height: round(s.height) };\n}\n\n/** Drops undefined fields and applies a fixed key order to a node. */\nfunction normNode(n: TeamNode): TeamNode {\n const out: TeamNode = {\n id: n.id,\n type: n.type,\n label: n.label,\n position: normPosition(n.position),\n size: normSize(n.size),\n };\n if (n.description) out.description = n.description;\n if (n.fill) out.fill = n.fill;\n if (n.stroke) out.stroke = n.stroke;\n return withForeignFields(out, n, TEAM_NODE_FIELDS);\n}\n\nfunction normInteraction(e: InteractionShape): InteractionShape {\n const out: InteractionShape = {\n id: e.id,\n mode: e.mode,\n position: normPosition(e.position),\n size: normSize(e.size),\n };\n if (e.label) out.label = e.label;\n if (e.fill) out.fill = e.fill;\n if (e.stroke) out.stroke = e.stroke;\n return withForeignFields(out, e, INTERACTION_FIELDS);\n}\n\nfunction normFlow(f: FlowShape): FlowShape {\n const out: FlowShape = {\n id: f.id,\n position: normPosition(f.position),\n size: normSize(f.size),\n };\n if (f.label) out.label = f.label;\n return withForeignFields(out, f, FLOW_FIELDS);\n}\n\nfunction normAnnotation(a: TextAnnotation): TextAnnotation {\n const out: TextAnnotation = {\n id: a.id,\n text: a.text,\n position: normPosition(a.position),\n size: normSize(a.size),\n };\n if (a.attachedTo) out.attachedTo = a.attachedTo;\n return withForeignFields(out, a, ANNOTATION_FIELDS);\n}\n\nconst byId = (a: { id: string }, b: { id: string }): number =>\n a.id < b.id ? -1 : a.id > b.id ? 1 : 0;\n\n/**\n * Returns a canonicalised copy of a document (sorted, rounded, version-stamped). Fields the\n * modeler does not know follow the known ones, sorted by name.\n */\nexport function canonicalize(doc: TtDocument): TtDocument {\n return withForeignFields(\n {\n version: DOCUMENT_VERSION,\n title: doc.title,\n nodes: [...doc.nodes].map(normNode).sort(byId),\n interactions: [...doc.interactions].map(normInteraction).sort(byId),\n flows: [...doc.flows].map(normFlow).sort(byId),\n annotations: [...doc.annotations].map(normAnnotation).sort(byId),\n },\n doc,\n DOCUMENT_FIELDS,\n );\n}\n\n/**\n * Serialises a document to deterministic JSON. An empty `annotations` list is left out, so\n * re-saving a model that has no annotations changes nothing but its version stamp. The pretty\n * form is the file on disk and ends with a line break, like the files editors and Git expect;\n * the compact form (share links, local storage) has none.\n */\nexport function serializeDocument(doc: TtDocument, pretty = true): string {\n const canonical = canonicalize(doc);\n const output =\n canonical.annotations.length > 0\n ? canonical\n : Object.fromEntries(Object.entries(canonical).filter(([key]) => key !== \"annotations\"));\n return pretty ? `${JSON.stringify(output, null, 2)}\\n` : JSON.stringify(output);\n}\n","/**\n * Factory helpers for constructing well-formed model objects with the correct\n * notation defaults (sizes, labels). Kept DOM-free.\n */\n\nimport { nanoid } from \"nanoid\";\nimport { ANNOTATION_SPEC, FLOW_SPEC, INTERACTION_MODE_SPECS, TEAM_TYPE_SPECS } from \"./notation\";\nimport type {\n FlowShape,\n InteractionMode,\n InteractionShape,\n Position,\n TeamNode,\n TeamType,\n TextAnnotation,\n TtDocument,\n} from \"./types\";\nimport { DOCUMENT_VERSION } from \"./types\";\n\nexport function newId(prefix: string): string {\n return `${prefix}_${nanoid(8)}`;\n}\n\n/** Creates a team node of the given type at a position, with notation defaults. */\nexport function createTeamNode(\n type: TeamType,\n position: Position,\n overrides: Partial<Omit<TeamNode, \"id\" | \"type\">> = {},\n): TeamNode {\n const spec = TEAM_TYPE_SPECS[type];\n return {\n id: newId(\"team\"),\n type,\n label: overrides.label ?? spec.label,\n description: overrides.description,\n position,\n size: overrides.size ?? { ...spec.defaultSize },\n fill: overrides.fill,\n stroke: overrides.stroke,\n };\n}\n\n/** Creates a placed interaction shape of the given mode, with notation defaults. */\nexport function createInteractionShape(\n mode: InteractionMode,\n position: Position,\n overrides: Partial<Omit<InteractionShape, \"id\" | \"mode\" | \"position\">> = {},\n): InteractionShape {\n const spec = INTERACTION_MODE_SPECS[mode];\n return {\n id: newId(\"int\"),\n mode,\n position,\n size: overrides.size ?? { ...spec.defaultSize },\n label: overrides.label,\n fill: overrides.fill,\n stroke: overrides.stroke,\n };\n}\n\n/** Creates a placed \"flow of change\" arrow, with notation defaults. */\nexport function createFlowShape(\n position: Position,\n overrides: Partial<Omit<FlowShape, \"id\" | \"position\">> = {},\n): FlowShape {\n return {\n id: newId(\"flow\"),\n position,\n size: overrides.size ?? { ...FLOW_SPEC.defaultSize },\n label: overrides.label ?? FLOW_SPEC.label,\n };\n}\n\n/** Creates a text annotation, optionally attached to a team, interaction or flow. */\nexport function createTextAnnotation(\n position: Position,\n overrides: Partial<Omit<TextAnnotation, \"id\" | \"position\">> = {},\n): TextAnnotation {\n return {\n id: newId(\"ann\"),\n text: overrides.text ?? \"\",\n position,\n size: overrides.size ?? { ...ANNOTATION_SPEC.defaultSize },\n attachedTo: overrides.attachedTo,\n };\n}\n\n/** An empty document with sensible defaults. */\nexport function emptyDocument(title = \"Untitled team topology\"): TtDocument {\n return {\n version: DOCUMENT_VERSION,\n title,\n nodes: [],\n interactions: [],\n flows: [],\n annotations: [],\n };\n}\n","/**\n * A small but complete example diagram exercising all four team types, all three\n * interaction modes (as placed shapes overlaying the team boundaries), a\n * flow-of-change element and an attached annotation. The stream-aligned teams\n * are stacked as parallel lanes along the flow of change, as in the Team\n * Topologies book: side by side on the flow they would read as hand-offs. Ids are\n * fixed so the fixture serialises stably.\n */\n\nimport { DOCUMENT_VERSION } from \"./types\";\nimport type { TtDocument } from \"./types\";\nimport { ANNOTATION_SPEC, INTERACTION_MODE_SPECS, TEAM_TYPE_SPECS } from \"./notation\";\n\nconst s = TEAM_TYPE_SPECS;\nconst i = INTERACTION_MODE_SPECS;\n\nconst LANE_WIDTH = 600;\n\nexport const SAMPLE_DOCUMENT: TtDocument = {\n version: DOCUMENT_VERSION,\n title: \"Online shop team topology\",\n nodes: [\n {\n id: \"team_test_automation\",\n type: \"enabling\",\n label: \"Test Automation\",\n description: \"Coaches stream-aligned teams in test automation, then steps back.\",\n position: { x: 40, y: 150 },\n size: { width: s.enabling.defaultSize.width, height: 222 },\n },\n {\n id: \"team_discovery\",\n type: \"stream-aligned\",\n label: \"Product Discovery\",\n description: \"Owns search, browsing and product pages end-to-end.\",\n position: { x: 220, y: 150 },\n size: { width: LANE_WIDTH, height: s[\"stream-aligned\"].defaultSize.height },\n },\n {\n id: \"team_checkout\",\n type: \"stream-aligned\",\n label: \"Checkout & Payments\",\n description: \"Owns the checkout and payment journey end-to-end.\",\n position: { x: 220, y: 276 },\n size: { width: LANE_WIDTH, height: s[\"stream-aligned\"].defaultSize.height },\n },\n {\n id: \"team_fulfilment\",\n type: \"stream-aligned\",\n label: \"Order Fulfilment\",\n description: \"Owns delivery, tracking and returns end-to-end.\",\n position: { x: 220, y: 402 },\n size: { width: LANE_WIDTH, height: s[\"stream-aligned\"].defaultSize.height },\n },\n {\n id: \"team_fraud\",\n type: \"complicated-subsystem\",\n label: \"Fraud Detection\",\n description: \"Specialists for the real-time fraud scoring model.\",\n position: { x: 880, y: 249 },\n size: { ...s[\"complicated-subsystem\"].defaultSize },\n },\n {\n id: \"team_platform\",\n type: \"platform\",\n label: \"Cloud Platform\",\n description: \"Self-service CI/CD, runtime and observability for all teams.\",\n position: { x: 220, y: 552 },\n size: { width: LANE_WIDTH, height: 110 },\n },\n ],\n interactions: [\n {\n id: \"int_testing_discovery\",\n mode: \"facilitating\",\n position: { x: 148, y: 156 },\n size: { ...i.facilitating.defaultSize },\n },\n {\n id: \"int_testing_checkout\",\n mode: \"facilitating\",\n position: { x: 148, y: 282 },\n size: { ...i.facilitating.defaultSize },\n },\n {\n id: \"int_checkout_fraud\",\n mode: \"collaboration\",\n label: \"fraud rules\",\n position: { x: 794, y: 288 },\n size: { ...i.collaboration.defaultSize },\n },\n {\n id: \"int_platform_fulfilment\",\n mode: \"x-as-a-service\",\n position: { x: 476, y: 486 },\n size: { ...i[\"x-as-a-service\"].defaultSize },\n },\n ],\n flows: [\n {\n id: \"flow_main\",\n label: \"Flow of change\",\n position: { x: 40, y: 40 },\n size: { width: 1010, height: 56 },\n },\n ],\n annotations: [\n {\n id: \"ann_fraud_handover\",\n text: \"Collaboration until the fraud rules are stable (Q3), then X-as-a-Service\",\n position: { x: 880, y: 423 },\n size: { ...ANNOTATION_SPEC.defaultSize },\n attachedTo: \"int_checkout_fraud\",\n },\n ],\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/notation.ts","../src/ids.ts","../src/schema.ts","../src/foreign.ts","../src/serialize.ts","../src/factory.ts","../src/sample.ts"],"names":["z","i","s","nanoid"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Pure (DOM-free) domain types for the Team Topologies model.\n *\n * This module is the canonical representation of a diagram and must never\n * import from the rendering layer (`@xyflow/react`) or touch the DOM, so it\n * can be unit-tested in isolation and reused across views / exporters.\n */\n\n/** MIME type used when dragging a team type from the palette onto the canvas. */\nexport const DND_MIME = \"application/x-tt-team-type\";\n\n/** The four fundamental team types in Team Topologies. */\nexport type TeamType = \"stream-aligned\" | \"enabling\" | \"complicated-subsystem\" | \"platform\";\n\nexport const TEAM_TYPES: readonly TeamType[] = [\n \"stream-aligned\",\n \"enabling\",\n \"complicated-subsystem\",\n \"platform\",\n] as const;\n\n/** The three core team interaction modes in Team Topologies. */\nexport type InteractionMode = \"collaboration\" | \"x-as-a-service\" | \"facilitating\";\n\nexport const INTERACTION_MODES: readonly InteractionMode[] = [\n \"collaboration\",\n \"x-as-a-service\",\n \"facilitating\",\n] as const;\n\n/** Geometric size of a node in canvas units (px). Encodes cognitive load. */\nexport interface Size {\n width: number;\n height: number;\n}\n\n/** Position of a node on the canvas in canvas units (px). */\nexport interface Position {\n x: number;\n y: number;\n}\n\n/** A team node in the canonical document model. */\nexport interface TeamNode {\n id: string;\n type: TeamType;\n label: string;\n description?: string;\n position: Position;\n size: Size;\n fill?: string;\n stroke?: string;\n}\n\n/**\n * An interaction in the canonical document model.\n *\n * Per the official Team Topologies notation, an interaction is a placed,\n * resizable SHAPE (parallelogram / triangle / circle) overlaid on the boundary\n * between the teams it relates to — not a connecting line. The relationship is\n * therefore spatial (overlap), so there is no source/target reference.\n */\nexport interface InteractionShape {\n id: string;\n mode: InteractionMode;\n label?: string;\n position: Position;\n size: Size;\n fill?: string;\n stroke?: string;\n}\n\n/**\n * A \"flow of change\" guide: a placed, resizable arrow element. Lets you anchor\n * the implied left-to-right flow, and visualise several team groupings on one\n * canvas.\n */\nexport interface FlowShape {\n id: string;\n label?: string;\n position: Position;\n size: Size;\n}\n\n/**\n * A free-text note beside the diagram (like a BPMN text annotation). It either\n * stands alone or is attached to exactly one team, interaction or flow, which\n * its dashed connector points at.\n */\nexport interface TextAnnotation {\n id: string;\n text: string;\n position: Position;\n size: Size;\n /** Id of the team, interaction or flow this annotation is attached to. */\n attachedTo?: string;\n}\n\n/** Current document schema version. Bump + add a migration when shape changes. */\nexport const DOCUMENT_VERSION = 3 as const;\n\n/**\n * A complete Team Topologies diagram. This is what gets serialised to JSON,\n * embedded into exported images, and encoded into share URLs.\n */\nexport interface TtDocument {\n version: typeof DOCUMENT_VERSION;\n title: string;\n nodes: TeamNode[];\n interactions: InteractionShape[];\n flows: FlowShape[];\n annotations: TextAnnotation[];\n}\n","/**\n * The Team Topologies visual notation, encoded as data.\n *\n * Colours, shapes and stroke styles follow the official\n * \"Team-Shape-Templates\" specification published by Team Topologies\n * (https://github.com/TeamTopologies/Team-Shape-Templates):\n *\n * - Team shapes are SOLID outlines (long-lived structures).\n * - Interaction-mode shapes are 50% transparent with DASHED outlines\n * (short-lived interactions).\n * - Each element is distinguished by SHAPE as well as colour, so the\n * notation stays readable for people with colour-vision deficiency.\n *\n * This module is pure data — it must not import the rendering layer.\n */\n\nimport type { InteractionMode, Size, TeamType } from \"./types\";\n\nexport type TeamShape = \"rounded-rect-horizontal\" | \"rounded-rect-vertical\" | \"octagon\" | \"rect\";\n\nexport type InteractionGlyph = \"parallelogram\" | \"triangle\" | \"circle\";\n\nexport type StrokeStyle = \"solid\" | \"dashed\" | \"dotted\";\n\nexport interface TeamTypeSpec {\n type: TeamType;\n /** Short display name. */\n label: string;\n /** One-line purpose, shown in the palette and inspector. */\n description: string;\n shape: TeamShape;\n fill: string;\n stroke: string;\n strokeStyle: StrokeStyle;\n strokeWidth: number;\n /** Default size when a node of this type is created. */\n defaultSize: Size;\n /** Minimum size enforced by the resizer. */\n minSize: Size;\n}\n\nexport interface InteractionModeSpec {\n mode: InteractionMode;\n label: string;\n description: string;\n shape: InteractionGlyph;\n fill: string;\n stroke: string;\n strokeStyle: StrokeStyle;\n strokeWidth: number;\n /**\n * The templates' fill opacity (short-lived → translucent). The renderer premixes the fill over\n * white at it and draws it opaque.\n */\n opacity: number;\n /** Whether direction is semantically meaningful (the X-as-a-Service triangle). */\n directional: boolean;\n /** Default size when a shape of this mode is created. */\n defaultSize: Size;\n /** Minimum size enforced by the resizer. */\n minSize: Size;\n}\n\n/** The left-to-right \"flow of change\" guide, a placeable annotation element. */\nexport interface FlowSpec {\n label: string;\n fill: string;\n stroke: string;\n strokeStyle: StrokeStyle;\n strokeWidth: number;\n defaultSize: Size;\n minSize: Size;\n}\n\n// The official notation colours (Team-Shape-Templates, above): foreign notation, guide §10.6.\n// brand-lint-disable\nexport const TEAM_TYPE_SPECS: Record<TeamType, TeamTypeSpec> = {\n \"stream-aligned\": {\n type: \"stream-aligned\",\n label: \"Stream-aligned\",\n description: \"Aligned to a single, valuable stream of work; owns it end-to-end.\",\n shape: \"rounded-rect-horizontal\",\n fill: \"#FFEDB8\",\n stroke: \"#FFD966\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 240, height: 96 },\n minSize: { width: 140, height: 64 },\n },\n enabling: {\n type: \"enabling\",\n label: \"Enabling\",\n description:\n \"Helps stream-aligned teams acquire missing capabilities; coaches, then steps back.\",\n shape: \"rounded-rect-vertical\",\n fill: \"#DFBDCF\",\n stroke: \"#D09CB7\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 120, height: 200 },\n minSize: { width: 80, height: 120 },\n },\n \"complicated-subsystem\": {\n type: \"complicated-subsystem\",\n label: \"Complicated Subsystem\",\n description:\n \"Owns a part of the system needing deep specialist knowledge, reducing others' cognitive load.\",\n shape: \"octagon\",\n fill: \"#FFC08B\",\n stroke: \"#E88814\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 170, height: 150 },\n minSize: { width: 110, height: 100 },\n },\n platform: {\n type: \"platform\",\n label: \"Platform\",\n description:\n \"Provides internal self-service capabilities to reduce cognitive load for stream-aligned teams.\",\n shape: \"rect\",\n fill: \"#B7CDF1\",\n stroke: \"#6D9EEB\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 380, height: 130 },\n minSize: { width: 200, height: 90 },\n },\n};\n\nexport const INTERACTION_MODE_SPECS: Record<InteractionMode, InteractionModeSpec> = {\n collaboration: {\n mode: \"collaboration\",\n label: \"Collaboration\",\n description:\n \"Two teams work closely together for a defined period; high overhead, high discovery.\",\n shape: \"parallelogram\",\n fill: \"#C6BEDF\",\n stroke: \"#967EE2\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n opacity: 0.5,\n directional: false,\n defaultSize: { width: 112, height: 72 },\n minSize: { width: 60, height: 44 },\n },\n \"x-as-a-service\": {\n mode: \"x-as-a-service\",\n label: \"X-as-a-Service\",\n description:\n \"One team consumes something the other provides 'as a service'; minimal collaboration.\",\n shape: \"triangle\",\n fill: \"#B4B4B4\",\n stroke: \"#999696\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n opacity: 0.5,\n directional: true,\n defaultSize: { width: 88, height: 78 },\n minSize: { width: 54, height: 48 },\n },\n facilitating: {\n mode: \"facilitating\",\n label: \"Facilitating\",\n description:\n \"One team helps/coaches another to clear impediments and learn; sensing and discovery.\",\n shape: \"circle\",\n fill: \"#C9DFBE\",\n stroke: \"#78996B\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n opacity: 0.5,\n directional: false,\n defaultSize: { width: 84, height: 84 },\n minSize: { width: 48, height: 48 },\n },\n};\n\n/**\n * The \"flow of change\" guide — a placeable dashed arrow (left-to-right).\n * Not a team or interaction: a standalone annotation element.\n */\nexport const FLOW_SPEC: FlowSpec = {\n label: \"Flow of change\",\n fill: \"transparent\",\n stroke: \"#6b6459\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n defaultSize: { width: 520, height: 64 },\n minSize: { width: 160, height: 36 },\n};\n// brand-lint-enable\n\n/**\n * A text annotation — not part of the Team Topologies notation, so it carries\n * no colours here; the renderer draws it in the neutral brand ink.\n */\nexport interface AnnotationSpec {\n label: string;\n defaultSize: Size;\n minSize: Size;\n}\n\nexport const ANNOTATION_SPEC: AnnotationSpec = {\n label: \"Annotation\",\n defaultSize: { width: 200, height: 64 },\n minSize: { width: 60, height: 30 },\n};\n\n/** Maps a stroke style to an SVG/CSS dash array (empty string = solid). */\nexport function dashArray(style: StrokeStyle, strokeWidth = 2): string {\n switch (style) {\n case \"dashed\":\n return `${strokeWidth * 3} ${strokeWidth * 2}`;\n case \"dotted\":\n return `${strokeWidth} ${strokeWidth * 1.5}`;\n case \"solid\":\n default:\n return \"\";\n }\n}\n\nexport const ALL_TEAM_SPECS: readonly TeamTypeSpec[] = Object.values(TEAM_TYPE_SPECS);\nexport const ALL_INTERACTION_SPECS: readonly InteractionModeSpec[] =\n Object.values(INTERACTION_MODE_SPECS);\n","/**\n * The id rules of a Team Topologies document. Besides the elements a document lists, a diagram\n * holds parts it never writes down: the diagram itself and the connector of every annotation. They\n * take ids of their own, so no element may use one of them; otherwise opening the file would fail\n * halfway, with the previous diagram already gone. The canvas also keeps its elements in a plain\n * object, where the names of JavaScript's built-in object properties already resolve.\n */\n\n/** The id of the diagram itself (the canvas root of the renderer). */\nexport const DIAGRAM_ROOT_ID = \"tt-root\";\n\n/** diagram-js names the roots it creates on its own `__implicitroot_<n>`. */\nconst ENGINE_ROOT_ID_PREFIX = \"__implicitroot\";\n\n/** Connectors are not stored: an annotation's connector derives its id from the annotation. */\nexport function associationId(annotationId: string): string {\n return `assoc_${annotationId}`;\n}\n\nexport interface DocumentIdProblem {\n /** Where the offending id sits, e.g. `[\"nodes\", 2, \"id\"]`. */\n path: (string | number)[];\n message: string;\n}\n\nconst COLLECTIONS = [\"nodes\", \"interactions\", \"flows\", \"annotations\"] as const;\n\ntype DocumentElements = Record<(typeof COLLECTIONS)[number], readonly { id: string }[]>;\n\n/** Ids such as `constructor`, `toString` or `__proto__`, which every plain object already has. */\nfunction isBuiltInPropertyId(id: string): boolean {\n return Object.hasOwn(Object.prototype, id);\n}\n\n/**\n * Every id of the document that would collide on the canvas: a duplicate, the diagram's own id, a\n * diagram-js root id, the name of a built-in object property, or the id of an annotation's\n * connector.\n */\nexport function documentIdProblems(doc: DocumentElements): DocumentIdProblem[] {\n const problems: DocumentIdProblem[] = [];\n const connectorIds = new Map(\n doc.annotations.map((annotation) => [associationId(annotation.id), annotation.id]),\n );\n const seen = new Set<string>();\n for (const collection of COLLECTIONS) {\n doc[collection].forEach((element, index) => {\n const path = [collection, index, \"id\"];\n const { id } = element;\n if (seen.has(id)) {\n problems.push({\n path,\n message: `duplicate id \"${id}\"; ids must be unique across nodes, interactions, flows and annotations`,\n });\n }\n seen.add(id);\n if (id === DIAGRAM_ROOT_ID) {\n problems.push({ path, message: `\"${id}\" is reserved for the diagram itself` });\n } else if (id.startsWith(ENGINE_ROOT_ID_PREFIX)) {\n problems.push({\n path,\n message: `ids starting with \"${ENGINE_ROOT_ID_PREFIX}\" are reserved`,\n });\n } else if (isBuiltInPropertyId(id)) {\n problems.push({\n path,\n message: `\"${id}\" is reserved: it names a built-in property of JavaScript objects`,\n });\n }\n const annotationId = connectorIds.get(id);\n if (annotationId !== undefined) {\n problems.push({\n path,\n message: `\"${id}\" is reserved for the connector of annotation \"${annotationId}\"`,\n });\n }\n });\n }\n return problems;\n}\n","/**\n * Runtime validation for the document model using Zod.\n *\n * Anything entering the app from the outside world (imported files, share\n * URLs, localStorage) is parsed through {@link parseDocument} so malformed or\n * tampered data can never corrupt the editor state. Fields the schema does not\n * know pass through untouched (see `foreign.ts`), so another tool's data\n * survives a save.\n */\n\nimport { z } from \"zod\";\nimport { documentIdProblems } from \"./ids\";\nimport { DOCUMENT_VERSION, INTERACTION_MODES, TEAM_TYPES } from \"./types\";\nimport type { TtDocument } from \"./types\";\n\nconst teamTypeSchema = z.enum(TEAM_TYPES as unknown as [string, ...string[]]);\nconst interactionModeSchema = z.enum(INTERACTION_MODES as unknown as [string, ...string[]]);\n\nconst sizeSchema = z.object({\n width: z.number().finite().positive(),\n height: z.number().finite().positive(),\n});\n\nconst positionSchema = z.object({\n x: z.number().finite(),\n y: z.number().finite(),\n});\n\nconst hexColor = z.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/, \"expected a hex colour\");\n\nexport const teamNodeSchema = z.looseObject({\n id: z.string().min(1),\n type: teamTypeSchema,\n label: z.string(),\n description: z.string().optional(),\n position: positionSchema,\n size: sizeSchema,\n fill: hexColor.optional(),\n stroke: hexColor.optional(),\n});\n\nexport const interactionSchema = z.looseObject({\n id: z.string().min(1),\n mode: interactionModeSchema,\n label: z.string().optional(),\n position: positionSchema,\n size: sizeSchema,\n fill: hexColor.optional(),\n stroke: hexColor.optional(),\n});\n\nexport const flowSchema = z.looseObject({\n id: z.string().min(1),\n label: z.string().optional(),\n position: positionSchema,\n size: sizeSchema,\n});\n\nexport const annotationSchema = z.looseObject({\n id: z.string().min(1),\n text: z.string(),\n position: positionSchema,\n size: sizeSchema,\n attachedTo: z.string().min(1).optional(),\n});\n\nexport const documentSchema = z\n .looseObject({\n version: z.literal(DOCUMENT_VERSION),\n title: z.string(),\n nodes: z.array(teamNodeSchema),\n interactions: z.array(interactionSchema),\n flows: z.array(flowSchema),\n annotations: z.array(annotationSchema),\n })\n .superRefine((document, context) => {\n for (const { path, message } of documentIdProblems(document)) {\n context.addIssue({ code: \"custom\", path, message });\n }\n });\n\n/** One reason a document is invalid, at the path of the offending value. */\nexport interface DocumentIssue {\n path: (string | number)[];\n message: string;\n}\n\nexport type ParseResult =\n { ok: true; document: TtDocument } | { ok: false; error: string; issues: DocumentIssue[] };\n\n/**\n * Objects and arrays nested deeper than this make a document invalid, the document itself counting\n * as the first level. The serializer, structured cloning and JSON tooling such as jsonc-parser\n * descend one call per level and overflow the stack a few thousand levels down; a Team Topologies\n * document needs four.\n */\nexport const MAX_NESTING_DEPTH = 100;\n\n/**\n * Validates and (if necessary) migrates unknown data into a {@link TtDocument}.\n * Returns a discriminated result rather than throwing so callers can show a\n * friendly message, or point at each offending value (`issues`).\n */\nexport function parseDocument(input: unknown): ParseResult {\n const tooDeep = nestingIssues(input);\n if (tooDeep.length > 0) return refused(tooDeep);\n const { document: migrated, interactionFileIndexes } = migrate(input);\n const result = documentSchema.safeParse(migrated);\n if (!result.success) {\n return refused(\n result.error.issues.map((issue) => ({\n path: pathInFile(\n issue.path.filter((key): key is string | number => typeof key !== \"symbol\"),\n interactionFileIndexes,\n ),\n message: issue.message,\n })),\n );\n }\n return { ok: true, document: result.data as TtDocument };\n}\n\nfunction refused(issues: DocumentIssue[]): ParseResult {\n return {\n ok: false,\n error: issues.map((i) => `${i.path.join(\".\") || \"(root)\"}: ${i.message}`).join(\"; \"),\n issues,\n };\n}\n\n/**\n * Every object or array at the first level too deep, in document order; what lies below it is not\n * visited. Walked with an explicit stack, because the documents it guards against are the ones that\n * overflow a recursive walk.\n */\nfunction nestingIssues(input: unknown): DocumentIssue[] {\n const issues: DocumentIssue[] = [];\n const pending: { value: unknown; path: (string | number)[] }[] = [{ value: input, path: [] }];\n while (pending.length > 0) {\n const { value, path } = pending.pop()!;\n if (typeof value !== \"object\" || value === null) continue;\n if (path.length >= MAX_NESTING_DEPTH) {\n issues.push({\n path,\n message: `objects and arrays may nest at most ${MAX_NESTING_DEPTH} levels deep`,\n });\n continue;\n }\n // Array.from visits the holes of a sparse array as undefined; map would keep them as holes.\n const entries: [string | number, unknown][] = Array.isArray(value)\n ? Array.from(value, (entry: unknown, index) => [index, entry])\n : Object.entries(value);\n for (const [key, entry] of entries.reverse()) {\n if (typeof entry === \"object\" && entry !== null) {\n pending.push({ value: entry, path: [...path, key] });\n }\n }\n }\n return issues;\n}\n\n/** The last document version that modelled interactions as edges without geometry. */\nconst EDGE_INTERACTIONS_VERSION = 1;\n\ninterface Migration {\n document: unknown;\n /** For each interaction the migrated document keeps, its index in the input. */\n interactionFileIndexes: readonly number[];\n}\n\n/**\n * Forward-migrates older document shapes to the current version. v1 modelled\n * interactions as edges (source/target, no geometry) and carried a\n * `showFlowOfChange` flag; v2 makes interactions placed shapes and adds `flows`;\n * v3 adds `annotations`. The edge-interactions of a v1 file can't be placed\n * meaningfully, so they're dropped. From v2 on, an interaction without position\n * or size is refused like any other missing field: dropped, it would vanish from\n * the file on the next save without a word.\n */\nfunction migrate(input: unknown): Migration {\n if (input == null || typeof input !== \"object\") {\n return { document: input, interactionFileIndexes: [] };\n }\n const doc = input as Record<string, unknown>;\n const next: Record<string, unknown> = { ...doc };\n delete next.showFlowOfChange; // v1 flag, gone in v2\n next.version = DOCUMENT_VERSION;\n if (typeof next.title !== \"string\") next.title = \"Untitled team topology\";\n if (!Array.isArray(next.nodes)) next.nodes = [];\n const dropsEdgeInteractions = doc.version === EDGE_INTERACTIONS_VERSION;\n const keptInteractions = Array.isArray(next.interactions)\n ? next.interactions\n .map((interaction: unknown, fileIndex) => ({ interaction, fileIndex }))\n .filter(({ interaction }) => !dropsEdgeInteractions || isPlacedShape(interaction))\n : [];\n next.interactions = keptInteractions.map(({ interaction }) => interaction);\n if (!Array.isArray(next.flows)) next.flows = [];\n if (!Array.isArray(next.annotations)) next.annotations = [];\n return {\n document: next,\n interactionFileIndexes: keptInteractions.map(({ fileIndex }) => fileIndex),\n };\n}\n\nfunction isPlacedShape(value: unknown): boolean {\n return value != null && typeof value === \"object\" && \"position\" in value && \"size\" in value;\n}\n\n/**\n * An issue's path in the input rather than in the migrated document: an editor points at the\n * file, and every legacy interaction dropped before an invalid one would shift its index.\n */\nfunction pathInFile(\n path: (string | number)[],\n interactionFileIndexes: readonly number[],\n): (string | number)[] {\n const [collection, index, ...rest] = path;\n if (collection !== \"interactions\" || typeof index !== \"number\") return path;\n const fileIndex = interactionFileIndexes[index];\n return fileIndex === undefined ? path : [collection, fileIndex, ...rest];\n}\n","/**\n * Fields a document carries that this modeler does not know, such as a vendor's `\"x-vendor\"` on a\n * team. They are kept through open and save, written after the known fields and sorted, so another\n * tool's data survives an edit in the modeler and the output stays deterministic.\n */\n\nexport const DOCUMENT_FIELDS = [\n \"version\",\n \"title\",\n \"nodes\",\n \"interactions\",\n \"flows\",\n \"annotations\",\n] as const;\nexport const TEAM_NODE_FIELDS = [\n \"id\",\n \"type\",\n \"label\",\n \"description\",\n \"position\",\n \"size\",\n \"fill\",\n \"stroke\",\n] as const;\nexport const INTERACTION_FIELDS = [\n \"id\",\n \"mode\",\n \"label\",\n \"position\",\n \"size\",\n \"fill\",\n \"stroke\",\n] as const;\nexport const FLOW_FIELDS = [\"id\", \"label\", \"position\", \"size\"] as const;\nexport const ANNOTATION_FIELDS = [\"id\", \"text\", \"position\", \"size\", \"attachedTo\"] as const;\n\n/** Unknown fields by name, sorted, with their values in canonical form. */\nexport type ForeignFields = Readonly<Record<string, unknown>>;\n\n/** JSON objects have no key order, so nested keys are sorted too: equal data, equal bytes. */\nfunction canonicalValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalValue);\n if (value === null || typeof value !== \"object\") return value;\n const record = value as Record<string, unknown>;\n return Object.fromEntries(\n Object.keys(record)\n .filter((key) => record[key] !== undefined)\n .sort()\n .map((key) => [key, canonicalValue(record[key])]),\n );\n}\n\n/** The fields of `value` outside `knownFields`, or undefined when there are none. */\nexport function foreignFields(\n value: object,\n knownFields: readonly string[],\n): ForeignFields | undefined {\n const record = value as Record<string, unknown>;\n const names = Object.keys(record)\n .filter((name) => !knownFields.includes(name) && record[name] !== undefined)\n .sort();\n if (names.length === 0) return undefined;\n return Object.fromEntries(names.map((name) => [name, canonicalValue(record[name])]));\n}\n\n/**\n * `known` followed by the foreign fields of `source`. Built from entries, never by assignment, so\n * a field named `__proto__` stays a field instead of replacing the prototype.\n */\nexport function withForeignFields<T extends object>(\n known: T,\n source: object | undefined,\n knownFields: readonly string[],\n): T {\n const foreign = source ? foreignFields(source, knownFields) : undefined;\n if (!foreign) return known;\n return Object.fromEntries([...Object.entries(known), ...Object.entries(foreign)]) as T;\n}\n","/**\n * Deterministic serialisation of the document model.\n *\n * Producing byte-stable JSON (sorted arrays, fixed key order, rounded\n * coordinates) makes diagrams diff-friendly in version control and gives\n * stable share URLs / embedded payloads.\n */\n\nimport {\n ANNOTATION_FIELDS,\n DOCUMENT_FIELDS,\n FLOW_FIELDS,\n INTERACTION_FIELDS,\n TEAM_NODE_FIELDS,\n withForeignFields,\n} from \"./foreign\";\nimport { DOCUMENT_VERSION } from \"./types\";\nimport type {\n FlowShape,\n InteractionShape,\n Position,\n Size,\n TeamNode,\n TextAnnotation,\n TtDocument,\n} from \"./types\";\n\n/** Round to 2 decimals to strip floating-point drift from drag operations. */\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nfunction normPosition(p: Position): Position {\n return { x: round(p.x), y: round(p.y) };\n}\n\nfunction normSize(s: Size): Size {\n return { width: round(s.width), height: round(s.height) };\n}\n\n/** Drops undefined fields and applies a fixed key order to a node. */\nfunction normNode(n: TeamNode): TeamNode {\n const out: TeamNode = {\n id: n.id,\n type: n.type,\n label: n.label,\n position: normPosition(n.position),\n size: normSize(n.size),\n };\n if (n.description) out.description = n.description;\n if (n.fill) out.fill = n.fill;\n if (n.stroke) out.stroke = n.stroke;\n return withForeignFields(out, n, TEAM_NODE_FIELDS);\n}\n\nfunction normInteraction(e: InteractionShape): InteractionShape {\n const out: InteractionShape = {\n id: e.id,\n mode: e.mode,\n position: normPosition(e.position),\n size: normSize(e.size),\n };\n if (e.label) out.label = e.label;\n if (e.fill) out.fill = e.fill;\n if (e.stroke) out.stroke = e.stroke;\n return withForeignFields(out, e, INTERACTION_FIELDS);\n}\n\nfunction normFlow(f: FlowShape): FlowShape {\n const out: FlowShape = {\n id: f.id,\n position: normPosition(f.position),\n size: normSize(f.size),\n };\n if (f.label) out.label = f.label;\n return withForeignFields(out, f, FLOW_FIELDS);\n}\n\nfunction normAnnotation(a: TextAnnotation): TextAnnotation {\n const out: TextAnnotation = {\n id: a.id,\n text: a.text,\n position: normPosition(a.position),\n size: normSize(a.size),\n };\n if (a.attachedTo) out.attachedTo = a.attachedTo;\n return withForeignFields(out, a, ANNOTATION_FIELDS);\n}\n\nconst byId = (a: { id: string }, b: { id: string }): number =>\n a.id < b.id ? -1 : a.id > b.id ? 1 : 0;\n\n/**\n * Returns a canonicalised copy of a document (sorted, rounded, version-stamped). Fields the\n * modeler does not know follow the known ones, sorted by name.\n */\nexport function canonicalize(doc: TtDocument): TtDocument {\n return withForeignFields(\n {\n version: DOCUMENT_VERSION,\n title: doc.title,\n nodes: [...doc.nodes].map(normNode).sort(byId),\n interactions: [...doc.interactions].map(normInteraction).sort(byId),\n flows: [...doc.flows].map(normFlow).sort(byId),\n annotations: [...doc.annotations].map(normAnnotation).sort(byId),\n },\n doc,\n DOCUMENT_FIELDS,\n );\n}\n\n/**\n * Serialises a document to deterministic JSON. An empty `annotations` list is left out, so\n * re-saving a model that has no annotations changes nothing but its version stamp. The pretty\n * form is the file on disk and ends with a line break, like the files editors and Git expect;\n * the compact form (share links, local storage) has none.\n */\nexport function serializeDocument(doc: TtDocument, pretty = true): string {\n const canonical = canonicalize(doc);\n const output =\n canonical.annotations.length > 0\n ? canonical\n : Object.fromEntries(Object.entries(canonical).filter(([key]) => key !== \"annotations\"));\n return pretty ? `${JSON.stringify(output, null, 2)}\\n` : JSON.stringify(output);\n}\n","/**\n * Factory helpers for constructing well-formed model objects with the correct\n * notation defaults (sizes, labels). Kept DOM-free.\n */\n\nimport { nanoid } from \"nanoid\";\nimport { ANNOTATION_SPEC, FLOW_SPEC, INTERACTION_MODE_SPECS, TEAM_TYPE_SPECS } from \"./notation\";\nimport type {\n FlowShape,\n InteractionMode,\n InteractionShape,\n Position,\n TeamNode,\n TeamType,\n TextAnnotation,\n TtDocument,\n} from \"./types\";\nimport { DOCUMENT_VERSION } from \"./types\";\n\nexport function newId(prefix: string): string {\n return `${prefix}_${nanoid(8)}`;\n}\n\n/** Creates a team node of the given type at a position, with notation defaults. */\nexport function createTeamNode(\n type: TeamType,\n position: Position,\n overrides: Partial<Omit<TeamNode, \"id\" | \"type\">> = {},\n): TeamNode {\n const spec = TEAM_TYPE_SPECS[type];\n return {\n id: newId(\"team\"),\n type,\n label: overrides.label ?? spec.label,\n description: overrides.description,\n position,\n size: overrides.size ?? { ...spec.defaultSize },\n fill: overrides.fill,\n stroke: overrides.stroke,\n };\n}\n\n/** Creates a placed interaction shape of the given mode, with notation defaults. */\nexport function createInteractionShape(\n mode: InteractionMode,\n position: Position,\n overrides: Partial<Omit<InteractionShape, \"id\" | \"mode\" | \"position\">> = {},\n): InteractionShape {\n const spec = INTERACTION_MODE_SPECS[mode];\n return {\n id: newId(\"int\"),\n mode,\n position,\n size: overrides.size ?? { ...spec.defaultSize },\n label: overrides.label,\n fill: overrides.fill,\n stroke: overrides.stroke,\n };\n}\n\n/** Creates a placed \"flow of change\" arrow, with notation defaults. */\nexport function createFlowShape(\n position: Position,\n overrides: Partial<Omit<FlowShape, \"id\" | \"position\">> = {},\n): FlowShape {\n return {\n id: newId(\"flow\"),\n position,\n size: overrides.size ?? { ...FLOW_SPEC.defaultSize },\n label: overrides.label ?? FLOW_SPEC.label,\n };\n}\n\n/** Creates a text annotation, optionally attached to a team, interaction or flow. */\nexport function createTextAnnotation(\n position: Position,\n overrides: Partial<Omit<TextAnnotation, \"id\" | \"position\">> = {},\n): TextAnnotation {\n return {\n id: newId(\"ann\"),\n text: overrides.text ?? \"\",\n position,\n size: overrides.size ?? { ...ANNOTATION_SPEC.defaultSize },\n attachedTo: overrides.attachedTo,\n };\n}\n\n/** An empty document with sensible defaults. */\nexport function emptyDocument(title = \"Untitled team topology\"): TtDocument {\n return {\n version: DOCUMENT_VERSION,\n title,\n nodes: [],\n interactions: [],\n flows: [],\n annotations: [],\n };\n}\n","/**\n * A small but complete example diagram exercising all four team types, all three\n * interaction modes (as placed shapes overlaying the team boundaries), a\n * flow-of-change element and an attached annotation. The stream-aligned teams\n * are stacked as parallel lanes along the flow of change, as in the Team\n * Topologies book: side by side on the flow they would read as hand-offs. Ids are\n * fixed so the fixture serialises stably.\n */\n\nimport { DOCUMENT_VERSION } from \"./types\";\nimport type { TtDocument } from \"./types\";\nimport { ANNOTATION_SPEC, INTERACTION_MODE_SPECS, TEAM_TYPE_SPECS } from \"./notation\";\n\nconst s = TEAM_TYPE_SPECS;\nconst i = INTERACTION_MODE_SPECS;\n\nconst LANE_WIDTH = 600;\n\nexport const SAMPLE_DOCUMENT: TtDocument = {\n version: DOCUMENT_VERSION,\n title: \"Online shop team topology\",\n nodes: [\n {\n id: \"team_test_automation\",\n type: \"enabling\",\n label: \"Test Automation\",\n description: \"Coaches stream-aligned teams in test automation, then steps back.\",\n position: { x: 40, y: 150 },\n size: { width: s.enabling.defaultSize.width, height: 222 },\n },\n {\n id: \"team_discovery\",\n type: \"stream-aligned\",\n label: \"Product Discovery\",\n description: \"Owns search, browsing and product pages end-to-end.\",\n position: { x: 220, y: 150 },\n size: { width: LANE_WIDTH, height: s[\"stream-aligned\"].defaultSize.height },\n },\n {\n id: \"team_checkout\",\n type: \"stream-aligned\",\n label: \"Checkout & Payments\",\n description: \"Owns the checkout and payment journey end-to-end.\",\n position: { x: 220, y: 276 },\n size: { width: LANE_WIDTH, height: s[\"stream-aligned\"].defaultSize.height },\n },\n {\n id: \"team_fulfilment\",\n type: \"stream-aligned\",\n label: \"Order Fulfilment\",\n description: \"Owns delivery, tracking and returns end-to-end.\",\n position: { x: 220, y: 402 },\n size: { width: LANE_WIDTH, height: s[\"stream-aligned\"].defaultSize.height },\n },\n {\n id: \"team_fraud\",\n type: \"complicated-subsystem\",\n label: \"Fraud Detection\",\n description: \"Specialists for the real-time fraud scoring model.\",\n position: { x: 880, y: 249 },\n size: { ...s[\"complicated-subsystem\"].defaultSize },\n },\n {\n id: \"team_platform\",\n type: \"platform\",\n label: \"Cloud Platform\",\n description: \"Self-service CI/CD, runtime and observability for all teams.\",\n position: { x: 220, y: 552 },\n size: { width: LANE_WIDTH, height: 110 },\n },\n ],\n interactions: [\n {\n id: \"int_testing_discovery\",\n mode: \"facilitating\",\n position: { x: 148, y: 156 },\n size: { ...i.facilitating.defaultSize },\n },\n {\n id: \"int_testing_checkout\",\n mode: \"facilitating\",\n position: { x: 148, y: 282 },\n size: { ...i.facilitating.defaultSize },\n },\n {\n id: \"int_checkout_fraud\",\n mode: \"collaboration\",\n label: \"fraud rules\",\n position: { x: 794, y: 288 },\n size: { ...i.collaboration.defaultSize },\n },\n {\n id: \"int_platform_fulfilment\",\n mode: \"x-as-a-service\",\n position: { x: 476, y: 486 },\n size: { ...i[\"x-as-a-service\"].defaultSize },\n },\n ],\n flows: [\n {\n id: \"flow_main\",\n label: \"Flow of change\",\n position: { x: 40, y: 40 },\n size: { width: 1010, height: 56 },\n },\n ],\n annotations: [\n {\n id: \"ann_fraud_handover\",\n text: \"Collaboration until the fraud rules are stable (Q3), then X-as-a-Service\",\n position: { x: 880, y: 423 },\n size: { ...ANNOTATION_SPEC.defaultSize },\n attachedTo: \"int_checkout_fraud\",\n },\n ],\n};\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -136,7 +136,10 @@ interface InteractionModeSpec {
|
|
|
136
136
|
stroke: string;
|
|
137
137
|
strokeStyle: StrokeStyle;
|
|
138
138
|
strokeWidth: number;
|
|
139
|
-
/**
|
|
139
|
+
/**
|
|
140
|
+
* The templates' fill opacity (short-lived → translucent). The renderer premixes the fill over
|
|
141
|
+
* white at it and draws it opaque.
|
|
142
|
+
*/
|
|
140
143
|
opacity: number;
|
|
141
144
|
/** Whether direction is semantically meaningful (the X-as-a-Service triangle). */
|
|
142
145
|
directional: boolean;
|
|
@@ -324,6 +327,13 @@ type ParseResult = {
|
|
|
324
327
|
error: string;
|
|
325
328
|
issues: DocumentIssue[];
|
|
326
329
|
};
|
|
330
|
+
/**
|
|
331
|
+
* Objects and arrays nested deeper than this make a document invalid, the document itself counting
|
|
332
|
+
* as the first level. The serializer, structured cloning and JSON tooling such as jsonc-parser
|
|
333
|
+
* descend one call per level and overflow the stack a few thousand levels down; a Team Topologies
|
|
334
|
+
* document needs four.
|
|
335
|
+
*/
|
|
336
|
+
declare const MAX_NESTING_DEPTH = 100;
|
|
327
337
|
/**
|
|
328
338
|
* Validates and (if necessary) migrates unknown data into a {@link TtDocument}.
|
|
329
339
|
* Returns a discriminated result rather than throwing so callers can show a
|
|
@@ -427,4 +437,5 @@ declare function emptyDocument(title?: string): TtDocument;
|
|
|
427
437
|
|
|
428
438
|
declare const SAMPLE_DOCUMENT: TtDocument;
|
|
429
439
|
|
|
430
|
-
export { ALL_INTERACTION_SPECS, ALL_TEAM_SPECS, ANNOTATION_FIELDS, ANNOTATION_SPEC,
|
|
440
|
+
export { ALL_INTERACTION_SPECS, ALL_TEAM_SPECS, ANNOTATION_FIELDS, ANNOTATION_SPEC, DIAGRAM_ROOT_ID, DND_MIME, DOCUMENT_FIELDS, DOCUMENT_VERSION, FLOW_FIELDS, FLOW_SPEC, INTERACTION_FIELDS, INTERACTION_MODES, INTERACTION_MODE_SPECS, MAX_NESTING_DEPTH, SAMPLE_DOCUMENT, TEAM_NODE_FIELDS, TEAM_TYPES, TEAM_TYPE_SPECS, annotationSchema, associationId, canonicalize, createFlowShape, createInteractionShape, createTeamNode, createTextAnnotation, dashArray, documentIdProblems, documentSchema, emptyDocument, flowSchema, foreignFields, interactionSchema, newId, parseDocument, serializeDocument, teamNodeSchema, withForeignFields };
|
|
441
|
+
export type { AnnotationSpec, DocumentIdProblem, DocumentIssue, FlowShape, FlowSpec, ForeignFields, InteractionGlyph, InteractionMode, InteractionModeSpec, InteractionShape, ParseResult, Position, Size, StrokeStyle, TeamNode, TeamShape, TeamType, TeamTypeSpec, TextAnnotation, TtDocument };
|
package/dist/index.d.ts
CHANGED
|
@@ -136,7 +136,10 @@ interface InteractionModeSpec {
|
|
|
136
136
|
stroke: string;
|
|
137
137
|
strokeStyle: StrokeStyle;
|
|
138
138
|
strokeWidth: number;
|
|
139
|
-
/**
|
|
139
|
+
/**
|
|
140
|
+
* The templates' fill opacity (short-lived → translucent). The renderer premixes the fill over
|
|
141
|
+
* white at it and draws it opaque.
|
|
142
|
+
*/
|
|
140
143
|
opacity: number;
|
|
141
144
|
/** Whether direction is semantically meaningful (the X-as-a-Service triangle). */
|
|
142
145
|
directional: boolean;
|
|
@@ -324,6 +327,13 @@ type ParseResult = {
|
|
|
324
327
|
error: string;
|
|
325
328
|
issues: DocumentIssue[];
|
|
326
329
|
};
|
|
330
|
+
/**
|
|
331
|
+
* Objects and arrays nested deeper than this make a document invalid, the document itself counting
|
|
332
|
+
* as the first level. The serializer, structured cloning and JSON tooling such as jsonc-parser
|
|
333
|
+
* descend one call per level and overflow the stack a few thousand levels down; a Team Topologies
|
|
334
|
+
* document needs four.
|
|
335
|
+
*/
|
|
336
|
+
declare const MAX_NESTING_DEPTH = 100;
|
|
327
337
|
/**
|
|
328
338
|
* Validates and (if necessary) migrates unknown data into a {@link TtDocument}.
|
|
329
339
|
* Returns a discriminated result rather than throwing so callers can show a
|
|
@@ -427,4 +437,5 @@ declare function emptyDocument(title?: string): TtDocument;
|
|
|
427
437
|
|
|
428
438
|
declare const SAMPLE_DOCUMENT: TtDocument;
|
|
429
439
|
|
|
430
|
-
export { ALL_INTERACTION_SPECS, ALL_TEAM_SPECS, ANNOTATION_FIELDS, ANNOTATION_SPEC,
|
|
440
|
+
export { ALL_INTERACTION_SPECS, ALL_TEAM_SPECS, ANNOTATION_FIELDS, ANNOTATION_SPEC, DIAGRAM_ROOT_ID, DND_MIME, DOCUMENT_FIELDS, DOCUMENT_VERSION, FLOW_FIELDS, FLOW_SPEC, INTERACTION_FIELDS, INTERACTION_MODES, INTERACTION_MODE_SPECS, MAX_NESTING_DEPTH, SAMPLE_DOCUMENT, TEAM_NODE_FIELDS, TEAM_TYPES, TEAM_TYPE_SPECS, annotationSchema, associationId, canonicalize, createFlowShape, createInteractionShape, createTeamNode, createTextAnnotation, dashArray, documentIdProblems, documentSchema, emptyDocument, flowSchema, foreignFields, interactionSchema, newId, parseDocument, serializeDocument, teamNodeSchema, withForeignFields };
|
|
441
|
+
export type { AnnotationSpec, DocumentIdProblem, DocumentIssue, FlowShape, FlowSpec, ForeignFields, InteractionGlyph, InteractionMode, InteractionModeSpec, InteractionShape, ParseResult, Position, Size, StrokeStyle, TeamNode, TeamShape, TeamType, TeamTypeSpec, TextAnnotation, TtDocument };
|
package/dist/index.js
CHANGED
|
@@ -247,25 +247,54 @@ var documentSchema = z.looseObject({
|
|
|
247
247
|
context.addIssue({ code: "custom", path, message });
|
|
248
248
|
}
|
|
249
249
|
});
|
|
250
|
+
var MAX_NESTING_DEPTH = 100;
|
|
250
251
|
function parseDocument(input) {
|
|
252
|
+
const tooDeep = nestingIssues(input);
|
|
253
|
+
if (tooDeep.length > 0) return refused(tooDeep);
|
|
251
254
|
const { document: migrated, interactionFileIndexes } = migrate(input);
|
|
252
255
|
const result = documentSchema.safeParse(migrated);
|
|
253
256
|
if (!result.success) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
error: issues.map((i2) => `${i2.path.join(".") || "(root)"}: ${i2.message}`).join("; "),
|
|
264
|
-
issues
|
|
265
|
-
};
|
|
257
|
+
return refused(
|
|
258
|
+
result.error.issues.map((issue) => ({
|
|
259
|
+
path: pathInFile(
|
|
260
|
+
issue.path.filter((key) => typeof key !== "symbol"),
|
|
261
|
+
interactionFileIndexes
|
|
262
|
+
),
|
|
263
|
+
message: issue.message
|
|
264
|
+
}))
|
|
265
|
+
);
|
|
266
266
|
}
|
|
267
267
|
return { ok: true, document: result.data };
|
|
268
268
|
}
|
|
269
|
+
function refused(issues) {
|
|
270
|
+
return {
|
|
271
|
+
ok: false,
|
|
272
|
+
error: issues.map((i2) => `${i2.path.join(".") || "(root)"}: ${i2.message}`).join("; "),
|
|
273
|
+
issues
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function nestingIssues(input) {
|
|
277
|
+
const issues = [];
|
|
278
|
+
const pending = [{ value: input, path: [] }];
|
|
279
|
+
while (pending.length > 0) {
|
|
280
|
+
const { value, path } = pending.pop();
|
|
281
|
+
if (typeof value !== "object" || value === null) continue;
|
|
282
|
+
if (path.length >= MAX_NESTING_DEPTH) {
|
|
283
|
+
issues.push({
|
|
284
|
+
path,
|
|
285
|
+
message: `objects and arrays may nest at most ${MAX_NESTING_DEPTH} levels deep`
|
|
286
|
+
});
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
const entries = Array.isArray(value) ? Array.from(value, (entry, index) => [index, entry]) : Object.entries(value);
|
|
290
|
+
for (const [key, entry] of entries.reverse()) {
|
|
291
|
+
if (typeof entry === "object" && entry !== null) {
|
|
292
|
+
pending.push({ value: entry, path: [...path, key] });
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return issues;
|
|
297
|
+
}
|
|
269
298
|
var EDGE_INTERACTIONS_VERSION = 1;
|
|
270
299
|
function migrate(input) {
|
|
271
300
|
if (input == null || typeof input !== "object") {
|
|
@@ -581,6 +610,6 @@ var SAMPLE_DOCUMENT = {
|
|
|
581
610
|
]
|
|
582
611
|
};
|
|
583
612
|
|
|
584
|
-
export { ALL_INTERACTION_SPECS, ALL_TEAM_SPECS, ANNOTATION_FIELDS, ANNOTATION_SPEC, DIAGRAM_ROOT_ID, DND_MIME, DOCUMENT_FIELDS, DOCUMENT_VERSION, FLOW_FIELDS, FLOW_SPEC, INTERACTION_FIELDS, INTERACTION_MODES, INTERACTION_MODE_SPECS, SAMPLE_DOCUMENT, TEAM_NODE_FIELDS, TEAM_TYPES, TEAM_TYPE_SPECS, annotationSchema, associationId, canonicalize, createFlowShape, createInteractionShape, createTeamNode, createTextAnnotation, dashArray, documentIdProblems, documentSchema, emptyDocument, flowSchema, foreignFields, interactionSchema, newId, parseDocument, serializeDocument, teamNodeSchema, withForeignFields };
|
|
613
|
+
export { ALL_INTERACTION_SPECS, ALL_TEAM_SPECS, ANNOTATION_FIELDS, ANNOTATION_SPEC, DIAGRAM_ROOT_ID, DND_MIME, DOCUMENT_FIELDS, DOCUMENT_VERSION, FLOW_FIELDS, FLOW_SPEC, INTERACTION_FIELDS, INTERACTION_MODES, INTERACTION_MODE_SPECS, MAX_NESTING_DEPTH, SAMPLE_DOCUMENT, TEAM_NODE_FIELDS, TEAM_TYPES, TEAM_TYPE_SPECS, annotationSchema, associationId, canonicalize, createFlowShape, createInteractionShape, createTeamNode, createTextAnnotation, dashArray, documentIdProblems, documentSchema, emptyDocument, flowSchema, foreignFields, interactionSchema, newId, parseDocument, serializeDocument, teamNodeSchema, withForeignFields };
|
|
585
614
|
//# sourceMappingURL=index.js.map
|
|
586
615
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/notation.ts","../src/ids.ts","../src/schema.ts","../src/foreign.ts","../src/serialize.ts","../src/factory.ts","../src/sample.ts"],"names":["i","s"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Pure (DOM-free) domain types for the Team Topologies model.\n *\n * This module is the canonical representation of a diagram and must never\n * import from the rendering layer (`@xyflow/react`) or touch the DOM, so it\n * can be unit-tested in isolation and reused across views / exporters.\n */\n\n/** MIME type used when dragging a team type from the palette onto the canvas. */\nexport const DND_MIME = \"application/x-tt-team-type\";\n\n/** The four fundamental team types in Team Topologies. */\nexport type TeamType = \"stream-aligned\" | \"enabling\" | \"complicated-subsystem\" | \"platform\";\n\nexport const TEAM_TYPES: readonly TeamType[] = [\n \"stream-aligned\",\n \"enabling\",\n \"complicated-subsystem\",\n \"platform\",\n] as const;\n\n/** The three core team interaction modes in Team Topologies. */\nexport type InteractionMode = \"collaboration\" | \"x-as-a-service\" | \"facilitating\";\n\nexport const INTERACTION_MODES: readonly InteractionMode[] = [\n \"collaboration\",\n \"x-as-a-service\",\n \"facilitating\",\n] as const;\n\n/** Geometric size of a node in canvas units (px). Encodes cognitive load. */\nexport interface Size {\n width: number;\n height: number;\n}\n\n/** Position of a node on the canvas in canvas units (px). */\nexport interface Position {\n x: number;\n y: number;\n}\n\n/** A team node in the canonical document model. */\nexport interface TeamNode {\n id: string;\n type: TeamType;\n label: string;\n description?: string;\n position: Position;\n size: Size;\n fill?: string;\n stroke?: string;\n}\n\n/**\n * An interaction in the canonical document model.\n *\n * Per the official Team Topologies notation, an interaction is a placed,\n * resizable SHAPE (parallelogram / triangle / circle) overlaid on the boundary\n * between the teams it relates to — not a connecting line. The relationship is\n * therefore spatial (overlap), so there is no source/target reference.\n */\nexport interface InteractionShape {\n id: string;\n mode: InteractionMode;\n label?: string;\n position: Position;\n size: Size;\n fill?: string;\n stroke?: string;\n}\n\n/**\n * A \"flow of change\" guide: a placed, resizable arrow element. Lets you anchor\n * the implied left-to-right flow, and visualise several team groupings on one\n * canvas.\n */\nexport interface FlowShape {\n id: string;\n label?: string;\n position: Position;\n size: Size;\n}\n\n/**\n * A free-text note beside the diagram (like a BPMN text annotation). It either\n * stands alone or is attached to exactly one team, interaction or flow, which\n * its dashed connector points at.\n */\nexport interface TextAnnotation {\n id: string;\n text: string;\n position: Position;\n size: Size;\n /** Id of the team, interaction or flow this annotation is attached to. */\n attachedTo?: string;\n}\n\n/** Current document schema version. Bump + add a migration when shape changes. */\nexport const DOCUMENT_VERSION = 3 as const;\n\n/**\n * A complete Team Topologies diagram. This is what gets serialised to JSON,\n * embedded into exported images, and encoded into share URLs.\n */\nexport interface TtDocument {\n version: typeof DOCUMENT_VERSION;\n title: string;\n nodes: TeamNode[];\n interactions: InteractionShape[];\n flows: FlowShape[];\n annotations: TextAnnotation[];\n}\n","/**\n * The Team Topologies visual notation, encoded as data.\n *\n * Colours, shapes and stroke styles follow the official\n * \"Team-Shape-Templates\" specification published by Team Topologies\n * (https://github.com/TeamTopologies/Team-Shape-Templates):\n *\n * - Team shapes are SOLID outlines (long-lived structures).\n * - Interaction-mode shapes are 50% transparent with DASHED outlines\n * (short-lived interactions).\n * - Each element is distinguished by SHAPE as well as colour, so the\n * notation stays readable for people with colour-vision deficiency.\n *\n * This module is pure data — it must not import the rendering layer.\n */\n\nimport type { InteractionMode, Size, TeamType } from \"./types\";\n\nexport type TeamShape = \"rounded-rect-horizontal\" | \"rounded-rect-vertical\" | \"octagon\" | \"rect\";\n\nexport type InteractionGlyph = \"parallelogram\" | \"triangle\" | \"circle\";\n\nexport type StrokeStyle = \"solid\" | \"dashed\" | \"dotted\";\n\nexport interface TeamTypeSpec {\n type: TeamType;\n /** Short display name. */\n label: string;\n /** One-line purpose, shown in the palette and inspector. */\n description: string;\n shape: TeamShape;\n fill: string;\n stroke: string;\n strokeStyle: StrokeStyle;\n strokeWidth: number;\n /** Default size when a node of this type is created. */\n defaultSize: Size;\n /** Minimum size enforced by the resizer. */\n minSize: Size;\n}\n\nexport interface InteractionModeSpec {\n mode: InteractionMode;\n label: string;\n description: string;\n shape: InteractionGlyph;\n fill: string;\n stroke: string;\n strokeStyle: StrokeStyle;\n strokeWidth: number;\n /** Opacity for the interaction shape (short-lived → translucent). */\n opacity: number;\n /** Whether direction is semantically meaningful (the X-as-a-Service triangle). */\n directional: boolean;\n /** Default size when a shape of this mode is created. */\n defaultSize: Size;\n /** Minimum size enforced by the resizer. */\n minSize: Size;\n}\n\n/** The left-to-right \"flow of change\" guide, a placeable annotation element. */\nexport interface FlowSpec {\n label: string;\n fill: string;\n stroke: string;\n strokeStyle: StrokeStyle;\n strokeWidth: number;\n defaultSize: Size;\n minSize: Size;\n}\n\nexport const TEAM_TYPE_SPECS: Record<TeamType, TeamTypeSpec> = {\n \"stream-aligned\": {\n type: \"stream-aligned\",\n label: \"Stream-aligned\",\n description: \"Aligned to a single, valuable stream of work; owns it end-to-end.\",\n shape: \"rounded-rect-horizontal\",\n fill: \"#FFEDB8\",\n stroke: \"#FFD966\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 240, height: 96 },\n minSize: { width: 140, height: 64 },\n },\n enabling: {\n type: \"enabling\",\n label: \"Enabling\",\n description:\n \"Helps stream-aligned teams acquire missing capabilities; coaches, then steps back.\",\n shape: \"rounded-rect-vertical\",\n fill: \"#DFBDCF\",\n stroke: \"#D09CB7\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 120, height: 200 },\n minSize: { width: 80, height: 120 },\n },\n \"complicated-subsystem\": {\n type: \"complicated-subsystem\",\n label: \"Complicated Subsystem\",\n description:\n \"Owns a part of the system needing deep specialist knowledge, reducing others' cognitive load.\",\n shape: \"octagon\",\n fill: \"#FFC08B\",\n stroke: \"#E88814\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 170, height: 150 },\n minSize: { width: 110, height: 100 },\n },\n platform: {\n type: \"platform\",\n label: \"Platform\",\n description:\n \"Provides internal self-service capabilities to reduce cognitive load for stream-aligned teams.\",\n shape: \"rect\",\n fill: \"#B7CDF1\",\n stroke: \"#6D9EEB\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 380, height: 130 },\n minSize: { width: 200, height: 90 },\n },\n};\n\nexport const INTERACTION_MODE_SPECS: Record<InteractionMode, InteractionModeSpec> = {\n collaboration: {\n mode: \"collaboration\",\n label: \"Collaboration\",\n description:\n \"Two teams work closely together for a defined period; high overhead, high discovery.\",\n shape: \"parallelogram\",\n fill: \"#C6BEDF\",\n stroke: \"#967EE2\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n opacity: 0.5,\n directional: false,\n defaultSize: { width: 112, height: 72 },\n minSize: { width: 60, height: 44 },\n },\n \"x-as-a-service\": {\n mode: \"x-as-a-service\",\n label: \"X-as-a-Service\",\n description:\n \"One team consumes something the other provides 'as a service'; minimal collaboration.\",\n shape: \"triangle\",\n fill: \"#B4B4B4\",\n stroke: \"#999696\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n opacity: 0.5,\n directional: true,\n defaultSize: { width: 88, height: 78 },\n minSize: { width: 54, height: 48 },\n },\n facilitating: {\n mode: \"facilitating\",\n label: \"Facilitating\",\n description:\n \"One team helps/coaches another to clear impediments and learn; sensing and discovery.\",\n shape: \"circle\",\n fill: \"#C9DFBE\",\n stroke: \"#78996B\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n opacity: 0.5,\n directional: false,\n defaultSize: { width: 84, height: 84 },\n minSize: { width: 48, height: 48 },\n },\n};\n\n/**\n * The \"flow of change\" guide — a placeable dashed arrow (left-to-right).\n * Not a team or interaction: a standalone annotation element.\n */\nexport const FLOW_SPEC: FlowSpec = {\n label: \"Flow of change\",\n fill: \"transparent\",\n stroke: \"#6b6459\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n defaultSize: { width: 520, height: 64 },\n minSize: { width: 160, height: 36 },\n};\n\n/**\n * A text annotation — not part of the Team Topologies notation, so it carries\n * no colours here; the renderer draws it in the neutral brand ink.\n */\nexport interface AnnotationSpec {\n label: string;\n defaultSize: Size;\n minSize: Size;\n}\n\nexport const ANNOTATION_SPEC: AnnotationSpec = {\n label: \"Annotation\",\n defaultSize: { width: 200, height: 64 },\n minSize: { width: 60, height: 30 },\n};\n\n/** Maps a stroke style to an SVG/CSS dash array (empty string = solid). */\nexport function dashArray(style: StrokeStyle, strokeWidth = 2): string {\n switch (style) {\n case \"dashed\":\n return `${strokeWidth * 3} ${strokeWidth * 2}`;\n case \"dotted\":\n return `${strokeWidth} ${strokeWidth * 1.5}`;\n case \"solid\":\n default:\n return \"\";\n }\n}\n\nexport const ALL_TEAM_SPECS: readonly TeamTypeSpec[] = Object.values(TEAM_TYPE_SPECS);\nexport const ALL_INTERACTION_SPECS: readonly InteractionModeSpec[] =\n Object.values(INTERACTION_MODE_SPECS);\n","/**\n * The id rules of a Team Topologies document. Besides the elements a document lists, a diagram\n * holds parts it never writes down: the diagram itself and the connector of every annotation. They\n * take ids of their own, so no element may use one of them; otherwise opening the file would fail\n * halfway, with the previous diagram already gone. The canvas also keeps its elements in a plain\n * object, where the names of JavaScript's built-in object properties already resolve.\n */\n\n/** The id of the diagram itself (the canvas root of the renderer). */\nexport const DIAGRAM_ROOT_ID = \"tt-root\";\n\n/** diagram-js names the roots it creates on its own `__implicitroot_<n>`. */\nconst ENGINE_ROOT_ID_PREFIX = \"__implicitroot\";\n\n/** Connectors are not stored: an annotation's connector derives its id from the annotation. */\nexport function associationId(annotationId: string): string {\n return `assoc_${annotationId}`;\n}\n\nexport interface DocumentIdProblem {\n /** Where the offending id sits, e.g. `[\"nodes\", 2, \"id\"]`. */\n path: (string | number)[];\n message: string;\n}\n\nconst COLLECTIONS = [\"nodes\", \"interactions\", \"flows\", \"annotations\"] as const;\n\ntype DocumentElements = Record<(typeof COLLECTIONS)[number], readonly { id: string }[]>;\n\n/** Ids such as `constructor`, `toString` or `__proto__`, which every plain object already has. */\nfunction isBuiltInPropertyId(id: string): boolean {\n return Object.hasOwn(Object.prototype, id);\n}\n\n/**\n * Every id of the document that would collide on the canvas: a duplicate, the diagram's own id, a\n * diagram-js root id, the name of a built-in object property, or the id of an annotation's\n * connector.\n */\nexport function documentIdProblems(doc: DocumentElements): DocumentIdProblem[] {\n const problems: DocumentIdProblem[] = [];\n const connectorIds = new Map(\n doc.annotations.map((annotation) => [associationId(annotation.id), annotation.id]),\n );\n const seen = new Set<string>();\n for (const collection of COLLECTIONS) {\n doc[collection].forEach((element, index) => {\n const path = [collection, index, \"id\"];\n const { id } = element;\n if (seen.has(id)) {\n problems.push({\n path,\n message: `duplicate id \"${id}\"; ids must be unique across nodes, interactions, flows and annotations`,\n });\n }\n seen.add(id);\n if (id === DIAGRAM_ROOT_ID) {\n problems.push({ path, message: `\"${id}\" is reserved for the diagram itself` });\n } else if (id.startsWith(ENGINE_ROOT_ID_PREFIX)) {\n problems.push({\n path,\n message: `ids starting with \"${ENGINE_ROOT_ID_PREFIX}\" are reserved`,\n });\n } else if (isBuiltInPropertyId(id)) {\n problems.push({\n path,\n message: `\"${id}\" is reserved: it names a built-in property of JavaScript objects`,\n });\n }\n const annotationId = connectorIds.get(id);\n if (annotationId !== undefined) {\n problems.push({\n path,\n message: `\"${id}\" is reserved for the connector of annotation \"${annotationId}\"`,\n });\n }\n });\n }\n return problems;\n}\n","/**\n * Runtime validation for the document model using Zod.\n *\n * Anything entering the app from the outside world (imported files, share\n * URLs, localStorage) is parsed through {@link parseDocument} so malformed or\n * tampered data can never corrupt the editor state. Fields the schema does not\n * know pass through untouched (see `foreign.ts`), so another tool's data\n * survives a save.\n */\n\nimport { z } from \"zod\";\nimport { documentIdProblems } from \"./ids\";\nimport { DOCUMENT_VERSION, INTERACTION_MODES, TEAM_TYPES } from \"./types\";\nimport type { TtDocument } from \"./types\";\n\nconst teamTypeSchema = z.enum(TEAM_TYPES as unknown as [string, ...string[]]);\nconst interactionModeSchema = z.enum(INTERACTION_MODES as unknown as [string, ...string[]]);\n\nconst sizeSchema = z.object({\n width: z.number().finite().positive(),\n height: z.number().finite().positive(),\n});\n\nconst positionSchema = z.object({\n x: z.number().finite(),\n y: z.number().finite(),\n});\n\nconst hexColor = z.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/, \"expected a hex colour\");\n\nexport const teamNodeSchema = z.looseObject({\n id: z.string().min(1),\n type: teamTypeSchema,\n label: z.string(),\n description: z.string().optional(),\n position: positionSchema,\n size: sizeSchema,\n fill: hexColor.optional(),\n stroke: hexColor.optional(),\n});\n\nexport const interactionSchema = z.looseObject({\n id: z.string().min(1),\n mode: interactionModeSchema,\n label: z.string().optional(),\n position: positionSchema,\n size: sizeSchema,\n fill: hexColor.optional(),\n stroke: hexColor.optional(),\n});\n\nexport const flowSchema = z.looseObject({\n id: z.string().min(1),\n label: z.string().optional(),\n position: positionSchema,\n size: sizeSchema,\n});\n\nexport const annotationSchema = z.looseObject({\n id: z.string().min(1),\n text: z.string(),\n position: positionSchema,\n size: sizeSchema,\n attachedTo: z.string().min(1).optional(),\n});\n\nexport const documentSchema = z\n .looseObject({\n version: z.literal(DOCUMENT_VERSION),\n title: z.string(),\n nodes: z.array(teamNodeSchema),\n interactions: z.array(interactionSchema),\n flows: z.array(flowSchema),\n annotations: z.array(annotationSchema),\n })\n .superRefine((document, context) => {\n for (const { path, message } of documentIdProblems(document)) {\n context.addIssue({ code: \"custom\", path, message });\n }\n });\n\n/** One reason a document is invalid, at the path of the offending value. */\nexport interface DocumentIssue {\n path: (string | number)[];\n message: string;\n}\n\nexport type ParseResult =\n { ok: true; document: TtDocument } | { ok: false; error: string; issues: DocumentIssue[] };\n\n/**\n * Validates and (if necessary) migrates unknown data into a {@link TtDocument}.\n * Returns a discriminated result rather than throwing so callers can show a\n * friendly message, or point at each offending value (`issues`).\n */\nexport function parseDocument(input: unknown): ParseResult {\n const { document: migrated, interactionFileIndexes } = migrate(input);\n const result = documentSchema.safeParse(migrated);\n if (!result.success) {\n const issues = result.error.issues.map((issue) => ({\n path: pathInFile(\n issue.path.filter((key): key is string | number => typeof key !== \"symbol\"),\n interactionFileIndexes,\n ),\n message: issue.message,\n }));\n return {\n ok: false,\n error: issues.map((i) => `${i.path.join(\".\") || \"(root)\"}: ${i.message}`).join(\"; \"),\n issues,\n };\n }\n return { ok: true, document: result.data as TtDocument };\n}\n\n/** The last document version that modelled interactions as edges without geometry. */\nconst EDGE_INTERACTIONS_VERSION = 1;\n\ninterface Migration {\n document: unknown;\n /** For each interaction the migrated document keeps, its index in the input. */\n interactionFileIndexes: readonly number[];\n}\n\n/**\n * Forward-migrates older document shapes to the current version. v1 modelled\n * interactions as edges (source/target, no geometry) and carried a\n * `showFlowOfChange` flag; v2 makes interactions placed shapes and adds `flows`;\n * v3 adds `annotations`. The edge-interactions of a v1 file can't be placed\n * meaningfully, so they're dropped. From v2 on, an interaction without position\n * or size is refused like any other missing field: dropped, it would vanish from\n * the file on the next save without a word.\n */\nfunction migrate(input: unknown): Migration {\n if (input == null || typeof input !== \"object\") {\n return { document: input, interactionFileIndexes: [] };\n }\n const doc = input as Record<string, unknown>;\n const next: Record<string, unknown> = { ...doc };\n delete next.showFlowOfChange; // v1 flag, gone in v2\n next.version = DOCUMENT_VERSION;\n if (typeof next.title !== \"string\") next.title = \"Untitled team topology\";\n if (!Array.isArray(next.nodes)) next.nodes = [];\n const dropsEdgeInteractions = doc.version === EDGE_INTERACTIONS_VERSION;\n const keptInteractions = Array.isArray(next.interactions)\n ? next.interactions\n .map((interaction: unknown, fileIndex) => ({ interaction, fileIndex }))\n .filter(({ interaction }) => !dropsEdgeInteractions || isPlacedShape(interaction))\n : [];\n next.interactions = keptInteractions.map(({ interaction }) => interaction);\n if (!Array.isArray(next.flows)) next.flows = [];\n if (!Array.isArray(next.annotations)) next.annotations = [];\n return {\n document: next,\n interactionFileIndexes: keptInteractions.map(({ fileIndex }) => fileIndex),\n };\n}\n\nfunction isPlacedShape(value: unknown): boolean {\n return value != null && typeof value === \"object\" && \"position\" in value && \"size\" in value;\n}\n\n/**\n * An issue's path in the input rather than in the migrated document: an editor points at the\n * file, and every legacy interaction dropped before an invalid one would shift its index.\n */\nfunction pathInFile(\n path: (string | number)[],\n interactionFileIndexes: readonly number[],\n): (string | number)[] {\n const [collection, index, ...rest] = path;\n if (collection !== \"interactions\" || typeof index !== \"number\") return path;\n const fileIndex = interactionFileIndexes[index];\n return fileIndex === undefined ? path : [collection, fileIndex, ...rest];\n}\n","/**\n * Fields a document carries that this modeler does not know, such as a vendor's `\"x-vendor\"` on a\n * team. They are kept through open and save, written after the known fields and sorted, so another\n * tool's data survives an edit in the modeler and the output stays deterministic.\n */\n\nexport const DOCUMENT_FIELDS = [\n \"version\",\n \"title\",\n \"nodes\",\n \"interactions\",\n \"flows\",\n \"annotations\",\n] as const;\nexport const TEAM_NODE_FIELDS = [\n \"id\",\n \"type\",\n \"label\",\n \"description\",\n \"position\",\n \"size\",\n \"fill\",\n \"stroke\",\n] as const;\nexport const INTERACTION_FIELDS = [\n \"id\",\n \"mode\",\n \"label\",\n \"position\",\n \"size\",\n \"fill\",\n \"stroke\",\n] as const;\nexport const FLOW_FIELDS = [\"id\", \"label\", \"position\", \"size\"] as const;\nexport const ANNOTATION_FIELDS = [\"id\", \"text\", \"position\", \"size\", \"attachedTo\"] as const;\n\n/** Unknown fields by name, sorted, with their values in canonical form. */\nexport type ForeignFields = Readonly<Record<string, unknown>>;\n\n/** JSON objects have no key order, so nested keys are sorted too: equal data, equal bytes. */\nfunction canonicalValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalValue);\n if (value === null || typeof value !== \"object\") return value;\n const record = value as Record<string, unknown>;\n return Object.fromEntries(\n Object.keys(record)\n .filter((key) => record[key] !== undefined)\n .sort()\n .map((key) => [key, canonicalValue(record[key])]),\n );\n}\n\n/** The fields of `value` outside `knownFields`, or undefined when there are none. */\nexport function foreignFields(\n value: object,\n knownFields: readonly string[],\n): ForeignFields | undefined {\n const record = value as Record<string, unknown>;\n const names = Object.keys(record)\n .filter((name) => !knownFields.includes(name) && record[name] !== undefined)\n .sort();\n if (names.length === 0) return undefined;\n return Object.fromEntries(names.map((name) => [name, canonicalValue(record[name])]));\n}\n\n/**\n * `known` followed by the foreign fields of `source`. Built from entries, never by assignment, so\n * a field named `__proto__` stays a field instead of replacing the prototype.\n */\nexport function withForeignFields<T extends object>(\n known: T,\n source: object | undefined,\n knownFields: readonly string[],\n): T {\n const foreign = source ? foreignFields(source, knownFields) : undefined;\n if (!foreign) return known;\n return Object.fromEntries([...Object.entries(known), ...Object.entries(foreign)]) as T;\n}\n","/**\n * Deterministic serialisation of the document model.\n *\n * Producing byte-stable JSON (sorted arrays, fixed key order, rounded\n * coordinates) makes diagrams diff-friendly in version control and gives\n * stable share URLs / embedded payloads.\n */\n\nimport {\n ANNOTATION_FIELDS,\n DOCUMENT_FIELDS,\n FLOW_FIELDS,\n INTERACTION_FIELDS,\n TEAM_NODE_FIELDS,\n withForeignFields,\n} from \"./foreign\";\nimport { DOCUMENT_VERSION } from \"./types\";\nimport type {\n FlowShape,\n InteractionShape,\n Position,\n Size,\n TeamNode,\n TextAnnotation,\n TtDocument,\n} from \"./types\";\n\n/** Round to 2 decimals to strip floating-point drift from drag operations. */\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nfunction normPosition(p: Position): Position {\n return { x: round(p.x), y: round(p.y) };\n}\n\nfunction normSize(s: Size): Size {\n return { width: round(s.width), height: round(s.height) };\n}\n\n/** Drops undefined fields and applies a fixed key order to a node. */\nfunction normNode(n: TeamNode): TeamNode {\n const out: TeamNode = {\n id: n.id,\n type: n.type,\n label: n.label,\n position: normPosition(n.position),\n size: normSize(n.size),\n };\n if (n.description) out.description = n.description;\n if (n.fill) out.fill = n.fill;\n if (n.stroke) out.stroke = n.stroke;\n return withForeignFields(out, n, TEAM_NODE_FIELDS);\n}\n\nfunction normInteraction(e: InteractionShape): InteractionShape {\n const out: InteractionShape = {\n id: e.id,\n mode: e.mode,\n position: normPosition(e.position),\n size: normSize(e.size),\n };\n if (e.label) out.label = e.label;\n if (e.fill) out.fill = e.fill;\n if (e.stroke) out.stroke = e.stroke;\n return withForeignFields(out, e, INTERACTION_FIELDS);\n}\n\nfunction normFlow(f: FlowShape): FlowShape {\n const out: FlowShape = {\n id: f.id,\n position: normPosition(f.position),\n size: normSize(f.size),\n };\n if (f.label) out.label = f.label;\n return withForeignFields(out, f, FLOW_FIELDS);\n}\n\nfunction normAnnotation(a: TextAnnotation): TextAnnotation {\n const out: TextAnnotation = {\n id: a.id,\n text: a.text,\n position: normPosition(a.position),\n size: normSize(a.size),\n };\n if (a.attachedTo) out.attachedTo = a.attachedTo;\n return withForeignFields(out, a, ANNOTATION_FIELDS);\n}\n\nconst byId = (a: { id: string }, b: { id: string }): number =>\n a.id < b.id ? -1 : a.id > b.id ? 1 : 0;\n\n/**\n * Returns a canonicalised copy of a document (sorted, rounded, version-stamped). Fields the\n * modeler does not know follow the known ones, sorted by name.\n */\nexport function canonicalize(doc: TtDocument): TtDocument {\n return withForeignFields(\n {\n version: DOCUMENT_VERSION,\n title: doc.title,\n nodes: [...doc.nodes].map(normNode).sort(byId),\n interactions: [...doc.interactions].map(normInteraction).sort(byId),\n flows: [...doc.flows].map(normFlow).sort(byId),\n annotations: [...doc.annotations].map(normAnnotation).sort(byId),\n },\n doc,\n DOCUMENT_FIELDS,\n );\n}\n\n/**\n * Serialises a document to deterministic JSON. An empty `annotations` list is left out, so\n * re-saving a model that has no annotations changes nothing but its version stamp. The pretty\n * form is the file on disk and ends with a line break, like the files editors and Git expect;\n * the compact form (share links, local storage) has none.\n */\nexport function serializeDocument(doc: TtDocument, pretty = true): string {\n const canonical = canonicalize(doc);\n const output =\n canonical.annotations.length > 0\n ? canonical\n : Object.fromEntries(Object.entries(canonical).filter(([key]) => key !== \"annotations\"));\n return pretty ? `${JSON.stringify(output, null, 2)}\\n` : JSON.stringify(output);\n}\n","/**\n * Factory helpers for constructing well-formed model objects with the correct\n * notation defaults (sizes, labels). Kept DOM-free.\n */\n\nimport { nanoid } from \"nanoid\";\nimport { ANNOTATION_SPEC, FLOW_SPEC, INTERACTION_MODE_SPECS, TEAM_TYPE_SPECS } from \"./notation\";\nimport type {\n FlowShape,\n InteractionMode,\n InteractionShape,\n Position,\n TeamNode,\n TeamType,\n TextAnnotation,\n TtDocument,\n} from \"./types\";\nimport { DOCUMENT_VERSION } from \"./types\";\n\nexport function newId(prefix: string): string {\n return `${prefix}_${nanoid(8)}`;\n}\n\n/** Creates a team node of the given type at a position, with notation defaults. */\nexport function createTeamNode(\n type: TeamType,\n position: Position,\n overrides: Partial<Omit<TeamNode, \"id\" | \"type\">> = {},\n): TeamNode {\n const spec = TEAM_TYPE_SPECS[type];\n return {\n id: newId(\"team\"),\n type,\n label: overrides.label ?? spec.label,\n description: overrides.description,\n position,\n size: overrides.size ?? { ...spec.defaultSize },\n fill: overrides.fill,\n stroke: overrides.stroke,\n };\n}\n\n/** Creates a placed interaction shape of the given mode, with notation defaults. */\nexport function createInteractionShape(\n mode: InteractionMode,\n position: Position,\n overrides: Partial<Omit<InteractionShape, \"id\" | \"mode\" | \"position\">> = {},\n): InteractionShape {\n const spec = INTERACTION_MODE_SPECS[mode];\n return {\n id: newId(\"int\"),\n mode,\n position,\n size: overrides.size ?? { ...spec.defaultSize },\n label: overrides.label,\n fill: overrides.fill,\n stroke: overrides.stroke,\n };\n}\n\n/** Creates a placed \"flow of change\" arrow, with notation defaults. */\nexport function createFlowShape(\n position: Position,\n overrides: Partial<Omit<FlowShape, \"id\" | \"position\">> = {},\n): FlowShape {\n return {\n id: newId(\"flow\"),\n position,\n size: overrides.size ?? { ...FLOW_SPEC.defaultSize },\n label: overrides.label ?? FLOW_SPEC.label,\n };\n}\n\n/** Creates a text annotation, optionally attached to a team, interaction or flow. */\nexport function createTextAnnotation(\n position: Position,\n overrides: Partial<Omit<TextAnnotation, \"id\" | \"position\">> = {},\n): TextAnnotation {\n return {\n id: newId(\"ann\"),\n text: overrides.text ?? \"\",\n position,\n size: overrides.size ?? { ...ANNOTATION_SPEC.defaultSize },\n attachedTo: overrides.attachedTo,\n };\n}\n\n/** An empty document with sensible defaults. */\nexport function emptyDocument(title = \"Untitled team topology\"): TtDocument {\n return {\n version: DOCUMENT_VERSION,\n title,\n nodes: [],\n interactions: [],\n flows: [],\n annotations: [],\n };\n}\n","/**\n * A small but complete example diagram exercising all four team types, all three\n * interaction modes (as placed shapes overlaying the team boundaries), a\n * flow-of-change element and an attached annotation. The stream-aligned teams\n * are stacked as parallel lanes along the flow of change, as in the Team\n * Topologies book: side by side on the flow they would read as hand-offs. Ids are\n * fixed so the fixture serialises stably.\n */\n\nimport { DOCUMENT_VERSION } from \"./types\";\nimport type { TtDocument } from \"./types\";\nimport { ANNOTATION_SPEC, INTERACTION_MODE_SPECS, TEAM_TYPE_SPECS } from \"./notation\";\n\nconst s = TEAM_TYPE_SPECS;\nconst i = INTERACTION_MODE_SPECS;\n\nconst LANE_WIDTH = 600;\n\nexport const SAMPLE_DOCUMENT: TtDocument = {\n version: DOCUMENT_VERSION,\n title: \"Online shop team topology\",\n nodes: [\n {\n id: \"team_test_automation\",\n type: \"enabling\",\n label: \"Test Automation\",\n description: \"Coaches stream-aligned teams in test automation, then steps back.\",\n position: { x: 40, y: 150 },\n size: { width: s.enabling.defaultSize.width, height: 222 },\n },\n {\n id: \"team_discovery\",\n type: \"stream-aligned\",\n label: \"Product Discovery\",\n description: \"Owns search, browsing and product pages end-to-end.\",\n position: { x: 220, y: 150 },\n size: { width: LANE_WIDTH, height: s[\"stream-aligned\"].defaultSize.height },\n },\n {\n id: \"team_checkout\",\n type: \"stream-aligned\",\n label: \"Checkout & Payments\",\n description: \"Owns the checkout and payment journey end-to-end.\",\n position: { x: 220, y: 276 },\n size: { width: LANE_WIDTH, height: s[\"stream-aligned\"].defaultSize.height },\n },\n {\n id: \"team_fulfilment\",\n type: \"stream-aligned\",\n label: \"Order Fulfilment\",\n description: \"Owns delivery, tracking and returns end-to-end.\",\n position: { x: 220, y: 402 },\n size: { width: LANE_WIDTH, height: s[\"stream-aligned\"].defaultSize.height },\n },\n {\n id: \"team_fraud\",\n type: \"complicated-subsystem\",\n label: \"Fraud Detection\",\n description: \"Specialists for the real-time fraud scoring model.\",\n position: { x: 880, y: 249 },\n size: { ...s[\"complicated-subsystem\"].defaultSize },\n },\n {\n id: \"team_platform\",\n type: \"platform\",\n label: \"Cloud Platform\",\n description: \"Self-service CI/CD, runtime and observability for all teams.\",\n position: { x: 220, y: 552 },\n size: { width: LANE_WIDTH, height: 110 },\n },\n ],\n interactions: [\n {\n id: \"int_testing_discovery\",\n mode: \"facilitating\",\n position: { x: 148, y: 156 },\n size: { ...i.facilitating.defaultSize },\n },\n {\n id: \"int_testing_checkout\",\n mode: \"facilitating\",\n position: { x: 148, y: 282 },\n size: { ...i.facilitating.defaultSize },\n },\n {\n id: \"int_checkout_fraud\",\n mode: \"collaboration\",\n label: \"fraud rules\",\n position: { x: 794, y: 288 },\n size: { ...i.collaboration.defaultSize },\n },\n {\n id: \"int_platform_fulfilment\",\n mode: \"x-as-a-service\",\n position: { x: 476, y: 486 },\n size: { ...i[\"x-as-a-service\"].defaultSize },\n },\n ],\n flows: [\n {\n id: \"flow_main\",\n label: \"Flow of change\",\n position: { x: 40, y: 40 },\n size: { width: 1010, height: 56 },\n },\n ],\n annotations: [\n {\n id: \"ann_fraud_handover\",\n text: \"Collaboration until the fraud rules are stable (Q3), then X-as-a-Service\",\n position: { x: 880, y: 423 },\n size: { ...ANNOTATION_SPEC.defaultSize },\n attachedTo: \"int_checkout_fraud\",\n },\n ],\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/notation.ts","../src/ids.ts","../src/schema.ts","../src/foreign.ts","../src/serialize.ts","../src/factory.ts","../src/sample.ts"],"names":["i","s"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Pure (DOM-free) domain types for the Team Topologies model.\n *\n * This module is the canonical representation of a diagram and must never\n * import from the rendering layer (`@xyflow/react`) or touch the DOM, so it\n * can be unit-tested in isolation and reused across views / exporters.\n */\n\n/** MIME type used when dragging a team type from the palette onto the canvas. */\nexport const DND_MIME = \"application/x-tt-team-type\";\n\n/** The four fundamental team types in Team Topologies. */\nexport type TeamType = \"stream-aligned\" | \"enabling\" | \"complicated-subsystem\" | \"platform\";\n\nexport const TEAM_TYPES: readonly TeamType[] = [\n \"stream-aligned\",\n \"enabling\",\n \"complicated-subsystem\",\n \"platform\",\n] as const;\n\n/** The three core team interaction modes in Team Topologies. */\nexport type InteractionMode = \"collaboration\" | \"x-as-a-service\" | \"facilitating\";\n\nexport const INTERACTION_MODES: readonly InteractionMode[] = [\n \"collaboration\",\n \"x-as-a-service\",\n \"facilitating\",\n] as const;\n\n/** Geometric size of a node in canvas units (px). Encodes cognitive load. */\nexport interface Size {\n width: number;\n height: number;\n}\n\n/** Position of a node on the canvas in canvas units (px). */\nexport interface Position {\n x: number;\n y: number;\n}\n\n/** A team node in the canonical document model. */\nexport interface TeamNode {\n id: string;\n type: TeamType;\n label: string;\n description?: string;\n position: Position;\n size: Size;\n fill?: string;\n stroke?: string;\n}\n\n/**\n * An interaction in the canonical document model.\n *\n * Per the official Team Topologies notation, an interaction is a placed,\n * resizable SHAPE (parallelogram / triangle / circle) overlaid on the boundary\n * between the teams it relates to — not a connecting line. The relationship is\n * therefore spatial (overlap), so there is no source/target reference.\n */\nexport interface InteractionShape {\n id: string;\n mode: InteractionMode;\n label?: string;\n position: Position;\n size: Size;\n fill?: string;\n stroke?: string;\n}\n\n/**\n * A \"flow of change\" guide: a placed, resizable arrow element. Lets you anchor\n * the implied left-to-right flow, and visualise several team groupings on one\n * canvas.\n */\nexport interface FlowShape {\n id: string;\n label?: string;\n position: Position;\n size: Size;\n}\n\n/**\n * A free-text note beside the diagram (like a BPMN text annotation). It either\n * stands alone or is attached to exactly one team, interaction or flow, which\n * its dashed connector points at.\n */\nexport interface TextAnnotation {\n id: string;\n text: string;\n position: Position;\n size: Size;\n /** Id of the team, interaction or flow this annotation is attached to. */\n attachedTo?: string;\n}\n\n/** Current document schema version. Bump + add a migration when shape changes. */\nexport const DOCUMENT_VERSION = 3 as const;\n\n/**\n * A complete Team Topologies diagram. This is what gets serialised to JSON,\n * embedded into exported images, and encoded into share URLs.\n */\nexport interface TtDocument {\n version: typeof DOCUMENT_VERSION;\n title: string;\n nodes: TeamNode[];\n interactions: InteractionShape[];\n flows: FlowShape[];\n annotations: TextAnnotation[];\n}\n","/**\n * The Team Topologies visual notation, encoded as data.\n *\n * Colours, shapes and stroke styles follow the official\n * \"Team-Shape-Templates\" specification published by Team Topologies\n * (https://github.com/TeamTopologies/Team-Shape-Templates):\n *\n * - Team shapes are SOLID outlines (long-lived structures).\n * - Interaction-mode shapes are 50% transparent with DASHED outlines\n * (short-lived interactions).\n * - Each element is distinguished by SHAPE as well as colour, so the\n * notation stays readable for people with colour-vision deficiency.\n *\n * This module is pure data — it must not import the rendering layer.\n */\n\nimport type { InteractionMode, Size, TeamType } from \"./types\";\n\nexport type TeamShape = \"rounded-rect-horizontal\" | \"rounded-rect-vertical\" | \"octagon\" | \"rect\";\n\nexport type InteractionGlyph = \"parallelogram\" | \"triangle\" | \"circle\";\n\nexport type StrokeStyle = \"solid\" | \"dashed\" | \"dotted\";\n\nexport interface TeamTypeSpec {\n type: TeamType;\n /** Short display name. */\n label: string;\n /** One-line purpose, shown in the palette and inspector. */\n description: string;\n shape: TeamShape;\n fill: string;\n stroke: string;\n strokeStyle: StrokeStyle;\n strokeWidth: number;\n /** Default size when a node of this type is created. */\n defaultSize: Size;\n /** Minimum size enforced by the resizer. */\n minSize: Size;\n}\n\nexport interface InteractionModeSpec {\n mode: InteractionMode;\n label: string;\n description: string;\n shape: InteractionGlyph;\n fill: string;\n stroke: string;\n strokeStyle: StrokeStyle;\n strokeWidth: number;\n /**\n * The templates' fill opacity (short-lived → translucent). The renderer premixes the fill over\n * white at it and draws it opaque.\n */\n opacity: number;\n /** Whether direction is semantically meaningful (the X-as-a-Service triangle). */\n directional: boolean;\n /** Default size when a shape of this mode is created. */\n defaultSize: Size;\n /** Minimum size enforced by the resizer. */\n minSize: Size;\n}\n\n/** The left-to-right \"flow of change\" guide, a placeable annotation element. */\nexport interface FlowSpec {\n label: string;\n fill: string;\n stroke: string;\n strokeStyle: StrokeStyle;\n strokeWidth: number;\n defaultSize: Size;\n minSize: Size;\n}\n\n// The official notation colours (Team-Shape-Templates, above): foreign notation, guide §10.6.\n// brand-lint-disable\nexport const TEAM_TYPE_SPECS: Record<TeamType, TeamTypeSpec> = {\n \"stream-aligned\": {\n type: \"stream-aligned\",\n label: \"Stream-aligned\",\n description: \"Aligned to a single, valuable stream of work; owns it end-to-end.\",\n shape: \"rounded-rect-horizontal\",\n fill: \"#FFEDB8\",\n stroke: \"#FFD966\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 240, height: 96 },\n minSize: { width: 140, height: 64 },\n },\n enabling: {\n type: \"enabling\",\n label: \"Enabling\",\n description:\n \"Helps stream-aligned teams acquire missing capabilities; coaches, then steps back.\",\n shape: \"rounded-rect-vertical\",\n fill: \"#DFBDCF\",\n stroke: \"#D09CB7\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 120, height: 200 },\n minSize: { width: 80, height: 120 },\n },\n \"complicated-subsystem\": {\n type: \"complicated-subsystem\",\n label: \"Complicated Subsystem\",\n description:\n \"Owns a part of the system needing deep specialist knowledge, reducing others' cognitive load.\",\n shape: \"octagon\",\n fill: \"#FFC08B\",\n stroke: \"#E88814\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 170, height: 150 },\n minSize: { width: 110, height: 100 },\n },\n platform: {\n type: \"platform\",\n label: \"Platform\",\n description:\n \"Provides internal self-service capabilities to reduce cognitive load for stream-aligned teams.\",\n shape: \"rect\",\n fill: \"#B7CDF1\",\n stroke: \"#6D9EEB\",\n strokeStyle: \"solid\",\n strokeWidth: 2,\n defaultSize: { width: 380, height: 130 },\n minSize: { width: 200, height: 90 },\n },\n};\n\nexport const INTERACTION_MODE_SPECS: Record<InteractionMode, InteractionModeSpec> = {\n collaboration: {\n mode: \"collaboration\",\n label: \"Collaboration\",\n description:\n \"Two teams work closely together for a defined period; high overhead, high discovery.\",\n shape: \"parallelogram\",\n fill: \"#C6BEDF\",\n stroke: \"#967EE2\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n opacity: 0.5,\n directional: false,\n defaultSize: { width: 112, height: 72 },\n minSize: { width: 60, height: 44 },\n },\n \"x-as-a-service\": {\n mode: \"x-as-a-service\",\n label: \"X-as-a-Service\",\n description:\n \"One team consumes something the other provides 'as a service'; minimal collaboration.\",\n shape: \"triangle\",\n fill: \"#B4B4B4\",\n stroke: \"#999696\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n opacity: 0.5,\n directional: true,\n defaultSize: { width: 88, height: 78 },\n minSize: { width: 54, height: 48 },\n },\n facilitating: {\n mode: \"facilitating\",\n label: \"Facilitating\",\n description:\n \"One team helps/coaches another to clear impediments and learn; sensing and discovery.\",\n shape: \"circle\",\n fill: \"#C9DFBE\",\n stroke: \"#78996B\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n opacity: 0.5,\n directional: false,\n defaultSize: { width: 84, height: 84 },\n minSize: { width: 48, height: 48 },\n },\n};\n\n/**\n * The \"flow of change\" guide — a placeable dashed arrow (left-to-right).\n * Not a team or interaction: a standalone annotation element.\n */\nexport const FLOW_SPEC: FlowSpec = {\n label: \"Flow of change\",\n fill: \"transparent\",\n stroke: \"#6b6459\",\n strokeStyle: \"dashed\",\n strokeWidth: 2,\n defaultSize: { width: 520, height: 64 },\n minSize: { width: 160, height: 36 },\n};\n// brand-lint-enable\n\n/**\n * A text annotation — not part of the Team Topologies notation, so it carries\n * no colours here; the renderer draws it in the neutral brand ink.\n */\nexport interface AnnotationSpec {\n label: string;\n defaultSize: Size;\n minSize: Size;\n}\n\nexport const ANNOTATION_SPEC: AnnotationSpec = {\n label: \"Annotation\",\n defaultSize: { width: 200, height: 64 },\n minSize: { width: 60, height: 30 },\n};\n\n/** Maps a stroke style to an SVG/CSS dash array (empty string = solid). */\nexport function dashArray(style: StrokeStyle, strokeWidth = 2): string {\n switch (style) {\n case \"dashed\":\n return `${strokeWidth * 3} ${strokeWidth * 2}`;\n case \"dotted\":\n return `${strokeWidth} ${strokeWidth * 1.5}`;\n case \"solid\":\n default:\n return \"\";\n }\n}\n\nexport const ALL_TEAM_SPECS: readonly TeamTypeSpec[] = Object.values(TEAM_TYPE_SPECS);\nexport const ALL_INTERACTION_SPECS: readonly InteractionModeSpec[] =\n Object.values(INTERACTION_MODE_SPECS);\n","/**\n * The id rules of a Team Topologies document. Besides the elements a document lists, a diagram\n * holds parts it never writes down: the diagram itself and the connector of every annotation. They\n * take ids of their own, so no element may use one of them; otherwise opening the file would fail\n * halfway, with the previous diagram already gone. The canvas also keeps its elements in a plain\n * object, where the names of JavaScript's built-in object properties already resolve.\n */\n\n/** The id of the diagram itself (the canvas root of the renderer). */\nexport const DIAGRAM_ROOT_ID = \"tt-root\";\n\n/** diagram-js names the roots it creates on its own `__implicitroot_<n>`. */\nconst ENGINE_ROOT_ID_PREFIX = \"__implicitroot\";\n\n/** Connectors are not stored: an annotation's connector derives its id from the annotation. */\nexport function associationId(annotationId: string): string {\n return `assoc_${annotationId}`;\n}\n\nexport interface DocumentIdProblem {\n /** Where the offending id sits, e.g. `[\"nodes\", 2, \"id\"]`. */\n path: (string | number)[];\n message: string;\n}\n\nconst COLLECTIONS = [\"nodes\", \"interactions\", \"flows\", \"annotations\"] as const;\n\ntype DocumentElements = Record<(typeof COLLECTIONS)[number], readonly { id: string }[]>;\n\n/** Ids such as `constructor`, `toString` or `__proto__`, which every plain object already has. */\nfunction isBuiltInPropertyId(id: string): boolean {\n return Object.hasOwn(Object.prototype, id);\n}\n\n/**\n * Every id of the document that would collide on the canvas: a duplicate, the diagram's own id, a\n * diagram-js root id, the name of a built-in object property, or the id of an annotation's\n * connector.\n */\nexport function documentIdProblems(doc: DocumentElements): DocumentIdProblem[] {\n const problems: DocumentIdProblem[] = [];\n const connectorIds = new Map(\n doc.annotations.map((annotation) => [associationId(annotation.id), annotation.id]),\n );\n const seen = new Set<string>();\n for (const collection of COLLECTIONS) {\n doc[collection].forEach((element, index) => {\n const path = [collection, index, \"id\"];\n const { id } = element;\n if (seen.has(id)) {\n problems.push({\n path,\n message: `duplicate id \"${id}\"; ids must be unique across nodes, interactions, flows and annotations`,\n });\n }\n seen.add(id);\n if (id === DIAGRAM_ROOT_ID) {\n problems.push({ path, message: `\"${id}\" is reserved for the diagram itself` });\n } else if (id.startsWith(ENGINE_ROOT_ID_PREFIX)) {\n problems.push({\n path,\n message: `ids starting with \"${ENGINE_ROOT_ID_PREFIX}\" are reserved`,\n });\n } else if (isBuiltInPropertyId(id)) {\n problems.push({\n path,\n message: `\"${id}\" is reserved: it names a built-in property of JavaScript objects`,\n });\n }\n const annotationId = connectorIds.get(id);\n if (annotationId !== undefined) {\n problems.push({\n path,\n message: `\"${id}\" is reserved for the connector of annotation \"${annotationId}\"`,\n });\n }\n });\n }\n return problems;\n}\n","/**\n * Runtime validation for the document model using Zod.\n *\n * Anything entering the app from the outside world (imported files, share\n * URLs, localStorage) is parsed through {@link parseDocument} so malformed or\n * tampered data can never corrupt the editor state. Fields the schema does not\n * know pass through untouched (see `foreign.ts`), so another tool's data\n * survives a save.\n */\n\nimport { z } from \"zod\";\nimport { documentIdProblems } from \"./ids\";\nimport { DOCUMENT_VERSION, INTERACTION_MODES, TEAM_TYPES } from \"./types\";\nimport type { TtDocument } from \"./types\";\n\nconst teamTypeSchema = z.enum(TEAM_TYPES as unknown as [string, ...string[]]);\nconst interactionModeSchema = z.enum(INTERACTION_MODES as unknown as [string, ...string[]]);\n\nconst sizeSchema = z.object({\n width: z.number().finite().positive(),\n height: z.number().finite().positive(),\n});\n\nconst positionSchema = z.object({\n x: z.number().finite(),\n y: z.number().finite(),\n});\n\nconst hexColor = z.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/, \"expected a hex colour\");\n\nexport const teamNodeSchema = z.looseObject({\n id: z.string().min(1),\n type: teamTypeSchema,\n label: z.string(),\n description: z.string().optional(),\n position: positionSchema,\n size: sizeSchema,\n fill: hexColor.optional(),\n stroke: hexColor.optional(),\n});\n\nexport const interactionSchema = z.looseObject({\n id: z.string().min(1),\n mode: interactionModeSchema,\n label: z.string().optional(),\n position: positionSchema,\n size: sizeSchema,\n fill: hexColor.optional(),\n stroke: hexColor.optional(),\n});\n\nexport const flowSchema = z.looseObject({\n id: z.string().min(1),\n label: z.string().optional(),\n position: positionSchema,\n size: sizeSchema,\n});\n\nexport const annotationSchema = z.looseObject({\n id: z.string().min(1),\n text: z.string(),\n position: positionSchema,\n size: sizeSchema,\n attachedTo: z.string().min(1).optional(),\n});\n\nexport const documentSchema = z\n .looseObject({\n version: z.literal(DOCUMENT_VERSION),\n title: z.string(),\n nodes: z.array(teamNodeSchema),\n interactions: z.array(interactionSchema),\n flows: z.array(flowSchema),\n annotations: z.array(annotationSchema),\n })\n .superRefine((document, context) => {\n for (const { path, message } of documentIdProblems(document)) {\n context.addIssue({ code: \"custom\", path, message });\n }\n });\n\n/** One reason a document is invalid, at the path of the offending value. */\nexport interface DocumentIssue {\n path: (string | number)[];\n message: string;\n}\n\nexport type ParseResult =\n { ok: true; document: TtDocument } | { ok: false; error: string; issues: DocumentIssue[] };\n\n/**\n * Objects and arrays nested deeper than this make a document invalid, the document itself counting\n * as the first level. The serializer, structured cloning and JSON tooling such as jsonc-parser\n * descend one call per level and overflow the stack a few thousand levels down; a Team Topologies\n * document needs four.\n */\nexport const MAX_NESTING_DEPTH = 100;\n\n/**\n * Validates and (if necessary) migrates unknown data into a {@link TtDocument}.\n * Returns a discriminated result rather than throwing so callers can show a\n * friendly message, or point at each offending value (`issues`).\n */\nexport function parseDocument(input: unknown): ParseResult {\n const tooDeep = nestingIssues(input);\n if (tooDeep.length > 0) return refused(tooDeep);\n const { document: migrated, interactionFileIndexes } = migrate(input);\n const result = documentSchema.safeParse(migrated);\n if (!result.success) {\n return refused(\n result.error.issues.map((issue) => ({\n path: pathInFile(\n issue.path.filter((key): key is string | number => typeof key !== \"symbol\"),\n interactionFileIndexes,\n ),\n message: issue.message,\n })),\n );\n }\n return { ok: true, document: result.data as TtDocument };\n}\n\nfunction refused(issues: DocumentIssue[]): ParseResult {\n return {\n ok: false,\n error: issues.map((i) => `${i.path.join(\".\") || \"(root)\"}: ${i.message}`).join(\"; \"),\n issues,\n };\n}\n\n/**\n * Every object or array at the first level too deep, in document order; what lies below it is not\n * visited. Walked with an explicit stack, because the documents it guards against are the ones that\n * overflow a recursive walk.\n */\nfunction nestingIssues(input: unknown): DocumentIssue[] {\n const issues: DocumentIssue[] = [];\n const pending: { value: unknown; path: (string | number)[] }[] = [{ value: input, path: [] }];\n while (pending.length > 0) {\n const { value, path } = pending.pop()!;\n if (typeof value !== \"object\" || value === null) continue;\n if (path.length >= MAX_NESTING_DEPTH) {\n issues.push({\n path,\n message: `objects and arrays may nest at most ${MAX_NESTING_DEPTH} levels deep`,\n });\n continue;\n }\n // Array.from visits the holes of a sparse array as undefined; map would keep them as holes.\n const entries: [string | number, unknown][] = Array.isArray(value)\n ? Array.from(value, (entry: unknown, index) => [index, entry])\n : Object.entries(value);\n for (const [key, entry] of entries.reverse()) {\n if (typeof entry === \"object\" && entry !== null) {\n pending.push({ value: entry, path: [...path, key] });\n }\n }\n }\n return issues;\n}\n\n/** The last document version that modelled interactions as edges without geometry. */\nconst EDGE_INTERACTIONS_VERSION = 1;\n\ninterface Migration {\n document: unknown;\n /** For each interaction the migrated document keeps, its index in the input. */\n interactionFileIndexes: readonly number[];\n}\n\n/**\n * Forward-migrates older document shapes to the current version. v1 modelled\n * interactions as edges (source/target, no geometry) and carried a\n * `showFlowOfChange` flag; v2 makes interactions placed shapes and adds `flows`;\n * v3 adds `annotations`. The edge-interactions of a v1 file can't be placed\n * meaningfully, so they're dropped. From v2 on, an interaction without position\n * or size is refused like any other missing field: dropped, it would vanish from\n * the file on the next save without a word.\n */\nfunction migrate(input: unknown): Migration {\n if (input == null || typeof input !== \"object\") {\n return { document: input, interactionFileIndexes: [] };\n }\n const doc = input as Record<string, unknown>;\n const next: Record<string, unknown> = { ...doc };\n delete next.showFlowOfChange; // v1 flag, gone in v2\n next.version = DOCUMENT_VERSION;\n if (typeof next.title !== \"string\") next.title = \"Untitled team topology\";\n if (!Array.isArray(next.nodes)) next.nodes = [];\n const dropsEdgeInteractions = doc.version === EDGE_INTERACTIONS_VERSION;\n const keptInteractions = Array.isArray(next.interactions)\n ? next.interactions\n .map((interaction: unknown, fileIndex) => ({ interaction, fileIndex }))\n .filter(({ interaction }) => !dropsEdgeInteractions || isPlacedShape(interaction))\n : [];\n next.interactions = keptInteractions.map(({ interaction }) => interaction);\n if (!Array.isArray(next.flows)) next.flows = [];\n if (!Array.isArray(next.annotations)) next.annotations = [];\n return {\n document: next,\n interactionFileIndexes: keptInteractions.map(({ fileIndex }) => fileIndex),\n };\n}\n\nfunction isPlacedShape(value: unknown): boolean {\n return value != null && typeof value === \"object\" && \"position\" in value && \"size\" in value;\n}\n\n/**\n * An issue's path in the input rather than in the migrated document: an editor points at the\n * file, and every legacy interaction dropped before an invalid one would shift its index.\n */\nfunction pathInFile(\n path: (string | number)[],\n interactionFileIndexes: readonly number[],\n): (string | number)[] {\n const [collection, index, ...rest] = path;\n if (collection !== \"interactions\" || typeof index !== \"number\") return path;\n const fileIndex = interactionFileIndexes[index];\n return fileIndex === undefined ? path : [collection, fileIndex, ...rest];\n}\n","/**\n * Fields a document carries that this modeler does not know, such as a vendor's `\"x-vendor\"` on a\n * team. They are kept through open and save, written after the known fields and sorted, so another\n * tool's data survives an edit in the modeler and the output stays deterministic.\n */\n\nexport const DOCUMENT_FIELDS = [\n \"version\",\n \"title\",\n \"nodes\",\n \"interactions\",\n \"flows\",\n \"annotations\",\n] as const;\nexport const TEAM_NODE_FIELDS = [\n \"id\",\n \"type\",\n \"label\",\n \"description\",\n \"position\",\n \"size\",\n \"fill\",\n \"stroke\",\n] as const;\nexport const INTERACTION_FIELDS = [\n \"id\",\n \"mode\",\n \"label\",\n \"position\",\n \"size\",\n \"fill\",\n \"stroke\",\n] as const;\nexport const FLOW_FIELDS = [\"id\", \"label\", \"position\", \"size\"] as const;\nexport const ANNOTATION_FIELDS = [\"id\", \"text\", \"position\", \"size\", \"attachedTo\"] as const;\n\n/** Unknown fields by name, sorted, with their values in canonical form. */\nexport type ForeignFields = Readonly<Record<string, unknown>>;\n\n/** JSON objects have no key order, so nested keys are sorted too: equal data, equal bytes. */\nfunction canonicalValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalValue);\n if (value === null || typeof value !== \"object\") return value;\n const record = value as Record<string, unknown>;\n return Object.fromEntries(\n Object.keys(record)\n .filter((key) => record[key] !== undefined)\n .sort()\n .map((key) => [key, canonicalValue(record[key])]),\n );\n}\n\n/** The fields of `value` outside `knownFields`, or undefined when there are none. */\nexport function foreignFields(\n value: object,\n knownFields: readonly string[],\n): ForeignFields | undefined {\n const record = value as Record<string, unknown>;\n const names = Object.keys(record)\n .filter((name) => !knownFields.includes(name) && record[name] !== undefined)\n .sort();\n if (names.length === 0) return undefined;\n return Object.fromEntries(names.map((name) => [name, canonicalValue(record[name])]));\n}\n\n/**\n * `known` followed by the foreign fields of `source`. Built from entries, never by assignment, so\n * a field named `__proto__` stays a field instead of replacing the prototype.\n */\nexport function withForeignFields<T extends object>(\n known: T,\n source: object | undefined,\n knownFields: readonly string[],\n): T {\n const foreign = source ? foreignFields(source, knownFields) : undefined;\n if (!foreign) return known;\n return Object.fromEntries([...Object.entries(known), ...Object.entries(foreign)]) as T;\n}\n","/**\n * Deterministic serialisation of the document model.\n *\n * Producing byte-stable JSON (sorted arrays, fixed key order, rounded\n * coordinates) makes diagrams diff-friendly in version control and gives\n * stable share URLs / embedded payloads.\n */\n\nimport {\n ANNOTATION_FIELDS,\n DOCUMENT_FIELDS,\n FLOW_FIELDS,\n INTERACTION_FIELDS,\n TEAM_NODE_FIELDS,\n withForeignFields,\n} from \"./foreign\";\nimport { DOCUMENT_VERSION } from \"./types\";\nimport type {\n FlowShape,\n InteractionShape,\n Position,\n Size,\n TeamNode,\n TextAnnotation,\n TtDocument,\n} from \"./types\";\n\n/** Round to 2 decimals to strip floating-point drift from drag operations. */\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nfunction normPosition(p: Position): Position {\n return { x: round(p.x), y: round(p.y) };\n}\n\nfunction normSize(s: Size): Size {\n return { width: round(s.width), height: round(s.height) };\n}\n\n/** Drops undefined fields and applies a fixed key order to a node. */\nfunction normNode(n: TeamNode): TeamNode {\n const out: TeamNode = {\n id: n.id,\n type: n.type,\n label: n.label,\n position: normPosition(n.position),\n size: normSize(n.size),\n };\n if (n.description) out.description = n.description;\n if (n.fill) out.fill = n.fill;\n if (n.stroke) out.stroke = n.stroke;\n return withForeignFields(out, n, TEAM_NODE_FIELDS);\n}\n\nfunction normInteraction(e: InteractionShape): InteractionShape {\n const out: InteractionShape = {\n id: e.id,\n mode: e.mode,\n position: normPosition(e.position),\n size: normSize(e.size),\n };\n if (e.label) out.label = e.label;\n if (e.fill) out.fill = e.fill;\n if (e.stroke) out.stroke = e.stroke;\n return withForeignFields(out, e, INTERACTION_FIELDS);\n}\n\nfunction normFlow(f: FlowShape): FlowShape {\n const out: FlowShape = {\n id: f.id,\n position: normPosition(f.position),\n size: normSize(f.size),\n };\n if (f.label) out.label = f.label;\n return withForeignFields(out, f, FLOW_FIELDS);\n}\n\nfunction normAnnotation(a: TextAnnotation): TextAnnotation {\n const out: TextAnnotation = {\n id: a.id,\n text: a.text,\n position: normPosition(a.position),\n size: normSize(a.size),\n };\n if (a.attachedTo) out.attachedTo = a.attachedTo;\n return withForeignFields(out, a, ANNOTATION_FIELDS);\n}\n\nconst byId = (a: { id: string }, b: { id: string }): number =>\n a.id < b.id ? -1 : a.id > b.id ? 1 : 0;\n\n/**\n * Returns a canonicalised copy of a document (sorted, rounded, version-stamped). Fields the\n * modeler does not know follow the known ones, sorted by name.\n */\nexport function canonicalize(doc: TtDocument): TtDocument {\n return withForeignFields(\n {\n version: DOCUMENT_VERSION,\n title: doc.title,\n nodes: [...doc.nodes].map(normNode).sort(byId),\n interactions: [...doc.interactions].map(normInteraction).sort(byId),\n flows: [...doc.flows].map(normFlow).sort(byId),\n annotations: [...doc.annotations].map(normAnnotation).sort(byId),\n },\n doc,\n DOCUMENT_FIELDS,\n );\n}\n\n/**\n * Serialises a document to deterministic JSON. An empty `annotations` list is left out, so\n * re-saving a model that has no annotations changes nothing but its version stamp. The pretty\n * form is the file on disk and ends with a line break, like the files editors and Git expect;\n * the compact form (share links, local storage) has none.\n */\nexport function serializeDocument(doc: TtDocument, pretty = true): string {\n const canonical = canonicalize(doc);\n const output =\n canonical.annotations.length > 0\n ? canonical\n : Object.fromEntries(Object.entries(canonical).filter(([key]) => key !== \"annotations\"));\n return pretty ? `${JSON.stringify(output, null, 2)}\\n` : JSON.stringify(output);\n}\n","/**\n * Factory helpers for constructing well-formed model objects with the correct\n * notation defaults (sizes, labels). Kept DOM-free.\n */\n\nimport { nanoid } from \"nanoid\";\nimport { ANNOTATION_SPEC, FLOW_SPEC, INTERACTION_MODE_SPECS, TEAM_TYPE_SPECS } from \"./notation\";\nimport type {\n FlowShape,\n InteractionMode,\n InteractionShape,\n Position,\n TeamNode,\n TeamType,\n TextAnnotation,\n TtDocument,\n} from \"./types\";\nimport { DOCUMENT_VERSION } from \"./types\";\n\nexport function newId(prefix: string): string {\n return `${prefix}_${nanoid(8)}`;\n}\n\n/** Creates a team node of the given type at a position, with notation defaults. */\nexport function createTeamNode(\n type: TeamType,\n position: Position,\n overrides: Partial<Omit<TeamNode, \"id\" | \"type\">> = {},\n): TeamNode {\n const spec = TEAM_TYPE_SPECS[type];\n return {\n id: newId(\"team\"),\n type,\n label: overrides.label ?? spec.label,\n description: overrides.description,\n position,\n size: overrides.size ?? { ...spec.defaultSize },\n fill: overrides.fill,\n stroke: overrides.stroke,\n };\n}\n\n/** Creates a placed interaction shape of the given mode, with notation defaults. */\nexport function createInteractionShape(\n mode: InteractionMode,\n position: Position,\n overrides: Partial<Omit<InteractionShape, \"id\" | \"mode\" | \"position\">> = {},\n): InteractionShape {\n const spec = INTERACTION_MODE_SPECS[mode];\n return {\n id: newId(\"int\"),\n mode,\n position,\n size: overrides.size ?? { ...spec.defaultSize },\n label: overrides.label,\n fill: overrides.fill,\n stroke: overrides.stroke,\n };\n}\n\n/** Creates a placed \"flow of change\" arrow, with notation defaults. */\nexport function createFlowShape(\n position: Position,\n overrides: Partial<Omit<FlowShape, \"id\" | \"position\">> = {},\n): FlowShape {\n return {\n id: newId(\"flow\"),\n position,\n size: overrides.size ?? { ...FLOW_SPEC.defaultSize },\n label: overrides.label ?? FLOW_SPEC.label,\n };\n}\n\n/** Creates a text annotation, optionally attached to a team, interaction or flow. */\nexport function createTextAnnotation(\n position: Position,\n overrides: Partial<Omit<TextAnnotation, \"id\" | \"position\">> = {},\n): TextAnnotation {\n return {\n id: newId(\"ann\"),\n text: overrides.text ?? \"\",\n position,\n size: overrides.size ?? { ...ANNOTATION_SPEC.defaultSize },\n attachedTo: overrides.attachedTo,\n };\n}\n\n/** An empty document with sensible defaults. */\nexport function emptyDocument(title = \"Untitled team topology\"): TtDocument {\n return {\n version: DOCUMENT_VERSION,\n title,\n nodes: [],\n interactions: [],\n flows: [],\n annotations: [],\n };\n}\n","/**\n * A small but complete example diagram exercising all four team types, all three\n * interaction modes (as placed shapes overlaying the team boundaries), a\n * flow-of-change element and an attached annotation. The stream-aligned teams\n * are stacked as parallel lanes along the flow of change, as in the Team\n * Topologies book: side by side on the flow they would read as hand-offs. Ids are\n * fixed so the fixture serialises stably.\n */\n\nimport { DOCUMENT_VERSION } from \"./types\";\nimport type { TtDocument } from \"./types\";\nimport { ANNOTATION_SPEC, INTERACTION_MODE_SPECS, TEAM_TYPE_SPECS } from \"./notation\";\n\nconst s = TEAM_TYPE_SPECS;\nconst i = INTERACTION_MODE_SPECS;\n\nconst LANE_WIDTH = 600;\n\nexport const SAMPLE_DOCUMENT: TtDocument = {\n version: DOCUMENT_VERSION,\n title: \"Online shop team topology\",\n nodes: [\n {\n id: \"team_test_automation\",\n type: \"enabling\",\n label: \"Test Automation\",\n description: \"Coaches stream-aligned teams in test automation, then steps back.\",\n position: { x: 40, y: 150 },\n size: { width: s.enabling.defaultSize.width, height: 222 },\n },\n {\n id: \"team_discovery\",\n type: \"stream-aligned\",\n label: \"Product Discovery\",\n description: \"Owns search, browsing and product pages end-to-end.\",\n position: { x: 220, y: 150 },\n size: { width: LANE_WIDTH, height: s[\"stream-aligned\"].defaultSize.height },\n },\n {\n id: \"team_checkout\",\n type: \"stream-aligned\",\n label: \"Checkout & Payments\",\n description: \"Owns the checkout and payment journey end-to-end.\",\n position: { x: 220, y: 276 },\n size: { width: LANE_WIDTH, height: s[\"stream-aligned\"].defaultSize.height },\n },\n {\n id: \"team_fulfilment\",\n type: \"stream-aligned\",\n label: \"Order Fulfilment\",\n description: \"Owns delivery, tracking and returns end-to-end.\",\n position: { x: 220, y: 402 },\n size: { width: LANE_WIDTH, height: s[\"stream-aligned\"].defaultSize.height },\n },\n {\n id: \"team_fraud\",\n type: \"complicated-subsystem\",\n label: \"Fraud Detection\",\n description: \"Specialists for the real-time fraud scoring model.\",\n position: { x: 880, y: 249 },\n size: { ...s[\"complicated-subsystem\"].defaultSize },\n },\n {\n id: \"team_platform\",\n type: \"platform\",\n label: \"Cloud Platform\",\n description: \"Self-service CI/CD, runtime and observability for all teams.\",\n position: { x: 220, y: 552 },\n size: { width: LANE_WIDTH, height: 110 },\n },\n ],\n interactions: [\n {\n id: \"int_testing_discovery\",\n mode: \"facilitating\",\n position: { x: 148, y: 156 },\n size: { ...i.facilitating.defaultSize },\n },\n {\n id: \"int_testing_checkout\",\n mode: \"facilitating\",\n position: { x: 148, y: 282 },\n size: { ...i.facilitating.defaultSize },\n },\n {\n id: \"int_checkout_fraud\",\n mode: \"collaboration\",\n label: \"fraud rules\",\n position: { x: 794, y: 288 },\n size: { ...i.collaboration.defaultSize },\n },\n {\n id: \"int_platform_fulfilment\",\n mode: \"x-as-a-service\",\n position: { x: 476, y: 486 },\n size: { ...i[\"x-as-a-service\"].defaultSize },\n },\n ],\n flows: [\n {\n id: \"flow_main\",\n label: \"Flow of change\",\n position: { x: 40, y: 40 },\n size: { width: 1010, height: 56 },\n },\n ],\n annotations: [\n {\n id: \"ann_fraud_handover\",\n text: \"Collaboration until the fraud rules are stable (Q3), then X-as-a-Service\",\n position: { x: 880, y: 423 },\n size: { ...ANNOTATION_SPEC.defaultSize },\n attachedTo: \"int_checkout_fraud\",\n },\n ],\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@miragon/team-topologies-schema-model",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "The Team Topologies data model with types, the notation specification, runtime validation, migrations and deterministic JSON serialization.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/Miragon/
|
|
9
|
-
"directory": "packages/schema-model"
|
|
8
|
+
"url": "git+https://github.com/Miragon/modeler-suite.git",
|
|
9
|
+
"directory": "modelers/team-topologies/packages/schema-model"
|
|
10
10
|
},
|
|
11
|
-
"homepage": "https://github.com/Miragon/
|
|
12
|
-
"bugs": "https://github.com/Miragon/
|
|
11
|
+
"homepage": "https://github.com/Miragon/modeler-suite/tree/main/modelers/team-topologies/packages/schema-model#readme",
|
|
12
|
+
"bugs": "https://github.com/Miragon/modeler-suite/issues",
|
|
13
13
|
"type": "module",
|
|
14
14
|
"sideEffects": false,
|
|
15
15
|
"exports": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"zod": "^4.6.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"tsup": "
|
|
43
|
+
"tsup": "9.0.0",
|
|
44
44
|
"typescript": "6.0.3",
|
|
45
45
|
"vitest": "5.0.5",
|
|
46
46
|
"zod": "4.6.7"
|