cry-search 1.0.1 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CLAUDE.md CHANGED
@@ -62,6 +62,12 @@ The numeric implementation uses a global token registry (`src/utils/tokenRegistr
62
62
  4. eg "abc 0.3x" -> "abc .3x"
63
63
  5. eg "007" -> "7"
64
64
  6. multiple periods stay as-is: "1.2.3" -> "1.2.3"
65
+ 1b. strip decimal period from pure standalone numbers (digits on both sides of period)
66
+ 1. eg "abc 11.22 x" -> "abc 1122 x"
67
+ 2. eg "abc 12,3 x" -> "abc 123 x" (after comma->period, then strip)
68
+ 3. mixed tokens with letters are NOT stripped: ".5kg" -> ".5kg", "12.3x" -> "12.3x"
69
+ 4. standalone decimals without leading digits are NOT stripped: ".3" -> ".3"
70
+ 5. multiple periods are NOT stripped: "1.2.3" -> "1.2.3"
65
71
  2. we remove spaces in pattern digits - digits
66
72
  1. eg. "12 - 25" => "12-25"
67
73
  3. we insert spaces between starting letters and digits (only at letter-to-digit boundaries)
@@ -71,8 +77,8 @@ The numeric implementation uses a global token registry (`src/utils/tokenRegistr
71
77
  3. sanitation
72
78
  1. case-insensitive
73
79
  2. diacritics-insensitive (č,ć,c -> same c)
74
- tsc 3. we only keep letters (a-z), digits (0-9), periods (.), minuses (-), tildes (~), query prefixes (<>+*!=?), spaces (" ") in search
75
- 4. other characters are replaced with space (" ")
80
+ 3. we only keep letters (`a-z`), digits (`0-9`), periods (`.`), minuses (`-`), tildes (`~`), query prefixes (`<>+*!=?`), spaces (` `) in search
81
+ 4. other characters are replaced with space (` `)
76
82
  2. tokenization
77
83
  1. we split strings on spaces
78
84
  2. then we trim all substrings
@@ -130,6 +136,32 @@ tsc 3. we only keep letters (a-z), digits (0-9), periods (.), minuses (-
130
136
  4. example use case
131
137
  1. search "krajnik angie" matches stranka "Krajnik" with pacient "Angie"
132
138
  2. returns: { primary: Stranka, secondaries: [matching Pacient], matchedIn: 'both' }
139
+ 9. augmented metadata
140
+ 1. purpose: add local/temporary searchable data to existing metadata without modifying the base metadata
141
+ 2. use case: search for items combined with page-specific data (e.g., match status, local flags, computed properties)
142
+ 3. class AugmentedMetadata
143
+ 1. wraps existing NumericSearchMetadata
144
+ 2. allows adding additional search tokens dynamically
145
+ 3. memory efficient: items without augmentation reuse original Uint32Array
146
+ 4. items with augmentation get merged sorted token array (base + augmented)
147
+ 5. constructor takes: baseMetadata, optional spec, optional initial augmented data
148
+ 6. spec controls tokenization: searchInFields, fieldMatchModes, etc.
149
+ 4. updating augmented data
150
+ 1. updateAugmented(id, obj) - single item update
151
+ 2. updateAugmentedBatch(map) - batch update (more efficient)
152
+ 3. clearAugmented(id) - remove augmentation for one item
153
+ 4. clearAllAugmented() - remove all augmentations
154
+ 5. searching
155
+ 1. implements NumericSearchMetadata interface
156
+ 2. works with all search functions (searchInDataReturnIds, etc.)
157
+ 3. combines base + augmented tokens during search
158
+ 4. supports all query prefixes and match modes
159
+ 6. example use case
160
+ 1. global zdravila metadata with names, manufacturers
161
+ 2. page-local augmented metadata adds "uparjen"/"neuparjen" status
162
+ 3. search "aspirin uparjen" finds Aspirin items with "uparjen" status
163
+ 4. updating status doesn't modify global metadata
164
+ 5. removing augmentation reverts to base metadata only
133
165
 
134
166
  ## Types
135
167
 
@@ -222,6 +254,54 @@ Override match behavior per token at search time. Priority: query prefix > field
222
254
  8. updateSearchMetadataBatch(metadata, batch, spec)
223
255
  1. creates temporary tokensMap, clears after use
224
256
  2. updates or deletes metadata for batch of objects
257
+ 9. syncSearchArrayMetadata(metadata, newData, spec?)
258
+ 1. syncs metadata with new data (inkrementalno posodabljanje)
259
+ 2. adds new items, updates changed items, removes old items
260
+ 3. compares token arrays - skips unchanged items (performance optimization)
261
+ 4. more efficient than full rebuild for partial updates
262
+ 5. uses single tokensMap for all operations (memory efficient)
263
+ 10. syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, options?, spec?)
264
+ 1. more efficient than syncSearchArrayMetadata when you have both datasets
265
+ 2. uses previousData to determine removals (no metadata.keys() iteration)
266
+ 3. skipUpdateCheck option - skip checking for updates (even faster)
267
+ 4. best for regular refresh cycles (e.g., every 30s from server)
268
+ 11. AugmentedMetadata class
269
+ 1. constructor(baseMetadata, spec?, augmentedDataMap?)
270
+ 1. baseMetadata: NumericSearchMetadata - base metadata to wrap (not modified)
271
+ 2. spec?: SearchableObjectSpec - controls tokenization of augmented objects
272
+ 3. augmentedDataMap?: Map<Id, any> - optional initial augmented data
273
+ 2. updateAugmented(id, obj) - add/update augmented data for one item
274
+ 3. updateAugmentedBatch(map) - batch update (more efficient than multiple single updates)
275
+ 4. clearAugmented(id) - remove augmentation for one item
276
+ 5. clearAllAugmented() - remove all augmentations
277
+ 6. implements NumericSearchMetadata interface (get, has, size, keys, values, entries, forEach)
278
+ 7. Map mutation methods (set, delete, clear) throw errors - use update methods instead
279
+ 12. Linked metadata update functions (incremental updates to linked metadata)
280
+ 1. upsertPrimaryItem(linked, item, spec?)
281
+ 1. adds or updates a primary item in linked metadata
282
+ 2. updates primaryData, primaryMeta, and initializes primaryToLinked index
283
+ 3. handles _deleted/_blocked by removing metadata
284
+ 4. returns { added: boolean } - true if item was new
285
+ 2. removePrimaryItem(linked, primaryId)
286
+ 1. removes primary item from data, metadata, and primaryToLinked index
287
+ 2. does NOT remove linked items (they become orphans)
288
+ 3. returns true if found and removed, false otherwise
289
+ 3. upsertLinkedItem(linked, item, foreignKeyGetter, spec?)
290
+ 1. adds or updates a linked item in linked metadata
291
+ 2. updates linkedData, linkedMeta, and primaryToLinked index
292
+ 3. handles foreign key changes (moves item between primaries)
293
+ 4. handles _deleted/_blocked by removing metadata
294
+ 5. returns { added: boolean, previousPrimaryId?: Id }
295
+ 4. removeLinkedItem(linked, linkedId, foreignKeyGetter)
296
+ 1. removes linked item from data, metadata, and primaryToLinked index
297
+ 2. returns true if found and removed, false otherwise
298
+ 5. syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKeyGetter, spec?)
299
+ 1. full sync of linked items for a single primary
300
+ 2. removes items not in newLinkedItems
301
+ 3. updates items with changed tokens
302
+ 4. adds new items
303
+ 5. only processes items whose foreign key matches primaryId
304
+ 6. returns { added: number, updated: number, removed: number }
225
305
 
