cry-search 1.0.7 → 1.0.8

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 (57) hide show
  1. package/CLAUDE.md +73 -98
  2. package/README.md +39 -28
  3. package/UNIVERSE.md +11 -18
  4. package/dist/common/SearchUniverse.d.ts.map +1 -1
  5. package/dist/common/numeric/AugmentedMetadata.d.ts +27 -92
  6. package/dist/common/numeric/AugmentedMetadata.d.ts.map +1 -1
  7. package/dist/common/numeric/createSearchArrayMetadata.d.ts +47 -7
  8. package/dist/common/numeric/createSearchArrayMetadata.d.ts.map +1 -1
  9. package/dist/common/numeric/findInLinkedArrays.d.ts +7 -4
  10. package/dist/common/numeric/findInLinkedArrays.d.ts.map +1 -1
  11. package/dist/common/numeric/scoring.d.ts +95 -0
  12. package/dist/common/numeric/scoring.d.ts.map +1 -0
  13. package/dist/common/numeric/searchAndRank.d.ts +18 -60
  14. package/dist/common/numeric/searchAndRank.d.ts.map +1 -1
  15. package/dist/common/numeric/searchInData.d.ts +17 -9
  16. package/dist/common/numeric/searchInData.d.ts.map +1 -1
  17. package/dist/common/numeric/syncSearchArrayMetadata.d.ts +7 -50
  18. package/dist/common/numeric/syncSearchArrayMetadata.d.ts.map +1 -1
  19. package/dist/common/numeric/updateSearchLinkedMetadata.d.ts +11 -110
  20. package/dist/common/numeric/updateSearchLinkedMetadata.d.ts.map +1 -1
  21. package/dist/common/numeric/updateSearchMetadata.d.ts.map +1 -1
  22. package/dist/index.cjs +614 -360
  23. package/dist/index.d.cts +3 -4
  24. package/dist/index.d.ts +3 -4
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +614 -360
  27. package/dist/types/index.d.ts +35 -50
  28. package/dist/types/index.d.ts.map +1 -1
  29. package/dist/utils/matchTokenNumeric.d.ts.map +1 -1
  30. package/dist/utils/prepareStringForSearchNumeric.d.ts +24 -29
  31. package/dist/utils/prepareStringForSearchNumeric.d.ts.map +1 -1
  32. package/package.json +4 -14
  33. package/dist/common/findInArray.d.ts +0 -37
  34. package/dist/common/findInArray.d.ts.map +0 -1
  35. package/dist/common/findInArrayReturnDataAndMeta.d.ts +0 -52
  36. package/dist/common/findInArrayReturnDataAndMeta.d.ts.map +0 -1
  37. package/dist/common/findInLinkedArrays.d.ts +0 -66
  38. package/dist/common/findInLinkedArrays.d.ts.map +0 -1
  39. package/dist/common/string/createSearchArrayMetadata.d.ts +0 -117
  40. package/dist/common/string/createSearchArrayMetadata.d.ts.map +0 -1
  41. package/dist/common/string/createSearchLinkedMetadata.d.ts +0 -36
  42. package/dist/common/string/createSearchLinkedMetadata.d.ts.map +0 -1
  43. package/dist/common/string/index.d.ts +0 -10
  44. package/dist/common/string/index.d.ts.map +0 -1
  45. package/dist/common/string/updateSearchMetadata.d.ts +0 -103
  46. package/dist/common/string/updateSearchMetadata.d.ts.map +0 -1
  47. package/dist/common/syncSearchArrayMetadata.d.ts +0 -68
  48. package/dist/common/syncSearchArrayMetadata.d.ts.map +0 -1
  49. package/dist/common/updateSearchLinkedMetadata.d.ts +0 -139
  50. package/dist/common/updateSearchLinkedMetadata.d.ts.map +0 -1
  51. package/dist/string.cjs +0 -930
  52. package/dist/string.d.cts +0 -26
  53. package/dist/string.d.ts +0 -26
  54. package/dist/string.d.ts.map +0 -1
  55. package/dist/string.js +0 -898
  56. package/dist/utils/matchToken.d.ts +0 -65
  57. package/dist/utils/matchToken.d.ts.map +0 -1
@@ -1,4 +1,27 @@
1
- import type { MatchMode, NumericSearchMetadata, NumericTokenSortedList, SearchableObject, SearchableData, SearchableObjectSpec } from '../../types';
1
+ import type { MatchMode, NumericSearchMetadata, NumericTokenSortedList, NumericTokenUnsortedList, SearchableObject, SearchableData, SearchableObjectSpec } from '../../types';
2
+ /**
3
+ * Checks if an object is deleted or blocked and should be excluded from search.
4
+ *
5
+ * @param obj - The searchable object to check
6
+ * @returns True if the object has _deleted or _blocked set
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * isDeletedOrBlocked({ _id: '1', name: 'Test' }) // false
11
+ * isDeletedOrBlocked({ _id: '1', name: 'Test', _deleted: new Date() }) // true
12
+ * ```
13
+ */
14
+ export declare function isDeletedOrBlocked(obj: SearchableObject): boolean;
15
+ /**
16
+ * Prefix characters for per-field match modes (used in {@link SearchableObjectSpec.fieldMatchModes}).
17
+ * Tokens from designated fields are stored with these prefixes so they match using the specified mode.
18
+ */
19
+ export declare const MATCH_MODE_PREFIXES: Record<MatchMode, string>;
20
+ /**
21
+ * Reverse mapping from query prefix to match mode.
22
+ * Used to parse user query strings like `=word`, `!word`, `?word`, `<word`, `>word`, `+word`, `*word`.
23
+ */
24
+ export declare const PREFIX_TO_MATCH_MODE: Record<string, MatchMode>;
2
25
  /**
3
26
  * Prefix characters for per-field match modes.
4
27
  * Note: With numeric tokens, prefixes are encoded differently.
@@ -27,14 +50,29 @@ export declare function decodeTokenId(encoded: number): number;
27
50
  */
28
51
  export declare function decodeMatchMode(encoded: number): MatchMode;
