@delali/narsil 0.3.1-next.73 → 0.3.1-next.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/{capabilities-CYeAWYxQ.d.ts → capabilities-BHNksicw.d.ts} +16 -2
  2. package/dist/{chunk-PU43WDY4.mjs → chunk-2E35UM3G.mjs} +1 -13
  3. package/dist/{chunk-AK3BLGCI.mjs → chunk-356UOTK2.mjs} +15 -48
  4. package/dist/chunk-7ODNRREZ.mjs +2050 -0
  5. package/dist/chunk-AIUOAN7Y.mjs +658 -0
  6. package/dist/{chunk-WVDFG45M.mjs → chunk-AMGDG4ZJ.mjs} +3 -2
  7. package/dist/{chunk-AFKH4ZK3.mjs → chunk-BT62MUM5.mjs} +1 -1
  8. package/dist/{chunk-LPBWCHBE.mjs → chunk-BT6BI4GV.mjs} +42 -4
  9. package/dist/{chunk-LJYTW7GT.mjs → chunk-IBR6634K.mjs} +1 -1
  10. package/dist/chunk-KEHK2O6P.mjs +13 -0
  11. package/dist/{chunk-CVFAFZSN.mjs → chunk-LOARLB4F.mjs} +46 -34
  12. package/dist/{chunk-3YKWSO54.mjs → chunk-NAMGDK45.mjs} +228 -649
  13. package/dist/{chunk-2WLD2NFW.mjs → chunk-PXDY5VRT.mjs} +3 -3
  14. package/dist/chunk-UOJIV2NG.mjs +593 -0
  15. package/dist/chunk-V3B24XR7.mjs +54 -0
  16. package/dist/{chunk-ZULSEZCE.mjs → chunk-WL2GDSCV.mjs} +100 -19
  17. package/dist/{chunk-THMSFOJO.mjs → chunk-YOVS4EV5.mjs} +582 -598
  18. package/dist/{client-D698E5ge.d.ts → client-D4sXFS9f.d.ts} +3 -3
  19. package/dist/client.d.ts +8 -8
  20. package/dist/{config-Bv8etwUZ.d.ts → config-B-GRonqw.d.ts} +2 -2
  21. package/dist/{config-QXU3HMpq.d.ts → config-C1kbq1X2.d.ts} +2 -2
  22. package/dist/direct-executor-AVNWB73C.mjs +16 -0
  23. package/dist/distribution/coordinator/etcd.d.ts +2 -2
  24. package/dist/distribution/coordinator/etcd.mjs +1 -1
  25. package/dist/distribution/coordinator/in-memory.d.ts +2 -2
  26. package/dist/distribution/coordinator/in-memory.mjs +1 -1
  27. package/dist/distribution.d.ts +8 -8
  28. package/dist/distribution.mjs +23 -13
  29. package/dist/{engine-D_OzKZ-6.d.ts → engine-DcGSd5vh.d.ts} +2 -2
  30. package/dist/index.browser.mjs +1272 -834
  31. package/dist/index.d.ts +27 -8
  32. package/dist/index.mjs +14 -11
  33. package/dist/invalidation/filesystem.mjs +1 -1
  34. package/dist/{memory-B4jMmygw.d.ts → memory-M9kPmYP8.d.ts} +1257 -1178
  35. package/dist/partial-words-DTIHO8G4.d.ts +19 -0
  36. package/dist/partial-words.d.ts +22 -0
  37. package/dist/partial-words.mjs +11 -0
  38. package/dist/pattern.mjs +2 -2
  39. package/dist/persistence/durability/checkpoint-worker.d.ts +33 -13
  40. package/dist/persistence/durability/checkpoint-worker.mjs +14 -11
  41. package/dist/react.d.ts +7 -7
  42. package/dist/{schema-BBOCdhND.d.ts → schema-DgyDijhf.d.ts} +6 -2
  43. package/dist/server.d.ts +10 -10
  44. package/dist/server.mjs +36 -11
  45. package/dist/{tasks-DpgCpW1x.d.ts → tasks-A8se0J98.d.ts} +1 -1
  46. package/dist/{thread-3LNVA43V.mjs → thread-BSIKT6ED.mjs} +16 -9
  47. package/dist/{types-BiUmaiWT.d.ts → types-ChrVy4lH.d.ts} +1 -1
  48. package/dist/vector/search-worker.d.ts +1 -1
  49. package/dist/vector/search-worker.mjs +4 -3
  50. package/dist/workers/entry.mjs +3 -3
  51. package/package.json +16 -7
  52. package/dist/chunk-XW25X6AU.mjs +0 -614
  53. package/dist/chunk-ZKRV5M2P.mjs +0 -75
  54. package/dist/direct-executor-5SRDFZAS.mjs +0 -13