226
306
  ## Token Registry Functions
227
307
 
@@ -237,15 +317,38 @@ Override match behavior per token at search time. Priority: query prefix > field
237
317
 
238
318
  ## String Implementation (Legacy)
239
319
 
240
- Available with `*String` suffix:
320
+ The string-based implementation is available as a separate entry point for backwards compatibility.
321
+
322
+ **Import from `cry-search/string`:**
323
+ ```typescript
324
+ import {
325
+ createSearchArrayMetadataString,
326
+ updateSearchMetadataString,
327
+ findInArray,
328
+ // ... other string-based functions
329
+ } from 'cry-search/string';
330
+ ```
331
+
332
+ **Available functions with `*String` suffix:**
241
333
  - createSearchArrayMetadataString
242
334
  - createSearchLinkedMetadataString
243
335
  - updateSearchMetadataString
244
336
  - updateSearchMetadataBatchString
337
+ - syncSearchArrayMetadataString
338
+ - syncSearchArrayMetadataStringWithPrevious
339
+ - upsertPrimaryItemString
340
+ - removePrimaryItemString
341
+ - upsertLinkedItemString
342
+ - removeLinkedItemString
343
+ - syncLinkedItemsForPrimaryString
245
344
  - findInArray (uses string metadata)
246
345
  - findInArrayReturnDataAndMeta