29
52
  /**
30
- * Prepares an object for search, returning numeric token IDs.
53
+ * Per-item result of {@link prepareObjectForSearchNumeric}.
54
+ *
55
+ * - `sorted`: deduplicated, ASC-sorted token IDs (with per-field mode bits) for retrieval.
56
+ * - `firstN`: first N tokens of `spec.keyFields` content in source order — for
57
+ * positional ranking. `undefined` when `keyFields` is not declared or yields no tokens.
58
+ */
59
+ export interface PreparedObjectTokens {
60
+ sorted: NumericTokenSortedList;
61
+ firstN: NumericTokenUnsortedList | undefined;
62
+ }
63
+ /**
64
+ * Prepares an object for search, returning numeric token IDs for both retrieval and ranking.
65
+ *
66
+ * Two parallel outputs:
67
+ * - `sorted`: full sorted union of tokens from `searchInFields` (or all fields).
68
+ * Per-field match modes are encoded in the high bits of each token ID.
69
+ * - `firstN`: tokens from `keyFields` (in declared order, concatenated), tokenized
70
+ * without sort, capped to `spec.firstTokensN` (default 8). Used by
71
+ * positional ranking. `undefined` when `keyFields` is not set.
31
72
  *
32
- * @param obj - The searchable object to prepare
33
- * @param spec - Optional specification for extraction and match modes
34
- * @param tokensMap - Map for string->number conversion
35
- * @returns undefined if object is _deleted or _blocked, otherwise sorted Uint32Array
73
+ * Returns `undefined` for `_deleted` / `_blocked` items.
36
74
  */
37
- export declare function prepareObjectForSearchNumeric<T extends SearchableObject, C = unknown>(obj: T, spec: SearchableObjectSpec<T, C> | undefined, tokensMap: Map<string, number>): NumericTokenSortedList | undefined;
75
+ export declare function prepareObjectForSearchNumeric<T extends SearchableObject, C = unknown>(obj: T, spec: SearchableObjectSpec<T, C> | undefined, tokensMap: Map<string, number>): PreparedObjectTokens | undefined;
38
76
  /**
39
77
  * Creates numeric search metadata for a collection of items.
40
78
  *
@@ -62,4 +100,6 @@ export declare function prepareObjectForSearchNumeric<T extends SearchableObject
62
100
  * ```
63
101
  */
64
102
  export declare function createSearchArrayMetadataNumeric<T extends SearchableObject, C = unknown>(data: SearchableData<T>, spec?: SearchableObjectSpec<T, C>): NumericSearchMetadata;
103
+ /** Constructs an empty {@link NumericSearchMetadata}. */
104
+ export declare function emptyNumericSearchMetadata(): NumericSearchMetadata;
65
105
  //# sourceMappingURL=createSearchArrayMetadata.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createSearchArrayMetadata.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/createSearchArrayMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,qBAAqB,EACrB,sBAAsB,EACtB,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACrB,MAAM,aAAa,CAAC;AASrB;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAMrD,CAAC;AAKF,mDAAmD;AACnD,eAAO,MAAM,aAAa,QAAwB,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAS1D;AAoED;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,CAAC,SAAS,gBAAgB,EAAE,CAAC,GAAG,OAAO,EACnF,GAAG,EAAE,CAAC,EACN,IAAI,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,EAC5C,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,sBAAsB,GAAG,SAAS,CAgBpC;AA8DD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,gCAAgC,CAAC,CAAC,SAAS,gBAAgB,EAAE,CAAC,GAAG,OAAO,EACtF,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EACvB,IAAI,CAAC,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAChC,qBAAqB,CAmBvB"}
1
+ {"version":3,"file":"createSearchArrayMetadata.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/createSearchArrayMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACrB,MAAM,aAAa,CAAC;AASrB;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAEjE;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAMzD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAS1D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAMrD,CAAC;AAKF,mDAAmD;AACnD,eAAO,MAAM,aAAa,QAAwB,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAS1D;AAoED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,sBAAsB,CAAC;IAC/B,MAAM,EAAE,wBAAwB,GAAG,SAAS,CAAC;CAC9C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,6BAA6B,CAAC,CAAC,SAAS,gBAAgB,EAAE,CAAC,GAAG,OAAO,EACnF,GAAG,EAAE,CAAC,EACN,IAAI,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,EAC5C,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,oBAAoB,GAAG,SAAS,CAoBlC;AA6GD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,gCAAgC,CAAC,CAAC,SAAS,gBAAgB,EAAE,CAAC,GAAG,OAAO,EACtF,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EACvB,IAAI,CAAC,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAChC,qBAAqB,CAoBvB;AAED,yDAAyD;AACzD,wBAAgB,0BAA0B,IAAI,qBAAqB,CAElE"}
@@ -1,12 +1,17 @@
1
1
  import type { SearchableObject, SearchOpts, LinkedSearchResult, LinkedSearchResultWithMeta } from '../../types';
2
2
  import type { NumericLinkedSearchMetadataWithData } from './createSearchLinkedMetadata';
3
3
  /**
4
- * Searches across linked data sets using numeric tokens.
4
+ * Searches across linked data sets using numeric tokens, ranked by positional relevance.
5
5
  *
6
- * For each primary item, collects all tokens from the primary and all its linked items,
6
+ * For each primary item, collects all tokens from the primary and its linked items,
7
7
  * then matches query tokens against this combined pool. Returns primary items with
8
8
  * only the linked items that contributed to the match.
9
9
  *
10
+ * **Ranking:** results are sorted by positional score (using `metadata.unsorted`
11
+ * of primary + matched linked items, in source order). Items with `keyFields`
12
+ * declared at build time get accurate positional scoring; items without retain
13
+ * primary insertion order via the deterministic tiebreaker.
14
+ *
10
15
  * **Key behaviors:**
11
16
  * - Tokens that match in the primary are excluded from linked matching (prevents
12
17
  * foreign key redundancy)
@@ -25,8 +30,6 @@ import type { NumericLinkedSearchMetadataWithData } from './createSearchLinkedMe
25
30
  export declare function findInLinkedArraysNumeric<TPrimary extends SearchableObject, TLinked extends SearchableObject>(query: string, linked: NumericLinkedSearchMetadataWithData<TPrimary, TLinked>, limit?: number, opts?: SearchOpts): LinkedSearchResultWithMeta<TPrimary, TLinked>;
26
31
  /**
27
32
  * Simplified version of {@link findInLinkedArraysNumeric} that returns just the results.
28
- *
29
- * Use this when you don't need the query tokens metadata.
30
33
  */
31
34
  export declare function findInLinkedArraysSimpleNumeric<TPrimary extends SearchableObject, TLinked extends SearchableObject>(query: string, linked: NumericLinkedSearchMetadataWithData<TPrimary, TLinked>, limit?: number, opts?: SearchOpts): LinkedSearchResult<TPrimary, TLinked>[];
