@miragon/team-topologies-schema-model 0.15.1 → 0.17.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/dist/index.cjs CHANGED
@@ -344,6 +344,47 @@ function pathInFile(path, interactionFileIndexes) {
344
344
  return fileIndex === void 0 ? path : [collection, fileIndex, ...rest];
345
345
  }
346
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
+
347
388
  // src/foreign.ts
348
389
  var DOCUMENT_FIELDS = [
349
390
  "version",
@@ -374,24 +415,11 @@ var INTERACTION_FIELDS = [
374
415
  ];
375
416
  var FLOW_FIELDS = ["id", "label", "position", "size"];
376
417
  var ANNOTATION_FIELDS = ["id", "text", "position", "size", "attachedTo"];
377
- function canonicalValue(value) {
378
- if (Array.isArray(value)) return value.map(canonicalValue);
379
- if (value === null || typeof value !== "object") return value;
380
- const record = value;
381
- return Object.fromEntries(
382
- Object.keys(record).filter((key) => record[key] !== void 0).sort().map((key) => [key, canonicalValue(record[key])])
383
- );
384
- }
385
418
  function foreignFields(value, knownFields) {
386
- const record = value;
387
- const names = Object.keys(record).filter((name) => !knownFields.includes(name) && record[name] !== void 0).sort();
388
- if (names.length === 0) return void 0;
389
- return Object.fromEntries(names.map((name) => [name, canonicalValue(record[name])]));
419
+ return copyForeignFields(value, knownFields, canonicalCopier());
390
420
  }
391
421
  function withForeignFields(known, source, knownFields) {
392
- const foreign = source ? foreignFields(source, knownFields) : void 0;
393
- if (!foreign) return known;
394
- return Object.fromEntries([...Object.entries(known), ...Object.entries(foreign)]);
422
+ return appendForeignFields(known, source, knownFields, canonicalCopier());
395
423
  }
396
424
 
397
425
  // src/serialize.ts
@@ -404,7 +432,7 @@ function normPosition(p) {
404
432
  function normSize(s2) {
405
433
  return { width: round(s2.width), height: round(s2.height) };
406
434
  }
407
- function normNode(n) {
435
+ function normNode(n, copy) {
408
436
  const out = {
409
437
  id: n.id,
410
438
  type: n.type,
@@ -415,9 +443,9 @@ function normNode(n) {
415
443
  if (n.description) out.description = n.description;
416
444
  if (n.fill) out.fill = n.fill;
417
445
  if (n.stroke) out.stroke = n.stroke;
418
- return withForeignFields(out, n, TEAM_NODE_FIELDS);
446
+ return appendForeignFields(out, n, TEAM_NODE_FIELDS, copy);
419
447
  }
420
- function normInteraction(e) {
448
+ function normInteraction(e, copy) {
421
449
  const out = {
422
450
  id: e.id,
423
451
  mode: e.mode,
@@ -427,18 +455,18 @@ function normInteraction(e) {
427
455
  if (e.label) out.label = e.label;
428
456
  if (e.fill) out.fill = e.fill;
429
457
  if (e.stroke) out.stroke = e.stroke;
430
- return withForeignFields(out, e, INTERACTION_FIELDS);
458
+ return appendForeignFields(out, e, INTERACTION_FIELDS, copy);
431
459
  }
432
- function normFlow(f) {
460
+ function normFlow(f, copy) {
433
461
  const out = {
434
462
  id: f.id,
435
463
  position: normPosition(f.position),
436
464
  size: normSize(f.size)
437
465
  };
438
466
  if (f.label) out.label = f.label;
439
- return withForeignFields(out, f, FLOW_FIELDS);
467
+ return appendForeignFields(out, f, FLOW_FIELDS, copy);
440
468
  }
441
- function normAnnotation(a) {
469
+ function normAnnotation(a, copy) {
442
470
  const out = {
443
471
  id: a.id,
444
472
  text: a.text,
@@ -446,21 +474,23 @@ function normAnnotation(a) {
446
474
  size: normSize(a.size)
447
475
  };
448
476
  if (a.attachedTo) out.attachedTo = a.attachedTo;
449
- return withForeignFields(out, a, ANNOTATION_FIELDS);
477
+ return appendForeignFields(out, a, ANNOTATION_FIELDS, copy);
450
478
  }
451
479
  var byId = (a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
452
480
  function canonicalize(doc) {
453
- return withForeignFields(
481
+ const copy = canonicalCopier();
482
+ return appendForeignFields(
454
483
  {
455
484
  version: DOCUMENT_VERSION,
456
485
  title: doc.title,
457
- nodes: [...doc.nodes].map(normNode).sort(byId),
458
- interactions: [...doc.interactions].map(normInteraction).sort(byId),
459
- flows: [...doc.flows].map(normFlow).sort(byId),
460
- 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)
461
490
  },
462
491
  doc,
463
- DOCUMENT_FIELDS
492
+ DOCUMENT_FIELDS,
493
+ copy
464
494
  );
465
495
  }
466
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 * 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 * 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":"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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 * 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
@@ -342,6 +342,47 @@ function pathInFile(path, interactionFileIndexes) {
342
342
  return fileIndex === void 0 ? path : [collection, fileIndex, ...rest];
343
343
  }
344
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
+
345
386
  // src/foreign.ts
346
387
  var DOCUMENT_FIELDS = [
347
388
  "version",
@@ -372,24 +413,11 @@ var INTERACTION_FIELDS = [
372
413
  ];
373
414
  var FLOW_FIELDS = ["id", "label", "position", "size"];
374
415
  var ANNOTATION_FIELDS = ["id", "text", "position", "size", "attachedTo"];
375
- function canonicalValue(value) {
376
- if (Array.isArray(value)) return value.map(canonicalValue);
377
- if (value === null || typeof value !== "object") return value;
378
- const record = value;
379
- return Object.fromEntries(
380
- Object.keys(record).filter((key) => record[key] !== void 0).sort().map((key) => [key, canonicalValue(record[key])])
381
- );
382
- }
383
416
  function foreignFields(value, knownFields) {
384
- const record = value;
385
- const names = Object.keys(record).filter((name) => !knownFields.includes(name) && record[name] !== void 0).sort();
386
- if (names.length === 0) return void 0;
387
- return Object.fromEntries(names.map((name) => [name, canonicalValue(record[name])]));
417
+ return copyForeignFields(value, knownFields, canonicalCopier());
388
418
  }
389
419
  function withForeignFields(known, source, knownFields) {
390
- const foreign = source ? foreignFields(source, knownFields) : void 0;
391
- if (!foreign) return known;
392
- return Object.fromEntries([...Object.entries(known), ...Object.entries(foreign)]);
420
+ return appendForeignFields(known, source, knownFields, canonicalCopier());
393
421
  }
394
422
 
395
423
  // src/serialize.ts
@@ -402,7 +430,7 @@ function normPosition(p) {
402
430
  function normSize(s2) {
403
431
  return { width: round(s2.width), height: round(s2.height) };
404
432
  }
405
- function normNode(n) {
433
+ function normNode(n, copy) {
406
434
  const out = {
407
435
  id: n.id,
408
436
  type: n.type,
@@ -413,9 +441,9 @@ function normNode(n) {
413
441
  if (n.description) out.description = n.description;
414
442
  if (n.fill) out.fill = n.fill;
415
443
  if (n.stroke) out.stroke = n.stroke;
416
- return withForeignFields(out, n, TEAM_NODE_FIELDS);
444
+ return appendForeignFields(out, n, TEAM_NODE_FIELDS, copy);
417
445
  }
418
- function normInteraction(e) {
446
+ function normInteraction(e, copy) {
419
447
  const out = {
420
448
  id: e.id,
421
449
  mode: e.mode,
@@ -425,18 +453,18 @@ function normInteraction(e) {
425
453
  if (e.label) out.label = e.label;
426
454
  if (e.fill) out.fill = e.fill;
427
455
  if (e.stroke) out.stroke = e.stroke;
428
- return withForeignFields(out, e, INTERACTION_FIELDS);
456
+ return appendForeignFields(out, e, INTERACTION_FIELDS, copy);
429
457
  }
430
- function normFlow(f) {
458
+ function normFlow(f, copy) {
431
459
  const out = {
432
460
  id: f.id,
433
461
  position: normPosition(f.position),
434
462
  size: normSize(f.size)
435
463
  };
436
464
  if (f.label) out.label = f.label;
437
- return withForeignFields(out, f, FLOW_FIELDS);
465
+ return appendForeignFields(out, f, FLOW_FIELDS, copy);
438
466
  }
439
- function normAnnotation(a) {
467
+ function normAnnotation(a, copy) {
440
468
  const out = {
441
469
  id: a.id,
442
470
  text: a.text,
@@ -444,21 +472,23 @@ function normAnnotation(a) {
444
472
  size: normSize(a.size)
445
473
  };
446
474
  if (a.attachedTo) out.attachedTo = a.attachedTo;
447
- return withForeignFields(out, a, ANNOTATION_FIELDS);
475
+ return appendForeignFields(out, a, ANNOTATION_FIELDS, copy);
448
476
  }
449
477
  var byId = (a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
450
478
  function canonicalize(doc) {
451
- return withForeignFields(
479
+ const copy = canonicalCopier();
480
+ return appendForeignFields(
452
481
  {
453
482
  version: DOCUMENT_VERSION,
454
483
  title: doc.title,
455
- nodes: [...doc.nodes].map(normNode).sort(byId),
456
- interactions: [...doc.interactions].map(normInteraction).sort(byId),
457
- flows: [...doc.flows].map(normFlow).sort(byId),
458
- 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)
459
488
  },
460
489
  doc,
461
- DOCUMENT_FIELDS
490
+ DOCUMENT_FIELDS,
491
+ copy
462
492
  );
463
493
  }
464
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 * 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 * 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.1",
3
+ "version": "0.17.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": {