247
346
  - findInLinkedArrays
248
347
 
348
+ **Bundle sizes:**
349
+ - Main bundle (`cry-search`): ~49 KB - includes only numeric implementation
350
+ - String bundle (`cry-search/string`): ~26 KB - includes only string implementation
351
+
249
352
  ## File Structure
250
353
 
251
354
  ```
@@ -256,7 +359,10 @@ src/
256
359
  │ │ ├── createSearchArrayMetadata.ts
257
360
  │ │ ├── createSearchLinkedMetadata.ts
258
361
  │ │ ├── updateSearchMetadata.ts
259
- │ │ └── searchInData.ts
362
+ │ │ ├── updateSearchLinkedMetadata.ts
363
+ │ │ ├── searchInData.ts
364
+ │ │ ├── syncSearchArrayMetadata.ts
365
+ │ │ └── AugmentedMetadata.ts
260
366
  │ ├── string/ # Legacy string implementation
261
367
  │ │ ├── index.ts
262
368
  │ │ ├── createSearchArrayMetadata.ts
package/README.md CHANGED
@@ -7,6 +7,7 @@ A fast, memory-efficient search library for large datasets with support for toke
7
7
  - **Fast search** - Pre-built metadata enables instant queries on large datasets
8
8
  - **Memory efficient** - Numeric token storage uses ~45% less memory than string-based approaches
9
9
  - **Updatable** - Add, update, or remove items without rebuilding metadata
10
+ - **Augmented metadata** - Add local/temporary searchable data without modifying global metadata
10
11
  - **Flexible matching** - Per-field match modes and query prefixes for prefix, suffix, anywhere, exact, and negation
11
12
  - **Search prefixes** - use `-word`, `--word`, or `~word` to exclude, `..word` for suffix, `=word` for exact match
12
13
  - **Automatic normalization** - Handles diacritics, case, dates, and number formatting
@@ -22,6 +23,7 @@ A fast, memory-efficient search library for large datasets with support for toke
22
23
  - [Single Table Search](#single-table-search)
23
24
  - [SearchUniverse with Linked Collections](#searchuniverse-with-linked-collections)
24
25
  - [Updating Existing Data](#updating-existing-data)
26
+ - [Augmented Metadata - Local Search Context](#augmented-metadata---local-search-context)
25
27
  - [Architecture](#architecture)
26
28
  - [Text Processing Pipeline](#text-processing-pipeline)
27
29
  - [Metadata Building](#metadata-building)
@@ -196,6 +198,86 @@ universe.updateSearchMetadata('pacienti', 'p1', {
196
198
  });
197
199
  ```
198
200
 
