@voltro/plugin-search 0.55.0 → 0.57.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.
Files changed (3) hide show
  1. package/CHANGELOG.md +691 -0
  2. package/dist/index.js +114 -113
  3. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -2,8 +2,9 @@ import { a as e, i as t, o as n, r, t as i } from "./rpc-CpryHBcM.js";
2
2
  import { Cause as a, Chunk as o, Data as s, Duration as c, Effect as l, Exit as u, Option as d, Schedule as f, Stream as p } from "effect";
3
3
  import { and as m, count as h, eq as g, id as _, integer as v, streamTable as y, table as b, text as x, timestamp as S } from "@voltro/database";
4
4
  import { definePlugin as ee, pluginInstanceName as te } from "@voltro/protocol";
5
+ import { replicaId as ne } from "@voltro/protocol/identity";
5
6
  //#region src/sanitize.ts
6
- var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
7
+ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), re = (e, t) => {
7
8
  let n = t ? new Set(t) : void 0;
8
9
  for (let [t, r] of e) {
9
10
  if (!w(r)) return {
@@ -244,7 +245,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
244
245
  transient: !1
245
246
  });
246
247
  return t;
247
- }, re = (e) => {
248
+ }, ie = (e) => {
248
249
  let t = (e) => JSON.stringify(e), n = L("typesense", e.field);
249
250
  switch (e.op) {
250
251
  case "eq": return `${n}:=${t(e.value)}`;
@@ -256,14 +257,14 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
256
257
  case "in": return `${n}:[${A(e.value).map(t).join(",")}]`;
257
258
  case "nin": return `${n}:!=[${A(e.value).map(t).join(",")}]`;
258
259
  }
259
- }, ie = (e, t = {}) => {
260
+ }, ae = (e, t = {}) => {
260
261
  let n = I("typesense", t), r, i = async () => (r ||= F("typesense", "typesense", () => import("typesense")).then((t) => {
261
262
  let n = t.Client;
262
263
  return new n({
263
264
  nodes: [{ url: e.url ?? e.host ?? "http://localhost:8108" }],
264
265
  apiKey: e.apiKey
265
266
  });
266
- }), r), a = (e) => e && e.length > 0 ? e.map(re).join(" && ") : void 0, o = async (e, t) => {
267
+ }), r), a = (e) => e && e.length > 0 ? e.map(ie).join(" && ") : void 0, o = async (e, t) => {
267
268
  try {
268
269
  return await t();
269
270
  } catch (t) {
@@ -299,10 +300,10 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
299
300
  ...d !== void 0 && d !== "auto" ? { num_typos: Math.min(2, Math.max(0, d)) } : {},
300
301
  ...p.after
301
302
  };
302
- return ae(await o.collections(e).documents().search(m));
303
+ return oe(await o.collections(e).documents().search(m));
303
304
  })
304
305
  };
305
- }, ae = (e) => {
306
+ }, oe = (e) => {
306
307
  let t = (e.hits ?? []).map((e) => {
307
308
  let t = {};
308
309
  for (let n of e.highlights ?? []) {
@@ -319,7 +320,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
319
320
  hits: t,
320
321
  facets: n
321
322
  };
322
- }, oe = (e) => {
323
+ }, se = (e) => {
323
324
  let t = (e) => JSON.stringify(e), n = L("meilisearch", e.field);
324
325
  switch (e.op) {
325
326
  case "eq": return `${n} = ${t(e.value)}`;
@@ -331,11 +332,11 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
331
332
  case "in": return `${n} IN [${A(e.value).map(t).join(", ")}]`;
332
333
  case "nin": return `${n} NOT IN [${A(e.value).map(t).join(", ")}]`;
333
334
  }
334
- }, R = (e, t = {}) => {
335
+ }, ce = (e, t = {}) => {
335
336
  let n = I("meilisearch", t), r, i = async () => (r ||= F("meilisearch", "meilisearch", () => import("meilisearch")).then((t) => new t.MeiliSearch({
336
337
  host: e.host ?? e.url ?? "http://localhost:7700",
337
338
  apiKey: e.apiKey
338
- })), r), a = (e) => e && e.length > 0 ? e.map(oe) : void 0, o = async (e, t) => {
339
+ })), r), a = (e) => e && e.length > 0 ? e.map(se) : void 0, o = async (e, t) => {
339
340
  try {
340
341
  return await t();
341
342
  } catch (t) {
@@ -372,10 +373,10 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
372
373
  } : {},
373
374
  ...o.after
374
375
  };
375
- return se(await (await i()).index(e).search(t, p), u);
376
+ return le(await (await i()).index(e).search(t, p), u);
376
377
  })
377
378
  };
