cry-search 1.0.1 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -29,19 +29,15 @@ var __export = (target, all) => {
29
29
  // src/index.ts
30
30
  var exports_src = {};
31
31
  __export(exports_src, {
32
- wrapMetadataLegacy: () => wrapMetadataLegacy,
33
- upsertPrimaryItem: () => upsertPrimaryItem,
34
- upsertLinkedItem: () => upsertLinkedItem,
35
- updateSearchMetadataString: () => updateSearchMetadata,
36
- updateSearchMetadataBatchString: () => updateSearchMetadataBatch,
32
+ upsertPrimaryItem: () => upsertPrimaryItemNumeric,
33
+ upsertLinkedItem: () => upsertLinkedItemNumeric,
37
34
  updateSearchMetadataBatch: () => updateSearchMetadataBatchNumeric,
38
35
  updateSearchMetadata: () => updateSearchMetadataNumeric,
39
- unwrapMetadataLegacy: () => unwrapMetadataLegacy,
40
36
  tokens: () => tokens,
41
37
  tokenize: () => tokenize,
42
- syncSearchArrayMetadataWithPrevious: () => syncSearchArrayMetadataWithPrevious,
43
- syncSearchArrayMetadata: () => syncSearchArrayMetadata,
44
- syncLinkedItemsForPrimary: () => syncLinkedItemsForPrimary,
38
+ syncSearchArrayMetadataWithPrevious: () => syncSearchArrayMetadataNumericWithPrevious,
39
+ syncSearchArrayMetadata: () => syncSearchArrayMetadataNumeric,
40
+ syncLinkedItemsForPrimary: () => syncLinkedItemsForPrimaryNumeric,
45
41
  searchableDataToArray: () => searchableDataToArray,
46
42
  searchInDataWithLimit: () => searchInDataReturnIdsWithLimitNumeric,
47
43
  searchInDataReturnObjects: () => searchInDataReturnObjectsNumeric,
@@ -49,22 +45,17 @@ __export(exports_src, {
49
45
  searchInData: () => searchInDataReturnIdsNumeric,
50
46
  sanitiseString: () => sanitiseString,
51
47
  resetTokenRegistry: () => resetTokenRegistry,
52
- removePrimaryItem: () => removePrimaryItem,
53
- removeLinkedItem: () => removeLinkedItem,
54
- removeFromSearchMetadataString: () => removeFromSearchMetadata,
55
- removeFromSearchMetadataBatchString: () => removeFromSearchMetadataBatch,
48
+ removePrimaryItem: () => removePrimaryItemNumeric,
49
+ removeLinkedItem: () => removeLinkedItemNumeric,
56
50
  removeFromSearchMetadataBatch: () => removeFromSearchMetadataBatchNumeric,
57
51
  removeFromSearchMetadata: () => removeFromSearchMetadataNumeric,
58
52
  registerToken: () => registerToken,
59
53
  preprocessString: () => preprocessString,
60
54
  prepareStringForSearch: () => prepareStringForSearch,
61
55
  prepareQueryTokens: () => prepareQueryTokens,
62
- prepareObjectForSearchString: () => prepareObjectForSearch,
63
56
  prepareObjectForSearch: () => prepareObjectForSearchNumeric,
64
57
  normalizeDates: () => normalizeDates,
65
58
  matchTokenInSortedListNumeric: () => matchTokenInSortedListNumeric,
66
- matchTokenInSortedList: () => matchTokenInSortedList,
67
- matchToken: () => matchToken,
68
59
  matchPreparedTokenInSortedList: () => matchPreparedTokenInSortedList,
69
60
  isDeletedOrBlocked: () => isDeletedOrBlocked,
70
61
  getTokenCount: () => getTokenCount,
@@ -72,33 +63,23 @@ __export(exports_src, {
72
63
  getOrCreateTokenId: () => getOrCreateTokenId,
73
64
  findTokenId: () => findTokenId,
74
65
  findInLinkedArraysSimpleNumeric: () => findInLinkedArraysSimpleNumeric,
75
- findInLinkedArraysSimple: () => findInLinkedArraysSimple,
76
66
  findInLinkedArraysNumeric: () => findInLinkedArraysNumeric,
77
- findInLinkedArrays: () => findInLinkedArrays,
78
- findInArrayReturnIds: () => findInArrayReturnIds,
79
- findInArrayReturnDataAndMeta: () => findInArrayReturnDataAndMeta,
80
- findInArray: () => findInArray,
81
- extractSearchableStringDefault: () => extractSearchableStringDefault,
82
67
  encodeTokenWithMode: () => encodeTokenWithMode,
83
68
  decodeTokenId: () => decodeTokenId,
84
69
  decodeMatchMode: () => decodeMatchMode,
85
70
  createTokensMap: () => createTokensMap,
86
- createSearchLinkedMetadataString: () => createSearchLinkedMetadata,
87
71
  createSearchLinkedMetadata: () => createSearchLinkedMetadataNumeric,
88
- createSearchArrayMetadataString: () => createSearchArrayMetadata,
89
72
  createSearchArrayMetadata: () => createSearchArrayMetadataNumeric,
90
73
  clearTokensMap: () => clearTokensMap,
91
74
  binarySearchUint32: () => binarySearchUint32,
92
75
  arrayToSearchableData: () => arrayToSearchableData,
93
76
  allTokensMatchNumeric: () => allTokensMatchNumeric,
94
- allTokensMatch: () => allTokensMatch,
95
77
  allPreparedTokensMatch: () => allPreparedTokensMatch,
96
78
  TOKEN_ID_MASK: () => TOKEN_ID_MASK,
97
79
  SearchUniverse: () => SearchUniverse,
98
- PREFIX_TO_MATCH_MODE: () => PREFIX_TO_MATCH_MODE,
99
- MATCH_MODE_PREFIXES: () => MATCH_MODE_PREFIXES,
100
80
  MATCH_MODE_BITS: () => MATCH_MODE_BITS,
101
- DEFAULT_SEARCH_OPTS: () => DEFAULT_SEARCH_OPTS
81
+ DEFAULT_SEARCH_OPTS: () => DEFAULT_SEARCH_OPTS,
82
+ AugmentedMetadata: () => AugmentedMetadata
102
83
  });
103
84
  module.exports = __toCommonJS(exports_src);
104
85
 
@@ -218,6 +199,7 @@ var RE_LEADING_ZEROS = /\b0+(\d)/g;
218
199
  var RE_DECIMAL_COMMA = /(\d),(\d)/g;
219
200
  var RE_STANDALONE_COMMA = /(?<!\d),(\d)/g;
220
201
  var RE_ZERO_DECIMAL = /\b0+\./g;
202
+ var RE_PURE_DECIMAL = /(?<![a-zA-Z\d.])(\d+)\.(\d+)(?![a-zA-Z.\d])/g;
221
203
  var RE_DIGIT_DASH = /(\d)\s*-\s*(\d)/g;
222
204
  var RE_LETTERS_DIGITS = /(^|\s)([a-zA-Z]+)(\d+)(?=\s|$)/g;
223
205
  var RE_DIGITS_LETTERS = /(^|\s)(\d+)([a-zA-Z]+)(?=\s|$)/g;
@@ -227,6 +209,7 @@ function preprocessString(input) {
227
209
  result = result.replace(RE_DECIMAL_COMMA, "$1.$2");
228
210
  result = result.replace(RE_STANDALONE_COMMA, ".$1");
229
211
  result = result.replace(RE_ZERO_DECIMAL, ".");
212
+ result = result.replace(RE_PURE_DECIMAL, "$1$2");
230
213
  result = result.replace(RE_DIGIT_DASH, "$1-$2");
231
214
  result = result.replace(RE_LETTERS_DIGITS, "$1$2 $3");
232
215
  result = result.replace(RE_DIGITS_LETTERS, "$1$2 $3");
@@ -369,13 +352,6 @@ function prepareStringForSearchNumeric(input, tokensMap) {
369
352
  }
370
353
 
371
354
  // src/common/string/createSearchArrayMetadata.ts
372
- var MATCH_MODE_PREFIXES = {
373
- start: "<",
374
- end: ">",
375
- startEnd: "+",
376
- anywhere: "*",
377
- whole: "!"
378
- };
379
355
  var PREFIX_TO_MATCH_MODE = {
380
356
  "<": "start",
381
357
  ">": "end",
@@ -386,155 +362,9 @@ var PREFIX_TO_MATCH_MODE = {
386
362
  "?": "anywhere"
387
363
  };
388
364
  var DEFAULT_EXCLUDED_FIELDS = new Set(["_id", "_deleted", "_blocked"]);
389
- function getValueByPath(obj, path) {
390
- const parts = path.split(".");
391
- let current = obj;
392
- for (let i = 0;i < parts.length; i++) {
393
- if (current == null)
394
- return;
395
- const part = parts[i];
396
- if (Array.isArray(current)) {
397
- const remainingPath = parts.slice(i).join(".");
398
- const results = [];
399
- for (const item of current) {
400
- const value = getValueByPath(item, remainingPath);
401
- if (value !== undefined) {
402
- if (Array.isArray(value)) {
403
- results.push(...value);
404
- } else {
405
- results.push(value);
406
- }
407
- }
408
- }
409
- return results.length > 0 ? results : undefined;
410
- }
411
- if (typeof current === "object") {
412
- current = current[part];
413
- } else {
414
- return;
415
- }
416
- }
417
- return current;
418
- }
419
- function isDotNotation(field) {
420
- return field.includes(".");
421
- }
422
- function getRootField(field) {
423
- const dotIndex = field.indexOf(".");
424
- return dotIndex === -1 ? field : field.slice(0, dotIndex);
425
- }
426
- function extractStringsFromValue(value, results) {
427
- if (value == null)
428
- return;
429
- if (typeof value === "string") {
430
- results.push(value);
431
- } else if (typeof value === "number") {
432
- results.push(String(value));
433
- } else if (value instanceof Date) {
434
- results.push(value.toISOString());
435
- } else if (Array.isArray(value)) {
436
- for (const item of value) {
437
- extractStringsFromValue(item, results);
438
- }
439
- } else if (typeof value === "object") {
440
- for (const v of Object.values(value)) {
441
- extractStringsFromValue(v, results);
442
- }
443
- }
444
- }
445
365
  function isDeletedOrBlocked(obj) {
446
366
  return obj._deleted != null || obj._blocked != null;
447
367
  }
448
- function extractSearchableStringDefault(obj, spec) {
449
- if (isDeletedOrBlocked(obj)) {
450
- return;
451
- }
452
- if (spec?.enrichSearchObjectFn) {
453
- spec.enrichSearchObjectFn(obj, spec.searchContext);
454
- }
455
- const parts = [];
456
- const fieldsToSearch = spec?.searchInFields ?? Object.keys(obj);
457
- const fieldsToExclude = new Set(spec?.dontSearchInFields ?? []);
458
- for (const key of fieldsToSearch) {
459
- const keyStr = key;
460
- if (!spec?.searchInFields && DEFAULT_EXCLUDED_FIELDS.has(keyStr))
461
- continue;
462
- if (fieldsToExclude.has(key))
463
- continue;
464
- const value = isDotNotation(keyStr) ? getValueByPath(obj, keyStr) : obj[key];
465
- extractStringsFromValue(value, parts);
466
- }
467
- return parts.join(" ");
468
- }
469
- function prepareObjectForSearch(obj, spec) {
470
- if (isDeletedOrBlocked(obj)) {
471
- return;
472
- }
473
- if (spec?.extractSearchableStringFn) {
474
- const searchableString = spec.extractSearchableStringFn(obj);
475
- if (searchableString === undefined) {
476
- return;
477
- }
478
- return prepareStringForSearch(searchableString);
479
- }
480
- return prepareObjectFieldsForSearch(obj, spec);
481
- }
482
- function prepareObjectFieldsForSearch(obj, spec) {
483
- if (spec?.enrichSearchObjectFn) {
484
- spec.enrichSearchObjectFn(obj, spec.searchContext);
485
- }
486
- const allTokens = [];
487
- const fieldMatchModes = spec?.fieldMatchModes;
488
- const fieldsToSearch = spec?.searchInFields ?? Object.keys(obj);
489
- const fieldsToExclude = new Set(spec?.dontSearchInFields ?? []);
490
- const processedRootFields = new Set;
491
- for (const key of fieldsToSearch) {
492
- const keyStr = key;
493
- if (!spec?.searchInFields && DEFAULT_EXCLUDED_FIELDS.has(keyStr))
494
- continue;
495
- if (fieldsToExclude.has(key))
496
- continue;
497
- const isDot = isDotNotation(keyStr);
498
- const rootField = getRootField(keyStr);
499
- let value;
500
- if (isDot) {
501
- value = getValueByPath(obj, keyStr);
502
- } else {
503
- value = obj[key];
504
- processedRootFields.add(rootField);
505
- }
506
- if (value == null)
507
- continue;
508
- const matchMode = fieldMatchModes?.[key];
509
- const prefix = matchMode ? MATCH_MODE_PREFIXES[matchMode] : "";
510
- const fieldStrings = [];
511
- extractStringsFromValue(value, fieldStrings);
512
- if (fieldStrings.length > 0) {
513
- const fieldText = fieldStrings.join(" ");
514
- const tokens2 = prepareStringForSearch(fieldText);
515
- for (const token of tokens2) {
516
- allTokens.push(prefix + token);
517
- }
518
- }
519
- }
520
- return [...new Set(allTokens)].sort();
521
- }
522
- function createSearchArrayMetadata(data, spec) {
523
- const metadata = new Map;
524
- for (const [id, item] of data) {
525
- const tokens2 = prepareObjectForSearch(item, spec);
526
- if (tokens2 !== undefined) {
527
- metadata.set(id, tokens2);
528
- }
529
- }
530
- return metadata;
531
- }
532
- function wrapMetadataLegacy(metadata) {
533
- return { items: metadata };
534
- }
535
- function unwrapMetadataLegacy(legacy) {
536
- return legacy.items;
537
- }
538
368
 
539
369
  // src/common/numeric/createSearchArrayMetadata.ts
540
370
  var MATCH_MODE_BITS = {
@@ -568,7 +398,7 @@ function decodeMatchMode(encoded) {
568
398
  }
569
399
  }
570
400
  var DEFAULT_EXCLUDED_FIELDS2 = new Set(["_id", "_deleted", "_blocked"]);
571
- function getValueByPath2(obj, path) {
401
+ function getValueByPath(obj, path) {
572
402
  const parts = path.split(".");
573
403
  let current = obj;
574
404
  for (let i = 0;i < parts.length; i++) {
@@ -579,7 +409,7 @@ function getValueByPath2(obj, path) {
579
409
  const remainingPath = parts.slice(i).join(".");
580
410
  const results = [];
581
411
  for (const item of current) {
582
- const value = getValueByPath2(item, remainingPath);
412
+ const value = getValueByPath(item, remainingPath);
583
413
  if (value !== undefined) {
584
414
  if (Array.isArray(value)) {
585
415
  results.push(...value);
@@ -598,10 +428,10 @@ function getValueByPath2(obj, path) {
598
428
  }
599
429
  return current;
600
430
  }
601
- function isDotNotation2(field) {
431
+ function isDotNotation(field) {
602
432
  return field.includes(".");
603
433
  }
604
- function extractStringsFromValue2(value, results) {
434
+ function extractStringsFromValue(value, results) {
605
435
  if (value == null)
606
436
  return;
607
437
  if (typeof value === "string") {
@@ -612,11 +442,11 @@ function extractStringsFromValue2(value, results) {
612
442
  results.push(value.toISOString());
613
443
  } else if (Array.isArray(value)) {
614
444
  for (const item of value) {
615
- extractStringsFromValue2(item, results);
445
+ extractStringsFromValue(item, results);
616
446
  }
617
447
  } else if (typeof value === "object") {
618
448
  for (const v of Object.values(value)) {
619
- extractStringsFromValue2(v, results);
449
+ extractStringsFromValue(v, results);
620
450
  }
621
451
  }
622
452
  }
@@ -647,13 +477,13 @@ function prepareObjectFieldsForSearchNumeric(obj, spec, tokensMap) {
647
477
  continue;
648
478
  if (fieldsToExclude.has(key))
649
479
  continue;
650
- const isDot = isDotNotation2(keyStr);
651
- const value = isDot ? getValueByPath2(obj, keyStr) : obj[key];
480
+ const isDot = isDotNotation(keyStr);
481
+ const value = isDot ? getValueByPath(obj, keyStr) : obj[key];
652
482
  if (value == null)
653
483
  continue;
654
484
  const matchMode = fieldMatchModes?.[key];
655
485
  const fieldStrings = [];
656
- extractStringsFromValue2(value, fieldStrings);
486
+ extractStringsFromValue(value, fieldStrings);
657
487
  if (fieldStrings.length > 0) {
658
488
  const fieldText = fieldStrings.join(" ");
659
489
  const datesNormalized = normalizeDates(fieldText);
@@ -1077,254 +907,179 @@ function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
1077
907
  function findInLinkedArraysSimpleNumeric(query, linked, limit = 10, opts) {
1078
908
  return findInLinkedArraysNumeric(query, linked, limit, opts).results;
1079
909
  }
1080
- // src/common/string/createSearchLinkedMetadata.ts
1081
- function createSearchLinkedMetadata(primaryData, primaryMetadata, linkedData, linkedMetadata, foreignKeyGetter) {
1082
- const primaryToLinked = new Map;
1083
- for (const [linkedId, linkedItem] of linkedData) {
1084
- const primaryId = foreignKeyGetter(linkedItem);
1085
- if (primaryId) {
1086
- const list = primaryToLinked.get(primaryId) || [];
1087
- list.push(linkedId);
1088
- primaryToLinked.set(primaryId, list);
910
+ // src/common/numeric/AugmentedMetadata.ts
911
+ class AugmentedMetadata {
912
+ baseMetadata;
913
+ augmentedTokens;
914
+ spec;
915
+ constructor(baseMetadata, spec, augmentedDataMap) {
916
+ this.baseMetadata = baseMetadata;
917
+ this.augmentedTokens = new Map;
918
+ this.spec = spec;
919
+ if (augmentedDataMap && augmentedDataMap.size > 0) {
920
+ this.updateAugmentedBatch(augmentedDataMap);
921
+ }
922
+ }
923
+ updateAugmented(id, augmentedData) {
924
+ if (!augmentedData) {
925
+ this.augmentedTokens.delete(id);
926
+ return;
1089
927
  }
1090
- }
1091
- return {
1092
- primaryMeta: primaryMetadata,
1093
- linkedMeta: linkedMetadata,
1094
- primaryToLinked,
1095
- primaryData,
1096
- linkedData
1097
- };
1098
- }
1099
- // src/common/string/updateSearchMetadata.ts
1100
- function updateSearchMetadata(metadata, objectId, obj, spec) {
1101
- const tokens2 = obj != null ? prepareObjectForSearch(obj, spec) : undefined;
1102
- if (tokens2 === undefined) {
1103
- metadata.delete(objectId);
1104
- return false;
1105
- } else {
1106
- metadata.set(objectId, tokens2);
1107
- return true;
1108
- }
1109
- }
1110
- function updateSearchMetadataBatch(metadata, batch, spec) {
1111
- if (batch.length === 0) {
1112
- return { updated: 0, removed: 0 };
1113
- }
1114
- let updated = 0;
1115
- let removed = 0;
1116
- for (const { objectId, obj } of batch) {
1117
- const wasUpdated = updateSearchMetadata(metadata, objectId, obj, spec);
1118
- if (wasUpdated) {
1119
- updated++;
928
+ const tokensMap = createTokensMap();
929
+ const tokens2 = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
930
+ if (tokens2 && tokens2.length > 0) {
931
+ this.augmentedTokens.set(id, tokens2);
1120
932
  } else {
1121
- removed++;
1122
- }
1123
- }
1124
- return { updated, removed };
1125
- }
1126
- function removeFromSearchMetadata(metadata, objectId) {
1127
- return metadata.delete(objectId);
1128
- }
1129
- function removeFromSearchMetadataBatch(metadata, objectIds) {
1130
- if (objectIds.length === 0) {
1131
- return 0;
1132
- }
1133
- let removed = 0;
1134
- for (const id of objectIds) {
1135
- if (metadata.delete(id)) {
1136
- removed++;
933
+ this.augmentedTokens.delete(id);
1137
934
  }
935
+ clearTokensMap(tokensMap);
1138
936
  }
1139
- return removed;
1140
- }
1141
- // src/utils/matchToken.ts
1142
- var RE_NUMERIC2 = /^[\d.\-]+$/;
1143
- var PREFIX_TO_MODE = {
1144
- "<": "start",
1145
- ">": "end",
1146
- "+": "startEnd",
1147
- "*": "anywhere",
1148
- "!": "whole"
1149
- };
1150
- function matchWithMode(searchToken, targetToken, mode) {
1151
- switch (mode) {
1152
- case "start":
1153
- return targetToken.startsWith(searchToken);
1154
- case "end":
1155
- return targetToken.endsWith(searchToken);
1156
- case "startEnd":
1157
- return targetToken.startsWith(searchToken) || targetToken.endsWith(searchToken);
1158
- case "anywhere":
1159
- return targetToken.includes(searchToken);
1160
- case "whole":
1161
- return targetToken === searchToken;
1162
- }
1163
- }
1164
- function matchToken(searchToken, targetToken, opts) {
1165
- const firstChar = targetToken[0];
1166
- const prefixMode = firstChar ? PREFIX_TO_MODE[firstChar] : undefined;
1167
- if (prefixMode) {
1168
- const actualTarget = targetToken.slice(1);
1169
- return matchWithMode(searchToken, actualTarget, prefixMode);
1170
- }
1171
- const matchWords = opts?.matchWords ?? DEFAULT_SEARCH_OPTS.matchWords;
1172
- const matchNumbers = opts?.matchNumbers ?? DEFAULT_SEARCH_OPTS.matchNumbers;
1173
- const isNumeric = RE_NUMERIC2.test(searchToken);
1174
- return matchWithMode(searchToken, targetToken, isNumeric ? matchNumbers : matchWords);
1175
- }
1176
- function matchTokenInSortedList(searchToken, targetTokens, opts) {
1177
- const isNumeric = RE_NUMERIC2.test(searchToken);
1178
- const effectiveMode = isNumeric ? opts?.matchNumbers ?? DEFAULT_SEARCH_OPTS.matchNumbers : opts?.matchWords ?? DEFAULT_SEARCH_OPTS.matchWords;
1179
- const canEarlyExit = effectiveMode === "start";
1180
- for (const targetToken of targetTokens) {
1181
- const firstChar = targetToken[0];
1182
- const hasPrefix = firstChar ? PREFIX_TO_MODE[firstChar] !== undefined : false;
1183
- if (hasPrefix) {
1184
- if (matchToken(searchToken, targetToken, opts)) {
1185
- return true;
937
+ updateAugmentedBatch(augmentedDataMap) {
938
+ const tokensMap = createTokensMap();
939
+ for (const [id, augmentedData] of augmentedDataMap) {
940
+ if (!augmentedData) {
941
+ this.augmentedTokens.delete(id);
942
+ continue;
1186
943
  }
1187
- } else {
1188
- if (canEarlyExit) {
1189
- if (targetToken.startsWith(searchToken)) {
1190
- return true;
1191
- }
1192
- if (targetToken > searchToken && targetToken[0] !== searchToken[0]) {
1193
- return false;
1194
- }
944
+ const tokens2 = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
945
+ if (tokens2 && tokens2.length > 0) {
946
+ this.augmentedTokens.set(id, tokens2);
1195
947
  } else {
1196
- if (matchToken(searchToken, targetToken, opts)) {
1197
- return true;
1198
- }
948
+ this.augmentedTokens.delete(id);
1199
949
  }
1200
950
  }
951
+ clearTokensMap(tokensMap);
1201
952
  }
1202
- return false;
1203
- }
1204
- function allTokensMatch(searchTokens, targetTokens, opts) {
1205
- for (const searchToken of searchTokens) {
1206
- if (!matchTokenInSortedList(searchToken, targetTokens, opts)) {
1207
- return false;
1208
- }
953
+ clearAugmented(id) {
954
+ this.augmentedTokens.delete(id);
1209
955
  }
1210
- return true;
1211
- }
1212
-
1213
- // src/common/findInArrayReturnDataAndMeta.ts
1214
- function findInArrayReturnDataAndMeta(query, data, metadata, limit = 10, opts) {
1215
- const queryTokens = prepareStringForSearch(query);
1216
- if (queryTokens.length === 0) {
956
+ clearAllAugmented() {
957
+ this.augmentedTokens.clear();
958
+ }
959
+ get(id) {
960
+ const baseTokens = this.baseMetadata.get(id);
961
+ if (!baseTokens)
962
+ return;
963
+ const augTokens = this.augmentedTokens.get(id);
964
+ if (!augTokens)
965
+ return baseTokens;
966
+ return this.mergeSortedTokenArrays(baseTokens, augTokens);
967
+ }
968
+ has(id) {
969
+ return this.baseMetadata.has(id);
970
+ }
971
+ get size() {
972
+ return this.baseMetadata.size;
973
+ }
974
+ [Symbol.iterator]() {
975
+ const self = this;
976
+ const baseIterator = this.baseMetadata[Symbol.iterator]();
1217
977
  return {
1218
- queryTokens,
1219
- results: []
978
+ next() {
979
+ const baseResult = baseIterator.next();
980
+ if (baseResult.done) {
981
+ return { done: true, value: undefined };
982
+ }
983
+ const [id, baseTokens] = baseResult.value;
984
+ const augTokens = self.augmentedTokens.get(id);
985
+ const tokens2 = augTokens ? self.mergeSortedTokenArrays(baseTokens, augTokens) : baseTokens;
986
+ return { done: false, value: [id, tokens2] };
987
+ },
988
+ [Symbol.iterator]() {
989
+ return this;
990
+ },
991
+ [Symbol.dispose]() {}
1220
992
  };
1221
993
  }
1222
- const results = [];
1223
- for (const [id, itemTokens] of metadata) {
1224
- if (results.length >= limit) {
1225
- break;
1226
- }
1227
- if (allTokensMatch(queryTokens, itemTokens, opts)) {
1228
- const item = data.get(id);
1229
- if (item) {
1230
- results.push({
1231
- item,
1232
- tokens: itemTokens
1233
- });
1234
- }
1235
- }
994
+ keys() {
995
+ return this.baseMetadata.keys();
1236
996
  }
1237
- return {
1238
- queryTokens,
1239
- results
1240
- };
1241
- }
1242
- function findInArrayReturnIds(query, metadata, limit = 10, opts) {
1243
- const queryTokens = prepareStringForSearch(query);
1244
- if (queryTokens.length === 0) {
1245
- return [];
997
+ values() {
998
+ const self = this;
999
+ const keysIterator = this.baseMetadata.keys();
1000
+ return {
1001
+ next() {
1002
+ const keyResult = keysIterator.next();
1003
+ if (keyResult.done) {
1004
+ return { done: true, value: undefined };
1005
+ }
1006
+ const tokens2 = self.get(keyResult.value);
1007
+ return tokens2 ? { done: false, value: tokens2 } : { done: true, value: undefined };
1008
+ },
1009
+ [Symbol.iterator]() {
1010
+ return this;
1011
+ },
1012
+ [Symbol.dispose]() {}
1013
+ };
1246
1014
  }
1247
- const results = [];
1248
- for (const [id, itemTokens] of metadata) {
1249
- if (results.length >= limit) {
1250
- break;
1251
- }
1252
- if (allTokensMatch(queryTokens, itemTokens, opts)) {
1253
- results.push(id);
1015
+ entries() {
1016
+ return this[Symbol.iterator]();
1017
+ }
1018
+ forEach(callbackfn) {
1019
+ for (const [id, tokens2] of this) {
1020
+ callbackfn(tokens2, id, this);
1254
1021
  }
1255
1022
  }
1256
- return results;
1257
- }
1258
-
1259
- // src/common/findInArray.ts
1260
- function findInArray(query, data, metadata, limit = 10, opts) {
1261
- const result = findInArrayReturnDataAndMeta(query, data, metadata, limit, opts);
1262
- return result.results.map((r) => r.item);
1263
- }
1264
- // src/common/findInLinkedArrays.ts
1265
- function findInLinkedArrays(query, linked, limit = 10, opts) {
1266
- const queryTokens = prepareStringForSearch(query);
1267
- const hasNegation = queryTokens.some((t) => t.startsWith("--") || t.startsWith("~") || t.length > 1 && t[0] === "-" && /^[a-z]/i.test(t[1]));
1268
- if (queryTokens.length === 0) {
1269
- return { queryTokens, results: [], hasNegation: false };
1023
+ set(_key, _value) {
1024
+ throw new Error("AugmentedMetadata.set() is not supported. Use updateAugmented() instead.");
1270
1025
  }
1271
- const results = [];
1272
- for (const [primaryId, primary] of linked.primaryData) {
1273
- if (results.length >= limit)
1274
- break;
1275
- const primaryTokens = linked.primaryMeta.get(primaryId);
1276
- if (!primaryTokens)
1277
- continue;
1278
- const linkedIds = linked.primaryToLinked.get(primaryId) || [];
1279
- const allTokens = [...primaryTokens];
1280
- for (const linkedId of linkedIds) {
1281
- const linkedTokens = linked.linkedMeta.get(linkedId);
1282
- if (linkedTokens) {
1283
- allTokens.push(...linkedTokens);
1284
- }
1285
- }
1286
- allTokens.sort();
1287
- if (allTokensMatch(queryTokens, allTokens, opts)) {
1288
- let anyMatchInPrimary = false;
1289
- let anyMatchInLinked = false;
1290
- const matchingLinkedIds = new Set;
1291
- const tokensMatchingPrimary = new Set;
1292
- for (const queryToken of queryTokens) {
1293
- if (matchTokenInSortedList(queryToken, primaryTokens, opts)) {
1294
- anyMatchInPrimary = true;
1295
- tokensMatchingPrimary.add(queryToken);
1026
+ delete(_key) {
1027
+ throw new Error("AugmentedMetadata.delete() is not supported. Use clearAugmented() instead.");
1028
+ }
1029
+ clear() {
1030
+ throw new Error("AugmentedMetadata.clear() is not supported. Use clearAllAugmented() instead.");
1031
+ }
1032
+ get [Symbol.toStringTag]() {
1033
+ return "AugmentedMetadata";
1034
+ }
1035
+ mergeSortedTokenArrays(a, b) {
1036
+ const merged = new Uint32Array(a.length + b.length);
1037
+ let i = 0, j = 0, k = 0;
1038
+ let lastToken = -1;
1039
+ while (i < a.length && j < b.length) {
1040
+ const tokenA = a[i];
1041
+ const tokenB = b[j];
1042
+ if (tokenA < tokenB) {
1043
+ if (tokenA !== lastToken) {
1044
+ merged[k++] = tokenA;
1045
+ lastToken = tokenA;
1296
1046
  }
1297
- }
1298
- const tokensForLinkedMatching = queryTokens.filter((t) => !tokensMatchingPrimary.has(t));
1299
- if (tokensForLinkedMatching.length > 0) {
1300
- for (const linkedId of linkedIds) {
1301
- const linkedTokens = linked.linkedMeta.get(linkedId);
1302
- if (linkedTokens) {
1303
- const matchesAllNonPrimaryTokens = tokensForLinkedMatching.every((queryToken) => matchTokenInSortedList(queryToken, linkedTokens, opts));
1304
- if (matchesAllNonPrimaryTokens) {
1305
- anyMatchInLinked = true;
1306
- matchingLinkedIds.add(linkedId);
1307
- }
1308
- }
1047
+ i++;
1048
+ } else if (tokenA > tokenB) {
1049
+ if (tokenB !== lastToken) {
1050
+ merged[k++] = tokenB;
1051
+ lastToken = tokenB;
1309
1052
  }
1053
+ j++;
1054
+ } else {
1055
+ if (tokenA !== lastToken) {
1056
+ merged[k++] = tokenA;
1057
+ lastToken = tokenA;
1058
+ }
1059
+ i++;
1060
+ j++;
1310
1061
  }
1311
- if (tokensForLinkedMatching.length > 0 && matchingLinkedIds.size === 0) {
1312
- continue;
1062
+ }
1063
+ while (i < a.length) {
1064
+ const tokenA = a[i];
1065
+ if (tokenA !== lastToken) {
1066
+ merged[k++] = tokenA;
1067
+ lastToken = tokenA;
1313
1068
  }
1314
- const matchedLinked = Array.from(matchingLinkedIds).map((id) => linked.linkedData.get(id)).filter((item) => item !== undefined);
1315
- results.push({
1316
- primary,
1317
- linked: matchedLinked,
1318
- matchedIn: anyMatchInPrimary && anyMatchInLinked ? "both" : anyMatchInPrimary ? "primary" : "linked"
1319
- });
1069
+ i++;
1070
+ }
1071
+ while (j < b.length) {
1072
+ const tokenB = b[j];
1073
+ if (tokenB !== lastToken) {
1074
+ merged[k++] = tokenB;
1075
+ lastToken = tokenB;
1076
+ }
1077
+ j++;
1320
1078
  }
1079
+ return merged.slice(0, k);
1321
1080
  }
1322
- return { queryTokens, results, hasNegation };
1323
- }
1324
- function findInLinkedArraysSimple(query, linked, limit = 10, opts) {
1325
- return findInLinkedArrays(query, linked, limit, opts).results;
1326
1081
  }
1327
- // src/common/syncSearchArrayMetadata.ts
1082
+ // src/common/numeric/syncSearchArrayMetadata.ts
1328
1083
  function tokensEqual(a, b) {
1329
1084
  if (a.length !== b.length)
1330
1085
  return false;
@@ -1334,7 +1089,7 @@ function tokensEqual(a, b) {
1334
1089
  }
1335
1090
  return true;
1336
1091
  }
1337
- function syncSearchArrayMetadata(metadata, newData, spec) {
1092
+ function syncSearchArrayMetadataNumeric(metadata, newData, spec) {
1338
1093
  const result = {
1339
1094
  added: 0,
1340
1095
  updated: 0,
@@ -1343,6 +1098,7 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
1343
1098
  updatedIds: [],
1344
1099
  removedIds: []
1345
1100
  };
1101
+ const tokensMap = createTokensMap();
1346
1102
  for (const id of metadata.keys()) {
1347
1103
  if (!newData.has(id)) {
1348
1104
  metadata.delete(id);
@@ -1351,7 +1107,7 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
1351
1107
  }
1352
1108
  }
1353
1109
  for (const [id, item] of newData) {
1354
- const newTokens = prepareObjectForSearch(item, spec);
1110
+ const newTokens = prepareObjectForSearchNumeric(item, spec, tokensMap);
1355
1111
  if (newTokens === undefined) {
1356
1112
  if (metadata.has(id)) {
1357
1113
  metadata.delete(id);
@@ -1371,9 +1127,10 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
1371
1127
  result.updatedIds.push(id);
1372
1128
  }
1373
1129
  }
1130
+ clearTokensMap(tokensMap);
1374
1131
  return result;
1375
1132
  }
1376
- function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, options, spec) {
1133
+ function syncSearchArrayMetadataNumericWithPrevious(metadata, previousData, newData, options, spec) {
1377
1134
  const result = {
1378
1135
  added: 0,
1379
1136
  updated: 0,
@@ -1382,6 +1139,7 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
1382
1139
  updatedIds: [],
1383
1140
  removedIds: []
1384
1141
  };
1142
+ const tokensMap = createTokensMap();
1385
1143
  for (const id of previousData.keys()) {
1386
1144
  if (!newData.has(id)) {
1387
1145
  metadata.delete(id);
@@ -1392,14 +1150,14 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
1392
1150
  for (const [id, item] of newData) {
1393
1151
  const wasInPrevious = previousData.has(id);
1394
1152
  if (!wasInPrevious) {
1395
- const tokens2 = prepareObjectForSearch(item, spec);
1153
+ const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
1396
1154
  if (tokens2 !== undefined) {
1397
1155
  metadata.set(id, tokens2);
1398
1156
  result.added++;
1399
1157
  result.addedIds.push(id);
1400
1158
  }
1401
1159
  } else if (!options?.skipUpdateCheck) {
1402
- const newTokens = prepareObjectForSearch(item, spec);
1160
+ const newTokens = prepareObjectForSearchNumeric(item, spec, tokensMap);
1403
1161
  if (newTokens === undefined) {
1404
1162
  metadata.delete(id);
1405
1163
  result.removed++;
@@ -1414,9 +1172,10 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
1414
1172
  }
1415
1173
  }
1416
1174
  }
1175
+ clearTokensMap(tokensMap);
1417
1176
  return result;
1418
1177
  }
1419
- // src/common/updateSearchLinkedMetadata.ts
1178
+ // src/common/numeric/updateSearchLinkedMetadata.ts
1420
1179
  function tokensEqual2(a, b) {
1421
1180
  if (a.length !== b.length)
1422
1181
  return false;
@@ -1426,11 +1185,13 @@ function tokensEqual2(a, b) {
1426
1185
  }
1427
1186
  return true;
1428
1187
  }
1429
- function upsertPrimaryItem(linked, item, spec) {
1188
+ function upsertPrimaryItemNumeric(linked, item, spec) {
1430
1189
  const id = item._id;
1431
1190
  const wasAdded = !linked.primaryData.has(id);
1432
1191
  linked.primaryData.set(id, item);
1433
- const tokens2 = prepareObjectForSearch(item, spec);
1192
+ const tokensMap = createTokensMap();
1193
+ const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
1194
+ clearTokensMap(tokensMap);
1434
1195
  if (tokens2 !== undefined) {
1435
1196
  linked.primaryMeta.set(id, tokens2);
1436
1197
  } else {
@@ -1441,7 +1202,7 @@ function upsertPrimaryItem(linked, item, spec) {
1441
1202
  }
1442
1203
  return { added: wasAdded };
1443
1204
  }
1444
- function removePrimaryItem(linked, primaryId) {
1205
+ function removePrimaryItemNumeric(linked, primaryId) {
1445
1206
  if (!linked.primaryData.has(primaryId)) {
1446
1207
  return false;
1447
1208
  }
@@ -1450,7 +1211,7 @@ function removePrimaryItem(linked, primaryId) {
1450
1211
  linked.primaryToLinked.delete(primaryId);
1451
1212
  return true;
1452
1213
  }
1453
- function upsertLinkedItem(linked, item, foreignKeyGetter, spec) {
1214
+ function upsertLinkedItemNumeric(linked, item, foreignKeyGetter, spec) {
1454
1215
  const id = item._id;
1455
1216
  const newPrimaryId = foreignKeyGetter(item);
1456
1217
  let previousPrimaryId;
@@ -1460,7 +1221,9 @@ function upsertLinkedItem(linked, item, foreignKeyGetter, spec) {
1460
1221
  }
1461
1222
  const wasAdded = !existingItem;
1462
1223
  linked.linkedData.set(id, item);
1463
- const tokens2 = prepareObjectForSearch(item, spec);
1224
+ const tokensMap = createTokensMap();
1225
+ const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
1226
+ clearTokensMap(tokensMap);
1464
1227
  if (tokens2 !== undefined) {
1465
1228
  linked.linkedMeta.set(id, tokens2);
1466
1229
  } else {
@@ -1492,7 +1255,7 @@ function upsertLinkedItem(linked, item, foreignKeyGetter, spec) {
1492
1255
  previousPrimaryId: wasAdded ? undefined : previousPrimaryId
1493
1256
  };
1494
1257
  }
1495
- function removeLinkedItem(linked, linkedId, foreignKeyGetter) {
1258
+ function removeLinkedItemNumeric(linked, linkedId, foreignKeyGetter) {
1496
1259
  const existingItem = linked.linkedData.get(linkedId);
1497
1260
  if (!existingItem) {
1498
1261
  return false;
@@ -1511,12 +1274,13 @@ function removeLinkedItem(linked, linkedId, foreignKeyGetter) {
1511
1274
  }
1512
1275
  return true;
1513
1276
  }
1514
- function syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKeyGetter, spec) {
1277
+ function syncLinkedItemsForPrimaryNumeric(linked, primaryId, newLinkedItems, foreignKeyGetter, spec) {
1515
1278
  const result = {
1516
1279
  added: 0,
1517
1280
  updated: 0,
1518
1281
  removed: 0
1519
1282
  };
1283
+ const tokensMap = createTokensMap();
1520
1284
  const currentLinkedIds = new Set(linked.primaryToLinked.get(primaryId) || []);
1521
1285
  const newLinkedIds = new Set;
1522
1286
  for (const [id, item] of newLinkedItems) {
@@ -1536,7 +1300,7 @@ function syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKey
1536
1300
  }
1537
1301
  for (const id of newLinkedIds) {
1538
1302
  const item = newLinkedItems.get(id);
1539
- const tokens2 = prepareObjectForSearch(item, spec);
1303
+ const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
1540
1304
  if (currentLinkedIds.has(id)) {
1541
1305
  const existingTokens = linked.linkedMeta.get(id);
1542
1306
  if (tokens2 !== undefined) {
@@ -1555,6 +1319,7 @@ function syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKey
1555
1319
  }
1556
1320
  }
1557
1321
  linked.primaryToLinked.set(primaryId, Array.from(newLinkedIds));
1322
+ clearTokensMap(tokensMap);
1558
1323
  return result;
1559
1324
  }
1560
1325
  // src/common/SearchUniverse.ts