@graview/core 0.1.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.
Files changed (327) hide show
  1. package/LICENSE +96 -0
  2. package/README.md +35 -0
  3. package/dist/app.d.ts +294 -0
  4. package/dist/app.d.ts.map +1 -0
  5. package/dist/app.js +49 -0
  6. package/dist/app.js.map +1 -0
  7. package/dist/arrange.d.ts +185 -0
  8. package/dist/arrange.d.ts.map +1 -0
  9. package/dist/arrange.js +456 -0
  10. package/dist/arrange.js.map +1 -0
  11. package/dist/beginning.d.ts +65 -0
  12. package/dist/beginning.d.ts.map +1 -0
  13. package/dist/beginning.js +94 -0
  14. package/dist/beginning.js.map +1 -0
  15. package/dist/bind.d.ts +42 -0
  16. package/dist/bind.d.ts.map +1 -0
  17. package/dist/bind.js +26 -0
  18. package/dist/bind.js.map +1 -0
  19. package/dist/city.d.ts +93 -0
  20. package/dist/city.d.ts.map +1 -0
  21. package/dist/city.js +160 -0
  22. package/dist/city.js.map +1 -0
  23. package/dist/cli/check/arrangement.d.ts +13 -0
  24. package/dist/cli/check/arrangement.d.ts.map +1 -0
  25. package/dist/cli/check/arrangement.js +63 -0
  26. package/dist/cli/check/arrangement.js.map +1 -0
  27. package/dist/cli/check/beginnings.d.ts +16 -0
  28. package/dist/cli/check/beginnings.d.ts.map +1 -0
  29. package/dist/cli/check/beginnings.js +53 -0
  30. package/dist/cli/check/beginnings.js.map +1 -0
  31. package/dist/cli/check/brand.d.ts +17 -0
  32. package/dist/cli/check/brand.d.ts.map +1 -0
  33. package/dist/cli/check/brand.js +153 -0
  34. package/dist/cli/check/brand.js.map +1 -0
  35. package/dist/cli/check/city.d.ts +17 -0
  36. package/dist/cli/check/city.d.ts.map +1 -0
  37. package/dist/cli/check/city.js +58 -0
  38. package/dist/cli/check/city.js.map +1 -0
  39. package/dist/cli/check/context.d.ts +50 -0
  40. package/dist/cli/check/context.d.ts.map +1 -0
  41. package/dist/cli/check/context.js +37 -0
  42. package/dist/cli/check/context.js.map +1 -0
  43. package/dist/cli/check/fields.d.ts +16 -0
  44. package/dist/cli/check/fields.d.ts.map +1 -0
  45. package/dist/cli/check/fields.js +237 -0
  46. package/dist/cli/check/fields.js.map +1 -0
  47. package/dist/cli/check/index.d.ts +14 -0
  48. package/dist/cli/check/index.d.ts.map +1 -0
  49. package/dist/cli/check/index.js +14 -0
  50. package/dist/cli/check/index.js.map +1 -0
  51. package/dist/cli/check/intelligence.d.ts +17 -0
  52. package/dist/cli/check/intelligence.d.ts.map +1 -0
  53. package/dist/cli/check/intelligence.js +136 -0
  54. package/dist/cli/check/intelligence.js.map +1 -0
  55. package/dist/cli/check/lenses.d.ts +17 -0
  56. package/dist/cli/check/lenses.d.ts.map +1 -0
  57. package/dist/cli/check/lenses.js +239 -0
  58. package/dist/cli/check/lenses.js.map +1 -0
  59. package/dist/cli/check/migrations.d.ts +16 -0
  60. package/dist/cli/check/migrations.d.ts.map +1 -0
  61. package/dist/cli/check/migrations.js +43 -0
  62. package/dist/cli/check/migrations.js.map +1 -0
  63. package/dist/cli/check/modules.d.ts +16 -0
  64. package/dist/cli/check/modules.d.ts.map +1 -0
  65. package/dist/cli/check/modules.js +123 -0
  66. package/dist/cli/check/modules.js.map +1 -0
  67. package/dist/cli/check/policy.d.ts +16 -0
  68. package/dist/cli/check/policy.d.ts.map +1 -0
  69. package/dist/cli/check/policy.js +90 -0
  70. package/dist/cli/check/policy.js.map +1 -0
  71. package/dist/cli/check/relations.d.ts +29 -0
  72. package/dist/cli/check/relations.d.ts.map +1 -0
  73. package/dist/cli/check/relations.js +279 -0
  74. package/dist/cli/check/relations.js.map +1 -0
  75. package/dist/cli/check/routes.d.ts +16 -0
  76. package/dist/cli/check/routes.d.ts.map +1 -0
  77. package/dist/cli/check/routes.js +31 -0
  78. package/dist/cli/check/routes.js.map +1 -0
  79. package/dist/cli/check/settings.d.ts +16 -0
  80. package/dist/cli/check/settings.d.ts.map +1 -0
  81. package/dist/cli/check/settings.js +81 -0
  82. package/dist/cli/check/settings.js.map +1 -0
  83. package/dist/cli/check.d.ts +36 -0
  84. package/dist/cli/check.d.ts.map +1 -0
  85. package/dist/cli/check.js +76 -0
  86. package/dist/cli/check.js.map +1 -0
  87. package/dist/cli/create.d.ts +20 -0
  88. package/dist/cli/create.d.ts.map +1 -0
  89. package/dist/cli/create.js +251 -0
  90. package/dist/cli/create.js.map +1 -0
  91. package/dist/cli/describe.d.ts +35 -0
  92. package/dist/cli/describe.d.ts.map +1 -0
  93. package/dist/cli/describe.js +230 -0
  94. package/dist/cli/describe.js.map +1 -0
  95. package/dist/cli/docs.d.ts +11 -0
  96. package/dist/cli/docs.d.ts.map +1 -0
  97. package/dist/cli/docs.js +152 -0
  98. package/dist/cli/docs.js.map +1 -0
  99. package/dist/cli/index.d.ts +18 -0
  100. package/dist/cli/index.d.ts.map +1 -0
  101. package/dist/cli/index.js +281 -0
  102. package/dist/cli/index.js.map +1 -0
  103. package/dist/extend.d.ts +23 -0
  104. package/dist/extend.d.ts.map +1 -0
  105. package/dist/extend.js +53 -0
  106. package/dist/extend.js.map +1 -0
  107. package/dist/graph/diff.d.ts +31 -0
  108. package/dist/graph/diff.d.ts.map +1 -0
  109. package/dist/graph/diff.js +71 -0
  110. package/dist/graph/diff.js.map +1 -0
  111. package/dist/graph/graph.d.ts +69 -0
  112. package/dist/graph/graph.d.ts.map +1 -0
  113. package/dist/graph/graph.js +284 -0
  114. package/dist/graph/graph.js.map +1 -0
  115. package/dist/graph/primitives.d.ts +52 -0
  116. package/dist/graph/primitives.d.ts.map +1 -0
  117. package/dist/graph/primitives.js +62 -0
  118. package/dist/graph/primitives.js.map +1 -0
  119. package/dist/graph/tracked.d.ts +31 -0
  120. package/dist/graph/tracked.d.ts.map +1 -0
  121. package/dist/graph/tracked.js +69 -0
  122. package/dist/graph/tracked.js.map +1 -0
  123. package/dist/graph/types.d.ts +34 -0
  124. package/dist/graph/types.d.ts.map +1 -0
  125. package/dist/graph/types.js +0 -0
  126. package/dist/graph/types.js.map +1 -0
  127. package/dist/index.d.ts +100 -0
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +90 -0
  130. package/dist/index.js.map +1 -0
  131. package/dist/installation.d.ts +112 -0
  132. package/dist/installation.d.ts.map +1 -0
  133. package/dist/installation.js +193 -0
  134. package/dist/installation.js.map +1 -0
  135. package/dist/intelligence-bridge.d.ts +73 -0
  136. package/dist/intelligence-bridge.d.ts.map +1 -0
  137. package/dist/intelligence-bridge.js +31 -0
  138. package/dist/intelligence-bridge.js.map +1 -0
  139. package/dist/invariants/engine.d.ts +36 -0
  140. package/dist/invariants/engine.d.ts.map +1 -0
  141. package/dist/invariants/engine.js +88 -0
  142. package/dist/invariants/engine.js.map +1 -0
  143. package/dist/invariants/types.d.ts +75 -0
  144. package/dist/invariants/types.d.ts.map +1 -0
  145. package/dist/invariants/types.js +2 -0
  146. package/dist/invariants/types.js.map +1 -0
  147. package/dist/modules.d.ts +75 -0
  148. package/dist/modules.d.ts.map +1 -0
  149. package/dist/modules.js +87 -0
  150. package/dist/modules.js.map +1 -0
  151. package/dist/mutations/decidable.d.ts +26 -0
  152. package/dist/mutations/decidable.d.ts.map +1 -0
  153. package/dist/mutations/decidable.js +39 -0
  154. package/dist/mutations/decidable.js.map +1 -0
  155. package/dist/mutations/define-mutation.d.ts +32 -0
  156. package/dist/mutations/define-mutation.d.ts.map +1 -0
  157. package/dist/mutations/define-mutation.js +181 -0
  158. package/dist/mutations/define-mutation.js.map +1 -0
  159. package/dist/mutations/derive-edits.d.ts +75 -0
  160. package/dist/mutations/derive-edits.d.ts.map +1 -0
  161. package/dist/mutations/derive-edits.js +240 -0
  162. package/dist/mutations/derive-edits.js.map +1 -0
  163. package/dist/mutations/form.d.ts +63 -0
  164. package/dist/mutations/form.d.ts.map +1 -0
  165. package/dist/mutations/form.js +113 -0
  166. package/dist/mutations/form.js.map +1 -0
  167. package/dist/mutations/node-ref.d.ts +83 -0
  168. package/dist/mutations/node-ref.d.ts.map +1 -0
  169. package/dist/mutations/node-ref.js +113 -0
  170. package/dist/mutations/node-ref.js.map +1 -0
  171. package/dist/mutations/types.d.ts +136 -0
  172. package/dist/mutations/types.d.ts.map +1 -0
  173. package/dist/mutations/types.js +2 -0
  174. package/dist/mutations/types.js.map +1 -0
  175. package/dist/ops/log.d.ts +35 -0
  176. package/dist/ops/log.d.ts.map +1 -0
  177. package/dist/ops/log.js +103 -0
  178. package/dist/ops/log.js.map +1 -0
  179. package/dist/ops/types.d.ts +52 -0
  180. package/dist/ops/types.d.ts.map +1 -0
  181. package/dist/ops/types.js +2 -0
  182. package/dist/ops/types.js.map +1 -0
  183. package/dist/ops/undo.d.ts +33 -0
  184. package/dist/ops/undo.d.ts.map +1 -0
  185. package/dist/ops/undo.js +65 -0
  186. package/dist/ops/undo.js.map +1 -0
  187. package/dist/permissions/policy.d.ts +68 -0
  188. package/dist/permissions/policy.d.ts.map +1 -0
  189. package/dist/permissions/policy.js +191 -0
  190. package/dist/permissions/policy.js.map +1 -0
  191. package/dist/permissions/types.d.ts +78 -0
  192. package/dist/permissions/types.d.ts.map +1 -0
  193. package/dist/permissions/types.js +17 -0
  194. package/dist/permissions/types.js.map +1 -0
  195. package/dist/persistence/memory.d.ts +6 -0
  196. package/dist/persistence/memory.d.ts.map +1 -0
  197. package/dist/persistence/memory.js +31 -0
  198. package/dist/persistence/memory.js.map +1 -0
  199. package/dist/persistence/sqlite.d.ts +59 -0
  200. package/dist/persistence/sqlite.d.ts.map +1 -0
  201. package/dist/persistence/sqlite.js +131 -0
  202. package/dist/persistence/sqlite.js.map +1 -0
  203. package/dist/persistence/types.d.ts +22 -0
  204. package/dist/persistence/types.d.ts.map +1 -0
  205. package/dist/persistence/types.js +2 -0
  206. package/dist/persistence/types.js.map +1 -0
  207. package/dist/presence.d.ts +38 -0
  208. package/dist/presence.d.ts.map +1 -0
  209. package/dist/presence.js +50 -0
  210. package/dist/presence.js.map +1 -0
  211. package/dist/scaffold/domain.d.ts +8 -0
  212. package/dist/scaffold/domain.d.ts.map +1 -0
  213. package/dist/scaffold/domain.js +331 -0
  214. package/dist/scaffold/domain.js.map +1 -0
  215. package/dist/scaffold/index.d.ts +66 -0
  216. package/dist/scaffold/index.d.ts.map +1 -0
  217. package/dist/scaffold/index.js +142 -0
  218. package/dist/scaffold/index.js.map +1 -0
  219. package/dist/scaffold/lens.d.ts +31 -0
  220. package/dist/scaffold/lens.d.ts.map +1 -0
  221. package/dist/scaffold/lens.js +176 -0
  222. package/dist/scaffold/lens.js.map +1 -0
  223. package/dist/scaffold/names.d.ts +44 -0
  224. package/dist/scaffold/names.d.ts.map +1 -0
  225. package/dist/scaffold/names.js +69 -0
  226. package/dist/scaffold/names.js.map +1 -0
  227. package/dist/scaffold/project.d.ts +41 -0
  228. package/dist/scaffold/project.d.ts.map +1 -0
  229. package/dist/scaffold/project.js +604 -0
  230. package/dist/scaffold/project.js.map +1 -0
  231. package/dist/scaffold/ui.d.ts +15 -0
  232. package/dist/scaffold/ui.d.ts.map +1 -0
  233. package/dist/scaffold/ui.js +536 -0
  234. package/dist/scaffold/ui.js.map +1 -0
  235. package/dist/schema/define-node.d.ts +132 -0
  236. package/dist/schema/define-node.d.ts.map +1 -0
  237. package/dist/schema/define-node.js +254 -0
  238. package/dist/schema/define-node.js.map +1 -0
  239. package/dist/schema/figures.d.ts +42 -0
  240. package/dist/schema/figures.d.ts.map +1 -0
  241. package/dist/schema/figures.js +220 -0
  242. package/dist/schema/figures.js.map +1 -0
  243. package/dist/schema/json-schema.d.ts +39 -0
  244. package/dist/schema/json-schema.d.ts.map +1 -0
  245. package/dist/schema/json-schema.js +74 -0
  246. package/dist/schema/json-schema.js.map +1 -0
  247. package/dist/schema/schema.d.ts +43 -0
  248. package/dist/schema/schema.d.ts.map +1 -0
  249. package/dist/schema/schema.js +102 -0
  250. package/dist/schema/schema.js.map +1 -0
  251. package/dist/schema/types.d.ts +201 -0
  252. package/dist/schema/types.d.ts.map +1 -0
  253. package/dist/schema/types.js +2 -0
  254. package/dist/schema/types.js.map +1 -0
  255. package/dist/search.d.ts +215 -0
  256. package/dist/search.d.ts.map +1 -0
  257. package/dist/search.js +449 -0
  258. package/dist/search.js.map +1 -0
  259. package/dist/settings.d.ts +30 -0
  260. package/dist/settings.d.ts.map +1 -0
  261. package/dist/settings.js +74 -0
  262. package/dist/settings.js.map +1 -0
  263. package/dist/store.d.ts +284 -0
  264. package/dist/store.d.ts.map +1 -0
  265. package/dist/store.js +660 -0
  266. package/dist/store.js.map +1 -0
  267. package/dist/studio-door.d.ts +187 -0
  268. package/dist/studio-door.d.ts.map +1 -0
  269. package/dist/studio-door.js +20 -0
  270. package/dist/studio-door.js.map +1 -0
  271. package/dist/sync/conflict.d.ts +37 -0
  272. package/dist/sync/conflict.d.ts.map +1 -0
  273. package/dist/sync/conflict.js +56 -0
  274. package/dist/sync/conflict.js.map +1 -0
  275. package/dist/sync/engine.d.ts +118 -0
  276. package/dist/sync/engine.d.ts.map +1 -0
  277. package/dist/sync/engine.js +341 -0
  278. package/dist/sync/engine.js.map +1 -0
  279. package/dist/sync/google-calendar.d.ts +54 -0
  280. package/dist/sync/google-calendar.d.ts.map +1 -0
  281. package/dist/sync/google-calendar.js +167 -0
  282. package/dist/sync/google-calendar.js.map +1 -0
  283. package/dist/sync/types.d.ts +125 -0
  284. package/dist/sync/types.d.ts.map +1 -0
  285. package/dist/sync/types.js +6 -0
  286. package/dist/sync/types.js.map +1 -0
  287. package/dist/temporal/effectivity.d.ts +75 -0
  288. package/dist/temporal/effectivity.d.ts.map +1 -0
  289. package/dist/temporal/effectivity.js +89 -0
  290. package/dist/temporal/effectivity.js.map +1 -0
  291. package/dist/testing.d.ts +63 -0
  292. package/dist/testing.d.ts.map +1 -0
  293. package/dist/testing.js +194 -0
  294. package/dist/testing.js.map +1 -0
  295. package/dist/theme/contrast.d.ts +47 -0
  296. package/dist/theme/contrast.d.ts.map +1 -0
  297. package/dist/theme/contrast.js +172 -0
  298. package/dist/theme/contrast.js.map +1 -0
  299. package/dist/theme/derive.d.ts +81 -0
  300. package/dist/theme/derive.d.ts.map +1 -0
  301. package/dist/theme/derive.js +171 -0
  302. package/dist/theme/derive.js.map +1 -0
  303. package/dist/theme/kit.d.ts +106 -0
  304. package/dist/theme/kit.d.ts.map +1 -0
  305. package/dist/theme/kit.js +84 -0
  306. package/dist/theme/kit.js.map +1 -0
  307. package/dist/theme/palettes.d.ts +32 -0
  308. package/dist/theme/palettes.d.ts.map +1 -0
  309. package/dist/theme/palettes.js +96 -0
  310. package/dist/theme/palettes.js.map +1 -0
  311. package/dist/theme/types.d.ts +131 -0
  312. package/dist/theme/types.d.ts.map +1 -0
  313. package/dist/theme/types.js +23 -0
  314. package/dist/theme/types.js.map +1 -0
  315. package/dist/views/types.d.ts +89 -0
  316. package/dist/views/types.d.ts.map +1 -0
  317. package/dist/views/types.js +88 -0
  318. package/dist/views/types.js.map +1 -0
  319. package/dist/watched.d.ts +33 -0
  320. package/dist/watched.d.ts.map +1 -0
  321. package/dist/watched.js +50 -0
  322. package/dist/watched.js.map +1 -0
  323. package/dist/who.d.ts +26 -0
  324. package/dist/who.d.ts.map +1 -0
  325. package/dist/who.js +20 -0
  326. package/dist/who.js.map +1 -0
  327. package/package.json +77 -0
