@delali/narsil 0.3.1-next.74 → 0.3.1-next.76

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 (45) hide show
  1. package/dist/{capabilities-CAMzmkAg.d.ts → capabilities-1lEYL3WK.d.ts} +16 -2
  2. package/dist/{chunk-Z3DQPOJQ.mjs → chunk-356UOTK2.mjs} +1 -1
  3. package/dist/chunk-4344I4MR.mjs +2217 -0
  4. package/dist/{chunk-PO53FV4Q.mjs → chunk-AMGDG4ZJ.mjs} +1 -1
  5. package/dist/{chunk-LX4JERXI.mjs → chunk-BT62MUM5.mjs} +1 -1
  6. package/dist/{chunk-NOZUQM7J.mjs → chunk-BT6BI4GV.mjs} +41 -3
  7. package/dist/{chunk-VKX2BPXD.mjs → chunk-D4EF7J3I.mjs} +127 -20
  8. package/dist/{chunk-BVBIQQKG.mjs → chunk-DFFQOA7S.mjs} +26 -67
  9. package/dist/{chunk-CTOSGRM7.mjs → chunk-G7IP3UDZ.mjs} +6 -5
  10. package/dist/chunk-GES7U2PM.mjs +68 -0
  11. package/dist/{chunk-CUZOX6CN.mjs → chunk-HH6ALOUZ.mjs} +31 -27
  12. package/dist/{chunk-LJYTW7GT.mjs → chunk-IBR6634K.mjs} +1 -1
  13. package/dist/{chunk-I23G3IZC.mjs → chunk-NO3ABFLE.mjs} +2 -63
  14. package/dist/{chunk-T5ZWEWVD.mjs → chunk-PJU6EF22.mjs} +3 -2
  15. package/dist/{chunk-TVFLHM7M.mjs → chunk-PXDY5VRT.mjs} +3 -3
  16. package/dist/{chunk-3DDUNI6N.mjs → chunk-V3B24XR7.mjs} +7 -1
  17. package/dist/{client-C-I70ArH.d.ts → client-ZXcbSViH.d.ts} +2 -2
  18. package/dist/client.d.ts +6 -6
  19. package/dist/{config-C6Iw5rCX.d.ts → config-DHL2KsfD.d.ts} +1 -1
  20. package/dist/{config-DJPH3IQB.d.ts → config-DTe5EbWW.d.ts} +4 -2
  21. package/dist/direct-executor-Q7PNCGZB.mjs +17 -0
  22. package/dist/distribution/coordinator/etcd.mjs +1 -1
  23. package/dist/distribution/coordinator/in-memory.mjs +1 -1
  24. package/dist/distribution.d.ts +5 -5
  25. package/dist/distribution.mjs +22 -15
  26. package/dist/{engine-B8eRPO7m.d.ts → engine-BjPBzWkA.d.ts} +1 -1
  27. package/dist/index.browser.mjs +158 -38
  28. package/dist/index.d.ts +5 -5
  29. package/dist/index.mjs +13 -13
  30. package/dist/invalidation/filesystem.mjs +1 -1
  31. package/dist/{memory-DJEwWoCi.d.ts → memory-DW3OJ0im.d.ts} +105 -24
  32. package/dist/partial-words.mjs +5 -4
  33. package/dist/pattern.mjs +3 -2
  34. package/dist/persistence/durability/checkpoint-worker.mjs +13 -13
  35. package/dist/react.d.ts +6 -6
  36. package/dist/server.d.ts +8 -8
  37. package/dist/server.mjs +34 -11
  38. package/dist/{tasks-BVmAKYBh.d.ts → tasks-BTbwBqar.d.ts} +1 -1
  39. package/dist/{thread-W6DPKEF6.mjs → thread-YOTNJEVY.mjs} +15 -10
  40. package/dist/vector/search-worker.mjs +2 -2
  41. package/dist/workers/entry.mjs +3 -3
  42. package/package.json +8 -7
  43. package/dist/chunk-XW25X6AU.mjs +0 -614
  44. package/dist/chunk-ZKRV5M2P.mjs +0 -75
  45. package/dist/direct-executor-KFAGILJC.mjs +0 -17
@@ -1,7 +1,7 @@
1
1
  import { OSQ_STEPS, OSQ_GRID, OSQ_REFINE_ROUNDS, OSQ_REFINE_TOLERANCE, OSQ4_NARROW_DIMENSION_LIMIT, DEFAULT_OSQ4_NARROW_OVERSAMPLE, DEFAULT_OVERSAMPLE_BY_BITS, OSQ_QUERY_BITS, OSQ_LAMBDA } from './chunk-ZJ4CSAB2.mjs';
2
2
  import { nativeSearchCoreIsEnabled, loadNativeCore, stopUsingTheNativeSearchCore, noteFallback } from './chunk-2E35UM3G.mjs';
3
3
  import { COMPACTION_TOMBSTONE_RATIO, COMPACTION_ABSOLUTE_THRESHOLD, MAX_LAYER_CAP, PLACEMENT_ROOM_REQUESTS, INITIAL_LIST_CAPACITY, DEFAULT_EF_SEARCH, INITIAL_UPPER_SLOTS } from './chunk-KEHK2O6P.mjs';
4
- import { compareCodePoints } from './chunk-LJYTW7GT.mjs';
4
+ import { compareCodePoints } from './chunk-IBR6634K.mjs';
5
5
  import { NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
6
6
  import { readSync, closeSync, openSync } from 'fs';
7
7
 
@@ -1,4 +1,4 @@
1
- import { requireDocumentWithinSizeLimit, validateRequiredFields } from './chunk-Z3DQPOJQ.mjs';
1
+ import { requireDocumentWithinSizeLimit, validateRequiredFields } from './chunk-356UOTK2.mjs';
2
2
  import { ErrorCodes, NarsilError } from './chunk-I64LXKO3.mjs';
3
3
 
4
4
  // src/narsil/internals.ts
@@ -1,4 +1,4 @@
1
- import { MAX_SORT_FIELDS } from './chunk-3DDUNI6N.mjs';
1
+ import { MAX_FILTER_DEPTH, MAX_SORT_FIELDS } from './chunk-V3B24XR7.mjs';
2
2
  import { nativeSearchCoreIsEnabled, loadNativeCore } from './chunk-2E35UM3G.mjs';
3
3
  import { NarsilError, ServerErrorCodes, ErrorCodes } from './chunk-I64LXKO3.mjs';
4
4
  import { mkdtemp, open, rm } from 'fs/promises';
@@ -423,6 +423,43 @@ function serializeBatchResult(result) {
423
423
  };
424
424
  }
425
425
 
426
+ // src/server/regex-policy.ts
427
+ function isRecord(value) {
428
+ return value !== null && typeof value === "object" && !Array.isArray(value);
429
+ }
430
+ function regexFieldIn(expression, depth) {
431
+ if (!isRecord(expression) || depth > MAX_FILTER_DEPTH) return null;
432
+ if (isRecord(expression.fields)) {
433
+ for (const [fieldPath, filter] of Object.entries(expression.fields)) {
434
+ if (isRecord(filter) && Object.hasOwn(filter, "regex")) return fieldPath;
435
+ }
436
+ }
437
+ for (const nested of [expression.and, expression.or]) {
438
+ if (!Array.isArray(nested)) continue;
439
+ for (const child of nested) {
440
+ const found = regexFieldIn(child, depth + 1);
441
+ if (found !== null) return found;
442
+ }
443
+ }
444
+ return regexFieldIn(expression.not, depth + 1);
445
+ }
446
+ function refusedRegex(filters, allowRegex) {
447
+ if (allowRegex) return null;
448
+ const fieldPath = regexFieldIn(filters, 0);
449
+ if (fieldPath === null) return null;
450
+ return new NarsilError(
451
+ ErrorCodes.SEARCH_INVALID_FILTER,
452
+ `This server refuses every "regex" test, because its operator set the allowRegex server option to false. Test field "${fieldPath}" with "contains" or "wildcard"`,
453
+ { fieldPath, operator: "regex", option: "allowRegex" }
454
+ );
455
+ }
456
+ function refuseRegex(ctx, filters, allowRegex) {
457
+ const refused = refusedRegex(filters, allowRegex);
458
+ if (refused === null) return false;
459
+ respondError(ctx, refused);
460
+ return true;
461
+ }
462
+
426
463
  // src/server/validation.ts
