@prometheus-ags/prometheus-entity-management 1.2.3 → 2.0.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/CHANGELOG.md +263 -0
- package/README.md +85 -6
- package/dist/index.d.mts +1004 -163
- package/dist/index.d.ts +1004 -163
- package/dist/index.js +2589 -1583
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2573 -1585
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,77 @@ import React$1, { ReactNode } from 'react';
|
|
|
5
5
|
import { ColumnDef as ColumnDef$1 } from '@tanstack/react-table';
|
|
6
6
|
import { PersistStorage } from 'zustand/middleware';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Typed errors used throughout 2.0 to drive retry policy and consumer
|
|
10
|
+
* UI decisions.
|
|
11
|
+
*
|
|
12
|
+
* Why two classes (not a discriminator field):
|
|
13
|
+
* - `instanceof` checks are zero-cost at runtime and survive bundler
|
|
14
|
+
* minification of property names.
|
|
15
|
+
* - Consumers can write `if (error instanceof TerminalError) renderInline()`
|
|
16
|
+
* without importing a type-narrowing helper.
|
|
17
|
+
* - The engine's retry policy is one `instanceof TransientError` check.
|
|
18
|
+
*
|
|
19
|
+
* 4xx → `TerminalError` (no retry — the request is structurally wrong:
|
|
20
|
+
* unauthorized, not-found, schema mismatch, validation failure).
|
|
21
|
+
*
|
|
22
|
+
* 5xx + network failures → `TransientError` (engine retries with
|
|
23
|
+
* exponential backoff up to `maxRetries`).
|
|
24
|
+
*
|
|
25
|
+
* Custom transports can throw either class. The default REST helper
|
|
26
|
+
* (`makeRestTransport`) maps HTTP status codes to the appropriate
|
|
27
|
+
* class automatically.
|
|
28
|
+
*
|
|
29
|
+
* Both classes preserve the original error via the standard
|
|
30
|
+
* `cause` option so stack traces survive the boundary.
|
|
31
|
+
*/
|
|
32
|
+
interface EntityErrorOptions {
|
|
33
|
+
/** HTTP status if the underlying transport was HTTP. */
|
|
34
|
+
status?: number;
|
|
35
|
+
/** Original thrown value (`Error`, `Response`, anything). */
|
|
36
|
+
cause?: unknown;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Permanent failure — do not retry. The request will not succeed by
|
|
40
|
+
* trying again with the same inputs.
|
|
41
|
+
*
|
|
42
|
+
* Typical sources: HTTP 4xx, missing tables, validation errors,
|
|
43
|
+
* permission denied, schema mismatches.
|
|
44
|
+
*/
|
|
45
|
+
declare class TerminalError extends Error {
|
|
46
|
+
readonly kind: "terminal";
|
|
47
|
+
readonly status?: number;
|
|
48
|
+
constructor(message: string, opts?: EntityErrorOptions);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Temporary failure — safe to retry. The engine will retry with
|
|
52
|
+
* exponential backoff up to the configured `maxRetries`.
|
|
53
|
+
*
|
|
54
|
+
* Typical sources: HTTP 5xx, network timeouts, fetch rejections,
|
|
55
|
+
* dropped sockets.
|
|
56
|
+
*/
|
|
57
|
+
declare class TransientError extends Error {
|
|
58
|
+
readonly kind: "transient";
|
|
59
|
+
readonly status?: number;
|
|
60
|
+
constructor(message: string, opts?: EntityErrorOptions);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Union of every typed error the library raises. Use on consumer-side
|
|
64
|
+
* `error` props when both classes are possible.
|
|
65
|
+
*/
|
|
66
|
+
type EntityError = TerminalError | TransientError;
|
|
67
|
+
/**
|
|
68
|
+
* Convert an unknown thrown value into a typed entity error.
|
|
69
|
+
*
|
|
70
|
+
* - Already-typed errors pass through.
|
|
71
|
+
* - HTTP-status-bearing errors become Terminal (4xx) or Transient (5xx).
|
|
72
|
+
* - `AbortError` / `DOMException` "AbortError" → Terminal (caller
|
|
73
|
+
* cancelled; not worth retrying).
|
|
74
|
+
* - Everything else → Transient (assume retryable; better than
|
|
75
|
+
* accidentally permanently failing on a one-off network blip).
|
|
76
|
+
*/
|
|
77
|
+
declare function toEntityError(err: unknown): EntityError;
|
|
78
|
+
|
|
8
79
|
/** Logical entity kind (e.g. `"Post"`). Used to partition the normalized graph. */
|
|
9
80
|
type EntityType = string;
|
|
10
81
|
/** Primary key for an entity within its `type`. Lists and relations reference this, not row copies. */
|
|
@@ -20,7 +91,7 @@ interface EntitySyncMetadata {
|
|
|
20
91
|
updatedAt: number | null;
|
|
21
92
|
}
|
|
22
93
|
/** Snapshot shape returned by sync-aware reads and graph-native query helpers. */
|
|
23
|
-
type EntitySnapshot<T extends
|
|
94
|
+
type EntitySnapshot<T extends object> = T & {
|
|
24
95
|
$synced: boolean;
|
|
25
96
|
$origin: SyncOrigin;
|
|
26
97
|
$updatedAt: number | null;
|
|
@@ -49,6 +120,14 @@ interface ListState {
|
|
|
49
120
|
isFetching: boolean;
|
|
50
121
|
isFetchingMore: boolean;
|
|
51
122
|
error: string | null;
|
|
123
|
+
/**
|
|
124
|
+
* Typed error instance for 2.0 hooks (`useEntities`, `useEntityQuery`).
|
|
125
|
+
* Carries `TerminalError` / `TransientError` so consumers can
|
|
126
|
+
* `instanceof`-check the failure mode without parsing the string in
|
|
127
|
+
* `error`. Both fields are written together by `setListError`; the
|
|
128
|
+
* string `error` field remains for back-compat with 1.x consumers.
|
|
129
|
+
*/
|
|
130
|
+
lastError: EntityError | null;
|
|
52
131
|
lastFetched: number | null;
|
|
53
132
|
stale: boolean;
|
|
54
133
|
currentPage: number | null;
|
|
@@ -131,8 +210,13 @@ interface GraphState {
|
|
|
131
210
|
setListFetching: (key: QueryKey, fetching: boolean) => void;
|
|
132
211
|
/** Pagination / “load more” in progress for the same list key. */
|
|
133
212
|
setListFetchingMore: (key: QueryKey, fetchingMore: boolean) => void;
|
|
134
|
-
/**
|
|
135
|
-
|
|
213
|
+
/**
|
|
214
|
+
* Record list fetch failure; clears both fetching flags.
|
|
215
|
+
* The optional `typed` argument is the typed `EntityError` instance
|
|
216
|
+
* (used by 2.0 hooks); when omitted only the string `error` field is
|
|
217
|
+
* populated (back-compat with 1.x callers).
|
|
218
|
+
*/
|
|
219
|
+
setListError: (key: QueryKey, error: string | null, typed?: EntityError | null) => void;
|
|
136
220
|
/** Mark a list query stale so hooks can refetch without discarding current ids (stale-while-revalidate). */
|
|
137
221
|
setListStale: (key: QueryKey, stale: boolean) => void;
|
|
138
222
|
/**
|
|
@@ -210,6 +294,21 @@ declare const useGraphStore: zustand.UseBoundStore<Omit<Omit<zustand.StoreApi<Gr
|
|
|
210
294
|
isFetching: boolean;
|
|
211
295
|
isFetchingMore: boolean;
|
|
212
296
|
error: string | null;
|
|
297
|
+
lastError: {
|
|
298
|
+
kind: "terminal";
|
|
299
|
+
status?: number | undefined;
|
|
300
|
+
name: string;
|
|
301
|
+
message: string;
|
|
302
|
+
stack?: string | undefined;
|
|
303
|
+
cause?: unknown;
|
|
304
|
+
} | {
|
|
305
|
+
kind: "transient";
|
|
306
|
+
status?: number | undefined;
|
|
307
|
+
name: string;
|
|
308
|
+
message: string;
|
|
309
|
+
stack?: string | undefined;
|
|
310
|
+
cause?: unknown;
|
|
311
|
+
} | null;
|
|
213
312
|
lastFetched: number | null;
|
|
214
313
|
stale: boolean;
|
|
215
314
|
currentPage: number | null;
|
|
@@ -239,7 +338,7 @@ declare const useGraphStore: zustand.UseBoundStore<Omit<Omit<zustand.StoreApi<Gr
|
|
|
239
338
|
insertIdInList: (key: QueryKey, id: EntityId, position: "start" | "end" | number) => void;
|
|
240
339
|
setListFetching: (key: QueryKey, fetching: boolean) => void;
|
|
241
340
|
setListFetchingMore: (key: QueryKey, fetchingMore: boolean) => void;
|
|
242
|
-
setListError: (key: QueryKey, error: string | null) => void;
|
|
341
|
+
setListError: (key: QueryKey, error: string | null, typed?: EntityError | null) => void;
|
|
243
342
|
setListStale: (key: QueryKey, stale: boolean) => void;
|
|
244
343
|
invalidateEntity: (type: EntityType, id?: EntityId) => void;
|
|
245
344
|
invalidateLists: (matcher: string | ((key: QueryKey) => boolean)) => void;
|
|
@@ -288,6 +387,21 @@ declare const useGraphStore: zustand.UseBoundStore<Omit<Omit<zustand.StoreApi<Gr
|
|
|
288
387
|
isFetching: boolean;
|
|
289
388
|
isFetchingMore: boolean;
|
|
290
389
|
error: string | null;
|
|
390
|
+
lastError: {
|
|
391
|
+
kind: "terminal";
|
|
392
|
+
status?: number | undefined;
|
|
393
|
+
name: string;
|
|
394
|
+
message: string;
|
|
395
|
+
stack?: string | undefined;
|
|
396
|
+
cause?: unknown;
|
|
397
|
+
} | {
|
|
398
|
+
kind: "transient";
|
|
399
|
+
status?: number | undefined;
|
|
400
|
+
name: string;
|
|
401
|
+
message: string;
|
|
402
|
+
stack?: string | undefined;
|
|
403
|
+
cause?: unknown;
|
|
404
|
+
} | null;
|
|
291
405
|
lastFetched: number | null;
|
|
292
406
|
stale: boolean;
|
|
293
407
|
currentPage: number | null;
|
|
@@ -317,7 +431,7 @@ declare const useGraphStore: zustand.UseBoundStore<Omit<Omit<zustand.StoreApi<Gr
|
|
|
317
431
|
insertIdInList: (key: QueryKey, id: EntityId, position: "start" | "end" | number) => void;
|
|
318
432
|
setListFetching: (key: QueryKey, fetching: boolean) => void;
|
|
319
433
|
setListFetchingMore: (key: QueryKey, fetchingMore: boolean) => void;
|
|
320
|
-
setListError: (key: QueryKey, error: string | null) => void;
|
|
434
|
+
setListError: (key: QueryKey, error: string | null, typed?: EntityError | null) => void;
|
|
321
435
|
setListStale: (key: QueryKey, stale: boolean) => void;
|
|
322
436
|
invalidateEntity: (type: EntityType, id?: EntityId) => void;
|
|
323
437
|
invalidateLists: (matcher: string | ((key: QueryKey) => boolean)) => void;
|
|
@@ -327,6 +441,481 @@ declare const useGraphStore: zustand.UseBoundStore<Omit<Omit<zustand.StoreApi<Gr
|
|
|
327
441
|
}) => void), shouldReplace: true): void;
|
|
328
442
|
}>;
|
|
329
443
|
|
|
444
|
+
/**
|
|
445
|
+
* Compiles a {@link FilterSpec} into a Prisma `where` object (plain JSON-serializable shape).
|
|
446
|
+
*
|
|
447
|
+
* Operator mapping matches common Prisma filter APIs: `eq` → `equals`, string ops use `mode: "insensitive"`,
|
|
448
|
+
* `nin` → `notIn`, `arrayContains` → `has`, `isNull` uses `null` / `{ not: null }` per `value`, and `isNotNull` → `{ not: null }`.
|
|
449
|
+
* Unsupported ops (`between`, `arrayOverlaps`, `matches`, `custom`) are omitted from the result.
|
|
450
|
+
*
|
|
451
|
+
* Top-level clause arrays are combined with `AND`. {@link FilterGroup} uses `AND` / `OR` to match `group.logic`.
|
|
452
|
+
*/
|
|
453
|
+
declare function toPrismaWhere(filter: FilterSpec): Record<string, unknown>;
|
|
454
|
+
/**
|
|
455
|
+
* Compiles a {@link SortSpec} into Prisma `orderBy` form: `[{ fieldName: "asc" | "desc" }, …]`.
|
|
456
|
+
* `nulls` and `comparator` on {@link SortClause} are ignored (local-only); extend callers if your Prisma version supports null ordering.
|
|
457
|
+
*/
|
|
458
|
+
declare function toPrismaOrderBy(sort: SortSpec): Record<string, string>[];
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Transport-agnostic comparison operators. Same spec can compile to REST, SQL, GraphQL, or local JS (`evaluator`).
|
|
462
|
+
* `custom` opts out of automatic serialization — use for predicates only the client can evaluate.
|
|
463
|
+
*/
|
|
464
|
+
type FilterOperator = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" | "contains" | "startsWith" | "endsWith" | "isNull" | "isNotNull" | "between" | "arrayContains" | "arrayOverlaps" | "matches" | "custom";
|
|
465
|
+
/** Atomic filter: field path, operator, optional value, and optional JS predicate for `custom`. */
|
|
466
|
+
interface FilterClause {
|
|
467
|
+
field: string;
|
|
468
|
+
op: FilterOperator;
|
|
469
|
+
value?: unknown;
|
|
470
|
+
predicate?: (fieldValue: unknown, entity: Record<string, unknown>) => boolean;
|
|
471
|
+
}
|
|
472
|
+
type FilterLogic = "and" | "or";
|
|
473
|
+
/** Nested boolean group so you can express `(A AND B) OR C` without losing structure when compiling to backends. */
|
|
474
|
+
interface FilterGroup {
|
|
475
|
+
logic: FilterLogic;
|
|
476
|
+
clauses: Array<FilterClause | FilterGroup>;
|
|
477
|
+
}
|
|
478
|
+
/** Top-level filter: flat AND list of clauses, or a recursive `FilterGroup`. */
|
|
479
|
+
type FilterSpec = FilterGroup | FilterClause[];
|
|
480
|
+
type SortDirection = "asc" | "desc";
|
|
481
|
+
/** Single sort key with optional null ordering and custom comparator for local sort parity with remote semantics. */
|
|
482
|
+
interface SortClause {
|
|
483
|
+
field: string;
|
|
484
|
+
direction: SortDirection;
|
|
485
|
+
nulls?: "first" | "last";
|
|
486
|
+
comparator?: (a: unknown, b: unknown) => number;
|
|
487
|
+
}
|
|
488
|
+
/** Ordered multi-key sort (stable application in `compareEntities`). */
|
|
489
|
+
type SortSpec = SortClause[];
|
|
490
|
+
/**
|
|
491
|
+
* Everything `useEntityView` needs to describe a virtualized collection: filters, sorts, and simple multi-field search.
|
|
492
|
+
* One descriptor can drive local evaluation, remote query compilation, or hybrid mode.
|
|
493
|
+
*/
|
|
494
|
+
interface ViewDescriptor {
|
|
495
|
+
filter?: FilterSpec;
|
|
496
|
+
sort?: SortSpec;
|
|
497
|
+
search?: {
|
|
498
|
+
query: string;
|
|
499
|
+
fields: string[];
|
|
500
|
+
minChars?: number;
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* How complete local graph data is relative to the view: **local** (all in memory), **remote** (server must filter/sort), **hybrid** (show local fast + remote reconcile).
|
|
505
|
+
*/
|
|
506
|
+
type CompletenessMode = "local" | "remote" | "hybrid";
|
|
507
|
+
/**
|
|
508
|
+
* Compile a view to flat REST query params (`sort`, `q`, and `field[op]=value` keys). Skips `custom` clauses — those cannot be expressed as strings.
|
|
509
|
+
*/
|
|
510
|
+
declare function toRestParams(view: ViewDescriptor): Record<string, string>;
|
|
511
|
+
/**
|
|
512
|
+
* Compile a view to parameterized SQL fragments for server-side filtering/sorting. Unknown ops become `TRUE` — validate or restrict ops at the edge.
|
|
513
|
+
*/
|
|
514
|
+
declare function toSQLClauses(view: ViewDescriptor): {
|
|
515
|
+
where: string;
|
|
516
|
+
orderBy: string;
|
|
517
|
+
params: unknown[];
|
|
518
|
+
};
|
|
519
|
+
/**
|
|
520
|
+
* Produce a GraphQL-variable-shaped object from a view (Hasura/Postgraphile-style `_op` maps). Intended as a starting point — wire to your actual schema.
|
|
521
|
+
*/
|
|
522
|
+
declare function toGraphQLVariables(view: ViewDescriptor): {
|
|
523
|
+
where?: Record<string, unknown>;
|
|
524
|
+
orderBy?: Array<Record<string, unknown>>;
|
|
525
|
+
search?: string;
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Normalize nested `FilterGroup` trees to a flat clause list for compilers that only understand atomic predicates.
|
|
530
|
+
*/
|
|
531
|
+
declare function flattenClauses(filter: FilterSpec): FilterClause[];
|
|
532
|
+
/** True if any clause requires client-side `predicate` logic — forces local/hybrid evaluation paths that cannot be pushed to generic REST/SQL. */
|
|
533
|
+
declare function hasCustomPredicates(filter: FilterSpec): boolean;
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* 2.0 transport contract.
|
|
537
|
+
*
|
|
538
|
+
* Why this exists: in 1.x each call site of `useEntityList` /
|
|
539
|
+
* `useEntityView` passed its own `fetch` closure + `normalize`
|
|
540
|
+
* callback. That leaked the transport contract to every consumer and
|
|
541
|
+
* was the structural cause of the Quick Stats trap — each widget could
|
|
542
|
+
* (and did) reinvent the same retry-loop bug.
|
|
543
|
+
*
|
|
544
|
+
* In 2.0 the transport is registered ONCE per entity type at app boot
|
|
545
|
+
* via `registerEntityTransport(type, transport)`. Hooks
|
|
546
|
+
* (`useEntities`, `useEntityQuery`) look up the registered transport
|
|
547
|
+
* by entity type — consumers never pass a fetcher.
|
|
548
|
+
*
|
|
549
|
+
* Transports are pluggable: a built-in `makeRestTransport` covers
|
|
550
|
+
* PostgREST / Supabase; future helpers can cover GraphQL, PGlite-direct,
|
|
551
|
+
* mock-in-memory, etc. The contract is intentionally tiny.
|
|
552
|
+
*/
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Transport-agnostic list query passed by `useEntities` / `useEntityQuery`
|
|
556
|
+
* down to the registered transport.
|
|
557
|
+
*
|
|
558
|
+
* The transport is responsible for compiling this into the
|
|
559
|
+
* transport-specific wire format (HTTP query string, GraphQL variables,
|
|
560
|
+
* SQL WHERE, in-memory predicate, etc.).
|
|
561
|
+
*/
|
|
562
|
+
interface ListQuery {
|
|
563
|
+
/** Optional filter; transport-agnostic, see `FilterSpec`. */
|
|
564
|
+
filter?: FilterSpec | null;
|
|
565
|
+
/** Optional sort spec; transport-agnostic. */
|
|
566
|
+
sort?: SortSpec | null;
|
|
567
|
+
/** Free-text search string; transport decides which fields to match. */
|
|
568
|
+
search?: string;
|
|
569
|
+
/** Page size hint. Transport may cap or ignore. */
|
|
570
|
+
limit?: number;
|
|
571
|
+
/** Opaque cursor for pagination (cursor or numeric offset). */
|
|
572
|
+
cursor?: string | number | null;
|
|
573
|
+
/** Aborts the request when fired. Transports MUST honour this. */
|
|
574
|
+
signal?: AbortSignal;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Page of results returned by `EntityTransport.list`.
|
|
578
|
+
*
|
|
579
|
+
* `total` is `null` when the backend doesn't report it cheaply
|
|
580
|
+
* (consumers should treat as "unknown" rather than "zero").
|
|
581
|
+
*
|
|
582
|
+
* `nextCursor` is `null`/`undefined` when there are no more pages.
|
|
583
|
+
*/
|
|
584
|
+
interface ListResult<T> {
|
|
585
|
+
rows: T[];
|
|
586
|
+
total: number | null;
|
|
587
|
+
nextCursor?: string | number | null;
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Operation flavour for a realtime change event.
|
|
591
|
+
*/
|
|
592
|
+
type ChangeOp = "insert" | "update" | "delete";
|
|
593
|
+
/**
|
|
594
|
+
* Realtime change event emitted by a transport's `subscribe`.
|
|
595
|
+
*
|
|
596
|
+
* For `delete` only `id` is meaningful; `row` MAY be omitted.
|
|
597
|
+
*/
|
|
598
|
+
interface ChangeEvent<T> {
|
|
599
|
+
op: ChangeOp;
|
|
600
|
+
id: string;
|
|
601
|
+
row?: T;
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* The full per-entity transport contract.
|
|
605
|
+
*
|
|
606
|
+
* One transport per entity type, registered at app boot. The hooks
|
|
607
|
+
* (`useEntities`, `useEntityQuery`) look it up via `getEntityTransport(type)`.
|
|
608
|
+
*
|
|
609
|
+
* Required: `identify`, `authoritative`, `list`.
|
|
610
|
+
* Optional: `get` (for single-row fetches), `subscribe` (for realtime),
|
|
611
|
+
* `staleTime` (hint for SWR).
|
|
612
|
+
*/
|
|
613
|
+
interface EntityTransport<T extends object> {
|
|
614
|
+
/**
|
|
615
|
+
* Derive the stable string id of a row. Used by the engine to write
|
|
616
|
+
* into the entity graph under the right id key.
|
|
617
|
+
*/
|
|
618
|
+
identify: (row: T) => string;
|
|
619
|
+
/**
|
|
620
|
+
* `true` when the local copy is considered authoritative (e.g. PGlite
|
|
621
|
+
* + Electric Tier-A sync) — consumers can render from cache without
|
|
622
|
+
* a remote round-trip on every mount.
|
|
623
|
+
*
|
|
624
|
+
* `false` when the remote is authoritative (Tier-B REST hybrid) — the
|
|
625
|
+
* cache is a hint, not the truth.
|
|
626
|
+
*/
|
|
627
|
+
authoritative: boolean;
|
|
628
|
+
/**
|
|
629
|
+
* Stale-time hint in ms. The engine SWR logic refetches when
|
|
630
|
+
* `Date.now() - lastFetched > staleTime`. Omit to inherit the engine
|
|
631
|
+
* default (30s).
|
|
632
|
+
*/
|
|
633
|
+
staleTime?: number;
|
|
634
|
+
/** Fetch a list. The signal in `q.signal` MUST be honoured. */
|
|
635
|
+
list: (q: ListQuery) => Promise<ListResult<T>>;
|
|
636
|
+
/** Fetch a single row by id. Optional. */
|
|
637
|
+
get?: (id: string, signal?: AbortSignal) => Promise<T | null>;
|
|
638
|
+
/**
|
|
639
|
+
* Subscribe to realtime change events for this entity type. Optional.
|
|
640
|
+
*
|
|
641
|
+
* Called by `useEntities` / `useEntityQuery` exactly once per
|
|
642
|
+
* subscriber-bearing key. The returned function MUST tear down all
|
|
643
|
+
* underlying resources (sockets, channels, intervals).
|
|
644
|
+
*/
|
|
645
|
+
subscribe?: (onChange: (ev: ChangeEvent<T>) => void) => () => void;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Process-global registry of `EntityTransport` instances by entity type.
|
|
650
|
+
*
|
|
651
|
+
* Why global state: every consumer of `useEntities("Client")` must
|
|
652
|
+
* resolve the SAME transport. Threading a registry through React
|
|
653
|
+
* context would require every test, every isolated story, every
|
|
654
|
+
* non-React caller (engine internals) to plumb the context — a tax
|
|
655
|
+
* that buys nothing. The 1.x library already used module-global state
|
|
656
|
+
* for the `useGraphStore` Zustand store; this follows the same shape.
|
|
657
|
+
*
|
|
658
|
+
* The registry is mutable: re-registering a type silently replaces the
|
|
659
|
+
* prior transport (tests rely on this; production code should only
|
|
660
|
+
* register once at app boot).
|
|
661
|
+
*/
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Register the transport for an entity type. Called once per type at
|
|
665
|
+
* app boot, typically from `src/shared/db/entity-transports.ts` in the
|
|
666
|
+
* consuming application.
|
|
667
|
+
*
|
|
668
|
+
* Re-registering REPLACES the prior transport — useful for tests, a
|
|
669
|
+
* footgun for production code. If you find yourself re-registering at
|
|
670
|
+
* runtime, you almost certainly want a different design.
|
|
671
|
+
*/
|
|
672
|
+
declare function registerEntityTransport<T extends object>(type: EntityType, transport: EntityTransport<T>): void;
|
|
673
|
+
/**
|
|
674
|
+
* Look up the transport for an entity type. Throws if none is
|
|
675
|
+
* registered — there is no "default" transport, by design.
|
|
676
|
+
*
|
|
677
|
+
* The cast to `EntityTransport<T>` is the API ergonomic
|
|
678
|
+
* compromise that lets call sites stay generic; the registry stores
|
|
679
|
+
* `EntityTransport<object>` because TypeScript can't otherwise unify
|
|
680
|
+
* heterogeneous rows in one map.
|
|
681
|
+
*/
|
|
682
|
+
declare function getEntityTransport<T extends object>(type: EntityType): EntityTransport<T>;
|
|
683
|
+
/**
|
|
684
|
+
* Test-only: clear ALL registered transports. Production code should
|
|
685
|
+
* never need this; tests use it to reset between specs.
|
|
686
|
+
*/
|
|
687
|
+
declare function __resetEntityTransports(): void;
|
|
688
|
+
/**
|
|
689
|
+
* Introspection: how many transports are currently registered.
|
|
690
|
+
* Useful for asserting in tests that boot wiring ran exactly once.
|
|
691
|
+
*/
|
|
692
|
+
declare function getRegisteredEntityTypes(): EntityType[];
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* `makeRestTransport` — built-in helper for the most common case: a
|
|
696
|
+
* Supabase / PostgREST backend reached through a `SupabaseClient`-like
|
|
697
|
+
* object.
|
|
698
|
+
*
|
|
699
|
+
* Why a helper (not a class): consumers stay declarative —
|
|
700
|
+
* registerEntityTransport("Client",
|
|
701
|
+
* makeRestTransport<Client>({ supabase, table: "client" }));
|
|
702
|
+
* — and the library never imports `@supabase/supabase-js` directly
|
|
703
|
+
* (peer-dep-free).
|
|
704
|
+
*
|
|
705
|
+
* The transport:
|
|
706
|
+
* - Compiles `ListQuery` (filter / sort / search / cursor / limit)
|
|
707
|
+
* into a PostgREST query via the supabase-js builder.
|
|
708
|
+
* - Maps HTTP status to `TerminalError` (4xx) or `TransientError`
|
|
709
|
+
* (5xx / network).
|
|
710
|
+
* - Honours `AbortSignal` via supabase-js `.abortSignal(signal)`.
|
|
711
|
+
* - Returns `total` from PostgREST `count: 'exact'` when requested.
|
|
712
|
+
*/
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* Minimal slice of the `@supabase/supabase-js` `SupabaseClient` we use.
|
|
716
|
+
* Declared structurally so the library does not need to import the
|
|
717
|
+
* package as a dependency (peer-dep-free).
|
|
718
|
+
*/
|
|
719
|
+
interface SupabaseLike {
|
|
720
|
+
from: (table: string) => SupabaseQueryBuilderLike;
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Subset of the supabase-js builder we exercise. Each call returns the
|
|
724
|
+
* same builder for chaining; `then`-able at the end resolves to
|
|
725
|
+
* `{ data, error, count, status }`.
|
|
726
|
+
*/
|
|
727
|
+
interface SupabaseQueryBuilderLike {
|
|
728
|
+
select: (columns: string, opts?: {
|
|
729
|
+
count?: "exact" | "planned" | "estimated";
|
|
730
|
+
head?: boolean;
|
|
731
|
+
}) => SupabaseQueryBuilderLike;
|
|
732
|
+
eq: (col: string, val: unknown) => SupabaseQueryBuilderLike;
|
|
733
|
+
neq: (col: string, val: unknown) => SupabaseQueryBuilderLike;
|
|
734
|
+
gt: (col: string, val: unknown) => SupabaseQueryBuilderLike;
|
|
735
|
+
gte: (col: string, val: unknown) => SupabaseQueryBuilderLike;
|
|
736
|
+
lt: (col: string, val: unknown) => SupabaseQueryBuilderLike;
|
|
737
|
+
lte: (col: string, val: unknown) => SupabaseQueryBuilderLike;
|
|
738
|
+
in: (col: string, vals: readonly unknown[]) => SupabaseQueryBuilderLike;
|
|
739
|
+
ilike: (col: string, pattern: string) => SupabaseQueryBuilderLike;
|
|
740
|
+
is: (col: string, val: null | boolean) => SupabaseQueryBuilderLike;
|
|
741
|
+
or: (filter: string) => SupabaseQueryBuilderLike;
|
|
742
|
+
order: (col: string, opts?: {
|
|
743
|
+
ascending?: boolean;
|
|
744
|
+
nullsFirst?: boolean;
|
|
745
|
+
}) => SupabaseQueryBuilderLike;
|
|
746
|
+
range: (from: number, to: number) => SupabaseQueryBuilderLike;
|
|
747
|
+
limit: (n: number) => SupabaseQueryBuilderLike;
|
|
748
|
+
abortSignal?: (signal: AbortSignal) => SupabaseQueryBuilderLike;
|
|
749
|
+
then: <TResult1 = unknown, TResult2 = never>(onfulfilled?: ((value: {
|
|
750
|
+
data: unknown;
|
|
751
|
+
error: unknown;
|
|
752
|
+
count?: number | null;
|
|
753
|
+
status?: number;
|
|
754
|
+
}) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null) => Promise<TResult1 | TResult2>;
|
|
755
|
+
}
|
|
756
|
+
/** Options for `makeRestTransport`. */
|
|
757
|
+
interface MakeRestTransportOptions<T extends object> {
|
|
758
|
+
/** A `@supabase/supabase-js` client (or any structurally-compatible thing). */
|
|
759
|
+
supabase: SupabaseLike;
|
|
760
|
+
/** PostgREST table name. */
|
|
761
|
+
table: string;
|
|
762
|
+
/** Columns to select (default `"*"`). */
|
|
763
|
+
select?: string;
|
|
764
|
+
/** Stable id derivation. Defaults to `(row) => String(row.id)`. */
|
|
765
|
+
identify?: (row: T) => string;
|
|
766
|
+
/** Whether the local cache is treated as authoritative. */
|
|
767
|
+
authoritative?: boolean;
|
|
768
|
+
/** Stale-time hint in ms. */
|
|
769
|
+
staleTime?: number;
|
|
770
|
+
/** Free-text search column list (compiled to `or=col.ilike.*query*,…`). */
|
|
771
|
+
searchColumns?: string[];
|
|
772
|
+
/** Default page size when `ListQuery.limit` is absent. */
|
|
773
|
+
defaultLimit?: number;
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Build an `EntityTransport<T>` from a Supabase client + a table name.
|
|
777
|
+
*
|
|
778
|
+
* The returned transport:
|
|
779
|
+
* - Maps `ListQuery.filter` clauses to PostgREST operators (`eq`, `gt`,
|
|
780
|
+
* `in`, `ilike`, `is null`, etc.).
|
|
781
|
+
* - Compiles `ListQuery.search` into an `or=` clause across
|
|
782
|
+
* `searchColumns`.
|
|
783
|
+
* - Uses `count: 'exact'` on first page to surface `total`.
|
|
784
|
+
* - Throws `TerminalError` on 4xx (no retry); `TransientError` on 5xx
|
|
785
|
+
* or network failure.
|
|
786
|
+
* - Honours `signal` via `.abortSignal(signal)` (supabase-js >= 2.39).
|
|
787
|
+
*/
|
|
788
|
+
declare function makeRestTransport<T extends object>(opts: MakeRestTransportOptions<T>): EntityTransport<T>;
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* `useEntities` — thin 2.0 hook (5-field API).
|
|
792
|
+
*
|
|
793
|
+
* Replaces the `useEntityList(opts)` pattern where each call site carried
|
|
794
|
+
* its own `fetch` closure, query-key shape, and retry logic. Instead:
|
|
795
|
+
*
|
|
796
|
+
* 1. Register a transport once at app boot:
|
|
797
|
+
* `registerEntityTransport("Invoice", makeRestTransport({ supabase, table: "invoice" }))`
|
|
798
|
+
*
|
|
799
|
+
* 2. Consume anywhere:
|
|
800
|
+
* `const { items, isLoading, isError, error } = useEntities<Invoice>("Invoice")`
|
|
801
|
+
*
|
|
802
|
+
* - 4xx from transport → `TerminalError`, no retry, `isError: true`, `isLoading: false`
|
|
803
|
+
* - 5xx/network → `TransientError`, up to `maxRetries` with exponential back-off
|
|
804
|
+
* - `enabled: false` → no fetch, `isLoading: false` immediately
|
|
805
|
+
* - SWR: within `staleTime` (from transport or engine default) → cached rows, no refetch
|
|
806
|
+
* - AbortController per fetch; aborted on unmount, key change, or `refetch()`
|
|
807
|
+
* - Transport `subscribe` wired on mount, torn down on unmount
|
|
808
|
+
*/
|
|
809
|
+
|
|
810
|
+
/** Subset of `ListQuery` that callers may pass alongside `enabled`. */
|
|
811
|
+
interface UseEntitiesOptions {
|
|
812
|
+
filter?: FilterSpec | null;
|
|
813
|
+
sort?: SortSpec | null;
|
|
814
|
+
search?: string;
|
|
815
|
+
limit?: number;
|
|
816
|
+
cursor?: string | number | null;
|
|
817
|
+
enabled?: boolean;
|
|
818
|
+
}
|
|
819
|
+
/** Five-field return — the entirety of what a list consumer needs for the common case. */
|
|
820
|
+
interface UseEntitiesResult<T> {
|
|
821
|
+
/** Resolved entity rows in the graph for this query, in server order. */
|
|
822
|
+
items: T[];
|
|
823
|
+
/** True only while the very first attempt is in-flight with no cached rows yet. */
|
|
824
|
+
isLoading: boolean;
|
|
825
|
+
/** True when the last attempt ended with any error (terminal or transient). */
|
|
826
|
+
isError: boolean;
|
|
827
|
+
/** Typed error instance — `instanceof TerminalError` (4xx) or `instanceof TransientError` (5xx/network). */
|
|
828
|
+
error: TerminalError | TransientError | null;
|
|
829
|
+
/** Manually trigger a fresh fetch (bypasses staleTime). */
|
|
830
|
+
refetch: () => void;
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Thin replacement for `useEntityList`.
|
|
834
|
+
* Looks up the registered `EntityTransport<T>` for `type` and drives a
|
|
835
|
+
* Zustand-backed SWR cycle. Returns `{ items, isLoading, isError, error, refetch }`.
|
|
836
|
+
*/
|
|
837
|
+
declare function useEntities<T extends object>(type: EntityType, options?: UseEntitiesOptions): UseEntitiesResult<T>;
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* `useEntityQuery` — rich 2.0 hook (replaces `useEntityView`).
|
|
841
|
+
*
|
|
842
|
+
* Same feature surface as `useEntityView` (view descriptor, hybrid mode,
|
|
843
|
+
* pagination, realtime sorted insertion, toolbar setters) but transport is
|
|
844
|
+
* looked up from the registry — callers no longer pass `remoteFetch`.
|
|
845
|
+
*
|
|
846
|
+
* Usage:
|
|
847
|
+
* registerEntityTransport("Client", makeRestTransport({ supabase, table: "client" }));
|
|
848
|
+
*
|
|
849
|
+
* const { items, setFilter, setSort, setSearch, fetchNextPage, error } =
|
|
850
|
+
* useEntityQuery<Client>("Client", { view: defaultView });
|
|
851
|
+
*/
|
|
852
|
+
|
|
853
|
+
interface UseEntityQueryOptions {
|
|
854
|
+
/** Initial view descriptor (filter/sort/search). */
|
|
855
|
+
view?: ViewDescriptor;
|
|
856
|
+
/** Force a completeness mode instead of auto-detecting. */
|
|
857
|
+
mode?: CompletenessMode;
|
|
858
|
+
/** Skip all fetching when false. `isLoading` is immediately `false`. */
|
|
859
|
+
enabled?: boolean;
|
|
860
|
+
/** SSR-seed ids for the base list slot (avoids flash-of-empty-state). */
|
|
861
|
+
initialIds?: EntityId[];
|
|
862
|
+
/** SSR-seed total for completeness heuristics. */
|
|
863
|
+
initialTotal?: number;
|
|
864
|
+
/** Debounce delay (ms) for view changes before a remote re-fetch fires. */
|
|
865
|
+
remoteDebounce?: number;
|
|
866
|
+
}
|
|
867
|
+
interface UseEntityQueryResult<T> {
|
|
868
|
+
/** Projected entity rows visible through the current view. */
|
|
869
|
+
items: T[];
|
|
870
|
+
/** All ids in the projected view (for virtualised renderers). */
|
|
871
|
+
viewIds: EntityId[];
|
|
872
|
+
/** Server-reported total or local count if complete, else null. */
|
|
873
|
+
viewTotal: number | null;
|
|
874
|
+
/** True while the very first page is loading with zero cached rows. */
|
|
875
|
+
isLoading: boolean;
|
|
876
|
+
/** True while any fetch (initial or page) is in-flight. */
|
|
877
|
+
isFetching: boolean;
|
|
878
|
+
/** True while a paginated "load more" fetch is in-flight. */
|
|
879
|
+
isFetchingMore: boolean;
|
|
880
|
+
/** True when the last attempt ended with any error. */
|
|
881
|
+
isError: boolean;
|
|
882
|
+
/**
|
|
883
|
+
* Typed error — `instanceof TerminalError` (4xx) or
|
|
884
|
+
* `instanceof TransientError` (5xx/network). `null` on success.
|
|
885
|
+
*/
|
|
886
|
+
error: TerminalError | TransientError | null;
|
|
887
|
+
/** True when there are more pages to load. */
|
|
888
|
+
hasNextPage: boolean;
|
|
889
|
+
/** Load the next page of results. */
|
|
890
|
+
fetchNextPage: () => void;
|
|
891
|
+
/** True when `completenessMode === "hybrid"` and remote is still in-flight while local rows are displayed. */
|
|
892
|
+
isShowingLocalPending: boolean;
|
|
893
|
+
/** Whether local graph data is complete for the current view. */
|
|
894
|
+
isLocallyComplete: boolean;
|
|
895
|
+
/** Resolved completeness mode for the current view. */
|
|
896
|
+
completenessMode: CompletenessMode;
|
|
897
|
+
/** Merge partial view descriptor updates. */
|
|
898
|
+
setView: (v: Partial<ViewDescriptor>) => void;
|
|
899
|
+
/** Replace the active filter spec. */
|
|
900
|
+
setFilter: (f: FilterSpec | null) => void;
|
|
901
|
+
/** Replace the active sort spec. */
|
|
902
|
+
setSort: (s: SortSpec | null) => void;
|
|
903
|
+
/** Update free-text search query. */
|
|
904
|
+
setSearch: (q: string) => void;
|
|
905
|
+
/** Reset view to the initial descriptor. */
|
|
906
|
+
clearView: () => void;
|
|
907
|
+
/** Force a fresh fetch (bypasses staleTime). */
|
|
908
|
+
refetch: () => void;
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* Rich list hook: view descriptor, local/remote/hybrid completeness, pagination,
|
|
912
|
+
* realtime sorted insertion, typed errors — all backed by the transport registry.
|
|
913
|
+
*
|
|
914
|
+
* @param type - Registered entity type key (e.g. `"Client"`)
|
|
915
|
+
* @param opts - View descriptor, mode override, SSR seeds, enabled gate
|
|
916
|
+
*/
|
|
917
|
+
declare function useEntityQuery<T extends object>(type: EntityType, opts?: UseEntityQueryOptions): UseEntityQueryResult<T>;
|
|
918
|
+
|
|
330
919
|
type GraphStore = ReturnType<typeof useGraphStore.getState>;
|
|
331
920
|
type GraphIncludeMap = Record<string, GraphIncludeRelation>;
|
|
332
921
|
type GraphIncludeRelation = {
|
|
@@ -358,7 +947,7 @@ type GraphIncludeRelation = {
|
|
|
358
947
|
};
|
|
359
948
|
include?: GraphIncludeMap;
|
|
360
949
|
};
|
|
361
|
-
interface GraphQueryOptions<TEntity extends
|
|
950
|
+
interface GraphQueryOptions<TEntity extends object> {
|
|
362
951
|
type: EntityType;
|
|
363
952
|
id?: EntityId;
|
|
364
953
|
ids?: EntityId[];
|
|
@@ -369,10 +958,10 @@ interface GraphQueryOptions<TEntity extends Record<string, unknown>> {
|
|
|
369
958
|
select?: ((entity: Record<string, unknown>) => unknown) | string[];
|
|
370
959
|
}
|
|
371
960
|
type ProjectedRow = Record<string, unknown>;
|
|
372
|
-
declare function queryOnce<TEntity extends
|
|
961
|
+
declare function queryOnce<TEntity extends object>(opts: GraphQueryOptions<TEntity> & {
|
|
373
962
|
id: EntityId;
|
|
374
963
|
}): ProjectedRow | null;
|
|
375
|
-
declare function queryOnce<TEntity extends
|
|
964
|
+
declare function queryOnce<TEntity extends object>(opts: GraphQueryOptions<TEntity>): ProjectedRow[];
|
|
376
965
|
declare const selectGraph: typeof queryOnce;
|
|
377
966
|
|
|
378
967
|
interface GraphDataSnapshot {
|
|
@@ -445,97 +1034,6 @@ interface GraphEffectHandle {
|
|
|
445
1034
|
}
|
|
446
1035
|
declare function createGraphEffect<T>(opts: GraphEffectOptions<T>): GraphEffectHandle;
|
|
447
1036
|
|
|
448
|
-
/**
|
|
449
|
-
* Compiles a {@link FilterSpec} into a Prisma `where` object (plain JSON-serializable shape).
|
|
450
|
-
*
|
|
451
|
-
* Operator mapping matches common Prisma filter APIs: `eq` → `equals`, string ops use `mode: "insensitive"`,
|
|
452
|
-
* `nin` → `notIn`, `arrayContains` → `has`, `isNull` uses `null` / `{ not: null }` per `value`, and `isNotNull` → `{ not: null }`.
|
|
453
|
-
* Unsupported ops (`between`, `arrayOverlaps`, `matches`, `custom`) are omitted from the result.
|
|
454
|
-
*
|
|
455
|
-
* Top-level clause arrays are combined with `AND`. {@link FilterGroup} uses `AND` / `OR` to match `group.logic`.
|
|
456
|
-
*/
|
|
457
|
-
declare function toPrismaWhere(filter: FilterSpec): Record<string, unknown>;
|
|
458
|
-
/**
|
|
459
|
-
* Compiles a {@link SortSpec} into Prisma `orderBy` form: `[{ fieldName: "asc" | "desc" }, …]`.
|
|
460
|
-
* `nulls` and `comparator` on {@link SortClause} are ignored (local-only); extend callers if your Prisma version supports null ordering.
|
|
461
|
-
*/
|
|
462
|
-
declare function toPrismaOrderBy(sort: SortSpec): Record<string, string>[];
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* Transport-agnostic comparison operators. Same spec can compile to REST, SQL, GraphQL, or local JS (`evaluator`).
|
|
466
|
-
* `custom` opts out of automatic serialization — use for predicates only the client can evaluate.
|
|
467
|
-
*/
|
|
468
|
-
type FilterOperator = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" | "contains" | "startsWith" | "endsWith" | "isNull" | "isNotNull" | "between" | "arrayContains" | "arrayOverlaps" | "matches" | "custom";
|
|
469
|
-
/** Atomic filter: field path, operator, optional value, and optional JS predicate for `custom`. */
|
|
470
|
-
interface FilterClause {
|
|
471
|
-
field: string;
|
|
472
|
-
op: FilterOperator;
|
|
473
|
-
value?: unknown;
|
|
474
|
-
predicate?: (fieldValue: unknown, entity: Record<string, unknown>) => boolean;
|
|
475
|
-
}
|
|
476
|
-
type FilterLogic = "and" | "or";
|
|
477
|
-
/** Nested boolean group so you can express `(A AND B) OR C` without losing structure when compiling to backends. */
|
|
478
|
-
interface FilterGroup {
|
|
479
|
-
logic: FilterLogic;
|
|
480
|
-
clauses: Array<FilterClause | FilterGroup>;
|
|
481
|
-
}
|
|
482
|
-
/** Top-level filter: flat AND list of clauses, or a recursive `FilterGroup`. */
|
|
483
|
-
type FilterSpec = FilterGroup | FilterClause[];
|
|
484
|
-
type SortDirection = "asc" | "desc";
|
|
485
|
-
/** Single sort key with optional null ordering and custom comparator for local sort parity with remote semantics. */
|
|
486
|
-
interface SortClause {
|
|
487
|
-
field: string;
|
|
488
|
-
direction: SortDirection;
|
|
489
|
-
nulls?: "first" | "last";
|
|
490
|
-
comparator?: (a: unknown, b: unknown) => number;
|
|
491
|
-
}
|
|
492
|
-
/** Ordered multi-key sort (stable application in `compareEntities`). */
|
|
493
|
-
type SortSpec = SortClause[];
|
|
494
|
-
/**
|
|
495
|
-
* Everything `useEntityView` needs to describe a virtualized collection: filters, sorts, and simple multi-field search.
|
|
496
|
-
* One descriptor can drive local evaluation, remote query compilation, or hybrid mode.
|
|
497
|
-
*/
|
|
498
|
-
interface ViewDescriptor {
|
|
499
|
-
filter?: FilterSpec;
|
|
500
|
-
sort?: SortSpec;
|
|
501
|
-
search?: {
|
|
502
|
-
query: string;
|
|
503
|
-
fields: string[];
|
|
504
|
-
minChars?: number;
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
/**
|
|
508
|
-
* How complete local graph data is relative to the view: **local** (all in memory), **remote** (server must filter/sort), **hybrid** (show local fast + remote reconcile).
|
|
509
|
-
*/
|
|
510
|
-
type CompletenessMode = "local" | "remote" | "hybrid";
|
|
511
|
-
/**
|
|
512
|
-
* Compile a view to flat REST query params (`sort`, `q`, and `field[op]=value` keys). Skips `custom` clauses — those cannot be expressed as strings.
|
|
513
|
-
*/
|
|
514
|
-
declare function toRestParams(view: ViewDescriptor): Record<string, string>;
|
|
515
|
-
/**
|
|
516
|
-
* Compile a view to parameterized SQL fragments for server-side filtering/sorting. Unknown ops become `TRUE` — validate or restrict ops at the edge.
|
|
517
|
-
*/
|
|
518
|
-
declare function toSQLClauses(view: ViewDescriptor): {
|
|
519
|
-
where: string;
|
|
520
|
-
orderBy: string;
|
|
521
|
-
params: unknown[];
|
|
522
|
-
};
|
|
523
|
-
/**
|
|
524
|
-
* Produce a GraphQL-variable-shaped object from a view (Hasura/Postgraphile-style `_op` maps). Intended as a starting point — wire to your actual schema.
|
|
525
|
-
*/
|
|
526
|
-
declare function toGraphQLVariables(view: ViewDescriptor): {
|
|
527
|
-
where?: Record<string, unknown>;
|
|
528
|
-
orderBy?: Array<Record<string, unknown>>;
|
|
529
|
-
search?: string;
|
|
530
|
-
};
|
|
531
|
-
|
|
532
|
-
/**
|
|
533
|
-
* Normalize nested `FilterGroup` trees to a flat clause list for compilers that only understand atomic predicates.
|
|
534
|
-
*/
|
|
535
|
-
declare function flattenClauses(filter: FilterSpec): FilterClause[];
|
|
536
|
-
/** True if any clause requires client-side `predicate` logic — forces local/hybrid evaluation paths that cannot be pushed to generic REST/SQL. */
|
|
537
|
-
declare function hasCustomPredicates(filter: FilterSpec): boolean;
|
|
538
|
-
|
|
539
1037
|
/**
|
|
540
1038
|
* Process-wide defaults for stale times, retries, and background revalidation.
|
|
541
1039
|
* Keeps hook signatures small: `useEntity` / `useEntityList` merge these with per-query overrides.
|
|
@@ -555,7 +1053,7 @@ interface EngineOptions {
|
|
|
555
1053
|
* Declarative **instruction** for loading one entity: wire transport (`fetch`), normalization, and graph writes.
|
|
556
1054
|
* Hooks pass this to `fetchEntity`; the graph remains source of truth after success.
|
|
557
1055
|
*/
|
|
558
|
-
interface EntityQueryOptions<TRaw, TEntity extends
|
|
1056
|
+
interface EntityQueryOptions<TRaw, TEntity extends object> {
|
|
559
1057
|
type: EntityType;
|
|
560
1058
|
id: EntityId | null | undefined;
|
|
561
1059
|
fetch: (id: EntityId) => Promise<TRaw>;
|
|
@@ -579,8 +1077,8 @@ interface ListFetchParams {
|
|
|
579
1077
|
*/
|
|
580
1078
|
interface ListResponse<T> {
|
|
581
1079
|
items: T[];
|
|
582
|
-
total?: number;
|
|
583
|
-
nextCursor?: string;
|
|
1080
|
+
total?: number | null;
|
|
1081
|
+
nextCursor?: string | null;
|
|
584
1082
|
prevCursor?: string;
|
|
585
1083
|
hasNextPage?: boolean;
|
|
586
1084
|
hasPrevPage?: boolean;
|
|
@@ -591,7 +1089,7 @@ interface ListResponse<T> {
|
|
|
591
1089
|
* Declarative **instruction** for a collection query: stable `queryKey`, fetcher, and per-row normalization into the graph.
|
|
592
1090
|
* `mode` controls whether a fetch replaces ids or appends (infinite scroll) when used with load-more.
|
|
593
1091
|
*/
|
|
594
|
-
interface ListQueryOptions<TRaw, TEntity extends
|
|
1092
|
+
interface ListQueryOptions<TRaw, TEntity extends object> {
|
|
595
1093
|
type: EntityType;
|
|
596
1094
|
queryKey: unknown[];
|
|
597
1095
|
fetch: (params: ListFetchParams) => Promise<ListResponse<TRaw>>;
|
|
@@ -633,12 +1131,12 @@ declare function configureEngine(opts: EngineOptions): void;
|
|
|
633
1131
|
* Run a single-entity fetch with dedupe, retries, normalization, and graph updates.
|
|
634
1132
|
* Call from hooks/adapters — not from presentational components.
|
|
635
1133
|
*/
|
|
636
|
-
declare function fetchEntity<TRaw, TEntity extends
|
|
1134
|
+
declare function fetchEntity<TRaw, TEntity extends object>(opts: EntityQueryOptions<TRaw, TEntity>, engineOpts: Required<EngineOptions>): Promise<void>;
|
|
637
1135
|
/**
|
|
638
1136
|
* Fetch a list page: upserts all rows, writes ids to the list key, supports append mode for pagination.
|
|
639
1137
|
* @param isLoadMore - When true, uses a separate dedupe key and `appendListResult` / `setListFetchingMore`.
|
|
640
1138
|
*/
|
|
641
|
-
declare function fetchList<TRaw, TEntity extends
|
|
1139
|
+
declare function fetchList<TRaw, TEntity extends object>(opts: ListQueryOptions<TRaw, TEntity>, params: ListFetchParams, engineOpts: Required<EngineOptions>, isLoadMore?: boolean): Promise<void>;
|
|
642
1140
|
|
|
643
1141
|
/**
|
|
644
1142
|
* Precompiled transport payloads for one view snapshot — pass to REST, GraphQL, or SQL backends without re-deriving from `ViewDescriptor`.
|
|
@@ -653,7 +1151,7 @@ interface ViewFetchParams {
|
|
|
653
1151
|
* Configure a **live view** over a base list: filter/sort/search in JS when data is complete, or compile the same spec to remote params when not.
|
|
654
1152
|
* `baseQueryKey` identifies the underlying id list in the graph; the hook may create additional keys for remote result sets.
|
|
655
1153
|
*/
|
|
656
|
-
interface UseEntityViewOptions<TEntity extends
|
|
1154
|
+
interface UseEntityViewOptions<TEntity extends object> {
|
|
657
1155
|
type: EntityType;
|
|
658
1156
|
baseQueryKey: unknown[];
|
|
659
1157
|
view: ViewDescriptor;
|
|
@@ -661,7 +1159,7 @@ interface UseEntityViewOptions<TEntity extends Record<string, unknown>> {
|
|
|
661
1159
|
remoteFetch?: (params: ViewFetchParams) => Promise<ListResponse<TEntity>>;
|
|
662
1160
|
normalize?: (raw: TEntity) => {
|
|
663
1161
|
id: EntityId;
|
|
664
|
-
data:
|
|
1162
|
+
data: TEntity;
|
|
665
1163
|
};
|
|
666
1164
|
remoteDebounce?: number;
|
|
667
1165
|
staleTime?: number;
|
|
@@ -683,7 +1181,14 @@ interface UseEntityViewResult<TEntity> {
|
|
|
683
1181
|
isFetching: boolean;
|
|
684
1182
|
isRemoteFetching: boolean;
|
|
685
1183
|
isShowingLocalPending: boolean;
|
|
1184
|
+
/**
|
|
1185
|
+
* Last error message from the remote fetcher (or the cached base
|
|
1186
|
+
* list state). `null` when the latest attempt succeeded or no
|
|
1187
|
+
* attempt has been made.
|
|
1188
|
+
*/
|
|
686
1189
|
error: string | null;
|
|
1190
|
+
/** Convenience for `error !== null`. TanStack-Query-style. */
|
|
1191
|
+
isError: boolean;
|
|
687
1192
|
hasNextPage: boolean;
|
|
688
1193
|
fetchNextPage: () => void;
|
|
689
1194
|
isLocallyComplete: boolean;
|
|
@@ -714,7 +1219,13 @@ interface UseEntityViewResult<TEntity> {
|
|
|
714
1219
|
* });
|
|
715
1220
|
* ```
|
|
716
1221
|
*/
|
|
717
|
-
|
|
1222
|
+
/**
|
|
1223
|
+
* @deprecated Use `useEntityQuery` from `"@prometheus-ags/prometheus-entity-management"` instead.
|
|
1224
|
+
* Register a transport: `registerEntityTransport("Foo", makeRestTransport({ supabase, table: "foo" }))`
|
|
1225
|
+
* Then consume: `const { items, setFilter, setSort } = useEntityQuery<Foo>("Foo", { view })`
|
|
1226
|
+
* `useEntityView` will be removed in a future major version.
|
|
1227
|
+
*/
|
|
1228
|
+
declare function useEntityView<TEntity extends object>(opts: UseEntityViewOptions<TEntity>): UseEntityViewResult<TEntity>;
|
|
718
1229
|
|
|
719
1230
|
/** UI mode for a single CRUD surface: drives which panels/forms are active without scattering boolean flags. */
|
|
720
1231
|
type CRUDMode = "list" | "detail" | "edit" | "create";
|
|
@@ -722,7 +1233,7 @@ type CRUDMode = "list" | "detail" | "edit" | "create";
|
|
|
722
1233
|
* Wire one entity type into list+detail+forms: remote list via `useEntityView`, optional detail fetch, and create/update/delete callbacks.
|
|
723
1234
|
* Mutations call `cascadeInvalidation` on success so related lists/entities refresh per registered schemas.
|
|
724
1235
|
*/
|
|
725
|
-
interface CRUDOptions<TEntity extends
|
|
1236
|
+
interface CRUDOptions<TEntity extends object> {
|
|
726
1237
|
type: EntityType;
|
|
727
1238
|
listQueryKey: unknown[];
|
|
728
1239
|
listFetch: (params: ViewFetchParams) => Promise<ListResponse<TEntity>>;
|
|
@@ -744,9 +1255,9 @@ interface CRUDOptions<TEntity extends Record<string, unknown>> {
|
|
|
744
1255
|
clearSelectionAfterDelete?: boolean;
|
|
745
1256
|
}
|
|
746
1257
|
/** Public field input for CRUD setters: supports classic `keyof T` calls and dotted nested paths for JSON-backed forms. */
|
|
747
|
-
type EntityFieldPath<TEntity extends
|
|
1258
|
+
type EntityFieldPath<TEntity extends object> = keyof TEntity | string;
|
|
748
1259
|
/** Tracks which fields diverge from loaded detail — edit buffer stays in React state so other views keep showing canonical graph data until save. */
|
|
749
|
-
interface DirtyFields<TEntity extends
|
|
1260
|
+
interface DirtyFields<TEntity extends object> {
|
|
750
1261
|
changed: ReadonlySet<EntityFieldPath<TEntity>>;
|
|
751
1262
|
isDirty: boolean;
|
|
752
1263
|
}
|
|
@@ -754,7 +1265,7 @@ interface DirtyFields<TEntity extends Record<string, unknown>> {
|
|
|
754
1265
|
* Everything a CRUD screen needs: composed `list` view, selection, detail subscription, relation joins, edit/create buffers, and mutating actions.
|
|
755
1266
|
* `applyOptimistic` is the escape hatch to mirror the buffer into `patches` for instant sliders/toggles without committing `save` yet.
|
|
756
1267
|
*/
|
|
757
|
-
interface CRUDState<TEntity extends
|
|
1268
|
+
interface CRUDState<TEntity extends object> {
|
|
758
1269
|
mode: CRUDMode;
|
|
759
1270
|
setMode: (mode: CRUDMode) => void;
|
|
760
1271
|
list: UseEntityViewResult<TEntity>;
|
|
@@ -797,7 +1308,7 @@ interface CRUDState<TEntity extends Record<string, unknown>> {
|
|
|
797
1308
|
* @param opts - `CRUDOptions` for type, list key/fetch, normalization, lifecycle callbacks
|
|
798
1309
|
* @returns `CRUDState` with list/detail/edit/create controls
|
|
799
1310
|
*/
|
|
800
|
-
declare function useEntityCRUD<TEntity extends
|
|
1311
|
+
declare function useEntityCRUD<TEntity extends object>(opts: CRUDOptions<TEntity>): CRUDState<TEntity>;
|
|
801
1312
|
|
|
802
1313
|
type FieldType = "text" | "textarea" | "number" | "email" | "url" | "date" | "boolean" | "enum" | "json" | "markdown" | "custom";
|
|
803
1314
|
interface FieldDescriptor<TEntity> {
|
|
@@ -826,7 +1337,7 @@ declare function Sheet({ open, onClose, title, subtitle, children, footer, width
|
|
|
826
1337
|
footer?: React$1.ReactNode;
|
|
827
1338
|
width?: string;
|
|
828
1339
|
}): react_jsx_runtime.JSX.Element;
|
|
829
|
-
declare function EntityDetailSheet<TEntity extends
|
|
1340
|
+
declare function EntityDetailSheet<TEntity extends object>({ crud, fields, title, description, children, showEditButton, showDeleteButton, deleteConfirmMessage }: {
|
|
830
1341
|
crud: CRUDState<TEntity>;
|
|
831
1342
|
fields: FieldDescriptor<TEntity>[];
|
|
832
1343
|
title?: string | ((e: TEntity) => string);
|
|
@@ -836,7 +1347,7 @@ declare function EntityDetailSheet<TEntity extends Record<string, unknown>>({ cr
|
|
|
836
1347
|
showDeleteButton?: boolean;
|
|
837
1348
|
deleteConfirmMessage?: string;
|
|
838
1349
|
}): react_jsx_runtime.JSX.Element;
|
|
839
|
-
declare function EntityFormSheet<TEntity extends
|
|
1350
|
+
declare function EntityFormSheet<TEntity extends object>({ crud, fields, createTitle, editTitle }: {
|
|
840
1351
|
crud: CRUDState<TEntity>;
|
|
841
1352
|
fields: FieldDescriptor<TEntity>[];
|
|
842
1353
|
createTitle?: string;
|
|
@@ -849,11 +1360,12 @@ interface JsonSchemaObject {
|
|
|
849
1360
|
description?: string;
|
|
850
1361
|
type?: string | string[];
|
|
851
1362
|
format?: string;
|
|
852
|
-
enum?: unknown[];
|
|
1363
|
+
enum?: readonly unknown[];
|
|
853
1364
|
default?: unknown;
|
|
854
1365
|
properties?: Record<string, JsonSchemaObject>;
|
|
855
1366
|
items?: JsonSchemaObject;
|
|
856
1367
|
required?: string[];
|
|
1368
|
+
additionalProperties?: boolean | JsonSchemaObject;
|
|
857
1369
|
["x-a2ui-component"]?: string;
|
|
858
1370
|
["x-display-order"]?: number;
|
|
859
1371
|
["x-field-type"]?: string;
|
|
@@ -872,7 +1384,7 @@ interface GetEntityJsonSchemaOptions {
|
|
|
872
1384
|
schemaId?: string;
|
|
873
1385
|
field?: string;
|
|
874
1386
|
}
|
|
875
|
-
interface SchemaFieldDescriptor<TEntity extends
|
|
1387
|
+
interface SchemaFieldDescriptor<TEntity extends object = Record<string, unknown>> extends FieldDescriptor<TEntity> {
|
|
876
1388
|
schemaPath: string;
|
|
877
1389
|
schema: JsonSchemaObject;
|
|
878
1390
|
componentHint?: string;
|
|
@@ -890,11 +1402,11 @@ interface GraphSnapshotWithSchemasOptions {
|
|
|
890
1402
|
declare function registerEntityJsonSchema(config: EntityJsonSchemaConfig): void;
|
|
891
1403
|
declare function registerRuntimeSchema(config: EntityJsonSchemaConfig): void;
|
|
892
1404
|
declare function getEntityJsonSchema(opts: GetEntityJsonSchemaOptions): EntityJsonSchemaConfig | null;
|
|
893
|
-
declare function useSchemaEntityFields<TEntity extends
|
|
1405
|
+
declare function useSchemaEntityFields<TEntity extends object = Record<string, unknown>>(opts: GetEntityJsonSchemaOptions & {
|
|
894
1406
|
schema?: JsonSchemaObject;
|
|
895
1407
|
rootField?: string;
|
|
896
1408
|
}): SchemaFieldDescriptor<TEntity>[];
|
|
897
|
-
declare function buildEntityFieldsFromSchema<TEntity extends
|
|
1409
|
+
declare function buildEntityFieldsFromSchema<TEntity extends object = Record<string, unknown>>(opts: BuildEntityFieldsFromSchemaOptions): SchemaFieldDescriptor<TEntity>[];
|
|
898
1410
|
declare function exportGraphSnapshotWithSchemas(opts: GraphSnapshotWithSchemasOptions): string;
|
|
899
1411
|
declare function renderMarkdownToHtml(value: string): string;
|
|
900
1412
|
declare function MarkdownFieldRenderer({ value, className }: {
|
|
@@ -966,6 +1478,26 @@ interface HydrateGraphFromStorageOptions {
|
|
|
966
1478
|
storage: GraphPersistenceAdapter;
|
|
967
1479
|
key: string;
|
|
968
1480
|
}
|
|
1481
|
+
/**
|
|
1482
|
+
* Retry-with-backoff policy for replaying pending offline actions.
|
|
1483
|
+
*
|
|
1484
|
+
* The replay loop tracks per-action attempt counts. After `maxAttempts`
|
|
1485
|
+
* failed attempts the action is considered "poisoned" — it is removed from
|
|
1486
|
+
* the in-memory pending queue (so it won't block other actions) and the
|
|
1487
|
+
* optional `poisonHandler` is invoked. Consumers typically log the action,
|
|
1488
|
+
* surface a UI prompt, or persist it to a dead-letter store.
|
|
1489
|
+
*
|
|
1490
|
+
* Defaults: 5 attempts, starting at 500ms, doubling up to 30s, with
|
|
1491
|
+
* "equal" jitter (random in `[delay/2, delay]`).
|
|
1492
|
+
*/
|
|
1493
|
+
interface ReplayRetryPolicy {
|
|
1494
|
+
maxAttempts?: number;
|
|
1495
|
+
initialDelayMs?: number;
|
|
1496
|
+
maxDelayMs?: number;
|
|
1497
|
+
backoffFactor?: number;
|
|
1498
|
+
jitter?: "full" | "equal" | "none";
|
|
1499
|
+
poisonHandler?: (action: GraphActionRecord, error: unknown) => void | Promise<void>;
|
|
1500
|
+
}
|
|
969
1501
|
interface StartLocalFirstGraphOptions {
|
|
970
1502
|
storage: GraphPersistenceAdapter;
|
|
971
1503
|
key?: string;
|
|
@@ -975,6 +1507,8 @@ interface StartLocalFirstGraphOptions {
|
|
|
975
1507
|
subscribe: (listener: (online: boolean) => void) => () => void;
|
|
976
1508
|
};
|
|
977
1509
|
persistDebounceMs?: number;
|
|
1510
|
+
/** Retry-with-backoff policy for offline action replay. */
|
|
1511
|
+
retryPolicy?: ReplayRetryPolicy;
|
|
978
1512
|
}
|
|
979
1513
|
interface LocalFirstGraphRuntime {
|
|
980
1514
|
ready: Promise<void>;
|
|
@@ -1008,6 +1542,26 @@ declare function hydrateGraphFromStorage(opts: HydrateGraphFromStorageOptions):
|
|
|
1008
1542
|
error?: undefined;
|
|
1009
1543
|
}>;
|
|
1010
1544
|
declare function startLocalFirstGraph(opts: StartLocalFirstGraphOptions): LocalFirstGraphRuntime;
|
|
1545
|
+
interface ResolvedRetryPolicy {
|
|
1546
|
+
maxAttempts: number;
|
|
1547
|
+
initialDelayMs: number;
|
|
1548
|
+
maxDelayMs: number;
|
|
1549
|
+
backoffFactor: number;
|
|
1550
|
+
jitter: "full" | "equal" | "none";
|
|
1551
|
+
poisonHandler?: (action: GraphActionRecord, error: unknown) => void | Promise<void>;
|
|
1552
|
+
}
|
|
1553
|
+
/**
|
|
1554
|
+
* Attempt to replay an action up to `maxAttempts` times. On exhaustion the
|
|
1555
|
+
* action goes to "poison" — the optional handler is invoked and the function
|
|
1556
|
+
* resolves. Exposed for unit testing.
|
|
1557
|
+
*/
|
|
1558
|
+
declare function replayActionWithRetry(action: GraphActionRecord, policy: ResolvedRetryPolicy): Promise<{
|
|
1559
|
+
ok: true;
|
|
1560
|
+
} | {
|
|
1561
|
+
ok: false;
|
|
1562
|
+
poisoned: true;
|
|
1563
|
+
error: unknown;
|
|
1564
|
+
}>;
|
|
1011
1565
|
|
|
1012
1566
|
/**
|
|
1013
1567
|
* Debug-time snapshot of entity graph health: counts, list queries, patches, staleness,
|
|
@@ -1071,7 +1625,7 @@ interface UseEntityResult<T> {
|
|
|
1071
1625
|
* });
|
|
1072
1626
|
* ```
|
|
1073
1627
|
*/
|
|
1074
|
-
declare function useEntity<TRaw, TEntity extends
|
|
1628
|
+
declare function useEntity<TRaw, TEntity extends object>(opts: EntityQueryOptions<TRaw, TEntity>): UseEntityResult<TEntity>;
|
|
1075
1629
|
/**
|
|
1076
1630
|
* Resolved rows for a list query: **`items` joins `ids` to the graph** at render time so shared entities update everywhere.
|
|
1077
1631
|
*/
|
|
@@ -1081,7 +1635,14 @@ interface UseEntityListResult<TEntity> {
|
|
|
1081
1635
|
isLoading: boolean;
|
|
1082
1636
|
isFetching: boolean;
|
|
1083
1637
|
isFetchingMore: boolean;
|
|
1638
|
+
/**
|
|
1639
|
+
* Last error message from the underlying fetcher, or `null` when
|
|
1640
|
+
* the latest attempt succeeded / no attempt has been made.
|
|
1641
|
+
* Combined with `isError` for TanStack-Query-style ergonomics.
|
|
1642
|
+
*/
|
|
1084
1643
|
error: string | null;
|
|
1644
|
+
/** Convenience for `error !== null`. TanStack-Query-style. */
|
|
1645
|
+
isError: boolean;
|
|
1085
1646
|
hasNextPage: boolean;
|
|
1086
1647
|
hasPrevPage: boolean;
|
|
1087
1648
|
total: number | null;
|
|
@@ -1107,12 +1668,18 @@ interface UseEntityListResult<TEntity> {
|
|
|
1107
1668
|
* });
|
|
1108
1669
|
* ```
|
|
1109
1670
|
*/
|
|
1110
|
-
|
|
1671
|
+
/**
|
|
1672
|
+
* @deprecated Use `useEntities` from `"@prometheus-ags/prometheus-entity-management"` instead.
|
|
1673
|
+
* Register a transport: `registerEntityTransport("Foo", makeRestTransport({ supabase, table: "foo" }))`
|
|
1674
|
+
* Then consume: `const { items } = useEntities<Foo>("Foo")`.
|
|
1675
|
+
* `useEntityList` will be removed in a future major version.
|
|
1676
|
+
*/
|
|
1677
|
+
declare function useEntityList<TRaw, TEntity extends object>(opts: ListQueryOptions<TRaw, TEntity>): UseEntityListResult<TEntity>;
|
|
1111
1678
|
/**
|
|
1112
1679
|
* Options for graph-aware mutations: API call + optional normalization into `entities`, optimistic patches, and targeted invalidation.
|
|
1113
1680
|
* Prefer `invalidateLists` prefixes / `invalidateEntities` over ad-hoc store calls so list UIs stay coherent.
|
|
1114
1681
|
*/
|
|
1115
|
-
interface MutationOptions<TInput, TRaw, TEntity extends
|
|
1682
|
+
interface MutationOptions<TInput, TRaw, TEntity extends object> {
|
|
1116
1683
|
type: EntityType;
|
|
1117
1684
|
mutate: (input: TInput) => Promise<TRaw>;
|
|
1118
1685
|
normalize?: (raw: TRaw, input: TInput) => {
|
|
@@ -1156,7 +1723,7 @@ interface UseMutationResult<TInput, TRaw> {
|
|
|
1156
1723
|
* });
|
|
1157
1724
|
* ```
|
|
1158
1725
|
*/
|
|
1159
|
-
declare function useEntityMutation<TInput, TRaw, TEntity extends
|
|
1726
|
+
declare function useEntityMutation<TInput, TRaw, TEntity extends object>(opts: MutationOptions<TInput, TRaw, TEntity>): UseMutationResult<TInput, TRaw>;
|
|
1160
1727
|
/**
|
|
1161
1728
|
* Read/write **UI-only** fields for one entity (`patches` layer) so selection, hover, or transient state is visible in every view that reads that id.
|
|
1162
1729
|
* Does not replace `useEntityCRUD`’s edit buffer for form drafts — patches are for shared, non-persisted overlays.
|
|
@@ -1165,7 +1732,7 @@ declare function useEntityMutation<TInput, TRaw, TEntity extends Record<string,
|
|
|
1165
1732
|
* @param id - Entity id (no-ops when null/undefined)
|
|
1166
1733
|
* @returns Current patch slice and helpers `augment` / `unaugment` / `clear`
|
|
1167
1734
|
*/
|
|
1168
|
-
declare function useEntityAugment<TEntity extends
|
|
1735
|
+
declare function useEntityAugment<TEntity extends object>(type: EntityType, id: EntityId | null | undefined): {
|
|
1169
1736
|
patch: Partial<TEntity> | null;
|
|
1170
1737
|
augment: (fields: Partial<TEntity>) => void;
|
|
1171
1738
|
unaugment: (keys: (keyof TEntity)[]) => void;
|
|
@@ -1181,7 +1748,7 @@ declare function useEntityAugment<TEntity extends Record<string, unknown>>(type:
|
|
|
1181
1748
|
* @throws Promise while loading (caught by the nearest Suspense boundary)
|
|
1182
1749
|
* @throws Error if the fetch fails with no data, if `id` is missing when required, or if the entity never resolves
|
|
1183
1750
|
*/
|
|
1184
|
-
declare function useSuspenseEntity<TRaw, TEntity extends
|
|
1751
|
+
declare function useSuspenseEntity<TRaw, TEntity extends object>(opts: EntityQueryOptions<TRaw, TEntity>): {
|
|
1185
1752
|
data: TEntity;
|
|
1186
1753
|
isFetching: boolean;
|
|
1187
1754
|
isStale: boolean;
|
|
@@ -1196,7 +1763,7 @@ declare function useSuspenseEntity<TRaw, TEntity extends Record<string, unknown>
|
|
|
1196
1763
|
* @throws Promise while initially loading (caught by the nearest Suspense boundary)
|
|
1197
1764
|
* @throws Error if the fetch fails while the list is still empty
|
|
1198
1765
|
*/
|
|
1199
|
-
declare function useSuspenseEntityList<TRaw, TEntity extends
|
|
1766
|
+
declare function useSuspenseEntityList<TRaw, TEntity extends object>(opts: ListQueryOptions<TRaw, TEntity>): Omit<UseEntityListResult<TEntity>, "isLoading">;
|
|
1200
1767
|
|
|
1201
1768
|
/**
|
|
1202
1769
|
* Evaluate `FilterSpec` against one in-memory entity — mirrors remote semantics as closely as plain JS allows.
|
|
@@ -1413,14 +1980,14 @@ declare function createSupabaseRealtimeAdapter(client: SupabaseClient$1, opts?:
|
|
|
1413
1980
|
interface ConvexClient {
|
|
1414
1981
|
onUpdate<T>(query: unknown, args: Record<string, unknown>, handler: (result: T) => void): UnsubscribeFn$1;
|
|
1415
1982
|
}
|
|
1416
|
-
interface ConvexChannelConfig<T extends
|
|
1983
|
+
interface ConvexChannelConfig<T extends object> {
|
|
1417
1984
|
type: string;
|
|
1418
1985
|
query: unknown;
|
|
1419
1986
|
args?: Record<string, unknown>;
|
|
1420
1987
|
extractId?: (record: T) => string;
|
|
1421
1988
|
normalize?: (record: T) => Record<string, unknown>;
|
|
1422
1989
|
}
|
|
1423
|
-
declare function createConvexAdapter<T extends
|
|
1990
|
+
declare function createConvexAdapter<T extends object>(opts: {
|
|
1424
1991
|
client: ConvexClient;
|
|
1425
1992
|
channels: ConvexChannelConfig<T>[];
|
|
1426
1993
|
}): RealtimeAdapter;
|
|
@@ -1436,7 +2003,7 @@ interface GQLWsClient {
|
|
|
1436
2003
|
complete: () => void;
|
|
1437
2004
|
}): UnsubscribeFn$1;
|
|
1438
2005
|
}
|
|
1439
|
-
interface GQLSubscriptionConfig<T extends
|
|
2006
|
+
interface GQLSubscriptionConfig<T extends object> {
|
|
1440
2007
|
type: string;
|
|
1441
2008
|
document: string;
|
|
1442
2009
|
variables?: Record<string, unknown>;
|
|
@@ -1447,7 +2014,7 @@ interface GQLPayload {
|
|
|
1447
2014
|
node?: Record<string, unknown>;
|
|
1448
2015
|
id?: string;
|
|
1449
2016
|
}
|
|
1450
|
-
declare function createGraphQLSubscriptionAdapter<T extends
|
|
2017
|
+
declare function createGraphQLSubscriptionAdapter<T extends object>(opts: {
|
|
1451
2018
|
client: GQLWsClient;
|
|
1452
2019
|
subscriptions: GQLSubscriptionConfig<T>[];
|
|
1453
2020
|
extractId?: (node: Record<string, unknown>, type: string) => string;
|
|
@@ -1457,7 +2024,7 @@ declare function createGraphQLSubscriptionAdapter<T extends Record<string, unkno
|
|
|
1457
2024
|
/**
|
|
1458
2025
|
* Options for {@link createPrismaEntityConfig}: one REST-backed resource aligned with Prisma-style `where` / `orderBy` / `include` payloads.
|
|
1459
2026
|
*/
|
|
1460
|
-
interface PrismaEntityConfigOptions<TEntity extends
|
|
2027
|
+
interface PrismaEntityConfigOptions<TEntity extends object> {
|
|
1461
2028
|
/** Graph entity type key (e.g. `"Task"`). */
|
|
1462
2029
|
type: string;
|
|
1463
2030
|
/** Base REST URL for the collection (list) and detail as `${endpoint}/:id`. */
|
|
@@ -1490,7 +2057,7 @@ declare function prismaRelationsToSchema(type: string, relations: PrismaEntityCo
|
|
|
1490
2057
|
* - {@link PrismaEntityConfigOptions.endpoint `endpoint`} — GET list; GET `${endpoint}/:id` for detail.
|
|
1491
2058
|
* - List/CRUD fetchers send `where` and `orderBy` as JSON query strings unless you override via {@link ListFetchParams.params}.
|
|
1492
2059
|
*/
|
|
1493
|
-
declare function createPrismaEntityConfig<TEntity extends
|
|
2060
|
+
declare function createPrismaEntityConfig<TEntity extends object>(config: PrismaEntityConfigOptions<TEntity>): {
|
|
1494
2061
|
/**
|
|
1495
2062
|
* Builds {@link EntityQueryOptions} for {@link useEntity} (GET `${endpoint}/:id`).
|
|
1496
2063
|
*/
|
|
@@ -1516,14 +2083,14 @@ declare function createPrismaEntityConfig<TEntity extends Record<string, unknown
|
|
|
1516
2083
|
schemas: () => EntitySchema[];
|
|
1517
2084
|
};
|
|
1518
2085
|
|
|
1519
|
-
interface PGlite {
|
|
2086
|
+
interface PGlite$1 {
|
|
1520
2087
|
query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<{
|
|
1521
2088
|
rows: T[];
|
|
1522
2089
|
}>;
|
|
1523
|
-
exec(sql: string): Promise<
|
|
2090
|
+
exec(sql: string): Promise<unknown>;
|
|
1524
2091
|
listen(channel: string, handler: (payload: string) => void): Promise<() => void>;
|
|
1525
2092
|
}
|
|
1526
|
-
interface ShapeMessage<T = Record<string, unknown>> {
|
|
2093
|
+
interface ShapeMessage$1<T = Record<string, unknown>> {
|
|
1527
2094
|
headers: {
|
|
1528
2095
|
operation: "insert" | "update" | "delete";
|
|
1529
2096
|
};
|
|
@@ -1531,21 +2098,21 @@ interface ShapeMessage<T = Record<string, unknown>> {
|
|
|
1531
2098
|
value: T;
|
|
1532
2099
|
key: string;
|
|
1533
2100
|
}
|
|
1534
|
-
interface ShapeStream<T = Record<string, unknown>> {
|
|
1535
|
-
subscribe(onMsg: (msgs: ShapeMessage<T>[]) => void, onErr?: (e: Error) => void): () => void;
|
|
2101
|
+
interface ShapeStream$1<T = Record<string, unknown>> {
|
|
2102
|
+
subscribe(onMsg: (msgs: ShapeMessage$1<T>[]) => void, onErr?: (e: Error) => void): () => void;
|
|
1536
2103
|
isUpToDate: boolean;
|
|
1537
2104
|
lastOffset: string;
|
|
1538
2105
|
}
|
|
1539
|
-
interface ElectricTableConfig<T extends
|
|
2106
|
+
interface ElectricTableConfig<T extends object> {
|
|
1540
2107
|
type: EntityType;
|
|
1541
2108
|
table: string;
|
|
1542
2109
|
where?: string;
|
|
1543
2110
|
idColumn?: string;
|
|
1544
2111
|
normalize?: (row: T) => Record<string, unknown>;
|
|
1545
|
-
shapeStream: ShapeStream<T>;
|
|
2112
|
+
shapeStream: ShapeStream$1<T>;
|
|
1546
2113
|
}
|
|
1547
2114
|
interface ElectricAdapterOptions {
|
|
1548
|
-
pglite: PGlite;
|
|
2115
|
+
pglite: PGlite$1;
|
|
1549
2116
|
tables: ElectricTableConfig<Record<string, unknown>>[];
|
|
1550
2117
|
onSynced?: () => void;
|
|
1551
2118
|
}
|
|
@@ -1556,7 +2123,7 @@ interface UseLocalFirstResult {
|
|
|
1556
2123
|
execute: (sql: string, params?: unknown[]) => Promise<void>;
|
|
1557
2124
|
}
|
|
1558
2125
|
declare function useLocalFirst(adapter: SyncAdapter): UseLocalFirstResult;
|
|
1559
|
-
declare function usePGliteQuery<T extends
|
|
2126
|
+
declare function usePGliteQuery<T extends object>(opts: {
|
|
1560
2127
|
adapter: SyncAdapter;
|
|
1561
2128
|
type: EntityType;
|
|
1562
2129
|
sql: string;
|
|
@@ -1569,6 +2136,280 @@ declare function usePGliteQuery<T extends Record<string, unknown>>(opts: {
|
|
|
1569
2136
|
error: string | null;
|
|
1570
2137
|
};
|
|
1571
2138
|
|
|
2139
|
+
/**
|
|
2140
|
+
* adapters/electricsql-tenant.ts
|
|
2141
|
+
*
|
|
2142
|
+
* Tenant-scoped Electric adapter — the safety primitive that enforces
|
|
2143
|
+
* **RULE 5 — Shape predicates ⊆ RLS** (see hotseaters constraints).
|
|
2144
|
+
*
|
|
2145
|
+
* PGlite has no row-level security. The only way to guarantee a client
|
|
2146
|
+
* never sees cross-tenant data through Electric is to refuse to attach
|
|
2147
|
+
* any shape that lacks a tenant predicate. This wrapper does exactly that:
|
|
2148
|
+
*
|
|
2149
|
+
* - Validates the tenant claim (currently `{ companyId }`) is a UUID.
|
|
2150
|
+
* - Refuses to attach a shape whose `tenantColumn` is `undefined`. We
|
|
2151
|
+
* accept explicit `null` for the company root itself (filtered by `id`).
|
|
2152
|
+
* - Builds the `where` clause from `tenantColumn` and the validated
|
|
2153
|
+
* companyId so individual shape factories cannot drift from RLS.
|
|
2154
|
+
* - Delegates to the existing `createElectricAdapter` for the actual
|
|
2155
|
+
* sync wiring.
|
|
2156
|
+
*
|
|
2157
|
+
* This also fulfils Change 13 item 11 (auth-claim-aware shape registration):
|
|
2158
|
+
* the `tenantClaim` is the typed seam where authn meets shape registration.
|
|
2159
|
+
*
|
|
2160
|
+
* Self-hosted Supabase only. Local stack and `https://electricsql.prometheusags.ai`
|
|
2161
|
+
* are the only acceptable Electric endpoints — this module does not
|
|
2162
|
+
* hard-code either; it only governs the predicate.
|
|
2163
|
+
*/
|
|
2164
|
+
|
|
2165
|
+
interface PGlite {
|
|
2166
|
+
query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<{
|
|
2167
|
+
rows: T[];
|
|
2168
|
+
}>;
|
|
2169
|
+
exec(sql: string): Promise<unknown>;
|
|
2170
|
+
listen(channel: string, handler: (payload: string) => void): Promise<() => void>;
|
|
2171
|
+
}
|
|
2172
|
+
interface ShapeMessage<T = Record<string, unknown>> {
|
|
2173
|
+
headers: {
|
|
2174
|
+
operation: "insert" | "update" | "delete";
|
|
2175
|
+
};
|
|
2176
|
+
offset: string;
|
|
2177
|
+
value: T;
|
|
2178
|
+
key: string;
|
|
2179
|
+
}
|
|
2180
|
+
interface ShapeStream<T = Record<string, unknown>> {
|
|
2181
|
+
subscribe(onMsg: (msgs: ShapeMessage<T>[]) => void, onErr?: (e: Error) => void): () => void;
|
|
2182
|
+
isUpToDate: boolean;
|
|
2183
|
+
lastOffset: string;
|
|
2184
|
+
}
|
|
2185
|
+
/** Auth claim required to register tenant-scoped shapes. */
|
|
2186
|
+
interface TenantClaim {
|
|
2187
|
+
companyId: string;
|
|
2188
|
+
}
|
|
2189
|
+
interface TenantScopedTableConfig<T extends object = Record<string, unknown>> {
|
|
2190
|
+
type: EntityType;
|
|
2191
|
+
table: string;
|
|
2192
|
+
/**
|
|
2193
|
+
* Column used for tenant filtering.
|
|
2194
|
+
*
|
|
2195
|
+
* - A string (`"company_id"`) yields `WHERE company_id = '<companyId>'`.
|
|
2196
|
+
* - Explicit `null` means the table IS the tenant root and is filtered by
|
|
2197
|
+
* `id = '<companyId>'`. Only the `company` table qualifies.
|
|
2198
|
+
* - `undefined` is **rejected** — this is the safety gate.
|
|
2199
|
+
*/
|
|
2200
|
+
tenantColumn: string | null;
|
|
2201
|
+
primaryKey?: string[];
|
|
2202
|
+
/**
|
|
2203
|
+
* Factory invoked with the constructed `where` clause and the tenant claim.
|
|
2204
|
+
* Consumers wire their preferred Electric `ShapeStream` builder here. The
|
|
2205
|
+
* factory must use the supplied `where` verbatim (no widening).
|
|
2206
|
+
*/
|
|
2207
|
+
shapeStreamFactory: (params: {
|
|
2208
|
+
table: string;
|
|
2209
|
+
where: string;
|
|
2210
|
+
tenantClaim: TenantClaim;
|
|
2211
|
+
}) => ShapeStream<T>;
|
|
2212
|
+
normalize?: (row: T) => Record<string, unknown>;
|
|
2213
|
+
}
|
|
2214
|
+
interface TenantScopedAdapterOptions {
|
|
2215
|
+
pglite: PGlite;
|
|
2216
|
+
tenantClaim: TenantClaim;
|
|
2217
|
+
tables: TenantScopedTableConfig[];
|
|
2218
|
+
onSynced?: () => void;
|
|
2219
|
+
}
|
|
2220
|
+
/**
|
|
2221
|
+
* Build the `where` clause for a single shape. Exposed for tests.
|
|
2222
|
+
*
|
|
2223
|
+
* - `tenantColumn === null` → `id = '<companyId>'` (company-root case)
|
|
2224
|
+
* - `tenantColumn === string` → `<tenantColumn> = '<companyId>'`
|
|
2225
|
+
*
|
|
2226
|
+
* Throws if `tenantColumn` is `undefined` or `companyId` is not a UUID.
|
|
2227
|
+
*/
|
|
2228
|
+
declare function buildTenantWhere(tenantColumn: string | null | undefined, companyId: string, tableLabel: string): string;
|
|
2229
|
+
/**
|
|
2230
|
+
* Build a tenant-scoped {@link SyncAdapter}.
|
|
2231
|
+
*
|
|
2232
|
+
* For each table in `tables`:
|
|
2233
|
+
* 1. Validates `tenantColumn` is defined (string or explicit null).
|
|
2234
|
+
* 2. Validates `companyId` is a UUID.
|
|
2235
|
+
* 3. Builds the predicate and calls `shapeStreamFactory(...)` to get the
|
|
2236
|
+
* actual `ShapeStream`.
|
|
2237
|
+
* 4. Hands the resulting list off to `createElectricAdapter` for wiring.
|
|
2238
|
+
*
|
|
2239
|
+
* @throws if any table lacks `tenantColumn`, or the company id is not a UUID.
|
|
2240
|
+
*/
|
|
2241
|
+
declare function createTenantScopedElectricAdapter(opts: TenantScopedAdapterOptions): SyncAdapter;
|
|
2242
|
+
|
|
2243
|
+
/**
|
|
2244
|
+
* adapters/pglite-persistence.ts
|
|
2245
|
+
*
|
|
2246
|
+
* PGlite-backed implementation of {@link GraphPersistenceAdapter}.
|
|
2247
|
+
*
|
|
2248
|
+
* Stores the local-first runtime's graph snapshot inside a PGlite table
|
|
2249
|
+
* (`_graph_snapshot` by default) instead of `localStorage`/`IndexedDB`.
|
|
2250
|
+
*
|
|
2251
|
+
* Why this exists:
|
|
2252
|
+
* - The app already has a PGlite handle for ElectricSQL sync.
|
|
2253
|
+
* - Putting the graph snapshot alongside synced data means one storage
|
|
2254
|
+
* surface to back up, clear, and reason about.
|
|
2255
|
+
* - Works in Tauri WebView + Node (PGlite is a WASM Postgres) without
|
|
2256
|
+
* pulling in browser-only storage.
|
|
2257
|
+
*
|
|
2258
|
+
* Contract:
|
|
2259
|
+
* - `get(key)` -> returns the stored string or null
|
|
2260
|
+
* - `set(key, v)` -> upserts (insert-or-replace), stamping `updated_at`
|
|
2261
|
+
* - `remove(key)` -> deletes the row (no-op if absent)
|
|
2262
|
+
*
|
|
2263
|
+
* The function lazily ensures the storage table exists on first call.
|
|
2264
|
+
* That `CREATE TABLE IF NOT EXISTS` is idempotent so it's safe to retry.
|
|
2265
|
+
*
|
|
2266
|
+
* Self-hosted Supabase only. HotSeatersMVP is the bible. This module does
|
|
2267
|
+
* not import `@electric-sql/pglite` — consumers pass a PGlite-shaped handle.
|
|
2268
|
+
*/
|
|
2269
|
+
|
|
2270
|
+
interface PGlitePersistenceClient {
|
|
2271
|
+
query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<{
|
|
2272
|
+
rows: T[];
|
|
2273
|
+
}>;
|
|
2274
|
+
exec(sql: string): Promise<unknown>;
|
|
2275
|
+
}
|
|
2276
|
+
interface CreatePGlitePersistenceAdapterOptions {
|
|
2277
|
+
/** Name of the snapshot table. Defaults to `_graph_snapshot`. */
|
|
2278
|
+
tableName?: string;
|
|
2279
|
+
}
|
|
2280
|
+
/**
|
|
2281
|
+
* Returns a {@link GraphPersistenceAdapter} that reads/writes the graph
|
|
2282
|
+
* snapshot through a PGlite-shaped client.
|
|
2283
|
+
*
|
|
2284
|
+
* @example
|
|
2285
|
+
* ```ts
|
|
2286
|
+
* import { PGlite } from "@electric-sql/pglite";
|
|
2287
|
+
* import { startLocalFirstGraph, createPGlitePersistenceAdapter } from "@prometheus-ags/prometheus-entity-management";
|
|
2288
|
+
*
|
|
2289
|
+
* const pglite = await PGlite.create("idb://hotseaters");
|
|
2290
|
+
* const storage = await createPGlitePersistenceAdapter(pglite);
|
|
2291
|
+
* const runtime = startLocalFirstGraph({ storage, key: "hotseaters:graph" });
|
|
2292
|
+
* ```
|
|
2293
|
+
*/
|
|
2294
|
+
declare function createPGlitePersistenceAdapter(pglite: PGlitePersistenceClient, options?: CreatePGlitePersistenceAdapterOptions): Promise<GraphPersistenceAdapter>;
|
|
2295
|
+
|
|
2296
|
+
/**
|
|
2297
|
+
* schema-from-sql.ts
|
|
2298
|
+
*
|
|
2299
|
+
* Generates a JSON Schema (and registers it via `registerEntityJsonSchema`)
|
|
2300
|
+
* directly from a Postgres `CREATE TABLE` statement. Lets a consumer keep
|
|
2301
|
+
* `latest-data/supabase/migrations/*.sql` as the single source of truth for
|
|
2302
|
+
* column shapes — no hand-maintained TypeScript schema duplicates.
|
|
2303
|
+
*
|
|
2304
|
+
* Deliberately regex-based: a real SQL parser is overkill for the slice of
|
|
2305
|
+
* DDL we care about, and would add a non-trivial runtime dep.
|
|
2306
|
+
*
|
|
2307
|
+
* Type mapping
|
|
2308
|
+
* ------------
|
|
2309
|
+
* UUID, TEXT, VARCHAR(*) -> { type: "string" }
|
|
2310
|
+
* INTEGER, INT, BIGINT, SMALLINT -> { type: "integer" }
|
|
2311
|
+
* NUMERIC(*), DECIMAL(*) -> { type: "number" }
|
|
2312
|
+
* BOOLEAN, BOOL -> { type: "boolean" }
|
|
2313
|
+
* TIMESTAMPTZ, TIMESTAMP -> { type: "string", format: "date-time" }
|
|
2314
|
+
* DATE -> { type: "string", format: "date" }
|
|
2315
|
+
* JSONB, JSON -> { type: "object" }
|
|
2316
|
+
* TEXT[] -> { type: "array", items: { type: "string" } }
|
|
2317
|
+
* anything else -> { type: "string" } + "x-warning"
|
|
2318
|
+
*
|
|
2319
|
+
* `required` is populated from `NOT NULL` columns that lack a `DEFAULT`.
|
|
2320
|
+
* Callers can pass `overrides` to deep-merge a partial config (typically to
|
|
2321
|
+
* narrow a JSONB column to an array, or to add `enum`/`format` hints).
|
|
2322
|
+
*/
|
|
2323
|
+
|
|
2324
|
+
interface RegisterEntityFromSqlOptions {
|
|
2325
|
+
entityType: string;
|
|
2326
|
+
/** A single `CREATE TABLE` statement (extra DDL around it is ignored). */
|
|
2327
|
+
createTableSql: string;
|
|
2328
|
+
/** Optional deep-merge overrides (overrides win). */
|
|
2329
|
+
overrides?: Partial<EntityJsonSchemaConfig>;
|
|
2330
|
+
}
|
|
2331
|
+
interface ParsedColumn {
|
|
2332
|
+
name: string;
|
|
2333
|
+
sqlType: string;
|
|
2334
|
+
notNull: boolean;
|
|
2335
|
+
hasDefault: boolean;
|
|
2336
|
+
}
|
|
2337
|
+
interface ParsedTable {
|
|
2338
|
+
tableName: string;
|
|
2339
|
+
columns: ParsedColumn[];
|
|
2340
|
+
}
|
|
2341
|
+
/**
|
|
2342
|
+
* Parse a `CREATE TABLE` block. Exposed for tests and for callers who need
|
|
2343
|
+
* the intermediate representation.
|
|
2344
|
+
*/
|
|
2345
|
+
declare function parseCreateTable(sql: string): ParsedTable;
|
|
2346
|
+
/**
|
|
2347
|
+
* Map a normalized (uppercased, whitespace-stripped) SQL type to a JSON
|
|
2348
|
+
* schema fragment.
|
|
2349
|
+
*
|
|
2350
|
+
* Returns `{ schema, warning }` so the caller can surface "unmapped type"
|
|
2351
|
+
* notes via `x-warning` on the property.
|
|
2352
|
+
*/
|
|
2353
|
+
declare function sqlTypeToJsonSchema(sqlType: string): {
|
|
2354
|
+
schema: JsonSchemaObject;
|
|
2355
|
+
warning?: string;
|
|
2356
|
+
};
|
|
2357
|
+
/**
|
|
2358
|
+
* Build (and register) an `EntityJsonSchemaConfig` from a CREATE TABLE
|
|
2359
|
+
* statement. Returns the registered config so callers can introspect it.
|
|
2360
|
+
*/
|
|
2361
|
+
declare function registerEntityFromSql(opts: RegisterEntityFromSqlOptions): EntityJsonSchemaConfig;
|
|
2362
|
+
|
|
2363
|
+
/**
|
|
2364
|
+
* table/use-entity-list-as-table.ts
|
|
2365
|
+
*
|
|
2366
|
+
* Adapter hook that shapes a `useEntityList` result for TanStack Table (or
|
|
2367
|
+
* any data-grid that wants a plain `data` array + `rowCount`).
|
|
2368
|
+
*
|
|
2369
|
+
* It deliberately does NOT bring `@tanstack/react-table` as a dependency.
|
|
2370
|
+
* Consumers wire the table; this helper only stabilizes the array reference
|
|
2371
|
+
* so the table doesn't re-render unnecessarily, and exposes the same
|
|
2372
|
+
* loading/error surface as `useEntityList`.
|
|
2373
|
+
*
|
|
2374
|
+
* @example
|
|
2375
|
+
* ```tsx
|
|
2376
|
+
* const tableProps = useEntityListAsTable({
|
|
2377
|
+
* type: "Client",
|
|
2378
|
+
* fetch: (params) => api.listClients(params),
|
|
2379
|
+
* normalize: (raw) => ({ id: raw.id, data: raw }),
|
|
2380
|
+
* });
|
|
2381
|
+
*
|
|
2382
|
+
* const table = useReactTable({
|
|
2383
|
+
* data: tableProps.data,
|
|
2384
|
+
* rowCount: tableProps.rowCount,
|
|
2385
|
+
* columns,
|
|
2386
|
+
* getCoreRowModel: getCoreRowModel(),
|
|
2387
|
+
* });
|
|
2388
|
+
* ```
|
|
2389
|
+
*/
|
|
2390
|
+
|
|
2391
|
+
interface UseEntityListAsTableOptions<TRaw, TEntity extends object> extends Omit<ListQueryOptions<TRaw, TEntity>, "type" | "queryKey"> {
|
|
2392
|
+
type: EntityType;
|
|
2393
|
+
/** Optional override for the cache key. Defaults to `["entity-list-as-table", type]`. */
|
|
2394
|
+
queryKey?: unknown[];
|
|
2395
|
+
}
|
|
2396
|
+
interface UseEntityListAsTableResult<TEntity> {
|
|
2397
|
+
data: TEntity[];
|
|
2398
|
+
rowCount: number;
|
|
2399
|
+
isLoading: boolean;
|
|
2400
|
+
isFetching: boolean;
|
|
2401
|
+
error: string | null;
|
|
2402
|
+
refetch: () => void;
|
|
2403
|
+
}
|
|
2404
|
+
/**
|
|
2405
|
+
* Wraps `useEntityList` for table consumers.
|
|
2406
|
+
*
|
|
2407
|
+
* Returns a referentially-stable `data` array (replaced only when items
|
|
2408
|
+
* actually change). TanStack Table treats `data` by identity for memoization,
|
|
2409
|
+
* so this is essential to avoid blowing away row state on every render.
|
|
2410
|
+
*/
|
|
2411
|
+
declare function useEntityListAsTable<TRaw, TEntity extends object>(opts: UseEntityListAsTableOptions<TRaw, TEntity>): UseEntityListAsTableResult<TEntity>;
|
|
2412
|
+
|
|
1572
2413
|
interface GQLClientConfig {
|
|
1573
2414
|
url: string;
|
|
1574
2415
|
headers?: () => Record<string, string>;
|
|
@@ -1587,7 +2428,7 @@ interface GQLResponse<T> {
|
|
|
1587
2428
|
data: T | null;
|
|
1588
2429
|
errors?: GQLError[];
|
|
1589
2430
|
}
|
|
1590
|
-
interface EntityDescriptor<TNode, TEntity extends
|
|
2431
|
+
interface EntityDescriptor<TNode, TEntity extends object> {
|
|
1591
2432
|
type: EntityType;
|
|
1592
2433
|
path: string;
|
|
1593
2434
|
extractId?: (node: TNode) => EntityId;
|
|
@@ -1602,13 +2443,13 @@ declare function normalizeGQLResponse<T>(data: T, descriptors: EntityDescriptor<
|
|
|
1602
2443
|
declare class GQLClient {
|
|
1603
2444
|
private cfg;
|
|
1604
2445
|
constructor(cfg: GQLClientConfig);
|
|
1605
|
-
query<TData, TEntity extends
|
|
2446
|
+
query<TData, TEntity extends object>(opts: {
|
|
1606
2447
|
document: string;
|
|
1607
2448
|
variables?: Record<string, unknown>;
|
|
1608
2449
|
descriptors: EntityDescriptor<unknown, TEntity>[];
|
|
1609
2450
|
cacheKey?: string;
|
|
1610
2451
|
}): Promise<GQLResponse<TData>>;
|
|
1611
|
-
mutate<TData, TEntity extends
|
|
2452
|
+
mutate<TData, TEntity extends object>(opts: {
|
|
1612
2453
|
document: string;
|
|
1613
2454
|
variables?: Record<string, unknown>;
|
|
1614
2455
|
descriptors?: EntityDescriptor<unknown, TEntity>[];
|
|
@@ -1627,7 +2468,7 @@ declare class GQLClient {
|
|
|
1627
2468
|
}
|
|
1628
2469
|
declare function createGQLClient(cfg: GQLClientConfig): GQLClient;
|
|
1629
2470
|
|
|
1630
|
-
interface GQLEntityOptions<TData, TEntity extends
|
|
2471
|
+
interface GQLEntityOptions<TData, TEntity extends object> {
|
|
1631
2472
|
client: GQLClient;
|
|
1632
2473
|
document: string;
|
|
1633
2474
|
variables?: Record<string, unknown>;
|
|
@@ -1640,7 +2481,7 @@ interface GQLEntityOptions<TData, TEntity extends Record<string, unknown>> {
|
|
|
1640
2481
|
onSuccess?: (data: TData) => void;
|
|
1641
2482
|
onError?: (err: Error) => void;
|
|
1642
2483
|
}
|
|
1643
|
-
declare function useGQLEntity<TData, TEntity extends
|
|
2484
|
+
declare function useGQLEntity<TData, TEntity extends object>(opts: GQLEntityOptions<TData, TEntity>): {
|
|
1644
2485
|
data: TEntity | null;
|
|
1645
2486
|
isLoading: boolean;
|
|
1646
2487
|
isFetching: boolean;
|
|
@@ -1648,7 +2489,7 @@ declare function useGQLEntity<TData, TEntity extends Record<string, unknown>>(op
|
|
|
1648
2489
|
isStale: boolean;
|
|
1649
2490
|
refetch: () => void;
|
|
1650
2491
|
};
|
|
1651
|
-
interface GQLListOptions<TData, TEntity extends
|
|
2492
|
+
interface GQLListOptions<TData, TEntity extends object> {
|
|
1652
2493
|
client: GQLClient;
|
|
1653
2494
|
document: string;
|
|
1654
2495
|
variables?: Record<string, unknown>;
|
|
@@ -1668,7 +2509,7 @@ interface GQLListOptions<TData, TEntity extends Record<string, unknown>> {
|
|
|
1668
2509
|
staleTime?: number;
|
|
1669
2510
|
enabled?: boolean;
|
|
1670
2511
|
}
|
|
1671
|
-
declare function useGQLList<TData, TEntity extends
|
|
2512
|
+
declare function useGQLList<TData, TEntity extends object>(opts: GQLListOptions<TData, TEntity>): {
|
|
1672
2513
|
items: TEntity[];
|
|
1673
2514
|
ids: string[];
|
|
1674
2515
|
isLoading: boolean;
|
|
@@ -1681,7 +2522,7 @@ declare function useGQLList<TData, TEntity extends Record<string, unknown>>(opts
|
|
|
1681
2522
|
fetchNextPage: () => void;
|
|
1682
2523
|
refetch: () => void;
|
|
1683
2524
|
};
|
|
1684
|
-
declare function useGQLMutation<TData, TEntity extends
|
|
2525
|
+
declare function useGQLMutation<TData, TEntity extends object>(opts: {
|
|
1685
2526
|
client: GQLClient;
|
|
1686
2527
|
document: string;
|
|
1687
2528
|
type: string;
|
|
@@ -1722,7 +2563,7 @@ declare function InlineCellEditor$1({ initialValue, onCommit, onCancel, classNam
|
|
|
1722
2563
|
onCancel: () => void;
|
|
1723
2564
|
className?: string;
|
|
1724
2565
|
}): react_jsx_runtime.JSX.Element;
|
|
1725
|
-
interface EntityTableProps<T extends
|
|
2566
|
+
interface EntityTableProps<T extends object> {
|
|
1726
2567
|
viewResult: UseEntityViewResult<T>;
|
|
1727
2568
|
columns: ColumnDef$1<T>[];
|
|
1728
2569
|
getRowId?: (row: T) => string;
|
|
@@ -1739,7 +2580,7 @@ interface EntityTableProps<T extends Record<string, unknown>> {
|
|
|
1739
2580
|
emptyState?: React$1.ReactNode;
|
|
1740
2581
|
className?: string;
|
|
1741
2582
|
}
|
|
1742
|
-
declare function EntityTable<T extends
|
|
2583
|
+
declare function EntityTable<T extends object>({ viewResult, columns, getRowId, selectedId, onRowClick, onCellEdit, onBulkAction, paginationMode, pageSize, searchPlaceholder, searchFields, toolbarChildren, showToolbar, emptyState, className }: EntityTableProps<T>): react_jsx_runtime.JSX.Element;
|
|
1743
2584
|
|
|
1744
2585
|
type ColumnFilterType = "text" | "number" | "date" | "dateRange" | "boolean" | "enum" | "relation" | "none";
|
|
1745
2586
|
interface EntityColumnMeta<TEntity> {
|
|
@@ -2256,7 +3097,7 @@ interface GalleryColumns {
|
|
|
2256
3097
|
xl?: number;
|
|
2257
3098
|
}
|
|
2258
3099
|
|
|
2259
|
-
declare function useTable<TData extends
|
|
3100
|
+
declare function useTable<TData extends object>(options: TableOptions<TData>): TableInstance<TData>;
|
|
2260
3101
|
|
|
2261
3102
|
/**
|
|
2262
3103
|
* table/row-models.ts
|
|
@@ -2650,7 +3491,7 @@ declare function TableStorageProvider({ adapter, realtimeMode, children, }: Tabl
|
|
|
2650
3491
|
declare function useTableStorageAdapter(): TableStorageAdapter;
|
|
2651
3492
|
declare function useTableRealtimeMode(): "auto-apply" | "notify";
|
|
2652
3493
|
|
|
2653
|
-
interface EntityListViewProps<TData extends
|
|
3494
|
+
interface EntityListViewProps<TData extends object> {
|
|
2654
3495
|
data?: TData[];
|
|
2655
3496
|
viewResult?: {
|
|
2656
3497
|
items: TData[];
|
|
@@ -2685,9 +3526,9 @@ interface EntityListViewProps<TData extends Record<string, unknown>> {
|
|
|
2685
3526
|
onRefresh?: () => void;
|
|
2686
3527
|
className?: string;
|
|
2687
3528
|
}
|
|
2688
|
-
declare function EntityListView<TData extends
|
|
3529
|
+
declare function EntityListView<TData extends object>(props: EntityListViewProps<TData>): react_jsx_runtime.JSX.Element;
|
|
2689
3530
|
|
|
2690
|
-
interface DataTableProps<TData extends
|
|
3531
|
+
interface DataTableProps<TData extends object> {
|
|
2691
3532
|
table: TableInstance<TData>;
|
|
2692
3533
|
actions?: ActionDef<TData>[];
|
|
2693
3534
|
enableInlineEdit?: boolean;
|
|
@@ -2697,9 +3538,9 @@ interface DataTableProps<TData extends Record<string, unknown>> {
|
|
|
2697
3538
|
getRowId?: (row: TData) => string;
|
|
2698
3539
|
className?: string;
|
|
2699
3540
|
}
|
|
2700
|
-
declare function DataTable<TData extends
|
|
3541
|
+
declare function DataTable<TData extends object>({ table, actions, enableInlineEdit, onInlineSave, selectionStore, enableMultiSelect, getRowId, className, }: DataTableProps<TData>): react_jsx_runtime.JSX.Element;
|
|
2701
3542
|
|
|
2702
|
-
interface GalleryViewProps<TData extends
|
|
3543
|
+
interface GalleryViewProps<TData extends object> {
|
|
2703
3544
|
rows: Row<TData>[];
|
|
2704
3545
|
columns: ColumnDef<TData>[];
|
|
2705
3546
|
itemDescriptor?: ItemDescriptor<TData>;
|
|
@@ -2713,9 +3554,9 @@ interface GalleryViewProps<TData extends Record<string, unknown>> {
|
|
|
2713
3554
|
galleryColumns?: GalleryColumns;
|
|
2714
3555
|
className?: string;
|
|
2715
3556
|
}
|
|
2716
|
-
declare function GalleryView<TData extends
|
|
3557
|
+
declare function GalleryView<TData extends object>({ rows, columns, itemDescriptor, renderCard, actions, enableInlineEdit, onInlineSave, selectionStore, enableMultiSelect, getRowId, galleryColumns, className, }: GalleryViewProps<TData>): react_jsx_runtime.JSX.Element;
|
|
2717
3558
|
|
|
2718
|
-
interface ListViewProps<TData extends
|
|
3559
|
+
interface ListViewProps<TData extends object> {
|
|
2719
3560
|
rows: Row<TData>[];
|
|
2720
3561
|
columns: ColumnDef<TData>[];
|
|
2721
3562
|
itemDescriptor?: ItemDescriptor<TData>;
|
|
@@ -2728,7 +3569,7 @@ interface ListViewProps<TData extends Record<string, unknown>> {
|
|
|
2728
3569
|
getRowId?: (row: TData) => string;
|
|
2729
3570
|
className?: string;
|
|
2730
3571
|
}
|
|
2731
|
-
declare function ListView<TData extends
|
|
3572
|
+
declare function ListView<TData extends object>({ rows, columns, itemDescriptor, renderItem, actions, enableInlineEdit, onInlineSave, selectionStore, enableMultiSelect, getRowId, className, }: ListViewProps<TData>): react_jsx_runtime.JSX.Element;
|
|
2732
3573
|
|
|
2733
3574
|
interface ViewModeSwitcherProps {
|
|
2734
3575
|
mode: ViewMode;
|
|
@@ -2813,7 +3654,7 @@ interface InlineCellEditorProps<TData> {
|
|
|
2813
3654
|
ariaLabel?: string;
|
|
2814
3655
|
}
|
|
2815
3656
|
declare function InlineCellEditor<TData>({ value: initialValue, columnDef, onSave, onCancel, className, inputId, ariaLabel, }: InlineCellEditorProps<TData>): react_jsx_runtime.JSX.Element;
|
|
2816
|
-
interface InlineItemEditorProps<TData extends
|
|
3657
|
+
interface InlineItemEditorProps<TData extends object> {
|
|
2817
3658
|
item: TData;
|
|
2818
3659
|
columns: ColumnDef<TData>[];
|
|
2819
3660
|
itemDescriptor?: ItemDescriptor<TData>;
|
|
@@ -2821,7 +3662,7 @@ interface InlineItemEditorProps<TData extends Record<string, unknown>> {
|
|
|
2821
3662
|
onCancel: () => void;
|
|
2822
3663
|
className?: string;
|
|
2823
3664
|
}
|
|
2824
|
-
declare function InlineItemEditor<TData extends
|
|
3665
|
+
declare function InlineItemEditor<TData extends object>({ item, columns, itemDescriptor: _itemDescriptor, onSave, onCancel, className, }: InlineItemEditorProps<TData>): react_jsx_runtime.JSX.Element;
|
|
2825
3666
|
|
|
2826
3667
|
interface MultiSelectBarProps {
|
|
2827
3668
|
store: StoreApi<SelectionStoreState>;
|
|
@@ -2935,4 +3776,4 @@ declare const TableHead: React$1.ForwardRefExoticComponent<React$1.ThHTMLAttribu
|
|
|
2935
3776
|
declare const TableCell: React$1.ForwardRefExoticComponent<React$1.TdHTMLAttributes<HTMLTableCellElement> & React$1.RefAttributes<HTMLTableCellElement>>;
|
|
2936
3777
|
declare const TableCaption: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLTableCaptionElement> & React$1.RefAttributes<HTMLTableCaptionElement>>;
|
|
2937
3778
|
|
|
2938
|
-
export { type AccessorFn, ActionButtonRow, type ActionDef, ActionDropdown, type ActionItem, type ActivePresets, type AdapterStatus, type AggregationFn, type BatchActionDef, type BelongsToRelation, type BuildEntityFieldsFromSchemaOptions, type CRUDMode, type CRUDOptions, type CRUDState, type CascadeContext, type Cell, type CellContext, type CellRenderer, type ChangeOperation, type ChangeSet, type ChannelConfig, type Column, type ColumnFilterType, type ColumnFiltersState, type ColumnOrderState, type ColumnPinningState, type ColumnPreset, ColumnPresetDialog, type ColumnPresetEntry, type ColumnSizingState, type ColumnVisibilityState, type CompletenessMode, DataTable, DataTableColumnHeader, DataTableFilter, DataTablePagination, DataTableToolbar, type DirtyFields, type ElectricAdapterOptions, ElectricSQLAdapter as ElectricSQLPresetAdapter, type ElectricSQLAdapterOptions as ElectricSQLPresetAdapterOptions, type ElectricTableConfig, EmptyState, type EmptyStateConfig, type EngineOptions, type EntityChange, type EntityColumnMeta, type EntityDescriptor, EntityDetailSheet, EntityFormSheet, type EntityId, type EntityJsonSchemaConfig, EntityListView, type EntityListViewProps, type EntityQueryOptions, type EntitySchema, type EntitySnapshot, type EntityState, type EntitySyncMetadata, EntityTable, type EntityType, type ExpandedState, type FieldDescriptor, type FieldType, type FilterClause, type FilterFn, type FilterGroup, type FilterOperator, type FilterPreset, FilterPresetDialog, type FilterSpec, GQLClient, type GQLClientConfig, type GQLEntityOptions, type GQLError, type GQLListOptions, type GQLResponse, type GalleryColumns, GalleryView, type GraphActionEvent, type GraphActionOptions, type GraphActionRecord$1 as GraphActionRecord, type GraphEffectEvent, type GraphEffectHandle, type GraphEffectOptions, type GraphIncludeMap, type GraphIncludeRelation, type GraphPersistenceAdapter, type GraphQueryOptions, type GraphSnapshotExportOptions, type GraphSnapshotPayload, type GraphSnapshotWithSchemasOptions, type GraphState, type GraphSyncStatus, type GraphToolContext, type GraphTransaction, type GroupingState, type HasManyRelation, type Header, type HeaderContext, type HeaderGroup, type HeaderRenderer, InlineCellEditor$1 as InlineCellEditor, InlineItemEditor, type ItemDescriptor, type ItemDescriptorBadge, type ItemDescriptorMeta, type ItemRenderContext, type JsonSchemaObject, type ListFetchParams, type ListQueryOptions, type ListResponse, type ListState, ListView, type LocalFirstGraphRuntime, type ManagerOptions, type ManyToManyRelation, MarkdownFieldEditor, MarkdownFieldRenderer, MemoryAdapter, MultiSelectBar, type PaginationState, type GraphActionRecord as PersistedGraphActionRecord, type PresetChangeEvent, type PresetChangeOperation, PresetPicker, type PresetStoreState, type UnsubscribeFn as PresetUnsubscribeFn, type PrismaEntityConfigOptions, type ColumnDef as PureColumnDef, type ColumnMeta as PureColumnMeta, InlineCellEditor as PureInlineCellEditor, type QueryKey, type RealtimeAdapter, RealtimeManager, type RelationDescriptor, type RestAdapterOptions, RestApiAdapter, type Row, type RowModel, type RowSelectionState, type SchemaFieldDescriptor, type SchemaGraphToolContext, SelectionContext, type SelectionStoreState, Sheet, type SortClause, type SortDirection, SortHeader, type SortSpec, type SortingFn, type SortingState, type StartLocalFirstGraphOptions, type SubscriptionConfig, type SupabaseAdapterOptions$1 as SupabaseAdapterOptions, SupabaseRealtimeAdapter as SupabasePresetAdapter, type SupabaseAdapterOptions as SupabasePresetAdapterOptions, type SyncAdapter, type SyncOrigin, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, type TableInstance, type TableOptions, type TablePresetSlice, TableRow, type TableState, type TableStorageAdapter, TableStorageProvider, type TableStorageProviderProps, type UnsubscribeFn$1 as UnsubscribeFn, type Updater, type UseEntityViewOptions, type UseEntityViewResult, type UseLocalFirstResult, type UseTablePresetsOptions, type UseTablePresetsResult, type ViewDescriptor, type ViewFetchParams, type ViewMode, ViewModeSwitcher, type WebSocketAdapterOptions, type ZustandAdapterOptions, ZustandPersistAdapter, actionsColumn$1 as actionsColumn, applyView, booleanColumn$1 as booleanColumn, buildEntityFieldsFromSchema, cascadeInvalidation, checkCompleteness, compareEntities, configureEngine, createConvexAdapter, createElectricAdapter, createGQLClient, createGraphAction, createGraphEffect, createGraphQLSubscriptionAdapter, createGraphTool, createGraphTransaction, createPresetStore, createPrismaEntityConfig, createRow, createSchemaGraphTool, createSelectionStore, createSupabaseRealtimeAdapter, createWebSocketAdapter, dateColumn$1 as dateColumn, dedupe, deleteAction, editAction, enumColumn$1 as enumColumn, executeGQL, exportGraphSnapshot, exportGraphSnapshotWithSchemas, fetchEntity, fetchList, flattenClauses, getCoreRowModel, getEntityJsonSchema, getExpandedRowModel, getFacetedMinMaxValues, getFacetedRowModel, getFacetedUniqueValues, getFilteredRowModel, getGroupedRowModel, getPaginatedRowModel, getRealtimeManager, getSchema, getSelectedRowModel, getSortedRowModel, hasCustomPredicates, hydrateGraphFromStorage, matchesFilter, matchesSearch, normalizeGQLResponse, numberColumn$1 as numberColumn, persistGraphToStorage, prismaRelationsToSchema, actionsColumn as pureActionsColumn, booleanColumn as pureBooleanColumn, dateColumn as pureDateColumn, enumColumn as pureEnumColumn, numberColumn as pureNumberColumn, selectionColumn as pureSelectionColumn, textColumn as pureTextColumn, queryOnce, readRelations, registerEntityJsonSchema, registerRuntimeSchema, registerSchema, renderMarkdownToHtml, resetRealtimeManager, selectGraph, selectionColumn$1 as selectionColumn, serializeKey, startGarbageCollector, startLocalFirstGraph, stopGarbageCollector, textColumn$1 as textColumn, toGraphQLVariables, toPrismaInclude, toPrismaOrderBy, toPrismaWhere, toRestParams, toSQLClauses, useEntity, useEntityAugment, useEntityCRUD, useEntityList, useEntityMutation, useEntityView, useGQLEntity, useGQLList, useGQLMutation, useGQLSubscription, useGraphDevTools, useGraphStore, useGraphSyncStatus, useLocalFirst, usePGliteQuery, useSchemaEntityFields, useSelectionContext, useSelectionStore, useSuspenseEntity, useSuspenseEntityList, useTable, useTablePresets, useTableRealtimeMode, useTableStorageAdapter, viewAction };
|
|
3779
|
+
export { type AccessorFn, ActionButtonRow, type ActionDef, ActionDropdown, type ActionItem, type ActivePresets, type AdapterStatus, type AggregationFn, type BatchActionDef, type BelongsToRelation, type BuildEntityFieldsFromSchemaOptions, type CRUDMode, type CRUDOptions, type CRUDState, type CascadeContext, type Cell, type CellContext, type CellRenderer, type ChangeEvent, type ChangeOp, type ChangeOperation, type ChangeSet, type ChannelConfig, type Column, type ColumnFilterType, type ColumnFiltersState, type ColumnOrderState, type ColumnPinningState, type ColumnPreset, ColumnPresetDialog, type ColumnPresetEntry, type ColumnSizingState, type ColumnVisibilityState, type CompletenessMode, type CreatePGlitePersistenceAdapterOptions, DataTable, DataTableColumnHeader, DataTableFilter, DataTablePagination, DataTableToolbar, type DirtyFields, type ElectricAdapterOptions, ElectricSQLAdapter as ElectricSQLPresetAdapter, type ElectricSQLAdapterOptions as ElectricSQLPresetAdapterOptions, type ElectricTableConfig, EmptyState, type EmptyStateConfig, type EngineOptions, type EntityChange, type EntityColumnMeta, type EntityDescriptor, EntityDetailSheet, type EntityError, type EntityErrorOptions, EntityFormSheet, type EntityId, type EntityJsonSchemaConfig, EntityListView, type EntityListViewProps, type EntityQueryOptions, type EntitySchema, type EntitySnapshot, type EntityState, type EntitySyncMetadata, EntityTable, type EntityTransport, type EntityType, type ExpandedState, type FieldDescriptor, type FieldType, type FilterClause, type FilterFn, type FilterGroup, type FilterOperator, type FilterPreset, FilterPresetDialog, type FilterSpec, GQLClient, type GQLClientConfig, type GQLEntityOptions, type GQLError, type GQLListOptions, type GQLResponse, type GalleryColumns, GalleryView, type GraphActionEvent, type GraphActionOptions, type GraphActionRecord$1 as GraphActionRecord, type GraphEffectEvent, type GraphEffectHandle, type GraphEffectOptions, type GraphIncludeMap, type GraphIncludeRelation, type GraphPersistenceAdapter, type GraphQueryOptions, type GraphSnapshotExportOptions, type GraphSnapshotPayload, type GraphSnapshotWithSchemasOptions, type GraphState, type GraphSyncStatus, type GraphToolContext, type GraphTransaction, type GroupingState, type HasManyRelation, type Header, type HeaderContext, type HeaderGroup, type HeaderRenderer, InlineCellEditor$1 as InlineCellEditor, InlineItemEditor, type ItemDescriptor, type ItemDescriptorBadge, type ItemDescriptorMeta, type ItemRenderContext, type JsonSchemaObject, type ListFetchParams, type ListQuery, type ListQueryOptions, type ListResponse, type ListResult, type ListState, ListView, type LocalFirstGraphRuntime, type MakeRestTransportOptions, type ManagerOptions, type ManyToManyRelation, MarkdownFieldEditor, MarkdownFieldRenderer, MemoryAdapter, MultiSelectBar, type PGlitePersistenceClient, type PaginationState, type GraphActionRecord as PersistedGraphActionRecord, type PresetChangeEvent, type PresetChangeOperation, PresetPicker, type PresetStoreState, type UnsubscribeFn as PresetUnsubscribeFn, type PrismaEntityConfigOptions, type ColumnDef as PureColumnDef, type ColumnMeta as PureColumnMeta, InlineCellEditor as PureInlineCellEditor, type QueryKey, type RealtimeAdapter, RealtimeManager, type RegisterEntityFromSqlOptions, type RelationDescriptor, type ReplayRetryPolicy, type RestAdapterOptions, RestApiAdapter, type Row, type RowModel, type RowSelectionState, type SchemaFieldDescriptor, type SchemaGraphToolContext, SelectionContext, type SelectionStoreState, Sheet, type SortClause, type SortDirection, SortHeader, type SortSpec, type SortingFn, type SortingState, type StartLocalFirstGraphOptions, type SubscriptionConfig, type SupabaseAdapterOptions$1 as SupabaseAdapterOptions, type SupabaseLike, SupabaseRealtimeAdapter as SupabasePresetAdapter, type SupabaseAdapterOptions as SupabasePresetAdapterOptions, type SupabaseQueryBuilderLike, type SyncAdapter, type SyncOrigin, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, type TableInstance, type TableOptions, type TablePresetSlice, TableRow, type TableState, type TableStorageAdapter, TableStorageProvider, type TableStorageProviderProps, type TenantClaim, type TenantScopedAdapterOptions, type TenantScopedTableConfig, TerminalError, TransientError, type UnsubscribeFn$1 as UnsubscribeFn, type Updater, type UseEntitiesOptions, type UseEntitiesResult, type UseEntityListAsTableOptions, type UseEntityListAsTableResult, type UseEntityQueryOptions, type UseEntityQueryResult, type UseEntityViewOptions, type UseEntityViewResult, type UseLocalFirstResult, type UseTablePresetsOptions, type UseTablePresetsResult, type ViewDescriptor, type ViewFetchParams, type ViewMode, ViewModeSwitcher, type WebSocketAdapterOptions, type ZustandAdapterOptions, ZustandPersistAdapter, __resetEntityTransports, actionsColumn$1 as actionsColumn, applyView, booleanColumn$1 as booleanColumn, buildEntityFieldsFromSchema, buildTenantWhere, cascadeInvalidation, checkCompleteness, compareEntities, configureEngine, createConvexAdapter, createElectricAdapter, createGQLClient, createGraphAction, createGraphEffect, createGraphQLSubscriptionAdapter, createGraphTool, createGraphTransaction, createPGlitePersistenceAdapter, createPresetStore, createPrismaEntityConfig, createRow, createSchemaGraphTool, createSelectionStore, createSupabaseRealtimeAdapter, createTenantScopedElectricAdapter, createWebSocketAdapter, dateColumn$1 as dateColumn, dedupe, deleteAction, editAction, enumColumn$1 as enumColumn, executeGQL, exportGraphSnapshot, exportGraphSnapshotWithSchemas, fetchEntity, fetchList, flattenClauses, getCoreRowModel, getEntityJsonSchema, getEntityTransport, getExpandedRowModel, getFacetedMinMaxValues, getFacetedRowModel, getFacetedUniqueValues, getFilteredRowModel, getGroupedRowModel, getPaginatedRowModel, getRealtimeManager, getRegisteredEntityTypes, getSchema, getSelectedRowModel, getSortedRowModel, hasCustomPredicates, hydrateGraphFromStorage, makeRestTransport, matchesFilter, matchesSearch, normalizeGQLResponse, numberColumn$1 as numberColumn, parseCreateTable, persistGraphToStorage, prismaRelationsToSchema, actionsColumn as pureActionsColumn, booleanColumn as pureBooleanColumn, dateColumn as pureDateColumn, enumColumn as pureEnumColumn, numberColumn as pureNumberColumn, selectionColumn as pureSelectionColumn, textColumn as pureTextColumn, queryOnce, readRelations, registerEntityFromSql, registerEntityJsonSchema, registerEntityTransport, registerRuntimeSchema, registerSchema, renderMarkdownToHtml, replayActionWithRetry, resetRealtimeManager, selectGraph, selectionColumn$1 as selectionColumn, serializeKey, sqlTypeToJsonSchema, startGarbageCollector, startLocalFirstGraph, stopGarbageCollector, textColumn$1 as textColumn, toEntityError, toGraphQLVariables, toPrismaInclude, toPrismaOrderBy, toPrismaWhere, toRestParams, toSQLClauses, useEntities, useEntity, useEntityAugment, useEntityCRUD, useEntityList, useEntityListAsTable, useEntityMutation, useEntityQuery, useEntityView, useGQLEntity, useGQLList, useGQLMutation, useGQLSubscription, useGraphDevTools, useGraphStore, useGraphSyncStatus, useLocalFirst, usePGliteQuery, useSchemaEntityFields, useSelectionContext, useSelectionStore, useSuspenseEntity, useSuspenseEntityList, useTable, useTablePresets, useTableRealtimeMode, useTableStorageAdapter, viewAction };
|