@miragon/team-topologies-schema-model 0.15.0 → 0.16.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 CHANGED
@@ -173,9 +173,12 @@ console.log(SAMPLE_DOCUMENT.title);
173
173
  the known fields, sorted by name (nested keys too), so another tool's data survives a save. Only
174
174
  they can nest deeper than the four levels of the known fields, and objects and arrays nest at
175
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.
176
+ `parseDocument()` refuses a deeper document with an issue at each first level too deep, the
177
+ first 100 of them in document order. The check runs without recursion, because the serializer
178
+ and JSON tools overflow the stack a few thousand levels down. It builds a path only for an
179
+ issue, so its memory grows with the number of containers, not with their number times their
180
+ depth, and it walks a container that a caller puts in several places or inside itself no more
181
+ than once per level.
179
182
  - **Ids:** `parseDocument()` rejects a document whose ids would collide on the canvas: an id used
180
183
  twice, the diagram's own id `tt-root` (`DIAGRAM_ROOT_ID`), ids starting with `__implicitroot`,
181
184
  `assoc_<annotation id>` (`associationId()`), the id of that annotation's connector, and the names
package/dist/index.cjs CHANGED
@@ -275,28 +275,44 @@ function refused(issues) {
275
275
  issues
276
276
  };
277
277
  }
278
+ var MAX_NESTING_ISSUES = 100;
278
279
  function nestingIssues(input) {
279
280
  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) {
281
+ if (!isContainer(input)) return issues;
282
+ const deepestWalk = /* @__PURE__ */ new WeakMap();
283
+ const open = [];
284
+ const enter = (container, keyInParent) => {
285
+ deepestWalk.set(container, open.length);
286
+ const keys = Array.isArray(container) ? void 0 : Object.keys(container);
287
+ const size = keys?.length ?? container.length;
288
+ open.push({ container, keys, size, next: 0, keyInParent });
289
+ };
290
+ enter(input);
291
+ while (open.length > 0 && issues.length < MAX_NESTING_ISSUES) {
292
+ const current = open[open.length - 1];
293
+ if (current.next === current.size) {
294
+ open.pop();
295
+ continue;
296
+ }
297
+ const index = current.next++;
298
+ const key = current.keys === void 0 ? index : current.keys[index];
299
+ const entry = current.container[key];
300
+ if (!isContainer(entry)) continue;
301
+ if (open.length >= MAX_NESTING_DEPTH) {
285
302
  issues.push({
286
- path,
303
+ path: [...open.flatMap(({ keyInParent }) => keyInParent ?? []), key],
287
304
  message: `objects and arrays may nest at most ${MAX_NESTING_DEPTH} levels deep`
288
305
  });
289
306
  continue;
290
307
  }
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
- }
308
+ if ((deepestWalk.get(entry) ?? -1) >= open.length) continue;
309
+ enter(entry, key);
297
310
  }
298
311
  return issues;
299
312
  }
313
+ function isContainer(value) {
314
+ return typeof value === "object" && value !== null;
315
+ }
300
316
  var EDGE_INTERACTIONS_VERSION = 1;