427
464
  function isPlainObject(value) {
428
465
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -616,7 +653,7 @@ function parseTaskListQuery(params, maxPageSize) {
616
653
 
617
654
  // src/server/handlers/document-reads.ts
618
655
  function createDocumentReadHandlers(deps) {
619
- const { engine, limits } = deps;
656
+ const { engine, limits, allowRegex } = deps;
620
657
  async function get(ctx) {
621
658
  try {
622
659
  const document = await engine.get(ctx.params[0], ctx.params[1]);
@@ -668,6 +705,7 @@ function createDocumentReadHandlers(deps) {
668
705
  rejectInvalid(ctx, failure);
669
706
  return;
670
707
  }
708
+ if (refuseRegex(ctx, params.filters, allowRegex)) return;
671
709
  try {
672
710
  respondJson(ctx, await engine.listDocuments(ctx.params[0], params));
673
711
  } catch (err) {
@@ -1155,4 +1193,4 @@ function childAppOf(app) {
1155
1193
  return candidate;
1156
1194
  }
1157
1195
 
1158
- export { ASYNC_IMPORT_CAPABILITY, DEFAULT_IMPORT_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_MAX_CONCURRENT_TASKS, DEFAULT_MAX_FETCH_DOCUMENTS, DEFAULT_MAX_IMPORT_BYTES, DEFAULT_MAX_IMPORT_ERRORS, DEFAULT_MAX_LINE_BYTES, DEFAULT_MAX_RESTORE_BYTES, DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_RETAINED_TASKS, DEFAULT_MAX_TASK_PAGE_SIZE, DEFAULT_TASK_PAGE_SIZE, DOCUMENT_EXPORT_CAPABILITY, DOCUMENT_EXPORT_CONTENT_TYPE, IMPORT_FLUSHES_IN_FLIGHT, INDEX_LIFECYCLE_CAPABILITY, INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT, MAIN_THREAD_GATE_SLOT, MAX_INDEX_TOUCH_INTERVAL_MS, MIN_COUNTED_SERVER_LIMIT, MIN_UNBOUNDED_SERVER_LIMIT, REBUILD_ANALYSIS_CAPABILITY, RELAY_STREAM_CHUNKS_IN_FLIGHT, RUNNING_TASK_TTL_MS, SERVER_CAPABILITIES, SNAPSHOT_ARCHIVE_CONTENT_TYPE, TASK_CANCEL_CAPABILITY, TASK_FILTER_CAPABILITY, TASK_PROGRESS_WRITE_INTERVAL_MS, TERMINAL_TASK_TTL_MS, acceptorOf, authorizerFor, badRequest, childAppOf, clearGateSlot, corsHeaderReader, createDocumentReadHandlers, createRouteRunner, createSharedGateBuffer, createSharedRequestGate, createVersionHandler, gateSlotOfWorker, httpStatusForNarsilError, loadUWebSockets, parseJson, parseJsonOptional, parseTaskListQuery, registerServerRoutes, rejectInvalid, resolveCors, respondError, respondJson, sendError, sendRelayed, sendStream, serializeBatchResult, serializeNarsilError, serverRoutes, statusLine, toHttpError, validateBatch, validateCreateIndex, validateDocumentBody, validateQuery, validateRebalance, validateSuggest, versionReport };
1196
+ export { ASYNC_IMPORT_CAPABILITY, DEFAULT_IMPORT_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_MAX_CONCURRENT_TASKS, DEFAULT_MAX_FETCH_DOCUMENTS, DEFAULT_MAX_IMPORT_BYTES, DEFAULT_MAX_IMPORT_ERRORS, DEFAULT_MAX_LINE_BYTES, DEFAULT_MAX_RESTORE_BYTES, DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_RETAINED_TASKS, DEFAULT_MAX_TASK_PAGE_SIZE, DEFAULT_TASK_PAGE_SIZE, DOCUMENT_EXPORT_CAPABILITY, DOCUMENT_EXPORT_CONTENT_TYPE, IMPORT_FLUSHES_IN_FLIGHT, INDEX_LIFECYCLE_CAPABILITY, INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT, MAIN_THREAD_GATE_SLOT, MAX_INDEX_TOUCH_INTERVAL_MS, MIN_COUNTED_SERVER_LIMIT, MIN_UNBOUNDED_SERVER_LIMIT, REBUILD_ANALYSIS_CAPABILITY, RELAY_STREAM_CHUNKS_IN_FLIGHT, RUNNING_TASK_TTL_MS, SERVER_CAPABILITIES, SNAPSHOT_ARCHIVE_CONTENT_TYPE, TASK_CANCEL_CAPABILITY, TASK_FILTER_CAPABILITY, TASK_PROGRESS_WRITE_INTERVAL_MS, TERMINAL_TASK_TTL_MS, acceptorOf, authorizerFor, badRequest, childAppOf, clearGateSlot, corsHeaderReader, createDocumentReadHandlers, createRouteRunner, createSharedGateBuffer, createSharedRequestGate, createVersionHandler, gateSlotOfWorker, httpStatusForNarsilError, loadUWebSockets, parseJson, parseJsonOptional, parseTaskListQuery, refuseRegex, registerServerRoutes, rejectInvalid, resolveCors, respondError, respondJson, sendError, sendRelayed, sendStream, serializeBatchResult, serializeNarsilError, serverRoutes, statusLine, toHttpError, validateBatch, validateCreateIndex, validateDocumentBody, validateQuery, validateRebalance, validateSuggest, versionReport };
@@ -1,10 +1,48 @@
1
- import { MAX_SORT_FIELDS, MAX_SORT_FIELD_NAME_LENGTH, MAX_CURSOR_LENGTH, MAX_CURSOR_ANCHOR_CODE_POINTS, RESULT_WINDOW, DEFAULT_FUZZY_PREFIX_LENGTH, DEFAULT_PAGE_SIZE, PREFIX_MAX_EXPANSIONS, PARTIAL_WORD_MIN_CODE_POINTS, PARTIAL_WORDS_ADDED_PER_QUERY } from './chunk-3DDUNI6N.mjs';
2
- import { DEFAULT_PATTERN_WORK_CAP, PATTERN_TEST_OPERATORS, bitsetIsEmpty, MAX_PATTERN_TEXT_CODE_POINTS, MAX_PATTERN_POSITIONS, createBitSet, bitsetSet, PATTERN_WORK_FLUSH_UNITS, MATCHER_STATE_BUDGET_BYTES } from './chunk-ZKRV5M2P.mjs';
3
- import { getFlatSchema, tokenize, getFieldValueByInternalId, getFieldValueForDoc, fuzzyTermMatches } from './chunk-I23G3IZC.mjs';
4
- import { MAX_LATITUDE_DEGREES, MAX_LONGITUDE_DEGREES, MIN_POLYGON_POINTS, flattenSchema, parsedTypeOf, isStringValuedBase, withSortableOption, isGeopointOrVectorType, EARTH_RADIUS_METERS, RADIUS_BOX_MARGIN_RATIO, RADIUS_BOX_MARGIN_RADIANS, FULL_TURN_DEGREES, ANTIMERIDIAN_SPAN_DEGREES, PROTOTYPE_POLLUTION_KEYS, DEG_TO_RAD, LOCATION_CODE_BITS_PER_AXIS, isLatitude, isLongitude, isWordIndexedFieldType, partialFieldsOf, MAX_COVERING_CELLS } from './chunk-Z3DQPOJQ.mjs';
5
- import { compareCodePoints, sortModeOf, defaultSortMode, SORT_VALUE_MAX_CODE_POINTS, toReducedSortValue, readSortField, compareComparableKeys, toComparableSortValue, exceedsCodePoints, holdsUnpairedSurrogate, isSortMode, SORT_MODES, compareSortValues, foldedCodePointCount, codePointCount } from './chunk-LJYTW7GT.mjs';
1
+ import { MAX_SORT_FIELDS, MAX_SORT_FIELD_NAME_LENGTH, MAX_CURSOR_LENGTH, MAX_CURSOR_ANCHOR_CODE_POINTS, RESULT_WINDOW, DEFAULT_FUZZY_PREFIX_LENGTH, MAX_FILTER_DEPTH, DEFAULT_PAGE_SIZE, MAX_FILTER_ARRAY_SIZE, GEO_UNIT_METRES, MAX_FILTER_TESTS, PREFIX_MAX_EXPANSIONS, PARTIAL_WORD_MIN_CODE_POINTS, PARTIAL_WORDS_ADDED_PER_QUERY } from './chunk-V3B24XR7.mjs';
2
+ import { DEFAULT_PATTERN_WORK_CAP, patternSearchModule, PATTERN_TEST_OPERATORS, bitsetIsEmpty, PATTERN_EXPRESSION_OPERATORS, MAX_PATTERN_POSITIONS, isPatternTolerance, foldTypoText, typoRunsNeeded, distinctTypoRunCount, createBitSet, bitsetSet, MAX_PATTERN_TEXT_CODE_POINTS, PATTERN_WORK_FLUSH_UNITS, MATCHER_STATE_BUDGET_BYTES } from './chunk-4344I4MR.mjs';
3
+ import { getFlatSchema, tokenize, getFieldValueByInternalId, getFieldValueForDoc } from './chunk-NO3ABFLE.mjs';
4
+ import { schemaFieldsOf, MAX_LATITUDE_DEGREES, MAX_LONGITUDE_DEGREES, MIN_POLYGON_POINTS, flattenSchema, parsedTypeOf, isStringValuedBase, withSortableOption, isGeopointOrVectorType, EARTH_RADIUS_METERS, RADIUS_BOX_MARGIN_RATIO, RADIUS_BOX_MARGIN_RADIANS, FULL_TURN_DEGREES, ANTIMERIDIAN_SPAN_DEGREES, PROTOTYPE_POLLUTION_KEYS, DEG_TO_RAD, LOCATION_CODE_BITS_PER_AXIS, isLatitude, isLongitude, isWordIndexedFieldType, partialFieldsOf, MAX_COVERING_CELLS } from './chunk-356UOTK2.mjs';
5
+ import { fuzzyTermMatches } from './chunk-GES7U2PM.mjs';
6
+ import { appendFoldedCodePoint, compareCodePoints, sortModeOf, defaultSortMode, SORT_VALUE_MAX_CODE_POINTS, toReducedSortValue, readSortField, compareComparableKeys, toComparableSortValue, exceedsCodePoints, singleFoldTable, holdsUnpairedSurrogate, isSortMode, SORT_MODES, compareSortValues, foldedCodePointCount, codePointCount } from './chunk-IBR6634K.mjs';
6
7
  import { NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
7
8
 
9
+ // src/core/pattern-index/platform.ts
10
+ function platformPatternSearch() {
11
+ return patternSearchModule;
12
+ }
13
+
14
+ // src/core/pattern-index/registry.ts
15
+ var registered = null;
16
+ function isPatternSearchModule(value) {
17
+ return value !== null && typeof value === "object" && value.name === "pattern" && "createIndex" in value && typeof value.createIndex === "function" && "readArrays" in value && typeof value.readArrays === "function" && "mergeArrays" in value && typeof value.mergeArrays === "function" && "matchInto" in value && typeof value.matchInto === "function" && "checkExpression" in value && typeof value.checkExpression === "function" && "expressionFootprint" in value && typeof value.expressionFootprint === "function";
18
+ }
19
+ function registerPatternSearch(module) {
20
+ if (!isPatternSearchModule(module)) {
21
+ throw new NarsilError(
22
+ ErrorCodes.CONFIG_INVALID,
23
+ 'registerPatternSearch takes the patternSearch object that "@delali/narsil/pattern" exports'
24
+ );
25
+ }
26
+ registered = module;
27
+ }
28
+ function availablePatternSearch() {
29
+ return registered ?? platformPatternSearch();
30
+ }
31
+ function requirePatternSearchFor(schema) {
32
+ for (const { path, pattern } of schemaFieldsOf(schema)) {
33
+ if (pattern) requirePatternSearch(path);
34
+ }
35
+ }
36
+ function requirePatternSearch(fieldPath) {
37
+ const module = availablePatternSearch();
38
+ if (module !== null) return module;
39
+ throw new NarsilError(
40
+ ErrorCodes.CONFIG_INVALID,
41
+ `Field "${fieldPath}" is a pattern field, but this bundle contains no pattern search code. Add import { patternSearch } from '@delali/narsil/pattern', then call registerPatternSearch(patternSearch) before you create or load the index`,
42
+ { field: fieldPath }
43
+ );
44
+ }
45
+
8
46
  // src/core/pattern-index/work-meter.ts
9
47
  var COUNTER_BYTES = 8;
10
48
  function capExceeded(cap) {
@@ -529,12 +567,6 @@ function decodeCursorText(encoded) {
529
567
  return new TextDecoder().decode(bytes);
530
568
  }
531
569
 
532
- // src/filters/constants.ts
533
- var MAX_FILTER_DEPTH = 30;
534
- var MAX_FILTER_TESTS = 1024;
535
- var MAX_FILTER_ARRAY_SIZE = 65536;
536
- var GEO_UNIT_METRES = { km: 1e3, mi: 1609.344, m: 1 };
537
-
538
570
  // src/filters/operands/checks.ts
539
571
  function operandKindOf(type) {
540
572
  if (type === void 0) return void 0;
@@ -955,6 +987,34 @@ function requireSizeOperands(fieldPath, filter, type) {
955
987
  }
956
988
  }
957
989
 
990
+ // src/core/pattern-index/host.ts
991
+ var NO_SOURCES = [];
992
+ var foldSources = null;
993
+ function sourcesByFold() {
994
+ if (foldSources !== null) return foldSources;
995
+ const sources = /* @__PURE__ */ new Map();
996
+ const add = (source, folded) => {
997
+ const known = sources.get(folded);
998
+ if (known === void 0) sources.set(folded, [source]);
999
+ else known.push(source);
1000
+ };
1001
+ for (const [source, folded] of singleFoldTable()) add(source, folded);
1002
+ foldSources = sources;
1003
+ return sources;
1004
+ }
1005
+ function singleFoldSources(folded) {
1006
+ return sourcesByFold().get(folded) ?? NO_SOURCES;
1007
+ }
1008
+ var PATTERN_HOST = { appendFoldedCodePoint, singleFoldSources };
1009
+ function patternIndexOf(indexes, fieldPath) {
1010
+ let index = indexes.get(fieldPath);
1011
+ if (index === void 0) {
1012
+ index = requirePatternSearch(fieldPath).createIndex(PATTERN_HOST);
1013
+ indexes.set(fieldPath, index);
1014
+ }
1015
+ return index;
1016
+ }
1017
+
958
1018
  // src/filters/operands/pattern.ts
959
1019
  function requirePatternField(fieldPath, operator, type) {
960
1020
  if (parsedTypeOf(type)?.pattern === true) return;
@@ -965,14 +1025,16 @@ function requirePatternField(fieldPath, operator, type) {
965
1025
  operator
966
1026
  );
967
1027
  }
1028
+ function requireTextLength(fieldPath, operator, text) {
1029
+ if (!exceedsCodePoints(text, MAX_PATTERN_TEXT_CODE_POINTS)) return;
1030
+ invalid(
1031
+ `The text of "${operator}" on pattern field "${fieldPath}" holds more than ${MAX_PATTERN_TEXT_CODE_POINTS} code points`,
1032
+ fieldPath,
1033
+ operator
1034
+ );
1035
+ }
968
1036
  function requirePatternText(fieldPath, operator, text, caseFold) {
969
- if (exceedsCodePoints(text, MAX_PATTERN_TEXT_CODE_POINTS)) {
970
- invalid(
971
- `The text of "${operator}" on pattern field "${fieldPath}" holds more than ${MAX_PATTERN_TEXT_CODE_POINTS} code points`,
972
- fieldPath,
973
- operator
974
- );
975
- }
1037
+ requireTextLength(fieldPath, operator, text);
976
1038
  if (caseFold && foldedCodePointCount(text) > MAX_PATTERN_POSITIONS) {
977
1039
  invalid(
978
1040
  `The text of "${operator}" on pattern field "${fieldPath}" has a case fold of more than ${MAX_PATTERN_POSITIONS} code points, while a pattern holds at most ${MAX_PATTERN_POSITIONS} positions`,
@@ -982,6 +1044,23 @@ function requirePatternText(fieldPath, operator, text, caseFold) {
982
1044
  }
983
1045
  }
984
1046
  var ELEMENT_OPERATORS2 = ["matchesAny", "containsAll"];
1047
+ function requireExpressions(fieldPath, filter, type) {
1048
+ for (const operator of PATTERN_EXPRESSION_OPERATORS) {
1049
+ const pattern = filter[operator];
1050
+ if (pattern === void 0) continue;
1051
+ if (typeof pattern !== "string")
1052
+ invalid(`"${operator}" on field "${fieldPath}" must be a string`, fieldPath, operator);
1053
+ requirePatternField(fieldPath, operator, type);
1054
+ requireTextLength(fieldPath, operator, pattern);
1055
+ requirePatternSearch(fieldPath).checkExpression(
1056
+ operator,
1057
+ pattern,
1058
+ filter.caseFold === true,
1059
+ fieldPath,
1060
+ PATTERN_HOST
1061
+ );
1062
+ }
1063
+ }
985
1064
  function requirePatternOperands(fieldPath, filter, type) {
986
1065
  if (filter.contains !== void 0) {
987
1066
  if (typeof filter.contains !== "string") {
@@ -995,6 +1074,8 @@ function requirePatternOperands(fieldPath, filter, type) {
995
1074
  }
996
1075
  requirePatternField(fieldPath, "caseFold", type);
997
1076
  }
1077
+ requireExpressions(fieldPath, filter, type);
1078
+ if (filter.tolerance !== void 0) requirePatternField(fieldPath, "tolerance", type);
998
1079
  if (parsedTypeOf(type)?.pattern !== true) return;
999
1080
  const caseFold = filter.caseFold === true;
1000
1081
  for (const operator of PATTERN_TEST_OPERATORS) {
@@ -1012,6 +1093,31 @@ function requirePatternOperands(fieldPath, filter, type) {
1012
1093
  if (typeof text === "string") requirePatternText(fieldPath, operator, text, false);
1013
1094
  }
1014
1095
  }
1096
+ requireTolerance(fieldPath, filter);
1097
+ }
1098
+ function requireTolerance(fieldPath, filter) {
1099
+ const { tolerance, eq } = filter;
1100
+ if (tolerance === void 0) return;
1101
+ if (!isPatternTolerance(tolerance)) {
1102
+ invalid(`"tolerance" on field "${fieldPath}" must be 0, 1, 2, or "auto"`, fieldPath, "tolerance");
1103
+ }
1104
+ if (typeof eq !== "string") {
1105
+ invalid(
1106
+ `"tolerance" applies only to an "eq" test, while the filter on field "${fieldPath}" sets no "eq" with text`,
1107
+ fieldPath,
1108
+ "tolerance"
1109
+ );
1110
+ }
1111
+ if (tolerance === 0 || tolerance === "auto") return;
1112
+ const text = foldTypoText(eq, PATTERN_HOST);
1113
+ const requiredRuns = typoRunsNeeded(tolerance, text.longestFold);
1114
+ const distinctRuns = distinctTypoRunCount(text, requiredRuns);
1115
+ if (distinctRuns >= requiredRuns) return;
1116
+ throw new NarsilError(
1117
+ ErrorCodes.SEARCH_INVALID_FILTER,
1118
+ `A tolerance of ${tolerance} on "eq" of pattern field "${fieldPath}" needs ${requiredRuns} distinct runs of three code points in the case fold of the text, while the text holds ${distinctRuns}. Lengthen the text, lower the tolerance, or set it to "auto"`,
1119
+ { fieldPath, operator: "tolerance", requiredRuns, distinctRuns }
1120
+ );
1015
1121
  }
1016
1122
  function requireWellFormedText(fieldPath, filter) {
1017
1123
  for (const [operator, operand] of Object.entries(filter)) {
@@ -1033,6 +1139,7 @@ var TEXT_OPERATORS = ["startsWith", "endsWith"];
1033
1139
  var EQUALITY_OPERATORS = ["eq", "ne"];
1034
1140
  var LIST_OPERATORS = ["in", "nin"];
1035
1141
  var GEO_OPERATORS = ["radius", "polygon"];
1142
+ var TEST_MODIFIERS = /* @__PURE__ */ new Set(["caseFold", "tolerance"]);
1036
1143
  function invalidShape(message) {
1037
1144
  throw new NarsilError(ErrorCodes.SEARCH_INVALID_FILTER, message);
1038
1145
  }
@@ -1136,7 +1243,7 @@ function filterTestCount(expression) {
1136
1243
  function testsIn(filter) {
1137
1244
  let tests = 0;
1138
1245
  for (const [operator, operand] of Object.entries(filter)) {
1139
- if (operator === "caseFold") continue;
1246
+ if (TEST_MODIFIERS.has(operator)) continue;
1140
1247
  tests += operator === "size" && isObjectRecord(operand) ? Math.max(1, Object.keys(operand).length) : 1;
1141
1248
  }
1142
1249
  return Math.max(1, tests);
@@ -2078,4 +2185,4 @@ function setNestedValue(obj, path, value) {
2078
2185
  current[segments[segments.length - 1]] = value;
2079
2186
  }
2080
2187
 
2081
- export { GEO_UNIT_METRES, MAX_FILTER_ARRAY_SIZE, MAX_FILTER_DEPTH, MAX_FILTER_TESTS, applyPagination, applyProjection, applySorting, clampRowCount, cloneProjected, collectQueryTermStats, computeFacets, countsWithoutScores, coveringRanges, createPatternWorkMeter, decodePageCursor, encodePageCursor, everyValueFacetConfig, fanOutMatchCount, fanOutQuery, filterTestCount, fnv1a, fnv1aBytes, fnv1aUint32s, fulltextMatches, joinPatternWorkMeter, kWayMerge, locationCode, mergeFacets, mergePartitionStats, normalizeSort, oversampledFacetConfig, oversampledShardSize, partitionsIn, polygonBoxes, polygonContainment, projectionKeepsField, pruneStatsToQueryTerms, radiusBoxes, readSortValues, requireMatchingCursor, requireSortableFields, requireValidFilter, requireValidOperands, requireWithinResultWindow, resolveProjection, sanitizeGlobalStats, setNestedValue, sortModesOf, sortSignatureEntry, sortSignatureOf, undeclaredFieldOnStrictIndex, undeclaredFilterField };
2188
+ export { PATTERN_HOST, applyPagination, applyProjection, applySorting, availablePatternSearch, clampRowCount, cloneProjected, collectQueryTermStats, computeFacets, countsWithoutScores, coveringRanges, createPatternWorkMeter, decodePageCursor, encodePageCursor, everyValueFacetConfig, fanOutMatchCount, fanOutQuery, filterTestCount, fnv1a, fnv1aBytes, fnv1aUint32s, fulltextMatches, joinPatternWorkMeter, kWayMerge, locationCode, mergeFacets, mergePartitionStats, normalizeSort, oversampledFacetConfig, oversampledShardSize, partitionsIn, patternIndexOf, polygonBoxes, polygonContainment, projectionKeepsField, pruneStatsToQueryTerms, radiusBoxes, readSortValues, registerPatternSearch, requireMatchingCursor, requirePatternSearch, requirePatternSearchFor, requireSortableFields, requireValidFilter, requireValidOperands, requireWithinResultWindow, resolveProjection, sanitizeGlobalStats, setNestedValue, sortModesOf, sortSignatureEntry, sortSignatureOf, undeclaredFieldOnStrictIndex, undeclaredFilterField };
@@ -1,15 +1,15 @@
1
- import { joinPatternWorkMeter, countsWithoutScores, fanOutMatchCount, fanOutQuery, sanitizeGlobalStats, computeFacets, cloneProjected, projectionKeepsField, setNestedValue, fnv1a, everyValueFacetConfig, mergeFacets, undeclaredFilterField, requireValidOperands, kWayMerge, polygonContainment, polygonBoxes, radiusBoxes, locationCode, coveringRanges, GEO_UNIT_METRES } from './chunk-VKX2BPXD.mjs';
1
+ import { requirePatternSearchFor, patternIndexOf, joinPatternWorkMeter, countsWithoutScores, fanOutMatchCount, fanOutQuery, sanitizeGlobalStats, computeFacets, cloneProjected, projectionKeepsField, setNestedValue, fnv1a, requirePatternSearch, PATTERN_HOST, everyValueFacetConfig, mergeFacets, undeclaredFilterField, requireValidOperands, kWayMerge, polygonContainment, polygonBoxes, radiusBoxes, locationCode, coveringRanges } from './chunk-D4EF7J3I.mjs';
2
2
  import { getLanguage, detectRuntime } from './chunk-4MQ5F4IL.mjs';
3
- import { MAX_DOC_ID_LENGTH } from './chunk-3DDUNI6N.mjs';
4
- import { SCRATCH_SLOTS_PER_THREAD_POOL, osqRecordBytes, openSharedVectorField, osqBitsOf, createVectorStore, DISK_STORAGE_BLOCK_BYTES, createOsqQuantizer, magnitude, createHNSWIndex, nativeStoreScratchBytes, createOrdinalFilter, isTombstoned, addToOrdinalFilter, ordinalFilterValues, nativeScoresOf, toScore, removeFromOrdinalFilter, euclideanDistance, dotProduct, cosineSimilarityWithMagnitudes, ordinalFilterHas, STORE_CALIBRATION_GENERATION, entryForOrd, toDistance, sharedMemoryAvailable, requireWholeNeighbourLists, topLayerInParts, GRAPH_BUILD_CHUNKS_IN_FLIGHT_PER_WORKER, GRAPH_BUILD_DISPATCH_CHUNK, releaseLocksHeldBy, VECTOR_SEARCH_TIMEOUT_MS, VECTOR_SEARCH_LOAD_TIMEOUT_MS, VECTOR_INSERT_TIMEOUT_MS, VECTOR_SCRATCH_SLOTS } from './chunk-PO53FV4Q.mjs';
3
+ import { MAX_DOC_ID_LENGTH, GEO_UNIT_METRES } from './chunk-V3B24XR7.mjs';
4
+ import { SCRATCH_SLOTS_PER_THREAD_POOL, osqRecordBytes, openSharedVectorField, osqBitsOf, createVectorStore, DISK_STORAGE_BLOCK_BYTES, createOsqQuantizer, magnitude, createHNSWIndex, nativeStoreScratchBytes, createOrdinalFilter, isTombstoned, addToOrdinalFilter, ordinalFilterValues, nativeScoresOf, toScore, removeFromOrdinalFilter, euclideanDistance, dotProduct, cosineSimilarityWithMagnitudes, ordinalFilterHas, STORE_CALIBRATION_GENERATION, entryForOrd, toDistance, sharedMemoryAvailable, requireWholeNeighbourLists, topLayerInParts, GRAPH_BUILD_CHUNKS_IN_FLIGHT_PER_WORKER, GRAPH_BUILD_DISPATCH_CHUNK, releaseLocksHeldBy, VECTOR_SEARCH_TIMEOUT_MS, VECTOR_SEARCH_LOAD_TIMEOUT_MS, VECTOR_INSERT_TIMEOUT_MS, VECTOR_SCRATCH_SLOTS } from './chunk-AMGDG4ZJ.mjs';
5
5
  import { noteFallback } from './chunk-2E35UM3G.mjs';
6
- import { GrowableUint32, patternSearchModule } from './chunk-XW25X6AU.mjs';
7
- import { bitsetHas, createBitSet, bitsetSet, bitsetOrInto, bitsetAndNotInto, bitsetAndInto, PATTERN_RUN_CODE_POINTS, bitsetFromSet, bitsetIsEmpty, bitsetAnd, bitsetNot } from './chunk-ZKRV5M2P.mjs';
8
- import { encodePartialSpellings, countSpelling, expandTermPrefix, suggestDisplayTerms, spellingCountsOf, codePointOrder, encodeStringBlob, partialWordSearchModule, partitionDocumentFrequency } from './chunk-T5ZWEWVD.mjs';
9
- import { tokenizeOptions, getNestedValue, visitTokens, textFieldsChanged, fuzzyPrefixOf, boundedLevenshtein, getFlatSchema, tokenize, getOrCreateFieldNameIndex, tokenizeIterator, getFieldValueByInternalId } from './chunk-I23G3IZC.mjs';
10
- import { schemaFieldsOf, partialFieldsOf, isWordIndexedBase, validateDocument, validateDocumentStrict, encodeDocument, extractVectorFieldsFromSchema, parsedTypeOf, isListBase, VINCENTY_CONVERGENCE_THRESHOLD, EARTH_RADIUS_METERS, VINCENTY_MAX_ITERATIONS, DEG_TO_RAD } from './chunk-Z3DQPOJQ.mjs';
6
+ import { GrowableUint32, bitsetHas, createBitSet, bitsetSet, bitsetOrInto, bitsetAndNotInto, bitsetAndInto, PATTERN_RUN_CODE_POINTS, bitsetFromSet, isPatternTolerance, bitsetIsEmpty, bitsetAnd, bitsetNot } from './chunk-4344I4MR.mjs';
7
+ import { encodePartialSpellings, countSpelling, expandTermPrefix, suggestDisplayTerms, spellingCountsOf, codePointOrder, encodeStringBlob, partialWordSearchModule, partitionDocumentFrequency } from './chunk-PJU6EF22.mjs';
8
+ import { tokenizeOptions, getNestedValue, visitTokens, textFieldsChanged, getFlatSchema, tokenize, getOrCreateFieldNameIndex, tokenizeIterator, getFieldValueByInternalId } from './chunk-NO3ABFLE.mjs';
9
+ import { partialFieldsOf, schemaFieldsOf, isWordIndexedBase, validateDocument, validateDocumentStrict, encodeDocument, extractVectorFieldsFromSchema, parsedTypeOf, isListBase, VINCENTY_CONVERGENCE_THRESHOLD, EARTH_RADIUS_METERS, VINCENTY_MAX_ITERATIONS, DEG_TO_RAD } from './chunk-356UOTK2.mjs';
11
10
  import { MAX_M, EARLIER_RELEASE_MIN_M, MIN_M } from './chunk-KEHK2O6P.mjs';
12
- import { compareCodePoints, appendFoldedCodePoint, toReducedSortValue, readSortField, defaultSortMode, compareComparableValues, truncateSortString, SORT_VALUE_MAX_CODE_POINTS } from './chunk-LJYTW7GT.mjs';
11
+ import { fuzzyPrefixOf, boundedLevenshtein } from './chunk-GES7U2PM.mjs';
12
+ import { compareCodePoints, toReducedSortValue, readSortField, defaultSortMode, compareComparableValues, truncateSortString, SORT_VALUE_MAX_CODE_POINTS } from './chunk-IBR6634K.mjs';
13
13
  import { NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
14
14
  import { totalmem } from 'os';
15
15
  import { getHeapStatistics } from 'v8';
@@ -944,54 +944,6 @@ function createSurfaceRegistry() {
944
944
  };
945
945
  }
946
946
 
947
- // src/core/pattern-index/platform.ts
948
- function platformPatternSearch() {
949
- return patternSearchModule;
950
- }
951
-
952
- // src/core/pattern-index/registry.ts
953
- var registered = null;
954
- function isPatternSearchModule(value) {
955
- return value !== null && typeof value === "object" && value.name === "pattern" && "createIndex" in value && typeof value.createIndex === "function" && "readArrays" in value && typeof value.readArrays === "function" && "mergeArrays" in value && typeof value.mergeArrays === "function" && "matchInto" in value && typeof value.matchInto === "function";
956
- }
957
- function registerPatternSearch(module) {
958
- if (!isPatternSearchModule(module)) {
959
- throw new NarsilError(
960
- ErrorCodes.CONFIG_INVALID,
961
- 'registerPatternSearch takes the patternSearch object that "@delali/narsil/pattern" exports'
962
- );
963
- }
964
- registered = module;
965
- }
966
- function availablePatternSearch() {
967
- return registered ?? platformPatternSearch();
968
- }
969
- function requirePatternSearchFor(schema) {
970
- for (const { path, pattern } of schemaFieldsOf(schema)) {
971
- if (pattern) requirePatternSearch(path);
972
- }
973
- }
974
- function requirePatternSearch(fieldPath) {
975
- const module = availablePatternSearch();
976
- if (module !== null) return module;
977
- throw new NarsilError(
978
- ErrorCodes.CONFIG_INVALID,
979
- `Field "${fieldPath}" is a pattern field, but this bundle contains no pattern search code. Add import { patternSearch } from '@delali/narsil/pattern', then call registerPatternSearch(patternSearch) before you create or load the index`,
980
- { field: fieldPath }
981
- );
982
- }
983
-
984
- // src/core/pattern-index/host.ts
985
- var PATTERN_HOST = { appendFoldedCodePoint };
986
- function patternIndexOf(indexes, fieldPath) {
987
- let index = indexes.get(fieldPath);
988
- if (index === void 0) {
989
- index = requirePatternSearch(fieldPath).createIndex(PATTERN_HOST);
990
- indexes.set(fieldPath, index);
991
- }
992
- return index;
993
- }
994
-
995
947
  // src/geo/haversine.ts
996
948
  function haversineDistance(lat1, lon1, lat2, lon2) {
997
949
  const phi1 = lat1 * DEG_TO_RAD;
@@ -2023,18 +1975,21 @@ function textsOf(operand) {
2023
1975
  }
2024
1976
  function evaluatePatternTests(fieldPath, filter, context, bitsets) {
2025
1977
  const caseFold = filter.caseFold === true;
2026
- const matching = (operator, texts) => {
1978
+ const matching = (operator, texts, tolerance = 0) => {
2027
1979
  const into = createBitSet(context.capacity);
2028
- for (const text of texts) context.matchPattern(fieldPath, operator, text, caseFold, into);
1980
+ for (const text of texts) context.matchPattern(fieldPath, operator, text, caseFold, tolerance, into);
2029
1981
  return into;
2030
1982
  };
2031
- if (typeof filter.eq === "string") bitsets.push(matching("eq", [filter.eq]));
1983
+ const eqTolerance = isPatternTolerance(filter.tolerance) ? filter.tolerance : 0;
1984
+ if (typeof filter.eq === "string") bitsets.push(matching("eq", [filter.eq], eqTolerance));
2032
1985
  if (typeof filter.ne === "string") bitsets.push(excluding(context, fieldPath, matching("eq", [filter.ne])));
2033
1986
  if (filter.in !== void 0) bitsets.push(matching("eq", textsOf(filter.in)));
2034
1987
  if (filter.nin !== void 0) bitsets.push(excluding(context, fieldPath, matching("eq", textsOf(filter.nin))));
2035
1988
  if (typeof filter.startsWith === "string") bitsets.push(matching("startsWith", [filter.startsWith]));
2036
1989
  if (typeof filter.endsWith === "string") bitsets.push(matching("endsWith", [filter.endsWith]));
2037
1990
  if (typeof filter.contains === "string") bitsets.push(matching("contains", [filter.contains]));
1991
+ if (typeof filter.wildcard === "string") bitsets.push(matching("wildcard", [filter.wildcard]));
1992
+ if (typeof filter.regex === "string") bitsets.push(matching("regex", [filter.regex]));
2038
1993
  }
2039
1994
 
2040
1995
  // src/filters/field-tests.ts
@@ -2082,7 +2037,7 @@ function elementBits(context, fieldPath, parsed, value) {
2082
2037
  const { capacity } = context;
2083
2038
  if (parsed.pattern) {
2084
2039
  const matches = createBitSet(capacity);
2085
- context.matchPattern(fieldPath, "eq", value, false, matches);
2040
+ context.matchPattern(fieldPath, "eq", value, false, 0, matches);
2086
2041
  return matches;
2087
2042
  }
2088
2043
  if (typeof value === "number")
@@ -2095,7 +2050,7 @@ function anyElementBits(context, fieldPath, parsed, values) {
2095
2050
  const { capacity } = context;
2096
2051
  const union = createBitSet(capacity);
2097
2052
  if (parsed.pattern) {
2098
- for (const value of values) context.matchPattern(fieldPath, "eq", value, false, union);
2053
+ for (const value of values) context.matchPattern(fieldPath, "eq", value, false, 0, union);
2099
2054
  return union;
2100
2055
  }
2101
2056
  if (parsed.base === "enum[]") {
@@ -2239,7 +2194,10 @@ var FIELD_FILTER_OPERATORS = [
2239
2194
  "startsWith",
2240
2195
  "endsWith",
2241
2196
  "contains",
2197
+ "wildcard",
2198
+ "regex",
2242
2199
  "caseFold",
2200
+ "tolerance",
2243
2201
  "containsAll",
2244
2202
  "matchesAny",
2245
2203
  "size",
@@ -2973,13 +2931,14 @@ function buildFilterContext(state, schema, meter) {
2973
2931
  sizeIndex: (fieldPath) => state.sizeIndexes.get(fieldPath),
2974
2932
  textRangeBitset: (fieldPath, bounds) => textRangeBitsetOf(state, fieldPath, flat[fieldPath], bounds, capacity),
2975
2933
  isPatternField: (fieldPath) => patternFields.has(fieldPath),
2976
- matchPattern: (fieldPath, operator, text, caseFold, into) => {
2934
+ matchPattern: (fieldPath, operator, text, caseFold, tolerance, into) => {
2977
2935
  const index = state.patternIndexes.get(fieldPath);
2978
2936
  if (index === void 0) return;
2979
2937
  requirePatternSearch(fieldPath).matchInto({
2980
2938
  operator,
2981
2939
  text,
2982
2940
  caseFold,
2941
+ tolerance,
2983
2942
  index,
2984
2943
  matches: into,
2985
2944
  meter,
@@ -3525,7 +3484,7 @@ function platformPartialWordSearch() {
3525
3484
  }
3526
3485
 
3527
3486
  // src/core/partition/partial-words/registry.ts
3528
- var registered2 = null;
3487
+ var registered = null;
3529
3488
  function isPartialWordSearchModule(value) {
3530
3489
  return value !== null && typeof value === "object" && value.name === "partialWords" && "createGrowingSlot" in value && typeof value.createGrowingSlot === "function" && "createFrozenSlot" in value && typeof value.createFrozenSlot === "function" && "buildTable" in value && typeof value.buildTable === "function" && "expand" in value && typeof value.expand === "function";
3531
3490
  }
@@ -3536,10 +3495,10 @@ function registerPartialWordSearch(module) {
3536
3495
  'Pass registerPartialWordSearch the partialWordSearch object that "@delali/narsil/partial-words" exports'
3537
3496
  );
3538
3497
  }
3539
- registered2 = module;
3498
+ registered = module;
3540
3499
  }
3541
3500
  function availablePartialWordSearch() {
3542
- return registered2 ?? platformPartialWordSearch();
3501
+ return registered ?? platformPartialWordSearch();
3543
3502
  }
3544
3503
  function requirePartialWordSearchFor(schema) {
3545
3504
  const fields = partialFieldsOf(schema);
@@ -11179,4 +11138,4 @@ function createDirectExecutor(options) {
11179
11138
  };
11180
11139
  }
11181
11140
 
11182
- export { CHECKSUM_YIELD_CHUNK_BYTES, CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, FIELD_FILTER_OPERATORS, FILTER_EXPRESSION_KEYS, MAX_FILE_BYTES, NATIVE_CRC32_MIN_BYTES, NO_LIVE_VECTOR_AT_POSITION, SHUTDOWN_TIMEOUT_MS, VALID_HNSW_METRICS, VECTOR_FILE_MAX_VECTORS, VECTOR_FILE_PAYLOAD_VERSION, assembleGraphParts, buildSegmentPayload, bytesToVectors, countDead, createDirectExecutor, createFrozenSegment, createPartitionIndex, createPartitionManager, createPartitionRouter, createSharedFrozenSegment, deadBitsWhere, deadBytesFor, decodeEveryStoredDocument, decodeMapWithoutFields, decodeStoredDocument, decodeVectorFilePayload, decodeVectorGraphPartPayload, decodeVectorGraphPayload, decodeVectorIndexParts, encodeSegmentState, freezeSegmentShared, generateId, getStopWords, getTokenizer, graphPartsOfEarlierPayload, hasStopWords, hasTokenizer, isCompositePartition, isDead, mergeFrozenSegments, mergeSegmentContents, missingWorkerEntry, nodeThreadId, partitionStateOf, readHeapStatistics, registerPartialWordSearch, registerPatternSearch, registerStopWords, registerTokenizer, requirePartialWordSearchFor, requirePatternSearchFor, resolveIndexAnalysis, resolvePartitionInsertOptions, resolveRequestThreadCount, resolveWorkerCount, resolveWorkerEntry, segmentArraysOf, selectionKeeps, shareSegmentArrays, spawnNodeWorker, splitWorkerBudget, survivorDocumentsOf, vectorsPerFile, vectorsToBytes, workerResourceLimits };
11141
+ export { CHECKSUM_YIELD_CHUNK_BYTES, CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, FIELD_FILTER_OPERATORS, FILTER_EXPRESSION_KEYS, MAX_FILE_BYTES, NATIVE_CRC32_MIN_BYTES, NO_LIVE_VECTOR_AT_POSITION, SHUTDOWN_TIMEOUT_MS, VALID_HNSW_METRICS, VECTOR_FILE_MAX_VECTORS, VECTOR_FILE_PAYLOAD_VERSION, assembleGraphParts, buildSegmentPayload, bytesToVectors, countDead, createDirectExecutor, createFrozenSegment, createPartitionIndex, createPartitionManager, createPartitionRouter, createSharedFrozenSegment, deadBitsWhere, deadBytesFor, decodeEveryStoredDocument, decodeMapWithoutFields, decodeStoredDocument, decodeVectorFilePayload, decodeVectorGraphPartPayload, decodeVectorGraphPayload, decodeVectorIndexParts, encodeSegmentState, freezeSegmentShared, generateId, getStopWords, getTokenizer, graphPartsOfEarlierPayload, hasStopWords, hasTokenizer, isCompositePartition, isDead, mergeFrozenSegments, mergeSegmentContents, missingWorkerEntry, nodeThreadId, partitionStateOf, readHeapStatistics, registerPartialWordSearch, registerStopWords, registerTokenizer, requirePartialWordSearchFor, resolveIndexAnalysis, resolvePartitionInsertOptions, resolveRequestThreadCount, resolveWorkerCount, resolveWorkerEntry, segmentArraysOf, selectionKeeps, shareSegmentArrays, spawnNodeWorker, splitWorkerBudget, survivorDocumentsOf, vectorsPerFile, vectorsToBytes, workerResourceLimits };
@@ -1,9 +1,10 @@
1
- import { clampRowCount, sortSignatureOf, requireSortableFields, decodePageCursor, requireMatchingCursor, resolveProjection, encodePageCursor, requireWithinResultWindow, normalizeSort, fanOutQuery, sortModesOf, applySorting, applyPagination, projectionKeepsField, countsWithoutScores, fanOutMatchCount, fnv1aBytes, requireValidFilter, createPatternWorkMeter, everyValueFacetConfig, fulltextMatches, mergeFacets, pruneStatsToQueryTerms, partitionsIn, undeclaredFieldOnStrictIndex } from './chunk-VKX2BPXD.mjs';
2
- import { MAX_INDEX_NAME_LENGTH, INDEX_NAME_PATTERN, MAX_DOC_ID_LENGTH, DEFAULT_LIMIT, DEFAULT_MAX_PER_GROUP, DEFAULT_SUGGEST_LIMIT, MAX_SUGGEST_LIMIT, MAX_SUGGEST_SCATTER_LIMIT, ABSOLUTE_WINDOWS_PATH_PATTERN, MODULE_URL_SCHEME_PATTERN, DEFAULT_LINEAR_ALPHA, MIN_LINEAR_ALPHA, MAX_LINEAR_ALPHA, DEFAULT_RANK_CONSTANT, MIN_RANK_CONSTANT, DEFAULT_OFFSET, DEFAULT_FUZZY_PREFIX_LENGTH, RESULT_WINDOW, PARTIAL_WORD_MIN_CODE_POINTS, PARTIAL_WORDS_ADDED_PER_QUERY, MAX_TOLERANCE, MAX_PREFIX_LENGTH } from './chunk-3DDUNI6N.mjs';
1
+ import { clampRowCount, sortSignatureOf, requireSortableFields, decodePageCursor, requireMatchingCursor, resolveProjection, encodePageCursor, requireWithinResultWindow, normalizeSort, fanOutQuery, sortModesOf, applySorting, applyPagination, projectionKeepsField, countsWithoutScores, fanOutMatchCount, fnv1aBytes, requireValidFilter, createPatternWorkMeter, everyValueFacetConfig, fulltextMatches, mergeFacets, pruneStatsToQueryTerms, partitionsIn, undeclaredFieldOnStrictIndex } from './chunk-D4EF7J3I.mjs';
2
+ import { MAX_INDEX_NAME_LENGTH, INDEX_NAME_PATTERN, MAX_DOC_ID_LENGTH, DEFAULT_LIMIT, DEFAULT_MAX_PER_GROUP, DEFAULT_SUGGEST_LIMIT, MAX_SUGGEST_LIMIT, MAX_SUGGEST_SCATTER_LIMIT, ABSOLUTE_WINDOWS_PATH_PATTERN, MODULE_URL_SCHEME_PATTERN, DEFAULT_LINEAR_ALPHA, MIN_LINEAR_ALPHA, MAX_LINEAR_ALPHA, DEFAULT_RANK_CONSTANT, MIN_RANK_CONSTANT, DEFAULT_OFFSET, DEFAULT_FUZZY_PREFIX_LENGTH, RESULT_WINDOW, PARTIAL_WORD_MIN_CODE_POINTS, PARTIAL_WORDS_ADDED_PER_QUERY, MAX_TOLERANCE, MAX_PREFIX_LENGTH } from './chunk-V3B24XR7.mjs';
3
3
  import { MIN_OVERSAMPLE } from './chunk-ZJ4CSAB2.mjs';
4
- import { tokenize, fuzzyTermMatches } from './chunk-I23G3IZC.mjs';
5
- import { partialFieldsOf, MIN_PATTERN_VALUE_LIMIT, MAX_PATTERN_VALUE_LIMIT, flattenSchema, isWordIndexedFieldType, isGeopointOrVectorType } from './chunk-Z3DQPOJQ.mjs';
6
- import { holdsUnpairedSurrogate, compareCodePoints, compareComparableKeys, codePointCount } from './chunk-LJYTW7GT.mjs';
4
+ import { tokenize } from './chunk-NO3ABFLE.mjs';
5
+ import { partialFieldsOf, MIN_PATTERN_VALUE_LIMIT, MAX_PATTERN_VALUE_LIMIT, flattenSchema, isWordIndexedFieldType, isGeopointOrVectorType } from './chunk-356UOTK2.mjs';
6
+ import { fuzzyTermMatches } from './chunk-GES7U2PM.mjs';
7
+ import { holdsUnpairedSurrogate, compareCodePoints, compareComparableKeys, codePointCount } from './chunk-IBR6634K.mjs';
7
8
  import { NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
8
9
 
9
10
  // src/search/cursor-binding.ts
@@ -0,0 +1,68 @@
1
+ // src/core/fuzzy.ts
2
+ var FIRST_SURROGATE = 55296;
3
+ var LAST_SURROGATE = 57343;
4
+ var LAST_BASIC_PLANE_CODE_POINT = 65535;
5
+ function hasSurrogate(text) {
6
+ for (let index = 0; index < text.length; index++) {
7
+ const unit = text.charCodeAt(index);
8
+ if (unit >= FIRST_SURROGATE && unit <= LAST_SURROGATE) return true;
9
+ }
10
+ return false;
11
+ }
12
+ function fuzzyPrefixOf(queryTerm, prefixLength) {
13
+ let end = 0;
14
+ for (let counted = 0; counted < prefixLength && end < queryTerm.length; counted++) {
15
+ const codePoint = queryTerm.codePointAt(end);
16
+ end += codePoint !== void 0 && codePoint > LAST_BASIC_PLANE_CODE_POINT ? 2 : 1;
17
+ }
18
+ return queryTerm.slice(0, end);
19
+ }
20
+ function fuzzyTermMatches(queryTerm, indexTerm, tolerance, prefixLength) {
21
+ if (queryTerm === indexTerm) return true;
22
+ if (tolerance <= 0) return false;
23
+ if (!indexTerm.startsWith(fuzzyPrefixOf(queryTerm, prefixLength))) return false;
24
+ return boundedLevenshtein(queryTerm, indexTerm, tolerance).withinTolerance;
25
+ }
26
+ function boundedLevenshtein(a, b, tolerance) {
27
+ if (tolerance < 0) return { distance: -1, withinTolerance: false, cells: 0 };
28
+ if (a === b) return { distance: 0, withinTolerance: true, cells: 0 };
29
+ return tabulatedLevenshtein(a, b, tolerance);
30
+ }
31
+ function tabulatedLevenshtein(a, b, tolerance) {
32
+ if (tolerance < 0) return { distance: -1, withinTolerance: false, cells: 0 };
33
+ if (hasSurrogate(a) || hasSurrogate(b)) return bandedDistance(Array.from(a), Array.from(b), tolerance);
34
+ return bandedDistance(a, b, tolerance);
35
+ }
36
+ function bandedDistance(a, b, tolerance) {
37
+ const m = a.length;
38
+ const n = b.length;
39
+ const beyond = tolerance + 1;
40
+ if (Math.abs(m - n) > tolerance) return { distance: beyond, withinTolerance: false, cells: 0 };
41
+ let previous = new Uint32Array(n + 1).fill(beyond);
42
+ let current = new Uint32Array(n + 1).fill(beyond);
43
+ const firstRowEnd = Math.min(n, tolerance);
44
+ for (let j = 0; j <= firstRowEnd; j++) previous[j] = j;
45
+ let cells = 0;
46
+ for (let i = 1; i <= m; i++) {
47
+ const low = Math.max(1, i - tolerance);
48
+ const high = Math.min(n, i + tolerance);
49
+ current[low - 1] = low === 1 ? i : beyond;
50
+ let rowMin = current[low - 1];
51
+ const character = a[i - 1];
52
+ if (high >= low) cells += high - low + 1;
53
+ for (let j = low; j <= high; j++) {
54
+ const substitution = previous[j - 1] + (character === b[j - 1] ? 0 : 1);
55
+ const cell = Math.min(previous[j] + 1, current[j - 1] + 1, substitution, beyond);
56
+ current[j] = cell;
57
+ if (cell < rowMin) rowMin = cell;
58
+ }
59
+ if (rowMin > tolerance) return { distance: beyond, withinTolerance: false, cells };
60
+ const finished = previous;
61
+ previous = current;
62
+ current = finished;
63
+ }
64
+ const distance = previous[n];
65
+ return { distance, withinTolerance: distance <= tolerance, cells };
66
+ }
67
+
68
+ export { boundedLevenshtein, fuzzyPrefixOf, fuzzyTermMatches, tabulatedLevenshtein };