@@ -0,0 +1,181 @@
1
+ import { GraphError } from "../graph/graph.js";
2
+ import { TrackedReader } from "../graph/tracked.js";
3
+ import { edgeId } from "../graph/types.js";
4
+ export function defineMutation(name, spec) {
5
+ return { ...spec, name };
6
+ }
7
+ /** Whether an act takes the framework's `id` argument: it creates, and has no `id` of its own. */
8
+ export function takesAnId(definition) {
9
+ if (!definition.creates?.length)
10
+ return false;
11
+ const shape = definition.input.shape;
12
+ return shape === undefined || !("id" in shape);
13
+ }
14
+ function requestedId(rawArgs) {
15
+ if (typeof rawArgs !== "object" || rawArgs === null)
16
+ return undefined;
17
+ const id = rawArgs["id"];
18
+ if (id === undefined)
19
+ return undefined;
20
+ if (typeof id !== "string" || id.trim().length === 0) {
21
+ throw new GraphError("An id must be a non-empty string", `Got ${JSON.stringify(id)}.`);
22
+ }
23
+ return id;
24
+ }
25
+ function withoutId(args) {
26
+ const { id: _id, ...rest } = args;
27
+ return rest;
28
+ }
29
+ /**
30
+ * An id from a name: the name's own letters, folded and hyphenated.
31
+ *
32
+ * It kept ASCII and dropped everything else, so "Zoë Lamarré" became
33
+ * `artist:zo-lamarr` — an address that is neither her name nor anybody's —
34
+ * and a name in any script without Latin letters became `item`. Accents are
35
+ * folded the way search folds them (`zoe-lamarre`, the id a person would
36
+ * guess), and a letter with no Latin form is kept as the letter it is.
37
+ */
38
+ export function slug(label) {
39
+ return (label
40
+ .normalize("NFKD")
41
+ .replace(/\p{M}/gu, "")
42
+ .toLowerCase()
43
+ .replace(/[^\p{L}\p{N}]+/gu, "-")
44
+ .replace(/^-+|-+$/g, "") || "item");
45
+ }
46
+ /**
47
+ * Runs a mutation against the graph WITHOUT applying it, returning the
48
+ * primitives it would emit plus the causal read set. Applying is the op
49
+ * log's job — keeping the two apart is what makes preview-as-diff free.
50
+ */
51
+ export function compileMutation(graph, definition, rawArgs) {
52
+ /*
53
+ * THE ID A CALLER BROUGHT. An act that creates a kind takes an optional
54
+ * `id` the framework adds beside its own arguments (see `takesAnId`):
55
+ * lifted here, before the declaration's own schema parses the rest, so a
56
+ * strict input is not asked about an argument it never declared. It goes
57
+ * to the first node `freshId` mints, and an id already in the graph is a
58
+ * refusal — a seed being synced, or an agent that will name this node in
59
+ * its next call, needs exactly the id it asked for or an honest no.
60
+ */
61
+ const requested = takesAnId(definition) ? requestedId(rawArgs) : undefined;
62
+ const parsed = definition.input.safeParse(requested === undefined ? rawArgs : withoutId(rawArgs));
63
+ if (!parsed.success) {
64
+ throw new GraphError(`Invalid arguments for mutation "${definition.name}"`, parsed.error.issues
65
+ .map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`)
66
+ .join("; "));
67
+ }
68
+ const args = parsed.data;
69
+ const reader = new TrackedReader(graph);
70
+ const primitives = [];
71
+ const minted = new Set();
72
+ const context = {
73
+ graph: reader,
74
+ schema: graph.schema,
75
+ emit(primitive) {
76
+ primitives.push(primitive);
77
+ },
78
+ addNode(node) {
79
+ primitives.push({ op: "add-node", node });
80
+ },
81
+ removeNode(id) {
82
+ const node = reader.getNode(id);
83
+ if (!node)
84
+ throw new GraphError(`Cannot remove missing node "${id}"`);
85
+ const touching = new Map();
86
+ for (const edge of graph.outEdges(id))
87
+ touching.set(edgeId(edge), edge);
88
+ for (const edge of graph.inEdges(id))
89
+ touching.set(edgeId(edge), edge);
90
+ for (const edge of touching.values()) {
91
+ reader.getNode(edge.from);
92
+ reader.getNode(edge.to);
93
+ primitives.push({ op: "remove-edge", edge });
94
+ }
95
+ primitives.push({ op: "remove-node", node });
96
+ },
97
+ patchNode(id, fields) {
98
+ const node = reader.getNode(id);
99
+ if (!node)
100
+ throw new GraphError(`Cannot patch missing node "${id}"`);
101
+ const before = {};
102
+ const after = {};
103
+ for (const [key, value] of Object.entries(fields)) {
104
+ const current = node[key];
105
+ if (JSON.stringify(current) === JSON.stringify(value))
106
+ continue;
107
+ before[key] = current;
108
+ after[key] = value;
109
+ }
110
+ if (Object.keys(after).length === 0)
111
+ return;
112
+ primitives.push({ op: "patch-node", id, before, after });
113
+ },
114
+ addEdge(edge) {
115
+ primitives.push({ op: "add-edge", edge });
116
+ },
117
+ removeEdge(edge) {
118
+ primitives.push({ op: "remove-edge", edge });
119
+ },
120
+ setSingleSource(kind, to, from) {
121
+ for (const edge of graph.inEdges(to, kind)) {
122
+ reader.getNode(edge.from);
123
+ if (edge.from === from)
124
+ continue;
125
+ primitives.push({ op: "remove-edge", edge });
126
+ }
127
+ if (!graph.inEdges(to, kind).some((e) => e.from === from)) {
128
+ primitives.push({ op: "add-edge", edge: { kind, from, to } });
129
+ }
130
+ },
131
+ freshId(label, prefix) {
132
+ if (requested !== undefined && !minted.has(requested)) {
133
+ if (reader.has(requested)) {
134
+ throw new GraphError(`Id "${requested}" is already taken`, `"${definition.name}" was asked to make a node with that id, and the graph has one. Pick another, or leave id out and let the act mint one.`);
135
+ }
136
+ minted.add(requested);
137
+ return requested;
138
+ }
139
+ const base = prefix ? `${prefix}:${slug(label)}` : slug(label);
140
+ if (!reader.has(base) && !minted.has(base)) {
141
+ minted.add(base);
142
+ return base;
143
+ }
144
+ let n = 2;
145
+ while (reader.has(`${base}-${n}`) || minted.has(`${base}-${n}`))
146
+ n++;
147
+ const id = `${base}-${n}`;
148
+ minted.add(id);
149
+ return id;
150
+ },
151
+ };
152
+ definition.apply(context, args);
153
+ const writes = new Set();
154
+ for (const primitive of primitives) {
155
+ switch (primitive.op) {
156
+ case "add-node":
157
+ case "remove-node":
158
+ writes.add(primitive.node.id);
159
+ break;
160
+ case "patch-node":
161
+ writes.add(primitive.id);
162
+ break;
163
+ case "add-edge":
164
+ case "remove-edge":
165
+ writes.add(primitive.edge.from);
166
+ writes.add(primitive.edge.to);
167
+ break;
168
+ }
169
+ }
170
+ const intent = definition.describe?.(args, reader) ??
171
+ `${definition.name}(${Object.entries(args)
172
+ .map(([k, v]) => `${k}=${JSON.stringify(v)}`)
173
+ .join(", ")})`;
174
+ return {
175
+ primitives,
176
+ reads: reader.reads(),
177
+ writes: [...writes],
178
+ intent,
179
+ };
180
+ }
181
+ //# sourceMappingURL=define-mutation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-mutation.js","sourceRoot":"","sources":["../../src/mutations/define-mutation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ import type { AnySchema } from "../schema/schema.js";
2
+ import type { AnyNodeDefinition } from "../schema/types.js";
3
+ import type { AnyMutationDefinition } from "./types.js";
4
+ /**
5
+ * A FIELD YOU COULD SET AT CREATION, YOU CAN CHANGE.
6
+ *
7
+ * Every app here had the same hole: a drill's minimum players asked for
8
+ * when the drill was made, shown on its card, and then frozen — no
9
+ * mutation took it, so the in-place edit honestly said "read-only" and
10
+ * there was nothing to reach for. The culture is right that every change
11
+ * is a named act, so the fix is not an anonymous `update`: it is a DERIVED,
12
+ * titled edit act per kind, covering exactly the settable fields nothing
13
+ * else writes, flowing through the policy like any named mutation. Opting
14
+ * out is a declaration (`fixed`, with the reason); and the checker warns
15
+ * when a field is still out of everyone's reach.
16
+ */
17
+ /** The fields of a kind a person could change: declared, and not fixed. */
18
+ export declare function settableFields(definition: AnyNodeDefinition): readonly string[];
19
+ /** The kinds a mutation's subject accepts, resolved against the schema. */
20
+ export declare function subjectKindsOf<S extends AnySchema>(schema: S, mutation: AnyMutationDefinition<S>): readonly string[];
21
+ /**
22
+ * Which fields a mutation writes on a given subject kind: its declaration
23
+ * when it has one, the name-match guess when it does not.
24
+ */
25
+ export declare function fieldsWrittenBy<S extends AnySchema>(mutation: AnyMutationDefinition<S>, definition: AnyNodeDefinition): readonly string[];
26
+ /** kind → field → the declared mutations that write it. */
27
+ export declare function fieldWriters<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[]): ReadonlyMap<string, ReadonlyMap<string, readonly string[]>>;
28
+ /** The settable fields of a kind that no declared mutation writes. */
29
+ export declare function unwrittenFields<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[], kind: string): readonly string[];
30
+ /** The name the derived edit act for a kind carries. */
31
+ export declare const editMutationName: (kind: string) => string;
32
+ /**
33
+ * The declared acts a derived edit resolves its PERMISSION through: those
34
+ * that already write a field of the kind, and those that create it. Who may
35
+ * edit a drill is whoever the policy already lets change or make a drill —
36
+ * there is no second list.
37
+ */
38
+ export declare function editVia<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[], kind: string): readonly string[];
39
+ /**
40
+ * One edit act per kind that has something nobody else writes.
41
+ *
42
+ * Its input is the subject plus each uncovered field as an optional
43
+ * argument carrying the kind's OWN field schema, so validation is the
44
+ * declaration's; `writes` names those fields, so `editableFields` needs no
45
+ * guess. A kind whose every settable field is already written derives
46
+ * nothing, and an app that declares its own `edit-<kind>` keeps it.
47
+ */
48
+ export declare function deriveEditMutations<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[]): AnyMutationDefinition<S>[];
49
+ /** The name the derived remove act for a kind carries. */
50
+ export declare const removeMutationName: (kind: string) => string;
51
+ /**
52
+ * The declared acts a derived remove resolves its PERMISSION through: the
53
+ * ones that bring the kind into being. Who may make a plot may take one
54
+ * out — narrower than the edit's reading on purpose, because a role that
55
+ * may re-time a drill has not been trusted with losing it.
56
+ */
57
+ export declare function removeVia<S extends AnySchema>(mutations: readonly AnyMutationDefinition<S>[], kind: string): readonly string[];
58
+ /** The declared acts a derived act rides, whichever act it is. */
59
+ export declare function derivedVia<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[], mutation: AnyMutationDefinition<S>): readonly string[] | undefined;
60
+ /**
61
+ * WHAT WAS MADE CAN BE UNMADE.
62
+ *
63
+ * Every app had a way to add a task and, mostly, no way to lose one — so an
64
+ * agent redesigning a board, or a seed being brought in step with a live
65
+ * store, had nothing to call and rewrote the seed instead. The culture is
66
+ * right that every change is a named act, so the fix is a DERIVED, titled
67
+ * remove act per kind: destructive, so it ranks last and is marked; taking
68
+ * the node's edges with it, as `removeNode` does; logged and undoable like
69
+ * everything else; and permitted through the acts that create the kind.
70
+ * An app that declares its own `remove-<kind>` keeps it.
71
+ */
72
+ export declare function deriveRemoveMutations<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[]): AnyMutationDefinition<S>[];
73
+ /** Every act the framework derives for a declaration: the edits, then the removes. */
74
+ export declare function deriveMutations<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[]): AnyMutationDefinition<S>[];
75
+ //# sourceMappingURL=derive-edits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derive-edits.d.ts","sourceRoot":"","sources":["../../src/mutations/derive-edits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,240 @@
1
+ import { z } from "zod";
2
+ import { labelOf } from "../schema/define-node.js";
3
+ import { humaniseField, nounOf } from "../schema/define-node.js";
4
+ import { nodeRef, nodeRefArgs } from "./node-ref.js";
5
+ /**
6
+ * A FIELD YOU COULD SET AT CREATION, YOU CAN CHANGE.
7
+ *
8
+ * Every app here had the same hole: a drill's minimum players asked for
9
+ * when the drill was made, shown on its card, and then frozen — no
10
+ * mutation took it, so the in-place edit honestly said "read-only" and
11
+ * there was nothing to reach for. The culture is right that every change
12
+ * is a named act, so the fix is not an anonymous `update`: it is a DERIVED,
13
+ * titled edit act per kind, covering exactly the settable fields nothing
14
+ * else writes, flowing through the policy like any named mutation. Opting
15
+ * out is a declaration (`fixed`, with the reason); and the checker warns
16
+ * when a field is still out of everyone's reach.
17
+ */
18
+ /** The fields of a kind a person could change: declared, and not fixed. */
19
+ export function settableFields(definition) {
20
+ const shape = definition.fields.shape;
21
+ return Object.keys(shape).filter((field) => !(field in (definition.fixed ?? {})));
22
+ }
23
+ /** The kinds a mutation's subject accepts, resolved against the schema. */
24
+ export function subjectKindsOf(schema, mutation) {
25
+ const subject = mutation.subject;
26
+ if (!subject)
27
+ return [];
28
+ return subject.kinds === "*"
29
+ ? schema.kinds
30
+ : subject.kinds;
31
+ }
32
+ /**
33
+ * Which fields a mutation writes on a given subject kind: its declaration
34
+ * when it has one, the name-match guess when it does not.
35
+ */
36
+ export function fieldsWrittenBy(mutation, definition) {
37
+ const subject = mutation.subject;
38
+ if (!subject)
39
+ return [];
40
+ const declared = new Set(Object.keys(definition.fields.shape));
41
+ if (mutation.writes)
42
+ return mutation.writes.filter((field) => declared.has(field));
43
+ const shape = mutation.input.shape ?? {};
44
+ const refs = new Set(nodeRefArgs(mutation.input).map((ref) => ref.name));
45
+ return Object.keys(shape).filter((name) => name !== subject.arg && declared.has(name) && !refs.has(name));
46
+ }
47
+ /** kind → field → the declared mutations that write it. */
48
+ export function fieldWriters(schema, mutations) {
49
+ const writers = new Map();
50
+ for (const mutation of mutations) {
51
+ for (const kind of subjectKindsOf(schema, mutation)) {
52
+ const definition = schema.tryDefinition(kind);
53
+ if (!definition)
54
+ continue;
55
+ for (const field of fieldsWrittenBy(mutation, definition)) {
56
+ const byField = writers.get(kind) ?? new Map();
57
+ byField.set(field, [...(byField.get(field) ?? []), mutation.name]);
58
+ writers.set(kind, byField);
59
+ }
60
+ }
61
+ }
62
+ return writers;
63
+ }
64
+ /** The settable fields of a kind that no declared mutation writes. */
65
+ export function unwrittenFields(schema, mutations, kind) {
66
+ const definition = schema.tryDefinition(kind);
67
+ if (!definition)
68
+ return [];
69
+ const written = fieldWriters(schema, mutations).get(kind);
70
+ return settableFields(definition).filter((field) => !written?.has(field));
71
+ }
72
+ /** The name the derived edit act for a kind carries. */
73
+ export const editMutationName = (kind) => `edit-${kind}`;
74
+ /**
75
+ * The declared acts a derived edit resolves its PERMISSION through: those
76
+ * that already write a field of the kind, and those that create it. Who may
77
+ * edit a drill is whoever the policy already lets change or make a drill —
78
+ * there is no second list.
79
+ */
80
+ export function editVia(schema, mutations, kind) {
81
+ const definition = schema.tryDefinition(kind);
82
+ if (!definition)
83
+ return [];
84
+ const via = new Set();
85
+ for (const mutation of mutations) {
86
+ if (mutation.derived)
87
+ continue;
88
+ if ((mutation.creates ?? []).includes(kind))
89
+ via.add(mutation.name);
90
+ if (subjectKindsOf(schema, mutation).includes(kind) &&
91
+ fieldsWrittenBy(mutation, definition).length > 0) {
92
+ via.add(mutation.name);
93
+ }
94
+ }
95
+ return [...via];
96
+ }
97
+ /**
98
+ * One edit act per kind that has something nobody else writes.
99
+ *
100
+ * Its input is the subject plus each uncovered field as an optional
101
+ * argument carrying the kind's OWN field schema, so validation is the
102
+ * declaration's; `writes` names those fields, so `editableFields` needs no
103
+ * guess. A kind whose every settable field is already written derives
104
+ * nothing, and an app that declares its own `edit-<kind>` keeps it.
105
+ */
106
+ export function deriveEditMutations(schema, mutations) {
107
+ const taken = new Set(mutations.map((mutation) => mutation.name));
108
+ const derived = [];
109
+ for (const definition of schema.definitions) {
110
+ const kind = definition.kind;
111
+ const name = editMutationName(kind);
112
+ if (taken.has(name))
113
+ continue;
114
+ const fields = unwrittenFields(schema, mutations, kind);
115
+ if (fields.length === 0)
116
+ continue;
117
+ const shape = definition.fields.shape;
118
+ const noun = nounOf(definition, kind);
119
+ const said = fields.map((field) => humaniseField(field).toLowerCase());
120
+ derived.push({
121
+ name,
122
+ derived: { kind, act: "edit" },
123
+ title: `Change the ${noun}`,
124
+ description: `Change what was set when this ${noun} was made: ${said.join(", ")}.`,
125
+ subject: { kinds: [kind], arg: "id" },
126
+ writes: fields,
127
+ input: z.object({
128
+ id: nodeRef([kind]),
129
+ ...Object.fromEntries(fields.map((field) => [field, shape[field].optional()])),
130
+ }),
131
+ describe: (args, graph) => {
132
+ const node = graph.getNode(args.id);
133
+ const label = node ? labelOf(definition, node) : args.id;
134
+ /*
135
+ * THE CHANGE AS THE RECORD READS IT. The log said "price → 49900"
136
+ * and "condition → \"cpo\"" beside a card that says "Price $49,900"
137
+ * and "Certified pre-owned": the declaration's own labels and
138
+ * formats are the words, and the raw value only where there is none.
139
+ */
140
+ const display = definition.display;
141
+ const quietly = (label) => (label === label.toUpperCase() ? label : label.charAt(0).toLowerCase() + label.slice(1));
142
+ const changes = fields
143
+ .filter((field) => args[field] !== undefined)
144
+ .map((field) => {
145
+ const value = args[field];
146
+ const format = display?.format?.[field];
147
+ let said;
148
+ try {
149
+ said = format ? String(format(value)) : JSON.stringify(value);
150
+ }
151
+ catch {
152
+ said = JSON.stringify(value);
153
+ }
154
+ return `${quietly(display?.labels?.[field] ?? humaniseField(field))} → ${said}`;
155
+ });
156
+ return `Change ${label}: ${changes.join(", ") || "nothing"}`;
157
+ },
158
+ apply(ctx, args) {
159
+ const patch = {};
160
+ for (const field of fields) {
161
+ const value = args[field];
162
+ if (value !== undefined)
163
+ patch[field] = value;
164
+ }
165
+ if (Object.keys(patch).length === 0) {
166
+ throw new Error(`Nothing to change — give at least one of ${said.join(", ")} a value.`);
167
+ }
168
+ ctx.patchNode(args.id, patch);
169
+ },
170
+ });
171
+ }
172
+ return derived;
173
+ }
174
+ /** The name the derived remove act for a kind carries. */
175
+ export const removeMutationName = (kind) => `remove-${kind}`;
176
+ /**
177
+ * The declared acts a derived remove resolves its PERMISSION through: the
178
+ * ones that bring the kind into being. Who may make a plot may take one
179
+ * out — narrower than the edit's reading on purpose, because a role that
180
+ * may re-time a drill has not been trusted with losing it.
181
+ */
182
+ export function removeVia(mutations, kind) {
183
+ return mutations
184
+ .filter((mutation) => !mutation.derived && (mutation.creates ?? []).includes(kind))
185
+ .map((mutation) => mutation.name);
186
+ }
187
+ /** The declared acts a derived act rides, whichever act it is. */
188
+ export function derivedVia(schema, mutations, mutation) {
189
+ if (!mutation.derived)
190
+ return undefined;
191
+ return mutation.derived.act === "edit"
192
+ ? editVia(schema, mutations, mutation.derived.kind)
193
+ : removeVia(mutations, mutation.derived.kind);
194
+ }
195
+ /**
196
+ * WHAT WAS MADE CAN BE UNMADE.
197
+ *
198
+ * Every app had a way to add a task and, mostly, no way to lose one — so an
199
+ * agent redesigning a board, or a seed being brought in step with a live
200
+ * store, had nothing to call and rewrote the seed instead. The culture is
201
+ * right that every change is a named act, so the fix is a DERIVED, titled
202
+ * remove act per kind: destructive, so it ranks last and is marked; taking
203
+ * the node's edges with it, as `removeNode` does; logged and undoable like
204
+ * everything else; and permitted through the acts that create the kind.
205
+ * An app that declares its own `remove-<kind>` keeps it.
206
+ */
207
+ export function deriveRemoveMutations(schema, mutations) {
208
+ const taken = new Set(mutations.map((mutation) => mutation.name));
209
+ const derived = [];
210
+ for (const definition of schema.definitions) {
211
+ const kind = definition.kind;
212
+ const name = removeMutationName(kind);
213
+ if (taken.has(name))
214
+ continue;
215
+ const noun = nounOf(definition, kind);
216
+ derived.push({
217
+ name,
218
+ derived: { kind, act: "remove" },
219
+ title: `Remove the ${noun}`,
220
+ description: `Take this ${noun} out of the graph, with every tie it has. Undo puts it back.`,
221
+ subject: { kinds: [kind], arg: "id" },
222
+ destructive: true,
223
+ input: z.object({ id: nodeRef([kind]) }),
224
+ describe: (args, graph) => {
225
+ const id = args.id;
226
+ const node = graph.getNode(id);
227
+ return `Remove ${node ? labelOf(definition, node) : id}`;
228
+ },
229
+ apply(ctx, args) {
230
+ ctx.removeNode(args.id);
231
+ },
232
+ });
233
+ }
234
+ return derived;
235
+ }
236
+ /** Every act the framework derives for a declaration: the edits, then the removes. */
237
+ export function deriveMutations(schema, mutations) {
238
+ return [...deriveEditMutations(schema, mutations), ...deriveRemoveMutations(schema, mutations)];
239
+ }
240
+ //# sourceMappingURL=derive-edits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derive-edits.js","sourceRoot":"","sources":["../../src/mutations/derive-edits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import type { z } from "zod";
2
+ /**
3
+ * A FORM, derived from a mutation's own input declaration.
4
+ *
5
+ * `argShape` answers "what sort of answer does one scalar argument want",
6
+ * which is enough for a prompt in the actions strip. A page is mostly forms,
7
+ * and a form needs the whole tree: a structured object is a fieldset, a
8
+ * discriminated union is a type picker followed by that type's fields, an
9
+ * array is a repeatable row. Until this existed, any mutation with a
10
+ * structured argument was honestly un-askable — the strip withheld it — and
11
+ * a routed page cannot withhold "New agreement": it has to render.
12
+ *
13
+ * Everything here is PLAIN DATA. A renderer (a page, the strip, an agent
14
+ * explaining itself) walks the tree; nothing downstream touches zod.
15
+ */
16
+ export type FormField = ScalarField | {
17
+ readonly control: "node";
18
+ readonly name: string;
19
+ readonly optional: boolean;
20
+ readonly kinds: readonly string[];
21
+ } | {
22
+ readonly control: "group";
23
+ readonly name: string;
24
+ readonly optional: boolean;
25
+ readonly fields: readonly FormField[];
26
+ } | {
27
+ readonly control: "variant";
28
+ readonly name: string;
29
+ readonly optional: boolean;
30
+ /** The discriminating literal field shared by every option. */
31
+ readonly tag: string;
32
+ readonly options: readonly {
33
+ readonly value: string;
34
+ /** The option's remaining fields, the tag excluded. */
35
+ readonly fields: readonly FormField[];
36
+ }[];
37
+ } | {
38
+ readonly control: "list";
39
+ readonly name: string;
40
+ readonly optional: boolean;
41
+ readonly item: FormField;
42
+ } | {
43
+ readonly control: "opaque";
44
+ readonly name: string;
45
+ readonly optional: boolean;
46
+ };
47
+ export interface ScalarField {
48
+ readonly control: "text" | "date" | "number" | "choice" | "boolean";
49
+ readonly name: string;
50
+ readonly optional: boolean;
51
+ /** A date with a time of day in it (`YYYY-MM-DDTHH:MM`): asked for with a date AND a time. */
52
+ readonly time?: true;
53
+ readonly options?: readonly string[];
54
+ readonly min?: number;
55
+ readonly max?: number;
56
+ }
57
+ /** Describes one argument as a form control tree. */
58
+ export declare function formField(name: string, schema: unknown): FormField;
59
+ /** The whole form for a mutation input object, one field per argument. */
60
+ export declare function formFields(input: z.ZodType | unknown): readonly FormField[];
61
+ /** True when every control in the tree is renderable — nothing opaque. */
62
+ export declare function formComplete(fields: readonly FormField[]): boolean;
63
+ //# sourceMappingURL=form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/mutations/form.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAG7B;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,SAAS,GACjB,WAAW,GACX;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAClH;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAA;CAAE,GACvH;IACE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS;QACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,uDAAuD;QACvD,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;KACvC,EAAE,CAAC;CACL,GACD;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GACzG;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,8FAA8F;IAC9F,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AA6BD,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,SAAS,CA+ElE;AAED,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,GAAG,OAAO,GAAG,SAAS,SAAS,EAAE,CAI3E;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,OAAO,CAelE"}