378
- }, se = (e, t) => ({
379
+ }, le = (e, t) => ({
379
380
  hits: e.hits.map((e) => {
380
381
  let { _formatted: n, ...r } = e;
381
382
  if (t && n) {
@@ -389,7 +390,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
389
390
  return { doc: r };
390
391
  }),
391
392
  facets: e.facetDistribution ?? {}
392
- }), ce = (e) => String(e).replace(/^-/, "\\-"), le = (e, t) => {
393
+ }), ue = (e) => String(e).replace(/^-/, "\\-"), de = (e, t) => {
393
394
  let n = typeof t == "boolean" ? +!!t : Number(t);
394
395
  if (!Number.isFinite(n)) throw new k({
395
396
  engine: "algolia",
@@ -398,10 +399,10 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
398
399
  transient: !1
399
400
  });
400
401
  return n;
401
- }, ue = (e) => {
402
+ }, fe = (e) => {
402
403
  let t = [], n = [];
403
404
  for (let r of e ?? []) {
404
- let e = L("algolia", r.field), i = (e) => ce(e), a = (t) => le(e, t);
405
+ let e = L("algolia", r.field), i = (e) => ue(e), a = (t) => de(e, t);
405
406
  switch (r.op) {
406
407
  case "eq":
407
408
  t.push(`${e}:${i(r.value)}`);
@@ -431,7 +432,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
431
432
  facetFilters: t,
432
433
  numericFilters: n
433
434
  };
434
- }, z = (e, t = {}) => {
435
+ }, pe = (e, t = {}) => {
435
436
  let n = I("algolia", t), r, i = async () => (r ||= F("algoliasearch", "algolia", () => import("algoliasearch")).then((t) => t.algoliasearch(e.appId ?? "", e.apiKey)), r), a = async (e, t) => {
436
437
  try {
437
438
  return await t();
@@ -461,7 +462,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
461
462
  });
462
463
  }),
463
464
  query: (e, { q: t, limit: r, offset: o, filters: s, facets: c, highlight: l, fuzziness: u, engineParams: d }) => a("query", async () => {
464
- let { facetFilters: a, numericFilters: f } = ue(s), p = o ? {
465
+ let { facetFilters: a, numericFilters: f } = fe(s), p = o ? {
465
466
  offset: o,
466
467
  length: r ?? 20
467
468
  } : { hitsPerPage: r ?? 20 }, m = n(d), h = {
@@ -479,13 +480,13 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
479
480
  ...u === 0 ? { typoTolerance: !1 } : {},
480
481
  ...m.after
481
482
  };
482
- return de(await (await i()).searchSingleIndex({
483
+ return me(await (await i()).searchSingleIndex({
483
484
  indexName: e,
484
485
  searchParams: h
485
486
  }), l);
486
487
  })
487
488
  };
488
- }, de = (e, t) => ({
489
+ }, me = (e, t) => ({
489
490
  hits: e.hits.map((e) => {
490
491
  let { _highlightResult: n, ...r } = e;
491
492
  if (t && n) {
@@ -499,13 +500,13 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
499
500
  return { doc: r };
500
501
  }),
501
502
  facets: e.facets ?? {}
502
- }), B = "_voltro_search_stats", V = () => ({
503
+ }), R = "_voltro_search_stats", he = () => ({
503
504
  synced: 0,
504
505
  removed: 0,
505
506
  dropped: 0,
506
507
  lastReindexAt: null,
507
508
  lastReindexCount: 0
508
- }), H = b(B, {
509
+ }), ge = b(R, {
509
510
  id: _({ prefix: "sstat" }),
510
511
  indexName: x().maxLength(191),
511
512
  replicaId: x().maxLength(191),
@@ -516,8 +517,8 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
516
517
  lastReindexAt: S().nullable(),
517
518
  lastReindexCount: v().default(0),
518
519
  updatedAt: S()
519
- }).unique("bySearchStatsIndexReplica", ["indexName", "replicaId"]).index("bySearchStatsIndex", ["indexName"]), U = () => [H], W = () => {
520
- let e = /* @__PURE__ */ new Map(), t = (t) => e.get(t) ?? V();
520
+ }).unique("bySearchStatsIndexReplica", ["indexName", "replicaId"]).index("bySearchStatsIndex", ["indexName"]), z = () => [ge], B = () => {
521
+ let e = /* @__PURE__ */ new Map(), t = (t) => e.get(t) ?? he();
521
522
  return {
522
523
  bump: async (n, r) => {
523
524
  let i = t(n);
@@ -552,15 +553,15 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
552
553
  },
553
554
  get: async (e) => t(e)
554
555
  };
555
- }, G = (e) => ({
556
- table: B,
556
+ }, V = (e) => ({
557
+ table: R,
557
558
  predicate: e,
558
559
  order: [],
559
560
  take: void 0,
560
561
  skip: void 0,
561
562
  projection: void 0
562
- }), fe = () => `sstat_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`, pe = () => process.env.VOLTRO_REPLICA_ID ?? process.env.HOSTNAME ?? process.env.POD_NAME ?? `pid_${process.pid}_${Math.random().toString(36).slice(2, 8)}`, K = 32, q = (e, t = pe()) => {
563
- let n = async (n) => (await e.query(G(m(g("indexName", n), g("replicaId", t)))))[0] ?? null, r = async (e) => {
563
+ }), _e = () => `sstat_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`, ve = () => ne(), H = 32, U = (e, t = ve()) => {
564
+ let n = async (n) => (await e.query(V(m(g("indexName", n), g("replicaId", t)))))[0] ?? null, r = async (e) => {
564
565
  try {
565
566
  return await e();
566
567
  } catch (e) {
@@ -572,7 +573,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
572
573
  });
573
574
  }
574
575
  }, i = (i, a, o, s) => r(async () => {
575
- for (let r = 0; r < K; r++) {
576
+ for (let r = 0; r < H; r++) {
576
577
  r > 0 && await new Promise((e) => setTimeout(e, r));
577
578
  let c = await n(i);
578
579
  if (c) {
@@ -589,7 +590,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
589
590
  updatedAt: /* @__PURE__ */ new Date()
590
591
  }, { where: m(g("id", String(c.id)), g("synced", t), g("removed", n), g("dropped", r)) }) === 1) return;
591
592
  } else {
592
- let n = fe(), r = await e.insertIgnore(B, {
593
+ let n = _e(), r = await e.insertIgnore(R, {
593
594
  id: n,
594
595
  indexName: i,
595
596
  replicaId: t,
@@ -608,7 +609,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
608
609
  throw new k({
609
610
  engine: "stats",
610
611
  op: "upsert",
611
- message: `search stats: contention on (${i}, ${t}) exceeded ${K} attempts`,
612
+ message: `search stats: contention on (${i}, ${t}) exceeded ${H} attempts`,
612
613
  transient: !0
613
614
  });
614
615
  });
@@ -633,7 +634,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
633
634
  lastReindexCount: t
634
635
  }),
635
636
  get: (t) => r(async () => {
636
- let n = await e.query(G(g("indexName", t))), r = n.some((e) => e.scope === "fleet"), i = (e) => {
637
+ let n = await e.query(V(g("indexName", t))), r = n.some((e) => e.scope === "fleet"), i = (e) => {
637
638
  let t = 0;
638
639
  for (let i of n) {
639
640
  let n = Number(i[e] ?? 0);
@@ -646,7 +647,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
646
647
  t && (a === null || t > a) && (a = t, o = Number(e.lastReindexCount ?? 0));
647
648
  }
648
649
  return {
649
- ...V(),
650
+ ...he(),
650
651
  synced: i("synced"),
651
652
  removed: i("removed"),
652
653
  dropped: i("dropped"),
@@ -655,7 +656,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
655
656
  };
656
657
  })
657
658
  };
658
- }, J = (e) => {
659
+ }, W = (e) => {
659
660
  let t = /* @__PURE__ */ new Map(), n = 0, r = !1, i = async () => {
660
661
  if (t.size === 0) return;
661
662
  let r = t;
@@ -687,12 +688,12 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
687
688
  },
688
689
  pending: () => n
689
690
  };
690
- }, me = (e) => (t, n, r) => e().add(t, n, r), he = (e) => e === void 0 || e === "memory" ? "memory" : typeof e.query == "function" ? e.engineKind === "memory" ? "memory" : "custom" : "vendor", ge = class extends Error {
691
+ }, G = (e) => (t, n, r) => e().add(t, n, r), K = (e) => e === void 0 || e === "memory" ? "memory" : typeof e.query == "function" ? e.engineKind === "memory" ? "memory" : "custom" : "vendor", q = class extends Error {
691
692
  _tag = "SearchBackendNotDurable";
692
693
  constructor(e) {
693
694
  super(e), this.name = "SearchBackendNotDurable";
694
695
  }
695
- }, _e = [
696
+ }, ye = [
696
697
  "plugin-search refuses to boot in production on the in-memory backend.",
697
698
  "",
698
699
  "The memory index lives in THIS process's heap. Two consequences, both silent:",
@@ -710,18 +711,18 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
710
711
  " searchPlugin({ singleProcessMemoryIndex: true, indexes })",
711
712
  "That is a claim about your topology, not a mute switch: if a second replica",
712
713
  "ever announces itself, the plugin logs that the claim was contradicted."
713
- ].join("\n"), ve = [
714
+ ].join("\n"), be = [
714
715
  "plugin-search is running the in-memory backend in production under",
715
716
  "`singleProcessMemoryIndex: true`. Holding you to the two conditions that makes true:",
716
717
  "exactly ONE process serves search, and it re-seeds every index at startup",
717
718
  "(`backfillIndex`) — the index is empty after each restart until it does."
718
- ].join(" "), ye = (e) => e.backendKind !== "memory" || !e.production ? { level: "quiet" } : e.singleProcessDeclared ? {
719
+ ].join(" "), J = (e) => e.backendKind !== "memory" || !e.production ? { level: "quiet" } : e.singleProcessDeclared ? {
719
720
  level: "note",
720
- message: ve
721
+ message: be
721
722
  } : {
722
723
  level: "refuse",
723
- message: _e
724
- }, be = (e, t) => t ? `search: replica "${e}" joined, but this app declared \`singleProcessMemoryIndex: true\`. That declaration is now false: each replica has its own in-memory index, so search results depend on which one serves the request. Configure a durable backend (typesense / meilisearch / algolia) or run one process.` : `search: replica "${e}" joined while search is served from an in-memory index. Each replica indexes only its OWN writes, so results depend on which replica answers. Configure a durable backend (typesense / meilisearch / algolia) before relying on these results.`, Y = "_voltro_search_drift", xe = b(Y, {
724
+ message: ye
725
+ }, xe = (e, t) => t ? `search: replica "${e}" joined, but this app declared \`singleProcessMemoryIndex: true\`. That declaration is now false: each replica has its own in-memory index, so search results depend on which one serves the request. Configure a durable backend (typesense / meilisearch / algolia) or run one process.` : `search: replica "${e}" joined while search is served from an in-memory index. Each replica indexes only its OWN writes, so results depend on which replica answers. Configure a durable backend (typesense / meilisearch / algolia) before relying on these results.`, Y = "_voltro_search_drift", Se = b(Y, {
725
726
  id: _({ prefix: "sdrft" }),
726
727
  indexName: x().maxLength(191),
727
728
  sourceTable: x().maxLength(191),
@@ -732,14 +733,14 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
732
733
  lastError: x().maxLength(1e3),
733
734
  firstFailedAt: S(),
734
735
  lastFailedAt: S()
735
- }).unique("bySearchDriftIndexRow", ["indexName", "rowId"]).index("bySearchDriftIndex", ["indexName"]), Se = (e, t) => ({
736
+ }).unique("bySearchDriftIndexRow", ["indexName", "rowId"]).index("bySearchDriftIndex", ["indexName"]), Ce = (e, t) => ({
736
737
  table: e,
737
738
  predicate: g("id", t),
738
739
  order: [],
739
740
  take: 1,
740
741
  skip: void 0,
741
742
  projection: void 0
742
- }), X = (e) => e ? new Date(e).toISOString() : (/* @__PURE__ */ new Date(0)).toISOString(), Ce = (e) => ({
743
+ }), X = (e) => e ? new Date(e).toISOString() : (/* @__PURE__ */ new Date(0)).toISOString(), we = (e) => ({
743
744
  indexName: String(e.indexName),
744
745
  sourceTable: String(e.sourceTable),
745
746
  rowId: String(e.rowId),
@@ -749,7 +750,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
749
750
  lastError: String(e.lastError ?? ""),
750
751
  firstFailedAt: X(e.firstFailedAt),
751
752
  lastFailedAt: X(e.lastFailedAt)
752
- }), we = () => {
753
+ }), Te = () => {
753
754
  let e = /* @__PURE__ */ new Map(), t = (e, t) => `${e}\u0000${t}`;
754
755
  return {
755
756
  record: async (n) => {
@@ -779,7 +780,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
779
780
  e.delete(t(n, r));
780
781
  }
781
782
  };
782
- }, Te = () => `sdrft_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`, Z = (e, t) => ({
783
+ }, Ee = () => `sdrft_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`, Z = (e, t) => ({
783
784
  table: Y,
784
785
  predicate: e,
785
786
  order: [{
@@ -789,9 +790,9 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
789
790
  take: t,
790
791
  skip: void 0,
791
792
  projection: void 0
792
- }), Ee = (e) => ({
793
+ }), De = (e) => ({
793
794
  record: async (t) => {
794
- let n = /* @__PURE__ */ new Date(), r = Te(), i = await e.insertIgnore(Y, {
795
+ let n = /* @__PURE__ */ new Date(), r = Ee(), i = await e.insertIgnore(Y, {
795
796
  id: r,
796
797
  indexName: t.indexName,
797
798
  sourceTable: t.sourceTable,
@@ -811,7 +812,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
811
812
  lastFailedAt: n
812
813
  }, { where: g("id", String(i.id)) });
813
814
  },
814
- list: async (t) => (await e.query(Z(void 0, t))).map(Ce),
815
+ list: async (t) => (await e.query(Z(void 0, t))).map(we),
815
816
  summary: async (t) => {
816
817
  let n = (await e.query({
817
818
  ...Z(g("indexName", t), void 0),
@@ -837,15 +838,15 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
837
838
  clear: async (t, n) => {
838
839
  await e.deleteMany(Y, { where: m(g("indexName", t), g("rowId", n)) });
839
840
  }
840
- }), De = () => [xe], Oe = (e, t) => {
841
+ }), Oe = () => [Se], ke = (e, t) => {
841
842
  if (e === void 0 || e === "memory") return N();
842
843
  if (typeof e.query == "function") return e;
843
844
  let n = e;
844
- return n.engine === "typesense" ? ie(n, t) : n.engine === "meilisearch" ? R(n, t) : n.engine === "algolia" ? z(n, t) : N();
845
- }, ke = async (e, t, n) => {
845
+ return n.engine === "typesense" ? ae(n, t) : n.engine === "meilisearch" ? ce(n, t) : n.engine === "algolia" ? pe(n, t) : N();
846
+ }, Ae = async (e, t, n) => {
846
847
  let r = n.map((e) => t.map(e));
847
848
  return r.length > 0 && await e.upsert(t.index, r), r.length;
848
- }, Ae = async (e, t, n) => {
849
+ }, je = async (e, t, n) => {
849
850
  if (n.op === "delete") {
850
851
  let r = n.old?.id;
851
852
  typeof r == "string" && await e.remove(t.index, [r]);
@@ -861,7 +862,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
861
862
  reindexBatchSize: 1e3,
862
863
  statsFlushIntervalMs: 5e3,
863
864
  statsFlushMaxBuffered: 1e3
864
- }, $ = (e) => ({
865
+ }, Me = (e) => ({
865
866
  retries: Math.max(0, e?.retries ?? Q.retries),
866
867
  retryBaseDelayMs: Math.max(1, e?.retryBaseDelayMs ?? Q.retryBaseDelayMs),
867
868
  retryMaxDelayMs: Math.max(1, e?.retryMaxDelayMs ?? Q.retryMaxDelayMs),
@@ -870,12 +871,12 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
870
871
  reindexBatchSize: Math.max(1, e?.reindexBatchSize ?? Q.reindexBatchSize),
871
872
  statsFlushIntervalMs: Math.max(0, e?.statsFlushIntervalMs ?? Q.statsFlushIntervalMs),
872
873
  statsFlushMaxBuffered: Math.max(1, e?.statsFlushMaxBuffered ?? Q.statsFlushMaxBuffered)
873
- }), je = (e) => e instanceof k ? e : new k({
874
+ }), Ne = (e) => e instanceof k ? e : new k({
874
875
  engine: "unknown",
875
876
  op: "upsert",
876
877
  message: String(e?.message ?? e),
877
878
  transient: !1
878
- }), Me = (e) => f.exponential(c.millis(e.retryBaseDelayMs), 2).pipe(f.either(f.spaced(c.millis(e.retryMaxDelayMs))), f.intersect(f.recurs(e.retries)), f.whileInput((e) => e.transient)), Ne = (e) => {
879
+ }), Pe = (e) => f.exponential(c.millis(e.retryBaseDelayMs), 2).pipe(f.either(f.spaced(c.millis(e.retryMaxDelayMs))), f.intersect(f.recurs(e.retries)), f.whileInput((e) => e.transient)), Fe = (e) => {
879
880
  if (!e || e === "memory" || typeof e.query == "function") return;
880
881
  let t = e;
881
882
  try {
@@ -883,40 +884,40 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
883
884
  } catch {
884
885
  return;
885
886
  }
886
- }, Pe = (e, t, n) => {
887
+ }, $ = (e, t, n) => {
887
888
  let r = n ?? [];
888
889
  return e ? t == null ? null : [...r, {
889
890
  field: e,
890
891
  op: "eq",
891
892
  value: t
892
893
  }] : r;
893
- }, Fe = (e) => [
894
+ }, Ie = (e) => [
894
895
  ...(e.filters ?? []).map((e) => ["filter", e.field]),
895
896
  ...(e.facets ?? []).map((e) => ["facet", e]),
896
897
  ...(e.highlight?.fields ?? []).map((e) => ["highlight", e])
897
- ], Ie = i, Le = (i) => {
898
+ ], Le = i, Re = (i) => {
898
899
  let s = te({
899
- base: Ie,
900
+ base: Le,
900
901
  alias: i.alias,
901
902
  instance: i.name
902
- }), c = () => void 0, f = () => void 0, m = $(i.sync), h = Me(m), g = Oe(i.backend, {
903
+ }), c = () => void 0, f = () => void 0, m = Me(i.sync), h = Pe(m), g = ke(i.backend, {
903
904
  ...i.allowedEngineParams ? { allowEngineParams: i.allowedEngineParams } : {},
904
905
  onWarn: (e, t) => c(e, t)
905
906
  }), _ = /* @__PURE__ */ new Map();
906
907
  for (let e of Object.values(i.indexes)) _.set(e.index, e);
907
- let v = he(i.backend), b = i.singleProcessMemoryIndex === !0, x = !1, S, C = {
908
+ let v = K(i.backend), b = i.singleProcessMemoryIndex === !0, x = !1, S, ne = {
908
909
  ...r,
909
910
  description: "Full-text search an index (facets/highlight/fuzzy/filters), auto-scoped to the caller tenant.",
910
911
  execute: (t, r) => {
911
912
  let { index: i, q: a, limit: o, offset: s, filters: c, facets: u, highlight: d, fuzziness: f, engineParams: p } = t, m = _.get(i);
912
913
  if (!m) return l.fail(new n({ index: i }));
913
- let h = ne(Fe({
914
+ let h = re(Ie({
914
915
  ...c ? { filters: c } : {},
915
916
  ...u ? { facets: u } : {},
916
917
  ...d ? { highlight: d } : {}
917
918
  }), m.queryableFields);
918
919
  if (h) return l.fail(new e(h));
919
- let v = r.request.subject.tenantId ?? null, y = Pe(m.tenantField, v, c);
920
+ let v = r.request.subject.tenantId ?? null, y = $(m.tenantField, v, c);
920
921
  if (y === null) return l.succeed({
921
922
  hits: [],
922
923
  facets: {}
@@ -933,30 +934,30 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
933
934
  };
934
935
  return l.promise(() => g.query(i, b));
935
936
  }
936
- }, w = Ne(i.backend), T = [
937
+ }, C = Fe(i.backend), w = [
937
938
  "store:changes:read",
938
939
  "store:write",
939
940
  "inspect:read",
940
941
  "inspect:write",
941
- ...w ? [`network:outbound:${w}`] : []
942
- ], E = W(), D = we(), O, k, A, j, M = (e, t, n) => j === void 0 ? l.tryPromise(() => E.bump(e, t, n)).pipe(l.catchAll((n) => l.sync(() => c("search stats bump failed", {
942
+ ...C ? [`network:outbound:${C}`] : []
943
+ ], T = B(), E = Te(), D, O, k, A, j = (e, t, n) => A === void 0 ? l.tryPromise(() => T.bump(e, t, n)).pipe(l.catchAll((n) => l.sync(() => c("search stats bump failed", {
943
944
  index: e,
944
945
  kind: t,
945
946
  error: String(n)
946
- })))) : l.sync(() => j.bump(e, t, n)), N = async (e) => {
947
- let t = await D.list(e), n = 0, r = 0;
947
+ })))) : l.sync(() => A.bump(e, t, n)), M = async (e) => {
948
+ let t = await E.list(e), n = 0, r = 0;
948
949
  for (let e of t) {
949
950
  let t = _.get(e.indexName);
950
951
  if (!t) {
951
- await D.clear(e.indexName, e.rowId);
952
+ await E.clear(e.indexName, e.rowId);
952
953
  continue;
953
954
  }
954
955
  try {
955
- if (!k) throw Error("data store not bound");
956
- let r = (await k.query(Se(e.sourceTable, e.rowId)))[0];
957
- r ? await g.upsert(t.index, [t.map(r)]) : await g.remove(t.index, [e.docId]), await D.clear(e.indexName, e.rowId), n++;
956
+ if (!O) throw Error("data store not bound");
957
+ let r = (await O.query(Ce(e.sourceTable, e.rowId)))[0];
958
+ r ? await g.upsert(t.index, [t.map(r)]) : await g.remove(t.index, [e.docId]), await E.clear(e.indexName, e.rowId), n++;
958
959
  } catch (t) {
959
- r++, await D.record({
960
+ r++, await E.record({
960
961
  ...e,
961
962
  error: String(t?.message ?? t)
962
963
  }).catch(() => void 0);
@@ -967,20 +968,20 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
967
968
  repaired: n,
968
969
  failed: r
969
970
  };
970
- }, P = (e) => ({
971
+ }, N = (e) => ({
971
972
  kind: "json",
972
973
  data: e
973
- }), F = (e, t) => ({
974
+ }), P = (e, t) => ({
974
975
  kind: "json",
975
976
  status: e,
976
977
  data: { error: t }
977
978
  });
978
979
  return ee({
979
980
  name: s,
980
- baseName: Ie,
981
+ baseName: Le,
981
982
  description: "External search index sync (Typesense/Meilisearch/Algolia/memory) via the ChangeEvent tap + a tenant-scoped query route.",
982
- permissions: T,
983
- routes: [C],
983
+ permissions: w,
984
+ routes: [ne],
984
985
  rpcClientDescriptors: t,
985
986
  inspectEndpoints: [
986
987
  {
@@ -988,9 +989,9 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
988
989
  path: "/indexes",
989
990
  description: "Configured indexes + durable, cross-replica sync stats + current index drift.",
990
991
  handler: () => l.promise(async () => {
991
- await j?.flushNow();
992
+ await A?.flushNow();
992
993
  let e = await Promise.all(Object.entries(i.indexes).map(async ([e, t]) => {
993
- let n = await E.get(t.index), r = await D.summary(t.index);
994
+ let n = await T.get(t.index), r = await E.summary(t.index);
994
995
  return {
995
996
  table: e,
996
997
  index: t.index,
@@ -1001,7 +1002,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
1001
1002
  drifted: r.pending > 0
1002
1003
  };
1003
1004
  }));
1004
- return P({
1005
+ return N({
1005
1006
  indexes: e,
1006
1007
  backend: typeof i.backend == "string" ? i.backend : i.backend ? "custom/vendor" : "memory",
1007
1008
  durable: v !== "memory",
@@ -1009,7 +1010,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
1009
1010
  pendingDrift: e.reduce((e, t) => e + t.pendingDrift, 0),
1010
1011
  sync: {
1011
1012
  ...m,
1012
- resyncArmed: O !== void 0
1013
+ resyncArmed: D !== void 0
1013
1014
  }
1014
1015
  });
1015
1016
  })
@@ -1019,8 +1020,8 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
1019
1020
  path: "/drift",
1020
1021
  description: "The changes that did NOT reach the engine, oldest first (the repair queue).",
1021
1022
  handler: (e) => l.promise(async () => {
1022
- let t = Number(new URL(e.url, "http://localhost").searchParams.get("limit") ?? 100), n = await D.list(Number.isFinite(t) && t > 0 ? Math.min(t, 1e3) : 100);
1023
- return P({ entries: n });
1023
+ let t = Number(new URL(e.url, "http://localhost").searchParams.get("limit") ?? 100), n = await E.list(Number.isFinite(t) && t > 0 ? Math.min(t, 1e3) : 100);
1024
+ return N({ entries: n });
1024
1025
  })
1025
1026
  },
1026
1027
  {
@@ -1032,17 +1033,17 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
1032
1033
  try {
1033
1034
  t = JSON.parse(e.body || "{}");
1034
1035
  } catch {
1035
- return F(400, "invalid JSON body");
1036
+ return P(400, "invalid JSON body");
1036
1037
  }
1037
- if (!k) return F(503, "data store not bound yet");
1038
+ if (!O) return P(503, "data store not bound yet");
1038
1039
  try {
1039
- let e = await N(Math.min(Math.max(1, t.limit ?? m.resyncBatchSize), 1e3));
1040
- return P({
1040
+ let e = await M(Math.min(Math.max(1, t.limit ?? m.resyncBatchSize), 1e3));
1041
+ return N({
1041
1042
  ok: !0,
1042
1043
  ...e
1043
1044
  });
1044
1045
  } catch (e) {
1045
- return F(500, e.message);
1046
+ return P(500, e.message);
1046
1047
  }
1047
1048
  })
1048
1049
  },
@@ -1055,27 +1056,27 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
1055
1056
  try {
1056
1057
  t = JSON.parse(e.body || "{}");
1057
1058
  } catch {
1058
- return F(400, "invalid JSON body");
1059
+ return P(400, "invalid JSON body");
1059
1060
  }
1060
1061
  let n = t.table, r = n ? i.indexes[n] : void 0;
1061
- if (!n || !r) return F(404, `no index configured for table "${t.table ?? ""}"`);
1062
- if (!A) return F(503, "data store not bound yet");
1063
- let s = 0, c = await l.runPromiseExit(y(A, {
1062
+ if (!n || !r) return P(404, `no index configured for table "${t.table ?? ""}"`);
1063
+ if (!k) return P(503, "data store not bound yet");
1064
+ let s = 0, c = await l.runPromiseExit(y(k, {
1064
1065
  table: n,
1065
1066
  chunkSize: m.reindexBatchSize
1066
1067
  }).pipe(p.chunks, p.runForEach((e) => l.tryPromise(async () => {
1067
- s += await ke(g, r, o.toReadonlyArray(e));
1068
+ s += await Ae(g, r, o.toReadonlyArray(e));
1068
1069
  }))));
1069
1070
  if (u.isFailure(c)) {
1070
1071
  let e = a.failureOption(c.cause), t = d.isSome(e) ? e.value : c.cause, n = t.cause ?? t.error ?? t;
1071
- return F(500, String(n?.message ?? n));
1072
+ return P(500, String(n?.message ?? n));
1072
1073
  }
1073
1074
  try {
1074
- await E.recordReindex(r.index, s, (/* @__PURE__ */ new Date()).toISOString());
1075
+ await T.recordReindex(r.index, s, (/* @__PURE__ */ new Date()).toISOString());
1075
1076
  } catch (e) {
1076
- return F(500, e.message);
1077
+ return P(500, e.message);
1077
1078
  }
1078
- return P({
1079
+ return N({
1079
1080
  ok: !0,
1080
1081
  table: n,
1081
1082
  index: r.index,
@@ -1084,17 +1085,17 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
1084
1085
  })
1085
1086
  }
1086
1087
  ],
1087
- extendSchema: { tables: [...U(), ...De()] },
1088
+ extendSchema: { tables: [...z(), ...Oe()] },
1088
1089
  bindDataStore: (e, t) => {
1089
- k = e, A = e, E = q(e), D = Ee(e), v === "memory" && t?.membership !== void 0 && (S = t.membership.onChange((e) => {
1090
- e.kind === "left" || x || (t.instanceId === void 0 || e.instanceId !== t.instanceId) && (x = !0, c(be(e.instanceId, b), {
1090
+ O = e, k = e, T = U(e, ...t?.instanceId === void 0 ? [] : [t.instanceId]), E = De(e), v === "memory" && t?.membership !== void 0 && (S = t.membership.onChange((e) => {
1091
+ e.kind === "left" || x || (t.instanceId === void 0 || e.instanceId !== t.instanceId) && (x = !0, c(xe(e.instanceId, b), {
1091
1092
  instanceId: t.instanceId ?? null,
1092
1093
  peer: e.instanceId,
1093
1094
  indexes: Object.keys(i.indexes)
1094
1095
  }));
1095
- })), !(m.resyncIntervalMs <= 0 || t?.scheduleCoordinated === void 0) && (O = t.scheduleCoordinated("search.resync", m.resyncIntervalMs, async () => {
1096
+ })), !(m.resyncIntervalMs <= 0 || t?.scheduleCoordinated === void 0) && (D = t.scheduleCoordinated("search.resync", m.resyncIntervalMs, async () => {
1096
1097
  try {
1097
- let e = await N(m.resyncBatchSize);
1098
+ let e = await M(m.resyncBatchSize);
1098
1099
  return (e.repaired > 0 || e.failed > 0) && f("search: drift repair pass", e), { idle: e.scanned === 0 };
1099
1100
  } catch (e) {
1100
1101
  return c("search: drift repair pass failed", { error: String(e?.message ?? e) }), { idle: !1 };
@@ -1113,10 +1114,10 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
1113
1114
  }
1114
1115
  };
1115
1116
  return l.tryPromise({
1116
- try: () => Ae(g, t, e),
1117
- catch: je
1117
+ try: () => je(g, t, e),
1118
+ catch: Ne
1118
1119
  }).pipe(l.retry(h)).pipe(l.matchEffect({
1119
- onSuccess: () => r ? M(t.index, e.op === "delete" ? "removed" : "synced", n) : l.void,
1120
+ onSuccess: () => r ? j(t.index, e.op === "delete" ? "removed" : "synced", n) : l.void,
1120
1121
  onFailure: (r) => {
1121
1122
  let i = {
1122
1123
  table: e.table,
@@ -1126,7 +1127,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
1126
1127
  transient: r.transient,
1127
1128
  error: r.message
1128
1129
  };
1129
- return o === "" ? l.sync(() => c("search: change not indexed and NOT recoverable (row has no id)", i)).pipe(l.zipRight(l.fail(r))) : l.tryPromise(() => D.record({
1130
+ return o === "" ? l.sync(() => c("search: change not indexed and NOT recoverable (row has no id)", i)).pipe(l.zipRight(l.fail(r))) : l.tryPromise(() => E.record({
1130
1131
  indexName: t.index,
1131
1132
  sourceTable: e.table,
1132
1133
  rowId: o,
@@ -1134,7 +1135,7 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
1134
1135
  op: s,
1135
1136
  error: r.message
1136
1137
  })).pipe(l.matchEffect({
1137
- onSuccess: () => M(t.index, "dropped", n).pipe(l.zipRight(l.sync(() => c("search: index drift recorded — will be repaired from the database", i)))),
1138
+ onSuccess: () => j(t.index, "dropped", n).pipe(l.zipRight(l.sync(() => c("search: index drift recorded — will be repaired from the database", i)))),
1138
1139
  onFailure: (e) => l.sync(() => c("search: change LOST — engine failed and the drift ledger could not record it", {
1139
1140
  ...i,
1140
1141
  ledgerError: String(e)
@@ -1145,13 +1146,13 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
1145
1146
  },
1146
1147
  onActivate: (e) => l.suspend(() => {
1147
1148
  c = (t, n) => e.logger.warn(t, n), f = (t, n) => e.logger.info(t, n);
1148
- let t = ye({
1149
+ let t = J({
1149
1150
  backendKind: v,
1150
1151
  production: (e.env?.NODE_ENV ?? process.env.NODE_ENV) === "production",
1151
1152
  singleProcessDeclared: b
1152
1153
  });
1153
- return t.level === "refuse" ? l.fail(new ge(t.message)) : (t.level === "note" && e.logger.info(t.message, { indexes: Object.keys(i.indexes) }), m.statsFlushIntervalMs > 0 && j === void 0 && (j = J({
1154
- flush: me(() => E),
1154
+ return t.level === "refuse" ? l.fail(new q(t.message)) : (t.level === "note" && e.logger.info(t.message, { indexes: Object.keys(i.indexes) }), m.statsFlushIntervalMs > 0 && A === void 0 && (A = W({
1155
+ flush: G(() => T),
1155
1156
  intervalMs: m.statsFlushIntervalMs,
1156
1157
  maxBuffered: m.statsFlushMaxBuffered
1157
1158
  })), l.sync(() => {
@@ -1164,11 +1165,11 @@ var C = /^[A-Za-z_][A-Za-z0-9_.]*$/, w = (e) => C.test(e), ne = (e, t) => {
1164
1165
  }));
1165
1166
  }),
1166
1167
  onDeactivate: () => l.promise(async () => {
1167
- O?.stop(), O = void 0, S?.(), S = void 0, x = !1;
1168
- let e = j;
1169
- j = void 0, await e?.shutdown();
1168
+ D?.stop(), D = void 0, S?.(), S = void 0, x = !1;
1169
+ let e = A;
1170
+ A = void 0, await e?.shutdown();
1170
1171
  })
1171
1172
  });
1172
1173
  };
1173
1174
  //#endregion
1174
- export { C as FIELD_NAME_PATTERN, Y as SEARCH_DRIFT_TABLE, B as SEARCH_STATS_TABLE, Q as SYNC_DEFAULTS, k as SearchBackendError, ge as SearchBackendNotDurable, e as SearchFieldRejected, n as SearchIndexNotFound, z as algoliaBackend, O as allowedEngineParams, Ae as applyChange, je as asBackendError, ye as auditMemoryBackend, he as backendKindOf, ke as backfillIndex, Ee as dataStoreDriftLedger, q as dataStoreStatsStore, Se as driftSourceQuery, De as driftTables, w as isSafeFieldName, J as makeSearchStatsBuffer, R as meilisearchBackend, N as memoryBackend, we as memoryDriftLedger, W as memoryStatsStore, be as peerObservedWarning, $ as resolveSyncOptions, D as sanitizeEngineParams, Pe as scopeSearchFilters, xe as searchDriftTable, Le as searchPlugin, H as searchStatsTable, U as searchTables, me as statsStoreFlush, Me as syncRetrySchedule, ie as typesenseBackend };
1175
+ export { C as FIELD_NAME_PATTERN, Y as SEARCH_DRIFT_TABLE, R as SEARCH_STATS_TABLE, Q as SYNC_DEFAULTS, k as SearchBackendError, q as SearchBackendNotDurable, e as SearchFieldRejected, n as SearchIndexNotFound, pe as algoliaBackend, O as allowedEngineParams, je as applyChange, Ne as asBackendError, J as auditMemoryBackend, K as backendKindOf, Ae as backfillIndex, De as dataStoreDriftLedger, U as dataStoreStatsStore, Ce as driftSourceQuery, Oe as driftTables, w as isSafeFieldName, W as makeSearchStatsBuffer, ce as meilisearchBackend, N as memoryBackend, Te as memoryDriftLedger, B as memoryStatsStore, xe as peerObservedWarning, Me as resolveSyncOptions, D as sanitizeEngineParams, $ as scopeSearchFilters, Se as searchDriftTable, Re as searchPlugin, ge as searchStatsTable, z as searchTables, G as statsStoreFlush, Pe as syncRetrySchedule, ae as typesenseBackend };