@ebbjs/storage 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,243 @@
1
+ import { isFieldMap as u, mergeFieldValue as p, latestHlc as F, componentModel as m, componentField as H, isFieldLeaf as W, componentName as b } from "@ebbjs/core";
2
+ const B = 500, y = 64, h = /* @__PURE__ */ new WeakMap(), K = (e) => {
3
+ let t = 2166136261;
4
+ for (let n = 0; n < e.length; n += 1)
5
+ t ^= e.charCodeAt(n), t = Math.imul(t, 16777619) >>> 0;
6
+ return t >>> 0;
7
+ }, R = (e) => K(e) % y, V = () => Array.from({ length: y }, () => ({})), k = (e, t) => {
8
+ let n = t;
9
+ const o = {
10
+ get map() {
11
+ if (n === void 0) {
12
+ const r = {};
13
+ for (const s of e) Object.assign(r, s);
14
+ n = r;
15
+ }
16
+ return n;
17
+ }
18
+ };
19
+ return h.set(o, e), o;
20
+ }, I = (e) => u(e) && h.has(e), Y = (e) => {
21
+ const t = h.get(e);
22
+ if (t === void 0) throw new Error("not a sharded map field");
23
+ return t;
24
+ }, $ = (e) => e.map, z = (e) => {
25
+ const t = V(), n = {};
26
+ for (const [o, r] of Object.entries(e))
27
+ t[R(o)][o] = r, n[o] = r;
28
+ return k(t, n);
29
+ }, O = (e) => !u(e) || I(e) ? e : Object.keys(e.map).length >= B ? z(e.map) : e, j = (e) => {
30
+ let t;
31
+ for (const [n, o] of Object.entries(e)) {
32
+ const r = O(o);
33
+ r !== o && (t === void 0 && (t = { ...e }), t[n] = r);
34
+ }
35
+ return t ?? e;
36
+ }, U = (e) => {
37
+ let t;
38
+ for (const [n, o] of Object.entries(e))
39
+ !u(o) || !I(o) || (t === void 0 && (t = { ...e }), t[n] = { map: $(o) });
40
+ return t ?? e;
41
+ }, q = (e, t) => {
42
+ const n = Y(e), o = [...n], r = /* @__PURE__ */ new Map();
43
+ for (const [s, l] of Object.entries(t.map)) {
44
+ const a = R(s), v = (r.get(a) ?? n[a])[s], g = p(v, l);
45
+ if (g === v) continue;
46
+ let i = r.get(a);
47
+ i === void 0 && (i = { ...n[a] }, r.set(a, i)), i[s] = g;
48
+ }
49
+ if (r.size === 0) return e;
50
+ for (const [s, l] of r) o[s] = l;
51
+ return k(o);
52
+ }, G = (e, t) => {
53
+ if (e !== void 0 && u(e) && I(e))
54
+ return u(t) ? q(e, t) : t;
55
+ const n = p(e, t);
56
+ return n === e ? n : O(n);
57
+ }, he = (e, t) => e.method === "delete" ? t?.type ?? "" : m(e.component), J = (e) => {
58
+ if (e.method === "delete") return null;
59
+ const t = H(e.component);
60
+ return e.method === "drop" ? { field: t, method: "drop", value: null } : { field: t, method: e.method, value: e.data };
61
+ }, Ie = { residentMapFields: !0 }, Q = (e, t, n) => {
62
+ const o = n?.residentMapFields ? G : p, r = e.fields[t.field], s = o(r, t.value);
63
+ return s === r ? e : { fields: { ...e.fields, [t.field]: s } };
64
+ }, A = (e, t) => {
65
+ const n = t(e.data.fields);
66
+ return n === e.data.fields ? e : { ...e, data: { ...e.data, fields: n } };
67
+ }, _e = (e) => A(e, j), we = (e) => A(e, U), X = (e, t, n, o, r) => {
68
+ const s = { [t.field]: t.value }, l = t.method === "replace";
69
+ return {
70
+ id: e.subject_id,
71
+ type: m(e.component),
72
+ data: { fields: r?.residentMapFields ? j(s) : s },
73
+ // A `replace` is the row's create; a `merge` arrives first only when the
74
+ // replica has not seen that create, so the placeholder waits for the base.
75
+ exists: l,
76
+ created_hlc: l ? o : null,
77
+ updated_hlc: o,
78
+ deleted_hlc: null,
79
+ last_gsn: n
80
+ };
81
+ }, Z = (e, t, n, o, r) => {
82
+ if (t.method === "delete")
83
+ return e ? {
84
+ ...e,
85
+ deleted_hlc: o,
86
+ updated_hlc: o,
87
+ last_gsn: Math.max(e.last_gsn, n)
88
+ } : null;
89
+ const s = J(t);
90
+ if (s === null) return e;
91
+ if (s.method === "drop") {
92
+ if (!e) return null;
93
+ const { [s.field]: a, ...w } = e.data.fields;
94
+ return {
95
+ ...e,
96
+ data: { fields: w },
97
+ updated_hlc: F(e.updated_hlc, o),
98
+ last_gsn: Math.max(e.last_gsn, n)
99
+ };
100
+ }
101
+ if (!e) return X(t, s, n, o, r);
102
+ const l = s.method === "replace" && !e.exists;
103
+ return {
104
+ ...e,
105
+ type: m(t.component),
106
+ // A leaf `replace` is the leaf-level LWW compare, so it shares the merge
107
+ // rule: an out-of-order base snapshot must not clobber a newer write.
108
+ data: Q(e.data, s, r),
109
+ exists: e.exists || s.method === "replace",
110
+ created_hlc: l ? o : e.created_hlc,
111
+ updated_hlc: F(e.updated_hlc, o),
112
+ deleted_hlc: null,
113
+ last_gsn: Math.max(e.last_gsn, n)
114
+ };
115
+ }, ee = (e, t, n) => {
116
+ let o = e;
117
+ for (const r of n.updates)
118
+ r.subject_id === t && (o = Z(o, r, n.gsn, n.hlc));
119
+ return o;
120
+ }, ve = (e, t) => {
121
+ let n = null;
122
+ for (const o of e)
123
+ n = ee(n, t, o);
124
+ return n;
125
+ }, T = "relationship", f = "entityGroup", C = "groups", _ = (e, t, n) => `${e}\0${t}\0${n}`, D = (e, t, n) => `${_(e, t, n)}`, te = (e) => _(C, f, e), ne = (e) => D(C, f, e), d = (e, t) => {
126
+ const n = e.data?.fields?.[t];
127
+ if (n === void 0 || !W(n)) return null;
128
+ const o = n.value;
129
+ return typeof o == "string" ? o : null;
130
+ }, oe = (e) => {
131
+ if (e.type !== T || e.deleted_hlc !== null) return null;
132
+ const t = d(e, "field"), n = d(e, "type"), o = d(e, "target_id"), r = d(e, "source_id");
133
+ return t === null || n === null || o === null || r === null ? null : { key: _(t, n, o), rowId: e.id, value: r };
134
+ }, re = (e) => {
135
+ if (e.type !== T || e.deleted_hlc !== null) return null;
136
+ const t = d(e, "field"), n = d(e, "type"), o = d(e, "source_id"), r = d(e, "target_id");
137
+ return t === null || n === null || o === null || r === null ? null : { key: D(t, n, o), rowId: e.id, value: r };
138
+ }, se = (e) => {
139
+ if (e.type !== f || e.deleted_hlc !== null) return null;
140
+ const t = d(e, "group_id"), n = d(e, "entity_id");
141
+ return t === null || n === null ? null : { key: te(t), rowId: e.id, value: n };
142
+ }, le = (e) => {
143
+ if (e.type !== f || e.deleted_hlc !== null) return null;
144
+ const t = d(e, "group_id"), n = d(e, "entity_id");
145
+ return t === null || n === null ? null : { key: ne(n), rowId: e.id, value: t };
146
+ }, de = (e) => oe(e) ?? se(e), ce = (e) => re(e) ?? le(e), x = (e) => [...e].sort(), ge = (e) => x(new Set(Object.values(e ?? {}))), P = (e) => Object.entries(e ?? {}).map(([t, n]) => ({ rowId: t, value: n })).sort(
147
+ (t, n) => t.value === n.value ? t.rowId.localeCompare(n.rowId) : t.value.localeCompare(n.value)
148
+ ), Fe = (e) => P(e).map(({ rowId: t, value: n }) => ({ relationshipId: t, targetId: n })), Me = (e) => P(e).map(({ rowId: t, value: n }) => ({ membershipId: t, groupId: n })), N = (e, t, n) => {
149
+ const o = { ...e };
150
+ return n ? o[t.rowId] = t.value : delete o[t.rowId], o;
151
+ }, ae = (e, t) => N(e, t, !0), ue = (e, t) => {
152
+ const n = N(e, t, !1);
153
+ return Object.keys(n).length === 0 ? null : n;
154
+ }, ie = (e, t) => e?.key === t?.key && e?.rowId === t?.rowId && e?.value === t?.value, L = (e) => (t, n) => {
155
+ const o = t === void 0 ? null : e(t), r = n === void 0 ? null : e(n);
156
+ return ie(o, r) ? { remove: null, add: null } : { remove: o, add: r };
157
+ }, Ee = L(de), Se = L(ce), M = (e, t, n) => {
158
+ if (n === null) {
159
+ const o = { ...e };
160
+ return delete o[t.key], o;
161
+ }
162
+ return { ...e, [t.key]: n };
163
+ }, be = (e, t) => {
164
+ if (t.remove === null && t.add === null) return e;
165
+ let n = e;
166
+ return t.remove !== null && (n = M(n, t.remove, ue(n[t.remove.key], t.remove))), t.add !== null && (n = M(n, t.add, ae(n[t.add.key], t.add))), n;
167
+ }, c = (e) => Object.keys(e.data?.fields ?? {}).map((t) => b(e.type, t)), E = (e) => e.deleted_hlc !== null, ye = (e, t) => {
168
+ if (e === t) return [];
169
+ if (e == null)
170
+ return t == null ? [] : c(t);
171
+ if (t == null) return c(e);
172
+ if (e.type !== t.type || E(e) !== E(t))
173
+ return [.../* @__PURE__ */ new Set([...c(e), ...c(t)])];
174
+ const n = e.data?.fields ?? {}, o = t.data?.fields ?? {}, r = [], s = /* @__PURE__ */ new Set([...Object.keys(n), ...Object.keys(o)]);
175
+ for (const l of s)
176
+ n[l] !== o[l] && r.push(b(t.type, l));
177
+ return r;
178
+ }, Re = (e, t) => {
179
+ if (e === t || e === void 0 && t === void 0) return null;
180
+ const n = e === void 0 ? [] : c(e), o = t === void 0 ? [] : c(t), r = new Set(n), s = new Set(o);
181
+ return {
182
+ rowId: (t ?? e).id,
183
+ remove: n.filter((l) => !s.has(l)),
184
+ add: o.filter((l) => !r.has(l))
185
+ };
186
+ }, ke = (e, t) => {
187
+ if (t.add.length === 0 && t.remove.length === 0) return e;
188
+ const n = new Map(e);
189
+ for (const o of t.remove) {
190
+ const r = n.get(o);
191
+ if (r === void 0) continue;
192
+ const s = new Set(r);
193
+ s.delete(t.rowId), s.size === 0 ? n.delete(o) : n.set(o, s);
194
+ }
195
+ for (const o of t.add)
196
+ n.set(o, /* @__PURE__ */ new Set([...n.get(o) ?? [], t.rowId]));
197
+ return n;
198
+ }, Oe = (e) => {
199
+ const t = /* @__PURE__ */ new Map();
200
+ for (const n of e)
201
+ for (const o of c(n)) {
202
+ const r = t.get(o);
203
+ r === void 0 ? t.set(o, /* @__PURE__ */ new Set([n.id])) : r.add(n.id);
204
+ }
205
+ return t;
206
+ }, je = (e, t) => x(e.get(t) ?? []), fe = 2, S = (e) => typeof e == "number" && Number.isInteger(e) && e >= 0, pe = (e) => typeof e == "object" && e !== null && typeof e.id == "string" && typeof e.type == "string" && typeof e.exists == "boolean" && (e.created_hlc === null || typeof e.created_hlc == "string"), Ae = (e) => {
207
+ if (typeof e != "object" || e === null) return !1;
208
+ const t = e;
209
+ return t.format !== fe || !S(t.position) || !S(t.revision) || !Array.isArray(t.entities) ? !1 : t.entities.every(pe);
210
+ };
211
+ export {
212
+ T as A,
213
+ ue as B,
214
+ ae as C,
215
+ f as M,
216
+ fe as R,
217
+ Fe as a,
218
+ ge as b,
219
+ ne as c,
220
+ je as d,
221
+ c as e,
222
+ D as f,
223
+ _e as g,
224
+ de as h,
225
+ Ae as i,
226
+ ce as j,
227
+ Oe as k,
228
+ Me as l,
229
+ te as m,
230
+ be as n,
231
+ Ee as o,
232
+ Se as p,
233
+ Re as q,
234
+ _ as r,
235
+ ke as s,
236
+ Z as t,
237
+ he as u,
238
+ ye as v,
239
+ we as w,
240
+ Ie as x,
241
+ ee as y,
242
+ ve as z
243
+ };
@@ -122,9 +122,10 @@ interface MembershipLink {
122
122
  * handled by the DirtyTracker.
123
123
  *
124
124
  * ## Merge Semantics
125
- * - **put** — full entity replacement
126
- * - **patch** — field-level Last-Writer-Wins (LWW): higher HLC wins; tiebreak by lexicographic `update_id`
127
- * - **delete** — soft delete (sets `deleted_hlc`); patch-on-deleted is ignored
125
+ * - **merge** — Last-Writer-Wins (LWW) at the component's field: higher HLC wins; tiebreak by lexicographic `update_id`
126
+ * - **replace** — the component's field is set whole; the first write to an absent row creates it
127
+ * - **drop** — the component's field is removed; the row survives
128
+ * - **delete** — soft delete (sets `deleted_hlc`); the row keeps its type
128
129
  *
129
130
  * A field value is either a leaf merged by the LWW rule above, or a
130
131
  * `{ map }` of nested field values merged key by key under the same
@@ -136,6 +137,9 @@ interface MembershipLink {
136
137
  * - `get(id)` — returns entity by ID, materializes if dirty
137
138
  * - `set(entity)` — directly sets an entity (bypasses materialization)
138
139
  * - `query(type)` — returns all materialized entities of a type
140
+ * - `queryByComponent(component)` — returns the live ids carrying that
141
+ * `<model>/<field>` component in ascending order, materializing dirty rows
142
+ * of the component's model first
139
143
  * - `queryByRelationship({ as, type, targetId })` — returns the distinct
140
144
  * source ids indexed under that triple in ascending order,
141
145
  * materializing dirty relationship rows first
@@ -154,6 +158,18 @@ interface EntityStore {
154
158
  get(id: string): Promise<Entity | null>;
155
159
  set(entity: Entity): Promise<void>;
156
160
  query(type: string): Promise<readonly Entity[]>;
161
+ /**
162
+ * Live rows currently carrying `component` (`<model>/<field>`), ascending by
163
+ * id. Existence is the set of present fields on a row, so this is an index
164
+ * read rather than a row filter; a tombstoned row's components are not
165
+ * existence.
166
+ *
167
+ * The dirty rows materialized first are the component prefix's model. That is
168
+ * the current `<model>/<field>` addressing rule (#797); a component namespace
169
+ * that is not the row's model (#805's `ebb/*` components on ordinary rows)
170
+ * has to decode the model differently and revisit this step.
171
+ */
172
+ queryByComponent(component: string): Promise<readonly string[]>;
157
173
  queryByRelationship(query: RelationshipIndexQuery): Promise<readonly string[]>;
158
174
  queryByRelationshipSource(query: RelationshipSourceQuery): Promise<readonly RelationshipLink[]>;
159
175
  queryByMembership(groupId: string): Promise<readonly string[]>;
@@ -263,8 +279,15 @@ type Revision = number;
263
279
  interface ReplicaChange {
264
280
  readonly revision: Revision;
265
281
  readonly id: string;
266
- readonly type: string;
267
282
  readonly deleted: boolean;
283
+ /**
284
+ * The components this change touched, so a derived reader invalidates on what
285
+ * it read rather than on the row's whole model. A tombstone transition touches
286
+ * every component the row carries, and a write that moves a row between models
287
+ * names each field under both prefixes. Empty only for a row that carried no
288
+ * component.
289
+ */
290
+ readonly components: readonly string[];
268
291
  }
269
292
  /**
270
293
  * Whether the replica retains a type's rows. The seam #500 builds on-demand
@@ -364,7 +387,11 @@ interface Replica {
364
387
  * with gsn 0, which would hide the row's folded position.
365
388
  */
366
389
  base(id: string): Entity | undefined;
367
- iterate(type: string): readonly Entity[];
390
+ /**
391
+ * Every row of `model`, whatever optional components it carries. Served by
392
+ * the model index with the overlay's model overrides layered on top.
393
+ */
394
+ iterate(model: string): readonly Entity[];
368
395
  /** Whether the materialization policy holds `type` in full. */
369
396
  isHeld(type: string): boolean;
370
397
  /**
@@ -395,6 +422,12 @@ interface Replica {
395
422
  * live sources pointing at `(as, type, targetId)`, ascending.
396
423
  */
397
424
  relationships(query: RelationshipQuery): readonly string[];
425
+ /**
426
+ * Ids currently carrying `component` (`<type>/<field>`) in the composed
427
+ * view, ascending. Component existence is the set of present fields on a
428
+ * row, so a query reading it costs its index rather than a row filter.
429
+ */
430
+ components(component: string): readonly string[];
398
431
  /**
399
432
  * Distinct live member entity ids of a group, or distinct live group
400
433
  * ids of an entity, ascending.
@@ -452,32 +485,32 @@ type OutboxStatus = "pending" | "acknowledged" | "error" | "conflicted";
452
485
  /**
453
486
  * One side of a contested slot: the buffered local write, or the value
454
487
  * the server holds once the catch-up window is applied. A leaf carries
455
- * its LWW triple; a whole-field map replacement has no single leaf, so
488
+ * its LWW triple; a whole-component map replacement has no single leaf, so
456
489
  * `update_id` / `hlc` are absent and `value` is the projected map. A
457
- * field an inbound `put` or `delete` reverted also has no triple, and
490
+ * component an inbound `merge` or `delete` reverted also has no triple, and
458
491
  * `value` is `undefined` because the server holds no value.
459
492
  */
460
493
  interface ConflictSide {
461
494
  /** Projected leaf or map value. `undefined` when the server holds nothing. */
462
495
  readonly value: unknown;
463
- /** `update_id` of the FieldValue; absent for a map side or a reverted field. */
496
+ /** `update_id` of the FieldValue; absent for a map side or a reverted component. */
464
497
  readonly update_id?: string;
465
- /** HLC carried by the FieldValue; absent for a map side or a reverted field. */
498
+ /** HLC carried by the FieldValue; absent for a map side or a reverted component. */
466
499
  readonly hlc?: string;
467
500
  }
468
501
  /**
469
- * One contested position on a losing Action: a field plus the map-key
470
- * path from the field root to the position. `path` is empty for a plain
471
- * leaf field, an entity-level touch that overlaps no position, or a
472
- * field an inbound `put` / `delete` reverted. Concurrent writes to
502
+ * One contested position on a losing Action: a component plus the map-key
503
+ * path from the component's value root to the position. `path` is empty for a
504
+ * plain leaf component, an entity-level touch that overlaps no position, or a
505
+ * component an inbound `merge` / `delete` reverted. Concurrent writes to
473
506
  * different keys are different slots and so are not conflicts.
474
507
  */
475
508
  interface ConflictSlot {
476
509
  /** The `subject_id` of the Update that carried the write. */
477
510
  readonly subjectId: string;
478
- /** The field name on that subject. */
479
- readonly field: string;
480
- /** Ordered map keys from the field root to the position; empty at the root. */
511
+ /** The `<model>/<field>` component name on that subject. */
512
+ readonly component: string;
513
+ /** Ordered map keys from the component root to the position; empty at the root. */
481
514
  readonly path: readonly string[];
482
515
  /** The buffered local value at the position. */
483
516
  readonly local: ConflictSide;
@@ -501,7 +534,8 @@ interface ConflictRemoteAction {
501
534
  */
502
535
  interface ConflictSubjectState {
503
536
  readonly subjectId: string;
504
- readonly subjectType: string;
537
+ /** The model the row is committed under. */
538
+ readonly model: string;
505
539
  readonly before: Entity | null;
506
540
  readonly after: Entity | null;
507
541
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ebbjs/storage",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "private": false,
5
5
  "description": "Storage components for ebbjs",
6
6
  "homepage": "https://ebbjs.com",
@@ -44,7 +44,7 @@
44
44
  "access": "public"
45
45
  },
46
46
  "dependencies": {
47
- "@ebbjs/core": "^1.0.0"
47
+ "@ebbjs/core": "^1.1.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "fake-indexeddb": "^6.2.5",
@@ -1,179 +0,0 @@
1
- import { isFieldMap as u, mergeFieldValue as m, latestHlc as P, isFieldLeaf as D } from "@ebbjs/core";
2
- const L = 500, E = 64, I = /* @__PURE__ */ new WeakMap(), N = (e) => {
3
- let r = 2166136261;
4
- for (let t = 0; t < e.length; t += 1)
5
- r ^= e.charCodeAt(t), r = Math.imul(r, 16777619) >>> 0;
6
- return r >>> 0;
7
- }, M = (e) => N(e) % E, C = () => Array.from({ length: E }, () => ({})), R = (e, r) => {
8
- let t = r;
9
- const n = {
10
- get map() {
11
- if (t === void 0) {
12
- const s = {};
13
- for (const o of e) Object.assign(s, o);
14
- t = s;
15
- }
16
- return t;
17
- }
18
- };
19
- return I.set(n, e), n;
20
- }, _ = (e) => u(e) && I.has(e), H = (e) => {
21
- const r = I.get(e);
22
- if (r === void 0) throw new Error("not a sharded map field");
23
- return r;
24
- }, V = (e) => e.map, W = (e) => {
25
- const r = C(), t = {};
26
- for (const [n, s] of Object.entries(e))
27
- r[M(n)][n] = s, t[n] = s;
28
- return R(r, t);
29
- }, b = (e) => !u(e) || _(e) ? e : Object.keys(e.map).length >= L ? W(e.map) : e, y = (e) => {
30
- let r;
31
- for (const [t, n] of Object.entries(e)) {
32
- const s = b(n);
33
- s !== n && (r === void 0 && (r = { ...e }), r[t] = s);
34
- }
35
- return r ?? e;
36
- }, K = (e) => {
37
- let r;
38
- for (const [t, n] of Object.entries(e))
39
- !u(n) || !_(n) || (r === void 0 && (r = { ...e }), r[t] = { map: V(n) });
40
- return r ?? e;
41
- }, Y = (e, r) => {
42
- const t = H(e), n = [...t], s = /* @__PURE__ */ new Map();
43
- for (const [o, d] of Object.entries(r.map)) {
44
- const a = M(o), c = (s.get(a) ?? t[a])[o], F = m(c, d);
45
- if (F === c) continue;
46
- let i = s.get(a);
47
- i === void 0 && (i = { ...t[a] }, s.set(a, i)), i[o] = F;
48
- }
49
- if (s.size === 0) return e;
50
- for (const [o, d] of s) n[o] = d;
51
- return R(n);
52
- }, $ = (e, r) => {
53
- if (e !== void 0 && u(e) && _(e))
54
- return u(r) ? Y(e, r) : r;
55
- const t = m(e, r);
56
- return t === e ? t : b(t);
57
- }, h = (e) => e.data?.fields ?? {}, ce = { residentMapFields: !0 }, B = (e, r, t) => {
58
- const n = h(r), s = t?.residentMapFields ? $ : m;
59
- let o;
60
- for (const [d, a] of Object.entries(n)) {
61
- const p = o === void 0 ? e.fields[d] : o[d], c = s(p, a);
62
- c !== p && (o === void 0 && (o = { ...e.fields }), o[d] = c);
63
- }
64
- return o === void 0 ? e : { fields: o };
65
- }, k = (e, r) => {
66
- const t = r(e.data.fields);
67
- return t === e.data.fields ? e : { ...e, data: { ...e.data, fields: t } };
68
- }, ue = (e) => k(e, y), ie = (e) => k(e, K), U = (e, r, t, n, s) => {
69
- switch (r.method) {
70
- case "put":
71
- return {
72
- id: r.subject_id,
73
- type: r.subject_type,
74
- data: {
75
- fields: s?.residentMapFields ? y(h(r)) : h(r)
76
- },
77
- created_hlc: n,
78
- updated_hlc: n,
79
- deleted_hlc: null,
80
- last_gsn: t
81
- };
82
- case "patch":
83
- return e ? e.deleted_hlc ? e : {
84
- ...e,
85
- data: B(e.data, r, s),
86
- updated_hlc: P(e.updated_hlc, n),
87
- last_gsn: Math.max(e.last_gsn, t)
88
- } : null;
89
- case "delete":
90
- return e ? {
91
- ...e,
92
- deleted_hlc: n,
93
- updated_hlc: n,
94
- last_gsn: Math.max(e.last_gsn, t)
95
- } : null;
96
- }
97
- }, q = (e, r, t) => {
98
- let n = e;
99
- for (const s of t.updates)
100
- s.subject_id === r && (n = U(n, s, t.gsn, t.hlc));
101
- return n;
102
- }, fe = (e, r) => {
103
- let t = null;
104
- for (const n of e)
105
- t = q(t, r, n);
106
- return t;
107
- }, S = "relationship", f = "entityGroup", j = "groups", v = (e, r, t) => `${e}\0${r}\0${t}`, O = (e, r, t) => `${v(e, r, t)}`, z = (e) => v(j, f, e), G = (e) => O(j, f, e), l = (e, r) => {
108
- const t = e.data?.fields?.[r];
109
- if (t === void 0 || !D(t)) return null;
110
- const n = t.value;
111
- return typeof n == "string" ? n : null;
112
- }, J = (e) => {
113
- if (e.type !== S || e.deleted_hlc !== null) return null;
114
- const r = l(e, "field"), t = l(e, "type"), n = l(e, "target_id"), s = l(e, "source_id");
115
- return r === null || t === null || n === null || s === null ? null : { key: v(r, t, n), rowId: e.id, value: s };
116
- }, Q = (e) => {
117
- if (e.type !== S || e.deleted_hlc !== null) return null;
118
- const r = l(e, "field"), t = l(e, "type"), n = l(e, "source_id"), s = l(e, "target_id");
119
- return r === null || t === null || n === null || s === null ? null : { key: O(r, t, n), rowId: e.id, value: s };
120
- }, X = (e) => {
121
- if (e.type !== f || e.deleted_hlc !== null) return null;
122
- const r = l(e, "group_id"), t = l(e, "entity_id");
123
- return r === null || t === null ? null : { key: z(r), rowId: e.id, value: t };
124
- }, Z = (e) => {
125
- if (e.type !== f || e.deleted_hlc !== null) return null;
126
- const r = l(e, "group_id"), t = l(e, "entity_id");
127
- return r === null || t === null ? null : { key: G(t), rowId: e.id, value: r };
128
- }, ee = (e) => J(e) ?? X(e), re = (e) => Q(e) ?? Z(e), te = (e) => [...e].sort(), pe = (e) => te(new Set(Object.values(e ?? {}))), x = (e) => Object.entries(e ?? {}).map(([r, t]) => ({ rowId: r, value: t })).sort(
129
- (r, t) => r.value === t.value ? r.rowId.localeCompare(t.rowId) : r.value.localeCompare(t.value)
130
- ), he = (e) => x(e).map(({ rowId: r, value: t }) => ({ relationshipId: r, targetId: t })), me = (e) => x(e).map(({ rowId: r, value: t }) => ({ membershipId: r, groupId: t })), A = (e, r, t) => {
131
- const n = { ...e };
132
- return t ? n[r.rowId] = r.value : delete n[r.rowId], n;
133
- }, ne = (e, r) => A(e, r, !0), se = (e, r) => {
134
- const t = A(e, r, !1);
135
- return Object.keys(t).length === 0 ? null : t;
136
- }, oe = (e, r) => e?.key === r?.key && e?.rowId === r?.rowId && e?.value === r?.value, T = (e) => (r, t) => {
137
- const n = r === void 0 ? null : e(r), s = t === void 0 ? null : e(t);
138
- return oe(n, s) ? { remove: null, add: null } : { remove: n, add: s };
139
- }, Ie = T(ee), _e = T(re), w = (e, r, t) => {
140
- if (t === null) {
141
- const n = { ...e };
142
- return delete n[r.key], n;
143
- }
144
- return { ...e, [r.key]: t };
145
- }, ve = (e, r) => {
146
- if (r.remove === null && r.add === null) return e;
147
- let t = e;
148
- return r.remove !== null && (t = w(t, r.remove, se(t[r.remove.key], r.remove))), r.add !== null && (t = w(t, r.add, ne(t[r.add.key], r.add))), t;
149
- }, le = 1, g = (e) => typeof e == "number" && Number.isInteger(e) && e >= 0, de = (e) => typeof e == "object" && e !== null && typeof e.id == "string" && typeof e.type == "string", Fe = (e) => {
150
- if (typeof e != "object" || e === null) return !1;
151
- const r = e;
152
- return r.format !== le || !g(r.position) || !g(r.revision) || !Array.isArray(r.entities) ? !1 : r.entities.every(de);
153
- };
154
- export {
155
- f as M,
156
- le as R,
157
- he as a,
158
- pe as b,
159
- G as c,
160
- ue as d,
161
- ee as e,
162
- O as f,
163
- re as g,
164
- ve as h,
165
- Fe as i,
166
- Ie as j,
167
- _e as k,
168
- me as l,
169
- z as m,
170
- U as n,
171
- ce as o,
172
- q as p,
173
- fe as q,
174
- v as r,
175
- S as s,
176
- se as t,
177
- ne as u,
178
- ie as w
179
- };