301
317
  function migrate(input) {
302
318
  if (input == null || typeof input !== "object") {
@@ -328,6 +344,47 @@ function pathInFile(path, interactionFileIndexes) {
328
344
  return fileIndex === void 0 ? path : [collection, fileIndex, ...rest];
329
345
  }
330
346
 
347
+ // src/canonical-copy.ts
348
+ var MAX_REPEATED_ENTRIES = 1e6;
349
+ function canonicalCopier() {
350
+ const ancestors = /* @__PURE__ */ new Set();
351
+ const copiedContainers = /* @__PURE__ */ new WeakSet();
352
+ let repeatedEntries = 0;
353
+ const copy = (value) => {
354
+ if (value === null || typeof value !== "object") return value;
355
+ if (ancestors.has(value)) throw new Error("Cannot serialize a cyclic document.");
356
+ if (copiedContainers.has(value)) {
357
+ repeatedEntries += Array.isArray(value) ? value.length : Object.keys(value).length;
358
+ if (repeatedEntries > MAX_REPEATED_ENTRIES) {
359
+ throw new Error(
360
+ `Cannot serialize a document whose shared objects and arrays would repeat more than ${MAX_REPEATED_ENTRIES} entries.`
361
+ );
362
+ }
363
+ } else {
364
+ copiedContainers.add(value);
365
+ }
366
+ ancestors.add(value);
367
+ const record = value;
368
+ const copied = Array.isArray(value) ? value.map(copy) : Object.fromEntries(
369
+ Object.keys(record).filter((key) => record[key] !== void 0).sort().map((key) => [key, copy(record[key])])
370
+ );
371
+ ancestors.delete(value);
372
+ return copied;
373
+ };
374
+ return copy;
375
+ }
376
+ function copyForeignFields(value, knownFields, copy) {
377
+ const record = value;
378
+ const names = Object.keys(record).filter((name) => !knownFields.includes(name) && record[name] !== void 0).sort();
379
+ if (names.length === 0) return void 0;
380
+ return Object.fromEntries(names.map((name) => [name, copy(record[name])]));
381
+ }
382
+ function appendForeignFields(known, source, knownFields, copy) {
383
+ const foreign = source ? copyForeignFields(source, knownFields, copy) : void 0;
384
+ if (!foreign) return known;
385
+ return Object.fromEntries([...Object.entries(known), ...Object.entries(foreign)]);
386
+ }
387
+
331
388
  // src/foreign.ts
332
389
  var DOCUMENT_FIELDS = [
333
390
  "version",
@@ -358,24 +415,11 @@ var INTERACTION_FIELDS = [
358
415
  ];
359
416
  var FLOW_FIELDS = ["id", "label", "position", "size"];
360
417
  var ANNOTATION_FIELDS = ["id", "text", "position", "size", "attachedTo"];
361
- function canonicalValue(value) {
362
- if (Array.isArray(value)) return value.map(canonicalValue);
363
- if (value === null || typeof value !== "object") return value;
364
- const record = value;
365
- return Object.fromEntries(
366
- Object.keys(record).filter((key) => record[key] !== void 0).sort().map((key) => [key, canonicalValue(record[key])])
367
- );
368
- }
369
418
  function foreignFields(value, knownFields) {
370
- const record = value;
371
- const names = Object.keys(record).filter((name) => !knownFields.includes(name) && record[name] !== void 0).sort();
372
- if (names.length === 0) return void 0;
373
- return Object.fromEntries(names.map((name) => [name, canonicalValue(record[name])]));
419
+ return copyForeignFields(value, knownFields, canonicalCopier());
374
420
  }
375
421
  function withForeignFields(known, source, knownFields) {
376
- const foreign = source ? foreignFields(source, knownFields) : void 0;
377
- if (!foreign) return known;
378
- return Object.fromEntries([...Object.entries(known), ...Object.entries(foreign)]);
422
+ return appendForeignFields(known, source, knownFields, canonicalCopier());
379
423
  }
380
424
 
381
425
  // src/serialize.ts
@@ -388,7 +432,7 @@ function normPosition(p) {
388
432
  function normSize(s2) {
389
433
  return { width: round(s2.width), height: round(s2.height) };
390
434
  }
391
- function normNode(n) {
435
+ function normNode(n, copy) {
392
436
  const out = {
393
437
  id: n.id,
394
438
  type: n.type,
@@ -399,9 +443,9 @@ function normNode(n) {
399
443
  if (n.description) out.description = n.description;
400
444
  if (n.fill) out.fill = n.fill;
401
445
  if (n.stroke) out.stroke = n.stroke;
402
- return withForeignFields(out, n, TEAM_NODE_FIELDS);
446
+ return appendForeignFields(out, n, TEAM_NODE_FIELDS, copy);
403
447
  }
404
- function normInteraction(e) {
448
+ function normInteraction(e, copy) {
405
449
  const out = {
406
450
  id: e.id,
407
451
  mode: e.mode,
@@ -411,18 +455,18 @@ function normInteraction(e) {
411
455
  if (e.label) out.label = e.label;
412
456
  if (e.fill) out.fill = e.fill;
413
457
  if (e.stroke) out.stroke = e.stroke;
414
- return withForeignFields(out, e, INTERACTION_FIELDS);
458
+ return appendForeignFields(out, e, INTERACTION_FIELDS, copy);
415
459
  }
416
- function normFlow(f) {
460
+ function normFlow(f, copy) {
417
461
  const out = {
418
462
  id: f.id,
419
463
  position: normPosition(f.position),
420
464
  size: normSize(f.size)
421
465
  };
422
466
  if (f.label) out.label = f.label;
423
- return withForeignFields(out, f, FLOW_FIELDS);
467
+ return appendForeignFields(out, f, FLOW_FIELDS, copy);
424
468
  }
425
- function normAnnotation(a) {
469
+ function normAnnotation(a, copy) {
426
470
  const out = {
427
471
  id: a.id,
428
472
  text: a.text,
@@ -430,21 +474,23 @@ function normAnnotation(a) {
430
474
  size: normSize(a.size)
431
475
  };
432
476
  if (a.attachedTo) out.attachedTo = a.attachedTo;
433
- return withForeignFields(out, a, ANNOTATION_FIELDS);
477
+ return appendForeignFields(out, a, ANNOTATION_FIELDS, copy);
434
478
  }
435
479
  var byId = (a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
436
480
  function canonicalize(doc) {
437
- return withForeignFields(
481
+ const copy = canonicalCopier();
482
+ return appendForeignFields(
438
483
  {
439
484
  version: DOCUMENT_VERSION,
440
485
  title: doc.title,
441
- nodes: [...doc.nodes].map(normNode).sort(byId),
442
- interactions: [...doc.interactions].map(normInteraction).sort(byId),
443
- flows: [...doc.flows].map(normFlow).sort(byId),
444
- annotations: [...doc.annotations].map(normAnnotation).sort(byId)
486
+ nodes: [...doc.nodes].map((node) => normNode(node, copy)).sort(byId),
487
+ interactions: [...doc.interactions].map((interaction) => normInteraction(interaction, copy)).sort(byId),
488
+ flows: [...doc.flows].map((flow) => normFlow(flow, copy)).sort(byId),
489
+ annotations: [...doc.annotations].map((annotation) => normAnnotation(annotation, copy)).sort(byId)
445
490
  },
446
491
  doc,
447
- DOCUMENT_FIELDS
492
+ DOCUMENT_FIELDS,
493
+ copy
448
494
  );
449
495
  }
450
496
  function serializeDocument(doc, pretty = true) {
@@ -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 /**\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"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/notation.ts","../src/ids.ts","../src/schema.ts","../src/canonical-copy.ts","../src/foreign.ts","../src/serialize.ts","../src/factory.ts","../src/sample.ts"],"names":["z","i","s","nanoid"],"mappings":";;;;;;AASO,IAAM,QAAA,GAAW;AAKjB,IAAM,UAAA,GAAkC;AAAA,EAC7C,gBAAA;AAAA,EACA,UAAA;AAAA,EACA,uBAAA;AAAA,EACA;AACF;AAKO,IAAM,iBAAA,GAAgD;AAAA,EAC3D,eAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACF;AAuEO,IAAM,gBAAA,GAAmB;;;ACvBzB,IAAM,eAAA,GAAkD;AAAA,EAC7D,gBAAA,EAAkB;AAAA,IAChB,IAAA,EAAM,gBAAA;AAAA,IACN,KAAA,EAAO,gBAAA;AAAA,IACP,WAAA,EAAa,mEAAA;AAAA,IACb,KAAA,EAAO,yBAAA;AAAA,IACP,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,SAAA;AAAA,IACR,WAAA,EAAa,OAAA;AAAA,IACb,WAAA,EAAa,CAAA;AAAA,IACb,WAAA,EAAa,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,EAAA,EAAG;AAAA,IACtC,OAAA,EAAS,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,EAAA;AAAG,GACpC;AAAA,EACA,QAAA,EAAU;AAAA,IACR,IAAA,EAAM,UAAA;AAAA,IACN,KAAA,EAAO,UAAA;AAAA,IACP,WAAA,EACE,oFAAA;AAAA,IACF,KAAA,EAAO,uBAAA;AAAA,IACP,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,SAAA;AAAA,IACR,WAAA,EAAa,OAAA;AAAA,IACb,WAAA,EAAa,CAAA;AAAA,IACb,WAAA,EAAa,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AAAA,IACvC,OAAA,EAAS,EAAE,KAAA,EAAO,EAAA,EAAI,QAAQ,GAAA;AAAI,GACpC;AAAA,EACA,uBAAA,EAAyB;AAAA,IACvB,IAAA,EAAM,uBAAA;AAAA,IACN,KAAA,EAAO,uBAAA;AAAA,IACP,WAAA,EACE,+FAAA;AAAA,IACF,KAAA,EAAO,SAAA;AAAA,IACP,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,SAAA;AAAA,IACR,WAAA,EAAa,OAAA;AAAA,IACb,WAAA,EAAa,CAAA;AAAA,IACb,WAAA,EAAa,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AAAA,IACvC,OAAA,EAAS,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA;AAAI,GACrC;AAAA,EACA,QAAA,EAAU;AAAA,IACR,IAAA,EAAM,UAAA;AAAA,IACN,KAAA,EAAO,UAAA;AAAA,IACP,WAAA,EACE,gGAAA;AAAA,IACF,KAAA,EAAO,MAAA;AAAA,IACP,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,SAAA;AAAA,IACR,WAAA,EAAa,OAAA;AAAA,IACb,WAAA,EAAa,CAAA;AAAA,IACb,WAAA,EAAa,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AAAA,IACvC,OAAA,EAAS,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,EAAA;AAAG;AAEtC;AAEO,IAAM,sBAAA,GAAuE;AAAA,EAClF,aAAA,EAAe;AAAA,IACb,IAAA,EAAM,eAAA;AAAA,IACN,KAAA,EAAO,eAAA;AAAA,IACP,WAAA,EACE,sFAAA;AAAA,IACF,KAAA,EAAO,eAAA;AAAA,IACP,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,SAAA;AAAA,IACR,WAAA,EAAa,QAAA;AAAA,IACb,WAAA,EAAa,CAAA;AAAA,IACb,OAAA,EAAS,GAAA;AAAA,IACT,WAAA,EAAa,KAAA;AAAA,IACb,WAAA,EAAa,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,EAAA,EAAG;AAAA,IACtC,OAAA,EAAS,EAAE,KAAA,EAAO,EAAA,EAAI,QAAQ,EAAA;AAAG,GACnC;AAAA,EACA,gBAAA,EAAkB;AAAA,IAChB,IAAA,EAAM,gBAAA;AAAA,IACN,KAAA,EAAO,gBAAA;AAAA,IACP,WAAA,EACE,uFAAA;AAAA,IACF,KAAA,EAAO,UAAA;AAAA,IACP,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,SAAA;AAAA,IACR,WAAA,EAAa,QAAA;AAAA,IACb,WAAA,EAAa,CAAA;AAAA,IACb,OAAA,EAAS,GAAA;AAAA,IACT,WAAA,EAAa,IAAA;AAAA,IACb,WAAA,EAAa,EAAE,KAAA,EAAO,EAAA,EAAI,QAAQ,EAAA,EAAG;AAAA,IACrC,OAAA,EAAS,EAAE,KAAA,EAAO,EAAA,EAAI,QAAQ,EAAA;AAAG,GACnC;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,IAAA,EAAM,cAAA;AAAA,IACN,KAAA,EAAO,cAAA;AAAA,IACP,WAAA,EACE,uFAAA;AAAA,IACF,KAAA,EAAO,QAAA;AAAA,IACP,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,SAAA;AAAA,IACR,WAAA,EAAa,QAAA;AAAA,IACb,WAAA,EAAa,CAAA;AAAA,IACb,OAAA,EAAS,GAAA;AAAA,IACT,WAAA,EAAa,KAAA;AAAA,IACb,WAAA,EAAa,EAAE,KAAA,EAAO,EAAA,EAAI,QAAQ,EAAA,EAAG;AAAA,IACrC,OAAA,EAAS,EAAE,KAAA,EAAO,EAAA,EAAI,QAAQ,EAAA;AAAG;AAErC;AAMO,IAAM,SAAA,GAAsB;AAAA,EACjC,KAAA,EAAO,gBAAA;AAAA,EACP,IAAA,EAAM,aAAA;AAAA,EACN,MAAA,EAAQ,SAAA;AAAA,EACR,WAAA,EAAa,QAAA;AAAA,EACb,WAAA,EAAa,CAAA;AAAA,EACb,WAAA,EAAa,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,EAAA,EAAG;AAAA,EACtC,OAAA,EAAS,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,EAAA;AACjC;AAaO,IAAM,eAAA,GAAkC;AAAA,EAC7C,KAAA,EAAO,YAAA;AAAA,EACP,WAAA,EAAa,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,EAAA,EAAG;AAAA,EACtC,OAAA,EAAS,EAAE,KAAA,EAAO,EAAA,EAAI,QAAQ,EAAA;AAChC;AAGO,SAAS,SAAA,CAAU,KAAA,EAAoB,WAAA,GAAc,CAAA,EAAW;AACrE,EAAA,QAAQ,KAAA;AAAO,IACb,KAAK,QAAA;AACH,MAAA,OAAO,CAAA,EAAG,WAAA,GAAc,CAAC,CAAA,CAAA,EAAI,cAAc,CAAC,CAAA,CAAA;AAAA,IAC9C,KAAK,QAAA;AACH,MAAA,OAAO,CAAA,EAAG,WAAW,CAAA,CAAA,EAAI,WAAA,GAAc,GAAG,CAAA,CAAA;AAAA,IAC5C,KAAK,OAAA;AAAA,IACL;AACE,MAAA,OAAO,EAAA;AAAA;AAEb;AAEO,IAAM,cAAA,GAA0C,MAAA,CAAO,MAAA,CAAO,eAAe;AAC7E,IAAM,qBAAA,GACX,MAAA,CAAO,MAAA,CAAO,sBAAsB;;;ACvN/B,IAAM,eAAA,GAAkB;AAG/B,IAAM,qBAAA,GAAwB,gBAAA;AAGvB,SAAS,cAAc,YAAA,EAA8B;AAC1D,EAAA,OAAO,SAAS,YAAY,CAAA,CAAA;AAC9B;AAQA,IAAM,WAAA,GAAc,CAAC,OAAA,EAAS,cAAA,EAAgB,SAAS,aAAa,CAAA;AAKpE,SAAS,oBAAoB,EAAA,EAAqB;AAChD,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,EAAE,CAAA;AAC3C;AAOO,SAAS,mBAAmB,GAAA,EAA4C;AAC7E,EAAA,MAAM,WAAgC,EAAC;AACvC,EAAA,MAAM,eAAe,IAAI,GAAA;AAAA,IACvB,GAAA,CAAI,WAAA,CAAY,GAAA,CAAI,CAAC,UAAA,KAAe,CAAC,aAAA,CAAc,UAAA,CAAW,EAAE,CAAA,EAAG,UAAA,CAAW,EAAE,CAAC;AAAA,GACnF;AACA,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,KAAA,MAAW,cAAc,WAAA,EAAa;AACpC,IAAA,GAAA,CAAI,UAAU,CAAA,CAAE,OAAA,CAAQ,CAAC,SAAS,KAAA,KAAU;AAC1C,MAAA,MAAM,IAAA,GAAO,CAAC,UAAA,EAAY,KAAA,EAAO,IAAI,CAAA;AACrC,MAAA,MAAM,EAAE,IAAG,GAAI,OAAA;AACf,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA,EAAG;AAChB,QAAA,QAAA,CAAS,IAAA,CAAK;AAAA,UACZ,IAAA;AAAA,UACA,OAAA,EAAS,iBAAiB,EAAE,CAAA,uEAAA;AAAA,SAC7B,CAAA;AAAA,MACH;AACA,MAAA,IAAA,CAAK,IAAI,EAAE,CAAA;AACX,MAAA,IAAI,OAAO,eAAA,EAAiB;AAC1B,QAAA,QAAA,CAAS,KAAK,EAAE,IAAA,EAAM,SAAS,CAAA,CAAA,EAAI,EAAE,wCAAwC,CAAA;AAAA,MAC/E,CAAA,MAAA,IAAW,EAAA,CAAG,UAAA,CAAW,qBAAqB,CAAA,EAAG;AAC/C,QAAA,QAAA,CAAS,IAAA,CAAK;AAAA,UACZ,IAAA;AAAA,UACA,OAAA,EAAS,sBAAsB,qBAAqB,CAAA,cAAA;AAAA,SACrD,CAAA;AAAA,MACH,CAAA,MAAA,IAAW,mBAAA,CAAoB,EAAE,CAAA,EAAG;AAClC,QAAA,QAAA,CAAS,IAAA,CAAK;AAAA,UACZ,IAAA;AAAA,UACA,OAAA,EAAS,IAAI,EAAE,CAAA,iEAAA;AAAA,SAChB,CAAA;AAAA,MACH;AACA,MAAA,MAAM,YAAA,GAAe,YAAA,CAAa,GAAA,CAAI,EAAE,CAAA;AACxC,MAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,QAAA,QAAA,CAAS,IAAA,CAAK;AAAA,UACZ,IAAA;AAAA,UACA,OAAA,EAAS,CAAA,CAAA,EAAI,EAAE,CAAA,+CAAA,EAAkD,YAAY,CAAA,CAAA;AAAA,SAC9E,CAAA;AAAA,MACH;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AACA,EAAA,OAAO,QAAA;AACT;;;AChEA,IAAM,cAAA,GAAiBA,KAAA,CAAE,IAAA,CAAK,UAA8C,CAAA;AAC5E,IAAM,qBAAA,GAAwBA,KAAA,CAAE,IAAA,CAAK,iBAAqD,CAAA;AAE1F,IAAM,UAAA,GAAaA,MAAE,MAAA,CAAO;AAAA,EAC1B,OAAOA,KAAA,CAAE,MAAA,EAAO,CAAE,MAAA,GAAS,QAAA,EAAS;AAAA,EACpC,QAAQA,KAAA,CAAE,MAAA,EAAO,CAAE,MAAA,GAAS,QAAA;AAC9B,CAAC,CAAA;AAED,IAAM,cAAA,GAAiBA,MAAE,MAAA,CAAO;AAAA,EAC9B,CAAA,EAAGA,KAAA,CAAE,MAAA,EAAO,CAAE,MAAA,EAAO;AAAA,EACrB,CAAA,EAAGA,KAAA,CAAE,MAAA,EAAO,CAAE,MAAA;AAChB,CAAC,CAAA;AAED,IAAM,WAAWA,KAAA,CAAE,MAAA,EAAO,CAAE,KAAA,CAAM,wCAAwC,uBAAuB,CAAA;AAE1F,IAAM,cAAA,GAAiBA,MAAE,WAAA,CAAY;AAAA,EAC1C,EAAA,EAAIA,KAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACpB,IAAA,EAAM,cAAA;AAAA,EACN,KAAA,EAAOA,MAAE,MAAA,EAAO;AAAA,EAChB,WAAA,EAAaA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACjC,QAAA,EAAU,cAAA;AAAA,EACV,IAAA,EAAM,UAAA;AAAA,EACN,IAAA,EAAM,SAAS,QAAA,EAAS;AAAA,EACxB,MAAA,EAAQ,SAAS,QAAA;AACnB,CAAC;AAEM,IAAM,iBAAA,GAAoBA,MAAE,WAAA,CAAY;AAAA,EAC7C,EAAA,EAAIA,KAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACpB,IAAA,EAAM,qBAAA;AAAA,EACN,KAAA,EAAOA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC3B,QAAA,EAAU,cAAA;AAAA,EACV,IAAA,EAAM,UAAA;AAAA,EACN,IAAA,EAAM,SAAS,QAAA,EAAS;AAAA,EACxB,MAAA,EAAQ,SAAS,QAAA;AACnB,CAAC;AAEM,IAAM,UAAA,GAAaA,MAAE,WAAA,CAAY;AAAA,EACtC,EAAA,EAAIA,KAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACpB,KAAA,EAAOA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC3B,QAAA,EAAU,cAAA;AAAA,EACV,IAAA,EAAM;AACR,CAAC;AAEM,IAAM,gBAAA,GAAmBA,MAAE,WAAA,CAAY;AAAA,EAC5C,EAAA,EAAIA,KAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACpB,IAAA,EAAMA,MAAE,MAAA,EAAO;AAAA,EACf,QAAA,EAAU,cAAA;AAAA,EACV,IAAA,EAAM,UAAA;AAAA,EACN,YAAYA,KAAA,CAAE,MAAA,GAAS,GAAA,CAAI,CAAC,EAAE,QAAA;AAChC,CAAC;AAEM,IAAM,cAAA,GAAiBA,MAC3B,WAAA,CAAY;AAAA,EACX,OAAA,EAASA,KAAA,CAAE,OAAA,CAAQ,gBAAgB,CAAA;AAAA,EACnC,KAAA,EAAOA,MAAE,MAAA,EAAO;AAAA,EAChB,KAAA,EAAOA,KAAA,CAAE,KAAA,CAAM,cAAc,CAAA;AAAA,EAC7B,YAAA,EAAcA,KAAA,CAAE,KAAA,CAAM,iBAAiB,CAAA;AAAA,EACvC,KAAA,EAAOA,KAAA,CAAE,KAAA,CAAM,UAAU,CAAA;AAAA,EACzB,WAAA,EAAaA,KAAA,CAAE,KAAA,CAAM,gBAAgB;AACvC,CAAC,CAAA,CACA,WAAA,CAAY,CAAC,QAAA,EAAU,OAAA,KAAY;AAClC,EAAA,KAAA,MAAW,EAAE,IAAA,EAAM,OAAA,EAAQ,IAAK,kBAAA,CAAmB,QAAQ,CAAA,EAAG;AAC5D,IAAA,OAAA,CAAQ,SAAS,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,SAAS,CAAA;AAAA,EACpD;AACF,CAAC;AAiBI,IAAM,iBAAA,GAAoB;AAO1B,SAAS,cAAc,KAAA,EAA6B;AACzD,EAAA,MAAM,OAAA,GAAU,cAAc,KAAK,CAAA;AACnC,EAAA,IAAI,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG,OAAO,QAAQ,OAAO,CAAA;AAC9C,EAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAU,sBAAA,EAAuB,GAAI,QAAQ,KAAK,CAAA;AACpE,EAAA,MAAM,MAAA,GAAS,cAAA,CAAe,SAAA,CAAU,QAAQ,CAAA;AAChD,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,OAAO,OAAA;AAAA,MACL,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,QAClC,IAAA,EAAM,UAAA;AAAA,UACJ,MAAM,IAAA,CAAK,MAAA,CAAO,CAAC,GAAA,KAAgC,OAAO,QAAQ,QAAQ,CAAA;AAAA,UAC1E;AAAA,SACF;AAAA,QACA,SAAS,KAAA,CAAM;AAAA,OACjB,CAAE;AAAA,KACJ;AAAA,EACF;AACA,EAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,QAAA,EAAU,OAAO,IAAA,EAAmB;AACzD;AAEA,SAAS,QAAQ,MAAA,EAAsC;AACrD,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,KAAA;AAAA,IACJ,OAAO,MAAA,CAAO,GAAA,CAAI,CAACC,EAAAA,KAAM,CAAA,EAAGA,GAAE,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,IAAK,QAAQ,CAAA,EAAA,EAAKA,EAAAA,CAAE,OAAO,CAAA,CAAE,CAAA,CAAE,KAAK,IAAI,CAAA;AAAA,IACnF;AAAA,GACF;AACF;AAOA,IAAM,kBAAA,GAAqB,GAAA;AAiB3B,SAAS,cAAc,KAAA,EAAiC;AACtD,EAAA,MAAM,SAA0B,EAAC;AACjC,EAAA,IAAI,CAAC,WAAA,CAAY,KAAK,CAAA,EAAG,OAAO,MAAA;AAGhC,EAAA,MAAM,WAAA,uBAAkB,OAAA,EAAwB;AAChD,EAAA,MAAM,OAAwB,EAAC;AAC/B,EAAA,MAAM,KAAA,GAAQ,CAAC,SAAA,EAAmB,WAAA,KAAwC;AACxE,IAAA,WAAA,CAAY,GAAA,CAAI,SAAA,EAAW,IAAA,CAAK,MAAM,CAAA;AACtC,IAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,SAAS,IAAI,MAAA,GAAY,MAAA,CAAO,KAAK,SAAS,CAAA;AACzE,IAAA,MAAM,IAAA,GAAO,IAAA,EAAM,MAAA,IAAW,SAAA,CAAwB,MAAA;AACtD,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,SAAA,EAAW,IAAA,EAAM,MAAM,IAAA,EAAM,CAAA,EAAG,aAAa,CAAA;AAAA,EAC3D,CAAA;AACA,EAAA,KAAA,CAAM,KAAK,CAAA;AACX,EAAA,OAAO,IAAA,CAAK,MAAA,GAAS,CAAA,IAAK,MAAA,CAAO,SAAS,kBAAA,EAAoB;AAC5D,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AACpC,IAAA,IAAI,OAAA,CAAQ,IAAA,KAAS,OAAA,CAAQ,IAAA,EAAM;AACjC,MAAA,IAAA,CAAK,GAAA,EAAI;AACT,MAAA;AAAA,IACF;AACA,IAAA,MAAM,QAAQ,OAAA,CAAQ,IAAA,EAAA;AACtB,IAAA,MAAM,MAAM,OAAA,CAAQ,IAAA,KAAS,SAAY,KAAA,GAAQ,OAAA,CAAQ,KAAK,KAAK,CAAA;AACnE,IAAA,MAAM,KAAA,GAAkB,OAAA,CAAQ,SAAA,CAA+C,GAAG,CAAA;AAClF,IAAA,IAAI,CAAC,WAAA,CAAY,KAAK,CAAA,EAAG;AACzB,IAAA,IAAI,IAAA,CAAK,UAAU,iBAAA,EAAmB;AACpC,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,CAAC,GAAG,IAAA,CAAK,OAAA,CAAQ,CAAC,EAAE,WAAA,EAAY,KAAM,WAAA,IAAe,EAAE,GAAG,GAAG,CAAA;AAAA,QACnE,OAAA,EAAS,uCAAuC,iBAAiB,CAAA,YAAA;AAAA,OAClE,CAAA;AACD,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,YAAY,GAAA,CAAI,KAAK,CAAA,IAAK,EAAA,KAAO,KAAK,MAAA,EAAQ;AACnD,IAAA,KAAA,CAAM,OAAO,GAAG,CAAA;AAAA,EAClB;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,YAAY,KAAA,EAAiC;AACpD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA;AAChD;AAGA,IAAM,yBAAA,GAA4B,CAAA;AAiBlC,SAAS,QAAQ,KAAA,EAA2B;AAC1C,EAAA,IAAI,KAAA,IAAS,IAAA,IAAQ,OAAO,KAAA,KAAU,QAAA,EAAU;AAC9C,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,sBAAA,EAAwB,EAAC,EAAE;AAAA,EACvD;AACA,EAAA,MAAM,GAAA,GAAM,KAAA;AACZ,EAAA,MAAM,IAAA,GAAgC,EAAE,GAAG,GAAA,EAAI;AAC/C,EAAA,OAAO,IAAA,CAAK,gBAAA;AACZ,EAAA,IAAA,CAAK,OAAA,GAAU,gBAAA;AACf,EAAA,IAAI,OAAO,IAAA,CAAK,KAAA,KAAU,QAAA,OAAe,KAAA,GAAQ,wBAAA;AACjD,EAAA,IAAI,CAAC,MAAM,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA,EAAG,IAAA,CAAK,QAAQ,EAAC;AAC9C,EAAA,MAAM,qBAAA,GAAwB,IAAI,OAAA,KAAY,yBAAA;AAC9C,EAAA,MAAM,gBAAA,GAAmB,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,YAAY,CAAA,GACpD,IAAA,CAAK,YAAA,CACF,GAAA,CAAI,CAAC,WAAA,EAAsB,SAAA,MAAe,EAAE,WAAA,EAAa,SAAA,EAAU,CAAE,CAAA,CACrE,MAAA,CAAO,CAAC,EAAE,WAAA,EAAY,KAAM,CAAC,qBAAA,IAAyB,aAAA,CAAc,WAAW,CAAC,CAAA,GACnF,EAAC;AACL,EAAA,IAAA,CAAK,eAAe,gBAAA,CAAiB,GAAA,CAAI,CAAC,EAAE,WAAA,OAAkB,WAAW,CAAA;AACzE,EAAA,IAAI,CAAC,MAAM,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA,EAAG,IAAA,CAAK,QAAQ,EAAC;AAC9C,EAAA,IAAI,CAAC,MAAM,OAAA,CAAQ,IAAA,CAAK,WAAW,CAAA,EAAG,IAAA,CAAK,cAAc,EAAC;AAC1D,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,IAAA;AAAA,IACV,wBAAwB,gBAAA,CAAiB,GAAA,CAAI,CAAC,EAAE,SAAA,OAAgB,SAAS;AAAA,GAC3E;AACF;AAEA,SAAS,cAAc,KAAA,EAAyB;AAC9C,EAAA,OAAO,SAAS,IAAA,IAAQ,OAAO,UAAU,QAAA,IAAY,UAAA,IAAc,SAAS,MAAA,IAAU,KAAA;AACxF;AAMA,SAAS,UAAA,CACP,MACA,sBAAA,EACqB;AACrB,EAAA,MAAM,CAAC,UAAA,EAAY,KAAA,EAAO,GAAG,IAAI,CAAA,GAAI,IAAA;AACrC,EAAA,IAAI,UAAA,KAAe,cAAA,IAAkB,OAAO,KAAA,KAAU,UAAU,OAAO,IAAA;AACvE,EAAA,MAAM,SAAA,GAAY,uBAAuB,KAAK,CAAA;AAC9C,EAAA,OAAO,cAAc,MAAA,GAAY,IAAA,GAAO,CAAC,UAAA,EAAY,SAAA,EAAW,GAAG,IAAI,CAAA;AACzE;;;AC9OA,IAAM,oBAAA,GAAuB,GAAA;AAWtB,SAAS,eAAA,GAAiC;AAE/C,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,EAAA,MAAM,gBAAA,uBAAuB,OAAA,EAAgB;AAC7C,EAAA,IAAI,eAAA,GAAkB,CAAA;AACtB,EAAA,MAAM,IAAA,GAAO,CAAC,KAAA,KAA4B;AACxC,IAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,OAAO,KAAA,KAAU,UAAU,OAAO,KAAA;AACxD,IAAA,IAAI,UAAU,GAAA,CAAI,KAAK,GAAG,MAAM,IAAI,MAAM,qCAAqC,CAAA;AAC/E,IAAA,IAAI,gBAAA,CAAiB,GAAA,CAAI,KAAK,CAAA,EAAG;AAC/B,MAAA,eAAA,IAAmB,KAAA,CAAM,QAAQ,KAAK,CAAA,GAAI,MAAM,MAAA,GAAS,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,CAAE,MAAA;AAC5E,MAAA,IAAI,kBAAkB,oBAAA,EAAsB;AAC1C,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,sFAAsF,oBAAoB,CAAA,SAAA;AAAA,SAC5G;AAAA,MACF;AAAA,IACF,CAAA,MAAO;AACL,MAAA,gBAAA,CAAiB,IAAI,KAAK,CAAA;AAAA,IAC5B;AACA,IAAA,SAAA,CAAU,IAAI,KAAK,CAAA;AACnB,IAAA,MAAM,MAAA,GAAS,KAAA;AACf,IAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,KAAK,IAC9B,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA,GACd,MAAA,CAAO,WAAA;AAAA,MACL,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CACf,MAAA,CAAO,CAAC,GAAA,KAAQ,MAAA,CAAO,GAAG,CAAA,KAAM,MAAS,CAAA,CACzC,MAAK,CACL,GAAA,CAAI,CAAC,GAAA,KAAQ,CAAC,GAAA,EAAK,KAAK,MAAA,CAAO,GAAG,CAAC,CAAC,CAAC;AAAA,KAC1C;AACJ,IAAA,SAAA,CAAU,OAAO,KAAK,CAAA;AACtB,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,iBAAA,CACd,KAAA,EACA,WAAA,EACA,IAAA,EAC+C;AAC/C,EAAA,MAAM,MAAA,GAAS,KAAA;AACf,EAAA,MAAM,QAAQ,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAC7B,MAAA,CAAO,CAAC,IAAA,KAAS,CAAC,WAAA,CAAY,QAAA,CAAS,IAAI,CAAA,IAAK,MAAA,CAAO,IAAI,CAAA,KAAM,MAAS,EAC1E,IAAA,EAAK;AACR,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAC/B,EAAA,OAAO,MAAA,CAAO,WAAA,CAAY,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAS,CAAC,IAAA,EAAM,IAAA,CAAK,MAAA,CAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;AAC3E;AAMO,SAAS,mBAAA,CACd,KAAA,EACA,MAAA,EACA,WAAA,EACA,IAAA,EACG;AACH,EAAA,MAAM,UAAU,MAAA,GAAS,iBAAA,CAAkB,MAAA,EAAQ,WAAA,EAAa,IAAI,CAAA,GAAI,MAAA;AACxE,EAAA,IAAI,CAAC,SAAS,OAAO,KAAA;AACrB,EAAA,OAAO,MAAA,CAAO,WAAA,CAAY,CAAC,GAAG,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG,GAAG,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAC,CAAC,CAAA;AAClF;;;AC9EO,IAAM,eAAA,GAAkB;AAAA,EAC7B,SAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,cAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF;AACO,IAAM,gBAAA,GAAmB;AAAA,EAC9B,IAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,aAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF;AACO,IAAM,kBAAA,GAAqB;AAAA,EAChC,IAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF;AACO,IAAM,WAAA,GAAc,CAAC,IAAA,EAAM,OAAA,EAAS,YAAY,MAAM;AACtD,IAAM,oBAAoB,CAAC,IAAA,EAAM,MAAA,EAAQ,UAAA,EAAY,QAAQ,YAAY;AAUzE,SAAS,aAAA,CACd,OACA,WAAA,EAC2B;AAC3B,EAAA,OAAO,iBAAA,CAAkB,KAAA,EAAO,WAAA,EAAa,eAAA,EAAiB,CAAA;AAChE;AAQO,SAAS,iBAAA,CACd,KAAA,EACA,MAAA,EACA,WAAA,EACG;AACH,EAAA,OAAO,mBAAA,CAAoB,KAAA,EAAO,MAAA,EAAQ,WAAA,EAAa,iBAAiB,CAAA;AAC1E;;;ACrCA,SAAS,MAAM,CAAA,EAAmB;AAChC,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,GAAI,GAAG,CAAA,GAAI,GAAA;AAC/B;AAEA,SAAS,aAAa,CAAA,EAAuB;AAC3C,EAAA,OAAO,EAAE,CAAA,EAAG,KAAA,CAAM,CAAA,CAAE,CAAC,GAAG,CAAA,EAAG,KAAA,CAAM,CAAA,CAAE,CAAC,CAAA,EAAE;AACxC;AAEA,SAAS,SAASC,EAAAA,EAAe;AAC/B,EAAA,OAAO,EAAE,KAAA,EAAO,KAAA,CAAMA,EAAAA,CAAE,KAAK,GAAG,MAAA,EAAQ,KAAA,CAAMA,EAAAA,CAAE,MAAM,CAAA,EAAE;AAC1D;AAGA,SAAS,QAAA,CAAS,GAAa,IAAA,EAA+B;AAC5D,EAAA,MAAM,GAAA,GAAgB;AAAA,IACpB,IAAI,CAAA,CAAE,EAAA;AAAA,IACN,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,OAAO,CAAA,CAAE,KAAA;AAAA,IACT,QAAA,EAAU,YAAA,CAAa,CAAA,CAAE,QAAQ,CAAA;AAAA,IACjC,IAAA,EAAM,QAAA,CAAS,CAAA,CAAE,IAAI;AAAA,GACvB;AACA,EAAA,IAAI,CAAA,CAAE,WAAA,EAAa,GAAA,CAAI,WAAA,GAAc,CAAA,CAAE,WAAA;AACvC,EAAA,IAAI,CAAA,CAAE,IAAA,EAAM,GAAA,CAAI,IAAA,GAAO,CAAA,CAAE,IAAA;AACzB,EAAA,IAAI,CAAA,CAAE,MAAA,EAAQ,GAAA,CAAI,MAAA,GAAS,CAAA,CAAE,MAAA;AAC7B,EAAA,OAAO,mBAAA,CAAoB,GAAA,EAAK,CAAA,EAAG,gBAAA,EAAkB,IAAI,CAAA;AAC3D;AAEA,SAAS,eAAA,CAAgB,GAAqB,IAAA,EAAuC;AACnF,EAAA,MAAM,GAAA,GAAwB;AAAA,IAC5B,IAAI,CAAA,CAAE,EAAA;AAAA,IACN,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,QAAA,EAAU,YAAA,CAAa,CAAA,CAAE,QAAQ,CAAA;AAAA,IACjC,IAAA,EAAM,QAAA,CAAS,CAAA,CAAE,IAAI;AAAA,GACvB;AACA,EAAA,IAAI,CAAA,CAAE,KAAA,EAAO,GAAA,CAAI,KAAA,GAAQ,CAAA,CAAE,KAAA;AAC3B,EAAA,IAAI,CAAA,CAAE,IAAA,EAAM,GAAA,CAAI,IAAA,GAAO,CAAA,CAAE,IAAA;AACzB,EAAA,IAAI,CAAA,CAAE,MAAA,EAAQ,GAAA,CAAI,MAAA,GAAS,CAAA,CAAE,MAAA;AAC7B,EAAA,OAAO,mBAAA,CAAoB,GAAA,EAAK,CAAA,EAAG,kBAAA,EAAoB,IAAI,CAAA;AAC7D;AAEA,SAAS,QAAA,CAAS,GAAc,IAAA,EAAgC;AAC9D,EAAA,MAAM,GAAA,GAAiB;AAAA,IACrB,IAAI,CAAA,CAAE,EAAA;AAAA,IACN,QAAA,EAAU,YAAA,CAAa,CAAA,CAAE,QAAQ,CAAA;AAAA,IACjC,IAAA,EAAM,QAAA,CAAS,CAAA,CAAE,IAAI;AAAA,GACvB;AACA,EAAA,IAAI,CAAA,CAAE,KAAA,EAAO,GAAA,CAAI,KAAA,GAAQ,CAAA,CAAE,KAAA;AAC3B,EAAA,OAAO,mBAAA,CAAoB,GAAA,EAAK,CAAA,EAAG,WAAA,EAAa,IAAI,CAAA;AACtD;AAEA,SAAS,cAAA,CAAe,GAAmB,IAAA,EAAqC;AAC9E,EAAA,MAAM,GAAA,GAAsB;AAAA,IAC1B,IAAI,CAAA,CAAE,EAAA;AAAA,IACN,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,QAAA,EAAU,YAAA,CAAa,CAAA,CAAE,QAAQ,CAAA;AAAA,IACjC,IAAA,EAAM,QAAA,CAAS,CAAA,CAAE,IAAI;AAAA,GACvB;AACA,EAAA,IAAI,CAAA,CAAE,UAAA,EAAY,GAAA,CAAI,UAAA,GAAa,CAAA,CAAE,UAAA;AACrC,EAAA,OAAO,mBAAA,CAAoB,GAAA,EAAK,CAAA,EAAG,iBAAA,EAAmB,IAAI,CAAA;AAC5D;AAEA,IAAM,IAAA,GAAO,CAAC,CAAA,EAAmB,CAAA,KAC/B,CAAA,CAAE,EAAA,GAAK,CAAA,CAAE,EAAA,GAAK,EAAA,GAAK,CAAA,CAAE,EAAA,GAAK,CAAA,CAAE,KAAK,CAAA,GAAI,CAAA;AAShC,SAAS,aAAa,GAAA,EAA6B;AACxD,EAAA,MAAM,OAAO,eAAA,EAAgB;AAC7B,EAAA,OAAO,mBAAA;AAAA,IACL;AAAA,MACE,OAAA,EAAS,gBAAA;AAAA,MACT,OAAO,GAAA,CAAI,KAAA;AAAA,MACX,KAAA,EAAO,CAAC,GAAG,GAAA,CAAI,KAAK,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,KAAS,SAAS,IAAA,EAAM,IAAI,CAAC,CAAA,CAAE,KAAK,IAAI,CAAA;AAAA,MACnE,YAAA,EAAc,CAAC,GAAG,GAAA,CAAI,YAAY,CAAA,CAC/B,GAAA,CAAI,CAAC,WAAA,KAAgB,gBAAgB,WAAA,EAAa,IAAI,CAAC,CAAA,CACvD,KAAK,IAAI,CAAA;AAAA,MACZ,KAAA,EAAO,CAAC,GAAG,GAAA,CAAI,KAAK,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,KAAS,SAAS,IAAA,EAAM,IAAI,CAAC,CAAA,CAAE,KAAK,IAAI,CAAA;AAAA,MACnE,WAAA,EAAa,CAAC,GAAG,GAAA,CAAI,WAAW,CAAA,CAC7B,GAAA,CAAI,CAAC,UAAA,KAAe,eAAe,UAAA,EAAY,IAAI,CAAC,CAAA,CACpD,KAAK,IAAI;AAAA,KACd;AAAA,IACA,GAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,GACF;AACF;AAQO,SAAS,iBAAA,CAAkB,GAAA,EAAiB,MAAA,GAAS,IAAA,EAAc;AACxE,EAAA,MAAM,SAAA,GAAY,aAAa,GAAG,CAAA;AAClC,EAAA,MAAM,SACJ,SAAA,CAAU,WAAA,CAAY,SAAS,CAAA,GAC3B,SAAA,GACA,OAAO,WAAA,CAAY,MAAA,CAAO,QAAQ,SAAS,CAAA,CAAE,OAAO,CAAC,CAAC,GAAG,CAAA,KAAM,GAAA,KAAQ,aAAa,CAAC,CAAA;AAC3F,EAAA,OAAO,SAAS,CAAA,EAAG,IAAA,CAAK,UAAU,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAC;AAAA,CAAA,GAAO,IAAA,CAAK,UAAU,MAAM,CAAA;AAChF;AClHO,SAAS,MAAM,MAAA,EAAwB;AAC5C,EAAA,OAAO,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIC,aAAA,CAAO,CAAC,CAAC,CAAA,CAAA;AAC/B;AAGO,SAAS,cAAA,CACd,IAAA,EACA,QAAA,EACA,SAAA,GAAoD,EAAC,EAC3C;AACV,EAAA,MAAM,IAAA,GAAO,gBAAgB,IAAI,CAAA;AACjC,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,MAAM,MAAM,CAAA;AAAA,IAChB,IAAA;AAAA,IACA,KAAA,EAAO,SAAA,CAAU,KAAA,IAAS,IAAA,CAAK,KAAA;AAAA,IAC/B,aAAa,SAAA,CAAU,WAAA;AAAA,IACvB,QAAA;AAAA,IACA,MAAM,SAAA,CAAU,IAAA,IAAQ,EAAE,GAAG,KAAK,WAAA,EAAY;AAAA,IAC9C,MAAM,SAAA,CAAU,IAAA;AAAA,IAChB,QAAQ,SAAA,CAAU;AAAA,GACpB;AACF;AAGO,SAAS,sBAAA,CACd,IAAA,EACA,QAAA,EACA,SAAA,GAAyE,EAAC,EACxD;AAClB,EAAA,MAAM,IAAA,GAAO,uBAAuB,IAAI,CAAA;AACxC,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,MAAM,KAAK,CAAA;AAAA,IACf,IAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAM,SAAA,CAAU,IAAA,IAAQ,EAAE,GAAG,KAAK,WAAA,EAAY;AAAA,IAC9C,OAAO,SAAA,CAAU,KAAA;AAAA,IACjB,MAAM,SAAA,CAAU,IAAA;AAAA,IAChB,QAAQ,SAAA,CAAU;AAAA,GACpB;AACF;AAGO,SAAS,eAAA,CACd,QAAA,EACA,SAAA,GAAyD,EAAC,EAC/C;AACX,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,MAAM,MAAM,CAAA;AAAA,IAChB,QAAA;AAAA,IACA,MAAM,SAAA,CAAU,IAAA,IAAQ,EAAE,GAAG,UAAU,WAAA,EAAY;AAAA,IACnD,KAAA,EAAO,SAAA,CAAU,KAAA,IAAS,SAAA,CAAU;AAAA,GACtC;AACF;AAGO,SAAS,oBAAA,CACd,QAAA,EACA,SAAA,GAA8D,EAAC,EAC/C;AAChB,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,MAAM,KAAK,CAAA;AAAA,IACf,IAAA,EAAM,UAAU,IAAA,IAAQ,EAAA;AAAA,IACxB,QAAA;AAAA,IACA,MAAM,SAAA,CAAU,IAAA,IAAQ,EAAE,GAAG,gBAAgB,WAAA,EAAY;AAAA,IACzD,YAAY,SAAA,CAAU;AAAA,GACxB;AACF;AAGO,SAAS,aAAA,CAAc,QAAQ,wBAAA,EAAsC;AAC1E,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,gBAAA;AAAA,IACT,KAAA;AAAA,IACA,OAAO,EAAC;AAAA,IACR,cAAc,EAAC;AAAA,IACf,OAAO,EAAC;AAAA,IACR,aAAa;AAAC,GAChB;AACF;;;ACpFA,IAAM,CAAA,GAAI,eAAA;AACV,IAAM,CAAA,GAAI,sBAAA;AAEV,IAAM,UAAA,GAAa,GAAA;AAEZ,IAAM,eAAA,GAA8B;AAAA,EACzC,OAAA,EAAS,gBAAA;AAAA,EACT,KAAA,EAAO,2BAAA;AAAA,EACP,KAAA,EAAO;AAAA,IACL;AAAA,MACE,EAAA,EAAI,sBAAA;AAAA,MACJ,IAAA,EAAM,UAAA;AAAA,MACN,KAAA,EAAO,iBAAA;AAAA,MACP,WAAA,EAAa,mEAAA;AAAA,MACb,QAAA,EAAU,EAAE,CAAA,EAAG,EAAA,EAAI,GAAG,GAAA,EAAI;AAAA,MAC1B,IAAA,EAAM,EAAE,KAAA,EAAO,CAAA,CAAE,SAAS,WAAA,CAAY,KAAA,EAAO,QAAQ,GAAA;AAAI,KAC3D;AAAA,IACA;AAAA,MACE,EAAA,EAAI,gBAAA;AAAA,MACJ,IAAA,EAAM,gBAAA;AAAA,MACN,KAAA,EAAO,mBAAA;AAAA,MACP,WAAA,EAAa,qDAAA;AAAA,MACb,QAAA,EAAU,EAAE,CAAA,EAAG,GAAA,EAAK,GAAG,GAAA,EAAI;AAAA,MAC3B,IAAA,EAAM,EAAE,KAAA,EAAO,UAAA,EAAY,QAAQ,CAAA,CAAE,gBAAgB,CAAA,CAAE,WAAA,CAAY,MAAA;AAAO,KAC5E;AAAA,IACA;AAAA,MACE,EAAA,EAAI,eAAA;AAAA,MACJ,IAAA,EAAM,gBAAA;AAAA,MACN,KAAA,EAAO,qBAAA;AAAA,MACP,WAAA,EAAa,mDAAA;AAAA,MACb,QAAA,EAAU,EAAE,CAAA,EAAG,GAAA,EAAK,GAAG,GAAA,EAAI;AAAA,MAC3B,IAAA,EAAM,EAAE,KAAA,EAAO,UAAA,EAAY,QAAQ,CAAA,CAAE,gBAAgB,CAAA,CAAE,WAAA,CAAY,MAAA;AAAO,KAC5E;AAAA,IACA;AAAA,MACE,EAAA,EAAI,iBAAA;AAAA,MACJ,IAAA,EAAM,gBAAA;AAAA,MACN,KAAA,EAAO,kBAAA;AAAA,MACP,WAAA,EAAa,iDAAA;AAAA,MACb,QAAA,EAAU,EAAE,CAAA,EAAG,GAAA,EAAK,GAAG,GAAA,EAAI;AAAA,MAC3B,IAAA,EAAM,EAAE,KAAA,EAAO,UAAA,EAAY,QAAQ,CAAA,CAAE,gBAAgB,CAAA,CAAE,WAAA,CAAY,MAAA;AAAO,KAC5E;AAAA,IACA;AAAA,MACE,EAAA,EAAI,YAAA;AAAA,MACJ,IAAA,EAAM,uBAAA;AAAA,MACN,KAAA,EAAO,iBAAA;AAAA,MACP,WAAA,EAAa,oDAAA;AAAA,MACb,QAAA,EAAU,EAAE,CAAA,EAAG,GAAA,EAAK,GAAG,GAAA,EAAI;AAAA,MAC3B,MAAM,EAAE,GAAG,CAAA,CAAE,uBAAuB,EAAE,WAAA;AAAY,KACpD;AAAA,IACA;AAAA,MACE,EAAA,EAAI,eAAA;AAAA,MACJ,IAAA,EAAM,UAAA;AAAA,MACN,KAAA,EAAO,gBAAA;AAAA,MACP,WAAA,EAAa,8DAAA;AAAA,MACb,QAAA,EAAU,EAAE,CAAA,EAAG,GAAA,EAAK,GAAG,GAAA,EAAI;AAAA,MAC3B,IAAA,EAAM,EAAE,KAAA,EAAO,UAAA,EAAY,QAAQ,GAAA;AAAI;AACzC,GACF;AAAA,EACA,YAAA,EAAc;AAAA,IACZ;AAAA,MACE,EAAA,EAAI,uBAAA;AAAA,MACJ,IAAA,EAAM,cAAA;AAAA,MACN,QAAA,EAAU,EAAE,CAAA,EAAG,GAAA,EAAK,GAAG,GAAA,EAAI;AAAA,MAC3B,IAAA,EAAM,EAAE,GAAG,CAAA,CAAE,aAAa,WAAA;AAAY,KACxC;AAAA,IACA;AAAA,MACE,EAAA,EAAI,sBAAA;AAAA,MACJ,IAAA,EAAM,cAAA;AAAA,MACN,QAAA,EAAU,EAAE,CAAA,EAAG,GAAA,EAAK,GAAG,GAAA,EAAI;AAAA,MAC3B,IAAA,EAAM,EAAE,GAAG,CAAA,CAAE,aAAa,WAAA;AAAY,KACxC;AAAA,IACA;AAAA,MACE,EAAA,EAAI,oBAAA;AAAA,MACJ,IAAA,EAAM,eAAA;AAAA,MACN,KAAA,EAAO,aAAA;AAAA,MACP,QAAA,EAAU,EAAE,CAAA,EAAG,GAAA,EAAK,GAAG,GAAA,EAAI;AAAA,MAC3B,IAAA,EAAM,EAAE,GAAG,CAAA,CAAE,cAAc,WAAA;AAAY,KACzC;AAAA,IACA;AAAA,MACE,EAAA,EAAI,yBAAA;AAAA,MACJ,IAAA,EAAM,gBAAA;AAAA,MACN,QAAA,EAAU,EAAE,CAAA,EAAG,GAAA,EAAK,GAAG,GAAA,EAAI;AAAA,MAC3B,MAAM,EAAE,GAAG,CAAA,CAAE,gBAAgB,EAAE,WAAA;AAAY;AAC7C,GACF;AAAA,EACA,KAAA,EAAO;AAAA,IACL;AAAA,MACE,EAAA,EAAI,WAAA;AAAA,MACJ,KAAA,EAAO,gBAAA;AAAA,MACP,QAAA,EAAU,EAAE,CAAA,EAAG,EAAA,EAAI,GAAG,EAAA,EAAG;AAAA,MACzB,IAAA,EAAM,EAAE,KAAA,EAAO,IAAA,EAAM,QAAQ,EAAA;AAAG;AAClC,GACF;AAAA,EACA,WAAA,EAAa;AAAA,IACX;AAAA,MACE,EAAA,EAAI,oBAAA;AAAA,MACJ,IAAA,EAAM,0EAAA;AAAA,MACN,QAAA,EAAU,EAAE,CAAA,EAAG,GAAA,EAAK,GAAG,GAAA,EAAI;AAAA,MAC3B,IAAA,EAAM,EAAE,GAAG,eAAA,CAAgB,WAAA,EAAY;AAAA,MACvC,UAAA,EAAY;AAAA;AACd;AAEJ","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 * At most this many nesting issues per document. Each carries a path of {@link MAX_NESTING_DEPTH}\n * keys, so one wide container beyond the limit would otherwise give millions of them and an error\n * text longer than a string may be.\n */\nconst MAX_NESTING_ISSUES = 100;\n\ninterface OpenContainer {\n readonly container: object;\n readonly keys: readonly string[] | undefined;\n readonly size: number;\n next: number;\n readonly keyInParent: string | number | undefined;\n}\n\n/**\n * Each object or array at the first level beyond {@link MAX_NESTING_DEPTH}, in document order, up\n * to {@link MAX_NESTING_ISSUES}; what lies below it is not visited. Walked with an explicit stack,\n * because the documents it guards against are the ones that overflow a recursive walk. The stack\n * holds only the containers the walk is inside of and a path is built only for an issue, so the\n * walk's memory grows with the number of containers, not with their number times their depth.\n */\nfunction nestingIssues(input: unknown): DocumentIssue[] {\n const issues: DocumentIssue[] = [];\n if (!isContainer(input)) return issues;\n // A caller in JavaScript may put one container in several places, or inside itself: walking it\n // again at a level no deeper than before finds nothing new, and would grow exponentially.\n const deepestWalk = new WeakMap<object, number>();\n const open: OpenContainer[] = [];\n const enter = (container: object, keyInParent?: string | number): void => {\n deepestWalk.set(container, open.length);\n const keys = Array.isArray(container) ? undefined : Object.keys(container);\n const size = keys?.length ?? (container as unknown[]).length;\n open.push({ container, keys, size, next: 0, keyInParent });\n };\n enter(input);\n while (open.length > 0 && issues.length < MAX_NESTING_ISSUES) {\n const current = open[open.length - 1]!;\n if (current.next === current.size) {\n open.pop();\n continue;\n }\n const index = current.next++;\n const key = current.keys === undefined ? index : current.keys[index]!;\n const entry: unknown = (current.container as Record<string | number, unknown>)[key];\n if (!isContainer(entry)) continue;\n if (open.length >= MAX_NESTING_DEPTH) {\n issues.push({\n path: [...open.flatMap(({ keyInParent }) => keyInParent ?? []), key],\n message: `objects and arrays may nest at most ${MAX_NESTING_DEPTH} levels deep`,\n });\n continue;\n }\n if ((deepestWalk.get(entry) ?? -1) >= open.length) continue;\n enter(entry, key);\n }\n return issues;\n}\n\nfunction isContainer(value: unknown): value is object {\n return typeof value === \"object\" && value !== null;\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 * The copy of the fields a document carries that this modeler does not know, in canonical form.\n * Not part of the package's API: `foreign.ts` copies with a new copier on every call, the\n * serializer with one copier for the whole document, so a value the document shares counts at\n * every place.\n */\n\n/**\n * A copy holds an object or array that sits in several places at each of them. An object that\n * holds the level below twice would need memory doubling with every level, and a wide object held\n * a thousand times would need a thousand copies of it. So each time a copier copies a container\n * again, it counts that container's entries; no real document repeats this many. A document that\n * shares nothing counts none, however large it is.\n */\nconst MAX_REPEATED_ENTRIES = 1_000_000;\n\n/** Copies one value into canonical form. */\nexport type CanonicalCopy = (value: unknown) => unknown;\n\n/**\n * A copier for one document. JSON objects have no key order, so nested keys are sorted too: equal\n * data, equal bytes. A value that sits in several places is copied at each of them, and its\n * entries count at every place after the first: past {@link MAX_REPEATED_ENTRIES} such repeated\n * entries it throws, and so does a value that contains itself.\n */\nexport function canonicalCopier(): CanonicalCopy {\n // Only the containers on the current path: one object in several places is no cycle.\n const ancestors = new Set<object>();\n const copiedContainers = new WeakSet<object>();\n let repeatedEntries = 0;\n const copy = (value: unknown): unknown => {\n if (value === null || typeof value !== \"object\") return value;\n if (ancestors.has(value)) throw new Error(\"Cannot serialize a cyclic document.\");\n if (copiedContainers.has(value)) {\n repeatedEntries += Array.isArray(value) ? value.length : Object.keys(value).length;\n if (repeatedEntries > MAX_REPEATED_ENTRIES) {\n throw new Error(\n `Cannot serialize a document whose shared objects and arrays would repeat more than ${MAX_REPEATED_ENTRIES} entries.`,\n );\n }\n } else {\n copiedContainers.add(value);\n }\n ancestors.add(value);\n const record = value as Record<string, unknown>;\n const copied = Array.isArray(value)\n ? value.map(copy)\n : Object.fromEntries(\n Object.keys(record)\n .filter((key) => record[key] !== undefined)\n .sort()\n .map((key) => [key, copy(record[key])]),\n );\n ancestors.delete(value);\n return copied;\n };\n return copy;\n}\n\n/** The fields of `value` outside `knownFields`, copied by `copy`, or undefined when there are none. */\nexport function copyForeignFields(\n value: object,\n knownFields: readonly string[],\n copy: CanonicalCopy,\n): Readonly<Record<string, unknown>> | 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, copy(record[name])]));\n}\n\n/**\n * `known` followed by the foreign fields of `source`, copied by `copy`. Built from entries, never\n * by assignment, so a field named `__proto__` stays a field instead of replacing the prototype.\n */\nexport function appendForeignFields<T extends object>(\n known: T,\n source: object | undefined,\n knownFields: readonly string[],\n copy: CanonicalCopy,\n): T {\n const foreign = source ? copyForeignFields(source, knownFields, copy) : undefined;\n if (!foreign) return known;\n return Object.fromEntries([...Object.entries(known), ...Object.entries(foreign)]) as T;\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\nimport { appendForeignFields, canonicalCopier, copyForeignFields } from \"./canonical-copy\";\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/**\n * The fields of `value` outside `knownFields`, or undefined when there are none. A value that\n * sits in several places of `value` is copied at each of them; past 1,000,000 entries repeated\n * that way it throws, and so does a value that contains itself.\n */\nexport function foreignFields(\n value: object,\n knownFields: readonly string[],\n): ForeignFields | undefined {\n return copyForeignFields(value, knownFields, canonicalCopier());\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. A value that sits in\n * several places of `source` is copied at each of them; past 1,000,000 entries repeated that way\n * it throws, and so does a value that contains itself.\n */\nexport function withForeignFields<T extends object>(\n known: T,\n source: object | undefined,\n knownFields: readonly string[],\n): T {\n return appendForeignFields(known, source, knownFields, canonicalCopier());\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} from \"./foreign\";\nimport { appendForeignFields, canonicalCopier, type CanonicalCopy } from \"./canonical-copy\";\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, copy: CanonicalCopy): 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 appendForeignFields(out, n, TEAM_NODE_FIELDS, copy);\n}\n\nfunction normInteraction(e: InteractionShape, copy: CanonicalCopy): 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 appendForeignFields(out, e, INTERACTION_FIELDS, copy);\n}\n\nfunction normFlow(f: FlowShape, copy: CanonicalCopy): 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 appendForeignFields(out, f, FLOW_FIELDS, copy);\n}\n\nfunction normAnnotation(a: TextAnnotation, copy: CanonicalCopy): 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 appendForeignFields(out, a, ANNOTATION_FIELDS, copy);\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. A value of such a field that sits\n * in several places of the document is copied at each of them, and its entries count at every\n * place after the first: past 1,000,000 such repeated entries it throws, and so does a value that\n * contains itself. A document that shares nothing has no such limit.\n */\nexport function canonicalize(doc: TtDocument): TtDocument {\n const copy = canonicalCopier();\n return appendForeignFields(\n {\n version: DOCUMENT_VERSION,\n title: doc.title,\n nodes: [...doc.nodes].map((node) => normNode(node, copy)).sort(byId),\n interactions: [...doc.interactions]\n .map((interaction) => normInteraction(interaction, copy))\n .sort(byId),\n flows: [...doc.flows].map((flow) => normFlow(flow, copy)).sort(byId),\n annotations: [...doc.annotations]\n .map((annotation) => normAnnotation(annotation, copy))\n .sort(byId),\n },\n doc,\n DOCUMENT_FIELDS,\n copy,\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
@@ -351,7 +351,10 @@ declare function parseDocument(input: unknown): ParseResult;
351
351
 
352
352
  /**
353
353
  * Returns a canonicalised copy of a document (sorted, rounded, version-stamped). Fields the
354
- * modeler does not know follow the known ones, sorted by name.
354
+ * modeler does not know follow the known ones, sorted by name. A value of such a field that sits
355
+ * in several places of the document is copied at each of them, and its entries count at every
356
+ * place after the first: past 1,000,000 such repeated entries it throws, and so does a value that
357
+ * contains itself. A document that shares nothing has no such limit.
355
358
  */
356
359
  declare function canonicalize(doc: TtDocument): TtDocument;
357
360
  /**
@@ -374,11 +377,17 @@ declare const FLOW_FIELDS: readonly ["id", "label", "position", "size"];
374
377
  declare const ANNOTATION_FIELDS: readonly ["id", "text", "position", "size", "attachedTo"];
375
378
  /** Unknown fields by name, sorted, with their values in canonical form. */
376
379
  type ForeignFields = Readonly<Record<string, unknown>>;
377
- /** The fields of `value` outside `knownFields`, or undefined when there are none. */
380
+ /**
381
+ * The fields of `value` outside `knownFields`, or undefined when there are none. A value that
382
+ * sits in several places of `value` is copied at each of them; past 1,000,000 entries repeated
383
+ * that way it throws, and so does a value that contains itself.
384
+ */
378
385
  declare function foreignFields(value: object, knownFields: readonly string[]): ForeignFields | undefined;
379
386
  /**
380
387
  * `known` followed by the foreign fields of `source`. Built from entries, never by assignment, so
381
- * a field named `__proto__` stays a field instead of replacing the prototype.
388
+ * a field named `__proto__` stays a field instead of replacing the prototype. A value that sits in
389
+ * several places of `source` is copied at each of them; past 1,000,000 entries repeated that way
390
+ * it throws, and so does a value that contains itself.
382
391
  */
383
392
  declare function withForeignFields<T extends object>(known: T, source: object | undefined, knownFields: readonly string[]): T;
384
393
 
package/dist/index.d.ts CHANGED
@@ -351,7 +351,10 @@ declare function parseDocument(input: unknown): ParseResult;
351
351
 
352
352
  /**
353
353
  * Returns a canonicalised copy of a document (sorted, rounded, version-stamped). Fields the
354
- * modeler does not know follow the known ones, sorted by name.
354
+ * modeler does not know follow the known ones, sorted by name. A value of such a field that sits
355
+ * in several places of the document is copied at each of them, and its entries count at every
356
+ * place after the first: past 1,000,000 such repeated entries it throws, and so does a value that
357
+ * contains itself. A document that shares nothing has no such limit.
355
358
  */
356
359
  declare function canonicalize(doc: TtDocument): TtDocument;
357
360
  /**
@@ -374,11 +377,17 @@ declare const FLOW_FIELDS: readonly ["id", "label", "position", "size"];
374
377
  declare const ANNOTATION_FIELDS: readonly ["id", "text", "position", "size", "attachedTo"];
375
378
  /** Unknown fields by name, sorted, with their values in canonical form. */
376
379
  type ForeignFields = Readonly<Record<string, unknown>>;
377
- /** The fields of `value` outside `knownFields`, or undefined when there are none. */
380
+ /**
381
+ * The fields of `value` outside `knownFields`, or undefined when there are none. A value that
382
+ * sits in several places of `value` is copied at each of them; past 1,000,000 entries repeated
383
+ * that way it throws, and so does a value that contains itself.
384
+ */
378
385
  declare function foreignFields(value: object, knownFields: readonly string[]): ForeignFields | undefined;
379
386
  /**
380
387
  * `known` followed by the foreign fields of `source`. Built from entries, never by assignment, so
381
- * a field named `__proto__` stays a field instead of replacing the prototype.
388
+ * a field named `__proto__` stays a field instead of replacing the prototype. A value that sits in
389
+ * several places of `source` is copied at each of them; past 1,000,000 entries repeated that way
390
+ * it throws, and so does a value that contains itself.
382
391
  */
383
392
  declare function withForeignFields<T extends object>(known: T, source: object | undefined, knownFields: readonly string[]): T;
384
393
 
package/dist/index.js CHANGED
@@ -273,28 +273,44 @@ function refused(issues) {
273
273
  issues
274
274
  };
275
275
  }
276
+ var MAX_NESTING_ISSUES = 100;
276
277
  function nestingIssues(input) {
277
278
  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) {
279
+ if (!isContainer(input)) return issues;
280
+ const deepestWalk = /* @__PURE__ */ new WeakMap();
281
+ const open = [];
282
+ const enter = (container, keyInParent) => {
283
+ deepestWalk.set(container, open.length);
284
+ const keys = Array.isArray(container) ? void 0 : Object.keys(container);
285
+ const size = keys?.length ?? container.length;
286
+ open.push({ container, keys, size, next: 0, keyInParent });
287
+ };
288
+ enter(input);
289
+ while (open.length > 0 && issues.length < MAX_NESTING_ISSUES) {
290
+ const current = open[open.length - 1];
291
+ if (current.next === current.size) {
292
+ open.pop();
293
+ continue;
294
+ }
295
+ const index = current.next++;
296
+ const key = current.keys === void 0 ? index : current.keys[index];
297
+ const entry = current.container[key];
298
+ if (!isContainer(entry)) continue;
299
+ if (open.length >= MAX_NESTING_DEPTH) {
283
300
  issues.push({
284
- path,
301
+ path: [...open.flatMap(({ keyInParent }) => keyInParent ?? []), key],
285
302
  message: `objects and arrays may nest at most ${MAX_NESTING_DEPTH} levels deep`
286
303
  });
287
304
  continue;
288
305
  }
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
- }
306
+ if ((deepestWalk.get(entry) ?? -1) >= open.length) continue;
307
+ enter(entry, key);
295
308
  }
296
309
  return issues;
297
310
  }
311
+ function isContainer(value) {
312
+ return typeof value === "object" && value !== null;
313
+ }
298
314
  var EDGE_INTERACTIONS_VERSION = 1;
299
315
  function migrate(input) {
300
316
  if (input == null || typeof input !== "object") {
@@ -326,6 +342,47 @@ function pathInFile(path, interactionFileIndexes) {
326
342
  return fileIndex === void 0 ? path : [collection, fileIndex, ...rest];
327
343
  }
328
344
 
345
+ // src/canonical-copy.ts
346
+ var MAX_REPEATED_ENTRIES = 1e6;
347
+ function canonicalCopier() {
348
+ const ancestors = /* @__PURE__ */ new Set();
349
+ const copiedContainers = /* @__PURE__ */ new WeakSet();
350
+ let repeatedEntries = 0;
351
+ const copy = (value) => {
352
+ if (value === null || typeof value !== "object") return value;
353
+ if (ancestors.has(value)) throw new Error("Cannot serialize a cyclic document.");
354
+ if (copiedContainers.has(value)) {
355
+ repeatedEntries += Array.isArray(value) ? value.length : Object.keys(value).length;
356
+ if (repeatedEntries > MAX_REPEATED_ENTRIES) {
357
+ throw new Error(
358
+ `Cannot serialize a document whose shared objects and arrays would repeat more than ${MAX_REPEATED_ENTRIES} entries.`
359
+ );
360
+ }
361
+ } else {
362
+ copiedContainers.add(value);
363
+ }
364
+ ancestors.add(value);
365
+ const record = value;
366
+ const copied = Array.isArray(value) ? value.map(copy) : Object.fromEntries(
367
+ Object.keys(record).filter((key) => record[key] !== void 0).sort().map((key) => [key, copy(record[key])])
368
+ );
369
+ ancestors.delete(value);
370
+ return copied;
371
+ };
372
+ return copy;
373
+ }
374
+ function copyForeignFields(value, knownFields, copy) {
375
+ const record = value;
376
+ const names = Object.keys(record).filter((name) => !knownFields.includes(name) && record[name] !== void 0).sort();
377
+ if (names.length === 0) return void 0;
378
+ return Object.fromEntries(names.map((name) => [name, copy(record[name])]));
379
+ }
380
+ function appendForeignFields(known, source, knownFields, copy) {
381
+ const foreign = source ? copyForeignFields(source, knownFields, copy) : void 0;
382
+ if (!foreign) return known;
383
+ return Object.fromEntries([...Object.entries(known), ...Object.entries(foreign)]);
384
+ }
385
+
329
386
  // src/foreign.ts
330
387
  var DOCUMENT_FIELDS = [
331
388
  "version",
@@ -356,24 +413,11 @@ var INTERACTION_FIELDS = [
356
413
  ];
357
414
  var FLOW_FIELDS = ["id", "label", "position", "size"];
358
415
  var ANNOTATION_FIELDS = ["id", "text", "position", "size", "attachedTo"];
359
- function canonicalValue(value) {
360
- if (Array.isArray(value)) return value.map(canonicalValue);
361
- if (value === null || typeof value !== "object") return value;
362
- const record = value;
363
- return Object.fromEntries(
364
- Object.keys(record).filter((key) => record[key] !== void 0).sort().map((key) => [key, canonicalValue(record[key])])
365
- );
366
- }
367
416
  function foreignFields(value, knownFields) {
368
- const record = value;
369
- const names = Object.keys(record).filter((name) => !knownFields.includes(name) && record[name] !== void 0).sort();
370
- if (names.length === 0) return void 0;
371
- return Object.fromEntries(names.map((name) => [name, canonicalValue(record[name])]));
417
+ return copyForeignFields(value, knownFields, canonicalCopier());
372
418
  }
373
419
  function withForeignFields(known, source, knownFields) {
374
- const foreign = source ? foreignFields(source, knownFields) : void 0;
375
- if (!foreign) return known;
376
- return Object.fromEntries([...Object.entries(known), ...Object.entries(foreign)]);
420
+ return appendForeignFields(known, source, knownFields, canonicalCopier());
377
421
  }
378
422
 
379
423
  // src/serialize.ts
@@ -386,7 +430,7 @@ function normPosition(p) {
386
430
  function normSize(s2) {
387
431
  return { width: round(s2.width), height: round(s2.height) };
388
432
  }
389
- function normNode(n) {
433
+ function normNode(n, copy) {
390
434
  const out = {
391
435
  id: n.id,
392
436
  type: n.type,
@@ -397,9 +441,9 @@ function normNode(n) {
397
441
  if (n.description) out.description = n.description;
398
442
  if (n.fill) out.fill = n.fill;
399
443
  if (n.stroke) out.stroke = n.stroke;
400
- return withForeignFields(out, n, TEAM_NODE_FIELDS);
444
+ return appendForeignFields(out, n, TEAM_NODE_FIELDS, copy);
401
445
  }
402
- function normInteraction(e) {
446
+ function normInteraction(e, copy) {
403
447
  const out = {
404
448
  id: e.id,
405
449
  mode: e.mode,
@@ -409,18 +453,18 @@ function normInteraction(e) {
409
453
  if (e.label) out.label = e.label;
410
454
  if (e.fill) out.fill = e.fill;
411
455
  if (e.stroke) out.stroke = e.stroke;
412
- return withForeignFields(out, e, INTERACTION_FIELDS);
456
+ return appendForeignFields(out, e, INTERACTION_FIELDS, copy);
413
457
  }
414
- function normFlow(f) {
458
+ function normFlow(f, copy) {
415
459
  const out = {
416
460
  id: f.id,
417
461
  position: normPosition(f.position),
418
462
  size: normSize(f.size)
419
463
  };
420
464
  if (f.label) out.label = f.label;
421
- return withForeignFields(out, f, FLOW_FIELDS);
465
+ return appendForeignFields(out, f, FLOW_FIELDS, copy);
422
466
  }
423
- function normAnnotation(a) {
467
+ function normAnnotation(a, copy) {
424
468
  const out = {
425
469
  id: a.id,
426
470
  text: a.text,
@@ -428,21 +472,23 @@ function normAnnotation(a) {
428
472
  size: normSize(a.size)
429
473
  };
430
474
  if (a.attachedTo) out.attachedTo = a.attachedTo;
431
- return withForeignFields(out, a, ANNOTATION_FIELDS);
475
+ return appendForeignFields(out, a, ANNOTATION_FIELDS, copy);
432
476
  }
433
477
  var byId = (a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
434
478
  function canonicalize(doc) {
435
- return withForeignFields(
479
+ const copy = canonicalCopier();
480
+ return appendForeignFields(
436
481
  {
437
482
  version: DOCUMENT_VERSION,
438
483
  title: doc.title,
439
- nodes: [...doc.nodes].map(normNode).sort(byId),
440
- interactions: [...doc.interactions].map(normInteraction).sort(byId),
441
- flows: [...doc.flows].map(normFlow).sort(byId),
442
- annotations: [...doc.annotations].map(normAnnotation).sort(byId)
484
+ nodes: [...doc.nodes].map((node) => normNode(node, copy)).sort(byId),
485
+ interactions: [...doc.interactions].map((interaction) => normInteraction(interaction, copy)).sort(byId),
486
+ flows: [...doc.flows].map((flow) => normFlow(flow, copy)).sort(byId),
487
+ annotations: [...doc.annotations].map((annotation) => normAnnotation(annotation, copy)).sort(byId)
443
488
  },
444
489
  doc,
445
- DOCUMENT_FIELDS
490
+ DOCUMENT_FIELDS,
491
+ copy
446
492
  );
447
493
  }
448
494
  function serializeDocument(doc, pretty = true) {
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 /**\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"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/notation.ts","../src/ids.ts","../src/schema.ts","../src/canonical-copy.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 * At most this many nesting issues per document. Each carries a path of {@link MAX_NESTING_DEPTH}\n * keys, so one wide container beyond the limit would otherwise give millions of them and an error\n * text longer than a string may be.\n */\nconst MAX_NESTING_ISSUES = 100;\n\ninterface OpenContainer {\n readonly container: object;\n readonly keys: readonly string[] | undefined;\n readonly size: number;\n next: number;\n readonly keyInParent: string | number | undefined;\n}\n\n/**\n * Each object or array at the first level beyond {@link MAX_NESTING_DEPTH}, in document order, up\n * to {@link MAX_NESTING_ISSUES}; what lies below it is not visited. Walked with an explicit stack,\n * because the documents it guards against are the ones that overflow a recursive walk. The stack\n * holds only the containers the walk is inside of and a path is built only for an issue, so the\n * walk's memory grows with the number of containers, not with their number times their depth.\n */\nfunction nestingIssues(input: unknown): DocumentIssue[] {\n const issues: DocumentIssue[] = [];\n if (!isContainer(input)) return issues;\n // A caller in JavaScript may put one container in several places, or inside itself: walking it\n // again at a level no deeper than before finds nothing new, and would grow exponentially.\n const deepestWalk = new WeakMap<object, number>();\n const open: OpenContainer[] = [];\n const enter = (container: object, keyInParent?: string | number): void => {\n deepestWalk.set(container, open.length);\n const keys = Array.isArray(container) ? undefined : Object.keys(container);\n const size = keys?.length ?? (container as unknown[]).length;\n open.push({ container, keys, size, next: 0, keyInParent });\n };\n enter(input);\n while (open.length > 0 && issues.length < MAX_NESTING_ISSUES) {\n const current = open[open.length - 1]!;\n if (current.next === current.size) {\n open.pop();\n continue;\n }\n const index = current.next++;\n const key = current.keys === undefined ? index : current.keys[index]!;\n const entry: unknown = (current.container as Record<string | number, unknown>)[key];\n if (!isContainer(entry)) continue;\n if (open.length >= MAX_NESTING_DEPTH) {\n issues.push({\n path: [...open.flatMap(({ keyInParent }) => keyInParent ?? []), key],\n message: `objects and arrays may nest at most ${MAX_NESTING_DEPTH} levels deep`,\n });\n continue;\n }\n if ((deepestWalk.get(entry) ?? -1) >= open.length) continue;\n enter(entry, key);\n }\n return issues;\n}\n\nfunction isContainer(value: unknown): value is object {\n return typeof value === \"object\" && value !== null;\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 * The copy of the fields a document carries that this modeler does not know, in canonical form.\n * Not part of the package's API: `foreign.ts` copies with a new copier on every call, the\n * serializer with one copier for the whole document, so a value the document shares counts at\n * every place.\n */\n\n/**\n * A copy holds an object or array that sits in several places at each of them. An object that\n * holds the level below twice would need memory doubling with every level, and a wide object held\n * a thousand times would need a thousand copies of it. So each time a copier copies a container\n * again, it counts that container's entries; no real document repeats this many. A document that\n * shares nothing counts none, however large it is.\n */\nconst MAX_REPEATED_ENTRIES = 1_000_000;\n\n/** Copies one value into canonical form. */\nexport type CanonicalCopy = (value: unknown) => unknown;\n\n/**\n * A copier for one document. JSON objects have no key order, so nested keys are sorted too: equal\n * data, equal bytes. A value that sits in several places is copied at each of them, and its\n * entries count at every place after the first: past {@link MAX_REPEATED_ENTRIES} such repeated\n * entries it throws, and so does a value that contains itself.\n */\nexport function canonicalCopier(): CanonicalCopy {\n // Only the containers on the current path: one object in several places is no cycle.\n const ancestors = new Set<object>();\n const copiedContainers = new WeakSet<object>();\n let repeatedEntries = 0;\n const copy = (value: unknown): unknown => {\n if (value === null || typeof value !== \"object\") return value;\n if (ancestors.has(value)) throw new Error(\"Cannot serialize a cyclic document.\");\n if (copiedContainers.has(value)) {\n repeatedEntries += Array.isArray(value) ? value.length : Object.keys(value).length;\n if (repeatedEntries > MAX_REPEATED_ENTRIES) {\n throw new Error(\n `Cannot serialize a document whose shared objects and arrays would repeat more than ${MAX_REPEATED_ENTRIES} entries.`,\n );\n }\n } else {\n copiedContainers.add(value);\n }\n ancestors.add(value);\n const record = value as Record<string, unknown>;\n const copied = Array.isArray(value)\n ? value.map(copy)\n : Object.fromEntries(\n Object.keys(record)\n .filter((key) => record[key] !== undefined)\n .sort()\n .map((key) => [key, copy(record[key])]),\n );\n ancestors.delete(value);\n return copied;\n };\n return copy;\n}\n\n/** The fields of `value` outside `knownFields`, copied by `copy`, or undefined when there are none. */\nexport function copyForeignFields(\n value: object,\n knownFields: readonly string[],\n copy: CanonicalCopy,\n): Readonly<Record<string, unknown>> | 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, copy(record[name])]));\n}\n\n/**\n * `known` followed by the foreign fields of `source`, copied by `copy`. Built from entries, never\n * by assignment, so a field named `__proto__` stays a field instead of replacing the prototype.\n */\nexport function appendForeignFields<T extends object>(\n known: T,\n source: object | undefined,\n knownFields: readonly string[],\n copy: CanonicalCopy,\n): T {\n const foreign = source ? copyForeignFields(source, knownFields, copy) : undefined;\n if (!foreign) return known;\n return Object.fromEntries([...Object.entries(known), ...Object.entries(foreign)]) as T;\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\nimport { appendForeignFields, canonicalCopier, copyForeignFields } from \"./canonical-copy\";\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/**\n * The fields of `value` outside `knownFields`, or undefined when there are none. A value that\n * sits in several places of `value` is copied at each of them; past 1,000,000 entries repeated\n * that way it throws, and so does a value that contains itself.\n */\nexport function foreignFields(\n value: object,\n knownFields: readonly string[],\n): ForeignFields | undefined {\n return copyForeignFields(value, knownFields, canonicalCopier());\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. A value that sits in\n * several places of `source` is copied at each of them; past 1,000,000 entries repeated that way\n * it throws, and so does a value that contains itself.\n */\nexport function withForeignFields<T extends object>(\n known: T,\n source: object | undefined,\n knownFields: readonly string[],\n): T {\n return appendForeignFields(known, source, knownFields, canonicalCopier());\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} from \"./foreign\";\nimport { appendForeignFields, canonicalCopier, type CanonicalCopy } from \"./canonical-copy\";\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, copy: CanonicalCopy): 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 appendForeignFields(out, n, TEAM_NODE_FIELDS, copy);\n}\n\nfunction normInteraction(e: InteractionShape, copy: CanonicalCopy): 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 appendForeignFields(out, e, INTERACTION_FIELDS, copy);\n}\n\nfunction normFlow(f: FlowShape, copy: CanonicalCopy): 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 appendForeignFields(out, f, FLOW_FIELDS, copy);\n}\n\nfunction normAnnotation(a: TextAnnotation, copy: CanonicalCopy): 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 appendForeignFields(out, a, ANNOTATION_FIELDS, copy);\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. A value of such a field that sits\n * in several places of the document is copied at each of them, and its entries count at every\n * place after the first: past 1,000,000 such repeated entries it throws, and so does a value that\n * contains itself. A document that shares nothing has no such limit.\n */\nexport function canonicalize(doc: TtDocument): TtDocument {\n const copy = canonicalCopier();\n return appendForeignFields(\n {\n version: DOCUMENT_VERSION,\n title: doc.title,\n nodes: [...doc.nodes].map((node) => normNode(node, copy)).sort(byId),\n interactions: [...doc.interactions]\n .map((interaction) => normInteraction(interaction, copy))\n .sort(byId),\n flows: [...doc.flows].map((flow) => normFlow(flow, copy)).sort(byId),\n annotations: [...doc.annotations]\n .map((annotation) => normAnnotation(annotation, copy))\n .sort(byId),\n },\n doc,\n DOCUMENT_FIELDS,\n copy,\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,6 +1,6 @@
1
1
  {
2
2
  "name": "@miragon/team-topologies-schema-model",
3
- "version": "0.15.0",
3
+ "version": "0.16.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": {