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.js CHANGED
@@ -114,6 +114,7 @@ var RE_LEADING_ZEROS = /\b0+(\d)/g;
114
114
  var RE_DECIMAL_COMMA = /(\d),(\d)/g;
115
115
  var RE_STANDALONE_COMMA = /(?<!\d),(\d)/g;
116
116
  var RE_ZERO_DECIMAL = /\b0+\./g;
117
+ var RE_PURE_DECIMAL = /(?<![a-zA-Z\d.])(\d+)\.(\d+)(?![a-zA-Z.\d])/g;
117
118
  var RE_DIGIT_DASH = /(\d)\s*-\s*(\d)/g;
118
119
  var RE_LETTERS_DIGITS = /(^|\s)([a-zA-Z]+)(\d+)(?=\s|$)/g;
119
120
  var RE_DIGITS_LETTERS = /(^|\s)(\d+)([a-zA-Z]+)(?=\s|$)/g;
@@ -123,6 +124,7 @@ function preprocessString(input) {
123
124
  result = result.replace(RE_DECIMAL_COMMA, "$1.$2");
124
125
  result = result.replace(RE_STANDALONE_COMMA, ".$1");
125
126
  result = result.replace(RE_ZERO_DECIMAL, ".");
127
+ result = result.replace(RE_PURE_DECIMAL, "$1$2");
126
128
  result = result.replace(RE_DIGIT_DASH, "$1-$2");
127
129
  result = result.replace(RE_LETTERS_DIGITS, "$1$2 $3");
128
130
  result = result.replace(RE_DIGITS_LETTERS, "$1$2 $3");
@@ -265,13 +267,6 @@ function prepareStringForSearchNumeric(input, tokensMap) {
265
267
  }
266
268
 
267
269
  // src/common/string/createSearchArrayMetadata.ts
268
- var MATCH_MODE_PREFIXES = {
269
- start: "<",
270
- end: ">",
271
- startEnd: "+",
272
- anywhere: "*",
273
- whole: "!"
274
- };
275
270
  var PREFIX_TO_MATCH_MODE = {
276
271
  "<": "start",
277
272
  ">": "end",
@@ -282,155 +277,9 @@ var PREFIX_TO_MATCH_MODE = {
282
277
  "?": "anywhere"
283
278
  };
284
279
  var DEFAULT_EXCLUDED_FIELDS = new Set(["_id", "_deleted", "_blocked"]);
285
- function getValueByPath(obj, path) {
286
- const parts = path.split(".");
287
- let current = obj;
288
- for (let i = 0;i < parts.length; i++) {
289
- if (current == null)
290
- return;
291
- const part = parts[i];
292
- if (Array.isArray(current)) {
293
- const remainingPath = parts.slice(i).join(".");
294
- const results = [];
295
- for (const item of current) {
296
- const value = getValueByPath(item, remainingPath);
297
- if (value !== undefined) {
298
- if (Array.isArray(value)) {
299
- results.push(...value);
300
- } else {
301
- results.push(value);
302
- }
303
- }
304
- }
305
- return results.length > 0 ? results : undefined;
306
- }
307
- if (typeof current === "object") {
308
- current = current[part];
309
- } else {
310
- return;
311
- }
312
- }
313
- return current;
314
- }
315
- function isDotNotation(field) {
316
- return field.includes(".");
317
- }
318
- function getRootField(field) {
319
- const dotIndex = field.indexOf(".");
320
- return dotIndex === -1 ? field : field.slice(0, dotIndex);
321
- }
322
- function extractStringsFromValue(value, results) {
323
- if (value == null)
324
- return;
325
- if (typeof value === "string") {
326
- results.push(value);
327
- } else if (typeof value === "number") {
328
- results.push(String(value));
329
- } else if (value instanceof Date) {
330
- results.push(value.toISOString());
331
- } else if (Array.isArray(value)) {
332
- for (const item of value) {
333
- extractStringsFromValue(item, results);
334
- }
335
- } else if (typeof value === "object") {
336
- for (const v of Object.values(value)) {
337
- extractStringsFromValue(v, results);
338
- }
339
- }
340
- }
341
280
  function isDeletedOrBlocked(obj) {
342
281
  return obj._deleted != null || obj._blocked != null;
343
282
  }
344
- function extractSearchableStringDefault(obj, spec) {
345
- if (isDeletedOrBlocked(obj)) {
346
- return;
347
- }
348
- if (spec?.enrichSearchObjectFn) {
349
- spec.enrichSearchObjectFn(obj, spec.searchContext);
350
- }
351
- const parts = [];
352
- const fieldsToSearch = spec?.searchInFields ?? Object.keys(obj);
353
- const fieldsToExclude = new Set(spec?.dontSearchInFields ?? []);
354
- for (const key of fieldsToSearch) {
355
- const keyStr = key;
356
- if (!spec?.searchInFields && DEFAULT_EXCLUDED_FIELDS.has(keyStr))
357
- continue;
358
- if (fieldsToExclude.has(key))
359
- continue;
360
- const value = isDotNotation(keyStr) ? getValueByPath(obj, keyStr) : obj[key];
361
- extractStringsFromValue(value, parts);
362
- }
363
- return parts.join(" ");
364
- }
365
- function prepareObjectForSearch(obj, spec) {
366
- if (isDeletedOrBlocked(obj)) {
367
- return;
368
- }
369
- if (spec?.extractSearchableStringFn) {
370
- const searchableString = spec.extractSearchableStringFn(obj);
371
- if (searchableString === undefined) {
372
- return;
373
- }
374
- return prepareStringForSearch(searchableString);
375
- }
376
- return prepareObjectFieldsForSearch(obj, spec);
377
- }
378
- function prepareObjectFieldsForSearch(obj, spec) {
379
- if (spec?.enrichSearchObjectFn) {
380
- spec.enrichSearchObjectFn(obj, spec.searchContext);
381
- }
382
- const allTokens = [];
383
- const fieldMatchModes = spec?.fieldMatchModes;
384
- const fieldsToSearch = spec?.searchInFields ?? Object.keys(obj);
385
- const fieldsToExclude = new Set(spec?.dontSearchInFields ?? []);
386
- const processedRootFields = new Set;
387
- for (const key of fieldsToSearch) {
388
- const keyStr = key;
389
- if (!spec?.searchInFields && DEFAULT_EXCLUDED_FIELDS.has(keyStr))
390
- continue;
391
- if (fieldsToExclude.has(key))
392
- continue;
393
- const isDot = isDotNotation(keyStr);
394
- const rootField = getRootField(keyStr);
395
- let value;
396
- if (isDot) {
397
- value = getValueByPath(obj, keyStr);
398
- } else {
399
- value = obj[key];
400
- processedRootFields.add(rootField);
401
- }
402
- if (value == null)
403
- continue;
404
- const matchMode = fieldMatchModes?.[key];
405
- const prefix = matchMode ? MATCH_MODE_PREFIXES[matchMode] : "";
406
- const fieldStrings = [];
407
- extractStringsFromValue(value, fieldStrings);
408
- if (fieldStrings.length > 0) {
409
- const fieldText = fieldStrings.join(" ");
410
- const tokens2 = prepareStringForSearch(fieldText);
411
- for (const token of tokens2) {
412
- allTokens.push(prefix + token);
413
- }
414
- }
415
- }
416
- return [...new Set(allTokens)].sort();
417
- }
418
- function createSearchArrayMetadata(data, spec) {
419
- const metadata = new Map;
420
- for (const [id, item] of data) {
421
- const tokens2 = prepareObjectForSearch(item, spec);
422
- if (tokens2 !== undefined) {
423
- metadata.set(id, tokens2);
424
- }
425
- }
426
- return metadata;
427
- }
428
- function wrapMetadataLegacy(metadata) {
429
- return { items: metadata };
430
- }
431
- function unwrapMetadataLegacy(legacy) {
432
- return legacy.items;
433
- }
434
283
 
435
284
  // src/common/numeric/createSearchArrayMetadata.ts
436
285
  var MATCH_MODE_BITS = {
@@ -464,7 +313,7 @@ function decodeMatchMode(encoded) {
464
313
  }
465
314
  }
466
315
  var DEFAULT_EXCLUDED_FIELDS2 = new Set(["_id", "_deleted", "_blocked"]);
467
- function getValueByPath2(obj, path) {
316
+ function getValueByPath(obj, path) {
468
317
  const parts = path.split(".");
469
318
  let current = obj;
470
319
  for (let i = 0;i < parts.length; i++) {
@@ -475,7 +324,7 @@ function getValueByPath2(obj, path) {
475
324
  const remainingPath = parts.slice(i).join(".");
476
325
  const results = [];
477
326
  for (const item of current) {
478
- const value = getValueByPath2(item, remainingPath);
327
+ const value = getValueByPath(item, remainingPath);
479
328
  if (value !== undefined) {
480
329
  if (Array.isArray(value)) {
481
330
  results.push(...value);
@@ -494,10 +343,10 @@ function getValueByPath2(obj, path) {
494
343
  }
495
344
  return current;
496
345
  }
497
- function isDotNotation2(field) {
346
+ function isDotNotation(field) {
498
347
  return field.includes(".");
499
348
  }
500
- function extractStringsFromValue2(value, results) {
349
+ function extractStringsFromValue(value, results) {
501
350
  if (value == null)
502
351
  return;
503
352
  if (typeof value === "string") {
@@ -508,11 +357,11 @@ function extractStringsFromValue2(value, results) {
508
357
  results.push(value.toISOString());
509
358
  } else if (Array.isArray(value)) {
510
359
  for (const item of value) {
511
- extractStringsFromValue2(item, results);
360
+ extractStringsFromValue(item, results);
512
361
  }
513
362
  } else if (typeof value === "object") {
514
363
  for (const v of Object.values(value)) {
515
- extractStringsFromValue2(v, results);
364
+ extractStringsFromValue(v, results);
516
365
  }
517
366
  }
518
367
  }
@@ -543,13 +392,13 @@ function prepareObjectFieldsForSearchNumeric(obj, spec, tokensMap) {
543
392
  continue;
544
393
  if (fieldsToExclude.has(key))
545
394
  continue;
546
- const isDot = isDotNotation2(keyStr);
547
- const value = isDot ? getValueByPath2(obj, keyStr) : obj[key];
395
+ const isDot = isDotNotation(keyStr);
396
+ const value = isDot ? getValueByPath(obj, keyStr) : obj[key];
548
397
  if (value == null)
549
398
  continue;
550
399
  const matchMode = fieldMatchModes?.[key];
551
400
  const fieldStrings = [];
552
- extractStringsFromValue2(value, fieldStrings);
401
+ extractStringsFromValue(value, fieldStrings);
553
402
  if (fieldStrings.length > 0) {
554
403
  const fieldText = fieldStrings.join(" ");
555
404
  const datesNormalized = normalizeDates(fieldText);
@@ -973,254 +822,179 @@ function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
973
822
  function findInLinkedArraysSimpleNumeric(query, linked, limit = 10, opts) {
974
823
  return findInLinkedArraysNumeric(query, linked, limit, opts).results;
975
824
  }
976
- // src/common/string/createSearchLinkedMetadata.ts
977
- function createSearchLinkedMetadata(primaryData, primaryMetadata, linkedData, linkedMetadata, foreignKeyGetter) {
978
- const primaryToLinked = new Map;
979
- for (const [linkedId, linkedItem] of linkedData) {
980
- const primaryId = foreignKeyGetter(linkedItem);
981
- if (primaryId) {
982
- const list = primaryToLinked.get(primaryId) || [];
983
- list.push(linkedId);
984
- primaryToLinked.set(primaryId, list);
825
+ // src/common/numeric/AugmentedMetadata.ts
826
+ class AugmentedMetadata {
827
+ baseMetadata;
828
+ augmentedTokens;
829
+ spec;
830
+ constructor(baseMetadata, spec, augmentedDataMap) {
831
+ this.baseMetadata = baseMetadata;
832
+ this.augmentedTokens = new Map;
833
+ this.spec = spec;
834
+ if (augmentedDataMap && augmentedDataMap.size > 0) {
835
+ this.updateAugmentedBatch(augmentedDataMap);
836
+ }
837
+ }
838
+ updateAugmented(id, augmentedData) {
839
+ if (!augmentedData) {
840
+ this.augmentedTokens.delete(id);
841
+ return;
985
842
  }
986
- }
987
- return {
988
- primaryMeta: primaryMetadata,
989
- linkedMeta: linkedMetadata,
990
- primaryToLinked,
991
- primaryData,
992
- linkedData
993
- };
994
- }
995
- // src/common/string/updateSearchMetadata.ts
996
- function updateSearchMetadata(metadata, objectId, obj, spec) {
997
- const tokens2 = obj != null ? prepareObjectForSearch(obj, spec) : undefined;
998
- if (tokens2 === undefined) {
999
- metadata.delete(objectId);
1000
- return false;
1001
- } else {
1002
- metadata.set(objectId, tokens2);
1003
- return true;
1004
- }
1005
- }
1006
- function updateSearchMetadataBatch(metadata, batch, spec) {
1007
- if (batch.length === 0) {
1008
- return { updated: 0, removed: 0 };
1009
- }
1010
- let updated = 0;
1011
- let removed = 0;
1012
- for (const { objectId, obj } of batch) {
1013
- const wasUpdated = updateSearchMetadata(metadata, objectId, obj, spec);
1014
- if (wasUpdated) {
1015
- updated++;
843
+ const tokensMap = createTokensMap();
844
+ const tokens2 = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
845
+ if (tokens2 && tokens2.length > 0) {
846
+ this.augmentedTokens.set(id, tokens2);
1016
847
  } else {
1017
- removed++;
1018
- }
1019
- }
1020
- return { updated, removed };
1021
- }
1022
- function removeFromSearchMetadata(metadata, objectId) {
1023
- return metadata.delete(objectId);
1024
- }
1025
- function removeFromSearchMetadataBatch(metadata, objectIds) {
1026
- if (objectIds.length === 0) {
1027
- return 0;
1028
- }
1029
- let removed = 0;
1030
- for (const id of objectIds) {
1031
- if (metadata.delete(id)) {
1032
- removed++;
848
+ this.augmentedTokens.delete(id);
1033
849
  }
850
+ clearTokensMap(tokensMap);
1034
851
  }
1035
- return removed;
1036
- }
1037
- // src/utils/matchToken.ts
1038
- var RE_NUMERIC2 = /^[\d.\-]+$/;
1039
- var PREFIX_TO_MODE = {
1040
- "<": "start",
1041
- ">": "end",
1042
- "+": "startEnd",
1043
- "*": "anywhere",
1044
- "!": "whole"
1045
- };
1046
- function matchWithMode(searchToken, targetToken, mode) {
1047
- switch (mode) {
1048
- case "start":
1049
- return targetToken.startsWith(searchToken);
1050
- case "end":
1051
- return targetToken.endsWith(searchToken);
1052
- case "startEnd":
1053
- return targetToken.startsWith(searchToken) || targetToken.endsWith(searchToken);
1054
- case "anywhere":
1055
- return targetToken.includes(searchToken);
1056
- case "whole":
1057
- return targetToken === searchToken;
1058
- }
1059
- }
1060
- function matchToken(searchToken, targetToken, opts) {
1061
- const firstChar = targetToken[0];
1062
- const prefixMode = firstChar ? PREFIX_TO_MODE[firstChar] : undefined;
1063
- if (prefixMode) {
1064
- const actualTarget = targetToken.slice(1);
1065
- return matchWithMode(searchToken, actualTarget, prefixMode);
1066
- }
1067
- const matchWords = opts?.matchWords ?? DEFAULT_SEARCH_OPTS.matchWords;
1068
- const matchNumbers = opts?.matchNumbers ?? DEFAULT_SEARCH_OPTS.matchNumbers;
1069
- const isNumeric = RE_NUMERIC2.test(searchToken);
1070
- return matchWithMode(searchToken, targetToken, isNumeric ? matchNumbers : matchWords);
1071
- }
1072
- function matchTokenInSortedList(searchToken, targetTokens, opts) {
1073
- const isNumeric = RE_NUMERIC2.test(searchToken);
1074
- const effectiveMode = isNumeric ? opts?.matchNumbers ?? DEFAULT_SEARCH_OPTS.matchNumbers : opts?.matchWords ?? DEFAULT_SEARCH_OPTS.matchWords;
1075
- const canEarlyExit = effectiveMode === "start";
1076
- for (const targetToken of targetTokens) {
1077
- const firstChar = targetToken[0];
1078
- const hasPrefix = firstChar ? PREFIX_TO_MODE[firstChar] !== undefined : false;
1079
- if (hasPrefix) {
1080
- if (matchToken(searchToken, targetToken, opts)) {
1081
- return true;
852
+ updateAugmentedBatch(augmentedDataMap) {
853
+ const tokensMap = createTokensMap();
854
+ for (const [id, augmentedData] of augmentedDataMap) {
855
+ if (!augmentedData) {
856
+ this.augmentedTokens.delete(id);
857
+ continue;
1082
858
  }
1083
- } else {
1084
- if (canEarlyExit) {
1085
- if (targetToken.startsWith(searchToken)) {
1086
- return true;
1087
- }
1088
- if (targetToken > searchToken && targetToken[0] !== searchToken[0]) {
1089
- return false;
1090
- }
859
+ const tokens2 = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
860
+ if (tokens2 && tokens2.length > 0) {
861
+ this.augmentedTokens.set(id, tokens2);
1091
862
  } else {
1092
- if (matchToken(searchToken, targetToken, opts)) {
1093
- return true;
1094
- }
863
+ this.augmentedTokens.delete(id);
1095
864
  }
1096
865
  }
866
+ clearTokensMap(tokensMap);
1097
867
  }
1098
- return false;
1099
- }
1100
- function allTokensMatch(searchTokens, targetTokens, opts) {
1101
- for (const searchToken of searchTokens) {
1102
- if (!matchTokenInSortedList(searchToken, targetTokens, opts)) {
1103
- return false;
1104
- }
868
+ clearAugmented(id) {
869
+ this.augmentedTokens.delete(id);
1105
870
  }
1106
- return true;
1107
- }
1108
-
1109
- // src/common/findInArrayReturnDataAndMeta.ts
1110
- function findInArrayReturnDataAndMeta(query, data, metadata, limit = 10, opts) {
1111
- const queryTokens = prepareStringForSearch(query);
1112
- if (queryTokens.length === 0) {
871
+ clearAllAugmented() {
872
+ this.augmentedTokens.clear();
873
+ }
874
+ get(id) {
875
+ const baseTokens = this.baseMetadata.get(id);
876
+ if (!baseTokens)
877
+ return;
878
+ const augTokens = this.augmentedTokens.get(id);
879
+ if (!augTokens)
880
+ return baseTokens;
881
+ return this.mergeSortedTokenArrays(baseTokens, augTokens);
882
+ }
883
+ has(id) {
884
+ return this.baseMetadata.has(id);
885
+ }
886
+ get size() {
887
+ return this.baseMetadata.size;
888
+ }
889
+ [Symbol.iterator]() {
890
+ const self = this;
891
+ const baseIterator = this.baseMetadata[Symbol.iterator]();
1113
892
  return {
1114
- queryTokens,
1115
- results: []
893
+ next() {
894
+ const baseResult = baseIterator.next();
895
+ if (baseResult.done) {
896
+ return { done: true, value: undefined };
897
+ }
898
+ const [id, baseTokens] = baseResult.value;
899
+ const augTokens = self.augmentedTokens.get(id);
900
+ const tokens2 = augTokens ? self.mergeSortedTokenArrays(baseTokens, augTokens) : baseTokens;
901
+ return { done: false, value: [id, tokens2] };
902
+ },
903
+ [Symbol.iterator]() {
904
+ return this;
905
+ },
906
+ [Symbol.dispose]() {}
1116
907
  };
1117
908
  }
1118
- const results = [];
1119
- for (const [id, itemTokens] of metadata) {
1120
- if (results.length >= limit) {
1121
- break;
1122
- }
1123
- if (allTokensMatch(queryTokens, itemTokens, opts)) {
1124
- const item = data.get(id);
1125
- if (item) {
1126
- results.push({
1127
- item,
1128
- tokens: itemTokens
1129
- });
1130
- }
1131
- }
909
+ keys() {
910
+ return this.baseMetadata.keys();
1132
911
  }
1133
- return {
1134
- queryTokens,
1135
- results
1136
- };
1137
- }
1138
- function findInArrayReturnIds(query, metadata, limit = 10, opts) {
1139
- const queryTokens = prepareStringForSearch(query);
1140
- if (queryTokens.length === 0) {
1141
- return [];
912
+ values() {
913
+ const self = this;
914
+ const keysIterator = this.baseMetadata.keys();
915
+ return {
916
+ next() {
917
+ const keyResult = keysIterator.next();
918
+ if (keyResult.done) {
919
+ return { done: true, value: undefined };
920
+ }
921
+ const tokens2 = self.get(keyResult.value);
922
+ return tokens2 ? { done: false, value: tokens2 } : { done: true, value: undefined };
923
+ },
924
+ [Symbol.iterator]() {
925
+ return this;
926
+ },
927
+ [Symbol.dispose]() {}
928
+ };
1142
929
  }
1143
- const results = [];
1144
- for (const [id, itemTokens] of metadata) {
1145
- if (results.length >= limit) {
1146
- break;
1147
- }
1148
- if (allTokensMatch(queryTokens, itemTokens, opts)) {
1149
- results.push(id);
930
+ entries() {
931
+ return this[Symbol.iterator]();
932
+ }
933
+ forEach(callbackfn) {
934
+ for (const [id, tokens2] of this) {
935
+ callbackfn(tokens2, id, this);
1150
936
  }
1151
937
  }
1152
- return results;
1153
- }
1154
-
1155
- // src/common/findInArray.ts
1156
- function findInArray(query, data, metadata, limit = 10, opts) {
1157
- const result = findInArrayReturnDataAndMeta(query, data, metadata, limit, opts);
1158
- return result.results.map((r) => r.item);
1159
- }
1160
- // src/common/findInLinkedArrays.ts
1161
- function findInLinkedArrays(query, linked, limit = 10, opts) {
1162
- const queryTokens = prepareStringForSearch(query);
1163
- const hasNegation = queryTokens.some((t) => t.startsWith("--") || t.startsWith("~") || t.length > 1 && t[0] === "-" && /^[a-z]/i.test(t[1]));
1164
- if (queryTokens.length === 0) {
1165
- return { queryTokens, results: [], hasNegation: false };
938
+ set(_key, _value) {
939
+ throw new Error("AugmentedMetadata.set() is not supported. Use updateAugmented() instead.");
1166
940
  }
1167
- const results = [];
1168
- for (const [primaryId, primary] of linked.primaryData) {
1169
- if (results.length >= limit)
1170
- break;
1171
- const primaryTokens = linked.primaryMeta.get(primaryId);
1172
- if (!primaryTokens)
1173
- continue;
1174
- const linkedIds = linked.primaryToLinked.get(primaryId) || [];
1175
- const allTokens = [...primaryTokens];
1176
- for (const linkedId of linkedIds) {
1177
- const linkedTokens = linked.linkedMeta.get(linkedId);
1178
- if (linkedTokens) {
1179
- allTokens.push(...linkedTokens);
1180
- }
1181
- }
1182
- allTokens.sort();
1183
- if (allTokensMatch(queryTokens, allTokens, opts)) {
1184
- let anyMatchInPrimary = false;
1185
- let anyMatchInLinked = false;
1186
- const matchingLinkedIds = new Set;
1187
- const tokensMatchingPrimary = new Set;
1188
- for (const queryToken of queryTokens) {
1189
- if (matchTokenInSortedList(queryToken, primaryTokens, opts)) {
1190
- anyMatchInPrimary = true;
1191
- tokensMatchingPrimary.add(queryToken);
941
+ delete(_key) {
942
+ throw new Error("AugmentedMetadata.delete() is not supported. Use clearAugmented() instead.");
943
+ }
944
+ clear() {
945
+ throw new Error("AugmentedMetadata.clear() is not supported. Use clearAllAugmented() instead.");
946
+ }
947
+ get [Symbol.toStringTag]() {
948
+ return "AugmentedMetadata";
949
+ }
950
+ mergeSortedTokenArrays(a, b) {
951
+ const merged = new Uint32Array(a.length + b.length);
952
+ let i = 0, j = 0, k = 0;
953
+ let lastToken = -1;
954
+ while (i < a.length && j < b.length) {
955
+ const tokenA = a[i];
956
+ const tokenB = b[j];
957
+ if (tokenA < tokenB) {
958
+ if (tokenA !== lastToken) {
959
+ merged[k++] = tokenA;
960
+ lastToken = tokenA;
1192
961
  }
1193
- }
1194
- const tokensForLinkedMatching = queryTokens.filter((t) => !tokensMatchingPrimary.has(t));
1195
- if (tokensForLinkedMatching.length > 0) {
1196
- for (const linkedId of linkedIds) {
1197
- const linkedTokens = linked.linkedMeta.get(linkedId);
1198
- if (linkedTokens) {
1199
- const matchesAllNonPrimaryTokens = tokensForLinkedMatching.every((queryToken) => matchTokenInSortedList(queryToken, linkedTokens, opts));
1200
- if (matchesAllNonPrimaryTokens) {
1201
- anyMatchInLinked = true;
1202
- matchingLinkedIds.add(linkedId);
1203
- }
1204
- }
962
+ i++;
963
+ } else if (tokenA > tokenB) {
964
+ if (tokenB !== lastToken) {
965
+ merged[k++] = tokenB;
966
+ lastToken = tokenB;
1205
967
  }
968
+ j++;
969
+ } else {
970
+ if (tokenA !== lastToken) {
971
+ merged[k++] = tokenA;
972
+ lastToken = tokenA;
973
+ }
974
+ i++;
975
+ j++;
1206
976
  }
1207
- if (tokensForLinkedMatching.length > 0 && matchingLinkedIds.size === 0) {
1208
- continue;
977
+ }
978
+ while (i < a.length) {
979
+ const tokenA = a[i];
980
+ if (tokenA !== lastToken) {
981
+ merged[k++] = tokenA;
982
+ lastToken = tokenA;
1209
983
  }
1210
- const matchedLinked = Array.from(matchingLinkedIds).map((id) => linked.linkedData.get(id)).filter((item) => item !== undefined);
1211
- results.push({
1212
- primary,
1213
- linked: matchedLinked,
1214
- matchedIn: anyMatchInPrimary && anyMatchInLinked ? "both" : anyMatchInPrimary ? "primary" : "linked"
1215
- });
984
+ i++;
985
+ }
986
+ while (j < b.length) {
987
+ const tokenB = b[j];
988
+ if (tokenB !== lastToken) {
989
+ merged[k++] = tokenB;
990
+ lastToken = tokenB;
991
+ }
992
+ j++;
1216
993
  }
994
+ return merged.slice(0, k);
1217
995
  }
1218
- return { queryTokens, results, hasNegation };
1219
- }
1220
- function findInLinkedArraysSimple(query, linked, limit = 10, opts) {
1221
- return findInLinkedArrays(query, linked, limit, opts).results;
1222
996
  }
1223
- // src/common/syncSearchArrayMetadata.ts
997
+ // src/common/numeric/syncSearchArrayMetadata.ts
1224
998
  function tokensEqual(a, b) {
1225
999
  if (a.length !== b.length)
1226
1000
  return false;
@@ -1230,7 +1004,7 @@ function tokensEqual(a, b) {
1230
1004
  }
1231
1005
  return true;
1232
1006
  }
1233
- function syncSearchArrayMetadata(metadata, newData, spec) {
1007
+ function syncSearchArrayMetadataNumeric(metadata, newData, spec) {
1234
1008
  const result = {
1235
1009
  added: 0,
1236
1010
  updated: 0,
@@ -1239,6 +1013,7 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
1239
1013
  updatedIds: [],
1240
1014
  removedIds: []
1241
1015
  };
1016
+ const tokensMap = createTokensMap();
1242
1017
  for (const id of metadata.keys()) {
1243
1018
  if (!newData.has(id)) {
1244
1019
  metadata.delete(id);
@@ -1247,7 +1022,7 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
1247
1022
  }
1248
1023
  }
1249
1024
  for (const [id, item] of newData) {
1250
- const newTokens = prepareObjectForSearch(item, spec);
1025
+ const newTokens = prepareObjectForSearchNumeric(item, spec, tokensMap);
1251
1026
  if (newTokens === undefined) {
1252
1027
  if (metadata.has(id)) {
1253
1028
  metadata.delete(id);
@@ -1267,9 +1042,10 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
1267
1042
  result.updatedIds.push(id);
1268
1043
  }
1269
1044
  }
1045
+ clearTokensMap(tokensMap);
1270
1046
  return result;
1271
1047
  }
1272
- function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, options, spec) {
1048
+ function syncSearchArrayMetadataNumericWithPrevious(metadata, previousData, newData, options, spec) {
1273
1049
  const result = {
1274
1050
  added: 0,
1275
1051
  updated: 0,
@@ -1278,6 +1054,7 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
1278
1054
  updatedIds: [],
1279
1055
  removedIds: []
1280
1056
  };
1057
+ const tokensMap = createTokensMap();
1281
1058
  for (const id of previousData.keys()) {
1282
1059
  if (!newData.has(id)) {
1283
1060
  metadata.delete(id);
@@ -1288,14 +1065,14 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
1288
1065
  for (const [id, item] of newData) {
1289
1066
  const wasInPrevious = previousData.has(id);
1290
1067
  if (!wasInPrevious) {
1291
- const tokens2 = prepareObjectForSearch(item, spec);
1068
+ const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
1292
1069
  if (tokens2 !== undefined) {
1293
1070
  metadata.set(id, tokens2);
1294
1071
  result.added++;
1295
1072
  result.addedIds.push(id);
1296
1073
  }
1297
1074
  } else if (!options?.skipUpdateCheck) {
1298
- const newTokens = prepareObjectForSearch(item, spec);
1075
+ const newTokens = prepareObjectForSearchNumeric(item, spec, tokensMap);
1299
1076
  if (newTokens === undefined) {
1300
1077
  metadata.delete(id);
1301
1078
  result.removed++;
@@ -1310,9 +1087,10 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
1310
1087
  }
1311
1088
  }
1312
1089
  }
1090
+ clearTokensMap(tokensMap);
1313
1091
  return result;
1314
1092
  }
1315
- // src/common/updateSearchLinkedMetadata.ts
1093
+ // src/common/numeric/updateSearchLinkedMetadata.ts
1316
1094
  function tokensEqual2(a, b) {
1317
1095
  if (a.length !== b.length)
1318
1096
  return false;
@@ -1322,11 +1100,13 @@ function tokensEqual2(a, b) {
1322
1100
  }
1323
1101
  return true;
1324
1102
  }
1325
- function upsertPrimaryItem(linked, item, spec) {
1103
+ function upsertPrimaryItemNumeric(linked, item, spec) {
1326
1104
  const id = item._id;
1327
1105
  const wasAdded = !linked.primaryData.has(id);
1328
1106
  linked.primaryData.set(id, item);
1329
- const tokens2 = prepareObjectForSearch(item, spec);
1107
+ const tokensMap = createTokensMap();
1108
+ const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
1109
+ clearTokensMap(tokensMap);
1330
1110
  if (tokens2 !== undefined) {
1331
1111
  linked.primaryMeta.set(id, tokens2);
1332
1112
  } else {
@@ -1337,7 +1117,7 @@ function upsertPrimaryItem(linked, item, spec) {
1337
1117
  }
1338
1118
  return { added: wasAdded };
1339
1119
  }
1340
- function removePrimaryItem(linked, primaryId) {
1120
+ function removePrimaryItemNumeric(linked, primaryId) {
1341
1121
  if (!linked.primaryData.has(primaryId)) {
1342
1122
  return false;
1343
1123
  }
@@ -1346,7 +1126,7 @@ function removePrimaryItem(linked, primaryId) {
1346
1126
  linked.primaryToLinked.delete(primaryId);
1347
1127
  return true;
1348
1128
  }
1349
- function upsertLinkedItem(linked, item, foreignKeyGetter, spec) {
1129
+ function upsertLinkedItemNumeric(linked, item, foreignKeyGetter, spec) {
1350
1130
  const id = item._id;
1351
1131
  const newPrimaryId = foreignKeyGetter(item);
1352
1132
  let previousPrimaryId;
@@ -1356,7 +1136,9 @@ function upsertLinkedItem(linked, item, foreignKeyGetter, spec) {
1356
1136
  }
1357
1137
  const wasAdded = !existingItem;
1358
1138
  linked.linkedData.set(id, item);
1359
- const tokens2 = prepareObjectForSearch(item, spec);
1139
+ const tokensMap = createTokensMap();
1140
+ const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
1141
+ clearTokensMap(tokensMap);
1360
1142
  if (tokens2 !== undefined) {
1361
1143
  linked.linkedMeta.set(id, tokens2);
1362
1144
  } else {
@@ -1388,7 +1170,7 @@ function upsertLinkedItem(linked, item, foreignKeyGetter, spec) {
1388
1170
  previousPrimaryId: wasAdded ? undefined : previousPrimaryId
1389
1171
  };
1390
1172
  }
1391
- function removeLinkedItem(linked, linkedId, foreignKeyGetter) {
1173
+ function removeLinkedItemNumeric(linked, linkedId, foreignKeyGetter) {
1392
1174
  const existingItem = linked.linkedData.get(linkedId);
1393
1175
  if (!existingItem) {
1394
1176
  return false;
@@ -1407,12 +1189,13 @@ function removeLinkedItem(linked, linkedId, foreignKeyGetter) {
1407
1189
  }
1408
1190
  return true;
1409
1191
  }
1410
- function syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKeyGetter, spec) {
1192
+ function syncLinkedItemsForPrimaryNumeric(linked, primaryId, newLinkedItems, foreignKeyGetter, spec) {
1411
1193
  const result = {
1412
1194
  added: 0,
1413
1195
  updated: 0,
1414
1196
  removed: 0
1415
1197
  };
1198
+ const tokensMap = createTokensMap();
1416
1199
  const currentLinkedIds = new Set(linked.primaryToLinked.get(primaryId) || []);
1417
1200
  const newLinkedIds = new Set;
1418
1201
  for (const [id, item] of newLinkedItems) {
@@ -1432,7 +1215,7 @@ function syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKey
1432
1215
  }
1433
1216
  for (const id of newLinkedIds) {
1434
1217
  const item = newLinkedItems.get(id);
1435
- const tokens2 = prepareObjectForSearch(item, spec);
1218
+ const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
1436
1219
  if (currentLinkedIds.has(id)) {
1437
1220
  const existingTokens = linked.linkedMeta.get(id);
1438
1221
  if (tokens2 !== undefined) {
@@ -1451,6 +1234,7 @@ function syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKey
1451
1234
  }
1452
1235
  }
1453
1236
  linked.primaryToLinked.set(primaryId, Array.from(newLinkedIds));
1237
+ clearTokensMap(tokensMap);
1454
1238
  return result;
1455
1239
  }
1456
1240
  // src/common/SearchUniverse.ts
@@ -1734,19 +1518,15 @@ class SearchUniverse {
1734
1518
  }
1735
1519
  }
1736
1520
  export {
1737
- wrapMetadataLegacy,
1738
- upsertPrimaryItem,
1739
- upsertLinkedItem,
1740
- updateSearchMetadata as updateSearchMetadataString,
1741
- updateSearchMetadataBatch as updateSearchMetadataBatchString,
1521
+ upsertPrimaryItemNumeric as upsertPrimaryItem,
1522
+ upsertLinkedItemNumeric as upsertLinkedItem,
1742
1523
  updateSearchMetadataBatchNumeric as updateSearchMetadataBatch,
1743
1524
  updateSearchMetadataNumeric as updateSearchMetadata,
1744
- unwrapMetadataLegacy,
1745
1525
  tokens,
1746
1526
  tokenize,
1747
- syncSearchArrayMetadataWithPrevious,
1748
- syncSearchArrayMetadata,
1749
- syncLinkedItemsForPrimary,
1527
+ syncSearchArrayMetadataNumericWithPrevious as syncSearchArrayMetadataWithPrevious,
1528
+ syncSearchArrayMetadataNumeric as syncSearchArrayMetadata,
1529
+ syncLinkedItemsForPrimaryNumeric as syncLinkedItemsForPrimary,
1750
1530
  searchableDataToArray,
1751
1531
  searchInDataReturnIdsWithLimitNumeric as searchInDataWithLimit,
1752
1532
  searchInDataReturnObjectsNumeric as searchInDataReturnObjects,
@@ -1754,22 +1534,17 @@ export {
1754
1534
  searchInDataReturnIdsNumeric as searchInData,
1755
1535
  sanitiseString,
1756
1536
  resetTokenRegistry,
1757
- removePrimaryItem,
1758
- removeLinkedItem,
1759
- removeFromSearchMetadata as removeFromSearchMetadataString,
1760
- removeFromSearchMetadataBatch as removeFromSearchMetadataBatchString,
1537
+ removePrimaryItemNumeric as removePrimaryItem,
1538
+ removeLinkedItemNumeric as removeLinkedItem,
1761
1539
  removeFromSearchMetadataBatchNumeric as removeFromSearchMetadataBatch,
1762
1540
  removeFromSearchMetadataNumeric as removeFromSearchMetadata,
1763
1541
  registerToken,
1764
1542
  preprocessString,
1765
1543
  prepareStringForSearch,
1766
1544
  prepareQueryTokens,
1767
- prepareObjectForSearch as prepareObjectForSearchString,
1768
1545
  prepareObjectForSearchNumeric as prepareObjectForSearch,
1769
1546
  normalizeDates,
1770
1547
  matchTokenInSortedListNumeric,
1771
- matchTokenInSortedList,
1772
- matchToken,
1773
1548
  matchPreparedTokenInSortedList,
1774
1549
  isDeletedOrBlocked,
1775
1550
  getTokenCount,
@@ -1777,31 +1552,21 @@ export {
1777
1552
  getOrCreateTokenId,
1778
1553
  findTokenId,
1779
1554
  findInLinkedArraysSimpleNumeric,
1780
- findInLinkedArraysSimple,
1781
1555
  findInLinkedArraysNumeric,
1782
- findInLinkedArrays,
1783
- findInArrayReturnIds,
1784
- findInArrayReturnDataAndMeta,
1785
- findInArray,
1786
- extractSearchableStringDefault,
1787
1556
  encodeTokenWithMode,
1788
1557
  decodeTokenId,
1789
1558
  decodeMatchMode,
1790
1559
  createTokensMap,
1791
- createSearchLinkedMetadata as createSearchLinkedMetadataString,
1792
1560
  createSearchLinkedMetadataNumeric as createSearchLinkedMetadata,
1793
- createSearchArrayMetadata as createSearchArrayMetadataString,
1794
1561
  createSearchArrayMetadataNumeric as createSearchArrayMetadata,
1795
1562
  clearTokensMap,
1796
1563
  binarySearchUint32,
1797
1564
  arrayToSearchableData,
1798
1565
  allTokensMatchNumeric,
1799
- allTokensMatch,
1800
1566
  allPreparedTokensMatch,
1801
1567
  TOKEN_ID_MASK,
1802
1568
  SearchUniverse,
1803
- PREFIX_TO_MATCH_MODE,
1804
- MATCH_MODE_PREFIXES,
1805
1569
  MATCH_MODE_BITS,
1806
- DEFAULT_SEARCH_OPTS
1570
+ DEFAULT_SEARCH_OPTS,
1571
+ AugmentedMetadata
1807
1572
  };