@prometheus-ags/prometheus-entity-management 1.0.0 → 1.2.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.js CHANGED
@@ -3,17 +3,17 @@
3
3
  var zustand = require('zustand');
4
4
  var middleware = require('zustand/middleware');
5
5
  var immer = require('zustand/middleware/immer');
6
- var React5 = require('react');
6
+ var React6 = require('react');
7
+ var jsxRuntime = require('react/jsx-runtime');
7
8
  var shallow = require('zustand/react/shallow');
8
9
  var reactTable = require('@tanstack/react-table');
9
10
  var lucideReact = require('lucide-react');
10
11
  var clsx = require('clsx');
11
12
  var tailwindMerge = require('tailwind-merge');
12
- var jsxRuntime = require('react/jsx-runtime');
13
13
 
14
14
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
15
15
 
16
- var React5__default = /*#__PURE__*/_interopDefault(React5);
16
+ var React6__default = /*#__PURE__*/_interopDefault(React6);
17
17
 
18
18
  // src/graph.ts
19
19
  var EMPTY_IDS = [];
@@ -23,6 +23,11 @@ var EMPTY_ENTITY_STATE = {
23
23
  error: null,
24
24
  stale: false
25
25
  };
26
+ var EMPTY_SYNC_METADATA = {
27
+ synced: true,
28
+ origin: "server",
29
+ updatedAt: null
30
+ };
26
31
  var EMPTY_LIST_STATE = {
27
32
  ids: EMPTY_IDS,
28
33
  total: null,
@@ -41,6 +46,9 @@ var EMPTY_LIST_STATE = {
41
46
  function defaultEntityState() {
42
47
  return { ...EMPTY_ENTITY_STATE };
43
48
  }
49
+ function defaultSyncMetadata() {
50
+ return { ...EMPTY_SYNC_METADATA };
51
+ }
44
52
  function defaultListState() {
45
53
  return { ...EMPTY_LIST_STATE, ids: [] };
46
54
  }
@@ -53,24 +61,33 @@ var useGraphStore = zustand.create()(
53
61
  entities: {},
54
62
  patches: {},
55
63
  entityStates: {},
64
+ syncMetadata: {},
56
65
  lists: {},
57
66
  upsertEntity: (type, id, data) => set((s) => {
58
67
  if (!s.entities[type]) s.entities[type] = {};
59
68
  s.entities[type][id] = { ...s.entities[type][id] ?? {}, ...data };
69
+ const key = ek(type, id);
70
+ if (!s.syncMetadata[key]) s.syncMetadata[key] = defaultSyncMetadata();
60
71
  }),
61
72
  upsertEntities: (type, entries) => set((s) => {
62
73
  if (!s.entities[type]) s.entities[type] = {};
63
- for (const { id, data } of entries)
74
+ for (const { id, data } of entries) {
64
75
  s.entities[type][id] = { ...s.entities[type][id] ?? {}, ...data };
76
+ const key = ek(type, id);
77
+ if (!s.syncMetadata[key]) s.syncMetadata[key] = defaultSyncMetadata();
78
+ }
65
79
  }),
66
80
  replaceEntity: (type, id, data) => set((s) => {
67
81
  if (!s.entities[type]) s.entities[type] = {};
68
82
  s.entities[type][id] = data;
83
+ const key = ek(type, id);
84
+ if (!s.syncMetadata[key]) s.syncMetadata[key] = defaultSyncMetadata();
69
85
  }),
70
86
  removeEntity: (type, id) => set((s) => {
71
87
  delete s.entities[type]?.[id];
72
88
  delete s.patches[type]?.[id];
73
89
  delete s.entityStates[ek(type, id)];
90
+ delete s.syncMetadata[ek(type, id)];
74
91
  }),
75
92
  patchEntity: (type, id, patch) => set((s) => {
76
93
  if (!s.patches[type]) s.patches[type] = {};
@@ -102,12 +119,20 @@ var useGraphStore = zustand.create()(
102
119
  s.entityStates[k].isFetching = false;
103
120
  s.entityStates[k].error = null;
104
121
  s.entityStates[k].stale = false;
122
+ s.syncMetadata[k] = { ...s.syncMetadata[k] ?? defaultSyncMetadata(), synced: true, origin: "server", updatedAt: Date.now() };
105
123
  }),
106
124
  setEntityStale: (type, id, stale) => set((s) => {
107
125
  const k = ek(type, id);
108
126
  if (!s.entityStates[k]) s.entityStates[k] = defaultEntityState();
109
127
  s.entityStates[k].stale = stale;
110
128
  }),
129
+ setEntitySyncMetadata: (type, id, metadata) => set((s) => {
130
+ const k = ek(type, id);
131
+ s.syncMetadata[k] = { ...s.syncMetadata[k] ?? defaultSyncMetadata(), ...metadata };
132
+ }),
133
+ clearEntitySyncMetadata: (type, id) => set((s) => {
134
+ delete s.syncMetadata[ek(type, id)];
135
+ }),
111
136
  setListResult: (key, ids, meta) => set((s) => {
112
137
  const ex = s.lists[key] ?? defaultListState();
113
138
  s.lists[key] = { ...ex, ...meta, ids, isFetching: false, isFetchingMore: false, error: null, stale: false, lastFetched: Date.now() };
@@ -179,11 +204,717 @@ var useGraphStore = zustand.create()(
179
204
  if (!base) return null;
180
205
  const patch = s.patches[type]?.[id];
181
206
  return patch ? { ...base, ...patch } : base;
207
+ },
208
+ readEntitySnapshot: (type, id) => {
209
+ const s = get();
210
+ const base = s.entities[type]?.[id];
211
+ if (!base) return null;
212
+ const patch = s.patches[type]?.[id];
213
+ const metadata = s.syncMetadata[ek(type, id)] ?? EMPTY_SYNC_METADATA;
214
+ return {
215
+ ...patch ? { ...base, ...patch } : base,
216
+ $synced: metadata.synced,
217
+ $origin: metadata.origin,
218
+ $updatedAt: metadata.updatedAt
219
+ };
182
220
  }
183
221
  }))
184
222
  )
185
223
  );
186
224
 
225
+ // src/graph-query.ts
226
+ function queryOnce(opts) {
227
+ const store = useGraphStore.getState();
228
+ const ids = resolveCandidateIds(store, opts);
229
+ let rows = ids.map((id) => store.readEntitySnapshot(opts.type, id)).filter((row) => row !== null);
230
+ if (opts.where) rows = rows.filter(opts.where);
231
+ if (opts.sort) rows = [...rows].sort(opts.sort);
232
+ const projected = rows.map((row) => applySelection(projectRow(row, opts.include, store), opts.select));
233
+ if (opts.id) return projected[0] ?? null;
234
+ return projected;
235
+ }
236
+ var selectGraph = queryOnce;
237
+ function resolveCandidateIds(store, opts) {
238
+ if (opts.id) return [opts.id];
239
+ if (opts.ids) return opts.ids;
240
+ if (opts.listKey) return store.lists[opts.listKey]?.ids ?? [];
241
+ return Object.keys(store.entities[opts.type] ?? {});
242
+ }
243
+ function projectRow(row, include, store) {
244
+ if (!include) return row;
245
+ const projected = { ...row };
246
+ for (const [key, relation] of Object.entries(include)) {
247
+ const related = resolveRelation(row, relation, store);
248
+ projected[key] = related;
249
+ }
250
+ return projected;
251
+ }
252
+ function resolveRelation(entity, relation, store) {
253
+ const include = relation.include;
254
+ switch (relation.via.kind) {
255
+ case "field": {
256
+ const relatedId = entity[relation.via.field];
257
+ if (typeof relatedId !== "string") return null;
258
+ const related = store.readEntitySnapshot(relation.type, relatedId);
259
+ return related ? projectRow(related, include, store) : null;
260
+ }
261
+ case "array": {
262
+ const ids = entity[relation.via.field];
263
+ if (!Array.isArray(ids)) return [];
264
+ return ids.map((id) => typeof id === "string" ? store.readEntitySnapshot(relation.type, id) : null).filter((row) => row !== null).map((row) => projectRow(row, include, store));
265
+ }
266
+ case "list": {
267
+ const key = typeof relation.via.key === "function" ? relation.via.key(entity) : relation.via.key;
268
+ if (!key) return [];
269
+ const ids = store.lists[key]?.ids ?? [];
270
+ return ids.map((id) => store.readEntitySnapshot(relation.type, id)).filter((row) => row !== null).map((row) => projectRow(row, include, store));
271
+ }
272
+ case "resolver": {
273
+ const resolved = relation.via.resolve(entity, store);
274
+ if (Array.isArray(resolved)) {
275
+ return resolved.map((id) => store.readEntitySnapshot(relation.type, id)).filter((row) => row !== null).map((row) => projectRow(row, include, store));
276
+ }
277
+ if (typeof resolved !== "string") return null;
278
+ const related = store.readEntitySnapshot(relation.type, resolved);
279
+ return related ? projectRow(related, include, store) : null;
280
+ }
281
+ }
282
+ }
283
+ function applySelection(row, select) {
284
+ if (!select) return row;
285
+ if (typeof select === "function") {
286
+ const result = select(row);
287
+ return result && typeof result === "object" ? result : { value: result };
288
+ }
289
+ const picked = {};
290
+ for (const key of select) {
291
+ if (key in row) picked[key] = row[key];
292
+ }
293
+ return picked;
294
+ }
295
+
296
+ // src/graph-actions.ts
297
+ var graphActionListeners = /* @__PURE__ */ new Set();
298
+ var graphActionReplayers = /* @__PURE__ */ new Map();
299
+ function createGraphTransaction() {
300
+ const baseline = cloneGraphData();
301
+ let closed = false;
302
+ const tx = {
303
+ upsertEntity(type, id, data) {
304
+ useGraphStore.getState().upsertEntity(type, id, data);
305
+ return tx;
306
+ },
307
+ replaceEntity(type, id, data) {
308
+ useGraphStore.getState().replaceEntity(type, id, data);
309
+ return tx;
310
+ },
311
+ removeEntity(type, id) {
312
+ useGraphStore.getState().removeEntity(type, id);
313
+ return tx;
314
+ },
315
+ patchEntity(type, id, patch) {
316
+ useGraphStore.getState().patchEntity(type, id, patch);
317
+ return tx;
318
+ },
319
+ clearPatch(type, id) {
320
+ useGraphStore.getState().clearPatch(type, id);
321
+ return tx;
322
+ },
323
+ insertIdInList(key, id, position) {
324
+ useGraphStore.getState().insertIdInList(key, id, position);
325
+ return tx;
326
+ },
327
+ removeIdFromAllLists(type, id) {
328
+ useGraphStore.getState().removeIdFromAllLists(type, id);
329
+ return tx;
330
+ },
331
+ setEntitySyncMetadata(type, id, metadata) {
332
+ useGraphStore.getState().setEntitySyncMetadata(type, id, metadata);
333
+ return tx;
334
+ },
335
+ markEntityPending(type, id, origin = "optimistic") {
336
+ useGraphStore.getState().setEntitySyncMetadata(type, id, {
337
+ synced: false,
338
+ origin,
339
+ updatedAt: Date.now()
340
+ });
341
+ return tx;
342
+ },
343
+ markEntitySynced(type, id, origin = "server") {
344
+ useGraphStore.getState().setEntitySyncMetadata(type, id, {
345
+ synced: true,
346
+ origin,
347
+ updatedAt: Date.now()
348
+ });
349
+ return tx;
350
+ },
351
+ commit() {
352
+ closed = true;
353
+ },
354
+ rollback() {
355
+ if (closed) return;
356
+ useGraphStore.setState(cloneGraphData(baseline));
357
+ closed = true;
358
+ },
359
+ snapshot() {
360
+ return cloneGraphData();
361
+ }
362
+ };
363
+ return tx;
364
+ }
365
+ function createGraphAction(opts) {
366
+ if (opts.key) {
367
+ graphActionReplayers.set(opts.key, async (record) => {
368
+ const tx = createGraphTransaction();
369
+ try {
370
+ const result = await opts.run(tx, record.input);
371
+ tx.commit();
372
+ return result;
373
+ } catch (error) {
374
+ tx.rollback();
375
+ throw error;
376
+ }
377
+ });
378
+ }
379
+ return async (input) => {
380
+ const tx = createGraphTransaction();
381
+ const record = opts.key ? {
382
+ id: `${opts.key}:${Date.now()}`,
383
+ key: opts.key,
384
+ input: structuredClone(input),
385
+ enqueuedAt: (/* @__PURE__ */ new Date()).toISOString()
386
+ } : null;
387
+ try {
388
+ if (record) emitGraphActionEvent({ type: "enqueued", record });
389
+ opts.optimistic?.(tx, input);
390
+ const result = await opts.run(tx, input);
391
+ opts.onSuccess?.(result, input, tx);
392
+ tx.commit();
393
+ if (record) emitGraphActionEvent({ type: "settled", record });
394
+ return result;
395
+ } catch (error) {
396
+ tx.rollback();
397
+ const normalized = error instanceof Error ? error : new Error(String(error));
398
+ if (record) emitGraphActionEvent({ type: "settled", record });
399
+ opts.onError?.(normalized, input);
400
+ throw normalized;
401
+ }
402
+ };
403
+ }
404
+ function subscribeGraphActionEvents(listener) {
405
+ graphActionListeners.add(listener);
406
+ return () => graphActionListeners.delete(listener);
407
+ }
408
+ async function replayRegisteredGraphAction(record) {
409
+ const replayer = graphActionReplayers.get(record.key);
410
+ if (!replayer) throw new Error(`No graph action registered for key "${record.key}"`);
411
+ return replayer(record);
412
+ }
413
+ function cloneGraphData(source = useGraphStore.getState()) {
414
+ return {
415
+ entities: structuredClone(source.entities),
416
+ patches: structuredClone(source.patches),
417
+ entityStates: structuredClone(source.entityStates),
418
+ syncMetadata: structuredClone(source.syncMetadata),
419
+ lists: structuredClone(source.lists)
420
+ };
421
+ }
422
+ function emitGraphActionEvent(event) {
423
+ for (const listener of graphActionListeners) listener(event);
424
+ }
425
+
426
+ // src/graph-effects.ts
427
+ function createGraphEffect(opts) {
428
+ const getKey = opts.getKey ?? defaultGetKey;
429
+ const isEqual = opts.isEqual ?? defaultIsEqual;
430
+ let initialized = false;
431
+ let previous = /* @__PURE__ */ new Map();
432
+ const evaluate = () => {
433
+ const nextValues = normalizeQueryResult(opts.query());
434
+ const next = /* @__PURE__ */ new Map();
435
+ nextValues.forEach((value, index) => {
436
+ next.set(getKey(value, index), value);
437
+ });
438
+ if (!initialized) {
439
+ initialized = true;
440
+ previous = next;
441
+ if (opts.skipInitial) return;
442
+ }
443
+ for (const [key, value] of next.entries()) {
444
+ const previousValue = previous.get(key);
445
+ if (previousValue === void 0) {
446
+ opts.onEnter?.({ key, value });
447
+ continue;
448
+ }
449
+ if (!isEqual(previousValue, value)) {
450
+ opts.onUpdate?.({ key, value, previousValue });
451
+ }
452
+ }
453
+ for (const [key, previousValue] of previous.entries()) {
454
+ if (!next.has(key)) opts.onExit?.({ key, previousValue });
455
+ }
456
+ previous = next;
457
+ };
458
+ evaluate();
459
+ const unsubscribe = useGraphStore.subscribe(() => {
460
+ evaluate();
461
+ });
462
+ return {
463
+ dispose: () => {
464
+ unsubscribe();
465
+ }
466
+ };
467
+ }
468
+ function normalizeQueryResult(value) {
469
+ if (value == null) return [];
470
+ return Array.isArray(value) ? value : [value];
471
+ }
472
+ function defaultGetKey(value, index) {
473
+ if (value && typeof value === "object") {
474
+ const record = value;
475
+ if (typeof record.id === "string") return record.id;
476
+ if (typeof record.$key === "string") return record.$key;
477
+ }
478
+ return String(index);
479
+ }
480
+ function defaultIsEqual(previousValue, nextValue) {
481
+ return JSON.stringify(previousValue) === JSON.stringify(nextValue);
482
+ }
483
+
484
+ // src/object-path.ts
485
+ function isObject(value) {
486
+ return typeof value === "object" && value !== null && !Array.isArray(value);
487
+ }
488
+ function getValueAtPath(source, path) {
489
+ if (!path) return source;
490
+ const segments = path.split(".").filter(Boolean);
491
+ let current = source;
492
+ for (const segment of segments) {
493
+ if (!isObject(current) && !Array.isArray(current)) return void 0;
494
+ current = current[segment];
495
+ }
496
+ return current;
497
+ }
498
+ function setValueAtPath(source, path, value) {
499
+ const segments = path.split(".").filter(Boolean);
500
+ if (segments.length === 0) return source;
501
+ const clone = structuredClone(source);
502
+ let current = clone;
503
+ for (let index = 0; index < segments.length - 1; index += 1) {
504
+ const segment = segments[index];
505
+ const next = current[segment];
506
+ if (!isObject(next)) current[segment] = {};
507
+ current = current[segment];
508
+ }
509
+ current[segments[segments.length - 1]] = value;
510
+ return clone;
511
+ }
512
+ function collectDirtyPaths(current, original, prefix = "", acc = /* @__PURE__ */ new Set()) {
513
+ if (isObject(current) && isObject(original)) {
514
+ const keys = /* @__PURE__ */ new Set([...Object.keys(current), ...Object.keys(original)]);
515
+ for (const key of keys) {
516
+ const nextPrefix = prefix ? `${prefix}.${key}` : key;
517
+ collectDirtyPaths(current[key], original[key], nextPrefix, acc);
518
+ }
519
+ return acc;
520
+ }
521
+ if (JSON.stringify(current) !== JSON.stringify(original) && prefix) acc.add(prefix);
522
+ return acc;
523
+ }
524
+ var schemaRegistry = /* @__PURE__ */ new Map();
525
+ function registerEntityJsonSchema(config) {
526
+ const key = registryKey(config.entityType, config.field, config.schemaId);
527
+ schemaRegistry.set(key, config);
528
+ }
529
+ function registerRuntimeSchema(config) {
530
+ registerEntityJsonSchema(config);
531
+ }
532
+ function getEntityJsonSchema(opts) {
533
+ const exact = schemaRegistry.get(registryKey(opts.entityType, opts.field, opts.schemaId));
534
+ if (exact) return exact;
535
+ if (opts.field) {
536
+ const byField = schemaRegistry.get(registryKey(opts.entityType, opts.field));
537
+ if (byField) return byField;
538
+ }
539
+ if (opts.schemaId) {
540
+ const byId = schemaRegistry.get(registryKey(opts.entityType, void 0, opts.schemaId));
541
+ if (byId) return byId;
542
+ }
543
+ for (const schema of schemaRegistry.values()) {
544
+ if (schema.entityType !== opts.entityType) continue;
545
+ if (opts.field && schema.field !== opts.field) continue;
546
+ return schema;
547
+ }
548
+ return null;
549
+ }
550
+ function useSchemaEntityFields(opts) {
551
+ return React6.useMemo(() => {
552
+ const schema = opts.schema ?? getEntityJsonSchema(opts)?.schema;
553
+ if (!schema) return [];
554
+ return buildEntityFieldsFromSchema({ schema, rootField: opts.rootField ?? opts.field });
555
+ }, [opts.entityType, opts.field, opts.rootField, opts.schemaId, opts.schema]);
556
+ }
557
+ function buildEntityFieldsFromSchema(opts) {
558
+ return buildSchemaFields(opts.schema, opts.rootField ?? "", "");
559
+ }
560
+ function exportGraphSnapshotWithSchemas(opts) {
561
+ return JSON.stringify(
562
+ {
563
+ scope: opts.scope,
564
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
565
+ data: opts.data,
566
+ schemas: opts.schemas.filter(Boolean)
567
+ },
568
+ null,
569
+ opts.pretty === false ? 0 : 2
570
+ );
571
+ }
572
+ function escapeHtml(input) {
573
+ return input.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
574
+ }
575
+ function renderMarkdownToHtml(value) {
576
+ const escaped = escapeHtml(value);
577
+ const blocks = escaped.split(/\n{2,}/).map((block) => block.trim()).filter(Boolean);
578
+ return blocks.map((block) => renderMarkdownBlock(block)).join("");
579
+ }
580
+ function MarkdownFieldRenderer({ value, className }) {
581
+ return /* @__PURE__ */ jsxRuntime.jsx(
582
+ "div",
583
+ {
584
+ className,
585
+ dangerouslySetInnerHTML: { __html: renderMarkdownToHtml(value ?? "") }
586
+ }
587
+ );
588
+ }
589
+ function MarkdownFieldEditor({
590
+ value,
591
+ onChange,
592
+ placeholder
593
+ }) {
594
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
595
+ /* @__PURE__ */ jsxRuntime.jsx(
596
+ "textarea",
597
+ {
598
+ value,
599
+ onChange: (event) => onChange(event.target.value),
600
+ placeholder,
601
+ className: "w-full min-h-[120px] rounded-md border bg-muted/50 px-3 py-2 text-sm resize-y focus:outline-none focus:ring-1 focus:ring-ring transition-colors"
602
+ }
603
+ ),
604
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border bg-background px-3 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownFieldRenderer, { value, className: "prose prose-sm max-w-none" }) })
605
+ ] });
606
+ }
607
+ function createMarkdownDetailRenderer(field) {
608
+ return (value, entity) => /* @__PURE__ */ jsxRuntime.jsx(MarkdownFieldRenderer, { value: String(value ?? getValueAtPath(entity, field) ?? ""), className: "prose prose-sm max-w-none" });
609
+ }
610
+ function buildSchemaFields(schema, pathPrefix, schemaPathPrefix) {
611
+ if (schema.type === "object" && schema.properties) {
612
+ const entries = Object.entries(schema.properties).sort(([, left], [, right]) => {
613
+ const l = left["x-display-order"] ?? Number.MAX_SAFE_INTEGER;
614
+ const r = right["x-display-order"] ?? Number.MAX_SAFE_INTEGER;
615
+ return l - r;
616
+ });
617
+ return entries.flatMap(([key, childSchema]) => {
618
+ if (childSchema["x-hidden"]) return [];
619
+ const field = pathPrefix ? `${pathPrefix}.${key}` : key;
620
+ const schemaPath = schemaPathPrefix ? `${schemaPathPrefix}.${key}` : key;
621
+ if (childSchema.type === "object" && childSchema.properties) {
622
+ return buildSchemaFields(childSchema, field, schemaPath);
623
+ }
624
+ return [schemaField(field, schemaPath, childSchema, schema.required?.includes(key) ?? false)];
625
+ });
626
+ }
627
+ return [];
628
+ }
629
+ function schemaField(field, schemaPath, schema, required) {
630
+ const type = inferFieldType(schema);
631
+ const descriptor = {
632
+ field,
633
+ label: schema.title ?? humanize(field.split(".").pop() ?? field),
634
+ type,
635
+ required,
636
+ hint: schema.description,
637
+ schemaPath,
638
+ schema,
639
+ componentHint: schema["x-a2ui-component"]
640
+ };
641
+ if (schema.enum) {
642
+ descriptor.options = schema.enum.map((value) => ({
643
+ value: String(value),
644
+ label: String(value)
645
+ }));
646
+ }
647
+ if (type === "markdown") {
648
+ descriptor.render = createMarkdownDetailRenderer(field);
649
+ }
650
+ return descriptor;
651
+ }
652
+ function inferFieldType(schema) {
653
+ const forced = schema["x-field-type"];
654
+ if (forced === "markdown") return "markdown";
655
+ if (schema.format === "markdown") return "markdown";
656
+ if (schema.enum) return "enum";
657
+ const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
658
+ switch (type) {
659
+ case "boolean":
660
+ return "boolean";
661
+ case "integer":
662
+ case "number":
663
+ return "number";
664
+ case "string":
665
+ if (schema.format === "email") return "email";
666
+ if (schema.format === "uri" || schema.format === "url") return "url";
667
+ if (schema.format === "date" || schema.format === "date-time") return "date";
668
+ return "text";
669
+ case "array":
670
+ case "object":
671
+ return "json";
672
+ default:
673
+ return "text";
674
+ }
675
+ }
676
+ function registryKey(entityType, field, schemaId) {
677
+ return `${entityType}::${field ?? "*"}::${schemaId ?? "*"}`;
678
+ }
679
+ function humanize(value) {
680
+ return value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
681
+ }
682
+ function renderMarkdownBlock(block) {
683
+ if (block.startsWith("# ")) return `<h1>${renderInlineMarkdown(block.slice(2))}</h1>`;
684
+ if (block.startsWith("## ")) return `<h2>${renderInlineMarkdown(block.slice(3))}</h2>`;
685
+ return `<p>${renderInlineMarkdown(block).replaceAll("\n", "<br/>")}</p>`;
686
+ }
687
+ function renderInlineMarkdown(block) {
688
+ return block.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
689
+ }
690
+
691
+ // src/ai-interop.ts
692
+ function exportGraphSnapshot(opts) {
693
+ const payload = {
694
+ scope: opts.scope,
695
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
696
+ data: opts.data
697
+ };
698
+ return JSON.stringify(payload, null, opts.pretty === false ? 0 : 2);
699
+ }
700
+ function createGraphTool(handler) {
701
+ return (input) => handler(input, {
702
+ store: useGraphStore.getState(),
703
+ queryOnce,
704
+ exportGraphSnapshot
705
+ });
706
+ }
707
+ function createSchemaGraphTool(handler) {
708
+ return (input) => handler(input, {
709
+ store: useGraphStore.getState(),
710
+ queryOnce,
711
+ exportGraphSnapshot,
712
+ getEntityJsonSchema,
713
+ exportGraphSnapshotWithSchemas
714
+ });
715
+ }
716
+ var DEFAULT_STORAGE_KEY = "prometheus:graph";
717
+ var useGraphSyncStatusStore = zustand.create((set) => ({
718
+ status: {
719
+ phase: "idle",
720
+ isOnline: true,
721
+ isSynced: true,
722
+ pendingActions: 0,
723
+ lastHydratedAt: null,
724
+ lastPersistedAt: null,
725
+ storageKey: null,
726
+ error: null
727
+ },
728
+ setStatus: (status) => set((state) => ({
729
+ status: {
730
+ ...state.status,
731
+ ...status
732
+ }
733
+ }))
734
+ }));
735
+ var pendingActions = /* @__PURE__ */ new Map();
736
+ function useGraphSyncStatus() {
737
+ return useGraphSyncStatusStore((state) => state.status);
738
+ }
739
+ async function persistGraphToStorage(opts) {
740
+ const payload = {
741
+ version: 1,
742
+ snapshot: cloneGraphSnapshot(),
743
+ pendingActions: opts.pendingActions ?? Array.from(pendingActions.values())
744
+ };
745
+ const json = JSON.stringify(payload);
746
+ await opts.storage.set(opts.key, json);
747
+ const persistedAt = (/* @__PURE__ */ new Date()).toISOString();
748
+ useGraphSyncStatusStore.getState().setStatus({
749
+ lastPersistedAt: persistedAt,
750
+ storageKey: opts.key,
751
+ pendingActions: payload.pendingActions.length
752
+ });
753
+ return {
754
+ ok: true,
755
+ key: opts.key,
756
+ bytes: json.length,
757
+ persistedAt
758
+ };
759
+ }
760
+ async function hydrateGraphFromStorage(opts) {
761
+ const raw = await opts.storage.get(opts.key);
762
+ if (!raw) {
763
+ return {
764
+ ok: false,
765
+ key: opts.key,
766
+ hydratedAt: null,
767
+ entityCounts: {},
768
+ error: "No persisted graph snapshot found"
769
+ };
770
+ }
771
+ try {
772
+ const parsed = JSON.parse(raw);
773
+ useGraphStore.setState(parsed.snapshot);
774
+ pendingActions.clear();
775
+ for (const action of parsed.pendingActions ?? []) pendingActions.set(action.id, action);
776
+ const hydratedAt = (/* @__PURE__ */ new Date()).toISOString();
777
+ useGraphSyncStatusStore.getState().setStatus({
778
+ lastHydratedAt: hydratedAt,
779
+ storageKey: opts.key,
780
+ pendingActions: pendingActions.size,
781
+ error: null
782
+ });
783
+ return {
784
+ ok: true,
785
+ key: opts.key,
786
+ hydratedAt,
787
+ entityCounts: Object.fromEntries(
788
+ Object.entries(parsed.snapshot.entities).map(([type, entities]) => [type, Object.keys(entities).length])
789
+ ),
790
+ pendingActions: Array.from(pendingActions.values())
791
+ };
792
+ } catch (error) {
793
+ const message = error instanceof Error ? error.message : String(error);
794
+ useGraphSyncStatusStore.getState().setStatus({
795
+ phase: "error",
796
+ error: message,
797
+ storageKey: opts.key
798
+ });
799
+ return {
800
+ ok: false,
801
+ key: opts.key,
802
+ hydratedAt: null,
803
+ entityCounts: {},
804
+ error: message
805
+ };
806
+ }
807
+ }
808
+ function startLocalFirstGraph(opts) {
809
+ const key = opts.key ?? DEFAULT_STORAGE_KEY;
810
+ const persistDebounceMs = opts.persistDebounceMs ?? 50;
811
+ const statusStore = useGraphSyncStatusStore.getState();
812
+ statusStore.setStatus({
813
+ phase: "hydrating",
814
+ storageKey: key,
815
+ isOnline: opts.onlineSource?.getIsOnline() ?? getDefaultOnlineSource().getIsOnline(),
816
+ isSynced: pendingActions.size === 0,
817
+ error: null
818
+ });
819
+ let persistTimer = null;
820
+ const schedulePersist = () => {
821
+ if (persistTimer) clearTimeout(persistTimer);
822
+ persistTimer = setTimeout(() => {
823
+ void persistGraphToStorage({ storage: opts.storage, key });
824
+ }, persistDebounceMs);
825
+ };
826
+ const graphUnsub = useGraphStore.subscribe(() => {
827
+ schedulePersist();
828
+ });
829
+ const actionUnsub = subscribeGraphActionEvents((event) => {
830
+ if (event.type === "enqueued") pendingActions.set(event.record.id, event.record);
831
+ if (event.type === "settled") pendingActions.delete(event.record.id);
832
+ useGraphSyncStatusStore.getState().setStatus({
833
+ pendingActions: pendingActions.size,
834
+ isSynced: pendingActions.size === 0
835
+ });
836
+ schedulePersist();
837
+ });
838
+ const onlineSource = opts.onlineSource ?? getDefaultOnlineSource();
839
+ const onlineUnsub = onlineSource.subscribe((online) => {
840
+ useGraphSyncStatusStore.getState().setStatus({
841
+ isOnline: online,
842
+ phase: online ? "ready" : "offline"
843
+ });
844
+ });
845
+ const ready = (async () => {
846
+ const hydrated = await hydrateGraphFromStorage({ storage: opts.storage, key });
847
+ if (opts.replayPendingActions && hydrated.ok && pendingActions.size > 0) {
848
+ useGraphSyncStatusStore.getState().setStatus({
849
+ phase: "syncing",
850
+ isSynced: false
851
+ });
852
+ for (const action of Array.from(pendingActions.values())) {
853
+ await replayRegisteredGraphAction(action);
854
+ pendingActions.delete(action.id);
855
+ }
856
+ await persistGraphToStorage({ storage: opts.storage, key });
857
+ }
858
+ const online = onlineSource.getIsOnline();
859
+ useGraphSyncStatusStore.getState().setStatus({
860
+ phase: online ? "ready" : "offline",
861
+ isOnline: online,
862
+ isSynced: pendingActions.size === 0,
863
+ pendingActions: pendingActions.size
864
+ });
865
+ })();
866
+ return {
867
+ ready,
868
+ dispose() {
869
+ graphUnsub();
870
+ actionUnsub();
871
+ onlineUnsub();
872
+ if (persistTimer) clearTimeout(persistTimer);
873
+ },
874
+ async persistNow() {
875
+ await persistGraphToStorage({ storage: opts.storage, key });
876
+ },
877
+ hydrate() {
878
+ return hydrateGraphFromStorage({ storage: opts.storage, key });
879
+ },
880
+ getStatus() {
881
+ return useGraphSyncStatusStore.getState().status;
882
+ }
883
+ };
884
+ }
885
+ function cloneGraphSnapshot() {
886
+ const state = useGraphStore.getState();
887
+ return {
888
+ entities: structuredClone(state.entities),
889
+ patches: structuredClone(state.patches),
890
+ entityStates: structuredClone(state.entityStates),
891
+ syncMetadata: structuredClone(state.syncMetadata),
892
+ lists: structuredClone(state.lists)
893
+ };
894
+ }
895
+ function getDefaultOnlineSource() {
896
+ if (typeof window !== "undefined" && typeof window.addEventListener === "function") {
897
+ return {
898
+ getIsOnline: () => window.navigator.onLine,
899
+ subscribe: (listener) => {
900
+ const onlineHandler = () => listener(true);
901
+ const offlineHandler = () => listener(false);
902
+ window.addEventListener("online", onlineHandler);
903
+ window.addEventListener("offline", offlineHandler);
904
+ return () => {
905
+ window.removeEventListener("online", onlineHandler);
906
+ window.removeEventListener("offline", offlineHandler);
907
+ };
908
+ }
909
+ };
910
+ }
911
+ return {
912
+ getIsOnline: () => true,
913
+ subscribe: () => () => {
914
+ }
915
+ };
916
+ }
917
+
187
918
  // src/engine.ts