32
35
  //# sourceMappingURL=findInLinkedArrays.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"findInLinkedArrays.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/findInLinkedArrays.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,0BAA0B,EAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,8BAA8B,CAAC;AAQxF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAEhC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAC9D,KAAK,GAAE,MAAW,EAClB,IAAI,CAAC,EAAE,UAAU,GAChB,0BAA0B,CAAC,QAAQ,EAAE,OAAO,CAAC,CAyJ/C;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAEhC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAC9D,KAAK,GAAE,MAAW,EAClB,IAAI,CAAC,EAAE,UAAU,GAChB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAEzC"}
1
+ {"version":3,"file":"findInLinkedArrays.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/findInLinkedArrays.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,0BAA0B,EAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,8BAA8B,CAAC;AAUxF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAEhC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAC9D,KAAK,GAAE,MAAW,EAClB,IAAI,CAAC,EAAE,UAAU,GAChB,0BAA0B,CAAC,QAAQ,EAAE,OAAO,CAAC,CA6K/C;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAEhC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAC9D,KAAK,GAAE,MAAW,EAClB,IAAI,CAAC,EAAE,UAAU,GAChB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAEzC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Tokenize a string preserving source token order (no alphabetic sort).
3
+ *
4
+ * Mirrors `prepareStringForSearch` but skips the trailing `.sort()` —
5
+ * required for positional / order-aware scoring.
6
+ *
7
+ * NOTE: do NOT pass the result to retrieval functions (`searchInData...`); those
8
+ * assume sorted lists for efficient AND-match.
9
+ */
10
+ export declare function orderedTokenize(input: string): string[];
11
+ /**
12
+ * Compute relevance score against a query using positional signals.
13
+ *
14
+ * Scoring components (additive):
15
+ * - **+100_000** if raw `query` equals any `exactKeys` value.
16
+ * - **+50** base for any subsequence-prefix match in `itemTokens`.
17
+ * - **+100** if ALL query tokens match (in order).
18
+ * - **+50** if first matched position is 0 (itemTokens starts with first query token).
19
+ * - **+80** if matched positions form a contiguous prefix `[0..k-1]` (perfect prefix).
20
+ * - **+30 * (matchedCount / span)** density bonus.
21
+ * - **-0.1 * itemTokensJoinedLen** length penalty (weak tiebreaker).
22
+ *
23
+ * Returns **1** if no query token matched (e.g. item is in the candidate set
24
+ * only via a secondary field). Returns **0** for empty query.
25
+ *
26
+ * @param query - Raw query string (used only for exact-key match)
27
+ * @param qTokens - Query tokens in source order (from {@link orderedTokenize})
28
+ * @param itemTokens - Item tokens in source order
29
+ * @param exactKeys - Optional values for the +100_000 exact-match boost
30
+ */
31
+ export declare function scoreOne(query: string, qTokens: string[], itemTokens: string[], exactKeys?: readonly string[] | undefined): number;
32
+ /**
33
+ * Order-agnostic scoring: each query token that exists anywhere in `itemTokens`
34
+ * contributes `perTokenWeight`. Source order of either side is ignored.
35
+ *
36
+ * Use for fields where token order is conventional but not semantic — typically
37
+ * **person names** ("Janez Novak" === "Novak Janez"), tag lists, or pet breeds.
38
+ *
39
+ * Each query token contributes at most once, and each item token can be consumed
40
+ * by at most one query token (greedy left-to-right matching).
41
+ *
42
+ * Examples (default `perTokenWeight = 30`):
43
+ * - `query=[janez, novak]`, `item=[janez, novak]` → **60**
44
+ * - `query=[novak, janez]`, `item=[janez, novak]` → **60** ← key invariant
45
+ * - `query=[janez, novak]`, `item=[novak, janez]` → **60**
46
+ * - `query=[janez, krajnik]`, `item=[janez, novak]` → 30 (only "janez" matches)
47
+ *
48
+ * Compare with order-sensitive {@link scoreOrderAndPresence}, which would give
49
+ * the reversed case (60 vs 40) different scores.
50
+ *
51
+ * @param qTokens - Query tokens
52
+ * @param itemTokens - Item tokens
53
+ * @param perTokenWeight - Bonus per matched query token (default 30)
54
+ */
55
+ export declare function scoreBag(qTokens: string[], itemTokens: string[], perTokenWeight?: number): number;
56
+ /**
57
+ * Per-token bonus weights for {@link scoreOrderAndPresence}.
58
+ *
59
+ * `ordered` should be larger than `presence` — in-order matches are stronger
60
+ * signals than out-of-order presence.
61
+ */
62
+ export interface OrderAndPresenceWeights {
63
+ /** Bonus per query token that matches in subsequence-prefix order. @default 30 */
64
+ ordered?: number;
65
+ /** Bonus per query token that exists somewhere in `itemTokens` but not in order. @default 10 */
66
+ presence?: number;
67
+ }
68
+ /**
69
+ * Compute an additive bonus signal from `metadata.unsorted` ordered tokens.
70
+ *
71
+ * Designed to be ADDED to a base score (e.g. `scoreOne` result). Distinguishes
72
+ * three cases per query token:
73
+ * 1. **Ordered match** — query token appears in `itemTokens` at a position
74
+ * consistent with the previous matches (subsequence-prefix in source order)
75
+ * → adds `weights.ordered` (default 30).
76
+ * 2. **Presence-only** — query token appears somewhere in `itemTokens` but
77
+ * breaks the source order → adds `weights.presence` (default 10).
78
+ * 3. **Absent** — no match in `itemTokens` → adds 0.
79
+ *
80
+ * Each query token contributes **at most once** (no double-counting): a token
81
+ * matched in phase 1 cannot also earn the presence bonus.
82
+ *
83
+ * Examples (defaults: ordered=30, presence=10):
84
+ * - `query=[izdaja, recepta]`, `item=[izdaja, recepta]` → 60 (both in order)
85
+ * - `query=[izdaja, recepta]`, `item=[izdaja]` → 30 (one in order, second absent)
86
+ * - `query=[izdaja, recepta]`, `item=[recepta, izdaja]` → 40 (first ordered + second presence)
87
+ *
88
+ * @param qTokens - Query tokens in source order (from {@link orderedTokenize})
89
+ * @param itemTokens - Item tokens in source order (typically from
90
+ * `metadata.unsorted` via `tokens[id]` lookup)
91
+ * @param weights - Optional weight overrides
92
+ * @returns Additive bonus, ≥ 0
93
+ */
94
+ export declare function scoreOrderAndPresence(qTokens: string[], itemTokens: string[], weights?: OrderAndPresenceWeights): number;
95
+ //# sourceMappingURL=scoring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoring.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/scoring.ts"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAKvD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,EAAE,MAAM,EAAE,EACpB,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACxC,MAAM,CAyCR;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,EAAE,MAAM,EAAE,EACpB,cAAc,SAAK,GAClB,MAAM,CAgBR;AAED;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gGAAgG;IAChG,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,CAAC,EAAE,uBAAuB,GAChC,MAAM,CAkCR"}
@@ -1,90 +1,48 @@
1
1
  import type { Id, NumericSearchMetadata, SearchableData, SearchableObject, SearchOpts } from "../../types";
2
- /**
3
- * Tokenizes a string preserving source order (no alphabetic sort).
4
- *
5
- * Mirrors {@link prepareStringForSearch} pipeline minus the trailing `.sort()`,
6
- * which is required for any positional / order-aware scoring.
7
- *
8
- * NOTE: do NOT use these tokens for cry-search candidate retrieval; those APIs
9
- * assume sorted lists for efficient binary search.
10
- */
11
- export declare function orderedTokenize(input: string): string[];
2
+ export { scoreOne, orderedTokenize, scoreOrderAndPresence, scoreBag } from "./scoring";
3
+ export type { OrderAndPresenceWeights } from "./scoring";
12
4
  /**
13
5
  * Result of a scored / ranked search.
14
6
  */
15
7
  export interface ScoredResult<T extends SearchableObject> {
16
- /** Item id. */
17
8
  id: Id;
18
- /** The matched item. */
19
9
  item: T;
20
10
  /** Relevance score (higher = better). 100_000 for exact-key match. */
21
11
  score: number;
22
12
  }
23
13
  /**
24
- * Options controlling {@link searchAndRank} scoring and retrieval.
14
+ * Options controlling {@link searchAndRankNumeric} scoring and retrieval.
25
15
  */
26
16
  export interface SearchAndRankOptions<T extends SearchableObject> {
27
17
  /**
28
- * Extracts the primary display text used for positional scoring.
29
- * Typically the human-readable label (`item => item.naziv`).
18
+ * Extracts the primary display text for an item. Used as **fallback** when
19
+ * `metadata.unsorted` has no entry for this id (i.e. spec didn't declare
20
+ * `keyFields`), and for locale-aware tiebreaker sorting.
30
21
  */
31
22
  primaryTextFn: (item: T) => string | undefined;
32
23
  /**
33
- * Optional: extracts values that must match the raw query string exactly
34
- * for a top-priority boost (e.g. crtnaKoda for invoice items).
35
- * Returns score 100_000 on exact equality.
24
+ * Optional: extracts values that must equal the raw query string for the
25
+ * top-priority +100_000 exact-key boost (e.g. crtnaKoda / barcode).
36
26
  */
37
27
  exactKeysFn?: (item: T) => readonly string[] | undefined;
38
- /** Maximum number of ranked results to return. Default: Infinity. */
28
+ /** Maximum number of ranked results returned. Default: Infinity. */
39
29
  limit?: number;
40
30
  /** Underlying search options passed to candidate retrieval. */
41
31
  opts?: SearchOpts;
42
32
  }
43
33
  /**
44
- * Computes a relevance score for one item against a query.
45
- *
46
- * Scoring components (additive):
47
- * - **+100_000** if the raw `query` equals any `exactKeys` value (e.g. crtnaKoda).
48
- * - **+50** base for any subsequence-prefix match of query tokens in primary text.
49
- * - **+100** if ALL query tokens match (in order) in primary text.
50
- * - **+50** if first matched position is 0 (primary text starts with first query token).
51
- * - **+80** if matched positions form a contiguous prefix `[0..k-1]` (perfect prefix).
52
- * - **+30 * (matchedCount / span)** density bonus (rewards contiguous matches).
53
- * - **-0.1 * primaryText.length** length penalty (weak tiebreaker — shorter wins).
54
- *
55
- * Returns **1** if the item was retrieved as a candidate but its primary text
56
- * contains no query token (match came from a secondary field).
57
- *
58
- * Returns **0** if the query is empty.
59
- */
60
- export declare function scoreOne<T extends SearchableObject>(item: T, query: string, qTokens: string[], primaryTextFn: (item: T) => string | undefined, exactKeys?: readonly string[] | undefined): number;
61
- /**
62
- * Searches with positional relevance scoring and returns ranked results.
63
- *
64
- * Combines candidate retrieval ({@link searchInDataReturnIdsNumeric}, sorted-token
65
- * AND-match) with a positional scoring layer that rewards in-order matches,
66
- * first-word matches, perfect prefixes, dense (contiguous) matches, and shorter
67
- * primary text.
34
+ * Search with positional relevance scoring and return ranked results.
68
35
  *
69
- * Results are sorted by score descending, with a stable tiebreaker on
70
- * locale-aware primary-text comparison.
36
+ * Combines candidate retrieval ({@link searchInDataReturnIdsNumeric}, AND-match
37
+ * over sorted token lists) with positional scoring per candidate. For best
38
+ * performance, declare `spec.keyFields` so item tokens are pre-stored in
39
+ * `metadata.unsorted` and `searchAndRank` avoids re-tokenizing at query time.
71
40
  *
72
- * @typeParam T - Item type (must extend SearchableObject)
73
- * @param query - Raw query string (tokenized internally)
74
- * @param data - SearchableData built via {@link arrayToSearchableData}
75
- * @param metadata - NumericSearchMetadata built via {@link createSearchArrayMetadata}
76
- * @param options - Scoring + retrieval options
77
- * @returns Array of `{ id, item, score }` ordered by score descending
41
+ * When `metadata.unsorted` has no entry for an id (i.e. `keyFields` not
42
+ * declared at build time), this function falls back to `orderedTokenize(
43
+ * primaryTextFn(item))` — same behavior as before the `keyFields` optimization.
78
44
  *
79
- * @example
80
- * ```typescript
81
- * const results = searchAndRank("pot mat", data, meta, {
82
- * primaryTextFn: (a) => a.naziv,
83
- * exactKeysFn: (a) => a.crtneKode,
84
- * limit: 20,
85
- * });
86
- * // results[0].item.naziv === "POTROŠNI MATERIAL"
87
- * ```
45
+ * Sort: score DESC, locale-aware `primaryTextFn(item)` ASC as tiebreaker.
88
46
  */
89
47
  export declare function searchAndRankNumeric<T extends SearchableObject>(query: string, data: SearchableData<T>, metadata: NumericSearchMetadata, options: SearchAndRankOptions<T>): ScoredResult<T>[];
90
48
  //# sourceMappingURL=searchAndRank.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"searchAndRank.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/searchAndRank.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,EAAE,EACF,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,UAAU,EACX,MAAM,aAAa,CAAC;AAOrB;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAKvD;AACD;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,gBAAgB;IACtD,eAAe;IACf,EAAE,EAAE,EAAE,CAAC;IACP,wBAAwB;IACxB,IAAI,EAAE,CAAC,CAAC;IACR,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS,gBAAgB;IAC9D;;;OAGG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;IAC/C;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACzD,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AACD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,gBAAgB,EACjD,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EAAE,EACjB,aAAa,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,EAC9C,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACxC,MAAM,CAyCR;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,gBAAgB,EAC7D,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EACvB,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAC/B,YAAY,CAAC,CAAC,CAAC,EAAE,CA0BnB"}
1
+ {"version":3,"file":"searchAndRank.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/searchAndRank.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,EAAE,EACF,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,UAAU,EACX,MAAM,aAAa,CAAC;AAMrB,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACvF,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAgBzD;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,gBAAgB;IACtD,EAAE,EAAE,EAAE,CAAC;IACP,IAAI,EAAE,CAAC,CAAC;IACR,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS,gBAAgB;IAC9D;;;;OAIG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;IAC/C;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACzD,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,gBAAgB,EAC7D,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EACvB,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAC/B,YAAY,CAAC,CAAC,CAAC,EAAE,CAiCnB"}
@@ -2,30 +2,38 @@ import type { Id, NumericSearchMetadata, SearchableData, SearchableObject, Searc
2
2
  /**
3
3
  * Searches in numeric metadata and returns matching IDs.
4
4
  *
5
+ * Results are RANKED by positional relevance when `spec.keyFields` is declared
6
+ * for the source data: items whose `metadata.unsorted` carries pre-ordered key
7
+ * tokens get scored via `scoreOne`. Items without an `unsorted` entry land at
8
+ * the bottom (score 0) in original insertion order.
9
+ *
5
10
  * @param query - The search query string
6
11
  * @param metadata - The NumericSearchMetadata to search in
7
12
  * @param opts - Optional search options for match mode
8
- * @returns Array of matching object IDs
13
+ * @returns Array of matching object IDs sorted by relevance DESC
9
14
  */
10
15
  export declare function searchInDataReturnIdsNumeric(query: string, metadata: NumericSearchMetadata, opts?: SearchOpts): Id[];
11
16
  /**
12
- * Searches in numeric metadata and returns matching objects.
17
+ * Searches in numeric metadata and returns matching objects, ranked.
13
18
  *
14
19
  * @param query - The search query string
15
20
  * @param metadata - The NumericSearchMetadata to search in
16
21
  * @param data - The SearchableData map for object lookup
17
22
  * @param opts - Optional search options for match mode
18
- * @returns Map of matching objects by ID
23
+ * @returns Map of matching objects by ID. Iteration order = relevance DESC.
19
24
  */
20
25
  export declare function searchInDataReturnObjectsNumeric<T extends SearchableObject>(query: string, metadata: NumericSearchMetadata, data: SearchableData<T>, opts?: SearchOpts): Map<Id, T>;
21
26
  /**
22
- * Searches with a limit and returns matching IDs.
27
+ * Searches with a limit and returns matching IDs, RANKED by positional relevance.
23
28
  *
24
- * @param query - The search query string
25
- * @param metadata - The NumericSearchMetadata to search in
26
- * @param limit - Maximum number of results to return
27
- * @param opts - Optional search options for match mode
28
- * @returns Array of matching object IDs (up to limit)
29
+ * Retrieval: AND-match of query tokens against each item's `metadata.sorted` —
30
+ * same as before. Result order changes: candidates are scored using
31
+ * `metadata.unsorted` (if present) and sorted by score DESC before `limit` is
32
+ * applied. Items without `unsorted` entries fall back to score 0 and retain
33
+ * insertion order among themselves.
34
+ *
35
+ * To preserve raw insertion order (no ranking), use a metadata built without
36
+ * `spec.keyFields` — items will all score 0 and remain in iteration order.
29
37
  */
30
38
  export declare function searchInDataReturnIdsWithLimitNumeric(query: string, metadata: NumericSearchMetadata, limit: number, opts?: SearchOpts): Id[];
31
39
  //# sourceMappingURL=searchInData.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"searchInData.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/searchInData.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,EAAE,EACF,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,UAAU,EACX,MAAM,aAAa,CAAC;AAIrB;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,qBAAqB,EAC/B,IAAI,CAAC,EAAE,UAAU,GAChB,EAAE,EAAE,CAEN;AAED;;;;;;;;GAQG;AACH,wBAAgB,gCAAgC,CAAC,CAAC,SAAS,gBAAgB,EACzE,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,qBAAqB,EAC/B,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EACvB,IAAI,CAAC,EAAE,UAAU,GAChB,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAYZ;AAED;;;;;;;;GAQG;AACH,wBAAgB,qCAAqC,CACnD,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,qBAAqB,EAC/B,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,UAAU,GAChB,EAAE,EAAE,CAsBN"}
1
+ {"version":3,"file":"searchInData.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/searchInData.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,EAAE,EACF,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,UAAU,EACX,MAAM,aAAa,CAAC;AAMrB;;;;;;;;;;;;GAYG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,qBAAqB,EAC/B,IAAI,CAAC,EAAE,UAAU,GAChB,EAAE,EAAE,CAEN;AAED;;;;;;;;GAQG;AACH,wBAAgB,gCAAgC,CAAC,CAAC,SAAS,gBAAgB,EACzE,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,qBAAqB,EAC/B,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EACvB,IAAI,CAAC,EAAE,UAAU,GAChB,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAYZ;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qCAAqC,CACnD,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,qBAAqB,EAC/B,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,UAAU,GAChB,EAAE,EAAE,CAiDN"}
@@ -3,62 +3,19 @@ export type { SyncResult, SyncOptions } from '../../types/index.js';
3
3
  /**
4
4
  * Syncs numeric search metadata with new data.
5
5
  *
6
- * This function performs a full sync of metadata against the provided data:
7
- * - Adds metadata for new items
8
- * - Removes metadata for items no longer in data (or marked `_deleted`/`_blocked`)
9
- * - Updates metadata for items whose tokens have changed
6
+ * Iterates `metadata.sorted.keys()` to find items absent from `newData` (removals).
7
+ * Then walks `newData`, tokenizing each item and updating metadata only when the
8
+ * resulting `sorted` or `firstN` differ from existing entries.
10
9
  *
11
- * Use this when you have completely new data to sync with. If you have both
12
- * previous and new data available, use {@link syncSearchArrayMetadataNumericWithPrevious}
13
- * for more efficient diffing.
14
- *
15
- * @typeParam T - Type of the searchable objects
16
- * @typeParam C - Type of the search context
17
- *
18
- * @param metadata - The NumericSearchMetadata map to update (mutated in place)
19
- * @param newData - The new data to sync with
20
- * @param spec - Optional specification for how to extract searchable text
21
- * @returns SyncResult with counts and IDs of added/updated/removed items
22
- *
23
- * @example
24
- * ```typescript
25
- * const newProducts = arrayToSearchableData(freshProductsFromServer);
26
- * const result = syncSearchArrayMetadataNumeric(metadata, newProducts, spec);
27
- *
28
- * console.log(`Added: ${result.added}, Updated: ${result.updated}, Removed: ${result.removed}`);
29
- * ```
10
+ * Use {@link syncSearchArrayMetadataNumericWithPrevious} when both previous and new
11
+ * datasets are on hand — it skips the `metadata.sorted.keys()` scan.
30
12
  */
31
13
  export declare function syncSearchArrayMetadataNumeric<T extends SearchableObject, C = unknown>(metadata: NumericSearchMetadata, newData: SearchableData<T>, spec?: SearchableObjectSpec<T, C>): SyncResult;
32
14
  /**
33
15
  * Syncs numeric search metadata using previous and new data for efficient diffing.
34
16
  *
35
- * More efficient than {@link syncSearchArrayMetadataNumeric} when you have both the
36
- * previous and new data available. Uses the previous data to determine
37
- * what was removed without iterating through all metadata keys.
38
- *
39
- * @typeParam T - Type of the searchable objects
40
- * @typeParam C - Type of the search context
41
- *
42
- * @param metadata - The NumericSearchMetadata map to update (mutated in place)
43
- * @param previousData - The previous data (used to determine what was removed)
44
- * @param newData - The new data to sync with
45
- * @param options - Optional sync options (e.g., skipUpdateCheck)
46
- * @param spec - Optional specification for how to extract searchable text
47
- * @returns SyncResult with counts and IDs of added/updated/removed items
48
- *
49
- * @example
50
- * ```typescript
51
- * const previousProducts = currentData;
52
- * const newProducts = arrayToSearchableData(freshProductsFromServer);
53
- *
54
- * const result = syncSearchArrayMetadataNumericWithPrevious(
55
- * metadata,
56
- * previousProducts,
57
- * newProducts,
58
- * { skipUpdateCheck: false },
59
- * spec
60
- * );
61
- * ```
17
+ * Determines removals from `previousData` (no scan of metadata.sorted.keys()) and
18
+ * uses `options.skipUpdateCheck` to avoid re-tokenizing items that already existed.
62
19
  */
63
20
  export declare function syncSearchArrayMetadataNumericWithPrevious<T extends SearchableObject, C = unknown>(metadata: NumericSearchMetadata, previousData: SearchableData<T>, newData: SearchableData<T>, options?: SyncOptions, spec?: SearchableObjectSpec<T, C>): SyncResult;
64
21
  //# sourceMappingURL=syncSearchArrayMetadata.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"syncSearchArrayMetadata.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/syncSearchArrayMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EAEpB,UAAU,EACV,WAAW,EACZ,MAAM,sBAAsB,CAAA;AAK7B,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAkBnE;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,8BAA8B,CAAC,CAAC,SAAS,gBAAgB,EAAE,CAAC,GAAG,OAAO,EACpF,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAC1B,IAAI,CAAC,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAChC,UAAU,CAoDZ;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,0CAA0C,CAAC,CAAC,SAAS,gBAAgB,EAAE,CAAC,GAAG,OAAO,EAChG,QAAQ,EAAE,qBAAqB,EAC/B,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC,EAC/B,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAC1B,OAAO,CAAC,EAAE,WAAW,EACrB,IAAI,CAAC,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAChC,UAAU,CAsDZ"}
1
+ {"version":3,"file":"syncSearchArrayMetadata.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/syncSearchArrayMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EAGpB,UAAU,EACV,WAAW,EACZ,MAAM,sBAAsB,CAAA;AAK7B,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAqCnE;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAAC,CAAC,SAAS,gBAAgB,EAAE,CAAC,GAAG,OAAO,EACpF,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAC1B,IAAI,CAAC,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAChC,UAAU,CAqDZ;AAED;;;;;GAKG;AACH,wBAAgB,0CAA0C,CAAC,CAAC,SAAS,gBAAgB,EAAE,CAAC,GAAG,OAAO,EAChG,QAAQ,EAAE,qBAAqB,EAC/B,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC,EAC/B,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAC1B,OAAO,CAAC,EAAE,WAAW,EACrB,IAAI,CAAC,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAChC,UAAU,CAsDZ"}
@@ -2,129 +2,30 @@ import type { Id, SearchableData, SearchableObject, SearchableObjectSpec, Upsert
2
2
  import type { NumericLinkedSearchMetadataWithData } from './createSearchLinkedMetadata.js';
3
3
  export type { UpsertResult, SyncLinkedResult } from '../../types/index.js';
4
4
  /**
5
- * Upserts a primary item into the linked metadata (numeric version).
5
+ * Upserts a primary item into linked metadata.
6
6
  *
7
- * - If the item doesn't exist, adds it to data, metadata, and initializes primaryToLinked index
8
- * - If the item exists, updates data and metadata
9
- * - Handles `_deleted`/`_blocked` items by removing their metadata
10
- *
11
- * @typeParam TPrimary - Type of primary items
12
- * @typeParam TLinked - Type of linked items
13
- * @typeParam C - Type of the search context
14
- *
15
- * @param linked - The linked metadata to update (mutated in place)
16
- * @param item - The primary item to upsert
17
- * @param spec - Optional specification for how to extract searchable text
18
- * @returns UpsertResult indicating if item was added or updated
19
- *
20
- * @example
21
- * ```typescript
22
- * const stranka = { _id: 's1', ime: 'Janez', priimek: 'Novak' };
23
- * const result = upsertPrimaryItemNumeric(linkedMeta, stranka, spec);
24
- * // result.added === true if stranka was new
25
- * ```
7
+ * Adds or updates the primary in `primaryData`, refreshes its tokens in `primaryMeta`,
8
+ * and initializes its `primaryToLinked` entry on first insertion. Items marked
9
+ * `_deleted`/`_blocked` get their metadata cleared (kept in data for reference).
26
10
  */
27
11
  export declare function upsertPrimaryItemNumeric<TPrimary extends SearchableObject, TLinked extends SearchableObject, C = unknown>(linked: NumericLinkedSearchMetadataWithData<TPrimary, TLinked>, item: TPrimary, spec?: SearchableObjectSpec<TPrimary, C>): UpsertResult;
28
12
  /**
29
- * Removes a primary item from the linked metadata (numeric version).
30
- *
31
- * Removes the item from data, metadata, and the primaryToLinked index.
32
- * Note: This does NOT automatically remove linked items - they will become orphans.
33
- * If you want to also remove linked items, call {@link removeLinkedItemNumeric} for each.
34
- *
35
- * @typeParam TPrimary - Type of primary items
36
- * @typeParam TLinked - Type of linked items
37
- *
38
- * @param linked - The linked metadata to update (mutated in place)
39
- * @param primaryId - The ID of the primary item to remove
40
- * @returns true if item was found and removed, false if not found
13
+ * Removes a primary item entirely. Linked items become orphans (caller must
14
+ * call {@link removeLinkedItemNumeric} on each if needed).
41
15
  */
42
16
  export declare function removePrimaryItemNumeric<TPrimary extends SearchableObject, TLinked extends SearchableObject>(linked: NumericLinkedSearchMetadataWithData<TPrimary, TLinked>, primaryId: Id): boolean;
43
17
  /**
44
- * Upserts a linked item into the linked metadata (numeric version).
45
- *
46
- * - If the item doesn't exist, adds it
47
- * - If the item exists, updates it
48
- * - Handles foreign key changes by updating the primaryToLinked index
49
- * (removes from old primary's list, adds to new primary's list)
50
- * - Handles `_deleted`/`_blocked` items by removing their metadata
51
- *
52
- * @typeParam TPrimary - Type of primary items
53
- * @typeParam TLinked - Type of linked items
54
- * @typeParam C - Type of the search context
55
- *
56
- * @param linked - The linked metadata to update (mutated in place)
57
- * @param item - The linked item to upsert
58
- * @param foreignKeyGetter - Function to get the primary ID from a linked item
59
- * @param spec - Optional specification for how to extract searchable text
60
- * @returns UpsertResult indicating if item was added or updated, and previous primary ID if FK changed
61
- *
62
- * @example
63
- * ```typescript
64
- * const pacient = { _id: 'p1', ime: 'Rex', stranka_id: 's1' };
65
- * const result = upsertLinkedItemNumeric(linkedMeta, pacient, (p) => p.stranka_id, spec);
66
- *
67
- * // If the pacient moved to a different stranka:
68
- * pacient.stranka_id = 's2';
69
- * const result2 = upsertLinkedItemNumeric(linkedMeta, pacient, (p) => p.stranka_id, spec);
70
- * // result2.previousPrimaryId === 's1'
71
- * ```
18
+ * Upserts a linked item; if its foreign key changed since previous state, moves
19
+ * the id in `primaryToLinked` from the old primary's bucket to the new one.
72
20
  */
73
21
  export declare function upsertLinkedItemNumeric<TPrimary extends SearchableObject, TLinked extends SearchableObject, C = unknown>(linked: NumericLinkedSearchMetadataWithData<TPrimary, TLinked>, item: TLinked, foreignKeyGetter: (item: TLinked) => Id | undefined, spec?: SearchableObjectSpec<TLinked, C>): UpsertResult;
74
22
  /**
75
- * Removes a linked item from the linked metadata (numeric version).
76
- *
77
- * Removes the item from data, metadata, and the primaryToLinked index.
78
- *
79
- * @typeParam TPrimary - Type of primary items
80
- * @typeParam TLinked - Type of linked items
81
- *
82
- * @param linked - The linked metadata to update (mutated in place)
83
- * @param linkedId - The ID of the linked item to remove
84
- * @param foreignKeyGetter - Function to get the primary ID from a linked item
85
- * @returns true if item was found and removed, false if not found
86
- *
87
- * @example
88
- * ```typescript
89
- * removeLinkedItemNumeric(linkedMeta, 'pacient-id', (p) => p.stranka_id);
90
- * ```
23
+ * Removes a linked item from data, metadata, and the parent primary's index entry.
91
24
  */
92
25
  export declare function removeLinkedItemNumeric<TPrimary extends SearchableObject, TLinked extends SearchableObject>(linked: NumericLinkedSearchMetadataWithData<TPrimary, TLinked>, linkedId: Id, foreignKeyGetter: (item: TLinked) => Id | undefined): boolean;
93
26
  /**
94
- * Syncs all linked items for a specific primary item (numeric version).
95
- *
96
- * This function performs a full sync of linked items belonging to a single primary:
97
- * - Removes linked items that are no longer in the new data
98
- * - Updates existing linked items if their tokens changed
99
- * - Adds new linked items
100
- * - Only processes items whose foreign key points to the given primary
101
- *
102
- * Use this when you have a complete new set of linked items for a primary
103
- * and want to update the metadata to match.
104
- *
105
- * @typeParam TPrimary - Type of primary items
106
- * @typeParam TLinked - Type of linked items
107
- * @typeParam C - Type of the search context
108
- *
109
- * @param linked - The linked metadata to update (mutated in place)
110
- * @param primaryId - The primary ID to sync linked items for
111
- * @param newLinkedItems - The new linked items (only items with matching FK will be processed)
112
- * @param foreignKeyGetter - Function to get the primary ID from a linked item
113
- * @param spec - Optional specification for how to extract searchable text
114
- * @returns SyncLinkedResult with counts of added/updated/removed items
115
- *
116
- * @example
117
- * ```typescript
118
- * const newPacienti = arrayToSearchableData(freshPacientiFromServer);
119
- * const result = syncLinkedItemsForPrimaryNumeric(
120
- * linkedMeta,
121
- * 'stranka-1',
122
- * newPacienti,
123
- * (p) => p.stranka_id,
124
- * spec
125
- * );
126
- * console.log(`Added: ${result.added}, Updated: ${result.updated}, Removed: ${result.removed}`);
127
- * ```
27
+ * Full sync of linked items for one primary: removes missing, updates changed,
28
+ * adds new. Only items whose foreign key equals `primaryId` are processed.
128
29
  */
129
30
  export declare function syncLinkedItemsForPrimaryNumeric<TPrimary extends SearchableObject, TLinked extends SearchableObject, C = unknown>(linked: NumericLinkedSearchMetadataWithData<TPrimary, TLinked>, primaryId: Id, newLinkedItems: SearchableData<TLinked>, foreignKeyGetter: (item: TLinked) => Id | undefined, spec?: SearchableObjectSpec<TLinked, C>): SyncLinkedResult;
130
31
  //# sourceMappingURL=updateSearchLinkedMetadata.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"updateSearchLinkedMetadata.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/updateSearchLinkedMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,EAAE,EACF,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAEjB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,iCAAiC,CAAA;AAK1F,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAkB1E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAChC,CAAC,GAAG,OAAO,EAEX,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAC9D,IAAI,EAAE,QAAQ,EACd,IAAI,CAAC,EAAE,oBAAoB,CAAC,QAAQ,EAAE,CAAC,CAAC,GACvC,YAAY,CAwBd;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAChC,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,OAAO,CAUxF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAChC,CAAC,GAAG,OAAO,EAEX,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAC9D,IAAI,EAAE,OAAO,EACb,gBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,EAAE,GAAG,SAAS,EACnD,IAAI,CAAC,EAAE,oBAAoB,CAAC,OAAO,EAAE,CAAC,CAAC,GACtC,YAAY,CA0Dd;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAEhC,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAC9D,QAAQ,EAAE,EAAE,EACZ,gBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,EAAE,GAAG,SAAS,GAClD,OAAO,CAyBT;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAChC,CAAC,GAAG,OAAO,EAEX,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAC9D,SAAS,EAAE,EAAE,EACb,cAAc,EAAE,cAAc,CAAC,OAAO,CAAC,EACvC,gBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,EAAE,GAAG,SAAS,EACnD,IAAI,CAAC,EAAE,oBAAoB,CAAC,OAAO,EAAE,CAAC,CAAC,GACtC,gBAAgB,CA8DlB"}
1
+ {"version":3,"file":"updateSearchLinkedMetadata.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/updateSearchLinkedMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,EAAE,EAEF,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAGjB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,iCAAiC,CAAA;AAK1F,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AA8C1E;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAChC,CAAC,GAAG,OAAO,EAEX,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAC9D,IAAI,EAAE,QAAQ,EACd,IAAI,CAAC,EAAE,oBAAoB,CAAC,QAAQ,EAAE,CAAC,CAAC,GACvC,YAAY,CAiBd;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAChC,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,OAAO,CAOxF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAChC,CAAC,GAAG,OAAO,EAEX,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAC9D,IAAI,EAAE,OAAO,EACb,gBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,EAAE,GAAG,SAAS,EACnD,IAAI,CAAC,EAAE,oBAAoB,CAAC,OAAO,EAAE,CAAC,CAAC,GACtC,YAAY,CAwCd;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAEhC,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAC9D,QAAQ,EAAE,EAAE,EACZ,gBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,EAAE,GAAG,SAAS,GAClD,OAAO,CAkBT;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,SAAS,gBAAgB,EACjC,OAAO,SAAS,gBAAgB,EAChC,CAAC,GAAG,OAAO,EAEX,MAAM,EAAE,mCAAmC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAC9D,SAAS,EAAE,EAAE,EACb,cAAc,EAAE,cAAc,CAAC,OAAO,CAAC,EACvC,gBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,EAAE,GAAG,SAAS,EACnD,IAAI,CAAC,EAAE,oBAAoB,CAAC,OAAO,EAAE,CAAC,CAAC,GACtC,gBAAgB,CAqDlB"}
@@ -1 +1 @@
1
- {"version":3,"file":"updateSearchMetadata.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/updateSearchMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,EAAE,EACF,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,6BAA6B,EAC9B,MAAM,aAAa,CAAC;AAIrB;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,SAAS,gBAAgB,EAAE,CAAC,GAAG,OAAO,EACjF,QAAQ,EAAE,qBAAqB,EAC/B,QAAQ,EAAE,EAAE,EACZ,GAAG,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,EACzB,IAAI,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,EAC5C,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,OAAO,CAUT;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gCAAgC,CAAC,CAAC,SAAS,gBAAgB,EAAE,CAAC,GAAG,OAAO,EACtF,QAAQ,EAAE,qBAAqB,EAC/B,KAAK,EAAE,6BAA6B,CAAC,CAAC,CAAC,EAAE,EACzC,IAAI,CAAC,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAChC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA0BtC;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,qBAAqB,EAC/B,QAAQ,EAAE,EAAE,GACX,OAAO,CAET;AAED;;;;;;GAMG;AACH,wBAAgB,oCAAoC,CAClD,QAAQ,EAAE,qBAAqB,EAC/B,SAAS,EAAE,EAAE,EAAE,GACd,MAAM,CAYR"}
1
+ {"version":3,"file":"updateSearchMetadata.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/updateSearchMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,EAAE,EACF,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,6BAA6B,EAC9B,MAAM,aAAa,CAAC;AAIrB;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,SAAS,gBAAgB,EAAE,CAAC,GAAG,OAAO,EACjF,QAAQ,EAAE,qBAAqB,EAC/B,QAAQ,EAAE,EAAE,EACZ,GAAG,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,EACzB,IAAI,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,EAC5C,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,OAAO,CAgBT;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gCAAgC,CAAC,CAAC,SAAS,gBAAgB,EAAE,CAAC,GAAG,OAAO,EACtF,QAAQ,EAAE,qBAAqB,EAC/B,KAAK,EAAE,6BAA6B,CAAC,CAAC,CAAC,EAAE,EACzC,IAAI,CAAC,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAChC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA0BtC;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,qBAAqB,EAC/B,QAAQ,EAAE,EAAE,GACX,OAAO,CAIT;AAED;;;;;;GAMG;AACH,wBAAgB,oCAAoC,CAClD,QAAQ,EAAE,qBAAqB,EAC/B,SAAS,EAAE,EAAE,EAAE,GACd,MAAM,CAYR"}