@voltro/plugin-search 0.85.0 → 0.86.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,11 @@
1
1
  # Third-Party Notices — @voltro/plugin-search
2
2
 
3
- This package depends on the open-source software listed below. Each is the
3
+ This package uses the open-source software listed below. Each is the
4
4
  property of its respective copyright holders and is used under the terms of
5
5
  its license. This file is provided for attribution; it grants no rights in
6
6
  @voltro/plugin-search itself, which is proprietary (see LICENSE).
7
7
 
8
- Generated from the resolved runtime dependency closure (57 packages).
8
+ Generated from the resolved runtime dependency closure (56 packages).
9
9
 
10
10
  ---
11
11
 
@@ -863,7 +863,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
863
863
  SOFTWARE.
864
864
  ```
865
865
 
866
- ## follow-redirects@1.16.0
866
+ ## follow-redirects@1.16.1
867
867
 
868
868
  License: MIT
869
869
 
@@ -1142,34 +1142,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1142
1142
  SOFTWARE.
1143
1143
  ```
1144
1144
 
1145
- ## layerr@3.0.0
1146
-
1147
- License: MIT
1148
-
1149
- ```
1150
- MIT License
1151
-
1152
- Copyright (c) 2020 Perry Mitchell
1153
-
1154
- Permission is hereby granted, free of charge, to any person obtaining a copy
1155
- of this software and associated documentation files (the "Software"), to deal
1156
- in the Software without restriction, including without limitation the rights
1157
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1158
- copies of the Software, and to permit persons to whom the Software is
1159
- furnished to do so, subject to the following conditions:
1160
-
1161
- The above copyright notice and this permission notice shall be included in all
1162
- copies or substantial portions of the Software.
1163
-
1164
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1165
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1166
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1167
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1168
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1169
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1170
- SOFTWARE.
1171
- ```
1172
-
1173
1145
  ## loglevel@1.9.2
1174
1146
 
1175
1147
  License: MIT
@@ -1782,14 +1754,14 @@ Apache License
1782
1754
  limitations under the License.
1783
1755
  ```
1784
1756
 
1785
- ## ulidx@2.4.1
1757
+ ## ulid@3.0.2
1786
1758
 
1787
1759
  License: MIT
1788
1760
 
1789
1761
  ```
1790
- MIT License
1762
+ The MIT License (MIT)
1791
1763
 
1792
- Copyright (c) 2021 Perry Mitchell
1764
+ Copyright (c) 2017 Alizain Feerasta
1793
1765
 
1794
1766
  Permission is hereby granted, free of charge, to any person obtaining a copy
