cry-search 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CLAUDE.md CHANGED
@@ -71,8 +71,8 @@ The numeric implementation uses a global token registry (`src/utils/tokenRegistr
71
71
  3. sanitation
72
72
  1. case-insensitive
73
73
  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 (" ")
74
+ 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 (` `)
76
76
  2. tokenization
77
77
  1. we split strings on spaces
78
78
  2. then we trim all substrings
@@ -130,6 +130,32 @@ tsc 3. we only keep letters (a-z), digits (0-9), periods (.), minuses (-
130
130
  4. example use case
131
131
  1. search "krajnik angie" matches stranka "Krajnik" with pacient "Angie"
132
132
  2. returns: { primary: Stranka, secondaries: [matching Pacient], matchedIn: 'both' }
133
+ 9. augmented metadata
134
+ 1. purpose: add local/temporary searchable data to existing metadata without modifying the base metadata
135
+ 2. use case: search for items combined with page-specific data (e.g., match status, local flags, computed properties)
136
+ 3. class AugmentedMetadata
137
+ 1. wraps existing NumericSearchMetadata
138
+ 2. allows adding additional search tokens dynamically
139
+ 3. memory efficient: items without augmentation reuse original Uint32Array
140
+ 4. items with augmentation get merged sorted token array (base + augmented)
141
+ 5. constructor takes: baseMetadata, optional spec, optional initial augmented data
142
+ 6. spec controls tokenization: searchInFields, fieldMatchModes, etc.
143
+ 4. updating augmented data
144
+ 1. updateAugmented(id, obj) - single item update
145
+ 2. updateAugmentedBatch(map) - batch update (more efficient)
146
+ 3. clearAugmented(id) - remove augmentation for one item
147
+ 4. clearAllAugmented() - remove all augmentations
148
+ 5. searching
149
+ 1. implements NumericSearchMetadata interface
150
+ 2. works with all search functions (searchInDataReturnIds, etc.)
151
+ 3. combines base + augmented tokens during search
152
+ 4. supports all query prefixes and match modes
153
+ 6. example use case
154
+ 1. global zdravila metadata with names, manufacturers
155
+ 2. page-local augmented metadata adds "uparjen"/"neuparjen" status
156
+ 3. search "aspirin uparjen" finds Aspirin items with "uparjen" status
157
+ 4. updating status doesn't modify global metadata
158
+ 5. removing augmentation reverts to base metadata only
133
159
 
134
160
  ## Types
135
161
 
@@ -222,6 +248,54 @@ Override match behavior per token at search time. Priority: query prefix > field
222
248
  8. updateSearchMetadataBatch(metadata, batch, spec)
223
249
  1. creates temporary tokensMap, clears after use
224
250
  2. updates or deletes metadata for batch of objects
251
+ 9. syncSearchArrayMetadata(metadata, newData, spec?)
252
+ 1. syncs metadata with new data (inkrementalno posodabljanje)
253
+ 2. adds new items, updates changed items, removes old items
254
+ 3. compares token arrays - skips unchanged items (performance optimization)
255
+ 4. more efficient than full rebuild for partial updates
256
+ 5. uses single tokensMap for all operations (memory efficient)
257
+ 10. syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, options?, spec?)
258
+ 1. more efficient than syncSearchArrayMetadata when you have both datasets
259
+ 2. uses previousData to determine removals (no metadata.keys() iteration)
260
+ 3. skipUpdateCheck option - skip checking for updates (even faster)
261
+ 4. best for regular refresh cycles (e.g., every 30s from server)
262
+ 11. AugmentedMetadata class
263
+ 1. constructor(baseMetadata, spec?, augmentedDataMap?)
264
+ 1. baseMetadata: NumericSearchMetadata - base metadata to wrap (not modified)
265
+ 2. spec?: SearchableObjectSpec - controls tokenization of augmented objects
266
+ 3. augmentedDataMap?: Map<Id, any> - optional initial augmented data
267
+ 2. updateAugmented(id, obj) - add/update augmented data for one item
268
+ 3. updateAugmentedBatch(map) - batch update (more efficient than multiple single updates)
269
+ 4. clearAugmented(id) - remove augmentation for one item
270
+ 5. clearAllAugmented() - remove all augmentations
271
+ 6. implements NumericSearchMetadata interface (get, has, size, keys, values, entries, forEach)
272
+ 7. Map mutation methods (set, delete, clear) throw errors - use update methods instead
273
+ 12. Linked metadata update functions (incremental updates to linked metadata)
274
+ 1. upsertPrimaryItem(linked, item, spec?)
275
+ 1. adds or updates a primary item in linked metadata
276
+ 2. updates primaryData, primaryMeta, and initializes primaryToLinked index
277
+ 3. handles _deleted/_blocked by removing metadata
278
+ 4. returns { added: boolean } - true if item was new
279
+ 2. removePrimaryItem(linked, primaryId)
280
+ 1. removes primary item from data, metadata, and primaryToLinked index
281
+ 2. does NOT remove linked items (they become orphans)
282
+ 3. returns true if found and removed, false otherwise
283
+ 3. upsertLinkedItem(linked, item, foreignKeyGetter, spec?)
284
+ 1. adds or updates a linked item in linked metadata
285
+ 2. updates linkedData, linkedMeta, and primaryToLinked index
286
+ 3. handles foreign key changes (moves item between primaries)
287
+ 4. handles _deleted/_blocked by removing metadata
288
+ 5. returns { added: boolean, previousPrimaryId?: Id }
289
+ 4. removeLinkedItem(linked, linkedId, foreignKeyGetter)
290
+ 1. removes linked item from data, metadata, and primaryToLinked index
291
+ 2. returns true if found and removed, false otherwise
292
+ 5. syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKeyGetter, spec?)
293
+ 1. full sync of linked items for a single primary
294
+ 2. removes items not in newLinkedItems
295
+ 3. updates items with changed tokens
296
+ 4. adds new items
297
+ 5. only processes items whose foreign key matches primaryId
298
+ 6. returns { added: number, updated: number, removed: number }
225
299
 
226
300
  ## Token Registry Functions
227
301
 
@@ -237,15 +311,38 @@ Override match behavior per token at search time. Priority: query prefix > field
237
311
 
238
312
  ## String Implementation (Legacy)
239
313
 
240
- Available with `*String` suffix:
314
+ The string-based implementation is available as a separate entry point for backwards compatibility.
315
+
316
+ **Import from `cry-search/string`:**
317
+ ```typescript
318
+ import {
319
+ createSearchArrayMetadataString,
320
+ updateSearchMetadataString,
321
+ findInArray,
322
+ // ... other string-based functions
323
+ } from 'cry-search/string';
324
+ ```
325
+
326
+ **Available functions with `*String` suffix:**
241
327
  - createSearchArrayMetadataString
242
328
  - createSearchLinkedMetadataString
243
329
  - updateSearchMetadataString
244
330
  - updateSearchMetadataBatchString
331
+ - syncSearchArrayMetadataString
332
+ - syncSearchArrayMetadataStringWithPrevious
333
+ - upsertPrimaryItemString
334
+ - removePrimaryItemString
335
+ - upsertLinkedItemString
336
+ - removeLinkedItemString
337
+ - syncLinkedItemsForPrimaryString
245
338
  - findInArray (uses string metadata)
246
339
  - findInArrayReturnDataAndMeta
247
340
  - findInLinkedArrays
248
341
 
342
+ **Bundle sizes:**
343
+ - Main bundle (`cry-search`): ~49 KB - includes only numeric implementation
344
+ - String bundle (`cry-search/string`): ~26 KB - includes only string implementation
345
+
249
346
  ## File Structure
250
347
 
251
348
  ```
@@ -256,7 +353,10 @@ src/
256
353
  │ │ ├── createSearchArrayMetadata.ts
257
354
  │ │ ├── createSearchLinkedMetadata.ts
258
355
  │ │ ├── updateSearchMetadata.ts
259
- │ │ └── searchInData.ts
356
+ │ │ ├── updateSearchLinkedMetadata.ts
357
+ │ │ ├── searchInData.ts
358
+ │ │ ├── syncSearchArrayMetadata.ts
359
+ │ │ └── AugmentedMetadata.ts
260
360
  │ ├── string/ # Legacy string implementation
261
361
  │ │ ├── index.ts
262
362
  │ │ ├── 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"}