@@ -1,7 +1,9 @@
1
- import { clampRowCount, sortSignatureOf, requireSortableFields, decodePageCursor, requireMatchingCursor, resolveProjection, encodePageCursor, requireWithinResultWindow, normalizeSort, fanOutQuery, sortModesOf, applySorting, applyPagination, projectionKeepsField, countsWithoutScores, fanOutMatchCount, tokenize, fnv1aBytes, requireValidFilter, createPatternWorkMeter, everyValueFacetConfig, fulltextMatches, mergeFacets, pruneStatsToQueryTerms, partitionsIn, undeclaredFieldOnStrictIndex, fuzzyTermMatches } from './chunk-3YKWSO54.mjs';
2
- import { MAX_INDEX_NAME_LENGTH, INDEX_NAME_PATTERN, MAX_DOC_ID_LENGTH, MIN_PATTERN_VALUE_LIMIT, MAX_PATTERN_VALUE_LIMIT, DEFAULT_LIMIT, DEFAULT_MAX_PER_GROUP, flattenSchema, DEFAULT_SUGGEST_LIMIT, MAX_SUGGEST_LIMIT, MAX_SUGGEST_SCATTER_LIMIT, ABSOLUTE_WINDOWS_PATH_PATTERN, MODULE_URL_SCHEME_PATTERN, DEFAULT_LINEAR_ALPHA, MIN_LINEAR_ALPHA, MAX_LINEAR_ALPHA, DEFAULT_RANK_CONSTANT, MIN_RANK_CONSTANT, DEFAULT_OFFSET, DEFAULT_FUZZY_PREFIX_LENGTH, RESULT_WINDOW, isWordIndexedFieldType, isGeopointOrVectorType, MAX_TOLERANCE, MAX_PREFIX_LENGTH } from './chunk-AK3BLGCI.mjs';
1
+ import { clampRowCount, sortSignatureOf, requireSortableFields, decodePageCursor, requireMatchingCursor, resolveProjection, encodePageCursor, requireWithinResultWindow, normalizeSort, fanOutQuery, sortModesOf, applySorting, applyPagination, projectionKeepsField, countsWithoutScores, fanOutMatchCount, fnv1aBytes, requireValidFilter, createPatternWorkMeter, everyValueFacetConfig, fulltextMatches, mergeFacets, pruneStatsToQueryTerms, partitionsIn, undeclaredFieldOnStrictIndex } from './chunk-NAMGDK45.mjs';
2
+ import { MAX_INDEX_NAME_LENGTH, INDEX_NAME_PATTERN, MAX_DOC_ID_LENGTH, DEFAULT_LIMIT, DEFAULT_MAX_PER_GROUP, DEFAULT_SUGGEST_LIMIT, MAX_SUGGEST_LIMIT, MAX_SUGGEST_SCATTER_LIMIT, ABSOLUTE_WINDOWS_PATH_PATTERN, MODULE_URL_SCHEME_PATTERN, DEFAULT_LINEAR_ALPHA, MIN_LINEAR_ALPHA, MAX_LINEAR_ALPHA, DEFAULT_RANK_CONSTANT, MIN_RANK_CONSTANT, DEFAULT_OFFSET, DEFAULT_FUZZY_PREFIX_LENGTH, RESULT_WINDOW, PARTIAL_WORD_MIN_CODE_POINTS, PARTIAL_WORDS_ADDED_PER_QUERY, MAX_TOLERANCE, MAX_PREFIX_LENGTH } from './chunk-V3B24XR7.mjs';
3
3
  import { MIN_OVERSAMPLE } from './chunk-ZJ4CSAB2.mjs';