1795
1767
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,398 @@
1
+ import { isSafeFieldName as e, sanitizeEngineParams as t } from "./sanitize.js";
2
+ import { Data as n } from "effect";
3
+ //#region src/backend.ts
4
+ var r = class extends n.TaggedError("SearchBackendError") {}, i = (e) => Array.isArray(e) ? e : [e], a = (e, t, n) => {
5
+ if (Math.abs(e.length - t.length) > n) return !1;
6
+ if (e === t) return !0;
7
+ if (Number.isNaN(n)) return !1;
8
+ let r = t.length, i = Math.floor(n), a = Array(r + 1).fill(Infinity), o = Array(r + 1).fill(Infinity);
9
+ for (let e = 0; e <= Math.min(r, i); e++) a[e] = e;
10
+ for (let s = 1; s <= e.length; s++) {
11
+ let c = Math.max(1, s - i), l = Math.min(r, s + i);
12
+ o[0] = s, c > 1 && (o[c - 1] = Infinity), l < r && (o[l + 1] = Infinity);
13
+ let u = s, d = e.charCodeAt(s - 1);
14
+ for (let e = c; e <= l; e++) {
15
+ let n = d === t.charCodeAt(e - 1) ? 0 : 1, r = Math.min(a[e] + 1, o[e - 1] + 1, a[e - 1] + n);
16
+ o[e] = r, u = Math.min(u, r);
17
+ }
18
+ if (u > n) return !1;
19
+ let f = a;
20
+ a = o, o = f;
21
+ }
22
+ return a[r] <= n;
23
+ }, o = (e) => e.length <= 4 ? 1 : 2, s = () => {
24
+ let e = /* @__PURE__ */ new Map(), t = (t) => {
25
+ let n = e.get(t);
26
+ return n || (n = /* @__PURE__ */ new Map(), e.set(t, n)), n;
27
+ }, n = (e, t) => {
28
+ let n = e[t.field];
29
+ switch (t.op) {
30
+ case "eq": return String(n) === String(t.value);
31
+ case "neq": return String(n) !== String(t.value);
32
+ case "in": return i(t.value).some((e) => String(n) === String(e));
33
+ case "nin": return i(t.value).every((e) => String(n) !== String(e));
34
+ case "gt":
35
+ case "gte":
36
+ case "lt":
37
+ case "lte": {
38
+ let [e, r] = [c(n), c(t.value)];
39
+ return e === void 0 || r === void 0 ? !1 : t.op === "gt" ? e > r : t.op === "gte" ? e >= r : t.op === "lt" ? e < r : e <= r;
40
+ }
41
+ }
42
+ }, r = (e, t) => !t || t.every((t) => n(e, t)), s = (e) => Object.entries(e).filter(([e]) => e !== "id").map(([e, t]) => [e, String(t)]), l = (e, t, n) => {
43
+ if (t.length === 0) return !0;
44
+ for (let [, r] of s(e)) {
45
+ let e = r.toLowerCase();
46
+ if (e.includes(t)) return !0;
47
+ if (n !== void 0 && n !== 0) {
48
+ let r = n === "auto" ? o(t) : n;
49
+ for (let n of e.split(/\s+/)) if (a(n, t, r)) return !0;
50
+ }
51
+ }
52
+ return !1;
53
+ }, u = (e, t, n) => {
54
+ if (t.length === 0) return {};
55
+ let r = n.preTag ?? "<mark>", i = n.postTag ?? "</mark>", a = n.fields && n.fields.length > 0 ? new Set(n.fields) : null, o = {}, c = new RegExp(t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi");
56
+ for (let [n, l] of s(e)) (!a || a.has(n)) && l.toLowerCase().includes(t) && (o[n] = l.replace(c, (e) => `${r}${e}${i}`));
57
+ return o;
58
+ };
59
+ return {
60
+ engineKind: "memory",
61
+ upsert: async (e, n) => {
62
+ let r = t(e);
63
+ for (let e of n) r.set(e.id, e);
64
+ },
65
+ remove: async (e, n) => {
66
+ let r = t(e);
67
+ for (let e of n) r.delete(e);
68
+ },
69
+ query: async (e, { q: n, limit: i, offset: a, filters: o, facets: s, highlight: c, fuzziness: d }) => {
70
+ let f = n.trim().toLowerCase(), p = [];
71
+ for (let n of t(e).values()) r(n, o) && l(n, f, d) && p.push(n);
72
+ let m = {};
73
+ if (s) for (let e of s) {
74
+ let t = {};
75
+ for (let n of p) {
76
+ let r = n[e];
77
+ if (r == null) continue;
78
+ let i = String(r);
79
+ t[i] = (t[i] ?? 0) + 1;
80
+ }
81
+ m[e] = t;
82
+ }
83
+ let h = a ?? 0;
84
+ return {
85
+ hits: (i === void 0 ? p.slice(h) : p.slice(h, h + i)).map((e) => c ? {
86
+ doc: e,
87
+ highlights: u(e, f, c)
88
+ } : { doc: e }),
89
+ facets: m
90
+ };
91
+ }
92
+ };
93
+ }, c = (e) => {
94
+ if (typeof e == "number") return e;
95
+ if (typeof e == "boolean") return +!!e;
96
+ if (typeof e == "string") {
97
+ let t = Number(e);
98
+ if (!Number.isNaN(t) && e.trim() !== "") return t;
99
+ let n = Date.parse(e);
100
+ return Number.isNaN(n) ? void 0 : n;
101
+ }
102
+ }, l = async (e, t, n) => {
103
+ try {
104
+ return await n();
105
+ } catch {
106
+ throw new r({
107
+ engine: t,
108
+ op: "query",
109
+ message: `the '${t}' search backend requires the '${e}' optional dependency. Install it to enable it (e.g. \`npm i ${e}\`).`,
110
+ transient: !1
111
+ });
112
+ }
113
+ }, u = (e, n) => (r) => {
114
+ let { params: i, appAllowed: a, dropped: o } = t(e, r, n.allowEngineParams);
115
+ return o.length > 0 && n.onWarn?.("search dropped disallowed engineParams", {
116
+ engine: e,
117
+ keys: o
118
+ }), {
119
+ before: i,
120
+ after: a
121
+ };
122
+ }, d = (t, n) => {
123
+ if (!e(n)) throw new r({
124
+ engine: t,
125
+ op: "query",
126
+ message: `filter field "${n}" is not a plain field path (^[A-Za-z_][A-Za-z0-9_.]*$)`,
127
+ transient: !1
128
+ });
129
+ return n;
130
+ }, f = (e) => {
131
+ let t = (e) => JSON.stringify(e), n = d("typesense", e.field);
132
+ switch (e.op) {
133
+ case "eq": return `${n}:=${t(e.value)}`;
134
+ case "neq": return `${n}:!=${t(e.value)}`;
135
+ case "gt": return `${n}:>${t(e.value)}`;
136
+ case "gte": return `${n}:>=${t(e.value)}`;
137
+ case "lt": return `${n}:<${t(e.value)}`;
138
+ case "lte": return `${n}:<=${t(e.value)}`;
139
+ case "in": return `${n}:[${i(e.value).map(t).join(",")}]`;
140
+ case "nin": return `${n}:!=[${i(e.value).map(t).join(",")}]`;
141
+ }
142
+ }, p = (e, t = {}) => {
143
+ let n = u("typesense", t), i, a = async () => (i ||= l("typesense", "typesense", () => import("typesense")).then((t) => {
144
+ let n = t.Client;
145
+ return new n({
146
+ nodes: [{ url: e.url ?? e.host ?? "http://localhost:8108" }],
147
+ apiKey: e.apiKey
148
+ });
149
+ }), i), o = (e) => e && e.length > 0 ? e.map(f).join(" && ") : void 0, s = async (e, t) => {
150
+ try {
151
+ return await t();
152
+ } catch (t) {
153
+ throw t instanceof r ? t : new r({
154
+ engine: "typesense",
155
+ op: e,
156
+ message: String(t?.message ?? t),
157
+ transient: !0
158
+ });
159
+ }
160
+ };
161
+ return {
162
+ upsert: (e, t) => s("upsert", async () => {
163
+ await (await a()).collections(e).documents().import(t, { action: "upsert" });
164
+ }),
165
+ remove: (e, t) => s("remove", async () => {
166
+ await (await a()).collections(e).documents().delete({ filter_by: `id:[${t.map((e) => JSON.stringify(e)).join(",")}]` });
167
+ }),
168
+ query: (e, { q: t, limit: r, offset: i, filters: c, facets: l, highlight: u, fuzziness: d, engineParams: f }) => s("query", async () => {
169
+ let s = await a(), p = n(f), h = {
170
+ ...p.before,
171
+ q: t || "*",
172
+ query_by: "*",
173
+ per_page: r ?? 20,
174
+ ...i ? { offset: i } : {},
175
+ ...o(c) ? { filter_by: o(c) } : {},
176
+ ...l && l.length > 0 ? { facet_by: l.join(",") } : {},
177
+ ...u ? {
178
+ ...u.fields && u.fields.length > 0 ? { highlight_fields: u.fields.join(",") } : { highlight_full_fields: "*" },
179
+ ...u.preTag ? { highlight_start_tag: u.preTag } : {},
180
+ ...u.postTag ? { highlight_end_tag: u.postTag } : {}
181
+ } : {},
182
+ ...d !== void 0 && d !== "auto" ? { num_typos: Math.min(2, Math.max(0, d)) } : {},
183
+ ...p.after
184
+ };
185
+ return m(await s.collections(e).documents().search(h));
186
+ })
187
+ };
188
+ }, m = (e) => {
189
+ let t = (e.hits ?? []).map((e) => {
190
+ let t = {};
191
+ for (let n of e.highlights ?? []) {
192
+ let e = n.snippet ?? n.value;
193
+ e && (t[n.field] = e);
194
+ }
195
+ return Object.keys(t).length > 0 ? {
196
+ doc: e.document,
197
+ highlights: t
198
+ } : { doc: e.document };
199
+ }), n = {};
200
+ for (let t of e.facet_counts ?? []) n[t.field_name] = Object.fromEntries(t.counts.map((e) => [e.value, e.count]));
201
+ return {
202
+ hits: t,
203
+ facets: n
204
+ };
205
+ }, h = (e) => {
206
+ let t = (e) => JSON.stringify(e), n = d("meilisearch", e.field);
207
+ switch (e.op) {
208
+ case "eq": return `${n} = ${t(e.value)}`;
209
+ case "neq": return `${n} != ${t(e.value)}`;
210
+ case "gt": return `${n} > ${t(e.value)}`;
211
+ case "gte": return `${n} >= ${t(e.value)}`;
212
+ case "lt": return `${n} < ${t(e.value)}`;
213
+ case "lte": return `${n} <= ${t(e.value)}`;
214
+ case "in": return `${n} IN [${i(e.value).map(t).join(", ")}]`;
215
+ case "nin": return `${n} NOT IN [${i(e.value).map(t).join(", ")}]`;
216
+ }
217
+ }, g = (e, t = {}) => {
218
+ let n = u("meilisearch", t), i, a = async () => (i ||= l("meilisearch", "meilisearch", () => import("meilisearch")).then((t) => new t.Meilisearch({
219
+ host: e.host ?? e.url ?? "http://localhost:7700",
220
+ apiKey: e.apiKey
221
+ })), i), o = (e) => e && e.length > 0 ? e.map(h) : void 0, s = async (e, t) => {
222
+ try {
223
+ return await t();
224
+ } catch (t) {
225
+ throw t instanceof r ? t : new r({
226
+ engine: "meilisearch",
227
+ op: e,
228
+ message: String(t?.message ?? t),
229
+ transient: !0
230
+ });
231
+ }
232
+ }, c = async (e, t) => {
233
+ let n = await (await a()).tasks.waitForTask(t, {
234
+ timeout: 6e4,
235
+ interval: 50
236
+ });
237
+ if (n.status !== "succeeded") throw new r({
238
+ engine: "meilisearch",
239
+ op: e,
240
+ message: n.error?.message ?? `Meilisearch task ${t.taskUid} ${n.status}`,
241
+ transient: n.status === "canceled"
242
+ });
243
+ };
244
+ return {
245
+ upsert: (e, t) => s("upsert", async () => {
246
+ await c("upsert", await (await a()).index(e).addDocuments([...t]));
247
+ }),
248
+ remove: (e, t) => s("remove", async () => {
249
+ await c("remove", await (await a()).index(e).deleteDocuments([...t]));
250
+ }),
251
+ query: (e, { q: t, limit: r, offset: i, filters: c, facets: l, highlight: u, fuzziness: d, engineParams: f }) => s("query", async () => {
252
+ let s = n(f), p = {
253
+ ...s.before,
254
+ limit: r ?? 20,
255
+ ...i ? { offset: i } : {},
256
+ ...o(c) ? { filter: o(c) } : {},
257
+ ...l && l.length > 0 ? { facets: [...l] } : {},
258
+ ...u ? {
259
+ attributesToHighlight: u.fields && u.fields.length > 0 ? [...u.fields] : ["*"],
260
+ ...u.preTag ? { highlightPreTag: u.preTag } : {},
261
+ ...u.postTag ? { highlightPostTag: u.postTag } : {}
262
+ } : {},
263
+ ...d === 0 ? {
264
+ rankingScoreThreshold: void 0,
265
+ typoTolerance: { enabled: !1 }
266
+ } : {},
267
+ ...s.after
268
+ };
269
+ return _(await (await a()).index(e).search(t, p), u);
270
+ })
271
+ };
272
+ }, _ = (e, t) => ({
273
+ hits: e.hits.map((e) => {
274
+ let { _formatted: n, ...r } = e;
275
+ if (t && n) {
276
+ let e = {};
277
+ for (let [t, r] of Object.entries(n)) t !== "id" && (e[t] = String(r));
278
+ return Object.keys(e).length > 0 ? {
279
+ doc: r,
280
+ highlights: e
281
+ } : { doc: r };
282
+ }
283
+ return { doc: r };
284
+ }),
285
+ facets: e.facetDistribution ?? {}
286
+ }), v = (e) => String(e).replace(/^-/, "\\-"), y = (e, t) => {
287
+ let n = typeof t == "boolean" ? +!!t : Number(t);
288
+ if (!Number.isFinite(n)) throw new r({
289
+ engine: "algolia",
290
+ op: "query",
291
+ message: `range filter on "${e}" needs a numeric value (got ${JSON.stringify(t)})`,
292
+ transient: !1
293
+ });
294
+ return n;
295
+ }, b = (e) => {
296
+ let t = [], n = [];
297
+ for (let r of e ?? []) {
298
+ let e = d("algolia", r.field), a = (e) => v(e), o = (t) => y(e, t);
299
+ switch (r.op) {
300
+ case "eq":
301
+ t.push(`${e}:${a(r.value)}`);
302
+ break;
303
+ case "neq":
304
+ t.push(`${e}:-${a(r.value)}`);
305
+ break;
306
+ case "in":
307
+ t.push(i(r.value).map((t) => `${e}:${a(t)}`));
308
+ break;
309
+ case "nin":
310
+ for (let n of i(r.value)) t.push(`${e}:-${a(n)}`);
311
+ break;
312
+ case "gt":
313
+ n.push(`${e} > ${o(r.value)}`);
314
+ break;
315
+ case "gte":
316
+ n.push(`${e} >= ${o(r.value)}`);
317
+ break;
318
+ case "lt":
319
+ n.push(`${e} < ${o(r.value)}`);
320
+ break;
321
+ case "lte": n.push(`${e} <= ${o(r.value)}`);
322
+ }
323
+ }
324
+ return {
325
+ facetFilters: t,
326
+ numericFilters: n
327
+ };
328
+ }, x = (e, t = {}) => {
329
+ let n = u("algolia", t), i, a = async () => (i ||= l("algoliasearch", "algolia", () => import("algoliasearch")).then((t) => t.algoliasearch(e.appId ?? "", e.apiKey)), i), o = async (e, t) => {
330
+ try {
331
+ return await t();
332
+ } catch (t) {
333
+ throw t instanceof r ? t : new r({
334
+ engine: "algolia",
335
+ op: e,
336
+ message: String(t?.message ?? t),
337
+ transient: !0
338
+ });
339
+ }
340
+ };
341
+ return {
342
+ upsert: (e, t) => o("upsert", async () => {
343
+ await (await a()).saveObjects({
344
+ indexName: e,
345
+ objects: t.map((e) => ({
346
+ ...e,
347
+ objectID: e.id
348
+ }))
349
+ });
350
+ }),
351
+ remove: (e, t) => o("remove", async () => {
352
+ await (await a()).deleteObjects({
353
+ indexName: e,
354
+ objectIDs: [...t]
355
+ });
356
+ }),
357
+ query: (e, { q: t, limit: r, offset: i, filters: s, facets: c, highlight: l, fuzziness: u, engineParams: d }) => o("query", async () => {
358
+ let { facetFilters: o, numericFilters: f } = b(s), p = i ? {
359
+ offset: i,
360
+ length: r ?? 20
361
+ } : { hitsPerPage: r ?? 20 }, m = n(d), h = {
362
+ ...m.before,
363
+ query: t,
364
+ ...p,
365
+ ...o.length > 0 ? { facetFilters: o } : {},
366
+ ...f.length > 0 ? { numericFilters: f } : {},
367
+ ...c && c.length > 0 ? { facets: [...c] } : {},
368
+ ...l ? {
369
+ ...l.fields && l.fields.length > 0 ? { attributesToHighlight: [...l.fields] } : {},
370
+ ...l.preTag ? { highlightPreTag: l.preTag } : {},
371
+ ...l.postTag ? { highlightPostTag: l.postTag } : {}
372
+ } : {},
373
+ ...u === 0 ? { typoTolerance: !1 } : {},
374
+ ...m.after
375
+ };
376
+ return S(await (await a()).searchSingleIndex({
377
+ indexName: e,
378
+ searchParams: h
379
+ }), l);
380
+ })
381
+ };
382
+ }, S = (e, t) => ({
383
+ hits: e.hits.map((e) => {
384
+ let { _highlightResult: n, ...r } = e;
385
+ if (t && n) {
386
+ let e = {};
387
+ for (let [t, r] of Object.entries(n)) t !== "id" && r?.value && (e[t] = r.value);
388
+ return Object.keys(e).length > 0 ? {
389
+ doc: r,
390
+ highlights: e
391
+ } : { doc: r };
392
+ }
393
+ return { doc: r };
394
+ }),
395
+ facets: e.facets ?? {}
396
+ });
397
+ //#endregion
398
+ export { r as SearchBackendError, x as algoliaBackend, a as editDistanceWithin, g as meilisearchBackend, s as memoryBackend, p as typesenseBackend };
package/dist/drift.js ADDED
@@ -0,0 +1,121 @@
1
+ import { and as e, count as t, eq as n, id as r, integer as i, table as a, text as o, timestamp as s } from "@voltro/database";
2
+ //#region src/drift.ts
3
+ var c = "_voltro_search_drift", l = a(c, {
4
+ id: r({ prefix: "sdrft" }),
5
+ indexName: o().maxLength(191),
6
+ sourceTable: o().maxLength(191),
7
+ rowId: o().maxLength(191),
8
+ docId: o().maxLength(191),
9
+ op: o().maxLength(16),
10
+ attempts: i().default(0),
11
+ lastError: o().maxLength(1e3),
12
+ firstFailedAt: s(),
13
+ lastFailedAt: s()
14
+ }).unique("bySearchDriftIndexRow", ["indexName", "rowId"]).index("bySearchDriftIndex", ["indexName"]), u = (e, t) => ({
15
+ table: e,
16
+ predicate: n("id", t),
17
+ order: [],
18
+ take: 1,
19
+ skip: void 0,
20
+ projection: void 0
21
+ }), d = (e) => e ? new Date(e).toISOString() : (/* @__PURE__ */ new Date(0)).toISOString(), f = (e) => ({
22
+ indexName: String(e.indexName),
23
+ sourceTable: String(e.sourceTable),
24
+ rowId: String(e.rowId),
25
+ docId: String(e.docId),
26
+ op: e.op === "remove" ? "remove" : "upsert",
27
+ attempts: Number(e.attempts ?? 0),
28
+ lastError: String(e.lastError ?? ""),
29
+ firstFailedAt: d(e.firstFailedAt),
30
+ lastFailedAt: d(e.lastFailedAt)
31
+ }), p = () => {
32
+ let e = /* @__PURE__ */ new Map(), t = (e, t) => `${e}\u0000${t}`;
33
+ return {
34
+ record: async (n) => {
35
+ let r = (/* @__PURE__ */ new Date()).toISOString(), i = e.get(t(n.indexName, n.rowId));
36
+ e.set(t(n.indexName, n.rowId), {
37
+ indexName: n.indexName,
38
+ sourceTable: n.sourceTable,
39
+ rowId: n.rowId,
40
+ docId: n.docId,
41
+ op: n.op,
42
+ attempts: (i?.attempts ?? 0) + 1,
43
+ lastError: n.error,
44
+ firstFailedAt: i?.firstFailedAt ?? r,
45
+ lastFailedAt: r
46
+ });
47
+ },
48
+ list: async (t) => [...e.values()].sort((e, t) => e.firstFailedAt.localeCompare(t.firstFailedAt)).slice(0, t),
49
+ summary: async (t) => {
50
+ let n = [...e.values()].filter((e) => e.indexName === t), r = null;
51
+ for (let e of n) (r === null || e.lastFailedAt > r) && (r = e.lastFailedAt);
52
+ return {
53
+ pending: n.length,
54
+ lastFailedAt: r
55
+ };
56
+ },
57
+ clear: async (n, r) => {
58
+ e.delete(t(n, r));
59
+ }
60
+ };
61
+ }, m = () => `sdrft_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`, h = (e, t) => ({
62
+ table: c,
63
+ predicate: e,
64
+ order: [{
65
+ column: "firstFailedAt",
66
+ direction: "asc"
67
+ }],
68
+ take: t,
69
+ skip: void 0,
70
+ projection: void 0
71
+ }), g = (r) => ({
72
+ record: async (e) => {
73
+ let t = /* @__PURE__ */ new Date(), i = m(), a = await r.insertIgnore(c, {
74
+ id: i,
75
+ indexName: e.indexName,
76
+ sourceTable: e.sourceTable,
77
+ rowId: e.rowId,
78
+ docId: e.docId,
79
+ op: e.op,
80
+ attempts: 1,
81
+ lastError: e.error.slice(0, 1e3),
82
+ firstFailedAt: t,
83
+ lastFailedAt: t
84
+ }, { conflictColumns: ["indexName", "rowId"] });
85
+ String(a.id) !== i && await r.updateMany(c, {
86
+ attempts: Number(a.attempts ?? 0) + 1,
87
+ op: e.op,
88
+ docId: e.docId,
89
+ lastError: e.error.slice(0, 1e3),
90
+ lastFailedAt: t
91
+ }, { where: n("id", String(a.id)) });
92
+ },
93
+ list: async (e) => (await r.query(h(void 0, e))).map(f),
94
+ summary: async (e) => {
95
+ let i = (await r.query({
96
+ ...h(n("indexName", e), void 0),
97
+ order: [],
98
+ aggregations: [t("n")]
99
+ }))[0], a = Number(i?.n ?? i?.count ?? 0);
100
+ if (a === 0) return {
101
+ pending: 0,
102
+ lastFailedAt: null
103
+ };
104
+ let o = await r.query({
105
+ ...h(n("indexName", e), 1),
106
+ order: [{
107
+ column: "lastFailedAt",
108
+ direction: "desc"
109
+ }]
110
+ });
111
+ return {
112
+ pending: a,
113
+ lastFailedAt: o[0] ? d(o[0].lastFailedAt) : null
114
+ };
115
+ },
116
+ clear: async (t, i) => {
117
+ await r.deleteMany(c, { where: e(n("indexName", t), n("rowId", i)) });
118
+ }
119
+ }), _ = () => [l];
120
+ //#endregion
121
+ export { c as SEARCH_DRIFT_TABLE, g as dataStoreDriftLedger, u as driftSourceQuery, _ as driftTables, p as memoryDriftLedger, l as searchDriftTable };
package/dist/errors.js ADDED
@@ -0,0 +1,13 @@
1
+ import { Schema as e } from "effect";
2
+ //#region src/errors.ts
3
+ var t = class extends e.TaggedError()("SearchIndexNotFound", { index: e.String }) {}, n = class extends e.TaggedError()("SearchFieldRejected", {
4
+ field: e.String,
5
+ where: e.Literals([
6
+ "filter",
7
+ "facet",
8
+ "highlight"
9
+ ]),
10
+ reason: e.Literals(["not-an-identifier", "not-queryable"])
11
+ }) {};
12
+ //#endregion
13
+ export { n as SearchFieldRejected, t as SearchIndexNotFound };