201
+ ### Augmented Metadata - Local Search Context
202
+
203
+ Sometimes you need to search items combined with page-specific data (like match status, local flags, computed properties) without modifying the global metadata. `AugmentedMetadata` wraps existing metadata and allows adding temporary searchable data.
204
+
205
+ ```typescript
206
+ import {
207
+ createSearchArrayMetadata,
208
+ searchInDataReturnIds,
209
+ AugmentedMetadata,
210
+ arrayToSearchableData,
211
+ type SearchableObject,
212
+ } from 'cry-search';
213
+
214
+ interface Medicine extends SearchableObject {
215
+ _id: string;
216
+ name: string;
217
+ manufacturer: string;
218
+ }
219
+
220
+ // Global data - shared across application
221
+ const medicines: Medicine[] = [
222
+ { _id: '1', name: 'Aspirin', manufacturer: 'Bayer' },
223
+ { _id: '2', name: 'Paracetamol', manufacturer: 'Krka' },
224
+ { _id: '3', name: 'Ibuprofen', manufacturer: 'Lek' },
225
+ ];
226
+
227
+ const data = arrayToSearchableData(medicines);
228
+ const globalMetadata = createSearchArrayMetadata(data);
229
+
230
+ // Page-specific: matching medicines with external registry
231
+ // Create augmented metadata with local match status
232
+ const augmented = new AugmentedMetadata(
233
+ globalMetadata,
234
+ { searchInFields: ['status', 'notes'] } // Control which fields to index
235
+ );
236
+
237
+ // User matches medicines with external registry
238
+ augmented.updateAugmented('1', { status: 'matched', notes: 'verified' });
239
+ augmented.updateAugmented('2', { status: 'unmatched', notes: '' });
240
+ augmented.updateAugmented('3', { status: 'matching in progress', notes: 'awaiting approval' });
241
+
242
+ // Search by base data + augmented status
243
+ const matchedAspirin = searchInDataReturnIds('aspirin matched', augmented);
244
+ // Returns: ['1']
245
+
246
+ const unmatchedItems = searchInDataReturnIds('unmatched', augmented);
247
+ // Returns: ['2']
248
+
249
+ const inProgress = searchInDataReturnIds('progress', augmented);
250
+ // Returns: ['3']
251
+
252
+ // Search with negation
253
+ const notMatched = searchInDataReturnIds('bayer -matched', augmented);
254
+ // Returns: [] (Bayer Aspirin is matched)
255
+
256
+ // Batch update for efficiency
257
+ augmented.updateAugmentedBatch(new Map([
258
+ ['1', { status: 'matched', notes: 'final' }],
259
+ ['2', { status: 'matched', notes: 'approved' }],
260
+ ['3', undefined], // Remove augmentation
261
+ ]));
262
+
263
+ // Clear specific item
264
+ augmented.clearAugmented('1'); // Reverts to global metadata only
265
+
266
+ // Clear all augmentations
267
+ augmented.clearAllAugmented(); // Reset to global state
268
+
269
+ // AugmentedMetadata is memory efficient:
270
+ // - Items without augmentation reuse original Uint32Array (no memory duplication)
271
+ // - Items with augmentation get merged sorted token array (base + augmented)
272
+ // - Global metadata remains unchanged
273
+ ```
274
+
275
+ **Use cases:**
276
+ - Medicine matching with external registries (matched/unmatched status)
277
+ - Products with local pricing or availability flags
278
+ - Documents with review status or approval state
279
+ - Items with computed scores or temporary categories
280
+
199
281
  ## Architecture
200
282
 
201
283
  cry-search uses a two-phase approach: **build** metadata once, then **search** instantly.
@@ -281,16 +363,18 @@ Priority: query prefix > field match mode > global SearchOpts default.
281
363
 
282
364
  ## Legacy String Implementation
283
365
 
284
- A string-based implementation is available for backwards compatibility. Import with the `String` suffix:
366
+ A string-based implementation is available for backwards compatibility. Import from the `/string` subpath:
285
367
 
286
368
  ```typescript
287
369
  import {
288
370
  createSearchArrayMetadataString,
289
371
  updateSearchMetadataString,
290
372
  findInArray, // String-based search function
291
- } from 'cry-search';
373
+ } from 'cry-search/string';
292
374
  ```
293
375
 
