cry-search 1.0.1 → 1.0.3

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
 
@@ -369,13 +350,6 @@ function prepareStringForSearchNumeric(input, tokensMap) {
369
350
  }
370
351
 
371
352
  // src/common/string/createSearchArrayMetadata.ts
372
- var MATCH_MODE_PREFIXES = {
373
- start: "<",
374
- end: ">",
375
- startEnd: "+",
376
- anywhere: "*",
377
- whole: "!"
378
- };
379
353
  var PREFIX_TO_MATCH_MODE = {
380
354
  "<": "start",
381
355
  ">": "end",
@@ -386,155 +360,9 @@ var PREFIX_TO_MATCH_MODE = {
386
360
  "?": "anywhere"
387
361
  };
388
362
  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
363
  function isDeletedOrBlocked(obj) {
446
364
  return obj._deleted != null || obj._blocked != null;
447
365
  }
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
366
 
539
367
  // src/common/numeric/createSearchArrayMetadata.ts
540
368
  var MATCH_MODE_BITS = {
@@ -568,7 +396,7 @@ function decodeMatchMode(encoded) {
568
396
  }
569
397
  }
570
398
  var DEFAULT_EXCLUDED_FIELDS2 = new Set(["_id", "_deleted", "_blocked"]);
571
- function getValueByPath2(obj, path) {
399
+ function getValueByPath(obj, path) {
572
400
  const parts = path.split(".");
573
401
  let current = obj;
574
402
  for (let i = 0;i < parts.length; i++) {
@@ -579,7 +407,7 @@ function getValueByPath2(obj, path) {
579
407
  const remainingPath = parts.slice(i).join(".");
580
408
  const results = [];
581
409
  for (const item of current) {
582
- const value = getValueByPath2(item, remainingPath);
410
+ const value = getValueByPath(item, remainingPath);
583
411
  if (value !== undefined) {
584
412
  if (Array.isArray(value)) {
585
413
  results.push(...value);
@@ -598,10 +426,10 @@ function getValueByPath2(obj, path) {
598
426
  }
599
427
  return current;
600
428
  }
601
- function isDotNotation2(field) {
429
+ function isDotNotation(field) {
602
430
  return field.includes(".");
603
431
  }
604
- function extractStringsFromValue2(value, results) {
432
+ function extractStringsFromValue(value, results) {
605
433
  if (value == null)
606
434
  return;
607
435
  if (typeof value === "string") {
@@ -612,11 +440,11 @@ function extractStringsFromValue2(value, results) {
612
440
  results.push(value.toISOString());
613
441
  } else if (Array.isArray(value)) {
614
442
  for (const item of value) {
615
- extractStringsFromValue2(item, results);
443
+ extractStringsFromValue(item, results);
616
444
  }
617
445
  } else if (typeof value === "object") {
618
446
  for (const v of Object.values(value)) {
619
- extractStringsFromValue2(v, results);
447
+ extractStringsFromValue(v, results);
620
448
  }
621
449
  }
622
450
  }
@@ -647,13 +475,13 @@ function prepareObjectFieldsForSearchNumeric(obj, spec, tokensMap) {
647
475
  continue;
648
476
  if (fieldsToExclude.has(key))
649
477
  continue;
650
- const isDot = isDotNotation2(keyStr);
651
- const value = isDot ? getValueByPath2(obj, keyStr) : obj[key];
478
+ const isDot = isDotNotation(keyStr);
479
+ const value = isDot ? getValueByPath(obj, keyStr) : obj[key];
652
480
  if (value == null)
653
481
  continue;
654
482
  const matchMode = fieldMatchModes?.[key];
655
483
  const fieldStrings = [];
656
- extractStringsFromValue2(value, fieldStrings);
484
+ extractStringsFromValue(value, fieldStrings);
657
485
  if (fieldStrings.length > 0) {
658
486
  const fieldText = fieldStrings.join(" ");
659
487
  const datesNormalized = normalizeDates(fieldText);
@@ -1077,254 +905,179 @@ function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
1077
905
  function findInLinkedArraysSimpleNumeric(query, linked, limit = 10, opts) {
1078
906
  return findInLinkedArraysNumeric(query, linked, limit, opts).results;
1079
907
  }
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);
908
+ // src/common/numeric/AugmentedMetadata.ts
909
+ class AugmentedMetadata {
910
+ baseMetadata;
911
+ augmentedTokens;
912
+ spec;
913
+ constructor(baseMetadata, spec, augmentedDataMap) {
914
+ this.baseMetadata = baseMetadata;
915
+ this.augmentedTokens = new Map;
916
+ this.spec = spec;
917
+ if (augmentedDataMap && augmentedDataMap.size > 0) {
918
+ this.updateAugmentedBatch(augmentedDataMap);
919
+ }
920
+ }
921
+ updateAugmented(id, augmentedData) {
922
+ if (!augmentedData) {
923
+ this.augmentedTokens.delete(id);
924
+ return;
1089
925
  }
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++;
926
+ const tokensMap = createTokensMap();
927
+ const tokens2 = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
928
+ if (tokens2 && tokens2.length > 0) {
929
+ this.augmentedTokens.set(id, tokens2);
1120
930
  } 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++;
931
+ this.augmentedTokens.delete(id);
1137
932
  }
933
+ clearTokensMap(tokensMap);
1138
934
  }
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;
935
+ updateAugmentedBatch(augmentedDataMap) {
936
+ const tokensMap = createTokensMap();
937
+ for (const [id, augmentedData] of augmentedDataMap) {
938
+ if (!augmentedData) {
939
+ this.augmentedTokens.delete(id);
940
+ continue;
1186
941
  }
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
- }
942
+ const tokens2 = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
943
+ if (tokens2 && tokens2.length > 0) {
944
+ this.augmentedTokens.set(id, tokens2);
1195
945
  } else {
1196
- if (matchToken(searchToken, targetToken, opts)) {
1197
- return true;
1198
- }
946
+ this.augmentedTokens.delete(id);
1199
947
  }
1200
948
  }
949
+ clearTokensMap(tokensMap);
1201
950
  }
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
- }
951
+ clearAugmented(id) {
952
+ this.augmentedTokens.delete(id);
1209
953
  }
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) {
954
+ clearAllAugmented() {
955
+ this.augmentedTokens.clear();
956
+ }
957
+ get(id) {
958
+ const baseTokens = this.baseMetadata.get(id);
959
+ if (!baseTokens)
960
+ return;
961
+ const augTokens = this.augmentedTokens.get(id);
962
+ if (!augTokens)
963
+ return baseTokens;
964
+ return this.mergeSortedTokenArrays(baseTokens, augTokens);
965
+ }
966
+ has(id) {
967
+ return this.baseMetadata.has(id);
968
+ }
969
+ get size() {
970
+ return this.baseMetadata.size;
971
+ }
972
+ [Symbol.iterator]() {
973
+ const self = this;
974
+ const baseIterator = this.baseMetadata[Symbol.iterator]();
1217
975
  return {
1218
- queryTokens,
1219
- results: []
976
+ next() {
977
+ const baseResult = baseIterator.next();
978
+ if (baseResult.done) {
979
+ return { done: true, value: undefined };
980
+ }
981
+ const [id, baseTokens] = baseResult.value;
982
+ const augTokens = self.augmentedTokens.get(id);
983
+ const tokens2 = augTokens ? self.mergeSortedTokenArrays(baseTokens, augTokens) : baseTokens;
984
+ return { done: false, value: [id, tokens2] };
985
+ },
986
+ [Symbol.iterator]() {
987
+ return this;
988
+ },
989
+ [Symbol.dispose]() {}
1220
990
  };
1221
991
  }
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
- }
992
+ keys() {
993
+ return this.baseMetadata.keys();
1236
994
  }
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 [];
995
+ values() {
996
+ const self = this;
997
+ const keysIterator = this.baseMetadata.keys();
998
+ return {
999
+ next() {
1000
+ const keyResult = keysIterator.next();
1001
+ if (keyResult.done) {
1002
+ return { done: true, value: undefined };
1003
+ }
1004
+ const tokens2 = self.get(keyResult.value);
1005
+ return tokens2 ? { done: false, value: tokens2 } : { done: true, value: undefined };
1006
+ },
1007
+ [Symbol.iterator]() {
1008
+ return this;
1009
+ },
1010
+ [Symbol.dispose]() {}
1011
+ };
1246
1012
  }
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);
1013
+ entries() {
1014
+ return this[Symbol.iterator]();
1015
+ }
1016
+ forEach(callbackfn) {
1017
+ for (const [id, tokens2] of this) {
1018
+ callbackfn(tokens2, id, this);
1254
1019
  }
1255
1020
  }
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 };
1021
+ set(_key, _value) {
1022
+ throw new Error("AugmentedMetadata.set() is not supported. Use updateAugmented() instead.");
1270
1023
  }
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);
1024
+ delete(_key) {
1025
+ throw new Error("AugmentedMetadata.delete() is not supported. Use clearAugmented() instead.");
1026
+ }
1027
+ clear() {
1028
+ throw new Error("AugmentedMetadata.clear() is not supported. Use clearAllAugmented() instead.");
1029
+ }
1030
+ get [Symbol.toStringTag]() {
1031
+ return "AugmentedMetadata";
1032
+ }
1033
+ mergeSortedTokenArrays(a, b) {
1034
+ const merged = new Uint32Array(a.length + b.length);
1035
+ let i = 0, j = 0, k = 0;
1036
+ let lastToken = -1;
1037
+ while (i < a.length && j < b.length) {
1038
+ const tokenA = a[i];
1039
+ const tokenB = b[j];
1040
+ if (tokenA < tokenB) {
1041
+ if (tokenA !== lastToken) {
1042
+ merged[k++] = tokenA;
1043
+ lastToken = tokenA;
1296
1044
  }
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
- }
1045
+ i++;
1046
+ } else if (tokenA > tokenB) {
1047
+ if (tokenB !== lastToken) {
1048
+ merged[k++] = tokenB;
1049
+ lastToken = tokenB;
1309
1050
  }
1051
+ j++;
1052
+ } else {
1053
+ if (tokenA !== lastToken) {
1054
+ merged[k++] = tokenA;
1055
+ lastToken = tokenA;
1056
+ }
1057
+ i++;
1058
+ j++;
1310
1059
  }
1311
- if (tokensForLinkedMatching.length > 0 && matchingLinkedIds.size === 0) {
1312
- continue;
1060
+ }
1061
+ while (i < a.length) {
1062
+ const tokenA = a[i];
1063
+ if (tokenA !== lastToken) {
1064
+ merged[k++] = tokenA;
1065
+ lastToken = tokenA;
1313
1066
  }
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
- });
1067
+ i++;
1068
+ }
1069
+ while (j < b.length) {
1070
+ const tokenB = b[j];
1071
+ if (tokenB !== lastToken) {
1072
+ merged[k++] = tokenB;
1073
+ lastToken = tokenB;
1074
+ }
1075
+ j++;
1320
1076
  }
1077
+ return merged.slice(0, k);
1321
1078
  }
1322
- return { queryTokens, results, hasNegation };
1323
- }
1324
- function findInLinkedArraysSimple(query, linked, limit = 10, opts) {
1325
- return findInLinkedArrays(query, linked, limit, opts).results;
1326
1079
  }
1327
- // src/common/syncSearchArrayMetadata.ts
1080
+ // src/common/numeric/syncSearchArrayMetadata.ts
1328
1081
  function tokensEqual(a, b) {
1329
1082
  if (a.length !== b.length)
1330
1083
  return false;
@@ -1334,7 +1087,7 @@ function tokensEqual(a, b) {
1334
1087
  }
1335
1088
  return true;
1336
1089
  }
1337
- function syncSearchArrayMetadata(metadata, newData, spec) {
1090
+ function syncSearchArrayMetadataNumeric(metadata, newData, spec) {
1338
1091
  const result = {
1339
1092
  added: 0,
1340
1093
  updated: 0,
@@ -1343,6 +1096,7 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
1343
1096
  updatedIds: [],
1344
1097
  removedIds: []
1345
1098
  };
1099
+ const tokensMap = createTokensMap();
1346
1100
  for (const id of metadata.keys()) {
1347
1101
  if (!newData.has(id)) {
1348
1102
  metadata.delete(id);
@@ -1351,7 +1105,7 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
1351
1105
  }
1352
1106
  }
1353
1107
  for (const [id, item] of newData) {
1354
- const newTokens = prepareObjectForSearch(item, spec);
1108
+ const newTokens = prepareObjectForSearchNumeric(item, spec, tokensMap);
1355
1109
  if (newTokens === undefined) {
1356
1110
  if (metadata.has(id)) {
1357
1111
  metadata.delete(id);
@@ -1371,9 +1125,10 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
1371
1125
  result.updatedIds.push(id);
1372
1126
  }
1373
1127
  }
1128
+ clearTokensMap(tokensMap);
1374
1129
  return result;
1375
1130
  }
1376
- function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, options, spec) {
1131
+ function syncSearchArrayMetadataNumericWithPrevious(metadata, previousData, newData, options, spec) {
1377
1132
  const result = {
1378
1133
  added: 0,
1379
1134
  updated: 0,
@@ -1382,6 +1137,7 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
1382
1137
  updatedIds: [],
1383
1138
  removedIds: []
1384
1139
  };
1140
+ const tokensMap = createTokensMap();
1385
1141
  for (const id of previousData.keys()) {
1386
1142
  if (!newData.has(id)) {
1387
1143
  metadata.delete(id);
@@ -1392,14 +1148,14 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
1392
1148
  for (const [id, item] of newData) {
1393
1149
  const wasInPrevious = previousData.has(id);
1394
1150
  if (!wasInPrevious) {
1395
- const tokens2 = prepareObjectForSearch(item, spec);
1151
+ const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
1396
1152
  if (tokens2 !== undefined) {
1397
1153
  metadata.set(id, tokens2);
1398
1154
  result.added++;
1399
1155
  result.addedIds.push(id);
1400
1156
  }
1401
1157
  } else if (!options?.skipUpdateCheck) {
1402
- const newTokens = prepareObjectForSearch(item, spec);
1158
+ const newTokens = prepareObjectForSearchNumeric(item, spec, tokensMap);
1403
1159
  if (newTokens === undefined) {
1404
1160
  metadata.delete(id);
1405
1161
  result.removed++;
@@ -1414,9 +1170,10 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
1414
1170
  }
1415
1171
  }
1416
1172
  }
1173
+ clearTokensMap(tokensMap);
1417
1174
  return result;
1418
1175
  }
1419
- // src/common/updateSearchLinkedMetadata.ts
1176
+ // src/common/numeric/updateSearchLinkedMetadata.ts
1420
1177
  function tokensEqual2(a, b) {
1421
1178
  if (a.length !== b.length)
1422
1179
  return false;
@@ -1426,11 +1183,13 @@ function tokensEqual2(a, b) {
1426
1183
  }
1427
1184
  return true;
1428
1185
  }
1429
- function upsertPrimaryItem(linked, item, spec) {
1186
+ function upsertPrimaryItemNumeric(linked, item, spec) {
1430
1187
  const id = item._id;
1431
1188
  const wasAdded = !linked.primaryData.has(id);
1432
1189
  linked.primaryData.set(id, item);
1433
- const tokens2 = prepareObjectForSearch(item, spec);
1190
+ const tokensMap = createTokensMap();
1191
+ const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
1192
+ clearTokensMap(tokensMap);
1434
1193
  if (tokens2 !== undefined) {
1435
1194
  linked.primaryMeta.set(id, tokens2);
1436
1195
  } else {
@@ -1441,7 +1200,7 @@ function upsertPrimaryItem(linked, item, spec) {
1441
1200
  }
1442
1201
  return { added: wasAdded };
1443
1202
  }
1444
- function removePrimaryItem(linked, primaryId) {
1203
+ function removePrimaryItemNumeric(linked, primaryId) {
1445
1204
  if (!linked.primaryData.has(primaryId)) {
1446
1205
  return false;
1447
1206
  }
@@ -1450,7 +1209,7 @@ function removePrimaryItem(linked, primaryId) {
1450
1209
  linked.primaryToLinked.delete(primaryId);
1451
1210
  return true;
1452
1211
  }
1453
- function upsertLinkedItem(linked, item, foreignKeyGetter, spec) {
1212
+ function upsertLinkedItemNumeric(linked, item, foreignKeyGetter, spec) {
1454
1213
  const id = item._id;
1455
1214
  const newPrimaryId = foreignKeyGetter(item);
1456
1215
  let previousPrimaryId;
@@ -1460,7 +1219,9 @@ function upsertLinkedItem(linked, item, foreignKeyGetter, spec) {
1460
1219
  }
1461
1220
  const wasAdded = !existingItem;
1462
1221
  linked.linkedData.set(id, item);
1463
- const tokens2 = prepareObjectForSearch(item, spec);
1222
+ const tokensMap = createTokensMap();
1223
+ const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
1224
+ clearTokensMap(tokensMap);
1464
1225
  if (tokens2 !== undefined) {
1465
1226
  linked.linkedMeta.set(id, tokens2);
1466
1227
  } else {
@@ -1492,7 +1253,7 @@ function upsertLinkedItem(linked, item, foreignKeyGetter, spec) {
1492
1253
  previousPrimaryId: wasAdded ? undefined : previousPrimaryId
1493
1254
  };
1494
1255
  }
1495
- function removeLinkedItem(linked, linkedId, foreignKeyGetter) {
1256
+ function removeLinkedItemNumeric(linked, linkedId, foreignKeyGetter) {
1496
1257
  const existingItem = linked.linkedData.get(linkedId);
1497
1258
  if (!existingItem) {
1498
1259
  return false;
@@ -1511,12 +1272,13 @@ function removeLinkedItem(linked, linkedId, foreignKeyGetter) {
1511
1272
  }
1512
1273
  return true;
1513
1274
  }
1514
- function syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKeyGetter, spec) {
1275
+ function syncLinkedItemsForPrimaryNumeric(linked, primaryId, newLinkedItems, foreignKeyGetter, spec) {
1515
1276
  const result = {
1516
1277
  added: 0,
1517
1278
  updated: 0,
1518
1279
  removed: 0
1519
1280
  };
1281
+ const tokensMap = createTokensMap();
1520
1282
  const currentLinkedIds = new Set(linked.primaryToLinked.get(primaryId) || []);
1521
1283
  const newLinkedIds = new Set;
1522
1284
  for (const [id, item] of newLinkedItems) {
@@ -1536,7 +1298,7 @@ function syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKey
1536
1298
  }
1537
1299
  for (const id of newLinkedIds) {
1538
1300
  const item = newLinkedItems.get(id);
1539
- const tokens2 = prepareObjectForSearch(item, spec);
1301
+ const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
1540
1302
  if (currentLinkedIds.has(id)) {
1541
1303
  const existingTokens = linked.linkedMeta.get(id);
1542
1304
  if (tokens2 !== undefined) {
@@ -1555,6 +1317,7 @@ function syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKey
1555
1317
  }
1556
1318
  }
1557
1319
  linked.primaryToLinked.set(primaryId, Array.from(newLinkedIds));
1320
+ clearTokensMap(tokensMap);
1558
1321
  return result;
1559
1322
  }
1560
1323
  // src/common/SearchUniverse.ts