@issuegraph/store 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 (47) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +239 -0
  3. package/dist/adapters/memory.d.ts +30 -0
  4. package/dist/adapters/memory.d.ts.map +1 -0
  5. package/dist/adapters/memory.js +81 -0
  6. package/dist/adapters/memory.js.map +1 -0
  7. package/dist/adapters/scripted.d.ts +67 -0
  8. package/dist/adapters/scripted.d.ts.map +1 -0
  9. package/dist/adapters/scripted.js +89 -0
  10. package/dist/adapters/scripted.js.map +1 -0
  11. package/dist/change.d.ts +75 -0
  12. package/dist/change.d.ts.map +1 -0
  13. package/dist/change.js +79 -0
  14. package/dist/change.js.map +1 -0
  15. package/dist/equality.d.ts +27 -0
  16. package/dist/equality.d.ts.map +1 -0
  17. package/dist/equality.js +60 -0
  18. package/dist/equality.js.map +1 -0
  19. package/dist/index.d.ts +22 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +21 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/model.d.ts +105 -0
  24. package/dist/model.d.ts.map +1 -0
  25. package/dist/model.js +64 -0
  26. package/dist/model.js.map +1 -0
  27. package/dist/mutation.d.ts +83 -0
  28. package/dist/mutation.d.ts.map +1 -0
  29. package/dist/mutation.js +58 -0
  30. package/dist/mutation.js.map +1 -0
  31. package/dist/source.d.ts +139 -0
  32. package/dist/source.d.ts.map +1 -0
  33. package/dist/source.js +17 -0
  34. package/dist/source.js.map +1 -0
  35. package/dist/store.d.ts +120 -0
  36. package/dist/store.d.ts.map +1 -0
  37. package/dist/store.js +529 -0
  38. package/dist/store.js.map +1 -0
  39. package/dist/validity.d.ts +44 -0
  40. package/dist/validity.d.ts.map +1 -0
  41. package/dist/validity.js +125 -0
  42. package/dist/validity.js.map +1 -0
  43. package/dist/write.d.ts +79 -0
  44. package/dist/write.d.ts.map +1 -0
  45. package/dist/write.js +84 -0
  46. package/dist/write.js.map +1 -0
  47. package/package.json +56 -0