188
919
  function serializeKey(key) {
189
920
  return JSON.stringify(key, (_, v) => v && typeof v === "object" && !Array.isArray(v) ? Object.fromEntries(Object.entries(v).sort()) : v);
@@ -420,7 +1151,7 @@ function subscriberCountServerSnapshot() {
420
1151
  return 0;
421
1152
  }
422
1153
  function useGraphDevTools() {
423
- const subscriberCount = React5.useSyncExternalStore(
1154
+ const subscriberCount = React6.useSyncExternalStore(
424
1155
  subscribeSubscriberStats,
425
1156
  getActiveSubscriberCount,
426
1157
  subscriberCountServerSnapshot
@@ -429,7 +1160,7 @@ function useGraphDevTools() {
429
1160
  const patches = zustand.useStore(useGraphStore, (state) => state.patches);
430
1161
  const entityStates = zustand.useStore(useGraphStore, (state) => state.entityStates);
431
1162
  const listsState = zustand.useStore(useGraphStore, (state) => state.lists);
432
- const graphPart = React5.useMemo(
1163
+ const graphPart = React6.useMemo(
433
1164
  () => collectGraphDevStats(entities, patches, entityStates, listsState),
434
1165
  [entities, patches, entityStates, listsState]
435
1166
  );
@@ -445,26 +1176,23 @@ function ensureListeners() {
445
1176
  function useEntity(opts) {
446
1177
  const { type, id, staleTime = getEngineOptions().defaultStaleTime, enabled = true } = opts;
447
1178
  ensureListeners();
448
- const fetchRef = React5.useRef(opts.fetch);
1179
+ const fetchRef = React6.useRef(opts.fetch);
449
1180
  fetchRef.current = opts.fetch;
450
- const normalizeRef = React5.useRef(opts.normalize);
1181
+ const normalizeRef = React6.useRef(opts.normalize);
451
1182
  normalizeRef.current = opts.normalize;
452
1183
  const data = zustand.useStore(useGraphStore, shallow.useShallow((state) => {
453
1184
  if (!id) return null;
454
- const base = state.entities[type]?.[id];
455
- if (!base) return null;
456
- const patch = state.patches[type]?.[id];
457
- return patch ? { ...base, ...patch } : base;
1185
+ return state.readEntitySnapshot(type, id);
458
1186
  }));
459
- const entityState = zustand.useStore(useGraphStore, React5.useCallback(
1187
+ const entityState = zustand.useStore(useGraphStore, React6.useCallback(
460
1188
  (state) => state.entityStates[`${type}:${id}`] ?? EMPTY_ENTITY_STATE,
461
1189
  [type, id]
462
1190
  ));
463
- const doFetch = React5.useCallback(() => {
1191
+ const doFetch = React6.useCallback(() => {
464
1192
  if (!id || !enabled) return;
465
1193
  fetchEntity({ type, id, fetch: fetchRef.current, normalize: normalizeRef.current }, getEngineOptions());
466
1194
  }, [id, enabled, type]);
467
- React5.useEffect(() => {
1195
+ React6.useEffect(() => {
468
1196
  if (!id || !enabled) return;
469
1197
  const token = registerSubscriber(`${type}:${id}`);
470
1198
  const state = useGraphStore.getState();
@@ -474,7 +1202,7 @@ function useEntity(opts) {
474
1202
  if (!hasData || isStale) doFetch();
475
1203
  return () => unregisterSubscriber(`${type}:${id}`, token);
476
1204
  }, [id, type, enabled, staleTime, doFetch]);
477
- React5.useEffect(() => {
1205
+ React6.useEffect(() => {
478
1206
  if (entityState.stale && id && enabled && !entityState.isFetching) doFetch();
479
1207
  }, [entityState.stale, id, enabled, entityState.isFetching, doFetch]);
480
1208
  return { data, isLoading: !data && entityState.isFetching, isFetching: entityState.isFetching, error: entityState.error, isStale: entityState.stale, refetch: doFetch };
@@ -482,49 +1210,44 @@ function useEntity(opts) {
482
1210
  function useEntityList(opts) {
483
1211
  const { type, queryKey, staleTime = getEngineOptions().defaultStaleTime, enabled = true, mode = "replace" } = opts;
484
1212
  ensureListeners();
485
- const key = React5.useMemo(() => serializeKey(queryKey), [queryKey]);
486
- const fetchRef = React5.useRef(opts.fetch);
1213
+ const key = React6.useMemo(() => serializeKey(queryKey), [queryKey]);
1214
+ const fetchRef = React6.useRef(opts.fetch);
487
1215
  fetchRef.current = opts.fetch;
488
- const normalizeRef = React5.useRef(opts.normalize);
1216
+ const normalizeRef = React6.useRef(opts.normalize);
489
1217
  normalizeRef.current = opts.normalize;
490
- const listState = zustand.useStore(useGraphStore, React5.useCallback((state) => state.lists[key] ?? EMPTY_LIST_STATE, [key]));
1218
+ const listState = zustand.useStore(useGraphStore, React6.useCallback((state) => state.lists[key] ?? EMPTY_LIST_STATE, [key]));
491
1219
  const items = zustand.useStore(
492
1220
  useGraphStore,
493
1221
  shallow.useShallow((state) => {
494
1222
  const ids = state.lists[key]?.ids ?? EMPTY_IDS;
495
- return ids.map((id) => {
496
- const base = state.entities[type]?.[id];
497
- if (!base) return null;
498
- const patch = state.patches[type]?.[id];
499
- return patch ? { ...base, ...patch } : base;
500
- }).filter((x) => x !== null);
1223
+ return ids.map((id) => state.readEntitySnapshot(type, id)).filter((x) => x !== null);
501
1224
  })
502
1225
  );
503
- const doFetch = React5.useCallback((params = {}) => {
1226
+ const doFetch = React6.useCallback((params = {}) => {
504
1227
  if (!enabled) return;
505
1228
  fetchList({ type, queryKey, mode, fetch: fetchRef.current, normalize: normalizeRef.current }, params, getEngineOptions(), false);
506
1229
  }, [enabled, type, queryKey, mode]);
507
- const fetchNextPage = React5.useCallback(() => {
1230
+ const fetchNextPage = React6.useCallback(() => {
508
1231
  if (!listState.hasNextPage || listState.isFetchingMore || !enabled) return;
509
1232
  fetchList({ type, queryKey, mode, fetch: fetchRef.current, normalize: normalizeRef.current }, { cursor: listState.nextCursor ?? void 0, page: (listState.currentPage ?? 0) + 1, pageSize: listState.pageSize ?? void 0 }, getEngineOptions(), true);
510
1233
  }, [listState.hasNextPage, listState.isFetchingMore, listState.nextCursor, listState.currentPage, listState.pageSize, enabled, type, queryKey, mode]);
511
- React5.useEffect(() => {
1234
+ React6.useEffect(() => {
512
1235
  if (!enabled) return;
513
1236
  const state = useGraphStore.getState();
514
1237
  const existing = state.lists[key];
515
1238
  const isStale = !existing?.lastFetched || existing.stale || Date.now() - (existing.lastFetched ?? 0) > staleTime;
516
1239
  if (!existing || isStale) doFetch({ page: 1, pageSize: listState.pageSize ?? void 0 });
517
1240
  }, [key, enabled, staleTime, doFetch, listState.pageSize]);
518
- React5.useEffect(() => {
1241
+ React6.useEffect(() => {
519
1242
  if (listState.stale && enabled && !listState.isFetching) doFetch();
520
1243
  }, [listState.stale, enabled, listState.isFetching, doFetch]);
521
1244
  return { items, ids: listState.ids, isLoading: listState.ids.length === 0 && listState.isFetching, isFetching: listState.isFetching, isFetchingMore: listState.isFetchingMore, error: listState.error, hasNextPage: listState.hasNextPage, hasPrevPage: listState.hasPrevPage, total: listState.total, currentPage: listState.currentPage, fetchNextPage, refetch: doFetch };
522
1245
  }
523
1246
  function useEntityMutation(opts) {
524
- const [state, setState] = React5.useState({ isPending: false, isSuccess: false, isError: false, error: null });
525
- const optsRef = React5.useRef(opts);
1247
+ const [state, setState] = React6.useState({ isPending: false, isSuccess: false, isError: false, error: null });
1248
+ const optsRef = React6.useRef(opts);
526
1249
  optsRef.current = opts;
527
- const mutate = React5.useCallback(async (input) => {
1250
+ const mutate = React6.useCallback(async (input) => {
528
1251
  const { type, mutate: apiFn, normalize, optimistic, invalidateLists, invalidateEntities, onSuccess, onError } = optsRef.current;
529
1252
  setState({ isPending: true, isSuccess: false, isError: false, error: null });
530
1253
  let rollback = null;
@@ -534,18 +1257,28 @@ function useEntityMutation(opts) {
534
1257
  const { id, patch } = opt;
535
1258
  const store = useGraphStore.getState();
536
1259
  const previous = { ...store.patches[type]?.[id] };
1260
+ const previousSync = store.syncMetadata[`${type}:${id}`];
537
1261
  store.patchEntity(type, id, patch);
538
- rollback = () => Object.keys(previous).length > 0 ? useGraphStore.getState().patchEntity(type, id, previous) : useGraphStore.getState().clearPatch(type, id);
1262
+ store.setEntitySyncMetadata(type, id, { synced: false, origin: "optimistic", updatedAt: Date.now() });
1263
+ rollback = () => {
1264
+ const currentStore = useGraphStore.getState();
1265
+ if (Object.keys(previous).length > 0) currentStore.patchEntity(type, id, previous);
1266
+ else currentStore.clearPatch(type, id);
1267
+ if (previousSync) currentStore.setEntitySyncMetadata(type, id, previousSync);
1268
+ else currentStore.clearEntitySyncMetadata(type, id);
1269
+ };
539
1270
  }
540
1271
  }
541
1272
  try {
542
1273
  const result = await apiFn(input);
543
1274
  if (normalize) {
544
1275
  const { id, data } = normalize(result, input);
545
- useGraphStore.getState().upsertEntity(type, id, data);
1276
+ const store = useGraphStore.getState();
1277
+ store.upsertEntity(type, id, data);
1278
+ store.setEntitySyncMetadata(type, id, { synced: true, origin: "server", updatedAt: Date.now() });
546
1279
  if (optimistic) {
547
1280
  const opt = optimistic(input);
548
- if (opt) useGraphStore.getState().clearPatch(type, opt.id);
1281
+ if (opt) store.clearPatch(type, opt.id);
549
1282
  }
550
1283
  }
551
1284
  if (invalidateLists) for (const k of invalidateLists) useGraphStore.getState().invalidateLists(k);
@@ -561,23 +1294,23 @@ function useEntityMutation(opts) {
561
1294
  return null;
562
1295
  }
563
1296
  }, []);
564
- const trigger = React5.useCallback((input) => {
1297
+ const trigger = React6.useCallback((input) => {
565
1298
  void mutate(input);
566
1299
  }, [mutate]);
567
- const reset = React5.useCallback(() => setState({ isPending: false, isSuccess: false, isError: false, error: null }), []);
1300
+ const reset = React6.useCallback(() => setState({ isPending: false, isSuccess: false, isError: false, error: null }), []);
568
1301
  return { mutate, trigger, reset, state };
569
1302
  }
570
1303
  function useEntityAugment(type, id) {
571
- const patch = zustand.useStore(useGraphStore, React5.useCallback((state) => id ? state.patches[type]?.[id] ?? null : null, [type, id]));
572
- const augment = React5.useCallback((fields) => {
1304
+ const patch = zustand.useStore(useGraphStore, React6.useCallback((state) => id ? state.patches[type]?.[id] ?? null : null, [type, id]));
1305
+ const augment = React6.useCallback((fields) => {
573
1306
  if (!id) return;
574
1307
  useGraphStore.getState().patchEntity(type, id, fields);
575
1308
  }, [type, id]);
576
- const unaugment = React5.useCallback((keys) => {
1309
+ const unaugment = React6.useCallback((keys) => {
577
1310
  if (!id) return;
578
1311
  useGraphStore.getState().unpatchEntity(type, id, keys);
579
1312
  }, [type, id]);
580
- const clear = React5.useCallback(() => {
1313
+ const clear = React6.useCallback(() => {
581
1314
  if (!id) return;
582
1315
  useGraphStore.getState().clearPatch(type, id);
583
1316
  }, [type, id]);
@@ -670,7 +1403,7 @@ function useSuspenseEntity(opts) {
670
1403
  };
671
1404
  }
672
1405
  function useSuspenseEntityList(opts) {
673
- const key = React5.useMemo(() => serializeKey(opts.queryKey), [opts.queryKey]);
1406
+ const key = React6.useMemo(() => serializeKey(opts.queryKey), [opts.queryKey]);
674
1407
  const result = useEntityList(opts);
675
1408
  if (result.isLoading) throw getListSuspensePromise(key);
676
1409
  if (result.error != null && result.items.length === 0) {
@@ -1008,17 +1741,17 @@ function hasCustomPredicates(filter) {
1008
1741
  var EMPTY_ENTITY_BUCKET = {};
1009
1742
  function useEntityView(opts) {
1010
1743
  const { type, baseQueryKey, mode: forcedMode, remoteFetch, remoteDebounce = 300, staleTime = getEngineOptions().defaultStaleTime, enabled = true, initialIds, initialTotal } = opts;
1011
- const optsRef = React5.useRef(opts);
1744
+ const optsRef = React6.useRef(opts);
1012
1745
  optsRef.current = opts;
1013
- const [liveView, setLiveView] = React5.useState(opts.view);
1014
- const liveViewRef = React5.useRef(liveView);
1746
+ const [liveView, setLiveView] = React6.useState(opts.view);
1747
+ const liveViewRef = React6.useRef(liveView);
1015
1748
  liveViewRef.current = liveView;
1016
- const [isRemoteFetching, setIsRemoteFetching] = React5.useState(false);
1017
- const [remoteError, setRemoteError] = React5.useState(null);
1018
- const [remoteResultKey, setRemoteResultKey] = React5.useState(null);
1019
- const debounceTimer = React5.useRef(null);
1020
- const baseKey = React5.useMemo(() => serializeKey(baseQueryKey), [baseQueryKey]);
1021
- const seededRef = React5.useRef(false);
1749
+ const [isRemoteFetching, setIsRemoteFetching] = React6.useState(false);
1750
+ const [remoteError, setRemoteError] = React6.useState(null);
1751
+ const [remoteResultKey, setRemoteResultKey] = React6.useState(null);
1752
+ const debounceTimer = React6.useRef(null);
1753
+ const baseKey = React6.useMemo(() => serializeKey(baseQueryKey), [baseQueryKey]);
1754
+ const seededRef = React6.useRef(false);
1022
1755
  if (!seededRef.current && initialIds && initialIds.length > 0) {
1023
1756
  seededRef.current = true;
1024
1757
  const store = useGraphStore.getState();
@@ -1028,14 +1761,14 @@ function useEntityView(opts) {
1028
1761
  }
1029
1762
  const listState = zustand.useStore(
1030
1763
  useGraphStore,
1031
- React5.useCallback((state) => state.lists[baseKey] ?? null, [baseKey])
1764
+ React6.useCallback((state) => state.lists[baseKey] ?? null, [baseKey])
1032
1765
  );
1033
- const remoteListState = zustand.useStore(useGraphStore, React5.useCallback((state) => remoteResultKey ? state.lists[remoteResultKey] ?? null : null, [remoteResultKey]));
1034
- const { isComplete } = React5.useMemo(() => {
1766
+ const remoteListState = zustand.useStore(useGraphStore, React6.useCallback((state) => remoteResultKey ? state.lists[remoteResultKey] ?? null : null, [remoteResultKey]));
1767
+ const { isComplete } = React6.useMemo(() => {
1035
1768
  if (!listState) return { isComplete: false };
1036
1769
  return checkCompleteness(listState.ids.length, listState.total, listState.hasNextPage);
1037
1770
  }, [listState]);
1038
- const completenessMode = React5.useMemo(() => {
1771
+ const completenessMode = React6.useMemo(() => {
1039
1772
  if (forcedMode) return forcedMode;
1040
1773
  if (liveView.filter && hasCustomPredicates(liveView.filter)) return "local";
1041
1774
  if (isComplete) return "local";
@@ -1047,12 +1780,7 @@ function useEntityView(opts) {
1047
1780
  shallow.useShallow((state) => {
1048
1781
  const list = state.lists[baseKey] ?? EMPTY_LIST_STATE;
1049
1782
  const sourceIds = completenessMode !== "remote" && remoteResultKey ? state.lists[remoteResultKey]?.ids ?? EMPTY_IDS : list.ids;
1050
- const getEntity = (id) => {
1051
- const base = state.entities[type]?.[id];
1052
- if (!base) return null;
1053
- const patch = state.patches[type]?.[id];
1054
- return patch ? { ...base, ...patch } : base;
1055
- };
1783
+ const getEntity = (id) => state.readEntitySnapshot(type, id);
1056
1784
  return applyView(
1057
1785
  sourceIds,
1058
1786
  getEntity,
@@ -1065,15 +1793,10 @@ function useEntityView(opts) {
1065
1793
  const items = zustand.useStore(
1066
1794
  useGraphStore,
1067
1795
  shallow.useShallow(
1068
- (state) => localViewIds.map((id) => {
1069
- const base = state.entities[type]?.[id];
1070
- if (!base) return null;
1071
- const patch = state.patches[type]?.[id];
1072
- return patch ? { ...base, ...patch } : base;
1073
- }).filter((item) => item !== null)
1796
+ (state) => localViewIds.map((id) => state.readEntitySnapshot(type, id)).filter((item) => item !== null)
1074
1797
  )
1075
1798
  );
1076
- const fireRemoteFetch = React5.useCallback(async (view, cursor) => {
1799
+ const fireRemoteFetch = React6.useCallback(async (view, cursor) => {
1077
1800
  const { remoteFetch: rf, normalize: norm, baseQueryKey: bqk } = optsRef.current;
1078
1801
  if (!rf) return;
1079
1802
  const params = { rest: toRestParams(view), graphql: toGraphQLVariables(view), sql: toSQLClauses(view), view };
@@ -1097,7 +1820,7 @@ function useEntityView(opts) {
1097
1820
  setIsRemoteFetching(false);
1098
1821
  }
1099
1822
  }, [type]);
1100
- React5.useEffect(() => {
1823
+ React6.useEffect(() => {
1101
1824
  if (!enabled || completenessMode === "local" || !remoteFetch) return;
1102
1825
  const searchQuery = liveView.search?.query ?? "";
1103
1826
  const minChars = liveView.search?.minChars ?? 2;
@@ -1108,14 +1831,14 @@ function useEntityView(opts) {
1108
1831
  if (debounceTimer.current) clearTimeout(debounceTimer.current);
1109
1832
  };
1110
1833
  }, [liveView, completenessMode, enabled, remoteFetch, remoteDebounce, fireRemoteFetch]);
1111
- React5.useEffect(() => {
1834
+ React6.useEffect(() => {
1112
1835
  if (!enabled) return;
1113
1836
  const state = useGraphStore.getState();
1114
1837
  const existing = state.lists[baseKey];
1115
1838
  const isStale = !existing?.lastFetched || existing.stale || Date.now() - (existing.lastFetched ?? 0) > staleTime;
1116
1839
  if (!existing || isStale) fireRemoteFetch(liveViewRef.current);
1117
1840
  }, [baseKey, enabled, staleTime, fireRemoteFetch]);
1118
- React5.useEffect(() => {
1841
+ React6.useEffect(() => {
1119
1842
  const unsub = useGraphStore.subscribe((state) => state.entities[type] ?? EMPTY_ENTITY_BUCKET, (newEntities, prevEntities) => {
1120
1843
  const view = liveViewRef.current;
1121
1844
  const store = useGraphStore.getState();
@@ -1125,17 +1848,11 @@ function useEntityView(opts) {
1125
1848
  const isPresent = id in newEntities;
1126
1849
  if (!isPresent) continue;
1127
1850
  const entity = newEntities[id];
1128
- const patch = store.patches[type]?.[id];
1129
- const merged = patch ? { ...entity, ...patch } : entity;
1851
+ const merged = store.readEntitySnapshot(type, id) ?? entity;
1130
1852
  const matches = (!view.filter || matchesFilter(merged, view.filter)) && (!view.search?.query || matchesSearch(merged, view.search.query, view.search.fields));
1131
1853
  if (matches && !list.ids.includes(id)) {
1132
1854
  if (view.sort && view.sort.length > 0) {
1133
- const idx = findInsertionIndex(merged, list.ids, (eid) => {
1134
- const b = store.entities[type]?.[eid];
1135
- if (!b) return null;
1136
- const p = store.patches[type]?.[eid];
1137
- return p ? { ...b, ...p } : b;
1138
- }, view.sort);
1855
+ const idx = findInsertionIndex(merged, list.ids, (eid) => store.readEntitySnapshot(type, eid), view.sort);
1139
1856
  store.insertIdInList(baseKey, id, idx);
1140
1857
  } else store.insertIdInList(baseKey, id, "start");
1141
1858
  }
@@ -1143,16 +1860,16 @@ function useEntityView(opts) {
1143
1860
  });
1144
1861
  return unsub;
1145
1862
  }, [type, baseKey]);
1146
- const setView = React5.useCallback((partial) => setLiveView((prev) => ({ ...prev, ...partial })), []);
1147
- const setFilter = React5.useCallback((filter) => setLiveView((prev) => ({ ...prev, filter: filter ?? void 0 })), []);
1148
- const setSort = React5.useCallback((sort) => setLiveView((prev) => ({ ...prev, sort: sort ?? void 0 })), []);
1149
- const setSearch = React5.useCallback((query) => setLiveView((prev) => ({ ...prev, search: prev.search ? { ...prev.search, query } : { query, fields: [] } })), []);
1150
- const clearView = React5.useCallback(() => setLiveView({}), []);
1151
- const fetchNextPage = React5.useCallback(() => {
1863
+ const setView = React6.useCallback((partial) => setLiveView((prev) => ({ ...prev, ...partial })), []);
1864
+ const setFilter = React6.useCallback((filter) => setLiveView((prev) => ({ ...prev, filter: filter ?? void 0 })), []);
1865
+ const setSort = React6.useCallback((sort) => setLiveView((prev) => ({ ...prev, sort: sort ?? void 0 })), []);
1866
+ const setSearch = React6.useCallback((query) => setLiveView((prev) => ({ ...prev, search: prev.search ? { ...prev.search, query } : { query, fields: [] } })), []);
1867
+ const clearView = React6.useCallback(() => setLiveView({}), []);
1868
+ const fetchNextPage = React6.useCallback(() => {
1152
1869
  if (completenessMode === "local" || isRemoteFetching) return;
1153
1870
  fireRemoteFetch(liveViewRef.current, remoteListState?.nextCursor ?? void 0);
1154
1871
  }, [completenessMode, isRemoteFetching, remoteListState?.nextCursor, fireRemoteFetch]);
1155
- const refetch = React5.useCallback(() => fireRemoteFetch(liveViewRef.current), [fireRemoteFetch]);
1872
+ const refetch = React6.useCallback(() => fireRemoteFetch(liveViewRef.current), [fireRemoteFetch]);
1156
1873
  const viewTotal = remoteListState?.total ?? (isComplete ? localViewIds.length : listState?.total ?? null);
1157
1874
  return {
1158
1875
  items,
@@ -1178,15 +1895,15 @@ function useEntityView(opts) {
1178
1895
  }
1179
1896
 
1180
1897
  // src/crud/relations.ts
1181
- var schemaRegistry = /* @__PURE__ */ new Map();
1898
+ var schemaRegistry2 = /* @__PURE__ */ new Map();
1182
1899
  function registerSchema(schema) {
1183
- schemaRegistry.set(schema.type, schema);
1900
+ schemaRegistry2.set(schema.type, schema);
1184
1901
  }
1185
1902
  function getSchema(type) {
1186
- return schemaRegistry.get(type) ?? null;
1903
+ return schemaRegistry2.get(type) ?? null;
1187
1904
  }
1188
1905
  function cascadeInvalidation(ctx) {
1189
- const schema = schemaRegistry.get(ctx.type);
1906
+ const schema = schemaRegistry2.get(ctx.type);
1190
1907
  if (!schema) return;
1191
1908
  const store = useGraphStore.getState();
1192
1909
  if (schema.globalListKeys) for (const key of schema.globalListKeys) store.invalidateLists(key);
@@ -1213,7 +1930,7 @@ function cascadeInvalidation(ctx) {
1213
1930
  }
1214
1931
  }
1215
1932
  }
1216
- for (const [, otherSchema] of schemaRegistry) {
1933
+ for (const [, otherSchema] of schemaRegistry2) {
1217
1934
  if (!otherSchema.relations) continue;
1218
1935
  for (const [, rel] of Object.entries(otherSchema.relations)) {
1219
1936
  if (rel.targetType !== ctx.type) continue;
@@ -1222,7 +1939,7 @@ function cascadeInvalidation(ctx) {
1222
1939
  }
1223
1940
  }
1224
1941
  function readRelations(type, entity) {
1225
- const schema = schemaRegistry.get(type);
1942
+ const schema = schemaRegistry2.get(type);
1226
1943
  if (!schema?.relations) return {};
1227
1944
  const store = useGraphStore.getState();
1228
1945
  const result = {};
@@ -1252,15 +1969,15 @@ function readRelations(type, entity) {
1252
1969
  // src/crud/use-entity-crud.ts
1253
1970
  function useEntityCRUD(opts) {
1254
1971
  const { type, listQueryKey, listFetch, normalize, detailFetch, onCreate, onUpdate, onDelete, createDefaults = {}, initialView = {}, selectAfterCreate = true, clearSelectionAfterDelete = true } = opts;
1255
- const optsRef = React5.useRef(opts);
1972
+ const optsRef = React6.useRef(opts);
1256
1973
  optsRef.current = opts;
1257
- const [mode, setMode] = React5.useState("list");
1258
- const [selectedId, setSelectedId] = React5.useState(null);
1259
- const select = React5.useCallback((id) => {
1974
+ const [mode, setMode] = React6.useState("list");
1975
+ const [selectedId, setSelectedId] = React6.useState(null);
1976
+ const select = React6.useCallback((id) => {
1260
1977
  setSelectedId(id);
1261
1978
  setMode(id ? "detail" : "list");
1262
1979
  }, []);
1263
- const openDetail = React5.useCallback((id) => {
1980
+ const openDetail = React6.useCallback((id) => {
1264
1981
  setSelectedId(id);
1265
1982
  setMode("detail");
1266
1983
  }, []);
@@ -1276,28 +1993,25 @@ function useEntityCRUD(opts) {
1276
1993
  normalize: (raw) => raw,
1277
1994
  enabled: !!selectedId
1278
1995
  });
1279
- const relations = React5.useMemo(() => detail ? readRelations(type, detail) : {}, [type, detail]);
1280
- const [editBuffer, setEditBuffer] = React5.useState({});
1281
- const [isSaving, setIsSaving] = React5.useState(false);
1282
- const [saveError, setSaveError] = React5.useState(null);
1283
- React5.useEffect(() => {
1996
+ const relations = React6.useMemo(() => detail ? readRelations(type, detail) : {}, [type, detail]);
1997
+ const [editBuffer, setEditBuffer] = React6.useState({});
1998
+ const [isSaving, setIsSaving] = React6.useState(false);
1999
+ const [saveError, setSaveError] = React6.useState(null);
2000
+ React6.useEffect(() => {
1284
2001
  if (detail) setEditBuffer({ ...detail });
1285
2002
  }, [selectedId]);
1286
- const setField = React5.useCallback((field, value) => setEditBuffer((prev) => ({ ...prev, [field]: value })), []);
1287
- const setFields = React5.useCallback((fields) => setEditBuffer((prev) => ({ ...prev, ...fields })), []);
1288
- const resetBuffer = React5.useCallback(() => {
2003
+ const setField = React6.useCallback((field, value) => setEditBuffer((prev) => setValueAtPath(prev, String(field), value)), []);
2004
+ const setFields = React6.useCallback((fields) => setEditBuffer((prev) => ({ ...prev, ...fields })), []);
2005
+ const resetBuffer = React6.useCallback(() => {
1289
2006
  const current = selectedId ? useGraphStore.getState().readEntity(type, selectedId) : null;
1290
2007
  setEditBuffer(current ? { ...current } : {});
1291
2008
  }, [type, selectedId]);
1292
- const dirty = React5.useMemo(() => {
2009
+ const dirty = React6.useMemo(() => {
1293
2010
  if (!detail) return { changed: /* @__PURE__ */ new Set(), isDirty: false };
1294
- const changed = /* @__PURE__ */ new Set();
1295
- for (const key of Object.keys(editBuffer)) {
1296
- if (JSON.stringify(editBuffer[key]) !== JSON.stringify(detail[key])) changed.add(key);
1297
- }
2011
+ const changed = collectDirtyPaths(editBuffer, detail);
1298
2012
  return { changed, isDirty: changed.size > 0 };
1299
2013
  }, [editBuffer, detail]);
1300
- const startEdit = React5.useCallback((id) => {
2014
+ const startEdit = React6.useCallback((id) => {
1301
2015
  const targetId = id ?? selectedId;
1302
2016
  if (targetId) {
1303
2017
  setSelectedId(targetId);
@@ -1306,32 +2020,40 @@ function useEntityCRUD(opts) {
1306
2020
  }
1307
2021
  setMode("edit");
1308
2022
  }, [selectedId, type]);
1309
- const cancelEdit = React5.useCallback(() => {
2023
+ const cancelEdit = React6.useCallback(() => {
1310
2024
  resetBuffer();
1311
2025
  setMode(selectedId ? "detail" : "list");
1312
2026
  setSaveError(null);
1313
2027
  }, [resetBuffer, selectedId]);
1314
- const applyOptimistic = React5.useCallback(() => {
2028
+ const applyOptimistic = React6.useCallback(() => {
1315
2029
  if (!selectedId) return;
1316
- useGraphStore.getState().patchEntity(type, selectedId, editBuffer);
2030
+ const store = useGraphStore.getState();
2031
+ store.patchEntity(type, selectedId, editBuffer);
2032
+ store.setEntitySyncMetadata(type, selectedId, { synced: false, origin: "optimistic", updatedAt: Date.now() });
1317
2033
  }, [type, selectedId, editBuffer]);
1318
- const save = React5.useCallback(async () => {
2034
+ const save = React6.useCallback(async () => {
1319
2035
  if (!selectedId || !onUpdate) return null;
1320
2036
  setIsSaving(true);
1321
2037
  setSaveError(null);
1322
- const previous = useGraphStore.getState().readEntity(type, selectedId);
1323
- useGraphStore.getState().upsertEntity(type, selectedId, editBuffer);
2038
+ const store = useGraphStore.getState();
2039
+ const previous = store.readEntity(type, selectedId);
2040
+ const previousSync = store.syncMetadata[`${type}:${selectedId}`];
2041
+ store.upsertEntity(type, selectedId, editBuffer);
2042
+ store.setEntitySyncMetadata(type, selectedId, { synced: false, origin: "optimistic", updatedAt: Date.now() });
1324
2043
  try {
1325
2044
  const result = await onUpdate(selectedId, editBuffer);
1326
2045
  const { id, data } = normalize(result);
1327
- useGraphStore.getState().replaceEntity(type, id, data);
1328
- useGraphStore.getState().clearPatch(type, id);
2046
+ store.replaceEntity(type, id, data);
2047
+ store.clearPatch(type, id);
2048
+ store.setEntitySyncMetadata(type, id, { synced: true, origin: "server", updatedAt: Date.now() });
1329
2049
  cascadeInvalidation({ type, id: selectedId, previous, next: data, op: "update" });
1330
2050
  setMode("detail");
1331
2051
  optsRef.current.onUpdateSuccess?.(result);
1332
2052
  return result;
1333
2053
  } catch (err) {
1334
- if (previous) useGraphStore.getState().replaceEntity(type, selectedId, previous);
2054
+ if (previous) store.replaceEntity(type, selectedId, previous);
2055
+ if (previousSync) store.setEntitySyncMetadata(type, selectedId, previousSync);
2056
+ else store.clearEntitySyncMetadata(type, selectedId);
1335
2057
  const error = err instanceof Error ? err : new Error(String(err));
1336
2058
  setSaveError(error.message);
1337
2059
  optsRef.current.onError?.("update", error);
@@ -1340,37 +2062,39 @@ function useEntityCRUD(opts) {
1340
2062
  setIsSaving(false);
1341
2063
  }
1342
2064
  }, [selectedId, type, editBuffer, normalize]);
1343
- const [createBuffer, setCreateBuffer] = React5.useState({ ...createDefaults });
1344
- const [isCreating, setIsCreating] = React5.useState(false);
1345
- const [createError, setCreateError] = React5.useState(null);
1346
- const setCreateField = React5.useCallback((field, value) => setCreateBuffer((prev) => ({ ...prev, [field]: value })), []);
1347
- const setCreateFields = React5.useCallback((fields) => setCreateBuffer((prev) => ({ ...prev, ...fields })), []);
1348
- const resetCreateBuffer = React5.useCallback(() => setCreateBuffer({ ...optsRef.current.createDefaults ?? {} }), []);
1349
- const startCreate = React5.useCallback(() => {
2065
+ const [createBuffer, setCreateBuffer] = React6.useState({ ...createDefaults });
2066
+ const [isCreating, setIsCreating] = React6.useState(false);
2067
+ const [createError, setCreateError] = React6.useState(null);
2068
+ const setCreateField = React6.useCallback((field, value) => setCreateBuffer((prev) => setValueAtPath(prev, String(field), value)), []);
2069
+ const setCreateFields = React6.useCallback((fields) => setCreateBuffer((prev) => ({ ...prev, ...fields })), []);
2070
+ const resetCreateBuffer = React6.useCallback(() => setCreateBuffer({ ...optsRef.current.createDefaults ?? {} }), []);
2071
+ const startCreate = React6.useCallback(() => {
1350
2072
  resetCreateBuffer();
1351
2073
  setCreateError(null);
1352
2074
  setMode("create");
1353
2075
  }, [resetCreateBuffer]);
1354
- const cancelCreate = React5.useCallback(() => {
2076
+ const cancelCreate = React6.useCallback(() => {
1355
2077
  resetCreateBuffer();
1356
2078
  setMode("list");
1357
2079
  setCreateError(null);
1358
2080
  }, [resetCreateBuffer]);
1359
- const create2 = React5.useCallback(async () => {
2081
+ const create3 = React6.useCallback(async () => {
1360
2082
  if (!onCreate) return null;
1361
2083
  setIsCreating(true);
1362
2084
  setCreateError(null);
1363
2085
  const tempId = `__temp__${Date.now()}`;
1364
2086
  const optimisticData = { ...createBuffer, id: tempId, _optimistic: true };
1365
- useGraphStore.getState().upsertEntity(type, tempId, optimisticData);
1366
- useGraphStore.getState().insertIdInList(serializeKey(listQueryKey), tempId, "start");
2087
+ const store = useGraphStore.getState();
2088
+ store.upsertEntity(type, tempId, optimisticData);
2089
+ store.setEntitySyncMetadata(type, tempId, { synced: false, origin: "optimistic", updatedAt: Date.now() });
2090
+ store.insertIdInList(serializeKey(listQueryKey), tempId, "start");
1367
2091
  try {
1368
2092
  const result = await onCreate(createBuffer);
1369
2093
  const { id: realId, data } = normalize(result);
1370
- useGraphStore.getState().removeEntity(type, tempId);
1371
- useGraphStore.getState().upsertEntity(type, realId, data);
1372
- useGraphStore.getState().setEntityFetched(type, realId);
1373
- const store = useGraphStore.getState();
2094
+ store.removeEntity(type, tempId);
2095
+ store.upsertEntity(type, realId, data);
2096
+ store.setEntityFetched(type, realId);
2097
+ store.setEntitySyncMetadata(type, realId, { synced: true, origin: "server", updatedAt: Date.now() });
1374
2098
  for (const key of Object.keys(store.lists)) {
1375
2099
  const list2 = store.lists[key];
1376
2100
  const idx = list2.ids.indexOf(tempId);
@@ -1388,8 +2112,8 @@ function useEntityCRUD(opts) {
1388
2112
  optsRef.current.onCreateSuccess?.(result);
1389
2113
  return result;
1390
2114
  } catch (err) {
1391
- useGraphStore.getState().removeEntity(type, tempId);
1392
- useGraphStore.getState().removeIdFromAllLists(type, tempId);
2115
+ store.removeEntity(type, tempId);
2116
+ store.removeIdFromAllLists(type, tempId);
1393
2117
  const error = err instanceof Error ? err : new Error(String(err));
1394
2118
  setCreateError(error.message);
1395
2119
  optsRef.current.onError?.("create", error);
@@ -1398,9 +2122,9 @@ function useEntityCRUD(opts) {
1398
2122
  setIsCreating(false);
1399
2123
  }
1400
2124
  }, [type, createBuffer, normalize, listQueryKey, selectAfterCreate, resetCreateBuffer]);
1401
- const [isDeleting, setIsDeleting] = React5.useState(false);
1402
- const [deleteError, setDeleteError] = React5.useState(null);
1403
- const deleteEntity = React5.useCallback(async (id) => {
2125
+ const [isDeleting, setIsDeleting] = React6.useState(false);
2126
+ const [deleteError, setDeleteError] = React6.useState(null);
2127
+ const deleteEntity = React6.useCallback(async (id) => {
1404
2128
  const targetId = id ?? selectedId;
1405
2129
  if (!targetId || !onDelete) return;
1406
2130
  setIsDeleting(true);
@@ -1428,7 +2152,7 @@ function useEntityCRUD(opts) {
1428
2152
  setIsDeleting(false);
1429
2153
  }
1430
2154
  }, [type, selectedId, listQueryKey, clearSelectionAfterDelete]);
1431
- return { mode, setMode, list, selectedId, select, openDetail, detail: detail ?? null, detailIsLoading, detailError: detailError ?? null, relations, editBuffer, setField, setFields, resetBuffer, dirty, startEdit, cancelEdit, save, isSaving, saveError, applyOptimistic, createBuffer, setCreateField, setCreateFields, resetCreateBuffer, startCreate, cancelCreate, create: create2, isCreating, createError, deleteEntity, isDeleting, deleteError, isEditing: mode === "edit" || mode === "create" };
2155
+ return { mode, setMode, list, selectedId, select, openDetail, detail: detail ?? null, detailIsLoading, detailError: detailError ?? null, relations, editBuffer, setField, setFields, resetBuffer, dirty, startEdit, cancelEdit, save, isSaving, saveError, applyOptimistic, createBuffer, setCreateField, setCreateFields, resetCreateBuffer, startCreate, cancelCreate, create: create3, isCreating, createError, deleteEntity, isDeleting, deleteError, isEditing: mode === "edit" || mode === "create" };
1432
2156
  }
1433
2157
 
1434
2158
  // src/adapters/realtime-manager.ts
@@ -2059,8 +2783,8 @@ function createElectricAdapter(opts) {
2059
2783
  };
2060
2784
  }
2061
2785
  function useLocalFirst(adapter) {
2062
- const [isSynced, setIsSynced] = React5.useState(adapter.isSynced());
2063
- React5.useEffect(() => {
2786
+ const [isSynced, setIsSynced] = React6.useState(adapter.isSynced());
2787
+ React6.useEffect(() => {
2064
2788
  const u1 = adapter.onSyncComplete(() => setIsSynced(true));
2065
2789
  const u2 = getRealtimeManager().register(adapter, []);
2066
2790
  return () => {
@@ -2068,15 +2792,15 @@ function useLocalFirst(adapter) {
2068
2792
  u2();
2069
2793
  };
2070
2794
  }, [adapter]);
2071
- const query = React5.useCallback(async (sql, params) => (await adapter.query(sql, params)).rows, [adapter]);
2072
- const execute = React5.useCallback((sql, params) => adapter.execute(sql, params), [adapter]);
2795
+ const query = React6.useCallback(async (sql, params) => (await adapter.query(sql, params)).rows, [adapter]);
2796
+ const execute = React6.useCallback((sql, params) => adapter.execute(sql, params), [adapter]);
2073
2797
  return { isSynced, query, execute };
2074
2798
  }
2075
2799
  function usePGliteQuery(opts) {
2076
2800
  const { adapter, type, sql, params, idColumn = "id", normalize, deps = [] } = opts;
2077
- const [isLoading, setIsLoading] = React5.useState(true);
2078
- const [error, setError] = React5.useState(null);
2079
- React5.useEffect(() => {
2801
+ const [isLoading, setIsLoading] = React6.useState(true);
2802
+ const [error, setError] = React6.useState(null);
2803
+ React6.useEffect(() => {
2080
2804
  let cancelled = false;
2081
2805
  setIsLoading(true);
2082
2806
  adapter.query(sql, params).then((r) => {
@@ -2189,20 +2913,17 @@ function createGQLClient(cfg) {
2189
2913
  }
2190
2914
  function useGQLEntity(opts) {
2191
2915
  const { type, id, staleTime = getEngineOptions().defaultStaleTime, enabled = true } = opts;
2192
- const optsRef = React5.useRef(opts);
2916
+ const optsRef = React6.useRef(opts);
2193
2917
  optsRef.current = opts;
2194
2918
  const data = zustand.useStore(useGraphStore, shallow.useShallow((s) => {
2195
2919
  if (!id) return null;
2196
- const base = s.entities[type]?.[id];
2197
- if (!base) return null;
2198
- const patch = s.patches[type]?.[id];
2199
- return patch ? { ...base, ...patch } : base;
2920
+ return s.readEntitySnapshot(type, id);
2200
2921
  }));
2201
- const entityState = zustand.useStore(useGraphStore, React5.useCallback(
2922
+ const entityState = zustand.useStore(useGraphStore, React6.useCallback(
2202
2923
  (s) => s.entityStates[`${type}:${id}`] ?? EMPTY_ENTITY_STATE,
2203
2924
  [type, id]
2204
2925
  ));
2205
- const doFetch = React5.useCallback(() => {
2926
+ const doFetch = React6.useCallback(() => {
2206
2927
  if (!id || !enabled) return;
2207
2928
  const { client, document: document2, variables, descriptor, sideDescriptors, onSuccess, onError } = optsRef.current;
2208
2929
  useGraphStore.getState().setEntityFetching(type, id, true);
@@ -2219,7 +2940,7 @@ function useGQLEntity(opts) {
2219
2940
  onError?.(e);
2220
2941
  });
2221
2942
  }, [id, type, enabled]);
2222
- React5.useEffect(() => {
2943
+ React6.useEffect(() => {
2223
2944
  if (!id || !enabled) return;
2224
2945
  const token = registerSubscriber(`${type}:${id}`);
2225
2946
  const s = useGraphStore.getState();
@@ -2227,30 +2948,25 @@ function useGQLEntity(opts) {
2227
2948
  if (!s.entities[type]?.[id] || !ex?.lastFetched || ex.stale || Date.now() - (ex.lastFetched ?? 0) > staleTime) doFetch();
2228
2949
  return () => unregisterSubscriber(`${type}:${id}`, token);
2229
2950
  }, [id, type, enabled, staleTime, doFetch]);
2230
- React5.useEffect(() => {
2951
+ React6.useEffect(() => {
2231
2952
  if (entityState.stale && id && enabled && !entityState.isFetching) doFetch();
2232
2953
  }, [entityState.stale, id, enabled, entityState.isFetching, doFetch]);
2233
2954
  return { data, isLoading: !data && entityState.isFetching, isFetching: entityState.isFetching, error: entityState.error, isStale: entityState.stale, refetch: doFetch };
2234
2955
  }
2235
2956
  function useGQLList(opts) {
2236
2957
  const { type, queryKey, staleTime = getEngineOptions().defaultStaleTime, enabled = true, mode = "replace" } = opts;
2237
- const optsRef = React5.useRef(opts);
2958
+ const optsRef = React6.useRef(opts);
2238
2959
  optsRef.current = opts;
2239
- const key = React5.useMemo(() => serializeKey(queryKey), [queryKey]);
2240
- const listState = zustand.useStore(useGraphStore, React5.useCallback((s) => s.lists[key] ?? EMPTY_LIST_STATE, [key]));
2960
+ const key = React6.useMemo(() => serializeKey(queryKey), [queryKey]);
2961
+ const listState = zustand.useStore(useGraphStore, React6.useCallback((s) => s.lists[key] ?? EMPTY_LIST_STATE, [key]));
2241
2962
  const items = zustand.useStore(
2242
2963
  useGraphStore,
2243
2964
  shallow.useShallow((s) => {
2244
2965
  const ids = s.lists[key]?.ids ?? EMPTY_IDS;
2245
- return ids.map((id) => {
2246
- const base = s.entities[type]?.[id];
2247
- if (!base) return null;
2248
- const p = s.patches[type]?.[id];
2249
- return p ? { ...base, ...p } : base;
2250
- }).filter((x) => x !== null);
2966
+ return ids.map((id) => s.readEntitySnapshot(type, id)).filter((x) => x !== null);
2251
2967
  })
2252
2968
  );
2253
- const doFetch = React5.useCallback((cursor, append = false) => {
2969
+ const doFetch = React6.useCallback((cursor, append = false) => {
2254
2970
  if (!enabled) return;
2255
2971
  const { client, document: document2, variables, descriptor, sideDescriptors, getItems, getPagination } = optsRef.current;
2256
2972
  const store = useGraphStore.getState();
@@ -2273,25 +2989,25 @@ function useGQLList(opts) {
2273
2989
  else useGraphStore.getState().setListResult(key, ids, meta);
2274
2990
  }).catch((e) => useGraphStore.getState().setListError(key, e.message));
2275
2991
  }, [key, enabled, mode]);
2276
- React5.useEffect(() => {
2992
+ React6.useEffect(() => {
2277
2993
  if (!enabled) return;
2278
2994
  const ex = useGraphStore.getState().lists[key];
2279
2995
  if (!ex || ex.stale || !ex.lastFetched || Date.now() - ex.lastFetched > staleTime) doFetch();
2280
2996
  }, [key, enabled, staleTime, doFetch]);
2281
- React5.useEffect(() => {
2997
+ React6.useEffect(() => {
2282
2998
  if (listState.stale && enabled && !listState.isFetching) doFetch();
2283
2999
  }, [listState.stale, enabled, listState.isFetching, doFetch]);
2284
- const fetchNextPage = React5.useCallback(() => {
3000
+ const fetchNextPage = React6.useCallback(() => {
2285
3001
  if (!listState.hasNextPage || listState.isFetchingMore) return;
2286
3002
  doFetch(listState.nextCursor ?? void 0, true);
2287
3003
  }, [listState.hasNextPage, listState.isFetchingMore, listState.nextCursor, doFetch]);
2288
3004
  return { items, ids: listState.ids, isLoading: listState.ids.length === 0 && listState.isFetching, isFetching: listState.isFetching, isFetchingMore: listState.isFetchingMore, error: listState.error, hasNextPage: listState.hasNextPage, total: listState.total, currentPage: listState.currentPage, fetchNextPage, refetch: () => doFetch() };
2289
3005
  }
2290
3006
  function useGQLMutation(opts) {
2291
- const optsRef = React5.useRef(opts);
3007
+ const optsRef = React6.useRef(opts);
2292
3008
  optsRef.current = opts;
2293
- const [state, setState] = React5.useState({ isPending: false, isSuccess: false, isError: false, error: null });
2294
- const mutate = React5.useCallback(async (variables) => {
3009
+ const [state, setState] = React6.useState({ isPending: false, isSuccess: false, isError: false, error: null });
3010
+ const mutate = React6.useCallback(async (variables) => {
2295
3011
  const { client, document: document2, descriptors, optimistic, invalidateLists, onSuccess, onError } = optsRef.current;
2296
3012
  setState({ isPending: true, isSuccess: false, isError: false, error: null });
2297
3013
  try {
@@ -2307,17 +3023,17 @@ function useGQLMutation(opts) {
2307
3023
  return null;
2308
3024
  }
2309
3025
  }, []);
2310
- const trigger = React5.useCallback((v) => {
3026
+ const trigger = React6.useCallback((v) => {
2311
3027
  void mutate(v);
2312
3028
  }, [mutate]);
2313
3029
  return { mutate, trigger, state };
2314
3030
  }
2315
3031
  function useGQLSubscription(opts) {
2316
3032
  const { document: document2, variables, enabled = true } = opts;
2317
- const [status, setStatus] = React5.useState({ connected: false, error: null });
2318
- const optsRef = React5.useRef(opts);
3033
+ const [status, setStatus] = React6.useState({ connected: false, error: null });
3034
+ const optsRef = React6.useRef(opts);
2319
3035
  optsRef.current = opts;
2320
- React5.useEffect(() => {
3036
+ React6.useEffect(() => {
2321
3037
  const { client, wsClient, descriptors, onData, onError } = optsRef.current;
2322
3038
  if (!enabled) return;
2323
3039
  const unsub = client.subscribe({ document: document2, variables, descriptors, wsClient, onData: (d) => {
@@ -2336,7 +3052,7 @@ function cn(...inputs) {
2336
3052
  return tailwindMerge.twMerge(clsx.clsx(inputs));
2337
3053
  }
2338
3054
  function InlineCellEditor({ initialValue, onCommit, onCancel, className }) {
2339
- const [value, setValue] = React5.useState(initialValue);
3055
+ const [value, setValue] = React6.useState(initialValue);
2340
3056
  return /* @__PURE__ */ jsxRuntime.jsx(
2341
3057
  "input",
2342
3058
  {
@@ -2366,22 +3082,22 @@ function InlineCellEditor({ initialValue, onCommit, onCancel, className }) {
2366
3082
  }
2367
3083
  function EntityTable({ viewResult, columns, getRowId = (r) => String(r.id), selectedId, onRowClick, onCellEdit, onBulkAction, paginationMode = "loadMore", pageSize = 50, searchPlaceholder = "Search\u2026", searchFields, toolbarChildren, showToolbar = true, emptyState, className }) {
2368
3084
  const { items, isLoading, isFetching, isRemoteFetching, isShowingLocalPending, hasNextPage, fetchNextPage, isFetchingMore, viewTotal, setSort, setSearch, refetch } = viewResult;
2369
- const [sorting, setSorting] = React5.useState([]);
2370
- const [rowSelection, setRowSelection] = React5.useState({});
2371
- const [colVis, setColVis] = React5.useState({});
2372
- const [search, setSearchLocal] = React5.useState("");
2373
- const [editingCell, setEditingCell] = React5.useState(null);
2374
- const [page, setPage] = React5.useState(1);
2375
- const handleSort = React5.useCallback((updater) => {
3085
+ const [sorting, setSorting] = React6.useState([]);
3086
+ const [rowSelection, setRowSelection] = React6.useState({});
3087
+ const [colVis, setColVis] = React6.useState({});
3088
+ const [search, setSearchLocal] = React6.useState("");
3089
+ const [editingCell, setEditingCell] = React6.useState(null);
3090
+ const [page, setPage] = React6.useState(1);
3091
+ const handleSort = React6.useCallback((updater) => {
2376
3092
  const next = typeof updater === "function" ? updater(sorting) : updater;
2377
3093
  setSorting(next);
2378
3094
  setSort(next.length ? next.map((s) => ({ field: s.id, direction: s.desc ? "desc" : "asc" })) : null);
2379
3095
  }, [sorting, setSort]);
2380
- const handleSearch = React5.useCallback((v) => {
3096
+ const handleSearch = React6.useCallback((v) => {
2381
3097
  setSearchLocal(v);
2382
3098
  setSearch(v);
2383
3099
  }, [setSearch]);
2384
- const pagedItems = React5.useMemo(() => paginationMode === "pages" ? items.slice((page - 1) * pageSize, page * pageSize) : items, [items, paginationMode, page, pageSize]);
3100
+ const pagedItems = React6.useMemo(() => paginationMode === "pages" ? items.slice((page - 1) * pageSize, page * pageSize) : items, [items, paginationMode, page, pageSize]);
2385
3101
  const totalPages = Math.ceil(items.length / pageSize);
2386
3102
  const table = reactTable.useReactTable({
2387
3103
  data: pagedItems,
@@ -2484,7 +3200,7 @@ function EntityTable({ viewResult, columns, getRowId = (r) => String(r.id), sele
2484
3200
  ] });
2485
3201
  }
2486
3202
  function Sheet({ open, onClose, title, subtitle, children, footer, width = "w-[480px]" }) {
2487
- React5__default.default.useEffect(() => {
3203
+ React6__default.default.useEffect(() => {
2488
3204
  const h = (e) => {
2489
3205
  if (e.key === "Escape") onClose();
2490
3206
  };
@@ -2520,6 +3236,8 @@ function FieldControl({ descriptor, value, onChange, entity, readonly }) {
2520
3236
  return /* @__PURE__ */ jsxRuntime.jsx("input", { type: "number", value: String(value ?? ""), onChange: (e) => onChange(e.target.valueAsNumber), placeholder: descriptor.placeholder, className: base });
2521
3237
  case "textarea":
2522
3238
  return /* @__PURE__ */ jsxRuntime.jsx("textarea", { value: String(value ?? ""), onChange: (e) => onChange(e.target.value), placeholder: descriptor.placeholder, className: "w-full min-h-[80px] rounded-md border bg-muted/50 px-3 py-2 text-sm resize-none focus:outline-none focus:ring-1 focus:ring-ring transition-colors" });
3239
+ case "markdown":
3240
+ return /* @__PURE__ */ jsxRuntime.jsx(MarkdownFieldEditor, { value: String(value ?? ""), onChange: (nextValue) => onChange(nextValue), placeholder: descriptor.placeholder });
2523
3241
  case "date":
2524
3242
  return /* @__PURE__ */ jsxRuntime.jsx("input", { type: "date", value: value ? new Date(value).toISOString().split("T")[0] : "", onChange: (e) => onChange(e.target.value ? new Date(e.target.value).toISOString() : null), className: base });
2525
3243
  case "boolean":
@@ -2539,12 +3257,35 @@ function FieldControl({ descriptor, value, onChange, entity, readonly }) {
2539
3257
  !value && /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select\u2026" }),
2540
3258
  (descriptor.options ?? []).map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value))
2541
3259
  ] });
3260
+ case "json":
3261
+ return /* @__PURE__ */ jsxRuntime.jsx(
3262
+ "textarea",
3263
+ {
3264
+ value: value != null ? JSON.stringify(value, null, 2) : "",
3265
+ onChange: (event) => {
3266
+ const nextValue = event.target.value;
3267
+ try {
3268
+ onChange(nextValue ? JSON.parse(nextValue) : null);
3269
+ } catch {
3270
+ onChange(nextValue);
3271
+ }
3272
+ },
3273
+ placeholder: descriptor.placeholder,
3274
+ className: "w-full min-h-[120px] rounded-md border bg-muted/50 px-3 py-2 text-sm font-mono resize-y focus:outline-none focus:ring-1 focus:ring-ring transition-colors"
3275
+ }
3276
+ );
2542
3277
  default:
2543
3278
  return /* @__PURE__ */ jsxRuntime.jsx("input", { value: String(value ?? ""), onChange: (e) => onChange(e.target.value), className: base });
2544
3279
  }
2545
3280
  }
3281
+ function FieldReadonlyValue({ descriptor, value, entity }) {
3282
+ if (descriptor.render) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: descriptor.render(value, entity) });
3283
+ if (descriptor.type === "markdown") return /* @__PURE__ */ jsxRuntime.jsx(MarkdownFieldRenderer, { value: String(value ?? ""), className: "prose prose-sm max-w-none py-1" });
3284
+ if (descriptor.type === "json") return /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs py-1 whitespace-pre-wrap break-words", children: JSON.stringify(value ?? null, null, 2) });
3285
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm py-1", children: value != null && value !== "" ? String(value) : "\u2014" });
3286
+ }
2546
3287
  function EntityDetailSheet({ crud, fields, title = "Details", description, children, showEditButton = true, showDeleteButton = true, deleteConfirmMessage = "This action cannot be undone." }) {
2547
- const [confirmDelete, setConfirmDelete] = React5__default.default.useState(false);
3288
+ const [confirmDelete, setConfirmDelete] = React6__default.default.useState(false);
2548
3289
  const open = crud.mode === "detail" && !!crud.selectedId;
2549
3290
  const entity = crud.detail;
2550
3291
  const resolvedTitle = entity && typeof title === "function" ? title(entity) : String(title);
@@ -2568,8 +3309,7 @@ function EntityDetailSheet({ crud, fields, title = "Details", description, child
2568
3309
  entity && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
2569
3310
  fields.map((f) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2570
3311
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] font-medium text-muted-foreground uppercase tracking-wide mb-1", children: f.label }),
2571
- /* @__PURE__ */ jsxRuntime.jsx(FieldControl, { descriptor: f, value: entity[f.field], onChange: () => {
2572
- }, entity, readonly: true })
3312
+ /* @__PURE__ */ jsxRuntime.jsx(FieldReadonlyValue, { descriptor: f, value: getValueAtPath(entity, f.field), entity })
2573
3313
  ] }, f.field)),
2574
3314
  children && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2575
3315
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t my-1" }),
@@ -2639,13 +3379,14 @@ function EntityFormSheet({ crud, fields, createTitle = "Create", editTitle = "Ed
2639
3379
  error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 rounded-md bg-destructive/10 border border-destructive/20 text-xs text-destructive", children: error }),
2640
3380
  visibleFields.map((f) => {
2641
3381
  const isDirty = !isCreate && crud.dirty.changed.has(f.field);
3382
+ const currentValue = getValueAtPath(buf, f.field);
2642
3383
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
2643
3384
  /* @__PURE__ */ jsxRuntime.jsxs("label", { className: cn("text-xs font-medium", isDirty ? "text-primary" : "text-muted-foreground"), children: [
2644
3385
  f.label,
2645
3386
  f.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-0.5", children: "*" }),
2646
3387
  isDirty && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1.5 text-[10px] font-normal opacity-70", children: "modified" })
2647
3388
  ] }),
2648
- /* @__PURE__ */ jsxRuntime.jsx(FieldControl, { descriptor: f, value: buf[f.field], onChange: (v) => setField(f.field, v), entity: buf, readonly: f.readonlyOnEdit && isEdit }),
3389
+ /* @__PURE__ */ jsxRuntime.jsx(FieldControl, { descriptor: f, value: currentValue, onChange: (v) => setField(f.field, v), entity: buf, readonly: f.readonlyOnEdit && isEdit }),
2649
3390
  f.hint && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] text-muted-foreground", children: f.hint })
2650
3391
  ] }, f.field);
2651
3392
  })
@@ -3303,43 +4044,43 @@ function buildHeaderGroups(columns, table) {
3303
4044
  function useTable(options) {
3304
4045
  const { data, columns: columnDefs } = options;
3305
4046
  const ini = options.initialState;
3306
- const [sorting, _setSorting] = React5.useState(
4047
+ const [sorting, _setSorting] = React6.useState(
3307
4048
  options.state?.sorting ?? ini?.sorting ?? []
3308
4049
  );
3309
- const [columnFilters, _setColumnFilters] = React5.useState(
4050
+ const [columnFilters, _setColumnFilters] = React6.useState(
3310
4051
  options.state?.columnFilters ?? ini?.columnFilters ?? []
3311
4052
  );
3312
- const [globalFilter, _setGlobalFilter] = React5.useState(
4053
+ const [globalFilter, _setGlobalFilter] = React6.useState(
3313
4054
  options.state?.globalFilter ?? ini?.globalFilter ?? ""
3314
4055
  );
3315
- const [rowSelection, _setRowSelection] = React5.useState(
4056
+ const [rowSelection, _setRowSelection] = React6.useState(
3316
4057
  options.state?.rowSelection ?? ini?.rowSelection ?? {}
3317
4058
  );
3318
- const [columnVisibility, _setColumnVisibility] = React5.useState(
4059
+ const [columnVisibility, _setColumnVisibility] = React6.useState(
3319
4060
  options.state?.columnVisibility ?? ini?.columnVisibility ?? {}
3320
4061
  );
3321
- const [columnOrder, _setColumnOrder] = React5.useState(
4062
+ const [columnOrder, _setColumnOrder] = React6.useState(
3322
4063
  options.state?.columnOrder ?? ini?.columnOrder ?? []
3323
4064
  );
3324
- const [columnPinning, _setColumnPinning] = React5.useState(
4065
+ const [columnPinning, _setColumnPinning] = React6.useState(
3325
4066
  options.state?.columnPinning ?? ini?.columnPinning ?? { left: [], right: [] }
3326
4067
  );
3327
- const [columnSizing, _setColumnSizing] = React5.useState(
4068
+ const [columnSizing, _setColumnSizing] = React6.useState(
3328
4069
  options.state?.columnSizing ?? ini?.columnSizing ?? {}
3329
4070
  );
3330
- const [columnSizingInfo, _setColumnSizingInfo] = React5.useState(
4071
+ const [columnSizingInfo, _setColumnSizingInfo] = React6.useState(
3331
4072
  options.state?.columnSizingInfo ?? ini?.columnSizingInfo ?? defaultState.columnSizingInfo
3332
4073
  );
3333
- const [expanded, _setExpanded] = React5.useState(
4074
+ const [expanded, _setExpanded] = React6.useState(
3334
4075
  options.state?.expanded ?? ini?.expanded ?? {}
3335
4076
  );
3336
- const [grouping, _setGrouping] = React5.useState(
4077
+ const [grouping, _setGrouping] = React6.useState(
3337
4078
  options.state?.grouping ?? ini?.grouping ?? []
3338
4079
  );
3339
- const [pagination, _setPagination] = React5.useState(
4080
+ const [pagination, _setPagination] = React6.useState(
3340
4081
  options.state?.pagination ?? ini?.pagination ?? { pageIndex: 0, pageSize: 10 }
3341
4082
  );
3342
- const state = React5.useMemo(
4083
+ const state = React6.useMemo(
3343
4084
  () => ({
3344
4085
  sorting: options.state?.sorting ?? sorting,
3345
4086
  columnFilters: options.state?.columnFilters ?? columnFilters,
@@ -3370,63 +4111,63 @@ function useTable(options) {
3370
4111
  pagination
3371
4112
  ]
3372
4113
  );
3373
- const stateRef = React5.useRef(state);
4114
+ const stateRef = React6.useRef(state);
3374
4115
  stateRef.current = state;
3375
- const setSorting = React5.useCallback((updater) => {
4116
+ const setSorting = React6.useCallback((updater) => {
3376
4117
  options.onSortingChange?.(updater);
3377
4118
  if (!options.state?.sorting) _setSorting((prev) => resolveUpdater(updater, prev));
3378
4119
  }, [options.onSortingChange, options.state?.sorting]);
3379
- const setColumnFilters = React5.useCallback((updater) => {
4120
+ const setColumnFilters = React6.useCallback((updater) => {
3380
4121
  options.onColumnFiltersChange?.(updater);
3381
4122
  if (!options.state?.columnFilters) _setColumnFilters((prev) => resolveUpdater(updater, prev));
3382
4123
  if (options.autoResetPageIndex !== false) {
3383
4124
  _setPagination((prev) => ({ ...prev, pageIndex: 0 }));
3384
4125
  }
3385
4126
  }, [options.onColumnFiltersChange, options.state?.columnFilters, options.autoResetPageIndex]);
3386
- const setGlobalFilter = React5.useCallback((value) => {
4127
+ const setGlobalFilter = React6.useCallback((value) => {
3387
4128
  options.onGlobalFilterChange?.(value);
3388
4129
  if (!options.state?.globalFilter) _setGlobalFilter(value);
3389
4130
  if (options.autoResetPageIndex !== false) {
3390
4131
  _setPagination((prev) => ({ ...prev, pageIndex: 0 }));
3391
4132
  }
3392
4133
  }, [options.onGlobalFilterChange, options.state?.globalFilter, options.autoResetPageIndex]);
3393
- const setRowSelection = React5.useCallback((updater) => {
4134
+ const setRowSelection = React6.useCallback((updater) => {
3394
4135
  options.onRowSelectionChange?.(updater);
3395
4136
  if (!options.state?.rowSelection) _setRowSelection((prev) => resolveUpdater(updater, prev));
3396
4137
  }, [options.onRowSelectionChange, options.state?.rowSelection]);
3397
- const setColumnVisibility = React5.useCallback((updater) => {
4138
+ const setColumnVisibility = React6.useCallback((updater) => {
3398
4139
  options.onColumnVisibilityChange?.(updater);
3399
4140
  if (!options.state?.columnVisibility) _setColumnVisibility((prev) => resolveUpdater(updater, prev));
3400
4141
  }, [options.onColumnVisibilityChange, options.state?.columnVisibility]);
3401
- const setColumnOrder = React5.useCallback((updater) => {
4142
+ const setColumnOrder = React6.useCallback((updater) => {
3402
4143
  options.onColumnOrderChange?.(updater);
3403
4144
  if (!options.state?.columnOrder) _setColumnOrder((prev) => resolveUpdater(updater, prev));
3404
4145
  }, [options.onColumnOrderChange, options.state?.columnOrder]);
3405
- const setColumnPinning = React5.useCallback((updater) => {
4146
+ const setColumnPinning = React6.useCallback((updater) => {
3406
4147
  options.onColumnPinningChange?.(updater);
3407
4148
  if (!options.state?.columnPinning) _setColumnPinning((prev) => resolveUpdater(updater, prev));
3408
4149
  }, [options.onColumnPinningChange, options.state?.columnPinning]);
3409
- const setColumnSizing = React5.useCallback((updater) => {
4150
+ const setColumnSizing = React6.useCallback((updater) => {
3410
4151
  options.onColumnSizingChange?.(updater);
3411
4152
  if (!options.state?.columnSizing) _setColumnSizing((prev) => resolveUpdater(updater, prev));
3412
4153
  }, [options.onColumnSizingChange, options.state?.columnSizing]);
3413
- const setColumnSizingInfo = React5.useCallback((updater) => {
4154
+ const setColumnSizingInfo = React6.useCallback((updater) => {
3414
4155
  options.onColumnSizingInfoChange?.(updater);
3415
4156
  if (!options.state?.columnSizingInfo) _setColumnSizingInfo((prev) => resolveUpdater(updater, prev));
3416
4157
  }, [options.onColumnSizingInfoChange, options.state?.columnSizingInfo]);
3417
- const setExpanded = React5.useCallback((updater) => {
4158
+ const setExpanded = React6.useCallback((updater) => {
3418
4159
  options.onExpandedChange?.(updater);
3419
4160
  if (!options.state?.expanded) _setExpanded((prev) => resolveUpdater(updater, prev));
3420
4161
  }, [options.onExpandedChange, options.state?.expanded]);
3421
- const setGrouping = React5.useCallback((updater) => {
4162
+ const setGrouping = React6.useCallback((updater) => {
3422
4163
  options.onGroupingChange?.(updater);
3423
4164
  if (!options.state?.grouping) _setGrouping((prev) => resolveUpdater(updater, prev));
3424
4165
  }, [options.onGroupingChange, options.state?.grouping]);
3425
- const setPagination = React5.useCallback((updater) => {
4166
+ const setPagination = React6.useCallback((updater) => {
3426
4167
  options.onPaginationChange?.(updater);
3427
4168
  if (!options.state?.pagination) _setPagination((prev) => resolveUpdater(updater, prev));
3428
4169
  }, [options.onPaginationChange, options.state?.pagination]);
3429
- const stateSetters = React5.useMemo(() => ({
4170
+ const stateSetters = React6.useMemo(() => ({
3430
4171
  setSorting,
3431
4172
  setColumnFilters,
3432
4173
  setGlobalFilter,
@@ -3453,13 +4194,13 @@ function useTable(options) {
3453
4194
  setGrouping,
3454
4195
  setPagination
3455
4196
  ]);
3456
- const getState = React5.useCallback(() => state, [state]);
3457
- const coreRowModelRef = React5.useRef(null);
3458
- const emptyCoreRowModel = React5.useMemo(
4197
+ const getState = React6.useCallback(() => state, [state]);
4198
+ const coreRowModelRef = React6.useRef(null);
4199
+ const emptyCoreRowModel = React6.useMemo(
3459
4200
  () => ({ rows: [], flatRows: [], rowsById: {} }),
3460
4201
  []
3461
4202
  );
3462
- const rowModelTable = React5.useMemo(
4203
+ const rowModelTable = React6.useMemo(
3463
4204
  () => ({
3464
4205
  options,
3465
4206
  getState: () => stateRef.current,
@@ -3469,11 +4210,11 @@ function useTable(options) {
3469
4210
  }),
3470
4211
  [options, setRowSelection, setExpanded, emptyCoreRowModel]
3471
4212
  );
3472
- const columns = React5.useMemo(
4213
+ const columns = React6.useMemo(
3473
4214
  () => buildColumns(columnDefs, { getState, ...stateSetters }, stateSetters),
3474
4215
  [columnDefs, getState, stateSetters]
3475
4216
  );
3476
- const orderedColumns = React5.useMemo(() => {
4217
+ const orderedColumns = React6.useMemo(() => {
3477
4218
  if (state.columnOrder.length === 0) return columns;
3478
4219
  const ordered = [];
3479
4220
  const remaining = [...columns];
@@ -3487,28 +4228,28 @@ function useTable(options) {
3487
4228
  ordered.push(...remaining);
3488
4229
  return ordered;
3489
4230
  }, [columns, state.columnOrder]);
3490
- const visibleColumns = React5.useMemo(
4231
+ const visibleColumns = React6.useMemo(
3491
4232
  () => orderedColumns.filter((c) => c.getIsVisible()),
3492
4233
  [orderedColumns]
3493
4234
  );
3494
- const leftPinnedColumns = React5.useMemo(
4235
+ const leftPinnedColumns = React6.useMemo(
3495
4236
  () => visibleColumns.filter((c) => c.getIsPinned() === "left"),
3496
4237
  [visibleColumns]
3497
4238
  );
3498
- const rightPinnedColumns = React5.useMemo(
4239
+ const rightPinnedColumns = React6.useMemo(
3499
4240
  () => visibleColumns.filter((c) => c.getIsPinned() === "right"),
3500
4241
  [visibleColumns]
3501
4242
  );
3502
- const centerColumns = React5.useMemo(
4243
+ const centerColumns = React6.useMemo(
3503
4244
  () => visibleColumns.filter((c) => c.getIsPinned() === false),
3504
4245
  [visibleColumns]
3505
4246
  );
3506
- const coreRowModel = React5.useMemo(() => {
4247
+ const coreRowModel = React6.useMemo(() => {
3507
4248
  const cm = getCoreRowModel2(data, columns, rowModelTable);
3508
4249
  coreRowModelRef.current = cm;
3509
4250
  return cm;
3510
4251
  }, [data, columns, rowModelTable]);
3511
- const filteredRowModel = React5.useMemo(() => {
4252
+ const filteredRowModel = React6.useMemo(() => {
3512
4253
  if (options.manualFiltering) return coreRowModel;
3513
4254
  return getFilteredRowModel(
3514
4255
  coreRowModel,
@@ -3518,32 +4259,32 @@ function useTable(options) {
3518
4259
  options.globalFilterFn
3519
4260
  );
3520
4261
  }, [coreRowModel, state.columnFilters, state.globalFilter, columns, options.manualFiltering, options.globalFilterFn]);
3521
- const sortedRowModel = React5.useMemo(() => {
4262
+ const sortedRowModel = React6.useMemo(() => {
3522
4263
  if (options.manualSorting) return filteredRowModel;
3523
4264
  return getSortedRowModel2(filteredRowModel, state.sorting, columns);
3524
4265
  }, [filteredRowModel, state.sorting, columns, options.manualSorting]);
3525
- const groupedRowModel = React5.useMemo(() => {
4266
+ const groupedRowModel = React6.useMemo(() => {
3526
4267
  if (options.manualGrouping || state.grouping.length === 0) return sortedRowModel;
3527
4268
  return getGroupedRowModel(sortedRowModel, state.grouping, columns, rowModelTable);
3528
4269
  }, [sortedRowModel, state.grouping, columns, options.manualGrouping, rowModelTable]);
3529
- const expandedRowModel = React5.useMemo(
4270
+ const expandedRowModel = React6.useMemo(
3530
4271
  () => getExpandedRowModel(groupedRowModel, state.expanded),
3531
4272
  [groupedRowModel, state.expanded]
3532
4273
  );
3533
4274
  const prePaginationRowModel = expandedRowModel;
3534
- const paginatedRowModel = React5.useMemo(() => {
4275
+ const paginatedRowModel = React6.useMemo(() => {
3535
4276
  if (options.manualPagination) return prePaginationRowModel;
3536
4277
  return getPaginatedRowModel(prePaginationRowModel, state.pagination);
3537
4278
  }, [prePaginationRowModel, state.pagination, options.manualPagination]);
3538
- const selectedRowModel = React5.useMemo(
4279
+ const selectedRowModel = React6.useMemo(
3539
4280
  () => getSelectedRowModel(coreRowModel, state.rowSelection),
3540
4281
  [coreRowModel, state.rowSelection]
3541
4282
  );
3542
- const pageCount = React5.useMemo(() => {
4283
+ const pageCount = React6.useMemo(() => {
3543
4284
  if (options.pageCount != null) return options.pageCount;
3544
4285
  return Math.ceil(prePaginationRowModel.rows.length / state.pagination.pageSize);
3545
4286
  }, [options.pageCount, prePaginationRowModel, state.pagination.pageSize]);
3546
- const table = React5.useMemo(() => {
4287
+ const table = React6.useMemo(() => {
3547
4288
  const inst = {
3548
4289
  options,
3549
4290
  getState: () => state,
@@ -3846,9 +4587,9 @@ function createSelectionStore() {
3846
4587
  function useSelectionStore(store, selector) {
3847
4588
  return zustand.useStore(store, selector);
3848
4589
  }
3849
- var SelectionContext = React5__default.default.createContext(null);
4590
+ var SelectionContext = React6__default.default.createContext(null);
3850
4591
  function useSelectionContext() {
3851
- const store = React5__default.default.useContext(SelectionContext);
4592
+ const store = React6__default.default.useContext(SelectionContext);
3852
4593
  if (!store) throw new Error("useSelectionContext must be used within a SelectionContext.Provider");
3853
4594
  return store;
3854
4595
  }
@@ -4574,18 +5315,18 @@ function generateId() {
4574
5315
  function useTablePresets(tableId, options = {}) {
4575
5316
  const { adapter, realtimeMode = "auto-apply", enabled = true } = options;
4576
5317
  const resolvedAdapter = adapter ?? new MemoryAdapter();
4577
- const adapterRef = React5.useRef(resolvedAdapter);
5318
+ const adapterRef = React6.useRef(resolvedAdapter);
4578
5319
  adapterRef.current = resolvedAdapter;
4579
- const storeRef = React5.useRef(createPresetStore(realtimeMode));
5320
+ const storeRef = React6.useRef(createPresetStore(realtimeMode));
4580
5321
  const store = storeRef.current;
4581
- const [isLoading, setIsLoading] = React5.useState(false);
4582
- const [isSubscribed, setIsSubscribed] = React5.useState(false);
4583
- React5.useEffect(() => {
5322
+ const [isLoading, setIsLoading] = React6.useState(false);
5323
+ const [isSubscribed, setIsSubscribed] = React6.useState(false);
5324
+ React6.useEffect(() => {
4584
5325
  if (!enabled) return;
4585
5326
  setIsLoading(true);
4586
5327
  store.getState().loadPresets(tableId, adapterRef.current).finally(() => setIsLoading(false));
4587
5328
  }, [tableId, enabled, store]);
4588
- React5.useEffect(() => {
5329
+ React6.useEffect(() => {
4589
5330
  if (!enabled) return;
4590
5331
  const currentAdapter = adapterRef.current;
4591
5332
  if (!currentAdapter.subscribe) {
@@ -4600,19 +5341,19 @@ function useTablePresets(tableId, options = {}) {
4600
5341
  }, [tableId, enabled, store]);
4601
5342
  const slice = zustand.useStore(store, (s) => s.presets[tableId] ?? s.getTablePresets(tableId));
4602
5343
  const allPendingChanges = zustand.useStore(store, (s) => s.pendingChanges);
4603
- const pendingChanges = React5.useMemo(
5344
+ const pendingChanges = React6.useMemo(
4604
5345
  () => allPendingChanges.filter((e) => e.tableId === tableId),
4605
5346
  [allPendingChanges, tableId]
4606
5347
  );
4607
- const activeFilterPreset = React5.useMemo(
5348
+ const activeFilterPreset = React6.useMemo(
4608
5349
  () => slice.filters.find((p) => p.id === slice.activeFilterId) ?? null,
4609
5350
  [slice.filters, slice.activeFilterId]
4610
5351
  );
4611
- const activeColumnPreset = React5.useMemo(
5352
+ const activeColumnPreset = React6.useMemo(
4612
5353
  () => slice.columns.find((p) => p.id === slice.activeColumnId) ?? null,
4613
5354
  [slice.columns, slice.activeColumnId]
4614
5355
  );
4615
- const applyFilterPreset = React5.useCallback(
5356
+ const applyFilterPreset = React6.useCallback(
4616
5357
  (id) => {
4617
5358
  store.getState().applyFilterPreset(tableId, id);
4618
5359
  adapterRef.current.saveActivePresets(tableId, {
@@ -4623,7 +5364,7 @@ function useTablePresets(tableId, options = {}) {
4623
5364
  },
4624
5365
  [tableId, slice.activeColumnId, slice.activeViewMode, store]
4625
5366
  );
4626
- const applyColumnPreset = React5.useCallback(
5367
+ const applyColumnPreset = React6.useCallback(
4627
5368
  (id) => {
4628
5369
  store.getState().applyColumnPreset(tableId, id);
4629
5370
  adapterRef.current.saveActivePresets(tableId, {
@@ -4634,7 +5375,7 @@ function useTablePresets(tableId, options = {}) {
4634
5375
  },
4635
5376
  [tableId, slice.activeFilterId, slice.activeViewMode, store]
4636
5377
  );
4637
- const setViewMode = React5.useCallback(
5378
+ const setViewMode = React6.useCallback(
4638
5379
  (mode) => {
4639
5380
  store.getState().setViewMode(tableId, mode);
4640
5381
  adapterRef.current.saveActivePresets(tableId, {
@@ -4645,7 +5386,7 @@ function useTablePresets(tableId, options = {}) {
4645
5386
  },
4646
5387
  [tableId, slice.activeFilterId, slice.activeColumnId, store]
4647
5388
  );
4648
- const saveFilterPreset = React5.useCallback(
5389
+ const saveFilterPreset = React6.useCallback(
4649
5390
  async (preset) => {
4650
5391
  const now = (/* @__PURE__ */ new Date()).toISOString();
4651
5392
  const full = {
@@ -4658,7 +5399,7 @@ function useTablePresets(tableId, options = {}) {
4658
5399
  },
4659
5400
  [tableId, store]
4660
5401
  );
4661
- const updateFilterPreset = React5.useCallback(
5402
+ const updateFilterPreset = React6.useCallback(
4662
5403
  async (id, patch) => {
4663
5404
  const existing = slice.filters.find((p) => p.id === id);
4664
5405
  if (!existing) return;
@@ -4672,7 +5413,7 @@ function useTablePresets(tableId, options = {}) {
4672
5413
  },
4673
5414
  [tableId, slice.filters, store]
4674
5415
  );
4675
- const saveColumnPreset = React5.useCallback(
5416
+ const saveColumnPreset = React6.useCallback(
4676
5417
  async (preset) => {
4677
5418
  const now = (/* @__PURE__ */ new Date()).toISOString();
4678
5419
  const full = {
@@ -4685,7 +5426,7 @@ function useTablePresets(tableId, options = {}) {
4685
5426
  },
4686
5427
  [tableId, store]
4687
5428
  );
4688
- const updateColumnPreset = React5.useCallback(
5429
+ const updateColumnPreset = React6.useCallback(
4689
5430
  async (id, patch) => {
4690
5431
  const existing = slice.columns.find((p) => p.id === id);
4691
5432
  if (!existing) return;
@@ -4699,25 +5440,25 @@ function useTablePresets(tableId, options = {}) {
4699
5440
  },
4700
5441
  [tableId, slice.columns, store]
4701
5442
  );
4702
- const deleteFilterPreset = React5.useCallback(
5443
+ const deleteFilterPreset = React6.useCallback(
4703
5444
  async (id) => {
4704
5445
  await store.getState().deleteFilterPreset(tableId, id, adapterRef.current);
4705
5446
  },
4706
5447
  [tableId, store]
4707
5448
  );
4708
- const deleteColumnPreset = React5.useCallback(
5449
+ const deleteColumnPreset = React6.useCallback(
4709
5450
  async (id) => {
4710
5451
  await store.getState().deleteColumnPreset(tableId, id, adapterRef.current);
4711
5452
  },
4712
5453
  [tableId, store]
4713
5454
  );
4714
- const acknowledgePendingChange = React5.useCallback(
5455
+ const acknowledgePendingChange = React6.useCallback(
4715
5456
  (index) => {
4716
5457
  store.getState().acknowledgePendingChange(index);
4717
5458
  },
4718
5459
  [store]
4719
5460
  );
4720
- const dismissPendingChanges = React5.useCallback(() => {
5461
+ const dismissPendingChanges = React6.useCallback(() => {
4721
5462
  store.getState().dismissPendingChanges(tableId);
4722
5463
  }, [tableId, store]);
4723
5464
  return {
@@ -4742,7 +5483,7 @@ function useTablePresets(tableId, options = {}) {
4742
5483
  isSubscribed
4743
5484
  };
4744
5485
  }
4745
- var TableStorageContext = React5.createContext({
5486
+ var TableStorageContext = React6.createContext({
4746
5487
  adapter: new MemoryAdapter(),
4747
5488
  realtimeMode: "auto-apply"
4748
5489
  });
@@ -4751,19 +5492,19 @@ function TableStorageProvider({
4751
5492
  realtimeMode = "auto-apply",
4752
5493
  children
4753
5494
  }) {
4754
- const value = React5.useMemo(
5495
+ const value = React6.useMemo(
4755
5496
  () => ({ adapter, realtimeMode }),
4756
5497
  [adapter, realtimeMode]
4757
5498
  );
4758
5499
  return /* @__PURE__ */ jsxRuntime.jsx(TableStorageContext.Provider, { value, children });
4759
5500
  }
4760
5501
  function useTableStorageAdapter() {
4761
- return React5.useContext(TableStorageContext).adapter;
5502
+ return React6.useContext(TableStorageContext).adapter;
4762
5503
  }
4763
5504
  function useTableRealtimeMode() {
4764
- return React5.useContext(TableStorageContext).realtimeMode;
5505
+ return React6.useContext(TableStorageContext).realtimeMode;
4765
5506
  }
4766
- var Table = React5__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
5507
+ var Table = React6__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
4767
5508
  "table",
4768
5509
  {
4769
5510
  ref,
@@ -4772,11 +5513,11 @@ var Table = React5__default.default.forwardRef(({ className, ...props }, ref) =>
4772
5513
  }
4773
5514
  ) }));
4774
5515
  Table.displayName = "Table";
4775
- var TableHeader = React5__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("thead", { ref, className: cn("bg-muted/60", className), ...props }));
5516
+ var TableHeader = React6__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("thead", { ref, className: cn("bg-muted/60", className), ...props }));
4776
5517
  TableHeader.displayName = "TableHeader";
4777
- var TableBody = React5__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { ref, className: cn("bg-background", className), ...props }));
5518
+ var TableBody = React6__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { ref, className: cn("bg-background", className), ...props }));
4778
5519
  TableBody.displayName = "TableBody";
4779
- var TableFooter = React5__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
5520
+ var TableFooter = React6__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4780
5521
  "tfoot",
4781
5522
  {
4782
5523
  ref,
@@ -4785,7 +5526,7 @@ var TableFooter = React5__default.default.forwardRef(({ className, ...props }, r
4785
5526
  }
4786
5527
  ));
4787
5528
  TableFooter.displayName = "TableFooter";
4788
- var TableRow = React5__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
5529
+ var TableRow = React6__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4789
5530
  "tr",
4790
5531
  {
4791
5532
  ref,
@@ -4797,7 +5538,7 @@ var TableRow = React5__default.default.forwardRef(({ className, ...props }, ref)
4797
5538
  }
4798
5539
  ));
4799
5540
  TableRow.displayName = "TableRow";
4800
- var TableHead = React5__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
5541
+ var TableHead = React6__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4801
5542
  "th",
4802
5543
  {
4803
5544
  ref,
@@ -4809,7 +5550,7 @@ var TableHead = React5__default.default.forwardRef(({ className, ...props }, ref
4809
5550
  }
4810
5551
  ));
4811
5552
  TableHead.displayName = "TableHead";
4812
- var TableCell = React5__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
5553
+ var TableCell = React6__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4813
5554
  "td",
4814
5555
  {
4815
5556
  ref,
@@ -4821,7 +5562,7 @@ var TableCell = React5__default.default.forwardRef(({ className, ...props }, ref
4821
5562
  }
4822
5563
  ));
4823
5564
  TableCell.displayName = "TableCell";
4824
- var TableCaption = React5__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
5565
+ var TableCaption = React6__default.default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4825
5566
  "caption",
4826
5567
  {
4827
5568
  ref,
@@ -4884,11 +5625,11 @@ function InlineCellEditor2({
4884
5625
  inputId,
4885
5626
  ariaLabel
4886
5627
  }) {
4887
- const [value, setValue] = React5.useState(initialValue);
4888
- const inputRef = React5.useRef(null);
4889
- const selectRef = React5.useRef(null);
5628
+ const [value, setValue] = React6.useState(initialValue);
5629
+ const inputRef = React6.useRef(null);
5630
+ const selectRef = React6.useRef(null);
4890
5631
  const filterType = columnDef.meta?.entityMeta?.filterType ?? "text";
4891
- React5.useEffect(() => {
5632
+ React6.useEffect(() => {
4892
5633
  if (filterType === "enum") {
4893
5634
  selectRef.current?.focus();
4894
5635
  return;
@@ -4897,7 +5638,7 @@ function InlineCellEditor2({
4897
5638
  inputRef.current?.focus();
4898
5639
  inputRef.current?.select();
4899
5640
  }, [filterType]);
4900
- const handleKeyDown = React5.useCallback(
5641
+ const handleKeyDown = React6.useCallback(
4901
5642
  (e) => {
4902
5643
  if (e.key === "Enter") {
4903
5644
  e.preventDefault();
@@ -4909,7 +5650,7 @@ function InlineCellEditor2({
4909
5650
  },
4910
5651
  [value, onSave, onCancel]
4911
5652
  );
4912
- const handleBlur = React5.useCallback(() => {
5653
+ const handleBlur = React6.useCallback(() => {
4913
5654
  onSave(value);
4914
5655
  }, [value, onSave]);
4915
5656
  if (filterType === "boolean") {
@@ -5017,8 +5758,8 @@ function InlineItemEditor({
5017
5758
  onCancel,
5018
5759
  className
5019
5760
  }) {
5020
- const baseId = React5.useId();
5021
- const [editValues, setEditValues] = React5.useState({});
5761
+ const baseId = React6.useId();
5762
+ const [editValues, setEditValues] = React6.useState({});
5022
5763
  const editableFields = columns.filter(
5023
5764
  (c) => c.meta?.entityMeta?.editable && c.accessorKey
5024
5765
  );
@@ -5119,11 +5860,11 @@ function ActionDropdown({
5119
5860
  actions,
5120
5861
  className
5121
5862
  }) {
5122
- const [isOpen, setIsOpen] = React5.useState(false);
5123
- const [confirmAction, setConfirmAction] = React5.useState(null);
5124
- const menuRef = React5.useRef(null);
5863
+ const [isOpen, setIsOpen] = React6.useState(false);
5864
+ const [confirmAction, setConfirmAction] = React6.useState(null);
5865
+ const menuRef = React6.useRef(null);
5125
5866
  const visibleActions = actions.filter((a) => !a.hidden?.(item));
5126
- React5.useEffect(() => {
5867
+ React6.useEffect(() => {
5127
5868
  function handleClick(e) {
5128
5869
  if (menuRef.current && !menuRef.current.contains(e.target)) {
5129
5870
  setIsOpen(false);
@@ -5195,7 +5936,7 @@ function ActionButtonRow({
5195
5936
  const visibleActions = actions.filter((a) => !a.hidden?.(item));
5196
5937
  const inline = visibleActions.slice(0, maxVisible);
5197
5938
  const overflow = visibleActions.slice(maxVisible);
5198
- const [confirmAction, setConfirmAction] = React5.useState(null);
5939
+ const [confirmAction, setConfirmAction] = React6.useState(null);
5199
5940
  function executeAction(action) {
5200
5941
  if (action.confirm) {
5201
5942
  setConfirmAction(action);
@@ -5363,10 +6104,10 @@ function DataTable({
5363
6104
  getRowId,
5364
6105
  className
5365
6106
  }) {
5366
- const [editingCell, setEditingCell] = React5.useState(null);
6107
+ const [editingCell, setEditingCell] = React6.useState(null);
5367
6108
  const headerGroups = table.getHeaderGroups();
5368
6109
  const rowModel = table.getRowModel();
5369
- const handleCellDoubleClick = React5.useCallback(
6110
+ const handleCellDoubleClick = React6.useCallback(
5370
6111
  (rowId, columnId, columnDef) => {
5371
6112
  if (!enableInlineEdit) return;
5372
6113
  if (!columnDef.meta?.entityMeta?.editable) return;
@@ -5374,7 +6115,7 @@ function DataTable({
5374
6115
  },
5375
6116
  [enableInlineEdit]
5376
6117
  );
5377
- const handleInlineSave = React5.useCallback(
6118
+ const handleInlineSave = React6.useCallback(
5378
6119
  async (row, columnId, value) => {
5379
6120
  const field = columnId;
5380
6121
  await onInlineSave?.(row.original, field, value);
@@ -5551,7 +6292,7 @@ function GalleryView({
5551
6292
  galleryColumns,
5552
6293
  className
5553
6294
  }) {
5554
- const [editingId, setEditingId] = React5.useState(null);
6295
+ const [editingId, setEditingId] = React6.useState(null);
5555
6296
  const breakpointClasses = galleryColumns ? buildBreakpointClasses(galleryColumns) : "";
5556
6297
  return /* @__PURE__ */ jsxRuntime.jsx(
5557
6298
  "div",
@@ -5615,7 +6356,7 @@ function GalleryCard({
5615
6356
  (s) => selectionStore ? s.isMultiSelectMode : false
5616
6357
  );
5617
6358
  const storeToggle = useSelectionStore(selStore, (s) => s.toggle);
5618
- const toggle = React5.useCallback(
6359
+ const toggle = React6.useCallback(
5619
6360
  (id) => {
5620
6361
  if (selectionStore) storeToggle(id);
5621
6362
  },
@@ -5776,7 +6517,7 @@ function ListView({
5776
6517
  getRowId,
5777
6518
  className
5778
6519
  }) {
5779
- const [editingId, setEditingId] = React5.useState(null);
6520
+ const [editingId, setEditingId] = React6.useState(null);
5780
6521
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("divide-y rounded-md border", className), children: rows.map((row) => {
5781
6522
  const id = getRowId?.(row.original) ?? row.id;
5782
6523
  const isEditing = editingId === id;
@@ -5829,7 +6570,7 @@ function ListItem({
5829
6570
  (s) => selectionStore ? s.isMultiSelectMode : false
5830
6571
  );
5831
6572
  const storeToggle = useSelectionStore(selStore, (s) => s.toggle);
5832
- const toggle = React5.useCallback(
6573
+ const toggle = React6.useCallback(
5833
6574
  (id) => {
5834
6575
  if (selectionStore) storeToggle(id);
5835
6576
  },
@@ -6023,7 +6764,7 @@ function DataTableToolbar({
6023
6764
  className,
6024
6765
  children
6025
6766
  }) {
6026
- const [colVisOpen, setColVisOpen] = React5.useState(false);
6767
+ const [colVisOpen, setColVisOpen] = React6.useState(false);
6027
6768
  const globalFilter = table.getState().globalFilter;
6028
6769
  const columnFilters = table.getState().columnFilters;
6029
6770
  const hasFilters = columnFilters.length > 0;
@@ -6191,7 +6932,7 @@ function DataTablePagination({
6191
6932
  totalCount,
6192
6933
  className
6193
6934
  }) {
6194
- const pageSizeId = React5.useId();
6935
+ const pageSizeId = React6.useId();
6195
6936
  if (mode === "none") return null;
6196
6937
  const state = table.getState();
6197
6938
  const count = totalCount ?? table.getPrePaginationRowModel().rows.length;
@@ -6340,7 +7081,7 @@ function ChevronsRightIcon({ className }) {
6340
7081
  ] });
6341
7082
  }
6342
7083
  function EmptyState({ config, isFiltered = false, className }) {
6343
- if (React5__default.default.isValidElement(config)) {
7084
+ if (React6__default.default.isValidElement(config)) {
6344
7085
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: config });
6345
7086
  }
6346
7087
  const cfg = config ?? {};
@@ -6390,7 +7131,7 @@ function MultiSelectBar({
6390
7131
  }) {
6391
7132
  const selectedIdsSet = useSelectionStore(store, (s) => s.selectedIds);
6392
7133
  const selectedCount = selectedIdsSet.size;
6393
- const selectedIds = React5.useMemo(() => Array.from(selectedIdsSet), [selectedIdsSet]);
7134
+ const selectedIds = React6.useMemo(() => Array.from(selectedIdsSet), [selectedIdsSet]);
6394
7135
  const deselectAll = useSelectionStore(store, (s) => s.deselectAll);
6395
7136
  useSelectionStore(store, (s) => s.selectAll);
6396
7137
  if (selectedCount === 0) return null;
@@ -6468,11 +7209,11 @@ function PresetPicker({
6468
7209
  pendingChangesCount = 0,
6469
7210
  className
6470
7211
  }) {
6471
- const [isOpen, setIsOpen] = React5.useState(false);
6472
- const [activeTab, setActiveTab] = React5.useState("filters");
6473
- const popoverRef = React5.useRef(null);
6474
- const triggerRef = React5.useRef(null);
6475
- React5.useEffect(() => {
7212
+ const [isOpen, setIsOpen] = React6.useState(false);
7213
+ const [activeTab, setActiveTab] = React6.useState("filters");
7214
+ const popoverRef = React6.useRef(null);
7215
+ const triggerRef = React6.useRef(null);
7216
+ React6.useEffect(() => {
6476
7217
  function handleClick(e) {
6477
7218
  if (popoverRef.current && !popoverRef.current.contains(e.target) && !triggerRef.current?.contains(e.target)) {
6478
7219
  setIsOpen(false);
@@ -6643,7 +7384,7 @@ function PresetItem({
6643
7384
  onEdit,
6644
7385
  onDelete
6645
7386
  }) {
6646
- const [showDeleteConfirm, setShowDeleteConfirm] = React5.useState(false);
7387
+ const [showDeleteConfirm, setShowDeleteConfirm] = React6.useState(false);
6647
7388
  return /* @__PURE__ */ jsxRuntime.jsxs(
6648
7389
  "div",
6649
7390
  {
@@ -6755,13 +7496,13 @@ function FilterPresetDialog({
6755
7496
  preset,
6756
7497
  onSave
6757
7498
  }) {
6758
- const nameId = React5.useId();
6759
- const descriptionId = React5.useId();
6760
- const [name, setName] = React5.useState(preset?.name ?? "");
6761
- const [description, setDescription] = React5.useState(preset?.description ?? "");
6762
- const [isDefault, setIsDefault] = React5.useState(preset?.isDefault ?? false);
6763
- const [logic, setLogic] = React5.useState("and");
6764
- const [clauses, setClauses] = React5.useState(() => {
7499
+ const nameId = React6.useId();
7500
+ const descriptionId = React6.useId();
7501
+ const [name, setName] = React6.useState(preset?.name ?? "");
7502
+ const [description, setDescription] = React6.useState(preset?.description ?? "");
7503
+ const [isDefault, setIsDefault] = React6.useState(preset?.isDefault ?? false);
7504
+ const [logic, setLogic] = React6.useState("and");
7505
+ const [clauses, setClauses] = React6.useState(() => {
6765
7506
  if (!preset?.filter) return [];
6766
7507
  const filterSpec = preset.filter;
6767
7508
  const rawClauses = Array.isArray(filterSpec) ? filterSpec : filterSpec.clauses ?? [];
@@ -7004,10 +7745,10 @@ function ColumnPresetDialog({
7004
7745
  preset,
7005
7746
  onSave
7006
7747
  }) {
7007
- const [name, setName] = React5.useState(preset?.name ?? "");
7008
- const [description, setDescription] = React5.useState(preset?.description ?? "");
7009
- const [isDefault, setIsDefault] = React5.useState(preset?.isDefault ?? false);
7010
- const [entries, setEntries] = React5.useState(() => {
7748
+ const [name, setName] = React6.useState(preset?.name ?? "");
7749
+ const [description, setDescription] = React6.useState(preset?.description ?? "");
7750
+ const [isDefault, setIsDefault] = React6.useState(preset?.isDefault ?? false);
7751
+ const [entries, setEntries] = React6.useState(() => {
7011
7752
  if (preset?.columns) return [...preset.columns];
7012
7753
  return columns.map((col, idx) => ({
7013
7754
  id: col.accessorKey ?? col.id ?? `col_${idx}`,
@@ -7017,7 +7758,7 @@ function ColumnPresetDialog({
7017
7758
  pinned: false
7018
7759
  }));
7019
7760
  });
7020
- const [dragIdx, setDragIdx] = React5.useState(null);
7761
+ const [dragIdx, setDragIdx] = React6.useState(null);
7021
7762
  function updateEntry(id, updates) {
7022
7763
  setEntries(
7023
7764
  (prev) => prev.map((e) => e.id === id ? { ...e, ...updates } : e)
@@ -7290,15 +8031,15 @@ function EntityListView(props) {
7290
8031
  onRefresh,
7291
8032
  className
7292
8033
  } = props;
7293
- const data = React5.useMemo(
8034
+ const data = React6.useMemo(
7294
8035
  () => viewResult?.items ?? dataProp ?? [],
7295
8036
  [viewResult?.items, dataProp]
7296
8037
  );
7297
- const selectionStoreRef = React5.useRef(null);
8038
+ const selectionStoreRef = React6.useRef(null);
7298
8039
  if (!selectionStoreRef.current) {
7299
8040
  selectionStoreRef.current = createSelectionStore();
7300
8041
  }
7301
- const [viewMode, setViewMode] = React5.useState(defaultViewMode);
8042
+ const [viewMode, setViewMode] = React6.useState(defaultViewMode);
7302
8043
  const adapter = useTableStorageAdapter();
7303
8044
  const realtimeMode = useTableRealtimeMode();
7304
8045
  const presets = useTablePresets(tableId ?? "__no_table_id__", {
@@ -7306,10 +8047,10 @@ function EntityListView(props) {
7306
8047
  realtimeMode,
7307
8048
  enabled: enablePresets && !!tableId
7308
8049
  });
7309
- const [filterDialogOpen, setFilterDialogOpen] = React5.useState(false);
7310
- const [columnDialogOpen, setColumnDialogOpen] = React5.useState(false);
7311
- const [editingFilterPreset, setEditingFilterPreset] = React5.useState(null);
7312
- const [editingColumnPreset, setEditingColumnPreset] = React5.useState(null);
8050
+ const [filterDialogOpen, setFilterDialogOpen] = React6.useState(false);
8051
+ const [columnDialogOpen, setColumnDialogOpen] = React6.useState(false);
8052
+ const [editingFilterPreset, setEditingFilterPreset] = React6.useState(null);
8053
+ const [editingColumnPreset, setEditingColumnPreset] = React6.useState(null);
7313
8054
  const table = useTable({
7314
8055
  data,
7315
8056
  columns,
@@ -7330,7 +8071,7 @@ function EntityListView(props) {
7330
8071
  const prePagRows = table.getPrePaginationRowModel();
7331
8072
  const isEmpty = data.length === 0;
7332
8073
  const isFilteredEmpty = !isEmpty && prePagRows.rows.length === 0;
7333
- const handleViewModeChange = React5.useCallback(
8074
+ const handleViewModeChange = React6.useCallback(
7334
8075
  (mode) => {
7335
8076
  setViewMode(mode);
7336
8077
  if (enablePresets && tableId) {
@@ -7339,19 +8080,19 @@ function EntityListView(props) {
7339
8080
  },
7340
8081
  [enablePresets, tableId, presets]
7341
8082
  );
7342
- const handleInlineSaveTable = React5.useCallback(
8083
+ const handleInlineSaveTable = React6.useCallback(
7343
8084
  (item, field, value) => {
7344
8085
  onInlineEdit?.(item, field, value);
7345
8086
  },
7346
8087
  [onInlineEdit]
7347
8088
  );
7348
- const handleInlineSaveItem = React5.useCallback(
8089
+ const handleInlineSaveItem = React6.useCallback(
7349
8090
  (item, changes) => {
7350
8091
  onInlineSave?.(item, changes);
7351
8092
  },
7352
8093
  [onInlineSave]
7353
8094
  );
7354
- const handleBatchAction = React5.useCallback(
8095
+ const handleBatchAction = React6.useCallback(
7355
8096
  (actionId, selectedIds) => {
7356
8097
  if (!onBatchAction) return;
7357
8098
  const selectedItems = data.filter((item) => {
@@ -7500,12 +8241,12 @@ function DataTableFilter({
7500
8241
  column,
7501
8242
  className
7502
8243
  }) {
7503
- const [isOpen, setIsOpen] = React5.useState(false);
7504
- const popoverRef = React5.useRef(null);
7505
- const triggerRef = React5.useRef(null);
8244
+ const [isOpen, setIsOpen] = React6.useState(false);
8245
+ const popoverRef = React6.useRef(null);
8246
+ const triggerRef = React6.useRef(null);
7506
8247
  const filterType = column.columnDef.meta?.entityMeta?.filterType ?? "text";
7507
8248
  const isFiltered = column.getIsFiltered();
7508
- React5.useEffect(() => {
8249
+ React6.useEffect(() => {
7509
8250
  function handleClick(e) {
7510
8251
  if (popoverRef.current && !popoverRef.current.contains(e.target) && !triggerRef.current?.contains(e.target)) {
7511
8252
  setIsOpen(false);
@@ -7563,7 +8304,7 @@ function FilterControl({
7563
8304
  }
7564
8305
  }
7565
8306
  function TextFilter({ column }) {
7566
- const id = React5.useId();
8307
+ const id = React6.useId();
7567
8308
  const value = column.getFilterValue() ?? "";
7568
8309
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
7569
8310
  /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "text-xs font-medium", children: "Contains" }),
@@ -7590,8 +8331,8 @@ function TextFilter({ column }) {
7590
8331
  ] });
7591
8332
  }
7592
8333
  function NumberFilter({ column }) {
7593
- const minId = React5.useId();
7594
- const maxId = React5.useId();
8334
+ const minId = React6.useId();
8335
+ const maxId = React6.useId();
7595
8336
  const value = column.getFilterValue() ?? [void 0, void 0];
7596
8337
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
7597
8338
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: "Range" }),
@@ -7695,8 +8436,8 @@ function EnumFilter({ column }) {
7695
8436
  ] });
7696
8437
  }
7697
8438
  function DateFilter({ column }) {
7698
- const startId = React5.useId();
7699
- const endId = React5.useId();
8439
+ const startId = React6.useId();
8440
+ const endId = React6.useId();
7700
8441
  const value = column.getFilterValue() ?? [void 0, void 0];
7701
8442
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
7702
8443
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: "Date range" }),
@@ -7740,13 +8481,13 @@ function selectionColumn2() {
7740
8481
  enableFiltering: false,
7741
8482
  enableHiding: false,
7742
8483
  enableResizing: false,
7743
- header: ({ table }) => React5__default.default.createElement("input", {
8484
+ header: ({ table }) => React6__default.default.createElement("input", {
7744
8485
  type: "checkbox",
7745
8486
  checked: table.getIsAllPageRowsSelected(),
7746
8487
  onChange: table.getToggleAllPageRowsSelectedHandler(),
7747
8488
  className: "h-4 w-4 rounded border-primary text-primary focus:ring-ring"
7748
8489
  }),
7749
- cell: ({ row }) => React5__default.default.createElement("input", {
8490
+ cell: ({ row }) => React6__default.default.createElement("input", {
7750
8491
  type: "checkbox",
7751
8492
  checked: row.getIsSelected(),
7752
8493
  onChange: row.getToggleSelectedHandler(),
@@ -7882,7 +8623,7 @@ function enumColumn2(options) {
7882
8623
  const opt = options.options.find((o) => o.value === val);
7883
8624
  if (!opt) return val;
7884
8625
  if (opt.badgeClassName) {
7885
- return React5__default.default.createElement(
8626
+ return React6__default.default.createElement(
7886
8627
  "span",
7887
8628
  {
7888
8629
  className: `inline-flex items-center rounded px-1.5 py-0.5 text-[11px] font-medium capitalize ${opt.badgeClassName}`
@@ -7890,7 +8631,7 @@ function enumColumn2(options) {
7890
8631
  opt.label
7891
8632
  );
7892
8633
  }
7893
- return React5__default.default.createElement(
8634
+ return React6__default.default.createElement(
7894
8635
  "span",
7895
8636
  {
7896
8637
  className: "inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium",
@@ -7947,6 +8688,8 @@ exports.GalleryView = GalleryView;
7947
8688
  exports.InlineCellEditor = InlineCellEditor;
7948
8689
  exports.InlineItemEditor = InlineItemEditor;
7949
8690
  exports.ListView = ListView;
8691
+ exports.MarkdownFieldEditor = MarkdownFieldEditor;
8692
+ exports.MarkdownFieldRenderer = MarkdownFieldRenderer;
7950
8693
  exports.MemoryAdapter = MemoryAdapter;
7951
8694
  exports.MultiSelectBar = MultiSelectBar;
7952
8695
  exports.PresetPicker = PresetPicker;
@@ -7971,6 +8714,7 @@ exports.ZustandPersistAdapter = ZustandPersistAdapter;
7971
8714
  exports.actionsColumn = actionsColumn;
7972
8715
  exports.applyView = applyView;
7973
8716
  exports.booleanColumn = booleanColumn;
8717
+ exports.buildEntityFieldsFromSchema = buildEntityFieldsFromSchema;
7974
8718
  exports.cascadeInvalidation = cascadeInvalidation;
7975
8719
  exports.checkCompleteness = checkCompleteness;
7976
8720
  exports.compareEntities = compareEntities;
@@ -7978,10 +8722,15 @@ exports.configureEngine = configureEngine;
7978
8722
  exports.createConvexAdapter = createConvexAdapter;
7979
8723
  exports.createElectricAdapter = createElectricAdapter;
7980
8724
  exports.createGQLClient = createGQLClient;
8725
+ exports.createGraphAction = createGraphAction;
8726
+ exports.createGraphEffect = createGraphEffect;
7981
8727
  exports.createGraphQLSubscriptionAdapter = createGraphQLSubscriptionAdapter;
8728
+ exports.createGraphTool = createGraphTool;
8729
+ exports.createGraphTransaction = createGraphTransaction;
7982
8730
  exports.createPresetStore = createPresetStore;
7983
8731
  exports.createPrismaEntityConfig = createPrismaEntityConfig;
7984
8732
  exports.createRow = createRow;
8733
+ exports.createSchemaGraphTool = createSchemaGraphTool;
7985
8734
  exports.createSelectionStore = createSelectionStore;
7986
8735
  exports.createSupabaseRealtimeAdapter = createSupabaseRealtimeAdapter;
7987
8736
  exports.createWebSocketAdapter = createWebSocketAdapter;
@@ -7991,10 +8740,13 @@ exports.deleteAction = deleteAction;
7991
8740
  exports.editAction = editAction;
7992
8741
  exports.enumColumn = enumColumn;
7993
8742
  exports.executeGQL = executeGQL;
8743
+ exports.exportGraphSnapshot = exportGraphSnapshot;
8744
+ exports.exportGraphSnapshotWithSchemas = exportGraphSnapshotWithSchemas;
7994
8745
  exports.fetchEntity = fetchEntity;
7995
8746
  exports.fetchList = fetchList;
7996
8747
  exports.flattenClauses = flattenClauses;
7997
8748
  exports.getCoreRowModel = getCoreRowModel2;
8749
+ exports.getEntityJsonSchema = getEntityJsonSchema;
7998
8750
  exports.getExpandedRowModel = getExpandedRowModel;
7999
8751
  exports.getFacetedMinMaxValues = getFacetedMinMaxValues;
8000
8752
  exports.getFacetedRowModel = getFacetedRowModel;
@@ -8007,10 +8759,12 @@ exports.getSchema = getSchema;
8007
8759
  exports.getSelectedRowModel = getSelectedRowModel;
8008
8760
  exports.getSortedRowModel = getSortedRowModel2;
8009
8761
  exports.hasCustomPredicates = hasCustomPredicates;
8762
+ exports.hydrateGraphFromStorage = hydrateGraphFromStorage;
8010
8763
  exports.matchesFilter = matchesFilter;
8011
8764
  exports.matchesSearch = matchesSearch;
8012
8765
  exports.normalizeGQLResponse = normalizeGQLResponse;
8013
8766
  exports.numberColumn = numberColumn;
8767
+ exports.persistGraphToStorage = persistGraphToStorage;
8014
8768
  exports.prismaRelationsToSchema = prismaRelationsToSchema;
8015
8769
  exports.pureActionsColumn = actionsColumn2;
8016
8770
  exports.pureBooleanColumn = booleanColumn2;
@@ -8019,12 +8773,18 @@ exports.pureEnumColumn = enumColumn2;
8019
8773
  exports.pureNumberColumn = numberColumn2;
8020
8774
  exports.pureSelectionColumn = selectionColumn2;
8021
8775
  exports.pureTextColumn = textColumn2;
8776
+ exports.queryOnce = queryOnce;
8022
8777
  exports.readRelations = readRelations;
8778
+ exports.registerEntityJsonSchema = registerEntityJsonSchema;
8779
+ exports.registerRuntimeSchema = registerRuntimeSchema;
8023
8780
  exports.registerSchema = registerSchema;
8781
+ exports.renderMarkdownToHtml = renderMarkdownToHtml;
8024
8782
  exports.resetRealtimeManager = resetRealtimeManager;
8783
+ exports.selectGraph = selectGraph;
8025
8784
  exports.selectionColumn = selectionColumn;
8026
8785
  exports.serializeKey = serializeKey;
8027
8786
  exports.startGarbageCollector = startGarbageCollector;
8787
+ exports.startLocalFirstGraph = startLocalFirstGraph;
8028
8788
  exports.stopGarbageCollector = stopGarbageCollector;
8029
8789
  exports.textColumn = textColumn;
8030
8790
  exports.toGraphQLVariables = toGraphQLVariables;
@@ -8045,8 +8805,10 @@ exports.useGQLMutation = useGQLMutation;
8045
8805
  exports.useGQLSubscription = useGQLSubscription;
8046
8806
  exports.useGraphDevTools = useGraphDevTools;
8047
8807
  exports.useGraphStore = useGraphStore;
8808
+ exports.useGraphSyncStatus = useGraphSyncStatus;
8048
8809
  exports.useLocalFirst = useLocalFirst;
8049
8810
  exports.usePGliteQuery = usePGliteQuery;
8811
+ exports.useSchemaEntityFields = useSchemaEntityFields;
8050
8812
  exports.useSelectionContext = useSelectionContext;
8051
8813
  exports.useSelectionStore = useSelectionStore;
8052
8814
  exports.useSuspenseEntity = useSuspenseEntity;