4
- import { holdsUnpairedSurrogate, compareCodePoints, compareComparableKeys } from './chunk-LJYTW7GT.mjs';
4
+ import { tokenize, fuzzyTermMatches } from './chunk-UOJIV2NG.mjs';
5
+ import { partialFieldsOf, MIN_PATTERN_VALUE_LIMIT, MAX_PATTERN_VALUE_LIMIT, flattenSchema, isWordIndexedFieldType, isGeopointOrVectorType } from './chunk-356UOTK2.mjs';
6
+ import { holdsUnpairedSurrogate, compareCodePoints, compareComparableKeys, codePointCount } from './chunk-IBR6634K.mjs';
5
7
  import { NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
6
8
 
7
9
  // src/search/cursor-binding.ts
@@ -129,7 +131,7 @@ function boundVectorOf(vector) {
129
131
  return bound;
130
132
  }
131
133
  var FILTERS_SLOT = 2;
132
- var BOUND_SLOT_COUNT = 15;
134
+ var BOUND_SLOT_COUNT = 16;
133
135
  function bindingOf(values) {
134
136
  const stream = { bytes: new Uint8Array(256), length: 0 };
135
137
  for (const value of values) {
@@ -148,6 +150,7 @@ function queryBindingOf(params) {
148
150
  params.tolerance,
149
151
  params.prefixLength,
150
152
  params.prefix,
153
+ params.partialWords,
151
154
  params.exact,
152
155
  params.pinned,
153
156
  params.mode,
@@ -316,9 +319,18 @@ function requireKnownMode(params) {
316
319
  { mode: String(params.mode), modes: [...SEARCH_MODES] }
317
320
  );
318
321
  }
322
+ function requireBooleanPartialWords(params) {
323
+ const setting = params.partialWords;
324
+ if (setting === void 0 || typeof setting === "boolean") return;
325
+ throw new NarsilError(ErrorCodes.CONFIG_INVALID, 'The "partialWords" query option takes true or false', {
326
+ option: "partialWords",
327
+ received: setting === null ? "null" : typeof setting
328
+ });
329
+ }
319
330
  function requireValidQueryOptions(params, config) {
320
331
  const strict = config.strict === true;
321
332
  requireValidTypoTolerance(params);
333
+ requireBooleanPartialWords(params);
322
334
  requireSortableFields(params.sort, config.schema, strict);
323
335
  requireValidQueryFilter(params.filters, config.schema);
324
336
  requireUsableQueryFields(params, config.schema, strict);
@@ -424,6 +436,16 @@ function validatePartitionConfig(partitions) {
424
436
  });
425
437
  }
426
438
  }
439
+ function requireSurfaceFormsForPartialFields(schema, surfaceForms) {
440
+ if (surfaceForms !== false) return;
441
+ const partialFields = partialFieldsOf(schema);
442
+ if (partialFields.length === 0) return;
443
+ throw new NarsilError(
444
+ ErrorCodes.CONFIG_INVALID,
445
+ `Field "${partialFields[0]}" declares "partial", which compares words as the documents wrote them, so its index needs surfaceForms left on`,
446
+ { fields: [...partialFields], surfaceForms: false }
447
+ );
448
+ }
427
449
  function validatePatternValueLimit(limit) {
428
450
  if (limit === void 0) return;
429
451
  if (typeof limit !== "number" || !Number.isInteger(limit) || limit < MIN_PATTERN_VALUE_LIMIT || limit > MAX_PATTERN_VALUE_LIMIT) {
@@ -813,6 +835,31 @@ function applySnippetTruncation(taggedText, originalText, positions, maxLen, pre
813
835
  if (needsTrailingEllipsis) snippet = `${snippet}...`;
814
836
  return { snippet, visiblePositions };
815
837
  }
838
+ function containsPartialWord(spelling, words) {
839
+ for (const word of words) {
840
+ if (spelling.length > word.length && spelling.includes(word)) return true;
841
+ }
842
+ return false;
843
+ }
844
+ function partialWordMatcher(text, language, partial) {
845
+ const indexed = tokenize(text, language, {
846
+ stem: true,
847
+ removeStopWords: true,
848
+ collectSurfaces: true,
849
+ customTokenizer: partial.customTokenizer,
850
+ stopWordOverride: partial.stopWordOverride
851
+ });
852
+ const positions = /* @__PURE__ */ new Set();
853
+ const spellings = /* @__PURE__ */ new Set();
854
+ for (let at = 0; at < indexed.tokens.length; at++) {
855
+ const spelling = indexed.surfaces?.[at] ?? indexed.tokens[at].token;
856
+ if (!containsPartialWord(spelling, partial.words)) continue;
857
+ positions.add(indexed.tokens[at].position);
858
+ spellings.add(spelling);
859
+ }
860
+ if (partial.customTokenizer !== void 0) return (_position, fieldToken) => spellings.has(fieldToken);
861
+ return (position) => positions.has(position);
862
+ }
816
863
  function highlightField(text, queryTokens, language, options) {
817
864
  const preTag = options?.preTag ?? "<mark>";
818
865
  const postTag = options?.postTag ?? "</mark>";
@@ -849,11 +896,13 @@ function highlightField(text, queryTokens, language, options) {
849
896
  matchByFieldToken.set(fieldToken, matches);
850
897
  return matches;
851
898
  };
899
+ const matchesInside = options?.partialWords === void 0 ? null : partialWordMatcher(text, language, options.partialWords);
852
900
  for (let i = 0; i < fieldResult.tokens.length; i++) {
853
901
  if (i >= charOffsets.length) break;
854
902
  const fieldToken = fieldResult.tokens[i].token;
855
903
  const prefixMatch = prefixToken !== void 0 && fieldToken.startsWith(prefixToken);
856
- if (prefixMatch || matchesQuery(fieldToken)) {
904
+ const insideMatch = matchesInside?.(fieldResult.tokens[i].position, fieldToken) === true;
905
+ if (prefixMatch || insideMatch || matchesQuery(fieldToken)) {
857
906
  matchedRanges.push({ start: charOffsets[i].start, end: charOffsets[i].end });
858
907
  }
859
908
  }
@@ -885,7 +934,39 @@ function highlightField(text, queryTokens, language, options) {
885
934
  }
886
935
 
887
936
  // src/engine/query/highlight.ts
888
- function applyHighlights(hits, params, language, analysis, readStoredDocument) {
937
+ function writtenWordsOf(params, language, analysis) {
938
+ return tokenize(params.term ?? "", language, {
939
+ stem: false,
940
+ removeStopWords: true,
941
+ customTokenizer: analysis.customTokenizer,
942
+ stopWordOverride: analysis.stopWords
943
+ }).tokens;
944
+ }
945
+ function partialWordTagging(params, schema, queryTokens, written, analysis) {
946
+ if (params.partialWords !== true || params.exact === true) return null;
947
+ const fields = partialFieldsOf(schema).filter((field) => params.fields === void 0 || params.fields.includes(field));
948
+ if (fields.length === 0) return null;
949
+ const writtenAt = /* @__PURE__ */ new Map();
950
+ for (const word of written) {
951
+ if (!writtenAt.has(word.position)) writtenAt.set(word.position, word.token);
952
+ }
953
+ const seenTokens = /* @__PURE__ */ new Set();
954
+ const words = [];
955
+ for (const queryToken of queryTokens) {
956
+ if (seenTokens.has(queryToken.token)) continue;
957
+ seenTokens.add(queryToken.token);
958
+ const word = writtenAt.get(queryToken.position);
959
+ if (word === void 0 || codePointCount(word) < PARTIAL_WORD_MIN_CODE_POINTS) continue;
960
+ words.push(word);
961
+ if (words.length === PARTIAL_WORDS_ADDED_PER_QUERY) break;
962
+ }
963
+ if (words.length === 0) return null;
964
+ return {
965
+ fields: new Set(fields),
966
+ highlight: { words, customTokenizer: analysis.customTokenizer, stopWordOverride: analysis.stopWords }
967
+ };
968
+ }
969
+ function applyHighlights(hits, params, language, analysis, schema, readStoredDocument) {
889
970
  if (!params.highlight) return;
890
971
  const queryTokenResult = tokenize(params.term ?? "", language, {
891
972
  stem: true,
@@ -893,17 +974,15 @@ function applyHighlights(hits, params, language, analysis, readStoredDocument) {
893
974
  customTokenizer: analysis.customTokenizer,
894
975
  stopWordOverride: analysis.stopWords
895
976
  });
977
+ const queryTokens = queryTokenResult.tokens;
978
+ const usesPrefix = params.prefix === true && params.exact !== true && queryTokens.length > 0;
979
+ const usesPartialWords = params.partialWords === true && params.exact !== true && queryTokens.length > 0;
980
+ const written = usesPrefix || usesPartialWords ? writtenWordsOf(params, language, analysis) : [];
896
981
  let prefixToken;
897
982
  let completedToken;
898
- if (params.prefix === true && params.exact !== true && queryTokenResult.tokens.length > 0) {
899
- const lastToken = queryTokenResult.tokens[queryTokenResult.tokens.length - 1];
900
- const unstemmed = tokenize(params.term ?? "", language, {
901
- stem: false,
902
- removeStopWords: true,
903
- customTokenizer: analysis.customTokenizer,
904
- stopWordOverride: analysis.stopWords
905
- });
906
- for (const t of unstemmed.tokens) {
983
+ if (usesPrefix) {
984
+ const lastToken = queryTokens[queryTokens.length - 1];
985
+ for (const t of written) {
907
986
  if (t.position === lastToken.position) {
908
987
  prefixToken = t.token;
909
988
  completedToken = lastToken.token;
@@ -911,6 +990,7 @@ function applyHighlights(hits, params, language, analysis, readStoredDocument) {
911
990
  }
912
991
  }
913
992
  }
993
+ const partialWords = usesPartialWords ? partialWordTagging(params, schema, queryTokens, written, analysis) : null;
914
994
  for (const hit of hits) {
915
995
  const highlights = {};
916
996
  const projected = hit.document;
@@ -922,14 +1002,15 @@ function applyHighlights(hits, params, language, analysis, readStoredDocument) {
922
1002
  fieldValue = stored?.[field];
923
1003
  }
924
1004
  if (typeof fieldValue === "string") {
925
- highlights[field] = highlightField(fieldValue, queryTokenResult.tokens, language, {
1005
+ highlights[field] = highlightField(fieldValue, queryTokens, language, {
926
1006
  preTag: params.highlight.preTag,
927
1007
  postTag: params.highlight.postTag,
928
1008
  maxSnippetLength: params.highlight.maxSnippetLength,
929
1009
  prefixToken,
930
1010
  completedToken,
931
1011
  tolerance: params.exact === true ? 0 : params.tolerance ?? 0,
932
- prefixLength: params.prefixLength ?? DEFAULT_FUZZY_PREFIX_LENGTH
1012
+ prefixLength: params.prefixLength ?? DEFAULT_FUZZY_PREFIX_LENGTH,
1013
+ partialWords: partialWords?.fields.has(field) === true ? partialWords.highlight : void 0
933
1014
  });
934
1015
  }
935
1016
  }
@@ -1439,7 +1520,7 @@ async function executeQuery(params, callerContext) {
1439
1520
  if (params.highlight) {
1440
1521
  const dropped = params.highlight.fields.some((field) => !projectionKeepsField(projection, field));
1441
1522
  const readStoredDocument = dropped ? (docId) => manager.get(docId, { kind: "full" }) : void 0;
1442
- applyHighlights(paginated, params, language, manager.analysis, readStoredDocument);
1523
+ applyHighlights(paginated, params, language, manager.analysis, manager.schema, readStoredDocument);
1443
1524
  }
1444
1525
  const elapsed = now() - startTime;
1445
1526
  return {
@@ -1557,4 +1638,4 @@ function pickDisplaySurface(surfaceOccurrences) {
1557
1638
  return best;
1558
1639
  }
1559
1640
 
1560
- export { clampLimit, dedupePinnedEntries, executeListDocuments, executePreflight, executeQuery, executeSuggest, foldGroupReducer, hitsKeptPerGroup, listBindingOf, now, queryBindingOf, resolveHybridFusion, validateBM25Params, validateDocId, validateIndexName, validatePartitionConfig, validatePatternValueLimit, validateWorkerConfig };
1641
+ export { clampLimit, dedupePinnedEntries, executeListDocuments, executePreflight, executeQuery, executeSuggest, foldGroupReducer, hitsKeptPerGroup, listBindingOf, now, queryBindingOf, requireSurfaceFormsForPartialFields, resolveHybridFusion, validateBM25Params, validateDocId, validateIndexName, validatePartitionConfig, validatePatternValueLimit, validateWorkerConfig };