@ai-matrx/entity-data 0.3.43 → 0.4.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.
@@ -1,244 +0,0 @@
1
- import * as _ai_matrx_realtime from '@ai-matrx/realtime';
2
- import { RealtimeManager, ChannelSpec } from '@ai-matrx/realtime';
3
- import { RecordsResult, Uuid as Uuid$1 } from '@ai-matrx/records';
4
- import { Lane, Uuid } from '@ai-matrx/records/data';
5
-
6
- /** A link as the door words it: `{token, id, label}`. */
7
- interface EntityWireRef {
8
- token: string;
9
- id: Uuid;
10
- label: string | null;
11
- }
12
- /** One row exactly as `platform.entity_list_scoped` / `entity_get` answer it. */
13
- interface EntityWireRow {
14
- id: Uuid;
15
- version: number;
16
- organization_id: Uuid;
17
- /** The row's own organization's custom fields, already masked by the store (a hidden field is null). */
18
- _custom?: Record<string, unknown>;
19
- /** The token's own columns; link columns are `EntityWireRef[]`. */
20
- [column: string]: unknown;
21
- }
22
- interface EntitySortApplied {
23
- column: string;
24
- dir: "asc" | "desc";
25
- nulls: "first" | "last";
26
- }
27
- interface EntityListAnswer {
28
- rows: EntityWireRow[];
29
- /** null when not asked for. */
30
- total: number | null;
31
- /** The total stopped at the store's count cap; `total` is then a floor, not a count. */
32
- total_is_capped: boolean;
33
- page_size: number;
34
- /** The keyset cursor of the next page; opaque. */
35
- next_after: string | null;
36
- has_more: boolean;
37
- sort_applied: EntitySortApplied[];
38
- /** Sort columns the door could not use (it keeps one key today). Said back, never hidden. */
39
- sort_ignored: string[];
40
- feed_cursor: null;
41
- }
42
- interface EntityGetAnswer {
43
- rows: EntityWireRow[];
44
- /** Ids that are not there or that this person cannot open. */
45
- missing: Uuid[];
46
- feed_cursor: null;
47
- }
48
- interface EntityColumnWire {
49
- key: string;
50
- label: string;
51
- type: string;
52
- origin: "platform" | "custom";
53
- required: boolean;
54
- readOnly: boolean;
55
- linksTo?: string[];
56
- choices?: string[];
57
- /** Custom columns only. */
58
- field_id?: Uuid;
59
- organization?: string;
60
- organization_id?: Uuid;
61
- }
62
- interface EntityColumnsAnswer {
63
- label: string;
64
- token: string;
65
- columns: EntityColumnWire[];
66
- can_create: boolean;
67
- can_update: boolean;
68
- /** The type's landing lane (`platform.entity_default_list_scope`). */
69
- default_scope: Lane;
70
- }
71
- /** One filter predicate as the door reads it (CONTRACT §3.2). */
72
- interface EntityWirePredicate {
73
- column: string;
74
- op: string;
75
- value?: unknown;
76
- values?: unknown[];
77
- negated?: boolean;
78
- }
79
- interface EntityWireSort {
80
- column: string;
81
- dir: "asc" | "desc";
82
- nulls: "last";
83
- }
84
- interface EntityWireQuery {
85
- /** Absent = the type's own landing lane. `organization_id` narrows any lane and never locks it. */
86
- scope?: {
87
- kind?: Lane;
88
- organization_id?: Uuid;
89
- };
90
- filter?: {
91
- all: EntityWirePredicate[];
92
- };
93
- search?: string;
94
- sort?: EntityWireSort[];
95
- pageSize?: number;
96
- }
97
- /** What every write door answers (`entity_insert` / `entity_update` / `entity_archive` / `entity_unarchive`). */
98
- interface EntityWriteAnswer {
99
- status: string;
100
- /** The rows as the read door now reads them, each with its NEW `version`. */
101
- rows: EntityWireRow[];
102
- validation: unknown[];
103
- feed_cursor: null;
104
- /** Archive and restore say what they did, in the store's words (trash words on these types). */
105
- message?: string;
106
- }
107
-
108
- /**
109
- * THE ECHO HEADER (U6). The entity doors take no `_op_id` argument: the writer's op id rides the request
110
- * as this header, PostgREST hands it to `request.headers`, and `platform._entity_org_notice` puts it on
111
- * the notice as `op_id`, so the browser that wrote drops its own echo (`@ai-matrx/records` `isOwnOp`).
112
- */
113
- declare const OP_ID_HEADER = "x-matrx-op-id";
114
- /** What a write takes beyond its arguments: the op id minted for it (`mintOpId`). */
115
- interface EntityWriteOptions {
116
- opId?: string;
117
- }
118
- /** The schema every entity door lives in. */
119
- declare const ENTITY_DOOR_SCHEMA = "platform";
120
- interface CreateEntityClientOptions {
121
- /** A supabase-js v2 client for the signed-in person, or anything with `rpc(fn, args, {schema})`. */
122
- dataSource?: unknown;
123
- /** Same thing, spelled the way the plan names it. Give one of the two. */
124
- supabase?: unknown;
125
- }
126
- interface EntityListRequest extends EntityWireQuery {
127
- token: string;
128
- /** Keyset cursor from the previous answer's `next_after`. */
129
- after?: string | null;
130
- /** Ask the door to skip the count. Default: counted. */
131
- withTotal?: boolean;
132
- archived?: "active" | "archived" | "all";
133
- }
134
- interface EntityClient {
135
- list(request: EntityListRequest): Promise<RecordsResult<EntityListAnswer>>;
136
- get(request: {
137
- token: string;
138
- ids: readonly Uuid$1[];
139
- }): Promise<RecordsResult<EntityGetAnswer>>;
140
- /** `organizationId` null reads the custom fields of every organization the person belongs to. */
141
- columns(request: {
142
- token: string;
143
- organizationId?: Uuid$1 | null;
144
- }): Promise<RecordsResult<EntityColumnsAnswer>>;
145
- /** One `entity_data` knob as `platform.knob_resolve` answers it for an organization (live updates read three). */
146
- knob(request: {
147
- key: string;
148
- organizationId?: Uuid$1 | null;
149
- }): Promise<RecordsResult<unknown>>;
150
- /** `platform.entity_insert`: rows into the organization the host names (never guessed). */
151
- insert(request: {
152
- token: string;
153
- organizationId: Uuid$1;
154
- rows: readonly Record<string, unknown>[];
155
- } & EntityWriteOptions): Promise<RecordsResult<EntityWriteAnswer>>;
156
- /** `platform.entity_update`: one row, refused as stale (`MX001`) unless `baseVersion` is still current. */
157
- update(request: {
158
- token: string;
159
- id: Uuid$1;
160
- baseVersion: number;
161
- patch: Record<string, unknown>;
162
- } & EntityWriteOptions): Promise<RecordsResult<EntityWriteAnswer>>;
163
- /** `platform.entity_archive` (on these types, the trash). */
164
- archive(request: {
165
- token: string;
166
- ids: readonly Uuid$1[];
167
- } & EntityWriteOptions): Promise<RecordsResult<EntityWriteAnswer>>;
168
- /** `platform.entity_unarchive`. */
169
- unarchive(request: {
170
- token: string;
171
- ids: readonly Uuid$1[];
172
- } & EntityWriteOptions): Promise<RecordsResult<EntityWriteAnswer>>;
173
- /** The organizations the person belongs to, as row security counts them (`iam.my_orgs()`: archived ones closed). */
174
- memberOrganizations(): Promise<RecordsResult<Uuid$1[]>>;
175
- }
176
- declare function createEntityClient(options: CreateEntityClientOptions): EntityClient;
177
-
178
- /** The topic is a CONTRACT WITH THE DATABASE (a trigger writes it, an RLS policy parses it): built once, here. */
179
- declare const entityOrgChannel: _ai_matrx_realtime.ChannelNamespace;
180
- /** The broadcast event the database sends on an organization topic. */
181
- declare const ENTITY_NOTICE_EVENT = "entity_bump";
182
- /** Starting values of the knobs the runtime coalesces with (entity_data.realtime_batch_ms / _max_wait_ms). */
183
- declare const DEFAULT_BATCH_MS = 150;
184
- declare const DEFAULT_MAX_WAIT_MS = 1000;
185
- /** Starting value of knob entity_data.realtime_max_org_topics. */
186
- declare const DEFAULT_MAX_ORG_TOPICS = 20;
187
- interface EntityNotice {
188
- id?: string;
189
- entity_type?: string;
190
- organization_id?: string;
191
- op?: "created" | "updated" | "deleted";
192
- /** The client operation that caused it (header `x-matrx-op-id`), or null for any other writer. */
193
- op_id?: string | null;
194
- /** `null` MEANS "more changed than the database lists: re-read". */
195
- ids?: string[] | null;
196
- at?: string;
197
- }
198
- /** A redelivered notice is the same notice: the database mints one id per send. */
199
- declare function entityNoticeKey(notice: EntityNotice): string | undefined;
200
- declare function entityOrgTopic(organizationId: string, token: string): string;
201
- /** The channel spec for one (organization, token): private, echo-guarded, deduped, backfilled. */
202
- declare function entityOrgChannelSpec(organizationId: string, token: string, onNotice: (notice: EntityNotice) => void, onBackfill: () => void): ChannelSpec;
203
- /**
204
- * Which organization topics to join, in order, until `max`: the active organization, the alias's `org`
205
- * filter, then the organizations of held rows by number of held rows (descending; organization id
206
- * ascending on ties), then the person's remaining memberships by id. Only memberships are kept when they
207
- * are known — any other topic is refused by the database anyway. Deterministic for the same input.
208
- */
209
- declare function orderOrganizationTopics(input: {
210
- active?: string | null;
211
- filter?: string | null;
212
- held?: ReadonlyMap<string, number>;
213
- members?: readonly string[] | null;
214
- max: number;
215
- }): string[];
216
- interface EntityNoticeSink {
217
- /** `ids` to re-read, or `null` to re-read everything this reader shows. */
218
- rows(ids: string[] | null): void;
219
- }
220
- interface EntityRealtime {
221
- /** Hear `token` across `organizationIds`; the sink gets one coalesced call per burst. Returns the stop. */
222
- subscribe(target: {
223
- token: string;
224
- organizationIds: readonly string[];
225
- }, sink: EntityNoticeSink): () => void;
226
- }
227
- interface CreateEntityRealtimeOptions {
228
- /** The host's realtime manager. Left out, the AMBIENT manager the app mounted — never a socket of our own. */
229
- manager?: RealtimeManager;
230
- /** Knob entity_data.realtime_batch_ms (starting value 150). */
231
- batchMs?: number;
232
- /** Knob entity_data.realtime_max_wait_ms (starting value 1000). */
233
- maxWaitMs?: number;
234
- }
235
- /** The live-notice layer for platform lists, bound to a realtime manager. One per host is enough. */
236
- declare function createEntityRealtime(options?: CreateEntityRealtimeOptions): EntityRealtime;
237
- /** The three live-update knobs as the store answers them for an organization (starting values when unset). */
238
- declare function readEntityRealtimeKnobs(client: Pick<EntityClient, "knob">, organizationId?: string | null): Promise<{
239
- batchMs: number;
240
- maxWaitMs: number;
241
- maxOrgTopics: number;
242
- }>;
243
-
244
- export { entityOrgTopic as A, orderOrganizationTopics as B, type CreateEntityClientOptions as C, DEFAULT_BATCH_MS as D, ENTITY_DOOR_SCHEMA as E, readEntityRealtimeKnobs as F, OP_ID_HEADER as O, type CreateEntityRealtimeOptions as a, DEFAULT_MAX_ORG_TOPICS as b, DEFAULT_MAX_WAIT_MS as c, ENTITY_NOTICE_EVENT as d, type EntityClient as e, type EntityColumnWire as f, type EntityColumnsAnswer as g, type EntityGetAnswer as h, type EntityListAnswer as i, type EntityListRequest as j, type EntityNotice as k, type EntityNoticeSink as l, type EntityRealtime as m, type EntitySortApplied as n, type EntityWirePredicate as o, type EntityWireQuery as p, type EntityWireRef as q, type EntityWireRow as r, type EntityWireSort as s, type EntityWriteAnswer as t, type EntityWriteOptions as u, createEntityClient as v, createEntityRealtime as w, entityNoticeKey as x, entityOrgChannel as y, entityOrgChannelSpec as z };