@signaldb/generic-fs 2.0.0-beta.1 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/deltaHelpers.d.ts +55 -0
- package/dist/index.mjs +151 -148
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export type IndexDelta<I> = {
|
|
2
|
+
adds: Map<string, Set<I>>;
|
|
3
|
+
removes: Map<string, Set<I>>;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Records a single index mutation into the delta map for a given indexed field.
|
|
7
|
+
*
|
|
8
|
+
* The delta map is grouped by `fieldPath`, and then by stringified key (`rawKey`).
|
|
9
|
+
* Each key maps to a set of identifiers to add/remove for that key.
|
|
10
|
+
* @param deltas - Accumulator of per-field index deltas.
|
|
11
|
+
* @param fieldPath - Dot-path of the indexed field (used as the delta bucket key).
|
|
12
|
+
* @param changeKind - Whether this identifier should be added to or removed from the index key.
|
|
13
|
+
* @param rawKey - The stringified index key value.
|
|
14
|
+
* @param identifier - The item identifier to add/remove for `rawKey`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function addToDelta<I>(deltas: Map<string, IndexDelta<I>>, fieldPath: string, changeKind: 'add' | 'remove', rawKey: string, identifier: I): void;
|
|
17
|
+
/**
|
|
18
|
+
* Computes the delta for a change in a single indexed field.
|
|
19
|
+
*
|
|
20
|
+
* Values are coerced to string keys (with `null`/`undefined` treated as "no key").
|
|
21
|
+
* If the derived keys are equal, no delta is recorded.
|
|
22
|
+
* @param deltas - Accumulator of per-field index deltas.
|
|
23
|
+
* @param fieldPath - Dot-path of the indexed field being tracked.
|
|
24
|
+
* @param oldValue - Previous value of the field.
|
|
25
|
+
* @param newValue - Next value of the field.
|
|
26
|
+
* @param identifier - The item identifier affected by the change.
|
|
27
|
+
*/
|
|
28
|
+
export declare function addDeltaForChange<I>(deltas: Map<string, IndexDelta<I>>, fieldPath: string, oldValue: any, newValue: any, identifier: I): void;
|
|
29
|
+
/**
|
|
30
|
+
* Accumulates index deltas for an upsert operation.
|
|
31
|
+
*
|
|
32
|
+
* - If `existingItem` is present, compares each maintained index field between the old and new item,
|
|
33
|
+
* recording removes/adds for key changes.
|
|
34
|
+
* - If `existingItem` is absent, treats the operation as an insert and records adds for each
|
|
35
|
+
* maintained index field that has a non-null value.
|
|
36
|
+
* @param deltas - Accumulator of per-field index deltas.
|
|
37
|
+
* @param indicesToMaintain - List of dot-paths for fields that are indexed.
|
|
38
|
+
* @param existingItem - Previous stored item (if any).
|
|
39
|
+
* @param nextItem - Incoming item to upsert.
|
|
40
|
+
*/
|
|
41
|
+
export declare const accumulateUpsertDelta: <T extends {
|
|
42
|
+
id: I;
|
|
43
|
+
}, I>(deltas: Map<string, IndexDelta<I>>, indicesToMaintain: string[], existingItem: T | undefined, nextItem: T) => void;
|
|
44
|
+
/**
|
|
45
|
+
* Accumulates index deltas for a remove/delete operation.
|
|
46
|
+
*
|
|
47
|
+
* For each maintained index field, records a removal of the item's identifier from the
|
|
48
|
+
* corresponding stringified key (skipping `null`/`undefined` values).
|
|
49
|
+
* @param deltas - Accumulator of per-field index deltas.
|
|
50
|
+
* @param indicesToMaintain - List of dot-paths for fields that are indexed.
|
|
51
|
+
* @param existingItem - The item being removed.
|
|
52
|
+
*/
|
|
53
|
+
export declare function accumulateRemoveDelta<T extends {
|
|
54
|
+
id: I;
|
|
55
|
+
}, I>(deltas: Map<string, IndexDelta<I>>, indicesToMaintain: string[], existingItem: T): void;
|
package/dist/index.mjs
CHANGED
|
@@ -1,195 +1,198 @@
|
|
|
1
|
-
import {
|
|
2
|
-
function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { get as j, createStorageAdapter as N } from "@signaldb/core";
|
|
2
|
+
function M(e, d, p, f, l) {
|
|
3
|
+
e.has(d) || e.set(d, { adds: /* @__PURE__ */ new Map(), removes: /* @__PURE__ */ new Map() });
|
|
4
|
+
const x = e.get(d);
|
|
5
|
+
if (!x)
|
|
6
|
+
return;
|
|
7
|
+
const I = p === "add" ? x.adds : x.removes;
|
|
8
|
+
I.has(f) || I.set(f, /* @__PURE__ */ new Set()), I.get(f)?.add(l);
|
|
9
|
+
}
|
|
10
|
+
const V = (e, d, p, f) => {
|
|
11
|
+
for (const l of d) {
|
|
12
|
+
const x = j(f, l);
|
|
13
|
+
x != null && M(e, l, "add", String(x), f.id);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
function C(e, d, p) {
|
|
17
|
+
for (const f of d) {
|
|
18
|
+
const l = j(p, f);
|
|
19
|
+
l != null && M(e, f, "remove", String(l), p.id);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function U(e, d) {
|
|
23
|
+
const p = e.joinPath(d, "items"), f = e.joinPath(d, "index"), l = async (t) => e.fileExists(t).catch(() => !1), x = async (t, n) => e.removeEntry(t, n).catch(() => {
|
|
24
|
+
}), I = async (t) => e.joinPath(await p, await e.fileNameForId(t)), g = async (t) => e.joinPath(await f, await e.fileNameForIndexKey(t)), R = async (t, n) => {
|
|
25
|
+
const a = await e.fileNameForIndexKey(n);
|
|
26
|
+
return e.joinPath(t, a);
|
|
27
|
+
}, S = async (t) => {
|
|
28
|
+
if (!await l(t))
|
|
9
29
|
return [];
|
|
10
|
-
const
|
|
11
|
-
return Array.isArray(
|
|
30
|
+
const a = await e.readObject(t).catch(() => []);
|
|
31
|
+
return Array.isArray(a) ? a : [];
|
|
12
32
|
}, K = (t) => {
|
|
13
33
|
const n = /* @__PURE__ */ new Map();
|
|
14
34
|
if (!Array.isArray(t))
|
|
15
35
|
return n;
|
|
16
|
-
for (const
|
|
17
|
-
for (const [
|
|
18
|
-
n.set(
|
|
36
|
+
for (const a of t)
|
|
37
|
+
for (const [s, i] of Object.entries(a))
|
|
38
|
+
n.set(s, new Set(i));
|
|
19
39
|
return n;
|
|
20
|
-
},
|
|
40
|
+
}, A = async (t, n) => {
|
|
21
41
|
if (n.size === 0) {
|
|
22
|
-
await
|
|
42
|
+
await l(t) && await x(t);
|
|
23
43
|
return;
|
|
24
44
|
}
|
|
25
|
-
const
|
|
26
|
-
n.forEach((
|
|
27
|
-
|
|
28
|
-
}), await
|
|
29
|
-
},
|
|
30
|
-
const n = await
|
|
45
|
+
const a = [];
|
|
46
|
+
n.forEach((s, i) => {
|
|
47
|
+
a.push({ [i]: [...s] });
|
|
48
|
+
}), await e.writeIndexObject(t, a);
|
|
49
|
+
}, b = async (t) => {
|
|
50
|
+
const n = await e.readIndexObject(t).catch(() => null);
|
|
31
51
|
return K(n);
|
|
32
|
-
},
|
|
33
|
-
const t = await
|
|
34
|
-
if (!await
|
|
52
|
+
}, O = async () => {
|
|
53
|
+
const t = await p;
|
|
54
|
+
if (!await l(t))
|
|
35
55
|
return [];
|
|
36
|
-
const
|
|
37
|
-
return await Promise.all(
|
|
38
|
-
const
|
|
39
|
-
Array.isArray(o) &&
|
|
40
|
-
})),
|
|
41
|
-
}, z = async (t, n =
|
|
42
|
-
const
|
|
43
|
-
await
|
|
56
|
+
const a = await e.listFilesRecursive(t), s = [];
|
|
57
|
+
return await Promise.all(a.map(async (i) => {
|
|
58
|
+
const w = await e.joinPath(t, i), o = await e.readObject(w).catch(() => null);
|
|
59
|
+
Array.isArray(o) && s.push(...o);
|
|
60
|
+
})), s;
|
|
61
|
+
}, z = async (t, n = O()) => {
|
|
62
|
+
const a = await n, s = await g(t);
|
|
63
|
+
await x(s, { recursive: !0 }), await e.ensureDir(s);
|
|
44
64
|
const i = /* @__PURE__ */ new Map();
|
|
45
|
-
for (const o of
|
|
46
|
-
const
|
|
47
|
-
if (
|
|
65
|
+
for (const o of a) {
|
|
66
|
+
const c = j(o, t);
|
|
67
|
+
if (c == null)
|
|
48
68
|
continue;
|
|
49
|
-
const
|
|
50
|
-
i.has(
|
|
69
|
+
const r = String(c);
|
|
70
|
+
i.has(r) || i.set(r, /* @__PURE__ */ new Set()), i.get(r)?.add(o.id);
|
|
51
71
|
}
|
|
52
|
-
const
|
|
53
|
-
for (const [o,
|
|
54
|
-
const
|
|
55
|
-
|
|
72
|
+
const w = {};
|
|
73
|
+
for (const [o, c] of i) {
|
|
74
|
+
const r = await e.fileNameForIndexKey(o);
|
|
75
|
+
w[r] || (w[r] = []), w[r].push({ [o]: [...c] });
|
|
56
76
|
}
|
|
57
|
-
await Promise.all(Object.entries(
|
|
58
|
-
const
|
|
59
|
-
await
|
|
77
|
+
await Promise.all(Object.entries(w).map(async ([o, c]) => {
|
|
78
|
+
const r = await e.joinPath(s, o);
|
|
79
|
+
await e.writeIndexObject(r, c);
|
|
60
80
|
}));
|
|
61
81
|
}, B = async (t) => {
|
|
62
|
-
const n = await
|
|
63
|
-
if (!await
|
|
82
|
+
const n = await g(t);
|
|
83
|
+
if (!await l(n))
|
|
64
84
|
throw new Error(`Index on field "${t}" does not exist`);
|
|
65
|
-
const
|
|
66
|
-
return await Promise.all(
|
|
67
|
-
const o = await
|
|
68
|
-
if (Array.isArray(
|
|
69
|
-
for (const
|
|
70
|
-
for (const [
|
|
71
|
-
i.has(
|
|
72
|
-
const
|
|
73
|
-
for (const
|
|
74
|
-
|
|
85
|
+
const s = await e.listFilesRecursive(n), i = /* @__PURE__ */ new Map();
|
|
86
|
+
return await Promise.all(s.map(async (w) => {
|
|
87
|
+
const o = await e.joinPath(n, w), c = await e.readIndexObject(o).catch(() => null);
|
|
88
|
+
if (Array.isArray(c))
|
|
89
|
+
for (const r of c)
|
|
90
|
+
for (const [h, m] of Object.entries(r)) {
|
|
91
|
+
i.has(h) || i.set(h, /* @__PURE__ */ new Set());
|
|
92
|
+
const P = i.get(h);
|
|
93
|
+
for (const y of m)
|
|
94
|
+
P?.add(y);
|
|
75
95
|
}
|
|
76
96
|
})), i;
|
|
77
|
-
},
|
|
78
|
-
t.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return;
|
|
82
|
-
const o = e === "add" ? c.adds : c.removes;
|
|
83
|
-
o.has(a) || o.set(a, /* @__PURE__ */ new Set()), o.get(a)?.add(i);
|
|
84
|
-
}, T = (t, n, e) => {
|
|
85
|
-
for (const a of I) {
|
|
86
|
-
const i = P(e, a);
|
|
87
|
-
i != null && O(t, a, "add", String(i), e.id);
|
|
88
|
-
}
|
|
89
|
-
}, $ = (t, n) => {
|
|
90
|
-
for (const e of I) {
|
|
91
|
-
const a = P(n, e);
|
|
92
|
-
a != null && O(t, e, "remove", String(a), n.id);
|
|
93
|
-
}
|
|
94
|
-
}, k = async (t) => {
|
|
95
|
-
await Promise.all([...t.entries()].map(async ([n, e]) => {
|
|
96
|
-
const a = await h(n);
|
|
97
|
-
if (!await u(a))
|
|
97
|
+
}, F = [], k = async (t) => {
|
|
98
|
+
await Promise.all([...t.entries()].map(async ([n, a]) => {
|
|
99
|
+
const s = await g(n);
|
|
100
|
+
if (!await l(s))
|
|
98
101
|
return;
|
|
99
|
-
await
|
|
100
|
-
const
|
|
101
|
-
...
|
|
102
|
-
...
|
|
102
|
+
await e.ensureDir(s);
|
|
103
|
+
const w = /* @__PURE__ */ new Set([
|
|
104
|
+
...a.adds.keys(),
|
|
105
|
+
...a.removes.keys()
|
|
103
106
|
]), o = /* @__PURE__ */ new Map();
|
|
104
|
-
await Promise.all([...
|
|
105
|
-
o.set(
|
|
107
|
+
await Promise.all([...w].map(async (r) => {
|
|
108
|
+
o.set(r, await e.fileNameForIndexKey(r));
|
|
106
109
|
}));
|
|
107
|
-
const
|
|
108
|
-
await Promise.all([...
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
if (o.get(
|
|
110
|
+
const c = new Set(o.values());
|
|
111
|
+
await Promise.all([...c].map(async (r) => {
|
|
112
|
+
const h = await e.joinPath(s, r), m = await b(h);
|
|
113
|
+
a.removes.forEach((P, y) => {
|
|
114
|
+
if (o.get(y) !== r)
|
|
112
115
|
return;
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
}),
|
|
116
|
-
if (o.get(
|
|
116
|
+
const u = m.get(y);
|
|
117
|
+
u && (P.forEach((E) => u.delete(E)), u.size === 0 && m.delete(y));
|
|
118
|
+
}), a.adds.forEach((P, y) => {
|
|
119
|
+
if (o.get(y) !== r)
|
|
117
120
|
return;
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
}), await
|
|
121
|
+
const u = m.get(y) ?? /* @__PURE__ */ new Set();
|
|
122
|
+
P.forEach((E) => u.add(E)), m.set(y, u);
|
|
123
|
+
}), await A(h, m);
|
|
121
124
|
}));
|
|
122
125
|
}));
|
|
123
|
-
},
|
|
124
|
-
const
|
|
125
|
-
if (!await
|
|
126
|
+
}, T = async (t, n) => {
|
|
127
|
+
const a = await g(t);
|
|
128
|
+
if (!await l(a))
|
|
126
129
|
return;
|
|
127
|
-
const i = await
|
|
128
|
-
await Promise.all(i.map(async (
|
|
129
|
-
const o = await
|
|
130
|
-
if (!Array.isArray(
|
|
130
|
+
const i = await e.listFilesRecursive(a);
|
|
131
|
+
await Promise.all(i.map(async (w) => {
|
|
132
|
+
const o = await e.joinPath(a, w), c = await e.readIndexObject(o).catch(() => null);
|
|
133
|
+
if (!Array.isArray(c))
|
|
131
134
|
return;
|
|
132
|
-
let
|
|
133
|
-
const
|
|
134
|
-
for (const
|
|
135
|
-
for (const [
|
|
136
|
-
const
|
|
137
|
-
|
|
135
|
+
let r = !1;
|
|
136
|
+
const h = /* @__PURE__ */ new Map();
|
|
137
|
+
for (const m of c)
|
|
138
|
+
for (const [P, y] of Object.entries(m)) {
|
|
139
|
+
const u = new Set(y), E = u.size;
|
|
140
|
+
u.delete(n), u.size !== E && (r = !0), u.size > 0 && h.set(P, u);
|
|
138
141
|
}
|
|
139
|
-
|
|
142
|
+
r && await A(o, h);
|
|
140
143
|
}));
|
|
141
|
-
},
|
|
144
|
+
}, $ = async (t, n, a) => {
|
|
142
145
|
if (n == null)
|
|
143
146
|
return;
|
|
144
|
-
const
|
|
145
|
-
if (!await
|
|
147
|
+
const s = String(n), i = await g(t);
|
|
148
|
+
if (!await l(i))
|
|
146
149
|
return;
|
|
147
|
-
await
|
|
148
|
-
const o = await R(i,
|
|
149
|
-
|
|
150
|
-
},
|
|
151
|
-
await Promise.all(
|
|
152
|
-
await
|
|
153
|
-
const
|
|
154
|
-
await
|
|
150
|
+
await e.ensureDir(i);
|
|
151
|
+
const o = await R(i, s), c = await b(o), r = c.get(s) ?? /* @__PURE__ */ new Set();
|
|
152
|
+
r.add(a), c.set(s, r), await A(o, c);
|
|
153
|
+
}, L = async (t, n) => {
|
|
154
|
+
await Promise.all(F.map(async (a) => {
|
|
155
|
+
await T(a, t.id);
|
|
156
|
+
const s = j(n, a);
|
|
157
|
+
await $(a, s, n.id);
|
|
155
158
|
}));
|
|
156
159
|
}, D = async (t, n) => {
|
|
157
|
-
const
|
|
158
|
-
await Promise.all(t.map(async (
|
|
159
|
-
const i = await
|
|
160
|
+
const a = /* @__PURE__ */ new Map();
|
|
161
|
+
await Promise.all(t.map(async (s) => {
|
|
162
|
+
const i = await I(s.id), w = await S(i), o = w.findIndex((c) => c.id === s.id);
|
|
160
163
|
if (n === "insert") {
|
|
161
164
|
if (o !== -1)
|
|
162
|
-
throw new Error(`Item with id "${String(
|
|
163
|
-
|
|
165
|
+
throw new Error(`Item with id "${String(s.id)}" already exists`);
|
|
166
|
+
V(a, F, void 0, s), await e.writeObject(i, [...w, s]);
|
|
164
167
|
} else {
|
|
165
168
|
if (o === -1)
|
|
166
|
-
throw new Error(`Item with id "${String(
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
+
throw new Error(`Item with id "${String(s.id)}" does not exist`);
|
|
170
|
+
const c = [...w], r = c[o];
|
|
171
|
+
c[o] = s, await e.writeObject(i, c), await L(r, s);
|
|
169
172
|
}
|
|
170
|
-
})),
|
|
173
|
+
})), a.size > 0 && await k(a);
|
|
171
174
|
};
|
|
172
|
-
return
|
|
175
|
+
return N({
|
|
173
176
|
setup: async () => {
|
|
174
|
-
await
|
|
177
|
+
await e.ensureDir(d);
|
|
175
178
|
},
|
|
176
179
|
teardown: async () => {
|
|
177
180
|
},
|
|
178
|
-
readAll:
|
|
179
|
-
readIds: async (t) => (await Promise.all(t.map(async (
|
|
180
|
-
const
|
|
181
|
-
return Array.isArray(i) ? i.find((
|
|
182
|
-
}))).filter((
|
|
181
|
+
readAll: O,
|
|
182
|
+
readIds: async (t) => (await Promise.all(t.map(async (a) => {
|
|
183
|
+
const s = await I(a), i = await e.readObject(s).catch(() => []) ?? [];
|
|
184
|
+
return Array.isArray(i) ? i.find((w) => w.id === a) ?? null : null;
|
|
185
|
+
}))).filter((a) => a != null),
|
|
183
186
|
createIndex: async (t) => {
|
|
184
187
|
if (t === "id")
|
|
185
188
|
throw new Error("Cannot create index on id field");
|
|
186
|
-
|
|
189
|
+
F.push(t), await z(t);
|
|
187
190
|
},
|
|
188
191
|
dropIndex: async (t) => {
|
|
189
|
-
const n = await
|
|
190
|
-
if (!await
|
|
192
|
+
const n = await g(t);
|
|
193
|
+
if (!await l(n))
|
|
191
194
|
throw new Error(`Index on field "${t}" does not exist`);
|
|
192
|
-
await
|
|
195
|
+
await e.removeEntry(n, { recursive: !0 });
|
|
193
196
|
},
|
|
194
197
|
readIndex: B,
|
|
195
198
|
insert: async (t) => {
|
|
@@ -200,18 +203,18 @@ function U(s, m) {
|
|
|
200
203
|
},
|
|
201
204
|
remove: async (t) => {
|
|
202
205
|
const n = /* @__PURE__ */ new Map();
|
|
203
|
-
await Promise.all(t.map(async (
|
|
204
|
-
const
|
|
205
|
-
if (
|
|
206
|
-
throw new Error(`Item with id "${String(
|
|
207
|
-
|
|
206
|
+
await Promise.all(t.map(async (a) => {
|
|
207
|
+
const s = await I(a.id), i = await S(s), w = i.findIndex((c) => c.id === a.id);
|
|
208
|
+
if (w === -1)
|
|
209
|
+
throw new Error(`Item with id "${String(a.id)}" does not exist`);
|
|
210
|
+
C(n, F, i[w]);
|
|
208
211
|
const o = [...i];
|
|
209
|
-
o.splice(
|
|
210
|
-
}) :
|
|
212
|
+
o.splice(w, 1), await (o.length === 0 ? e.removeEntry(s).catch(() => {
|
|
213
|
+
}) : e.writeObject(s, o));
|
|
211
214
|
})), await k(n);
|
|
212
215
|
},
|
|
213
216
|
removeAll: async () => {
|
|
214
|
-
await
|
|
217
|
+
await l(d) && await e.removeEntry(d, { recursive: !0 });
|
|
215
218
|
}
|
|
216
219
|
});
|
|
217
220
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import { createStorageAdapter, get } from '@signaldb/core';\n/**\n * Creates a storage adapter for managing a SignalDB collection using a generic filesystem-like driver.\n * Data is sharded into subdirectories based on item identifiers, and indices are maintained as files.\n * @param driver - The driver that handles low-level file operations.\n * @param folderName - The root folder path for storing the collection data.\n * @returns A SignalDB storage adapter for managing data in a filesystem-like storage.\n */\nexport default function createGenericFSAdapter(driver, folderName) {\n const itemsDirectoryPathPromise = driver.joinPath(folderName, 'items');\n const indexRootPathPromise = driver.joinPath(folderName, 'index');\n const safeFileExists = async (path) => driver.fileExists(path).catch(() => false);\n const safeRemoveEntry = async (path, options) => driver.removeEntry(path, options).catch(() => { });\n const toItemsFilePath = async (identifier) => driver.joinPath(await itemsDirectoryPathPromise, await driver.fileNameForId(identifier));\n const toIndexPathForField = async (fieldPath) => driver.joinPath(await indexRootPathPromise, await driver.fileNameForIndexKey(fieldPath));\n const toIndexBucketFilePath = async (indexPath, rawKey) => {\n const bucketFileName = await driver.fileNameForIndexKey(rawKey);\n return driver.joinPath(indexPath, bucketFileName);\n };\n const readItemsArrayOrEmpty = async (filePath) => {\n const exists = await safeFileExists(filePath);\n if (!exists)\n return [];\n const data = await driver.readObject(filePath).catch(() => []);\n return Array.isArray(data) ? data : [];\n };\n const loadBucketIndexFromData = (data) => {\n const bucketIndex = new Map();\n if (!Array.isArray(data))\n return bucketIndex;\n for (const entry of data) {\n for (const [rawKey, identifierList] of Object.entries(entry)) {\n bucketIndex.set(rawKey, new Set(identifierList));\n }\n }\n return bucketIndex;\n };\n const writeBucketIndex = async (filePath, bucketIndex) => {\n if (bucketIndex.size === 0) {\n const exists = await safeFileExists(filePath);\n if (exists)\n await safeRemoveEntry(filePath);\n return;\n }\n const output = [];\n bucketIndex.forEach((identifierSet, rawKey) => {\n output.push({ [rawKey]: [...identifierSet] });\n });\n await driver.writeIndexObject(filePath, output);\n };\n const readBucketIndex = async (filePath) => {\n const data = await driver.readIndexObject(filePath).catch(() => null);\n return loadBucketIndexFromData(data);\n };\n const readAll = async () => {\n const itemsDirectoryPath = await itemsDirectoryPathPromise;\n const directoryExists = await safeFileExists(itemsDirectoryPath);\n if (!directoryExists)\n return [];\n const relativeFiles = await driver.listFilesRecursive(itemsDirectoryPath);\n const aggregatedItems = [];\n await Promise.all(relativeFiles.map(async (relativePath) => {\n const fullPath = await driver.joinPath(itemsDirectoryPath, relativePath);\n const itemsInFile = await driver.readObject(fullPath).catch(() => null);\n if (Array.isArray(itemsInFile))\n aggregatedItems.push(...itemsInFile);\n }));\n return aggregatedItems;\n };\n const ensureIndex = async (fieldPath, itemsPromise = readAll()) => {\n const allItems = await itemsPromise;\n const indexPath = await toIndexPathForField(fieldPath);\n await safeRemoveEntry(indexPath, { recursive: true });\n await driver.ensureDir(indexPath);\n // Build value -> Set<identifier>\n const indexMap = new Map();\n for (const item of allItems) {\n const fieldValue = get(item, fieldPath);\n if (fieldValue == null)\n continue;\n const keyString = String(fieldValue);\n if (!indexMap.has(keyString))\n indexMap.set(keyString, new Set());\n indexMap.get(keyString)?.add(item.id);\n }\n // Group entries by bucket file name, then persist each bucket\n const buckets = {};\n for (const [rawKeyString, identifierSet] of indexMap) {\n const bucketFileName = await driver.fileNameForIndexKey(rawKeyString);\n if (!buckets[bucketFileName])\n buckets[bucketFileName] = [];\n buckets[bucketFileName].push({ [rawKeyString]: [...identifierSet] });\n }\n await Promise.all(Object.entries(buckets).map(async ([bucketFileName, records]) => {\n const filePath = await driver.joinPath(indexPath, bucketFileName);\n await driver.writeIndexObject(filePath, records);\n }));\n };\n const readIndex = async (fieldPath) => {\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n throw new Error(`Index on field \"${fieldPath}\" does not exist`);\n const relativeFiles = await driver.listFilesRecursive(indexPath);\n const resultIndex = new Map();\n await Promise.all(relativeFiles.map(async (relativePath) => {\n const fullPath = await driver.joinPath(indexPath, relativePath);\n const maps = await driver.readIndexObject(fullPath).catch(() => null);\n if (!Array.isArray(maps))\n return;\n for (const entry of maps) {\n for (const [rawKey, identifierList] of Object.entries(entry)) {\n if (!resultIndex.has(rawKey))\n resultIndex.set(rawKey, new Set());\n const target = resultIndex.get(rawKey);\n for (const identifier of identifierList)\n target?.add(identifier);\n }\n }\n }));\n return resultIndex;\n };\n // Track which field paths should be kept up-to-date incrementally.\n const indicesToMaintain = [];\n const addToDelta = (deltas, fieldPath, changeKind, rawKey, identifier) => {\n if (!deltas.has(fieldPath))\n deltas.set(fieldPath, { adds: new Map(), removes: new Map() });\n const delta = deltas.get(fieldPath);\n if (!delta)\n return;\n const target = changeKind === 'add' ? delta.adds : delta.removes;\n if (!target.has(rawKey))\n target.set(rawKey, new Set());\n target.get(rawKey)?.add(identifier);\n };\n const addDeltaForChange = (deltas, fieldPath, oldValue, newValue, identifier) => {\n const oldKey = oldValue == null ? undefined : String(oldValue);\n const newKey = newValue == null ? undefined : String(newValue);\n if (oldKey === newKey)\n return;\n if (oldKey != null)\n addToDelta(deltas, fieldPath, 'remove', oldKey, identifier);\n if (newKey != null)\n addToDelta(deltas, fieldPath, 'add', newKey, identifier);\n };\n const accumulateUpsertDelta = (deltas, existingItem, nextItem) => {\n if (existingItem) {\n for (const fieldPath of indicesToMaintain) {\n addDeltaForChange(deltas, fieldPath, get(existingItem, fieldPath), get(nextItem, fieldPath), nextItem.id);\n }\n }\n else {\n for (const fieldPath of indicesToMaintain) {\n const value = get(nextItem, fieldPath);\n if (value == null)\n continue;\n addToDelta(deltas, fieldPath, 'add', String(value), nextItem.id);\n }\n }\n };\n const accumulateRemoveDelta = (deltas, existingItem) => {\n for (const fieldPath of indicesToMaintain) {\n const value = get(existingItem, fieldPath);\n if (value == null)\n continue;\n addToDelta(deltas, fieldPath, 'remove', String(value), existingItem.id);\n }\n };\n const applyIndexDeltas = async (deltas) => {\n // For each indexed field with changes, touch only the affected bucket files\n await Promise.all([...deltas.entries()].map(async ([fieldPath, delta]) => {\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n return; // Only update indices that exist\n await driver.ensureDir(indexPath);\n // Compute impacted bucket filenames\n const touchedRawKeys = new Set([\n ...delta.adds.keys(),\n ...delta.removes.keys(),\n ]);\n const rawKeyToBucketFileName = new Map();\n await Promise.all([...touchedRawKeys].map(async (rawKey) => {\n rawKeyToBucketFileName.set(rawKey, await driver.fileNameForIndexKey(rawKey));\n }));\n const touchedBucketFileNames = new Set(rawKeyToBucketFileName.values());\n await Promise.all([...touchedBucketFileNames].map(async (bucketFileName) => {\n const filePath = await driver.joinPath(indexPath, bucketFileName);\n const bucketIndex = await readBucketIndex(filePath);\n // Apply removals for keys that map to this bucket\n delta.removes.forEach((identifierSet, rawKey) => {\n if (rawKeyToBucketFileName.get(rawKey) !== bucketFileName)\n return;\n const setForKey = bucketIndex.get(rawKey);\n if (!setForKey)\n return;\n identifierSet.forEach(identifier => setForKey.delete(identifier));\n if (setForKey.size === 0)\n bucketIndex.delete(rawKey);\n });\n // Apply additions\n delta.adds.forEach((identifierSet, rawKey) => {\n if (rawKeyToBucketFileName.get(rawKey) !== bucketFileName)\n return;\n const setForKey = bucketIndex.get(rawKey) ?? new Set();\n identifierSet.forEach(identifier => setForKey.add(identifier));\n bucketIndex.set(rawKey, setForKey);\n });\n await writeBucketIndex(filePath, bucketIndex);\n }));\n }));\n };\n const removeIdFromIndex = async (fieldPath, identifier) => {\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n return;\n const relativeFiles = await driver.listFilesRecursive(indexPath);\n await Promise.all(relativeFiles.map(async (relativePath) => {\n const filePath = await driver.joinPath(indexPath, relativePath);\n const data = await driver.readIndexObject(filePath).catch(() => null);\n if (!Array.isArray(data))\n return;\n let changed = false;\n const bucketIndex = new Map();\n for (const entry of data) {\n for (const [rawKey, identifierList] of Object.entries(entry)) {\n const set = new Set(identifierList);\n const before = set.size;\n set.delete(identifier);\n if (set.size !== before)\n changed = true;\n if (set.size > 0)\n bucketIndex.set(rawKey, set);\n }\n }\n if (!changed)\n return;\n await writeBucketIndex(filePath, bucketIndex);\n }));\n };\n const addIdToIndex = async (fieldPath, value, identifier) => {\n if (value == null)\n return;\n const rawKey = String(value);\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n return;\n await driver.ensureDir(indexPath);\n const filePath = await toIndexBucketFilePath(indexPath, rawKey);\n const bucketIndex = await readBucketIndex(filePath);\n const setForKey = bucketIndex.get(rawKey) ?? new Set();\n setForKey.add(identifier);\n bucketIndex.set(rawKey, setForKey);\n await writeBucketIndex(filePath, bucketIndex);\n };\n const updateIndexForReplace = async (oldItem, nextItem) => {\n await Promise.all(indicesToMaintain.map(async (fieldPath) => {\n await removeIdFromIndex(fieldPath, oldItem.id);\n const newValue = get(nextItem, fieldPath);\n await addIdToIndex(fieldPath, newValue, nextItem.id);\n }));\n };\n const upsertItems = async (items, mode) => {\n const deltas = new Map();\n await Promise.all(items.map(async (item) => {\n const filePath = await toItemsFilePath(item.id);\n const existingArray = await readItemsArrayOrEmpty(filePath);\n const indexOfItem = existingArray.findIndex(existing => existing.id === item.id);\n if (mode === 'insert') {\n if (indexOfItem !== -1)\n throw new Error(`Item with id \"${String(item.id)}\" already exists`);\n accumulateUpsertDelta(deltas, undefined, item);\n await driver.writeObject(filePath, [...existingArray, item]);\n }\n else {\n if (indexOfItem === -1)\n throw new Error(`Item with id \"${String(item.id)}\" does not exist`);\n const updatedArray = [...existingArray];\n const oldItem = updatedArray[indexOfItem];\n updatedArray[indexOfItem] = item;\n await driver.writeObject(filePath, updatedArray);\n await updateIndexForReplace(oldItem, item);\n }\n }));\n // Only apply deltas for inserts (replace handled by direct purge+add)\n if (deltas.size > 0) {\n await applyIndexDeltas(deltas);\n }\n };\n return createStorageAdapter({\n setup: async () => {\n await driver.ensureDir(folderName);\n },\n teardown: async () => {\n // no-op\n },\n readAll,\n readIds: async (identifiers) => {\n const results = await Promise.all(identifiers.map(async (identifier) => {\n const filePath = await toItemsFilePath(identifier);\n const itemsInFile = await driver.readObject(filePath).catch(() => []) ?? [];\n if (!Array.isArray(itemsInFile))\n return null;\n return itemsInFile.find(item => item.id === identifier) ?? null;\n }));\n return results.filter((value) => value != null);\n },\n createIndex: async (fieldPath) => {\n if (fieldPath === 'id')\n throw new Error('Cannot create index on id field');\n indicesToMaintain.push(fieldPath);\n await ensureIndex(fieldPath);\n },\n dropIndex: async (fieldPath) => {\n const pathToDrop = await toIndexPathForField(fieldPath);\n const exists = await safeFileExists(pathToDrop);\n if (!exists)\n throw new Error(`Index on field \"${fieldPath}\" does not exist`);\n await driver.removeEntry(pathToDrop, { recursive: true });\n },\n readIndex,\n insert: async (itemsToInsert) => {\n await upsertItems(itemsToInsert, 'insert');\n },\n replace: async (itemsToReplace) => {\n await upsertItems(itemsToReplace, 'replace');\n },\n remove: async (itemsToRemove) => {\n const deltas = new Map();\n await Promise.all(itemsToRemove.map(async (item) => {\n const filePath = await toItemsFilePath(item.id);\n const existingArray = await readItemsArrayOrEmpty(filePath);\n const indexOfItem = existingArray.findIndex(existing => existing.id === item.id);\n if (indexOfItem === -1)\n throw new Error(`Item with id \"${String(item.id)}\" does not exist`);\n accumulateRemoveDelta(deltas, existingArray[indexOfItem]);\n const updatedArray = [...existingArray];\n updatedArray.splice(indexOfItem, 1);\n await (updatedArray.length === 0\n ? driver.removeEntry(filePath).catch(() => { })\n : driver.writeObject(filePath, updatedArray));\n }));\n await applyIndexDeltas(deltas);\n },\n removeAll: async () => {\n const exists = await safeFileExists(folderName);\n if (!exists)\n return;\n await driver.removeEntry(folderName, { recursive: true });\n },\n });\n}\n"],"names":["createGenericFSAdapter","driver","folderName","itemsDirectoryPathPromise","indexRootPathPromise","safeFileExists","path","safeRemoveEntry","options","toItemsFilePath","identifier","toIndexPathForField","fieldPath","toIndexBucketFilePath","indexPath","rawKey","bucketFileName","readItemsArrayOrEmpty","filePath","data","loadBucketIndexFromData","bucketIndex","entry","identifierList","writeBucketIndex","output","identifierSet","readBucketIndex","readAll","itemsDirectoryPath","relativeFiles","aggregatedItems","relativePath","fullPath","itemsInFile","ensureIndex","itemsPromise","allItems","indexMap","item","fieldValue","get","keyString","buckets","rawKeyString","records","readIndex","resultIndex","maps","target","indicesToMaintain","addToDelta","deltas","changeKind","delta","accumulateUpsertDelta","existingItem","nextItem","value","accumulateRemoveDelta","applyIndexDeltas","touchedRawKeys","rawKeyToBucketFileName","touchedBucketFileNames","setForKey","removeIdFromIndex","changed","set","before","addIdToIndex","updateIndexForReplace","oldItem","newValue","upsertItems","items","mode","existingArray","indexOfItem","existing","updatedArray","createStorageAdapter","identifiers","pathToDrop","itemsToInsert","itemsToReplace","itemsToRemove"],"mappings":";AAQA,SAAwBA,EAAuBC,GAAQC,GAAY;AAC/D,QAAMC,IAA4BF,EAAO,SAASC,GAAY,OAAO,GAC/DE,IAAuBH,EAAO,SAASC,GAAY,OAAO,GAC1DG,IAAiB,OAAOC,MAASL,EAAO,WAAWK,CAAI,EAAE,MAAM,MAAM,EAAK,GAC1EC,IAAkB,OAAOD,GAAME,MAAYP,EAAO,YAAYK,GAAME,CAAO,EAAE,MAAM,MAAM;AAAA,EAAE,CAAC,GAC5FC,IAAkB,OAAOC,MAAeT,EAAO,SAAS,MAAME,GAA2B,MAAMF,EAAO,cAAcS,CAAU,CAAC,GAC/HC,IAAsB,OAAOC,MAAcX,EAAO,SAAS,MAAMG,GAAsB,MAAMH,EAAO,oBAAoBW,CAAS,CAAC,GAClIC,IAAwB,OAAOC,GAAWC,MAAW;AACvD,UAAMC,IAAiB,MAAMf,EAAO,oBAAoBc,CAAM;AAC9D,WAAOd,EAAO,SAASa,GAAWE,CAAc;AAAA,EACpD,GACMC,IAAwB,OAAOC,MAAa;AAE9C,QAAI,CADW,MAAMb,EAAea,CAAQ;AAExC,aAAO,CAAA;AACX,UAAMC,IAAO,MAAMlB,EAAO,WAAWiB,CAAQ,EAAE,MAAM,MAAM,EAAE;AAC7D,WAAO,MAAM,QAAQC,CAAI,IAAIA,IAAO,CAAA;AAAA,EACxC,GACMC,IAA0B,CAACD,MAAS;AACtC,UAAME,wBAAkB,IAAA;AACxB,QAAI,CAAC,MAAM,QAAQF,CAAI;AACnB,aAAOE;AACX,eAAWC,KAASH;AAChB,iBAAW,CAACJ,GAAQQ,CAAc,KAAK,OAAO,QAAQD,CAAK;AACvD,QAAAD,EAAY,IAAIN,GAAQ,IAAI,IAAIQ,CAAc,CAAC;AAGvD,WAAOF;AAAA,EACX,GACMG,IAAmB,OAAON,GAAUG,MAAgB;AACtD,QAAIA,EAAY,SAAS,GAAG;AAExB,MADe,MAAMhB,EAAea,CAAQ,KAExC,MAAMX,EAAgBW,CAAQ;AAClC;AAAA,IACJ;AACA,UAAMO,IAAS,CAAA;AACf,IAAAJ,EAAY,QAAQ,CAACK,GAAeX,MAAW;AAC3C,MAAAU,EAAO,KAAK,EAAE,CAACV,CAAM,GAAG,CAAC,GAAGW,CAAa,GAAG;AAAA,IAChD,CAAC,GACD,MAAMzB,EAAO,iBAAiBiB,GAAUO,CAAM;AAAA,EAClD,GACME,IAAkB,OAAOT,MAAa;AACxC,UAAMC,IAAO,MAAMlB,EAAO,gBAAgBiB,CAAQ,EAAE,MAAM,MAAM,IAAI;AACpE,WAAOE,EAAwBD,CAAI;AAAA,EACvC,GACMS,IAAU,YAAY;AACxB,UAAMC,IAAqB,MAAM1B;AAEjC,QAAI,CADoB,MAAME,EAAewB,CAAkB;AAE3D,aAAO,CAAA;AACX,UAAMC,IAAgB,MAAM7B,EAAO,mBAAmB4B,CAAkB,GAClEE,IAAkB,CAAA;AACxB,iBAAM,QAAQ,IAAID,EAAc,IAAI,OAAOE,MAAiB;AACxD,YAAMC,IAAW,MAAMhC,EAAO,SAAS4B,GAAoBG,CAAY,GACjEE,IAAc,MAAMjC,EAAO,WAAWgC,CAAQ,EAAE,MAAM,MAAM,IAAI;AACtE,MAAI,MAAM,QAAQC,CAAW,KACzBH,EAAgB,KAAK,GAAGG,CAAW;AAAA,IAC3C,CAAC,CAAC,GACKH;AAAA,EACX,GACMI,IAAc,OAAOvB,GAAWwB,IAAeR,QAAc;AAC/D,UAAMS,IAAW,MAAMD,GACjBtB,IAAY,MAAMH,EAAoBC,CAAS;AACrD,UAAML,EAAgBO,GAAW,EAAE,WAAW,IAAM,GACpD,MAAMb,EAAO,UAAUa,CAAS;AAEhC,UAAMwB,wBAAe,IAAA;AACrB,eAAWC,KAAQF,GAAU;AACzB,YAAMG,IAAaC,EAAIF,GAAM3B,CAAS;AACtC,UAAI4B,KAAc;AACd;AACJ,YAAME,IAAY,OAAOF,CAAU;AACnC,MAAKF,EAAS,IAAII,CAAS,KACvBJ,EAAS,IAAII,GAAW,oBAAI,IAAA,CAAK,GACrCJ,EAAS,IAAII,CAAS,GAAG,IAAIH,EAAK,EAAE;AAAA,IACxC;AAEA,UAAMI,IAAU,CAAA;AAChB,eAAW,CAACC,GAAclB,CAAa,KAAKY,GAAU;AAClD,YAAMtB,IAAiB,MAAMf,EAAO,oBAAoB2C,CAAY;AACpE,MAAKD,EAAQ3B,CAAc,MACvB2B,EAAQ3B,CAAc,IAAI,CAAA,IAC9B2B,EAAQ3B,CAAc,EAAE,KAAK,EAAE,CAAC4B,CAAY,GAAG,CAAC,GAAGlB,CAAa,GAAG;AAAA,IACvE;AACA,UAAM,QAAQ,IAAI,OAAO,QAAQiB,CAAO,EAAE,IAAI,OAAO,CAAC3B,GAAgB6B,CAAO,MAAM;AAC/E,YAAM3B,IAAW,MAAMjB,EAAO,SAASa,GAAWE,CAAc;AAChE,YAAMf,EAAO,iBAAiBiB,GAAU2B,CAAO;AAAA,IACnD,CAAC,CAAC;AAAA,EACN,GACMC,IAAY,OAAOlC,MAAc;AACnC,UAAME,IAAY,MAAMH,EAAoBC,CAAS;AAErD,QAAI,CADgB,MAAMP,EAAeS,CAAS;AAE9C,YAAM,IAAI,MAAM,mBAAmBF,CAAS,kBAAkB;AAClE,UAAMkB,IAAgB,MAAM7B,EAAO,mBAAmBa,CAAS,GACzDiC,wBAAkB,IAAA;AACxB,iBAAM,QAAQ,IAAIjB,EAAc,IAAI,OAAOE,MAAiB;AACxD,YAAMC,IAAW,MAAMhC,EAAO,SAASa,GAAWkB,CAAY,GACxDgB,IAAO,MAAM/C,EAAO,gBAAgBgC,CAAQ,EAAE,MAAM,MAAM,IAAI;AACpE,UAAK,MAAM,QAAQe,CAAI;AAEvB,mBAAW1B,KAAS0B;AAChB,qBAAW,CAACjC,GAAQQ,CAAc,KAAK,OAAO,QAAQD,CAAK,GAAG;AAC1D,YAAKyB,EAAY,IAAIhC,CAAM,KACvBgC,EAAY,IAAIhC,GAAQ,oBAAI,IAAA,CAAK;AACrC,kBAAMkC,IAASF,EAAY,IAAIhC,CAAM;AACrC,uBAAWL,KAAca;AACrB,cAAA0B,GAAQ,IAAIvC,CAAU;AAAA,UAC9B;AAAA,IAER,CAAC,CAAC,GACKqC;AAAA,EACX,GAEMG,IAAoB,CAAA,GACpBC,IAAa,CAACC,GAAQxC,GAAWyC,GAAYtC,GAAQL,MAAe;AACtE,IAAK0C,EAAO,IAAIxC,CAAS,KACrBwC,EAAO,IAAIxC,GAAW,EAAE,MAAM,oBAAI,IAAA,GAAO,SAAS,oBAAI,IAAA,GAAO;AACjE,UAAM0C,IAAQF,EAAO,IAAIxC,CAAS;AAClC,QAAI,CAAC0C;AACD;AACJ,UAAML,IAASI,MAAe,QAAQC,EAAM,OAAOA,EAAM;AACzD,IAAKL,EAAO,IAAIlC,CAAM,KAClBkC,EAAO,IAAIlC,GAAQ,oBAAI,IAAA,CAAK,GAChCkC,EAAO,IAAIlC,CAAM,GAAG,IAAIL,CAAU;AAAA,EACtC,GAWM6C,IAAwB,CAACH,GAAQI,GAAcC,MAAa;AAO1D,eAAW7C,KAAasC,GAAmB;AACvC,YAAMQ,IAAQjB,EAAIgB,GAAU7C,CAAS;AACrC,MAAI8C,KAAS,QAEbP,EAAWC,GAAQxC,GAAW,OAAO,OAAO8C,CAAK,GAAGD,EAAS,EAAE;AAAA,IACnE;AAAA,EAER,GACME,IAAwB,CAACP,GAAQI,MAAiB;AACpD,eAAW5C,KAAasC,GAAmB;AACvC,YAAMQ,IAAQjB,EAAIe,GAAc5C,CAAS;AACzC,MAAI8C,KAAS,QAEbP,EAAWC,GAAQxC,GAAW,UAAU,OAAO8C,CAAK,GAAGF,EAAa,EAAE;AAAA,IAC1E;AAAA,EACJ,GACMI,IAAmB,OAAOR,MAAW;AAEvC,UAAM,QAAQ,IAAI,CAAC,GAAGA,EAAO,SAAS,EAAE,IAAI,OAAO,CAACxC,GAAW0C,CAAK,MAAM;AACtE,YAAMxC,IAAY,MAAMH,EAAoBC,CAAS;AAErD,UAAI,CADgB,MAAMP,EAAeS,CAAS;AAE9C;AACJ,YAAMb,EAAO,UAAUa,CAAS;AAEhC,YAAM+C,wBAAqB,IAAI;AAAA,QAC3B,GAAGP,EAAM,KAAK,KAAA;AAAA,QACd,GAAGA,EAAM,QAAQ,KAAA;AAAA,MAAK,CACzB,GACKQ,wBAA6B,IAAA;AACnC,YAAM,QAAQ,IAAI,CAAC,GAAGD,CAAc,EAAE,IAAI,OAAO9C,MAAW;AACxD,QAAA+C,EAAuB,IAAI/C,GAAQ,MAAMd,EAAO,oBAAoBc,CAAM,CAAC;AAAA,MAC/E,CAAC,CAAC;AACF,YAAMgD,IAAyB,IAAI,IAAID,EAAuB,QAAQ;AACtE,YAAM,QAAQ,IAAI,CAAC,GAAGC,CAAsB,EAAE,IAAI,OAAO/C,MAAmB;AACxE,cAAME,IAAW,MAAMjB,EAAO,SAASa,GAAWE,CAAc,GAC1DK,IAAc,MAAMM,EAAgBT,CAAQ;AAElD,QAAAoC,EAAM,QAAQ,QAAQ,CAAC5B,GAAeX,MAAW;AAC7C,cAAI+C,EAAuB,IAAI/C,CAAM,MAAMC;AACvC;AACJ,gBAAMgD,IAAY3C,EAAY,IAAIN,CAAM;AACxC,UAAKiD,MAELtC,EAAc,QAAQ,CAAAhB,MAAcsD,EAAU,OAAOtD,CAAU,CAAC,GAC5DsD,EAAU,SAAS,KACnB3C,EAAY,OAAON,CAAM;AAAA,QACjC,CAAC,GAEDuC,EAAM,KAAK,QAAQ,CAAC5B,GAAeX,MAAW;AAC1C,cAAI+C,EAAuB,IAAI/C,CAAM,MAAMC;AACvC;AACJ,gBAAMgD,IAAY3C,EAAY,IAAIN,CAAM,yBAAS,IAAA;AACjD,UAAAW,EAAc,QAAQ,CAAAhB,MAAcsD,EAAU,IAAItD,CAAU,CAAC,GAC7DW,EAAY,IAAIN,GAAQiD,CAAS;AAAA,QACrC,CAAC,GACD,MAAMxC,EAAiBN,GAAUG,CAAW;AAAA,MAChD,CAAC,CAAC;AAAA,IACN,CAAC,CAAC;AAAA,EACN,GACM4C,IAAoB,OAAOrD,GAAWF,MAAe;AACvD,UAAMI,IAAY,MAAMH,EAAoBC,CAAS;AAErD,QAAI,CADgB,MAAMP,EAAeS,CAAS;AAE9C;AACJ,UAAMgB,IAAgB,MAAM7B,EAAO,mBAAmBa,CAAS;AAC/D,UAAM,QAAQ,IAAIgB,EAAc,IAAI,OAAOE,MAAiB;AACxD,YAAMd,IAAW,MAAMjB,EAAO,SAASa,GAAWkB,CAAY,GACxDb,IAAO,MAAMlB,EAAO,gBAAgBiB,CAAQ,EAAE,MAAM,MAAM,IAAI;AACpE,UAAI,CAAC,MAAM,QAAQC,CAAI;AACnB;AACJ,UAAI+C,IAAU;AACd,YAAM7C,wBAAkB,IAAA;AACxB,iBAAWC,KAASH;AAChB,mBAAW,CAACJ,GAAQQ,CAAc,KAAK,OAAO,QAAQD,CAAK,GAAG;AAC1D,gBAAM6C,IAAM,IAAI,IAAI5C,CAAc,GAC5B6C,IAASD,EAAI;AACnB,UAAAA,EAAI,OAAOzD,CAAU,GACjByD,EAAI,SAASC,MACbF,IAAU,KACVC,EAAI,OAAO,KACX9C,EAAY,IAAIN,GAAQoD,CAAG;AAAA,QACnC;AAEJ,MAAKD,KAEL,MAAM1C,EAAiBN,GAAUG,CAAW;AAAA,IAChD,CAAC,CAAC;AAAA,EACN,GACMgD,IAAe,OAAOzD,GAAW8C,GAAOhD,MAAe;AACzD,QAAIgD,KAAS;AACT;AACJ,UAAM3C,IAAS,OAAO2C,CAAK,GACrB5C,IAAY,MAAMH,EAAoBC,CAAS;AAErD,QAAI,CADgB,MAAMP,EAAeS,CAAS;AAE9C;AACJ,UAAMb,EAAO,UAAUa,CAAS;AAChC,UAAMI,IAAW,MAAML,EAAsBC,GAAWC,CAAM,GACxDM,IAAc,MAAMM,EAAgBT,CAAQ,GAC5C8C,IAAY3C,EAAY,IAAIN,CAAM,yBAAS,IAAA;AACjD,IAAAiD,EAAU,IAAItD,CAAU,GACxBW,EAAY,IAAIN,GAAQiD,CAAS,GACjC,MAAMxC,EAAiBN,GAAUG,CAAW;AAAA,EAChD,GACMiD,IAAwB,OAAOC,GAASd,MAAa;AACvD,UAAM,QAAQ,IAAIP,EAAkB,IAAI,OAAOtC,MAAc;AACzD,YAAMqD,EAAkBrD,GAAW2D,EAAQ,EAAE;AAC7C,YAAMC,IAAW/B,EAAIgB,GAAU7C,CAAS;AACxC,YAAMyD,EAAazD,GAAW4D,GAAUf,EAAS,EAAE;AAAA,IACvD,CAAC,CAAC;AAAA,EACN,GACMgB,IAAc,OAAOC,GAAOC,MAAS;AACvC,UAAMvB,wBAAa,IAAA;AACnB,UAAM,QAAQ,IAAIsB,EAAM,IAAI,OAAOnC,MAAS;AACxC,YAAMrB,IAAW,MAAMT,EAAgB8B,EAAK,EAAE,GACxCqC,IAAgB,MAAM3D,EAAsBC,CAAQ,GACpD2D,IAAcD,EAAc,UAAU,OAAYE,EAAS,OAAOvC,EAAK,EAAE;AAC/E,UAAIoC,MAAS,UAAU;AACnB,YAAIE,MAAgB;AAChB,gBAAM,IAAI,MAAM,iBAAiB,OAAOtC,EAAK,EAAE,CAAC,kBAAkB;AACtE,QAAAgB,EAAsBH,GAAQ,QAAWb,CAAI,GAC7C,MAAMtC,EAAO,YAAYiB,GAAU,CAAC,GAAG0D,GAAerC,CAAI,CAAC;AAAA,MAC/D,OACK;AACD,YAAIsC,MAAgB;AAChB,gBAAM,IAAI,MAAM,iBAAiB,OAAOtC,EAAK,EAAE,CAAC,kBAAkB;AACtE,cAAMwC,IAAe,CAAC,GAAGH,CAAa,GAChCL,IAAUQ,EAAaF,CAAW;AACxC,QAAAE,EAAaF,CAAW,IAAItC,GAC5B,MAAMtC,EAAO,YAAYiB,GAAU6D,CAAY,GAC/C,MAAMT,EAAsBC,GAAShC,CAAI;AAAA,MAC7C;AAAA,IACJ,CAAC,CAAC,GAEEa,EAAO,OAAO,KACd,MAAMQ,EAAiBR,CAAM;AAAA,EAErC;AACA,SAAO4B,EAAqB;AAAA,IACxB,OAAO,YAAY;AACf,YAAM/E,EAAO,UAAUC,CAAU;AAAA,IACrC;AAAA,IACA,UAAU,YAAY;AAAA,IAEtB;AAAA,IACA,SAAA0B;AAAA,IACA,SAAS,OAAOqD,OACI,MAAM,QAAQ,IAAIA,EAAY,IAAI,OAAOvE,MAAe;AACpE,YAAMQ,IAAW,MAAMT,EAAgBC,CAAU,GAC3CwB,IAAc,MAAMjC,EAAO,WAAWiB,CAAQ,EAAE,MAAM,MAAM,CAAA,CAAE,KAAK,CAAA;AACzE,aAAK,MAAM,QAAQgB,CAAW,IAEvBA,EAAY,KAAK,CAAAK,MAAQA,EAAK,OAAO7B,CAAU,KAAK,OADhD;AAAA,IAEf,CAAC,CAAC,GACa,OAAO,CAACgD,MAAUA,KAAS,IAAI;AAAA,IAElD,aAAa,OAAO9C,MAAc;AAC9B,UAAIA,MAAc;AACd,cAAM,IAAI,MAAM,iCAAiC;AACrD,MAAAsC,EAAkB,KAAKtC,CAAS,GAChC,MAAMuB,EAAYvB,CAAS;AAAA,IAC/B;AAAA,IACA,WAAW,OAAOA,MAAc;AAC5B,YAAMsE,IAAa,MAAMvE,EAAoBC,CAAS;AAEtD,UAAI,CADW,MAAMP,EAAe6E,CAAU;AAE1C,cAAM,IAAI,MAAM,mBAAmBtE,CAAS,kBAAkB;AAClE,YAAMX,EAAO,YAAYiF,GAAY,EAAE,WAAW,IAAM;AAAA,IAC5D;AAAA,IACA,WAAApC;AAAA,IACA,QAAQ,OAAOqC,MAAkB;AAC7B,YAAMV,EAAYU,GAAe,QAAQ;AAAA,IAC7C;AAAA,IACA,SAAS,OAAOC,MAAmB;AAC/B,YAAMX,EAAYW,GAAgB,SAAS;AAAA,IAC/C;AAAA,IACA,QAAQ,OAAOC,MAAkB;AAC7B,YAAMjC,wBAAa,IAAA;AACnB,YAAM,QAAQ,IAAIiC,EAAc,IAAI,OAAO9C,MAAS;AAChD,cAAMrB,IAAW,MAAMT,EAAgB8B,EAAK,EAAE,GACxCqC,IAAgB,MAAM3D,EAAsBC,CAAQ,GACpD2D,IAAcD,EAAc,UAAU,OAAYE,EAAS,OAAOvC,EAAK,EAAE;AAC/E,YAAIsC,MAAgB;AAChB,gBAAM,IAAI,MAAM,iBAAiB,OAAOtC,EAAK,EAAE,CAAC,kBAAkB;AACtE,QAAAoB,EAAsBP,GAAQwB,EAAcC,CAAW,CAAC;AACxD,cAAME,IAAe,CAAC,GAAGH,CAAa;AACtC,QAAAG,EAAa,OAAOF,GAAa,CAAC,GAClC,OAAOE,EAAa,WAAW,IACzB9E,EAAO,YAAYiB,CAAQ,EAAE,MAAM,MAAM;AAAA,QAAE,CAAC,IAC5CjB,EAAO,YAAYiB,GAAU6D,CAAY;AAAA,MACnD,CAAC,CAAC,GACF,MAAMnB,EAAiBR,CAAM;AAAA,IACjC;AAAA,IACA,WAAW,YAAY;AAEnB,MADe,MAAM/C,EAAeH,CAAU,KAG9C,MAAMD,EAAO,YAAYC,GAAY,EAAE,WAAW,IAAM;AAAA,IAC5D;AAAA,EAAA,CACH;AACL;"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/deltaHelpers.ts","../src/index.ts"],"sourcesContent":["import { get } from '@signaldb/core';\n/**\n * Records a single index mutation into the delta map for a given indexed field.\n *\n * The delta map is grouped by `fieldPath`, and then by stringified key (`rawKey`).\n * Each key maps to a set of identifiers to add/remove for that key.\n * @param deltas - Accumulator of per-field index deltas.\n * @param fieldPath - Dot-path of the indexed field (used as the delta bucket key).\n * @param changeKind - Whether this identifier should be added to or removed from the index key.\n * @param rawKey - The stringified index key value.\n * @param identifier - The item identifier to add/remove for `rawKey`.\n */\nexport function addToDelta(deltas, fieldPath, changeKind, rawKey, identifier) {\n if (!deltas.has(fieldPath))\n deltas.set(fieldPath, { adds: new Map(), removes: new Map() });\n const delta = deltas.get(fieldPath);\n if (!delta)\n return;\n const target = changeKind === 'add' ? delta.adds : delta.removes;\n if (!target.has(rawKey))\n target.set(rawKey, new Set());\n target.get(rawKey)?.add(identifier);\n}\n/**\n * Computes the delta for a change in a single indexed field.\n *\n * Values are coerced to string keys (with `null`/`undefined` treated as \"no key\").\n * If the derived keys are equal, no delta is recorded.\n * @param deltas - Accumulator of per-field index deltas.\n * @param fieldPath - Dot-path of the indexed field being tracked.\n * @param oldValue - Previous value of the field.\n * @param newValue - Next value of the field.\n * @param identifier - The item identifier affected by the change.\n */\nexport function addDeltaForChange(deltas, fieldPath, oldValue, newValue, identifier) {\n const oldKey = oldValue == null ? undefined : String(oldValue);\n const newKey = newValue == null ? undefined : String(newValue);\n if (oldKey === newKey)\n return;\n if (oldKey != null)\n addToDelta(deltas, fieldPath, 'remove', oldKey, identifier);\n if (newKey != null)\n addToDelta(deltas, fieldPath, 'add', newKey, identifier);\n}\n/**\n * Accumulates index deltas for an upsert operation.\n *\n * - If `existingItem` is present, compares each maintained index field between the old and new item,\n * recording removes/adds for key changes.\n * - If `existingItem` is absent, treats the operation as an insert and records adds for each\n * maintained index field that has a non-null value.\n * @param deltas - Accumulator of per-field index deltas.\n * @param indicesToMaintain - List of dot-paths for fields that are indexed.\n * @param existingItem - Previous stored item (if any).\n * @param nextItem - Incoming item to upsert.\n */\nexport const accumulateUpsertDelta = (deltas, indicesToMaintain, existingItem, nextItem) => {\n if (existingItem) {\n for (const fieldPath of indicesToMaintain) {\n addDeltaForChange(deltas, fieldPath, get(existingItem, fieldPath), get(nextItem, fieldPath), nextItem.id);\n }\n }\n else {\n for (const fieldPath of indicesToMaintain) {\n const value = get(nextItem, fieldPath);\n if (value == null)\n continue;\n addToDelta(deltas, fieldPath, 'add', String(value), nextItem.id);\n }\n }\n};\n/**\n * Accumulates index deltas for a remove/delete operation.\n *\n * For each maintained index field, records a removal of the item's identifier from the\n * corresponding stringified key (skipping `null`/`undefined` values).\n * @param deltas - Accumulator of per-field index deltas.\n * @param indicesToMaintain - List of dot-paths for fields that are indexed.\n * @param existingItem - The item being removed.\n */\nexport function accumulateRemoveDelta(deltas, indicesToMaintain, existingItem) {\n for (const fieldPath of indicesToMaintain) {\n const value = get(existingItem, fieldPath);\n if (value == null)\n continue;\n addToDelta(deltas, fieldPath, 'remove', String(value), existingItem.id);\n }\n}\n","import { createStorageAdapter, get } from '@signaldb/core';\nimport { accumulateUpsertDelta, accumulateRemoveDelta, } from './deltaHelpers';\n/**\n * Creates a storage adapter for managing a SignalDB collection using a generic filesystem-like driver.\n * Data is sharded into subdirectories based on item identifiers, and indices are maintained as files.\n * @param driver - The driver that handles low-level file operations.\n * @param folderName - The root folder path for storing the collection data.\n * @returns A SignalDB storage adapter for managing data in a filesystem-like storage.\n */\nexport default function createGenericFSAdapter(driver, folderName) {\n const itemsDirectoryPathPromise = driver.joinPath(folderName, 'items');\n const indexRootPathPromise = driver.joinPath(folderName, 'index');\n const safeFileExists = async (path) => driver.fileExists(path).catch(() => false);\n const safeRemoveEntry = async (path, options) => driver.removeEntry(path, options).catch(() => { });\n const toItemsFilePath = async (identifier) => driver.joinPath(await itemsDirectoryPathPromise, await driver.fileNameForId(identifier));\n const toIndexPathForField = async (fieldPath) => driver.joinPath(await indexRootPathPromise, await driver.fileNameForIndexKey(fieldPath));\n const toIndexBucketFilePath = async (indexPath, rawKey) => {\n const bucketFileName = await driver.fileNameForIndexKey(rawKey);\n return driver.joinPath(indexPath, bucketFileName);\n };\n const readItemsArrayOrEmpty = async (filePath) => {\n const exists = await safeFileExists(filePath);\n if (!exists)\n return [];\n const data = await driver.readObject(filePath).catch(() => []);\n return Array.isArray(data) ? data : [];\n };\n const loadBucketIndexFromData = (data) => {\n const bucketIndex = new Map();\n if (!Array.isArray(data))\n return bucketIndex;\n for (const entry of data) {\n for (const [rawKey, identifierList] of Object.entries(entry)) {\n bucketIndex.set(rawKey, new Set(identifierList));\n }\n }\n return bucketIndex;\n };\n const writeBucketIndex = async (filePath, bucketIndex) => {\n if (bucketIndex.size === 0) {\n const exists = await safeFileExists(filePath);\n if (exists)\n await safeRemoveEntry(filePath);\n return;\n }\n const output = [];\n bucketIndex.forEach((identifierSet, rawKey) => {\n output.push({ [rawKey]: [...identifierSet] });\n });\n await driver.writeIndexObject(filePath, output);\n };\n const readBucketIndex = async (filePath) => {\n const data = await driver.readIndexObject(filePath).catch(() => null);\n return loadBucketIndexFromData(data);\n };\n const readAll = async () => {\n const itemsDirectoryPath = await itemsDirectoryPathPromise;\n const directoryExists = await safeFileExists(itemsDirectoryPath);\n if (!directoryExists)\n return [];\n const relativeFiles = await driver.listFilesRecursive(itemsDirectoryPath);\n const aggregatedItems = [];\n await Promise.all(relativeFiles.map(async (relativePath) => {\n const fullPath = await driver.joinPath(itemsDirectoryPath, relativePath);\n const itemsInFile = await driver.readObject(fullPath).catch(() => null);\n if (Array.isArray(itemsInFile))\n aggregatedItems.push(...itemsInFile);\n }));\n return aggregatedItems;\n };\n const ensureIndex = async (fieldPath, itemsPromise = readAll()) => {\n const allItems = await itemsPromise;\n const indexPath = await toIndexPathForField(fieldPath);\n await safeRemoveEntry(indexPath, { recursive: true });\n await driver.ensureDir(indexPath);\n // Build value -> Set<identifier>\n const indexMap = new Map();\n for (const item of allItems) {\n const fieldValue = get(item, fieldPath);\n if (fieldValue == null)\n continue;\n const keyString = String(fieldValue);\n if (!indexMap.has(keyString))\n indexMap.set(keyString, new Set());\n indexMap.get(keyString)?.add(item.id);\n }\n // Group entries by bucket file name, then persist each bucket\n const buckets = {};\n for (const [rawKeyString, identifierSet] of indexMap) {\n const bucketFileName = await driver.fileNameForIndexKey(rawKeyString);\n if (!buckets[bucketFileName])\n buckets[bucketFileName] = [];\n buckets[bucketFileName].push({ [rawKeyString]: [...identifierSet] });\n }\n await Promise.all(Object.entries(buckets).map(async ([bucketFileName, records]) => {\n const filePath = await driver.joinPath(indexPath, bucketFileName);\n await driver.writeIndexObject(filePath, records);\n }));\n };\n const readIndex = async (fieldPath) => {\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n throw new Error(`Index on field \"${fieldPath}\" does not exist`);\n const relativeFiles = await driver.listFilesRecursive(indexPath);\n const resultIndex = new Map();\n await Promise.all(relativeFiles.map(async (relativePath) => {\n const fullPath = await driver.joinPath(indexPath, relativePath);\n const maps = await driver.readIndexObject(fullPath).catch(() => null);\n if (!Array.isArray(maps))\n return;\n for (const entry of maps) {\n for (const [rawKey, identifierList] of Object.entries(entry)) {\n if (!resultIndex.has(rawKey))\n resultIndex.set(rawKey, new Set());\n const target = resultIndex.get(rawKey);\n for (const identifier of identifierList)\n target?.add(identifier);\n }\n }\n }));\n return resultIndex;\n };\n // Track which field paths should be kept up-to-date incrementally.\n const indicesToMaintain = [];\n const applyIndexDeltas = async (deltas) => {\n // For each indexed field with changes, touch only the affected bucket files\n await Promise.all([...deltas.entries()].map(async ([fieldPath, delta]) => {\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n return; // Only update indices that exist\n await driver.ensureDir(indexPath);\n // Compute impacted bucket filenames\n const touchedRawKeys = new Set([\n ...delta.adds.keys(),\n ...delta.removes.keys(),\n ]);\n const rawKeyToBucketFileName = new Map();\n await Promise.all([...touchedRawKeys].map(async (rawKey) => {\n rawKeyToBucketFileName.set(rawKey, await driver.fileNameForIndexKey(rawKey));\n }));\n const touchedBucketFileNames = new Set(rawKeyToBucketFileName.values());\n await Promise.all([...touchedBucketFileNames].map(async (bucketFileName) => {\n const filePath = await driver.joinPath(indexPath, bucketFileName);\n const bucketIndex = await readBucketIndex(filePath);\n // Apply removals for keys that map to this bucket\n delta.removes.forEach((identifierSet, rawKey) => {\n if (rawKeyToBucketFileName.get(rawKey) !== bucketFileName)\n return;\n const setForKey = bucketIndex.get(rawKey);\n if (!setForKey)\n return;\n identifierSet.forEach(identifier => setForKey.delete(identifier));\n if (setForKey.size === 0)\n bucketIndex.delete(rawKey);\n });\n // Apply additions\n delta.adds.forEach((identifierSet, rawKey) => {\n if (rawKeyToBucketFileName.get(rawKey) !== bucketFileName)\n return;\n const setForKey = bucketIndex.get(rawKey) ?? new Set();\n identifierSet.forEach(identifier => setForKey.add(identifier));\n bucketIndex.set(rawKey, setForKey);\n });\n await writeBucketIndex(filePath, bucketIndex);\n }));\n }));\n };\n const removeIdFromIndex = async (fieldPath, identifier) => {\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n return;\n const relativeFiles = await driver.listFilesRecursive(indexPath);\n await Promise.all(relativeFiles.map(async (relativePath) => {\n const filePath = await driver.joinPath(indexPath, relativePath);\n const data = await driver.readIndexObject(filePath).catch(() => null);\n if (!Array.isArray(data))\n return;\n let changed = false;\n const bucketIndex = new Map();\n for (const entry of data) {\n for (const [rawKey, identifierList] of Object.entries(entry)) {\n const set = new Set(identifierList);\n const before = set.size;\n set.delete(identifier);\n if (set.size !== before)\n changed = true;\n if (set.size > 0)\n bucketIndex.set(rawKey, set);\n }\n }\n if (!changed)\n return;\n await writeBucketIndex(filePath, bucketIndex);\n }));\n };\n const addIdToIndex = async (fieldPath, value, identifier) => {\n if (value == null)\n return;\n const rawKey = String(value);\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n return;\n await driver.ensureDir(indexPath);\n const filePath = await toIndexBucketFilePath(indexPath, rawKey);\n const bucketIndex = await readBucketIndex(filePath);\n const setForKey = bucketIndex.get(rawKey) ?? new Set();\n setForKey.add(identifier);\n bucketIndex.set(rawKey, setForKey);\n await writeBucketIndex(filePath, bucketIndex);\n };\n const updateIndexForReplace = async (oldItem, nextItem) => {\n await Promise.all(indicesToMaintain.map(async (fieldPath) => {\n await removeIdFromIndex(fieldPath, oldItem.id);\n const newValue = get(nextItem, fieldPath);\n await addIdToIndex(fieldPath, newValue, nextItem.id);\n }));\n };\n const upsertItems = async (items, mode) => {\n const deltas = new Map();\n await Promise.all(items.map(async (item) => {\n const filePath = await toItemsFilePath(item.id);\n const existingArray = await readItemsArrayOrEmpty(filePath);\n const indexOfItem = existingArray.findIndex(existing => existing.id === item.id);\n if (mode === 'insert') {\n if (indexOfItem !== -1)\n throw new Error(`Item with id \"${String(item.id)}\" already exists`);\n accumulateUpsertDelta(deltas, indicesToMaintain, undefined, item);\n await driver.writeObject(filePath, [...existingArray, item]);\n }\n else {\n if (indexOfItem === -1)\n throw new Error(`Item with id \"${String(item.id)}\" does not exist`);\n const updatedArray = [...existingArray];\n const oldItem = updatedArray[indexOfItem];\n updatedArray[indexOfItem] = item;\n await driver.writeObject(filePath, updatedArray);\n await updateIndexForReplace(oldItem, item);\n }\n }));\n // Only apply deltas for inserts (replace handled by direct purge+add)\n if (deltas.size > 0) {\n await applyIndexDeltas(deltas);\n }\n };\n return createStorageAdapter({\n setup: async () => {\n await driver.ensureDir(folderName);\n },\n teardown: async () => {\n // no-op\n },\n readAll,\n readIds: async (identifiers) => {\n const results = await Promise.all(identifiers.map(async (identifier) => {\n const filePath = await toItemsFilePath(identifier);\n const itemsInFile = await driver.readObject(filePath).catch(() => []) ?? [];\n if (!Array.isArray(itemsInFile))\n return null;\n return itemsInFile.find(item => item.id === identifier) ?? null;\n }));\n return results.filter((value) => value != null);\n },\n createIndex: async (fieldPath) => {\n if (fieldPath === 'id')\n throw new Error('Cannot create index on id field');\n indicesToMaintain.push(fieldPath);\n await ensureIndex(fieldPath);\n },\n dropIndex: async (fieldPath) => {\n const pathToDrop = await toIndexPathForField(fieldPath);\n const exists = await safeFileExists(pathToDrop);\n if (!exists)\n throw new Error(`Index on field \"${fieldPath}\" does not exist`);\n await driver.removeEntry(pathToDrop, { recursive: true });\n },\n readIndex,\n insert: async (itemsToInsert) => {\n await upsertItems(itemsToInsert, 'insert');\n },\n replace: async (itemsToReplace) => {\n await upsertItems(itemsToReplace, 'replace');\n },\n remove: async (itemsToRemove) => {\n const deltas = new Map();\n await Promise.all(itemsToRemove.map(async (item) => {\n const filePath = await toItemsFilePath(item.id);\n const existingArray = await readItemsArrayOrEmpty(filePath);\n const indexOfItem = existingArray.findIndex(existing => existing.id === item.id);\n if (indexOfItem === -1)\n throw new Error(`Item with id \"${String(item.id)}\" does not exist`);\n accumulateRemoveDelta(deltas, indicesToMaintain, existingArray[indexOfItem]);\n const updatedArray = [...existingArray];\n updatedArray.splice(indexOfItem, 1);\n await (updatedArray.length === 0\n ? driver.removeEntry(filePath).catch(() => { })\n : driver.writeObject(filePath, updatedArray));\n }));\n await applyIndexDeltas(deltas);\n },\n removeAll: async () => {\n const exists = await safeFileExists(folderName);\n if (!exists)\n return;\n await driver.removeEntry(folderName, { recursive: true });\n },\n });\n}\n"],"names":["addToDelta","deltas","fieldPath","changeKind","rawKey","identifier","delta","target","accumulateUpsertDelta","indicesToMaintain","existingItem","nextItem","value","get","accumulateRemoveDelta","createGenericFSAdapter","driver","folderName","itemsDirectoryPathPromise","indexRootPathPromise","safeFileExists","path","safeRemoveEntry","options","toItemsFilePath","toIndexPathForField","toIndexBucketFilePath","indexPath","bucketFileName","readItemsArrayOrEmpty","filePath","data","loadBucketIndexFromData","bucketIndex","entry","identifierList","writeBucketIndex","output","identifierSet","readBucketIndex","readAll","itemsDirectoryPath","relativeFiles","aggregatedItems","relativePath","fullPath","itemsInFile","ensureIndex","itemsPromise","allItems","indexMap","item","fieldValue","keyString","buckets","rawKeyString","records","readIndex","resultIndex","maps","applyIndexDeltas","touchedRawKeys","rawKeyToBucketFileName","touchedBucketFileNames","setForKey","removeIdFromIndex","changed","set","before","addIdToIndex","updateIndexForReplace","oldItem","newValue","upsertItems","items","mode","existingArray","indexOfItem","existing","updatedArray","createStorageAdapter","identifiers","pathToDrop","itemsToInsert","itemsToReplace","itemsToRemove"],"mappings":";AAYO,SAASA,EAAWC,GAAQC,GAAWC,GAAYC,GAAQC,GAAY;AAC1E,EAAKJ,EAAO,IAAIC,CAAS,KACrBD,EAAO,IAAIC,GAAW,EAAE,MAAM,oBAAI,IAAA,GAAO,SAAS,oBAAI,IAAA,GAAO;AACjE,QAAMI,IAAQL,EAAO,IAAIC,CAAS;AAClC,MAAI,CAACI;AACD;AACJ,QAAMC,IAASJ,MAAe,QAAQG,EAAM,OAAOA,EAAM;AACzD,EAAKC,EAAO,IAAIH,CAAM,KAClBG,EAAO,IAAIH,GAAQ,oBAAI,IAAA,CAAK,GAChCG,EAAO,IAAIH,CAAM,GAAG,IAAIC,CAAU;AACtC;AAkCO,MAAMG,IAAwB,CAACP,GAAQQ,GAAmBC,GAAcC,MAAa;AAOpF,aAAWT,KAAaO,GAAmB;AACvC,UAAMG,IAAQC,EAAIF,GAAUT,CAAS;AACrC,IAAIU,KAAS,QAEbZ,EAAWC,GAAQC,GAAW,OAAO,OAAOU,CAAK,GAAGD,EAAS,EAAE;AAAA,EACnE;AAER;AAUO,SAASG,EAAsBb,GAAQQ,GAAmBC,GAAc;AAC3E,aAAWR,KAAaO,GAAmB;AACvC,UAAMG,IAAQC,EAAIH,GAAcR,CAAS;AACzC,IAAIU,KAAS,QAEbZ,EAAWC,GAAQC,GAAW,UAAU,OAAOU,CAAK,GAAGF,EAAa,EAAE;AAAA,EAC1E;AACJ;AC9EA,SAAwBK,EAAuBC,GAAQC,GAAY;AAC/D,QAAMC,IAA4BF,EAAO,SAASC,GAAY,OAAO,GAC/DE,IAAuBH,EAAO,SAASC,GAAY,OAAO,GAC1DG,IAAiB,OAAOC,MAASL,EAAO,WAAWK,CAAI,EAAE,MAAM,MAAM,EAAK,GAC1EC,IAAkB,OAAOD,GAAME,MAAYP,EAAO,YAAYK,GAAME,CAAO,EAAE,MAAM,MAAM;AAAA,EAAE,CAAC,GAC5FC,IAAkB,OAAOnB,MAAeW,EAAO,SAAS,MAAME,GAA2B,MAAMF,EAAO,cAAcX,CAAU,CAAC,GAC/HoB,IAAsB,OAAOvB,MAAcc,EAAO,SAAS,MAAMG,GAAsB,MAAMH,EAAO,oBAAoBd,CAAS,CAAC,GAClIwB,IAAwB,OAAOC,GAAWvB,MAAW;AACvD,UAAMwB,IAAiB,MAAMZ,EAAO,oBAAoBZ,CAAM;AAC9D,WAAOY,EAAO,SAASW,GAAWC,CAAc;AAAA,EACpD,GACMC,IAAwB,OAAOC,MAAa;AAE9C,QAAI,CADW,MAAMV,EAAeU,CAAQ;AAExC,aAAO,CAAA;AACX,UAAMC,IAAO,MAAMf,EAAO,WAAWc,CAAQ,EAAE,MAAM,MAAM,EAAE;AAC7D,WAAO,MAAM,QAAQC,CAAI,IAAIA,IAAO,CAAA;AAAA,EACxC,GACMC,IAA0B,CAACD,MAAS;AACtC,UAAME,wBAAkB,IAAA;AACxB,QAAI,CAAC,MAAM,QAAQF,CAAI;AACnB,aAAOE;AACX,eAAWC,KAASH;AAChB,iBAAW,CAAC3B,GAAQ+B,CAAc,KAAK,OAAO,QAAQD,CAAK;AACvD,QAAAD,EAAY,IAAI7B,GAAQ,IAAI,IAAI+B,CAAc,CAAC;AAGvD,WAAOF;AAAA,EACX,GACMG,IAAmB,OAAON,GAAUG,MAAgB;AACtD,QAAIA,EAAY,SAAS,GAAG;AAExB,MADe,MAAMb,EAAeU,CAAQ,KAExC,MAAMR,EAAgBQ,CAAQ;AAClC;AAAA,IACJ;AACA,UAAMO,IAAS,CAAA;AACf,IAAAJ,EAAY,QAAQ,CAACK,GAAelC,MAAW;AAC3C,MAAAiC,EAAO,KAAK,EAAE,CAACjC,CAAM,GAAG,CAAC,GAAGkC,CAAa,GAAG;AAAA,IAChD,CAAC,GACD,MAAMtB,EAAO,iBAAiBc,GAAUO,CAAM;AAAA,EAClD,GACME,IAAkB,OAAOT,MAAa;AACxC,UAAMC,IAAO,MAAMf,EAAO,gBAAgBc,CAAQ,EAAE,MAAM,MAAM,IAAI;AACpE,WAAOE,EAAwBD,CAAI;AAAA,EACvC,GACMS,IAAU,YAAY;AACxB,UAAMC,IAAqB,MAAMvB;AAEjC,QAAI,CADoB,MAAME,EAAeqB,CAAkB;AAE3D,aAAO,CAAA;AACX,UAAMC,IAAgB,MAAM1B,EAAO,mBAAmByB,CAAkB,GAClEE,IAAkB,CAAA;AACxB,iBAAM,QAAQ,IAAID,EAAc,IAAI,OAAOE,MAAiB;AACxD,YAAMC,IAAW,MAAM7B,EAAO,SAASyB,GAAoBG,CAAY,GACjEE,IAAc,MAAM9B,EAAO,WAAW6B,CAAQ,EAAE,MAAM,MAAM,IAAI;AACtE,MAAI,MAAM,QAAQC,CAAW,KACzBH,EAAgB,KAAK,GAAGG,CAAW;AAAA,IAC3C,CAAC,CAAC,GACKH;AAAA,EACX,GACMI,IAAc,OAAO7C,GAAW8C,IAAeR,QAAc;AAC/D,UAAMS,IAAW,MAAMD,GACjBrB,IAAY,MAAMF,EAAoBvB,CAAS;AACrD,UAAMoB,EAAgBK,GAAW,EAAE,WAAW,IAAM,GACpD,MAAMX,EAAO,UAAUW,CAAS;AAEhC,UAAMuB,wBAAe,IAAA;AACrB,eAAWC,KAAQF,GAAU;AACzB,YAAMG,IAAavC,EAAIsC,GAAMjD,CAAS;AACtC,UAAIkD,KAAc;AACd;AACJ,YAAMC,IAAY,OAAOD,CAAU;AACnC,MAAKF,EAAS,IAAIG,CAAS,KACvBH,EAAS,IAAIG,GAAW,oBAAI,IAAA,CAAK,GACrCH,EAAS,IAAIG,CAAS,GAAG,IAAIF,EAAK,EAAE;AAAA,IACxC;AAEA,UAAMG,IAAU,CAAA;AAChB,eAAW,CAACC,GAAcjB,CAAa,KAAKY,GAAU;AAClD,YAAMtB,IAAiB,MAAMZ,EAAO,oBAAoBuC,CAAY;AACpE,MAAKD,EAAQ1B,CAAc,MACvB0B,EAAQ1B,CAAc,IAAI,CAAA,IAC9B0B,EAAQ1B,CAAc,EAAE,KAAK,EAAE,CAAC2B,CAAY,GAAG,CAAC,GAAGjB,CAAa,GAAG;AAAA,IACvE;AACA,UAAM,QAAQ,IAAI,OAAO,QAAQgB,CAAO,EAAE,IAAI,OAAO,CAAC1B,GAAgB4B,CAAO,MAAM;AAC/E,YAAM1B,IAAW,MAAMd,EAAO,SAASW,GAAWC,CAAc;AAChE,YAAMZ,EAAO,iBAAiBc,GAAU0B,CAAO;AAAA,IACnD,CAAC,CAAC;AAAA,EACN,GACMC,IAAY,OAAOvD,MAAc;AACnC,UAAMyB,IAAY,MAAMF,EAAoBvB,CAAS;AAErD,QAAI,CADgB,MAAMkB,EAAeO,CAAS;AAE9C,YAAM,IAAI,MAAM,mBAAmBzB,CAAS,kBAAkB;AAClE,UAAMwC,IAAgB,MAAM1B,EAAO,mBAAmBW,CAAS,GACzD+B,wBAAkB,IAAA;AACxB,iBAAM,QAAQ,IAAIhB,EAAc,IAAI,OAAOE,MAAiB;AACxD,YAAMC,IAAW,MAAM7B,EAAO,SAASW,GAAWiB,CAAY,GACxDe,IAAO,MAAM3C,EAAO,gBAAgB6B,CAAQ,EAAE,MAAM,MAAM,IAAI;AACpE,UAAK,MAAM,QAAQc,CAAI;AAEvB,mBAAWzB,KAASyB;AAChB,qBAAW,CAACvD,GAAQ+B,CAAc,KAAK,OAAO,QAAQD,CAAK,GAAG;AAC1D,YAAKwB,EAAY,IAAItD,CAAM,KACvBsD,EAAY,IAAItD,GAAQ,oBAAI,IAAA,CAAK;AACrC,kBAAMG,IAASmD,EAAY,IAAItD,CAAM;AACrC,uBAAWC,KAAc8B;AACrB,cAAA5B,GAAQ,IAAIF,CAAU;AAAA,UAC9B;AAAA,IAER,CAAC,CAAC,GACKqD;AAAA,EACX,GAEMjD,IAAoB,CAAA,GACpBmD,IAAmB,OAAO3D,MAAW;AAEvC,UAAM,QAAQ,IAAI,CAAC,GAAGA,EAAO,SAAS,EAAE,IAAI,OAAO,CAACC,GAAWI,CAAK,MAAM;AACtE,YAAMqB,IAAY,MAAMF,EAAoBvB,CAAS;AAErD,UAAI,CADgB,MAAMkB,EAAeO,CAAS;AAE9C;AACJ,YAAMX,EAAO,UAAUW,CAAS;AAEhC,YAAMkC,wBAAqB,IAAI;AAAA,QAC3B,GAAGvD,EAAM,KAAK,KAAA;AAAA,QACd,GAAGA,EAAM,QAAQ,KAAA;AAAA,MAAK,CACzB,GACKwD,wBAA6B,IAAA;AACnC,YAAM,QAAQ,IAAI,CAAC,GAAGD,CAAc,EAAE,IAAI,OAAOzD,MAAW;AACxD,QAAA0D,EAAuB,IAAI1D,GAAQ,MAAMY,EAAO,oBAAoBZ,CAAM,CAAC;AAAA,MAC/E,CAAC,CAAC;AACF,YAAM2D,IAAyB,IAAI,IAAID,EAAuB,QAAQ;AACtE,YAAM,QAAQ,IAAI,CAAC,GAAGC,CAAsB,EAAE,IAAI,OAAOnC,MAAmB;AACxE,cAAME,IAAW,MAAMd,EAAO,SAASW,GAAWC,CAAc,GAC1DK,IAAc,MAAMM,EAAgBT,CAAQ;AAElD,QAAAxB,EAAM,QAAQ,QAAQ,CAACgC,GAAelC,MAAW;AAC7C,cAAI0D,EAAuB,IAAI1D,CAAM,MAAMwB;AACvC;AACJ,gBAAMoC,IAAY/B,EAAY,IAAI7B,CAAM;AACxC,UAAK4D,MAEL1B,EAAc,QAAQ,CAAAjC,MAAc2D,EAAU,OAAO3D,CAAU,CAAC,GAC5D2D,EAAU,SAAS,KACnB/B,EAAY,OAAO7B,CAAM;AAAA,QACjC,CAAC,GAEDE,EAAM,KAAK,QAAQ,CAACgC,GAAelC,MAAW;AAC1C,cAAI0D,EAAuB,IAAI1D,CAAM,MAAMwB;AACvC;AACJ,gBAAMoC,IAAY/B,EAAY,IAAI7B,CAAM,yBAAS,IAAA;AACjD,UAAAkC,EAAc,QAAQ,CAAAjC,MAAc2D,EAAU,IAAI3D,CAAU,CAAC,GAC7D4B,EAAY,IAAI7B,GAAQ4D,CAAS;AAAA,QACrC,CAAC,GACD,MAAM5B,EAAiBN,GAAUG,CAAW;AAAA,MAChD,CAAC,CAAC;AAAA,IACN,CAAC,CAAC;AAAA,EACN,GACMgC,IAAoB,OAAO/D,GAAWG,MAAe;AACvD,UAAMsB,IAAY,MAAMF,EAAoBvB,CAAS;AAErD,QAAI,CADgB,MAAMkB,EAAeO,CAAS;AAE9C;AACJ,UAAMe,IAAgB,MAAM1B,EAAO,mBAAmBW,CAAS;AAC/D,UAAM,QAAQ,IAAIe,EAAc,IAAI,OAAOE,MAAiB;AACxD,YAAMd,IAAW,MAAMd,EAAO,SAASW,GAAWiB,CAAY,GACxDb,IAAO,MAAMf,EAAO,gBAAgBc,CAAQ,EAAE,MAAM,MAAM,IAAI;AACpE,UAAI,CAAC,MAAM,QAAQC,CAAI;AACnB;AACJ,UAAImC,IAAU;AACd,YAAMjC,wBAAkB,IAAA;AACxB,iBAAWC,KAASH;AAChB,mBAAW,CAAC3B,GAAQ+B,CAAc,KAAK,OAAO,QAAQD,CAAK,GAAG;AAC1D,gBAAMiC,IAAM,IAAI,IAAIhC,CAAc,GAC5BiC,IAASD,EAAI;AACnB,UAAAA,EAAI,OAAO9D,CAAU,GACjB8D,EAAI,SAASC,MACbF,IAAU,KACVC,EAAI,OAAO,KACXlC,EAAY,IAAI7B,GAAQ+D,CAAG;AAAA,QACnC;AAEJ,MAAKD,KAEL,MAAM9B,EAAiBN,GAAUG,CAAW;AAAA,IAChD,CAAC,CAAC;AAAA,EACN,GACMoC,IAAe,OAAOnE,GAAWU,GAAOP,MAAe;AACzD,QAAIO,KAAS;AACT;AACJ,UAAMR,IAAS,OAAOQ,CAAK,GACrBe,IAAY,MAAMF,EAAoBvB,CAAS;AAErD,QAAI,CADgB,MAAMkB,EAAeO,CAAS;AAE9C;AACJ,UAAMX,EAAO,UAAUW,CAAS;AAChC,UAAMG,IAAW,MAAMJ,EAAsBC,GAAWvB,CAAM,GACxD6B,IAAc,MAAMM,EAAgBT,CAAQ,GAC5CkC,IAAY/B,EAAY,IAAI7B,CAAM,yBAAS,IAAA;AACjD,IAAA4D,EAAU,IAAI3D,CAAU,GACxB4B,EAAY,IAAI7B,GAAQ4D,CAAS,GACjC,MAAM5B,EAAiBN,GAAUG,CAAW;AAAA,EAChD,GACMqC,IAAwB,OAAOC,GAAS5D,MAAa;AACvD,UAAM,QAAQ,IAAIF,EAAkB,IAAI,OAAOP,MAAc;AACzD,YAAM+D,EAAkB/D,GAAWqE,EAAQ,EAAE;AAC7C,YAAMC,IAAW3D,EAAIF,GAAUT,CAAS;AACxC,YAAMmE,EAAanE,GAAWsE,GAAU7D,EAAS,EAAE;AAAA,IACvD,CAAC,CAAC;AAAA,EACN,GACM8D,IAAc,OAAOC,GAAOC,MAAS;AACvC,UAAM1E,wBAAa,IAAA;AACnB,UAAM,QAAQ,IAAIyE,EAAM,IAAI,OAAOvB,MAAS;AACxC,YAAMrB,IAAW,MAAMN,EAAgB2B,EAAK,EAAE,GACxCyB,IAAgB,MAAM/C,EAAsBC,CAAQ,GACpD+C,IAAcD,EAAc,UAAU,OAAYE,EAAS,OAAO3B,EAAK,EAAE;AAC/E,UAAIwB,MAAS,UAAU;AACnB,YAAIE,MAAgB;AAChB,gBAAM,IAAI,MAAM,iBAAiB,OAAO1B,EAAK,EAAE,CAAC,kBAAkB;AACtE,QAAA3C,EAAsBP,GAAQQ,GAAmB,QAAW0C,CAAI,GAChE,MAAMnC,EAAO,YAAYc,GAAU,CAAC,GAAG8C,GAAezB,CAAI,CAAC;AAAA,MAC/D,OACK;AACD,YAAI0B,MAAgB;AAChB,gBAAM,IAAI,MAAM,iBAAiB,OAAO1B,EAAK,EAAE,CAAC,kBAAkB;AACtE,cAAM4B,IAAe,CAAC,GAAGH,CAAa,GAChCL,IAAUQ,EAAaF,CAAW;AACxC,QAAAE,EAAaF,CAAW,IAAI1B,GAC5B,MAAMnC,EAAO,YAAYc,GAAUiD,CAAY,GAC/C,MAAMT,EAAsBC,GAASpB,CAAI;AAAA,MAC7C;AAAA,IACJ,CAAC,CAAC,GAEElD,EAAO,OAAO,KACd,MAAM2D,EAAiB3D,CAAM;AAAA,EAErC;AACA,SAAO+E,EAAqB;AAAA,IACxB,OAAO,YAAY;AACf,YAAMhE,EAAO,UAAUC,CAAU;AAAA,IACrC;AAAA,IACA,UAAU,YAAY;AAAA,IAEtB;AAAA,IACA,SAAAuB;AAAA,IACA,SAAS,OAAOyC,OACI,MAAM,QAAQ,IAAIA,EAAY,IAAI,OAAO5E,MAAe;AACpE,YAAMyB,IAAW,MAAMN,EAAgBnB,CAAU,GAC3CyC,IAAc,MAAM9B,EAAO,WAAWc,CAAQ,EAAE,MAAM,MAAM,CAAA,CAAE,KAAK,CAAA;AACzE,aAAK,MAAM,QAAQgB,CAAW,IAEvBA,EAAY,KAAK,CAAAK,MAAQA,EAAK,OAAO9C,CAAU,KAAK,OADhD;AAAA,IAEf,CAAC,CAAC,GACa,OAAO,CAACO,MAAUA,KAAS,IAAI;AAAA,IAElD,aAAa,OAAOV,MAAc;AAC9B,UAAIA,MAAc;AACd,cAAM,IAAI,MAAM,iCAAiC;AACrD,MAAAO,EAAkB,KAAKP,CAAS,GAChC,MAAM6C,EAAY7C,CAAS;AAAA,IAC/B;AAAA,IACA,WAAW,OAAOA,MAAc;AAC5B,YAAMgF,IAAa,MAAMzD,EAAoBvB,CAAS;AAEtD,UAAI,CADW,MAAMkB,EAAe8D,CAAU;AAE1C,cAAM,IAAI,MAAM,mBAAmBhF,CAAS,kBAAkB;AAClE,YAAMc,EAAO,YAAYkE,GAAY,EAAE,WAAW,IAAM;AAAA,IAC5D;AAAA,IACA,WAAAzB;AAAA,IACA,QAAQ,OAAO0B,MAAkB;AAC7B,YAAMV,EAAYU,GAAe,QAAQ;AAAA,IAC7C;AAAA,IACA,SAAS,OAAOC,MAAmB;AAC/B,YAAMX,EAAYW,GAAgB,SAAS;AAAA,IAC/C;AAAA,IACA,QAAQ,OAAOC,MAAkB;AAC7B,YAAMpF,wBAAa,IAAA;AACnB,YAAM,QAAQ,IAAIoF,EAAc,IAAI,OAAOlC,MAAS;AAChD,cAAMrB,IAAW,MAAMN,EAAgB2B,EAAK,EAAE,GACxCyB,IAAgB,MAAM/C,EAAsBC,CAAQ,GACpD+C,IAAcD,EAAc,UAAU,OAAYE,EAAS,OAAO3B,EAAK,EAAE;AAC/E,YAAI0B,MAAgB;AAChB,gBAAM,IAAI,MAAM,iBAAiB,OAAO1B,EAAK,EAAE,CAAC,kBAAkB;AACtE,QAAArC,EAAsBb,GAAQQ,GAAmBmE,EAAcC,CAAW,CAAC;AAC3E,cAAME,IAAe,CAAC,GAAGH,CAAa;AACtC,QAAAG,EAAa,OAAOF,GAAa,CAAC,GAClC,OAAOE,EAAa,WAAW,IACzB/D,EAAO,YAAYc,CAAQ,EAAE,MAAM,MAAM;AAAA,QAAE,CAAC,IAC5Cd,EAAO,YAAYc,GAAUiD,CAAY;AAAA,MACnD,CAAC,CAAC,GACF,MAAMnB,EAAiB3D,CAAM;AAAA,IACjC;AAAA,IACA,WAAW,YAAY;AAEnB,MADe,MAAMmB,EAAeH,CAAU,KAG9C,MAAMD,EAAO,YAAYC,GAAY,EAAE,WAAW,IAAM;AAAA,IAC5D;AAAA,EAAA,CACH;AACL;"}
|
package/dist/index.umd.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(x,E){typeof exports=="object"&&typeof module<"u"?module.exports=E(require("@signaldb/core")):typeof define=="function"&&define.amd?define(["@signaldb/core"],E):(x=typeof globalThis<"u"?globalThis:x||self,x.SignalDB=E(x.core))})(this,(function(x){"use strict";function E(e,l,I,f,d){e.has(l)||e.set(l,{adds:new Map,removes:new Map});const h=e.get(l);if(!h)return;const g=I==="add"?h.adds:h.removes;g.has(f)||g.set(f,new Set),g.get(f)?.add(d)}const R=(e,l,I,f)=>{for(const d of l){const h=x.get(f,d);h!=null&&E(e,d,"add",String(h),f.id)}};function B(e,l,I){for(const f of l){const d=x.get(I,f);d!=null&&E(e,f,"remove",String(d),I.id)}}function K(e,l){const I=e.joinPath(l,"items"),f=e.joinPath(l,"index"),d=async t=>e.fileExists(t).catch(()=>!1),h=async(t,n)=>e.removeEntry(t,n).catch(()=>{}),g=async t=>e.joinPath(await I,await e.fileNameForId(t)),F=async t=>e.joinPath(await f,await e.fileNameForIndexKey(t)),T=async(t,n)=>{const a=await e.fileNameForIndexKey(n);return e.joinPath(t,a)},A=async t=>{if(!await d(t))return[];const a=await e.readObject(t).catch(()=>[]);return Array.isArray(a)?a:[]},z=t=>{const n=new Map;if(!Array.isArray(t))return n;for(const a of t)for(const[s,i]of Object.entries(a))n.set(s,new Set(i));return n},S=async(t,n)=>{if(n.size===0){await d(t)&&await h(t);return}const a=[];n.forEach((s,i)=>{a.push({[i]:[...s]})}),await e.writeIndexObject(t,a)},O=async t=>{const n=await e.readIndexObject(t).catch(()=>null);return z(n)},k=async()=>{const t=await I;if(!await d(t))return[];const a=await e.listFilesRecursive(t),s=[];return await Promise.all(a.map(async i=>{const w=await e.joinPath(t,i),o=await e.readObject(w).catch(()=>null);Array.isArray(o)&&s.push(...o)})),s},$=async(t,n=k())=>{const a=await n,s=await F(t);await h(s,{recursive:!0}),await e.ensureDir(s);const i=new Map;for(const o of a){const c=x.get(o,t);if(c==null)continue;const r=String(c);i.has(r)||i.set(r,new Set),i.get(r)?.add(o.id)}const w={};for(const[o,c]of i){const r=await e.fileNameForIndexKey(o);w[r]||(w[r]=[]),w[r].push({[o]:[...c]})}await Promise.all(Object.entries(w).map(async([o,c])=>{const r=await e.joinPath(s,o);await e.writeIndexObject(r,c)}))},L=async t=>{const n=await F(t);if(!await d(n))throw new Error(`Index on field "${t}" does not exist`);const s=await e.listFilesRecursive(n),i=new Map;return await Promise.all(s.map(async w=>{const o=await e.joinPath(n,w),c=await e.readIndexObject(o).catch(()=>null);if(Array.isArray(c))for(const r of c)for(const[m,p]of Object.entries(r)){i.has(m)||i.set(m,new Set);const P=i.get(m);for(const y of p)P?.add(y)}})),i},b=[],D=async t=>{await Promise.all([...t.entries()].map(async([n,a])=>{const s=await F(n);if(!await d(s))return;await e.ensureDir(s);const w=new Set([...a.adds.keys(),...a.removes.keys()]),o=new Map;await Promise.all([...w].map(async r=>{o.set(r,await e.fileNameForIndexKey(r))}));const c=new Set(o.values());await Promise.all([...c].map(async r=>{const m=await e.joinPath(s,r),p=await O(m);a.removes.forEach((P,y)=>{if(o.get(y)!==r)return;const u=p.get(y);u&&(P.forEach(j=>u.delete(j)),u.size===0&&p.delete(y))}),a.adds.forEach((P,y)=>{if(o.get(y)!==r)return;const u=p.get(y)??new Set;P.forEach(j=>u.add(j)),p.set(y,u)}),await S(m,p)}))}))},N=async(t,n)=>{const a=await F(t);if(!await d(a))return;const i=await e.listFilesRecursive(a);await Promise.all(i.map(async w=>{const o=await e.joinPath(a,w),c=await e.readIndexObject(o).catch(()=>null);if(!Array.isArray(c))return;let r=!1;const m=new Map;for(const p of c)for(const[P,y]of Object.entries(p)){const u=new Set(y),j=u.size;u.delete(n),u.size!==j&&(r=!0),u.size>0&&m.set(P,u)}r&&await S(o,m)}))},V=async(t,n,a)=>{if(n==null)return;const s=String(n),i=await F(t);if(!await d(i))return;await e.ensureDir(i);const o=await T(i,s),c=await O(o),r=c.get(s)??new Set;r.add(a),c.set(s,r),await S(o,c)},q=async(t,n)=>{await Promise.all(b.map(async a=>{await N(a,t.id);const s=x.get(n,a);await V(a,s,n.id)}))},M=async(t,n)=>{const a=new Map;await Promise.all(t.map(async s=>{const i=await g(s.id),w=await A(i),o=w.findIndex(c=>c.id===s.id);if(n==="insert"){if(o!==-1)throw new Error(`Item with id "${String(s.id)}" already exists`);R(a,b,void 0,s),await e.writeObject(i,[...w,s])}else{if(o===-1)throw new Error(`Item with id "${String(s.id)}" does not exist`);const c=[...w],r=c[o];c[o]=s,await e.writeObject(i,c),await q(r,s)}})),a.size>0&&await D(a)};return x.createStorageAdapter({setup:async()=>{await e.ensureDir(l)},teardown:async()=>{},readAll:k,readIds:async t=>(await Promise.all(t.map(async a=>{const s=await g(a),i=await e.readObject(s).catch(()=>[])??[];return Array.isArray(i)?i.find(w=>w.id===a)??null:null}))).filter(a=>a!=null),createIndex:async t=>{if(t==="id")throw new Error("Cannot create index on id field");b.push(t),await $(t)},dropIndex:async t=>{const n=await F(t);if(!await d(n))throw new Error(`Index on field "${t}" does not exist`);await e.removeEntry(n,{recursive:!0})},readIndex:L,insert:async t=>{await M(t,"insert")},replace:async t=>{await M(t,"replace")},remove:async t=>{const n=new Map;await Promise.all(t.map(async a=>{const s=await g(a.id),i=await A(s),w=i.findIndex(c=>c.id===a.id);if(w===-1)throw new Error(`Item with id "${String(a.id)}" does not exist`);B(n,b,i[w]);const o=[...i];o.splice(w,1),await(o.length===0?e.removeEntry(s).catch(()=>{}):e.writeObject(s,o))})),await D(n)},removeAll:async()=>{await d(l)&&await e.removeEntry(l,{recursive:!0})}})}return K}));
|
|
2
2
|
//# sourceMappingURL=index.umd.js.map
|
package/dist/index.umd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.umd.js","sources":["../src/index.ts"],"sourcesContent":["import { createStorageAdapter, get } from '@signaldb/core';\n/**\n * Creates a storage adapter for managing a SignalDB collection using a generic filesystem-like driver.\n * Data is sharded into subdirectories based on item identifiers, and indices are maintained as files.\n * @param driver - The driver that handles low-level file operations.\n * @param folderName - The root folder path for storing the collection data.\n * @returns A SignalDB storage adapter for managing data in a filesystem-like storage.\n */\nexport default function createGenericFSAdapter(driver, folderName) {\n const itemsDirectoryPathPromise = driver.joinPath(folderName, 'items');\n const indexRootPathPromise = driver.joinPath(folderName, 'index');\n const safeFileExists = async (path) => driver.fileExists(path).catch(() => false);\n const safeRemoveEntry = async (path, options) => driver.removeEntry(path, options).catch(() => { });\n const toItemsFilePath = async (identifier) => driver.joinPath(await itemsDirectoryPathPromise, await driver.fileNameForId(identifier));\n const toIndexPathForField = async (fieldPath) => driver.joinPath(await indexRootPathPromise, await driver.fileNameForIndexKey(fieldPath));\n const toIndexBucketFilePath = async (indexPath, rawKey) => {\n const bucketFileName = await driver.fileNameForIndexKey(rawKey);\n return driver.joinPath(indexPath, bucketFileName);\n };\n const readItemsArrayOrEmpty = async (filePath) => {\n const exists = await safeFileExists(filePath);\n if (!exists)\n return [];\n const data = await driver.readObject(filePath).catch(() => []);\n return Array.isArray(data) ? data : [];\n };\n const loadBucketIndexFromData = (data) => {\n const bucketIndex = new Map();\n if (!Array.isArray(data))\n return bucketIndex;\n for (const entry of data) {\n for (const [rawKey, identifierList] of Object.entries(entry)) {\n bucketIndex.set(rawKey, new Set(identifierList));\n }\n }\n return bucketIndex;\n };\n const writeBucketIndex = async (filePath, bucketIndex) => {\n if (bucketIndex.size === 0) {\n const exists = await safeFileExists(filePath);\n if (exists)\n await safeRemoveEntry(filePath);\n return;\n }\n const output = [];\n bucketIndex.forEach((identifierSet, rawKey) => {\n output.push({ [rawKey]: [...identifierSet] });\n });\n await driver.writeIndexObject(filePath, output);\n };\n const readBucketIndex = async (filePath) => {\n const data = await driver.readIndexObject(filePath).catch(() => null);\n return loadBucketIndexFromData(data);\n };\n const readAll = async () => {\n const itemsDirectoryPath = await itemsDirectoryPathPromise;\n const directoryExists = await safeFileExists(itemsDirectoryPath);\n if (!directoryExists)\n return [];\n const relativeFiles = await driver.listFilesRecursive(itemsDirectoryPath);\n const aggregatedItems = [];\n await Promise.all(relativeFiles.map(async (relativePath) => {\n const fullPath = await driver.joinPath(itemsDirectoryPath, relativePath);\n const itemsInFile = await driver.readObject(fullPath).catch(() => null);\n if (Array.isArray(itemsInFile))\n aggregatedItems.push(...itemsInFile);\n }));\n return aggregatedItems;\n };\n const ensureIndex = async (fieldPath, itemsPromise = readAll()) => {\n const allItems = await itemsPromise;\n const indexPath = await toIndexPathForField(fieldPath);\n await safeRemoveEntry(indexPath, { recursive: true });\n await driver.ensureDir(indexPath);\n // Build value -> Set<identifier>\n const indexMap = new Map();\n for (const item of allItems) {\n const fieldValue = get(item, fieldPath);\n if (fieldValue == null)\n continue;\n const keyString = String(fieldValue);\n if (!indexMap.has(keyString))\n indexMap.set(keyString, new Set());\n indexMap.get(keyString)?.add(item.id);\n }\n // Group entries by bucket file name, then persist each bucket\n const buckets = {};\n for (const [rawKeyString, identifierSet] of indexMap) {\n const bucketFileName = await driver.fileNameForIndexKey(rawKeyString);\n if (!buckets[bucketFileName])\n buckets[bucketFileName] = [];\n buckets[bucketFileName].push({ [rawKeyString]: [...identifierSet] });\n }\n await Promise.all(Object.entries(buckets).map(async ([bucketFileName, records]) => {\n const filePath = await driver.joinPath(indexPath, bucketFileName);\n await driver.writeIndexObject(filePath, records);\n }));\n };\n const readIndex = async (fieldPath) => {\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n throw new Error(`Index on field \"${fieldPath}\" does not exist`);\n const relativeFiles = await driver.listFilesRecursive(indexPath);\n const resultIndex = new Map();\n await Promise.all(relativeFiles.map(async (relativePath) => {\n const fullPath = await driver.joinPath(indexPath, relativePath);\n const maps = await driver.readIndexObject(fullPath).catch(() => null);\n if (!Array.isArray(maps))\n return;\n for (const entry of maps) {\n for (const [rawKey, identifierList] of Object.entries(entry)) {\n if (!resultIndex.has(rawKey))\n resultIndex.set(rawKey, new Set());\n const target = resultIndex.get(rawKey);\n for (const identifier of identifierList)\n target?.add(identifier);\n }\n }\n }));\n return resultIndex;\n };\n // Track which field paths should be kept up-to-date incrementally.\n const indicesToMaintain = [];\n const addToDelta = (deltas, fieldPath, changeKind, rawKey, identifier) => {\n if (!deltas.has(fieldPath))\n deltas.set(fieldPath, { adds: new Map(), removes: new Map() });\n const delta = deltas.get(fieldPath);\n if (!delta)\n return;\n const target = changeKind === 'add' ? delta.adds : delta.removes;\n if (!target.has(rawKey))\n target.set(rawKey, new Set());\n target.get(rawKey)?.add(identifier);\n };\n const addDeltaForChange = (deltas, fieldPath, oldValue, newValue, identifier) => {\n const oldKey = oldValue == null ? undefined : String(oldValue);\n const newKey = newValue == null ? undefined : String(newValue);\n if (oldKey === newKey)\n return;\n if (oldKey != null)\n addToDelta(deltas, fieldPath, 'remove', oldKey, identifier);\n if (newKey != null)\n addToDelta(deltas, fieldPath, 'add', newKey, identifier);\n };\n const accumulateUpsertDelta = (deltas, existingItem, nextItem) => {\n if (existingItem) {\n for (const fieldPath of indicesToMaintain) {\n addDeltaForChange(deltas, fieldPath, get(existingItem, fieldPath), get(nextItem, fieldPath), nextItem.id);\n }\n }\n else {\n for (const fieldPath of indicesToMaintain) {\n const value = get(nextItem, fieldPath);\n if (value == null)\n continue;\n addToDelta(deltas, fieldPath, 'add', String(value), nextItem.id);\n }\n }\n };\n const accumulateRemoveDelta = (deltas, existingItem) => {\n for (const fieldPath of indicesToMaintain) {\n const value = get(existingItem, fieldPath);\n if (value == null)\n continue;\n addToDelta(deltas, fieldPath, 'remove', String(value), existingItem.id);\n }\n };\n const applyIndexDeltas = async (deltas) => {\n // For each indexed field with changes, touch only the affected bucket files\n await Promise.all([...deltas.entries()].map(async ([fieldPath, delta]) => {\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n return; // Only update indices that exist\n await driver.ensureDir(indexPath);\n // Compute impacted bucket filenames\n const touchedRawKeys = new Set([\n ...delta.adds.keys(),\n ...delta.removes.keys(),\n ]);\n const rawKeyToBucketFileName = new Map();\n await Promise.all([...touchedRawKeys].map(async (rawKey) => {\n rawKeyToBucketFileName.set(rawKey, await driver.fileNameForIndexKey(rawKey));\n }));\n const touchedBucketFileNames = new Set(rawKeyToBucketFileName.values());\n await Promise.all([...touchedBucketFileNames].map(async (bucketFileName) => {\n const filePath = await driver.joinPath(indexPath, bucketFileName);\n const bucketIndex = await readBucketIndex(filePath);\n // Apply removals for keys that map to this bucket\n delta.removes.forEach((identifierSet, rawKey) => {\n if (rawKeyToBucketFileName.get(rawKey) !== bucketFileName)\n return;\n const setForKey = bucketIndex.get(rawKey);\n if (!setForKey)\n return;\n identifierSet.forEach(identifier => setForKey.delete(identifier));\n if (setForKey.size === 0)\n bucketIndex.delete(rawKey);\n });\n // Apply additions\n delta.adds.forEach((identifierSet, rawKey) => {\n if (rawKeyToBucketFileName.get(rawKey) !== bucketFileName)\n return;\n const setForKey = bucketIndex.get(rawKey) ?? new Set();\n identifierSet.forEach(identifier => setForKey.add(identifier));\n bucketIndex.set(rawKey, setForKey);\n });\n await writeBucketIndex(filePath, bucketIndex);\n }));\n }));\n };\n const removeIdFromIndex = async (fieldPath, identifier) => {\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n return;\n const relativeFiles = await driver.listFilesRecursive(indexPath);\n await Promise.all(relativeFiles.map(async (relativePath) => {\n const filePath = await driver.joinPath(indexPath, relativePath);\n const data = await driver.readIndexObject(filePath).catch(() => null);\n if (!Array.isArray(data))\n return;\n let changed = false;\n const bucketIndex = new Map();\n for (const entry of data) {\n for (const [rawKey, identifierList] of Object.entries(entry)) {\n const set = new Set(identifierList);\n const before = set.size;\n set.delete(identifier);\n if (set.size !== before)\n changed = true;\n if (set.size > 0)\n bucketIndex.set(rawKey, set);\n }\n }\n if (!changed)\n return;\n await writeBucketIndex(filePath, bucketIndex);\n }));\n };\n const addIdToIndex = async (fieldPath, value, identifier) => {\n if (value == null)\n return;\n const rawKey = String(value);\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n return;\n await driver.ensureDir(indexPath);\n const filePath = await toIndexBucketFilePath(indexPath, rawKey);\n const bucketIndex = await readBucketIndex(filePath);\n const setForKey = bucketIndex.get(rawKey) ?? new Set();\n setForKey.add(identifier);\n bucketIndex.set(rawKey, setForKey);\n await writeBucketIndex(filePath, bucketIndex);\n };\n const updateIndexForReplace = async (oldItem, nextItem) => {\n await Promise.all(indicesToMaintain.map(async (fieldPath) => {\n await removeIdFromIndex(fieldPath, oldItem.id);\n const newValue = get(nextItem, fieldPath);\n await addIdToIndex(fieldPath, newValue, nextItem.id);\n }));\n };\n const upsertItems = async (items, mode) => {\n const deltas = new Map();\n await Promise.all(items.map(async (item) => {\n const filePath = await toItemsFilePath(item.id);\n const existingArray = await readItemsArrayOrEmpty(filePath);\n const indexOfItem = existingArray.findIndex(existing => existing.id === item.id);\n if (mode === 'insert') {\n if (indexOfItem !== -1)\n throw new Error(`Item with id \"${String(item.id)}\" already exists`);\n accumulateUpsertDelta(deltas, undefined, item);\n await driver.writeObject(filePath, [...existingArray, item]);\n }\n else {\n if (indexOfItem === -1)\n throw new Error(`Item with id \"${String(item.id)}\" does not exist`);\n const updatedArray = [...existingArray];\n const oldItem = updatedArray[indexOfItem];\n updatedArray[indexOfItem] = item;\n await driver.writeObject(filePath, updatedArray);\n await updateIndexForReplace(oldItem, item);\n }\n }));\n // Only apply deltas for inserts (replace handled by direct purge+add)\n if (deltas.size > 0) {\n await applyIndexDeltas(deltas);\n }\n };\n return createStorageAdapter({\n setup: async () => {\n await driver.ensureDir(folderName);\n },\n teardown: async () => {\n // no-op\n },\n readAll,\n readIds: async (identifiers) => {\n const results = await Promise.all(identifiers.map(async (identifier) => {\n const filePath = await toItemsFilePath(identifier);\n const itemsInFile = await driver.readObject(filePath).catch(() => []) ?? [];\n if (!Array.isArray(itemsInFile))\n return null;\n return itemsInFile.find(item => item.id === identifier) ?? null;\n }));\n return results.filter((value) => value != null);\n },\n createIndex: async (fieldPath) => {\n if (fieldPath === 'id')\n throw new Error('Cannot create index on id field');\n indicesToMaintain.push(fieldPath);\n await ensureIndex(fieldPath);\n },\n dropIndex: async (fieldPath) => {\n const pathToDrop = await toIndexPathForField(fieldPath);\n const exists = await safeFileExists(pathToDrop);\n if (!exists)\n throw new Error(`Index on field \"${fieldPath}\" does not exist`);\n await driver.removeEntry(pathToDrop, { recursive: true });\n },\n readIndex,\n insert: async (itemsToInsert) => {\n await upsertItems(itemsToInsert, 'insert');\n },\n replace: async (itemsToReplace) => {\n await upsertItems(itemsToReplace, 'replace');\n },\n remove: async (itemsToRemove) => {\n const deltas = new Map();\n await Promise.all(itemsToRemove.map(async (item) => {\n const filePath = await toItemsFilePath(item.id);\n const existingArray = await readItemsArrayOrEmpty(filePath);\n const indexOfItem = existingArray.findIndex(existing => existing.id === item.id);\n if (indexOfItem === -1)\n throw new Error(`Item with id \"${String(item.id)}\" does not exist`);\n accumulateRemoveDelta(deltas, existingArray[indexOfItem]);\n const updatedArray = [...existingArray];\n updatedArray.splice(indexOfItem, 1);\n await (updatedArray.length === 0\n ? driver.removeEntry(filePath).catch(() => { })\n : driver.writeObject(filePath, updatedArray));\n }));\n await applyIndexDeltas(deltas);\n },\n removeAll: async () => {\n const exists = await safeFileExists(folderName);\n if (!exists)\n return;\n await driver.removeEntry(folderName, { recursive: true });\n },\n });\n}\n"],"names":["createGenericFSAdapter","driver","folderName","itemsDirectoryPathPromise","indexRootPathPromise","safeFileExists","path","safeRemoveEntry","options","toItemsFilePath","identifier","toIndexPathForField","fieldPath","toIndexBucketFilePath","indexPath","rawKey","bucketFileName","readItemsArrayOrEmpty","filePath","data","loadBucketIndexFromData","bucketIndex","entry","identifierList","writeBucketIndex","output","identifierSet","readBucketIndex","readAll","itemsDirectoryPath","relativeFiles","aggregatedItems","relativePath","fullPath","itemsInFile","ensureIndex","itemsPromise","allItems","indexMap","item","fieldValue","get","keyString","buckets","rawKeyString","records","readIndex","resultIndex","maps","target","indicesToMaintain","addToDelta","deltas","changeKind","delta","accumulateUpsertDelta","existingItem","nextItem","value","accumulateRemoveDelta","applyIndexDeltas","touchedRawKeys","rawKeyToBucketFileName","touchedBucketFileNames","setForKey","removeIdFromIndex","changed","set","before","addIdToIndex","updateIndexForReplace","oldItem","newValue","upsertItems","items","mode","existingArray","indexOfItem","existing","updatedArray","createStorageAdapter","identifiers","pathToDrop","itemsToInsert","itemsToReplace","itemsToRemove"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/deltaHelpers.ts","../src/index.ts"],"sourcesContent":["import { get } from '@signaldb/core';\n/**\n * Records a single index mutation into the delta map for a given indexed field.\n *\n * The delta map is grouped by `fieldPath`, and then by stringified key (`rawKey`).\n * Each key maps to a set of identifiers to add/remove for that key.\n * @param deltas - Accumulator of per-field index deltas.\n * @param fieldPath - Dot-path of the indexed field (used as the delta bucket key).\n * @param changeKind - Whether this identifier should be added to or removed from the index key.\n * @param rawKey - The stringified index key value.\n * @param identifier - The item identifier to add/remove for `rawKey`.\n */\nexport function addToDelta(deltas, fieldPath, changeKind, rawKey, identifier) {\n if (!deltas.has(fieldPath))\n deltas.set(fieldPath, { adds: new Map(), removes: new Map() });\n const delta = deltas.get(fieldPath);\n if (!delta)\n return;\n const target = changeKind === 'add' ? delta.adds : delta.removes;\n if (!target.has(rawKey))\n target.set(rawKey, new Set());\n target.get(rawKey)?.add(identifier);\n}\n/**\n * Computes the delta for a change in a single indexed field.\n *\n * Values are coerced to string keys (with `null`/`undefined` treated as \"no key\").\n * If the derived keys are equal, no delta is recorded.\n * @param deltas - Accumulator of per-field index deltas.\n * @param fieldPath - Dot-path of the indexed field being tracked.\n * @param oldValue - Previous value of the field.\n * @param newValue - Next value of the field.\n * @param identifier - The item identifier affected by the change.\n */\nexport function addDeltaForChange(deltas, fieldPath, oldValue, newValue, identifier) {\n const oldKey = oldValue == null ? undefined : String(oldValue);\n const newKey = newValue == null ? undefined : String(newValue);\n if (oldKey === newKey)\n return;\n if (oldKey != null)\n addToDelta(deltas, fieldPath, 'remove', oldKey, identifier);\n if (newKey != null)\n addToDelta(deltas, fieldPath, 'add', newKey, identifier);\n}\n/**\n * Accumulates index deltas for an upsert operation.\n *\n * - If `existingItem` is present, compares each maintained index field between the old and new item,\n * recording removes/adds for key changes.\n * - If `existingItem` is absent, treats the operation as an insert and records adds for each\n * maintained index field that has a non-null value.\n * @param deltas - Accumulator of per-field index deltas.\n * @param indicesToMaintain - List of dot-paths for fields that are indexed.\n * @param existingItem - Previous stored item (if any).\n * @param nextItem - Incoming item to upsert.\n */\nexport const accumulateUpsertDelta = (deltas, indicesToMaintain, existingItem, nextItem) => {\n if (existingItem) {\n for (const fieldPath of indicesToMaintain) {\n addDeltaForChange(deltas, fieldPath, get(existingItem, fieldPath), get(nextItem, fieldPath), nextItem.id);\n }\n }\n else {\n for (const fieldPath of indicesToMaintain) {\n const value = get(nextItem, fieldPath);\n if (value == null)\n continue;\n addToDelta(deltas, fieldPath, 'add', String(value), nextItem.id);\n }\n }\n};\n/**\n * Accumulates index deltas for a remove/delete operation.\n *\n * For each maintained index field, records a removal of the item's identifier from the\n * corresponding stringified key (skipping `null`/`undefined` values).\n * @param deltas - Accumulator of per-field index deltas.\n * @param indicesToMaintain - List of dot-paths for fields that are indexed.\n * @param existingItem - The item being removed.\n */\nexport function accumulateRemoveDelta(deltas, indicesToMaintain, existingItem) {\n for (const fieldPath of indicesToMaintain) {\n const value = get(existingItem, fieldPath);\n if (value == null)\n continue;\n addToDelta(deltas, fieldPath, 'remove', String(value), existingItem.id);\n }\n}\n","import { createStorageAdapter, get } from '@signaldb/core';\nimport { accumulateUpsertDelta, accumulateRemoveDelta, } from './deltaHelpers';\n/**\n * Creates a storage adapter for managing a SignalDB collection using a generic filesystem-like driver.\n * Data is sharded into subdirectories based on item identifiers, and indices are maintained as files.\n * @param driver - The driver that handles low-level file operations.\n * @param folderName - The root folder path for storing the collection data.\n * @returns A SignalDB storage adapter for managing data in a filesystem-like storage.\n */\nexport default function createGenericFSAdapter(driver, folderName) {\n const itemsDirectoryPathPromise = driver.joinPath(folderName, 'items');\n const indexRootPathPromise = driver.joinPath(folderName, 'index');\n const safeFileExists = async (path) => driver.fileExists(path).catch(() => false);\n const safeRemoveEntry = async (path, options) => driver.removeEntry(path, options).catch(() => { });\n const toItemsFilePath = async (identifier) => driver.joinPath(await itemsDirectoryPathPromise, await driver.fileNameForId(identifier));\n const toIndexPathForField = async (fieldPath) => driver.joinPath(await indexRootPathPromise, await driver.fileNameForIndexKey(fieldPath));\n const toIndexBucketFilePath = async (indexPath, rawKey) => {\n const bucketFileName = await driver.fileNameForIndexKey(rawKey);\n return driver.joinPath(indexPath, bucketFileName);\n };\n const readItemsArrayOrEmpty = async (filePath) => {\n const exists = await safeFileExists(filePath);\n if (!exists)\n return [];\n const data = await driver.readObject(filePath).catch(() => []);\n return Array.isArray(data) ? data : [];\n };\n const loadBucketIndexFromData = (data) => {\n const bucketIndex = new Map();\n if (!Array.isArray(data))\n return bucketIndex;\n for (const entry of data) {\n for (const [rawKey, identifierList] of Object.entries(entry)) {\n bucketIndex.set(rawKey, new Set(identifierList));\n }\n }\n return bucketIndex;\n };\n const writeBucketIndex = async (filePath, bucketIndex) => {\n if (bucketIndex.size === 0) {\n const exists = await safeFileExists(filePath);\n if (exists)\n await safeRemoveEntry(filePath);\n return;\n }\n const output = [];\n bucketIndex.forEach((identifierSet, rawKey) => {\n output.push({ [rawKey]: [...identifierSet] });\n });\n await driver.writeIndexObject(filePath, output);\n };\n const readBucketIndex = async (filePath) => {\n const data = await driver.readIndexObject(filePath).catch(() => null);\n return loadBucketIndexFromData(data);\n };\n const readAll = async () => {\n const itemsDirectoryPath = await itemsDirectoryPathPromise;\n const directoryExists = await safeFileExists(itemsDirectoryPath);\n if (!directoryExists)\n return [];\n const relativeFiles = await driver.listFilesRecursive(itemsDirectoryPath);\n const aggregatedItems = [];\n await Promise.all(relativeFiles.map(async (relativePath) => {\n const fullPath = await driver.joinPath(itemsDirectoryPath, relativePath);\n const itemsInFile = await driver.readObject(fullPath).catch(() => null);\n if (Array.isArray(itemsInFile))\n aggregatedItems.push(...itemsInFile);\n }));\n return aggregatedItems;\n };\n const ensureIndex = async (fieldPath, itemsPromise = readAll()) => {\n const allItems = await itemsPromise;\n const indexPath = await toIndexPathForField(fieldPath);\n await safeRemoveEntry(indexPath, { recursive: true });\n await driver.ensureDir(indexPath);\n // Build value -> Set<identifier>\n const indexMap = new Map();\n for (const item of allItems) {\n const fieldValue = get(item, fieldPath);\n if (fieldValue == null)\n continue;\n const keyString = String(fieldValue);\n if (!indexMap.has(keyString))\n indexMap.set(keyString, new Set());\n indexMap.get(keyString)?.add(item.id);\n }\n // Group entries by bucket file name, then persist each bucket\n const buckets = {};\n for (const [rawKeyString, identifierSet] of indexMap) {\n const bucketFileName = await driver.fileNameForIndexKey(rawKeyString);\n if (!buckets[bucketFileName])\n buckets[bucketFileName] = [];\n buckets[bucketFileName].push({ [rawKeyString]: [...identifierSet] });\n }\n await Promise.all(Object.entries(buckets).map(async ([bucketFileName, records]) => {\n const filePath = await driver.joinPath(indexPath, bucketFileName);\n await driver.writeIndexObject(filePath, records);\n }));\n };\n const readIndex = async (fieldPath) => {\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n throw new Error(`Index on field \"${fieldPath}\" does not exist`);\n const relativeFiles = await driver.listFilesRecursive(indexPath);\n const resultIndex = new Map();\n await Promise.all(relativeFiles.map(async (relativePath) => {\n const fullPath = await driver.joinPath(indexPath, relativePath);\n const maps = await driver.readIndexObject(fullPath).catch(() => null);\n if (!Array.isArray(maps))\n return;\n for (const entry of maps) {\n for (const [rawKey, identifierList] of Object.entries(entry)) {\n if (!resultIndex.has(rawKey))\n resultIndex.set(rawKey, new Set());\n const target = resultIndex.get(rawKey);\n for (const identifier of identifierList)\n target?.add(identifier);\n }\n }\n }));\n return resultIndex;\n };\n // Track which field paths should be kept up-to-date incrementally.\n const indicesToMaintain = [];\n const applyIndexDeltas = async (deltas) => {\n // For each indexed field with changes, touch only the affected bucket files\n await Promise.all([...deltas.entries()].map(async ([fieldPath, delta]) => {\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n return; // Only update indices that exist\n await driver.ensureDir(indexPath);\n // Compute impacted bucket filenames\n const touchedRawKeys = new Set([\n ...delta.adds.keys(),\n ...delta.removes.keys(),\n ]);\n const rawKeyToBucketFileName = new Map();\n await Promise.all([...touchedRawKeys].map(async (rawKey) => {\n rawKeyToBucketFileName.set(rawKey, await driver.fileNameForIndexKey(rawKey));\n }));\n const touchedBucketFileNames = new Set(rawKeyToBucketFileName.values());\n await Promise.all([...touchedBucketFileNames].map(async (bucketFileName) => {\n const filePath = await driver.joinPath(indexPath, bucketFileName);\n const bucketIndex = await readBucketIndex(filePath);\n // Apply removals for keys that map to this bucket\n delta.removes.forEach((identifierSet, rawKey) => {\n if (rawKeyToBucketFileName.get(rawKey) !== bucketFileName)\n return;\n const setForKey = bucketIndex.get(rawKey);\n if (!setForKey)\n return;\n identifierSet.forEach(identifier => setForKey.delete(identifier));\n if (setForKey.size === 0)\n bucketIndex.delete(rawKey);\n });\n // Apply additions\n delta.adds.forEach((identifierSet, rawKey) => {\n if (rawKeyToBucketFileName.get(rawKey) !== bucketFileName)\n return;\n const setForKey = bucketIndex.get(rawKey) ?? new Set();\n identifierSet.forEach(identifier => setForKey.add(identifier));\n bucketIndex.set(rawKey, setForKey);\n });\n await writeBucketIndex(filePath, bucketIndex);\n }));\n }));\n };\n const removeIdFromIndex = async (fieldPath, identifier) => {\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n return;\n const relativeFiles = await driver.listFilesRecursive(indexPath);\n await Promise.all(relativeFiles.map(async (relativePath) => {\n const filePath = await driver.joinPath(indexPath, relativePath);\n const data = await driver.readIndexObject(filePath).catch(() => null);\n if (!Array.isArray(data))\n return;\n let changed = false;\n const bucketIndex = new Map();\n for (const entry of data) {\n for (const [rawKey, identifierList] of Object.entries(entry)) {\n const set = new Set(identifierList);\n const before = set.size;\n set.delete(identifier);\n if (set.size !== before)\n changed = true;\n if (set.size > 0)\n bucketIndex.set(rawKey, set);\n }\n }\n if (!changed)\n return;\n await writeBucketIndex(filePath, bucketIndex);\n }));\n };\n const addIdToIndex = async (fieldPath, value, identifier) => {\n if (value == null)\n return;\n const rawKey = String(value);\n const indexPath = await toIndexPathForField(fieldPath);\n const indexExists = await safeFileExists(indexPath);\n if (!indexExists)\n return;\n await driver.ensureDir(indexPath);\n const filePath = await toIndexBucketFilePath(indexPath, rawKey);\n const bucketIndex = await readBucketIndex(filePath);\n const setForKey = bucketIndex.get(rawKey) ?? new Set();\n setForKey.add(identifier);\n bucketIndex.set(rawKey, setForKey);\n await writeBucketIndex(filePath, bucketIndex);\n };\n const updateIndexForReplace = async (oldItem, nextItem) => {\n await Promise.all(indicesToMaintain.map(async (fieldPath) => {\n await removeIdFromIndex(fieldPath, oldItem.id);\n const newValue = get(nextItem, fieldPath);\n await addIdToIndex(fieldPath, newValue, nextItem.id);\n }));\n };\n const upsertItems = async (items, mode) => {\n const deltas = new Map();\n await Promise.all(items.map(async (item) => {\n const filePath = await toItemsFilePath(item.id);\n const existingArray = await readItemsArrayOrEmpty(filePath);\n const indexOfItem = existingArray.findIndex(existing => existing.id === item.id);\n if (mode === 'insert') {\n if (indexOfItem !== -1)\n throw new Error(`Item with id \"${String(item.id)}\" already exists`);\n accumulateUpsertDelta(deltas, indicesToMaintain, undefined, item);\n await driver.writeObject(filePath, [...existingArray, item]);\n }\n else {\n if (indexOfItem === -1)\n throw new Error(`Item with id \"${String(item.id)}\" does not exist`);\n const updatedArray = [...existingArray];\n const oldItem = updatedArray[indexOfItem];\n updatedArray[indexOfItem] = item;\n await driver.writeObject(filePath, updatedArray);\n await updateIndexForReplace(oldItem, item);\n }\n }));\n // Only apply deltas for inserts (replace handled by direct purge+add)\n if (deltas.size > 0) {\n await applyIndexDeltas(deltas);\n }\n };\n return createStorageAdapter({\n setup: async () => {\n await driver.ensureDir(folderName);\n },\n teardown: async () => {\n // no-op\n },\n readAll,\n readIds: async (identifiers) => {\n const results = await Promise.all(identifiers.map(async (identifier) => {\n const filePath = await toItemsFilePath(identifier);\n const itemsInFile = await driver.readObject(filePath).catch(() => []) ?? [];\n if (!Array.isArray(itemsInFile))\n return null;\n return itemsInFile.find(item => item.id === identifier) ?? null;\n }));\n return results.filter((value) => value != null);\n },\n createIndex: async (fieldPath) => {\n if (fieldPath === 'id')\n throw new Error('Cannot create index on id field');\n indicesToMaintain.push(fieldPath);\n await ensureIndex(fieldPath);\n },\n dropIndex: async (fieldPath) => {\n const pathToDrop = await toIndexPathForField(fieldPath);\n const exists = await safeFileExists(pathToDrop);\n if (!exists)\n throw new Error(`Index on field \"${fieldPath}\" does not exist`);\n await driver.removeEntry(pathToDrop, { recursive: true });\n },\n readIndex,\n insert: async (itemsToInsert) => {\n await upsertItems(itemsToInsert, 'insert');\n },\n replace: async (itemsToReplace) => {\n await upsertItems(itemsToReplace, 'replace');\n },\n remove: async (itemsToRemove) => {\n const deltas = new Map();\n await Promise.all(itemsToRemove.map(async (item) => {\n const filePath = await toItemsFilePath(item.id);\n const existingArray = await readItemsArrayOrEmpty(filePath);\n const indexOfItem = existingArray.findIndex(existing => existing.id === item.id);\n if (indexOfItem === -1)\n throw new Error(`Item with id \"${String(item.id)}\" does not exist`);\n accumulateRemoveDelta(deltas, indicesToMaintain, existingArray[indexOfItem]);\n const updatedArray = [...existingArray];\n updatedArray.splice(indexOfItem, 1);\n await (updatedArray.length === 0\n ? driver.removeEntry(filePath).catch(() => { })\n : driver.writeObject(filePath, updatedArray));\n }));\n await applyIndexDeltas(deltas);\n },\n removeAll: async () => {\n const exists = await safeFileExists(folderName);\n if (!exists)\n return;\n await driver.removeEntry(folderName, { recursive: true });\n },\n });\n}\n"],"names":["addToDelta","deltas","fieldPath","changeKind","rawKey","identifier","delta","target","accumulateUpsertDelta","indicesToMaintain","existingItem","nextItem","value","get","accumulateRemoveDelta","createGenericFSAdapter","driver","folderName","itemsDirectoryPathPromise","indexRootPathPromise","safeFileExists","path","safeRemoveEntry","options","toItemsFilePath","toIndexPathForField","toIndexBucketFilePath","indexPath","bucketFileName","readItemsArrayOrEmpty","filePath","data","loadBucketIndexFromData","bucketIndex","entry","identifierList","writeBucketIndex","output","identifierSet","readBucketIndex","readAll","itemsDirectoryPath","relativeFiles","aggregatedItems","relativePath","fullPath","itemsInFile","ensureIndex","itemsPromise","allItems","indexMap","item","fieldValue","keyString","buckets","rawKeyString","records","readIndex","resultIndex","maps","applyIndexDeltas","touchedRawKeys","rawKeyToBucketFileName","touchedBucketFileNames","setForKey","removeIdFromIndex","changed","set","before","addIdToIndex","updateIndexForReplace","oldItem","newValue","upsertItems","items","mode","existingArray","indexOfItem","existing","updatedArray","createStorageAdapter","identifiers","pathToDrop","itemsToInsert","itemsToReplace","itemsToRemove"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signaldb/generic-fs",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "rimraf dist && vite build",
|
|
@@ -54,6 +54,6 @@
|
|
|
54
54
|
"dist"
|
|
55
55
|
],
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@signaldb/core": "2.0.0-beta.
|
|
57
|
+
"@signaldb/core": "2.0.0-beta.2"
|
|
58
58
|
}
|
|
59
59
|
}
|