package/dist/store.js ADDED
@@ -0,0 +1,529 @@
1
+ /**
2
+ * The store: the one stateful module, and the only place IO happens.
3
+ *
4
+ * Everything it decides is decided by the pure modules beside it — validity,
5
+ * the write ledger and projection, the order diff. What lives here is the state
6
+ * itself, the calls into the injected data source, and the notification.
7
+ *
8
+ * **The rule the structure exists to enforce:** the selection order is derived
9
+ * from `landed` and from nothing else. `projected` — the landed document plus
10
+ * every unsettled edit — is built in one place and is not in scope where the
11
+ * deriver is called, so an optimistic edge cannot reach the order by anyone
12
+ * forgetting a filter.
13
+ */
14
+ import { sameEdgeSet, } from "./model.js";
15
+ import { diffOrder } from "./change.js";
16
+ import { sameValue } from "./equality.js";
17
+ import { anyPending, project } from "./write.js";
18
+ import { nextDocument, structuralRefusal } from "./validity.js";
19
+ // Frozen because every store starts on this one object, and a shared mutable
20
+ // default is a cross-instance leak waiting for the first caller who sorts in
21
+ // place.
22
+ const EMPTY_DOCUMENT = Object.freeze({
23
+ issues: Object.freeze([]),
24
+ edges: Object.freeze([]),
25
+ });
26
+ /**
27
+ * Take ownership of a list the store is about to publish: copy it, then freeze.
28
+ *
29
+ * The arrays a snapshot hands out ARE the store's state — `landed` and `issues`
30
+ * arrive from the adapter, `order.rows` from the deriver — and `Object.freeze`
31
+ * on the snapshot object protects none of them. A consumer calling `.sort()` on
32
+ * one (the common slip; `[...list].sort()` is the careful form) would reorder
33
+ * store state with no dispatch, no re-derivation and no notification, and the
34
+ * next order would derive from a document nobody wrote.
35
+ *
36
+ * COPIED BEFORE FREEZING, not frozen in place, because these arrive from the
37
+ * host: freezing an adapter's own array would freeze it out of its own storage
38
+ * for handing one over.
39
+ *
40
+ * THE CONTAINERS ONLY. The elements stay as the host made them — the store owns
41
+ * which edges and rows it holds, the host owns what each one is — because
42
+ * freezing those would reach into objects an adapter or a deriver may still be
43
+ * using. `readonly` in the types is what discourages touching them; nothing at
44
+ * runtime can promise it without taking objects that are not ours.
45
+ */
46
+ function own(list) {
47
+ return Object.freeze([...list]);
48
+ }
49
+ /** A host-supplied document the store is taking on: its containers become ours. */
50
+ function ownDocument(document) {
51
+ return Object.freeze({ issues: own(document.issues), edges: own(document.edges) });
52
+ }
53
+ /**
54
+ * Rows from the injected deriver, with their nested container taken on too.
55
+ *
56
+ * `holdReasons` is the deriver's array, so it is copied for the same reason the
57
+ * top-level list is: the store must be able to freeze what it publishes without
58
+ * freezing a host out of its own storage.
59
+ */
60
+ function ownRows(rows) {
61
+ return own(rows.map((row) => ({ ...row, holdReasons: own(row.holdReasons) })));
62
+ }
63
+ /**
64
+ * Freeze every array reachable from a published value.
65
+ *
66
+ * `own` at each entry point covers the containers the store adopts directly,
67
+ * and that is exactly as far as it went — one level, when the predicate was
68
+ * never one level. Arrays nested inside published values (a conflict document's
69
+ * edges, an edge's state list, a row's hold reasons) are reachable from
70
+ * `getSnapshot()` just the same, and a consumer splicing one of those changes
71
+ * store state as surely as splicing `landed` would.
72
+ *
73
+ * ARRAYS ONLY: objects are walked but not frozen. That is the boundary the
74
+ * store can honestly keep — it owns which edges and rows it holds, the host
75
+ * owns what each one IS — and freezing the contents would seize objects an
76
+ * adapter or a deriver may still be using.
77
+ *
78
+ * Not short-circuited on an already-frozen array: `own` freezes a container
79
+ * without touching what is inside it, so stopping at the first frozen array
80
+ * would skip exactly the nested ones this exists to reach.
81
+ */
82
+ function freezeArrays(value) {
83
+ if (Array.isArray(value)) {
84
+ Object.freeze(value);
85
+ for (const item of value)
86
+ freezeArrays(item);
87
+ return;
88
+ }
89
+ if (typeof value === 'object' && value !== null) {
90
+ for (const nested of Object.values(value))
91
+ freezeArrays(nested);
92
+ }
93
+ }
94
+ const NO_PROJECTION = Object.freeze([]);
95
+ function messageOf(thrown) {
96
+ return thrown instanceof Error ? thrown.message : String(thrown);
97
+ }
98
+ /**
99
+ * Create a store over one data source.
100
+ *
101
+ * Nothing is loaded until `hydrate()` is called, so a host can construct the
102
+ * store during render and start the load where it wants to.
103
+ */
104
+ export function createStore(config) {
105
+ const { source, derive, guard } = config;
106
+ let landed = EMPTY_DOCUMENT;
107
+ let status = 'idle';
108
+ let hydrationError;
109
+ let records = [];
110
+ let selection = [];
111
+ let rows = [];
112
+ let lastChange;
113
+ let orderError;
114
+ let sequence = 0;
115
+ /**
116
+ * The edit the summary would belong to.
117
+ *
118
+ * A summary is written when a write LANDS, which can be after a newer edit
119
+ * has already started — and the contract is that a summary lasts until the
120
+ * next edit. Without this, a host shows the previous edit's blast radius
121
+ * beside the one the user is making now.
122
+ */
123
+ let currentProposal;
124
+ const queue = [];
125
+ let draining = false;
126
+ const listeners = new Set();
127
+ const settlers = new Map();
128
+ const initial = {
129
+ status,
130
+ issues: landed.issues,
131
+ landed: landed.edges,
132
+ projected: NO_PROJECTION,
133
+ order: Object.freeze({ rows: ownRows(rows), status: 'settled' }),
134
+ writes: own(records),
135
+ selection: own(selection),
136
+ };
137
+ let published = Object.freeze(initial);
138
+ /**
139
+ * Adopt a document, reusing the arrays already held where the new ones say
140
+ * the same thing.
141
+ *
142
+ * Not an optimisation: `landed` is what everything downstream compares
143
+ * against, so an adapter returning an equal-but-fresh array on every call
144
+ * would make every slice of the snapshot look changed and defeat the "update
145
+ * only if something changed" rule at its source rather than at its edge.
146
+ */
147
+ function adopt(next) {
148
+ const adopted = {
149
+ issues: sameValue(landed.issues, next.issues) ? landed.issues : own(next.issues),
150
+ edges: sameEdgeSet(landed.edges, next.edges) ? landed.edges : own(next.edges),
151
+ };
152
+ landed = adopted;
153
+ }
154
+ /**
155
+ * Rebuild the snapshot, reusing every slice that has not changed, and notify
156
+ * only if the result differs from what is already published.
157
+ *
158
+ * Per-slice reuse rather than one all-or-nothing comparison, so a host
159
+ * memoising on `snapshot.order.rows` is not re-rendered by an unrelated
160
+ * selection change — and `getSnapshot()` returns the identical reference when
161
+ * nothing at all moved, which is what `useSyncExternalStore` requires.
162
+ */
163
+ function publish() {
164
+ // CALL THIS ONLY ONCE THE OPERATION IS FULLY COMMITTED. Subscribers run
165
+ // synchronously and may call straight back into the store, so anything left
166
+ // undone at this point can be overtaken by the re-entrant call — which is
167
+ // how a follow-up edit once jumped the queue ahead of the edit that
168
+ // triggered it. Every other call site already commits first; keep it that
169
+ // way rather than making each one rediscover the rule.
170
+ const nextProjected = project(landed, records, new Set(selection));
171
+ const nextOrderStatus = anyPending(records) ? 'held' : 'settled';
172
+ // One comparison for every slice. Nothing here names a field, so a field
173
+ // added to any of these shapes is compared without this block changing.
174
+ const projected = sameValue(published.projected, nextProjected)
175
+ ? published.projected
176
+ : own(nextProjected);
177
+ // The rows keep their identity across a status-only change. Rebuilding the
178
+ // view is cheap; handing a host a new array when the ranking did not move
179
+ // defeats whatever it memoised on, and the status flips on every write.
180
+ const orderRows = sameValue(published.order.rows, rows) ? published.order.rows : rows;
181
+ const order = published.order.status === nextOrderStatus && published.order.rows === orderRows
182
+ ? published.order
183
+ : Object.freeze({ rows: orderRows, status: nextOrderStatus });
184
+ const writes = sameValue(published.writes, records) ? published.writes : own(records);
185
+ const selected = sameValue(published.selection, selection) ? published.selection : own(selection);
186
+ const unchanged = published.status === status &&
187
+ published.hydrationError === hydrationError &&
188
+ published.issues === landed.issues &&
189
+ published.landed === landed.edges &&
190
+ published.projected === projected &&
191
+ published.order === order &&
192
+ published.writes === writes &&
193
+ published.lastChange === lastChange &&
194
+ published.orderError === orderError &&
195
+ published.selection === selected;
196
+ if (unchanged)
197
+ return;
198
+ // Optional keys are omitted rather than set to `undefined`, because
199
+ // `exactOptionalPropertyTypes` is on and a host testing `'lastChange' in
200
+ // snapshot` must not find an empty one.
201
+ published = Object.freeze({
202
+ status,
203
+ ...(hydrationError === undefined ? {} : { hydrationError }),
204
+ issues: landed.issues,
205
+ landed: landed.edges,
206
+ projected,
207
+ order,
208
+ writes,
209
+ ...(lastChange === undefined ? {} : { lastChange }),
210
+ ...(orderError === undefined ? {} : { orderError }),
211
+ selection: selected,
212
+ });
213
+ freezeArrays(published);
214
+ // Isolated, and for the same reason as the guard and the deriver: a host
215
+ // callback that throws must not break the store. Rethrown asynchronously so
216
+ // it still surfaces as an unhandled error rather than being swallowed.
217
+ for (const listener of listeners) {
218
+ try {
219
+ listener();
220
+ }
221
+ catch (thrown) {
222
+ queueMicrotask(() => {
223
+ throw thrown;
224
+ });
225
+ }
226
+ }
227
+ }
228
+ /**
229
+ * Recompute the order from `landed`, and record what moved.
230
+ *
231
+ * A deriver that throws is a HOST callback failing, and the write it followed
232
+ * has already landed — so this cannot become a failed write and must not
233
+ * escape into the dispatch queue, where it would strand every edit behind it.
234
+ * The previously derived rows stand, `orderError` says why they are stale, and
235
+ * no change summary is emitted for an order nobody computed.
236
+ */
237
+ function reDerive(cause) {
238
+ const previous = rows;
239
+ let next;
240
+ try {
241
+ next = derive(landed);
242
+ }
243
+ catch (thrown) {
244
+ orderError = messageOf(thrown);
245
+ return;
246
+ }
247
+ // RECOVERING FROM A STALE BASELINE EMITS NO SUMMARY. While `orderError`
248
+ // stood, the published rows were the ones from before the edit that broke
249
+ // the deriver — so diffing the recovered order against them would credit
250
+ // that edit's movement to this one. There is no baseline that would make
251
+ // the attribution true, so none is claimed.
252
+ const recovering = orderError !== undefined;
253
+ orderError = undefined;
254
+ rows = ownRows(next);
255
+ // Only for the edit that is still the current one. A landing that a newer
256
+ // proposal has already overtaken has no summary to publish — the newer edit
257
+ // owns that slot, and will fill it when it lands.
258
+ const overtaken = cause !== undefined && cause.mutationId !== currentProposal;
259
+ if (cause !== undefined && !recovering && !overtaken)
260
+ lastChange = diffOrder(previous, rows, cause);
261
+ }
262
+ function recordFor(mutationId) {
263
+ return records.find((record) => record.mutationId === mutationId);
264
+ }
265
+ function putRecord(next) {
266
+ records = recordFor(next.mutationId) === undefined
267
+ ? [...records, next]
268
+ : records.map((record) => (record.mutationId === next.mutationId ? next : record));
269
+ }
270
+ function dropRecord(mutationId) {
271
+ records = records.filter((record) => record.mutationId !== mutationId);
272
+ }
273
+ function settle(mutationId) {
274
+ const resolve = settlers.get(mutationId);
275
+ settlers.delete(mutationId);
276
+ resolve?.();
277
+ }
278
+ /**
279
+ * Why this edit cannot happen — structurally, then by the injected guard.
280
+ *
281
+ * A guard that throws reached no verdict, and an unknown verdict is not
282
+ * permission to write: it refuses, fail-closed, with the thrown message as
283
+ * the reason. Letting it escape would strand the whole dispatch queue behind
284
+ * an edit that stayed pending for ever.
285
+ */
286
+ function refusalFor(mutation) {
287
+ const structural = structuralRefusal(landed, mutation);
288
+ if (structural !== undefined)
289
+ return structural;
290
+ if (guard === undefined)
291
+ return undefined;
292
+ try {
293
+ return guard({ mutation, current: landed, next: nextDocument(landed, mutation) });
294
+ }
295
+ catch (thrown) {
296
+ return { code: 'guard-failed', message: messageOf(thrown) };
297
+ }
298
+ }
299
+ async function dispatch(mutation) {
300
+ let result;
301
+ try {
302
+ result = await source.dispatch(mutation);
303
+ }
304
+ catch (thrown) {
305
+ // A crashing adapter must not leave the edit pending for ever, and must
306
+ // not look like a success. It is the same fact as a rejection — the write
307
+ // did not land — so it gets the same state and the same retry.
308
+ putRecord({
309
+ mutationId: mutation.mutationId,
310
+ mutation,
311
+ state: 'failed',
312
+ reason: messageOf(thrown),
313
+ });
314
+ settle(mutation.mutationId);
315
+ publish();
316
+ return;
317
+ }
318
+ switch (result.outcome) {
319
+ case 'applied': {
320
+ adopt(result.document);
321
+ dropRecord(mutation.mutationId);
322
+ reDerive(mutation);
323
+ break;
324
+ }
325
+ case 'unchanged': {
326
+ // Adopted like `applied`, because it is the same kind of claim about the
327
+ // document — and often said BECAUSE the store is out of date, which is
328
+ // exactly when not adopting it loses an edge that genuinely exists.
329
+ //
330
+ // Re-derived with NO cause: whatever moved was somebody else's doing, so
331
+ // attributing it to this edit would be wrong. `adopt` no-ops when the
332
+ // document already matches, so the ordinary case changes nothing.
333
+ adopt(result.document);
334
+ dropRecord(mutation.mutationId);
335
+ reDerive(undefined);
336
+ break;
337
+ }
338
+ case 'rejected': {
339
+ putRecord({
340
+ mutationId: mutation.mutationId,
341
+ mutation,
342
+ state: 'failed',
343
+ reason: result.reason,
344
+ });
345
+ break;
346
+ }
347
+ case 'conflict': {
348
+ putRecord({
349
+ mutationId: mutation.mutationId,
350
+ mutation,
351
+ state: 'conflict',
352
+ // Taken on rather than retained by reference: it is exposed through
353
+ // `snapshot.writes`, so a consumer must not be able to edit the
354
+ // adapter's own arrays through it.
355
+ upstream: ownDocument(result.upstream),
356
+ });
357
+ break;
358
+ }
359
+ }
360
+ settle(mutation.mutationId);
361
+ publish();
362
+ }
363
+ /**
364
+ * Refuse or dispatch, and put the record in the ledger either way.
365
+ *
366
+ * A refusal is recorded and NEVER dispatched — "refused before any write" is
367
+ * a fact about the adapter not being called, not just about the colour of the
368
+ * edge, and that is what the tests assert.
369
+ */
370
+ function start(mutation) {
371
+ // The summary is evidence for ONE edit, and the contract is that it lasts
372
+ // until the next edit or an explicit dismissal. Clearing it here is what
373
+ // makes that true: left standing, a host would show the previous edit's
374
+ // blast radius beside the edit the user is making now.
375
+ lastChange = undefined;
376
+ currentProposal = mutation.mutationId;
377
+ const settled = new Promise((resolve) => settlers.set(mutation.mutationId, resolve));
378
+ const refusal = refusalFor(mutation);
379
+ if (refusal !== undefined) {
380
+ putRecord({ mutationId: mutation.mutationId, mutation, state: 'invalid', reason: refusal });
381
+ settle(mutation.mutationId);
382
+ publish();
383
+ return { mutationId: mutation.mutationId, settled };
384
+ }
385
+ putRecord({ mutationId: mutation.mutationId, mutation, state: 'pending' });
386
+ // ENQUEUE BEFORE NOTIFYING. `publish` runs subscribers synchronously, so a
387
+ // subscriber proposing a follow-up re-enters here — and if the queue does
388
+ // not yet hold this edit, the nested one takes its place in line and goes
389
+ // out first. Two edits on the same edge then apply in the reverse of the
390
+ // order the user made them.
391
+ queue.push({ kind: 'dispatch', mutation });
392
+ publish();
393
+ void drain();
394
+ return { mutationId: mutation.mutationId, settled };
395
+ }
396
+ /**
397
+ * Run the queue, one authoritative operation at a time — dispatches and
398
+ * document reads alike, since both answer with a document.
399
+ *
400
+ * An edit that WAITED is re-checked before it goes out, because `landed` may
401
+ * have moved under it — a sibling edit can delete the relationship this one
402
+ * retypes, and dispatching against a document that no longer admits it would
403
+ * defeat "refused before any write". An edit that did not wait keeps the
404
+ * verdict `start` already reached, so the guard is called once per edit in
405
+ * the ordinary case and twice only when the document genuinely moved.
406
+ */
407
+ async function drain() {
408
+ if (draining)
409
+ return;
410
+ draining = true;
411
+ try {
412
+ for (let next = queue.shift(); next !== undefined; next = queue.shift()) {
413
+ if (next.kind === 'load') {
414
+ next.done(await runLoad(next.first));
415
+ continue;
416
+ }
417
+ // ALWAYS re-checked, not only when something is known to have moved.
418
+ // Knowing that needs bookkeeping about document freshness, and every
419
+ // version of that bookkeeping this store has had was wrong in a way
420
+ // nobody could see. `refusalFor` is pure and cheap; asking it twice
421
+ // costs a great deal less than being wrong about when to ask.
422
+ const refusal = refusalFor(next.mutation);
423
+ if (refusal !== undefined) {
424
+ putRecord({
425
+ mutationId: next.mutation.mutationId,
426
+ mutation: next.mutation,
427
+ state: 'invalid',
428
+ reason: refusal,
429
+ });
430
+ settle(next.mutation.mutationId);
431
+ publish();
432
+ continue;
433
+ }
434
+ await dispatch(next.mutation);
435
+ }
436
+ }
437
+ finally {
438
+ draining = false;
439
+ }
440
+ }
441
+ /** Queue a read of the document, behind whatever is already in flight. */
442
+ function load(first) {
443
+ return new Promise((resolve) => {
444
+ queue.push({ kind: 'load', first, done: resolve });
445
+ void drain();
446
+ });
447
+ }
448
+ /** A handle for a call that had nothing to act on. Already settled. */
449
+ function noop(mutationId) {
450
+ return { mutationId, settled: Promise.resolve() };
451
+ }
452
+ /** Read the document. Only ever called from the queue. */
453
+ /** Read the document. Resolves `true` when the read succeeded. */
454
+ async function runLoad(first) {
455
+ if (first) {
456
+ status = 'hydrating';
457
+ hydrationError = undefined;
458
+ publish();
459
+ }
460
+ try {
461
+ const document = await source.hydrate();
462
+ adopt(document);
463
+ status = 'ready';
464
+ hydrationError = undefined;
465
+ reDerive(undefined);
466
+ }
467
+ catch (thrown) {
468
+ hydrationError = messageOf(thrown);
469
+ // A failed refresh keeps the last good document and stays `ready`; only a
470
+ // first load that never produced one reports `failed`.
471
+ if (first)
472
+ status = 'failed';
473
+ publish();
474
+ return false;
475
+ }
476
+ publish();
477
+ return true;
478
+ }
479
+ return {
480
+ getSnapshot: () => published,
481
+ subscribe(listener) {
482
+ listeners.add(listener);
483
+ return () => {
484
+ listeners.delete(listener);
485
+ };
486
+ },
487
+ hydrate: async () => {
488
+ await load(true);
489
+ },
490
+ rehydrate: async () => {
491
+ await load(false);
492
+ },
493
+ propose(proposal) {
494
+ sequence += 1;
495
+ // A per-store counter, not a random identifier: identities only have to
496
+ // be unique within one store, and a deterministic one keeps every test
497
+ // that reads a mutation id reproducible.
498
+ return start({ ...proposal, mutationId: `m${sequence}` });
499
+ },
500
+ retry(mutationId) {
501
+ const record = recordFor(mutationId);
502
+ if (record === undefined || record.state === 'pending')
503
+ return noop(mutationId);
504
+ return start(record.mutation);
505
+ },
506
+ /**
507
+ * Single-step on purpose: it reads the record and acts on it with no
508
+ * `await` in between, so nothing can change underneath it. A resolution
509
+ * that had to refresh first could not have that property, which is why the
510
+ * store does not offer one.
511
+ */
512
+ discardMine(mutationId) {
513
+ const record = recordFor(mutationId);
514
+ if (record === undefined || record.state === 'pending')
515
+ return;
516
+ dropRecord(mutationId);
517
+ publish();
518
+ },
519
+ select(edgeIds) {
520
+ selection = [...edgeIds];
521
+ publish();
522
+ },
523
+ dismissChange() {
524
+ lastChange = undefined;
525
+ publish();
526
+ },
527
+ };
528
+ }
529
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAKL,WAAW,GACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAoB,SAAS,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAwC,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AA4GhE,6EAA6E;AAC7E,6EAA6E;AAC7E,SAAS;AACT,MAAM,cAAc,GAAkB,MAAM,CAAC,MAAM,CAAC;IAClD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAS,GAAG,CAAI,IAAkB;IAChC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,mFAAmF;AACnF,SAAS,WAAW,CAAC,QAAuB;IAC1C,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACrF,CAAC;AAED;;;;;;GAMG;AACH,SAAS,OAAO,CAAC,IAAyB;IACxC,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,WAAW,EAAE,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACjF,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrB,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;YAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AACD,MAAM,aAAa,GAA6B,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAElE,SAAS,SAAS,CAAC,MAAe;IAChC,OAAO,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACnE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC7C,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAEzC,IAAI,MAAM,GAAkB,cAAc,CAAC;IAC3C,IAAI,MAAM,GAAoB,MAAM,CAAC;IACrC,IAAI,cAAkC,CAAC;IACvC,IAAI,OAAO,GAA2B,EAAE,CAAC;IACzC,IAAI,SAAS,GAAsB,EAAE,CAAC;IACtC,IAAI,IAAI,GAAwB,EAAE,CAAC;IACnC,IAAI,UAAmC,CAAC;IACxC,IAAI,UAA8B,CAAC;IACnC,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB;;;;;;;OAOG;IACH,IAAI,eAAuC,CAAC;IAuB5C,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IACxC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEnD,MAAM,OAAO,GAAkB;QAC7B,MAAM;QACN,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,KAAK;QACpB,SAAS,EAAE,aAAa;QACxB,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAChE,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC;QACpB,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC;KAC1B,CAAC;IACF,IAAI,SAAS,GAAkB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEtD;;;;;;;;OAQG;IACH,SAAS,KAAK,CAAC,IAAmB;QAChC,MAAM,OAAO,GAAG;YACd,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;YAChF,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;SAC9E,CAAC;QACF,MAAM,GAAG,OAAO,CAAC;IACnB,CAAC;IAED;;;;;;;;OAQG;IACH,SAAS,OAAO;QACd,wEAAwE;QACxE,4EAA4E;QAC5E,0EAA0E;QAC1E,oEAAoE;QACpE,0EAA0E;QAC1E,uDAAuD;QACvD,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;QACnE,MAAM,eAAe,GAAgB,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;QAE9E,yEAAyE;QACzE,wEAAwE;QACxE,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,aAAa,CAAC;YAC7D,CAAC,CAAC,SAAS,CAAC,SAAS;YACrB,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACvB,2EAA2E;QAC3E,0EAA0E;QAC1E,wEAAwE;QACxE,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QACtF,MAAM,KAAK,GACT,SAAS,CAAC,KAAK,CAAC,MAAM,KAAK,eAAe,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS;YAC9E,CAAC,CAAC,SAAS,CAAC,KAAK;YACjB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtF,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAElG,MAAM,SAAS,GACb,SAAS,CAAC,MAAM,KAAK,MAAM;YAC3B,SAAS,CAAC,cAAc,KAAK,cAAc;YAC3C,SAAS,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;YAClC,SAAS,CAAC,MAAM,KAAK,MAAM,CAAC,KAAK;YACjC,SAAS,CAAC,SAAS,KAAK,SAAS;YACjC,SAAS,CAAC,KAAK,KAAK,KAAK;YACzB,SAAS,CAAC,MAAM,KAAK,MAAM;YAC3B,SAAS,CAAC,UAAU,KAAK,UAAU;YACnC,SAAS,CAAC,UAAU,KAAK,UAAU;YACnC,SAAS,CAAC,SAAS,KAAK,QAAQ,CAAC;QACnC,IAAI,SAAS;YAAE,OAAO;QAEtB,oEAAoE;QACpE,yEAAyE;QACzE,wCAAwC;QACxC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;YACxB,MAAM;YACN,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC;YAC3D,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,KAAK;YACpB,SAAS;YACT,KAAK;YACL,MAAM;YACN,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;YACnD,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;YACnD,SAAS,EAAE,QAAQ;SACpB,CAAC,CAAC;QACH,YAAY,CAAC,SAAS,CAAC,CAAC;QACxB,yEAAyE;QACzE,4EAA4E;QAC5E,uEAAuE;QACvE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,QAAQ,EAAE,CAAC;YACb,CAAC;YAAC,OAAO,MAAM,EAAE,CAAC;gBAChB,cAAc,CAAC,GAAG,EAAE;oBAClB,MAAM,MAAM,CAAC;gBACf,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,SAAS,QAAQ,CAAC,KAA2B;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC;QACtB,IAAI,IAAyB,CAAC;QAC9B,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,MAAM,EAAE,CAAC;YAChB,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,wEAAwE;QACxE,0EAA0E;QAC1E,yEAAyE;QACzE,yEAAyE;QACzE,4CAA4C;QAC5C,MAAM,UAAU,GAAG,UAAU,KAAK,SAAS,CAAC;QAC5C,UAAU,GAAG,SAAS,CAAC;QACvB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACrB,0EAA0E;QAC1E,4EAA4E;QAC5E,kDAAkD;QAClD,MAAM,SAAS,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,KAAK,eAAe,CAAC;QAC9E,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,UAAU,IAAI,CAAC,SAAS;YAAE,UAAU,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACtG,CAAC;IAED,SAAS,SAAS,CAAC,UAAsB;QACvC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;IACpE,CAAC;IAED,SAAS,SAAS,CAAC,IAAiB;QAClC,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,SAAS;YAChD,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC;YACpB,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,KAAK,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACvF,CAAC;IAED,SAAS,UAAU,CAAC,UAAsB;QACxC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;IACzE,CAAC;IAED,SAAS,MAAM,CAAC,UAAsB;QACpC,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACzC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5B,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;IAED;;;;;;;OAOG;IACH,SAAS,UAAU,CAAC,QAAkB;QACpC,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACvD,IAAI,UAAU,KAAK,SAAS;YAAE,OAAO,UAAU,CAAC;QAChD,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC1C,IAAI,CAAC;YACH,OAAO,KAAK,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;QACpF,CAAC;QAAC,OAAO,MAAM,EAAE,CAAC;YAChB,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,KAAK,UAAU,QAAQ,CAAC,QAAkB;QACxC,IAAI,MAAsB,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,MAAM,EAAE,CAAC;YAChB,wEAAwE;YACxE,0EAA0E;YAC1E,+DAA+D;YAC/D,SAAS,CAAC;gBACR,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,QAAQ;gBACR,KAAK,EAAE,QAAQ;gBACf,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC;aAC1B,CAAC,CAAC;YACH,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAC5B,OAAO,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,QAAQ,MAAM,CAAC,OAAO,EAAE,CAAC;YACvB,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACvB,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;gBAChC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBACnB,MAAM;YACR,CAAC;YACD,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,yEAAyE;gBACzE,uEAAuE;gBACvE,oEAAoE;gBACpE,EAAE;gBACF,yEAAyE;gBACzE,sEAAsE;gBACtE,kEAAkE;gBAClE,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACvB,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;gBAChC,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACpB,MAAM;YACR,CAAC;YACD,KAAK,UAAU,CAAC,CAAC,CAAC;gBAChB,SAAS,CAAC;oBACR,UAAU,EAAE,QAAQ,CAAC,UAAU;oBAC/B,QAAQ;oBACR,KAAK,EAAE,QAAQ;oBACf,MAAM,EAAE,MAAM,CAAC,MAAM;iBACtB,CAAC,CAAC;gBACH,MAAM;YACR,CAAC;YACD,KAAK,UAAU,CAAC,CAAC,CAAC;gBAChB,SAAS,CAAC;oBACR,UAAU,EAAE,QAAQ,CAAC,UAAU;oBAC/B,QAAQ;oBACR,KAAK,EAAE,UAAU;oBACjB,oEAAoE;oBACpE,gEAAgE;oBAChE,mCAAmC;oBACnC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC;iBACvC,CAAC,CAAC;gBACH,MAAM;YACR,CAAC;QACH,CAAC;QACD,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC5B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED;;;;;;OAMG;IACH,SAAS,KAAK,CAAC,QAAkB;QAC/B,0EAA0E;QAC1E,yEAAyE;QACzE,wEAAwE;QACxE,uDAAuD;QACvD,UAAU,GAAG,SAAS,CAAC;QACvB,eAAe,GAAG,QAAQ,CAAC,UAAU,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QAC3F,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,SAAS,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YAC5F,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAC5B,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;QACtD,CAAC;QAED,SAAS,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAC3E,2EAA2E;QAC3E,0EAA0E;QAC1E,0EAA0E;QAC1E,yEAAyE;QACzE,4BAA4B;QAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3C,OAAO,EAAE,CAAC;QACV,KAAK,KAAK,EAAE,CAAC;QACb,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;IACtD,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,UAAU,KAAK;QAClB,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,CAAC;YACH,KAAK,IAAI,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,EAAE,IAAI,KAAK,SAAS,EAAE,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;gBACxE,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBACzB,IAAI,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;oBACrC,SAAS;gBACX,CAAC;gBACD,qEAAqE;gBACrE,qEAAqE;gBACrE,oEAAoE;gBACpE,oEAAoE;gBACpE,8DAA8D;gBAC9D,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC1C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;oBAC1B,SAAS,CAAC;wBACR,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU;wBACpC,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,KAAK,EAAE,SAAS;wBAChB,MAAM,EAAE,OAAO;qBAChB,CAAC,CAAC;oBACH,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;oBACjC,OAAO,EAAE,CAAC;oBACV,SAAS;gBACX,CAAC;gBACD,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,QAAQ,GAAG,KAAK,CAAC;QACnB,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,SAAS,IAAI,CAAC,KAAc;QAC1B,OAAO,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;YACtC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YACnD,KAAK,KAAK,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;IAED,uEAAuE;IACvE,SAAS,IAAI,CAAC,UAAsB;QAClC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;IACpD,CAAC;IAED,0DAA0D;IAC1D,kEAAkE;IAClE,KAAK,UAAU,OAAO,CAAC,KAAc;QACnC,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,GAAG,WAAW,CAAC;YACrB,cAAc,GAAG,SAAS,CAAC;YAC3B,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;YACxC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAChB,MAAM,GAAG,OAAO,CAAC;YACjB,cAAc,GAAG,SAAS,CAAC;YAC3B,QAAQ,CAAC,SAAS,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,MAAM,EAAE,CAAC;YAChB,cAAc,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;YACnC,0EAA0E;YAC1E,uDAAuD;YACvD,IAAI,KAAK;gBAAE,MAAM,GAAG,QAAQ,CAAC;YAC7B,OAAO,EAAE,CAAC;YACV,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,WAAW,EAAE,GAAG,EAAE,CAAC,SAAS;QAE5B,SAAS,CAAC,QAAQ;YAChB,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxB,OAAO,GAAG,EAAE;gBACV,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC7B,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;QACD,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;QAED,OAAO,CAAC,QAAQ;YACd,QAAQ,IAAI,CAAC,CAAC;YACd,wEAAwE;YACxE,uEAAuE;YACvE,yCAAyC;YACzC,OAAO,KAAK,CAAC,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,IAAI,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,KAAK,CAAC,UAAU;YACd,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;gBAAE,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC;YAChF,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;QAED;;;;;WAKG;QACH,WAAW,CAAC,UAAU;YACpB,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;gBAAE,OAAO;YAC/D,UAAU,CAAC,UAAU,CAAC,CAAC;YACvB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,CAAC,OAAO;YACZ,SAAS,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;YACzB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,aAAa;YACX,UAAU,GAAG,SAAS,CAAC;YACvB,OAAO,EAAE,CAAC;QACZ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The document algebra, and the half of `invalid` that needs no graph walk.
3
+ *
4
+ * Pure and synchronous throughout: everything here answers "what would this
5
+ * edit produce" or "why can it not happen", and neither question has any
6
+ * business touching a network, a clock or the store's state.
7
+ *
8
+ * The split with {@link ../source.ts EdgeGuard} is by what the answer NEEDS TO
9
+ * SEE. A self-edge, an unknown reference and a duplicate are visible in the
10
+ * edit itself; a cycle is only visible by walking the graph, and the walk
11
+ * belongs with the derivation so the package family has one of it. Both halves
12
+ * produce the same refusal, and neither ever reaches `dispatch`.
13
+ */
14
+ import { type EdgeId, type GraphDocument, type StoredEdge } from './model.ts';
15
+ import type { InvalidReason, Mutation } from './mutation.ts';
16
+ /**
17
+ * What an edit does to the projection: which landed edges it replaces, which
18
+ * edges it introduces, and which of them carry its state.
19
+ *
20
+ * A `delete` draws nothing and hides nothing — it MARKS the edge it is removing
21
+ * and leaves it visible. That is deliberate rather than a missing case: the
22
+ * design draws `failed` as a ghost with a ✕ terminal, and there is no ghost to
23
+ * draw if an optimistic delete has already taken the edge off the canvas. The
24
+ * edge leaves the document when the write lands, not when it is proposed.
25
+ */
26
+ export interface EdgeChange {
27
+ readonly hidden: readonly EdgeId[];
28
+ readonly drawn: readonly StoredEdge[];
29
+ readonly marked: readonly EdgeId[];
30
+ }
31
+ /** The edge an edit produces, or `undefined` for one that produces none. */
32
+ export declare function resultingEdge(document: GraphDocument, mutation: Mutation): StoredEdge | undefined;
33
+ /** How an edit shows up in the projection while it is unlanded. */
34
+ export declare function edgeChangeFor(document: GraphDocument, mutation: Mutation): EdgeChange;
35
+ /** The document an edit would produce, if it landed exactly as proposed. */
36
+ export declare function nextDocument(document: GraphDocument, mutation: Mutation): GraphDocument;
37
+ /**
38
+ * Why this edit cannot happen, from the edit and the document alone.
39
+ *
40
+ * Returns `undefined` when nothing structural stands in the way — which is not
41
+ * the same as "valid": an injected guard runs afterwards and may still refuse.
42
+ */
43
+ export declare function structuralRefusal(document: GraphDocument, mutation: Mutation): InvalidReason | undefined;
44
+ //# sourceMappingURL=validity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validity.d.ts","sourceRoot":"","sources":["../src/validity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,EACL,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,UAAU,EAIhB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE7D;;;;;;;;;GASG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAejG;AAED,mEAAmE;AACnE,wBAAgB,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,GAAG,UAAU,CA2BrF;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,GAAG,aAAa,CASvF;AAMD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,QAAQ,GACjB,aAAa,GAAG,SAAS,CA2C3B"}