376
+ The string implementation is excluded from the main bundle. The default import (`cry-search`) only includes the modern numeric implementation, keeping bundle sizes smaller.
377
+
294
378
  ## Specification
295
379
 
296
380
  See [CLAUDE.md](./CLAUDE.md) for the complete technical specification including:
@@ -0,0 +1,111 @@
1
+ import type { Id, NumericSearchMetadata, NumericTokenSortedList, SearchableObjectSpec } from '../../types/index.js';
2
+ /**
3
+ * AugmentedMetadata wraps existing NumericSearchMetadata and allows adding
4
+ * additional search tokens dynamically without modifying the base metadata.
5
+ *
6
+ * Use case: Add local/temporary data (e.g., "uparjen"/"neuparjen" status) to
7
+ * existing global metadata for searching.
8
+ *
9
+ * Items without augmentation reuse the original Uint32Array (no memory duplication).
10
+ * Items with augmentation get a merged sorted token array.
11
+ *
12
+ * @example
13
+ * const augmented = new AugmentedMetadata(zdravilaMeta, { searchInFields: ['status', 'notes'] });
14
+ * augmented.updateAugmented(id1, { status: "uparjen", notes: "v teku" });
15
+ * augmented.updateAugmented(id2, { status: "neuparjen" });
16
+ *
17
+ * // Now search works with augmented tokens
18
+ * const results = searchInDataReturnIds("aspirin uparjen", augmented);
19
+ */
20
+ export declare class AugmentedMetadata implements NumericSearchMetadata {
21
+ private baseMetadata;
22
+ private augmentedTokens;
23
+ private spec;
24
+ /**
25
+ * @param baseMetadata - Base search metadata (not modified)
26
+ * @param spec - Optional spec for tokenizing augmented objects (searchInFields, fieldMatchModes, etc.)
27
+ * @param augmentedDataMap - Optional initial augmented data map (id -> object)
28
+ */
29
+ constructor(baseMetadata: NumericSearchMetadata, spec?: SearchableObjectSpec<any>, augmentedDataMap?: Map<Id, any>);
30
+ /**
31
+ * Update augmented data for a single item.
32
+ * Pass undefined to remove augmentation for this item.
33
+ *
34
+ * @param id - Item ID
35
+ * @param augmentedData - Additional searchable object (will be tokenized using spec)
36
+ */
37
+ updateAugmented(id: Id, augmentedData: any): void;
38
+ /**
39
+ * Batch update augmented data for multiple items.
40
+ * More efficient than calling updateAugmented multiple times.
41
+ *
42
+ * @param augmentedDataMap - Map of id -> augmented object (will be tokenized using spec)
43
+ */
44
+ updateAugmentedBatch(augmentedDataMap: Map<Id, any>): void;
45
+ /**
46
+ * Remove augmentation for a single item (reverts to base metadata only).
47
+ */
48
+ clearAugmented(id: Id): void;
49
+ /**
50
+ * Remove all augmentations (reverts to base metadata for all items).
51
+ */
52
+ clearAllAugmented(): void;
53
+ /**
54
+ * Get merged tokens for an item (base + augmented).
55
+ * Returns undefined if item doesn't exist in base metadata.
56
+ */
57
+ get(id: Id): NumericTokenSortedList | undefined;
58
+ /**
59
+ * Check if item exists in base metadata.
60
+ */
61
+ has(id: Id): boolean;
62
+ /**
63
+ * Get number of items in base metadata.
64
+ */
65
+ get size(): number;
66
+ /**
67
+ * Iterate over all items (id -> merged tokens).
68
+ */
69
+ [Symbol.iterator](): MapIterator<[Id, NumericTokenSortedList]>;
70
+ /**
71
+ * Iterate over all IDs.
72
+ */
73
+ keys(): MapIterator<Id>;
74
+ /**
75
+ * Iterate over all merged token arrays.
76
+ */
77
+ values(): MapIterator<NumericTokenSortedList>;
78
+ /**
79
+ * Iterate over all [id, merged tokens] entries.
80
+ */
81
+ entries(): MapIterator<[Id, NumericTokenSortedList]>;
82
+ /**
83
+ * Execute callback for each item.
84
+ */
85
+ forEach(callbackfn: (value: NumericTokenSortedList, key: Id, map: Map<Id, NumericTokenSortedList>) => void): void;
86
+ /**
87
+ * Not supported - this is a read-only wrapper.
88
+ * Use updateAugmented() or updateAugmentedBatch() instead.
89
+ */
90
+ set(_key: Id, _value: NumericTokenSortedList): this;
91
+ /**
92
+ * Not supported - this is a read-only wrapper.
93
+ * Use clearAugmented() instead.
94
+ */
95
+ delete(_key: Id): boolean;
96
+ /**
97
+ * Not supported - this is a read-only wrapper.
98
+ * Use clearAllAugmented() instead.
99
+ */
100
+ clear(): void;
101
+ /**
102
+ * Symbol.toStringTag for Map interface.
103
+ */
104
+ get [Symbol.toStringTag](): string;
105
+ /**
106
+ * Merge two sorted Uint32Arrays into a new sorted Uint32Array.
107
+ * Removes duplicates.
108
+ */
109
+ private mergeSortedTokenArrays;
110
+ }
111
+ //# sourceMappingURL=AugmentedMetadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AugmentedMetadata.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/AugmentedMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAInH;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,iBAAkB,YAAW,qBAAqB;IAC7D,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,eAAe,CAAiC;IACxD,OAAO,CAAC,IAAI,CAAuC;IAEnD;;;;OAIG;gBAED,YAAY,EAAE,qBAAqB,EACnC,IAAI,CAAC,EAAE,oBAAoB,CAAC,GAAG,CAAC,EAChC,gBAAgB,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC;IAWjC;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,GAAG,IAAI;IAkBjD;;;;;OAKG;IACH,oBAAoB,CAAC,gBAAgB,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,IAAI;IAqB1D;;OAEG;IACH,cAAc,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI;IAI5B;;OAEG;IACH,iBAAiB,IAAI,IAAI;IAIzB;;;OAGG;IACH,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,sBAAsB,GAAG,SAAS;IAW/C;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO;IAIpB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,CAAC,EAAE,EAAE,sBAAsB,CAAC,CAAC;IAwB9D;;OAEG;IACH,IAAI,IAAI,WAAW,CAAC,EAAE,CAAC;IAIvB;;OAEG;IACH,MAAM,IAAI,WAAW,CAAC,sBAAsB,CAAC;IAsB7C;;OAEG;IACH,OAAO,IAAI,WAAW,CAAC,CAAC,EAAE,EAAE,sBAAsB,CAAC,CAAC;IAIpD;;OAEG;IACH,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,sBAAsB,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,sBAAsB,CAAC,KAAK,IAAI,GAAG,IAAI;IAMjH;;;OAGG;IACH,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,sBAAsB,GAAG,IAAI;IAInD;;;OAGG;IACH,MAAM,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO;IAIzB;;;OAGG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAEjC;IAED;;;OAGG;IACH,OAAO,CAAC,sBAAsB;CAoD/B"}
@@ -6,4 +6,7 @@ export { createSearchLinkedMetadataNumeric, type NumericLinkedSearchMetadataWith
6
6
  export { updateSearchMetadataNumeric, updateSearchMetadataBatchNumeric, removeFromSearchMetadataNumeric, removeFromSearchMetadataBatchNumeric, } from './updateSearchMetadata';
7
7
  export { searchInDataReturnIdsNumeric, searchInDataReturnObjectsNumeric, searchInDataReturnIdsWithLimitNumeric, } from './searchInData';
8
8
  export { findInLinkedArraysNumeric, findInLinkedArraysSimpleNumeric, } from './findInLinkedArrays';
9
+ export { AugmentedMetadata } from './AugmentedMetadata';
10
+ export { syncSearchArrayMetadataNumeric, syncSearchArrayMetadataNumericWithPrevious, } from './syncSearchArrayMetadata';
11
+ export { upsertPrimaryItemNumeric, removePrimaryItemNumeric, upsertLinkedItemNumeric, removeLinkedItemNumeric, syncLinkedItemsForPrimaryNumeric, } from './updateSearchLinkedMetadata';
9
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,gCAAgC,EAChC,6BAA6B,EAC7B,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,aAAa,EACb,eAAe,GAChB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,iCAAiC,EACjC,KAAK,mCAAmC,GACzC,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,2BAA2B,EAC3B,gCAAgC,EAChC,+BAA+B,EAC/B,oCAAoC,GACrC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,4BAA4B,EAC5B,gCAAgC,EAChC,qCAAqC,GACtC,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,yBAAyB,EACzB,+BAA+B,GAChC,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/common/numeric/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,gCAAgC,EAChC,6BAA6B,EAC7B,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,aAAa,EACb,eAAe,GAChB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,iCAAiC,EACjC,KAAK,mCAAmC,GACzC,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,2BAA2B,EAC3B,gCAAgC,EAChC,+BAA+B,EAC/B,oCAAoC,GACrC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,4BAA4B,EAC5B,gCAAgC,EAChC,qCAAqC,GACtC,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,yBAAyB,EACzB,+BAA+B,GAChC,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EACL,8BAA8B,EAC9B,0CAA0C,GAC3C,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,gCAAgC,GACjC,MAAM,8BAA8B,CAAC"}
@@ -0,0 +1,64 @@
1
+ import type { NumericSearchMetadata, SearchableData, SearchableObject, SearchableObjectSpec, SyncResult, SyncOptions } from '../../types/index.js';
2
+ export type { SyncResult, SyncOptions } from '../../types/index.js';
3
+ /**
4
+ * Syncs numeric search metadata with new data.
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
10
+ *
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
+ * ```
30
+ */
31
+ export declare function syncSearchArrayMetadataNumeric<T extends SearchableObject, C = unknown>(metadata: NumericSearchMetadata, newData: SearchableData<T>, spec?: SearchableObjectSpec<T, C>): SyncResult;
32
+ /**
33
+ * Syncs numeric search metadata using previous and new data for efficient diffing.
34
+ *
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
+ * ```
62
+ */
63
+ 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
+ //# sourceMappingURL=syncSearchArrayMetadata.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,130 @@
1
+ import type { Id, SearchableData, SearchableObject, SearchableObjectSpec, UpsertResult, SyncLinkedResult } from '../../types/index.js';
2
+ import type { NumericLinkedSearchMetadataWithData } from './createSearchLinkedMetadata.js';
3
+ export type { UpsertResult, SyncLinkedResult } from '../../types/index.js';
4
+ /**
5
+ * Upserts a primary item into the linked metadata (numeric version).
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
+ * ```
26
+ */
27
+ export declare function upsertPrimaryItemNumeric<TPrimary extends SearchableObject, TLinked extends SearchableObject, C = unknown>(linked: NumericLinkedSearchMetadataWithData<TPrimary, TLinked>, item: TPrimary, spec?: SearchableObjectSpec<TPrimary, C>): UpsertResult;
28
+ /**
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
41
+ */
42
+ export declare function removePrimaryItemNumeric<TPrimary extends SearchableObject, TLinked extends SearchableObject>(linked: NumericLinkedSearchMetadataWithData<TPrimary, TLinked>, primaryId: Id): boolean;
43
+ /**
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
+ * ```
72
+ */
73
+ 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
+ /**
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
+ * ```
91
+ */
92
+ export declare function removeLinkedItemNumeric<TPrimary extends SearchableObject, TLinked extends SearchableObject>(linked: NumericLinkedSearchMetadataWithData<TPrimary, TLinked>, linkedId: Id, foreignKeyGetter: (item: TLinked) => Id | undefined): boolean;
93
+ /**
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
+ * ```
128
+ */
129
+ 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
+ //# sourceMappingURL=updateSearchLinkedMetadata.d.ts.map
@@ -0,0 +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"}