@devisfuture/mega-collection 1.0.8 → 1.0.10
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/README.md +1 -1
- package/dist/filter/index.d.mts +4 -86
- package/dist/index.d.mts +4 -71
- package/dist/merge/index.d.mts +1 -1
- package/dist/search/index.d.mts +4 -74
- package/dist/sort/index.d.mts +4 -83
- package/dist/types-D24zQWME.d.mts +15 -0
- package/package.json +1 -1
- package/dist/types-BlZO_NQA.d.mts +0 -29
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<img src="./illustration.png" alt="electron-modular illustration" width="640" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
[](https://codecov.io/gh/trae-op/mega-collection) [](https://www.typescriptlang.org/)
|
|
5
|
+
[](https://www.npmjs.com/package/@devisfuture/mega-collection) [](https://codecov.io/gh/trae-op/mega-collection) [](https://www.typescriptlang.org/)
|
|
6
6
|
|
|
7
7
|
# @devisfuture/mega-collection
|
|
8
8
|
|
package/dist/filter/index.d.mts
CHANGED
|
@@ -1,117 +1,35 @@
|
|
|
1
|
-
import { C as CollectionItem, F as FilterCriterion } from '../types-
|
|
2
|
-
export { I as IndexableKey } from '../types-
|
|
1
|
+
import { C as CollectionItem, F as FilterCriterion } from '../types-D24zQWME.mjs';
|
|
2
|
+
export { I as IndexableKey } from '../types-D24zQWME.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* FilterEngine
|
|
6
|
-
*
|
|
7
|
-
* Strategy:
|
|
8
|
-
* 1. If hash-map indexes exist (built via buildIndex), use O(1) lookups per
|
|
9
|
-
* value and intersect results across fields. This is the *fast path*.
|
|
10
|
-
*
|
|
11
|
-
* 2. If no index is available for a field, fall back to a single-pass linear
|
|
12
|
-
* scan using a `Set` for each criterion (O(n) but with O(1) membership
|
|
13
|
-
* test per item).
|
|
14
|
-
*
|
|
15
|
-
* Multiple criteria are combined with AND logic: an item must satisfy
|
|
16
|
-
* ALL criteria to be included.
|
|
5
|
+
* FilterEngine class for filtering collections by multiple criteria,
|
|
6
|
+
* supporting indexed lookups and linear scans for large datasets.
|
|
17
7
|
*/
|
|
18
8
|
|
|
19
9
|
interface FilterEngineOptions<T extends CollectionItem = CollectionItem> {
|
|
20
|
-
/**
|
|
21
|
-
* The dataset to index. When provided together with `fields`, all indexes
|
|
22
|
-
* are built automatically inside the constructor — no manual `buildIndex`
|
|
23
|
-
* calls needed.
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```ts
|
|
27
|
-
* const engine = new FilterEngine<User>({ data: users, fields: ["city", "age"] });
|
|
28
|
-
* engine.filter(users, [{ field: "city", values: ["Kyiv"] }]);
|
|
29
|
-
* ```
|
|
30
|
-
*/
|
|
31
10
|
data?: T[];
|
|
32
|
-
/**
|
|
33
|
-
* Fields to build a hash-map index for. Requires `data` to be set as well.
|
|
34
|
-
* When both are present, `buildIndex` is called for each field in the constructor.
|
|
35
|
-
*/
|
|
36
11
|
fields?: (keyof T & string)[];
|
|
37
|
-
/**
|
|
38
|
-
* Enables sequential filtering by the previous filter result.
|
|
39
|
-
*
|
|
40
|
-
* When `true`, each call to `filter(criteria)` (without explicit `data`)
|
|
41
|
-
* uses the previous filter output as the next input dataset.
|
|
42
|
-
*
|
|
43
|
-
* @default false
|
|
44
|
-
*/
|
|
45
12
|
filterByPreviousResult?: boolean;
|
|
46
13
|
}
|
|
47
14
|
declare class FilterEngine<T extends CollectionItem> {
|
|
48
15
|
private indexer;
|
|
49
16
|
private readonly filterByPreviousResult;
|
|
50
|
-
/** Reference to the full dataset (set via the constructor or `buildIndex`). */
|
|
51
17
|
private data;
|
|
52
|
-
/** Last filter output used as the next input in sequential mode. */
|
|
53
18
|
private previousResult;
|
|
54
|
-
/** Last criteria used in sequential mode. */
|
|
55
19
|
private previousCriteria;
|
|
56
|
-
/** Dataset reference used to compute previous sequential result. */
|
|
57
20
|
private previousBaseData;
|
|
58
21
|
constructor(options?: FilterEngineOptions<T>);
|
|
59
|
-
/**
|
|
60
|
-
* Build a hash-map index for a field to enable O(1) fast-path filtering.
|
|
61
|
-
*
|
|
62
|
-
* Two call signatures are supported:
|
|
63
|
-
* - `buildIndex(data, field)` — explicit dataset (original API)
|
|
64
|
-
* - `buildIndex(field)` — reuses the dataset supplied in the constructor
|
|
65
|
-
*
|
|
66
|
-
* @returns `this` for chaining.
|
|
67
|
-
*/
|
|
68
22
|
private buildIndex;
|
|
69
|
-
/**
|
|
70
|
-
* Free all index memory.
|
|
71
|
-
*/
|
|
72
23
|
clearIndexes(): void;
|
|
73
|
-
/**
|
|
74
|
-
* Reset sequential filtering state.
|
|
75
|
-
*
|
|
76
|
-
* Useful when `filterByPreviousResult` is enabled and you want
|
|
77
|
-
* the next `filter(criteria)` call to start from the full dataset.
|
|
78
|
-
*/
|
|
79
24
|
resetFilterState(): void;
|
|
80
|
-
/**
|
|
81
|
-
* Apply multiple filter criteria (AND logic).
|
|
82
|
-
*
|
|
83
|
-
* Two call signatures:
|
|
84
|
-
* - `filter(criteria)` — uses the dataset supplied in the constructor.
|
|
85
|
-
* - `filter(data, criteria)` — explicit dataset (original API).
|
|
86
|
-
*
|
|
87
|
-
* @returns Filtered array.
|
|
88
|
-
*/
|
|
89
25
|
filter(criteria: FilterCriterion<T>[]): T[];
|
|
90
26
|
filter(data: T[], criteria: FilterCriterion<T>[]): T[];
|
|
91
27
|
private cloneCriteria;
|
|
92
28
|
private hasCriteriaAdditions;
|
|
93
29
|
private hasCriteriaRemovals;
|
|
94
30
|
private getAddedCriteria;
|
|
95
|
-
/**
|
|
96
|
-
* Single-pass linear filter using pre-indexed criteria value Sets.
|
|
97
|
-
* O(n × k) where n = data.length, k = criteria count.
|
|
98
|
-
* Each criterion check is O(1) via Map + Set lookup — no nested data iteration.
|
|
99
|
-
*/
|
|
100
31
|
private linearFilter;
|
|
101
|
-
/**
|
|
102
|
-
* Pure index-based filtering with selectivity-driven pruning.
|
|
103
|
-
*
|
|
104
|
-
* Strategy:
|
|
105
|
-
* 1. Sort criteria by estimated result-set size (smallest first).
|
|
106
|
-
* 2. Materialise only the most selective criterion via the index.
|
|
107
|
-
* 3. Pre-index remaining criteria values into Sets for O(1) checks.
|
|
108
|
-
* 4. Single-pass filter over candidates — no nested collection iteration.
|
|
109
|
-
*/
|
|
110
32
|
private filterViaIndex;
|
|
111
|
-
/**
|
|
112
|
-
* Estimate the number of items an indexed criterion would return.
|
|
113
|
-
* Used to sort criteria by selectivity for faster intersection.
|
|
114
|
-
*/
|
|
115
33
|
private estimateIndexSize;
|
|
116
34
|
}
|
|
117
35
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,75 +1,31 @@
|
|
|
1
1
|
import { TextSearchEngine, TextSearchEngineOptions } from './search/index.mjs';
|
|
2
2
|
import { FilterEngine } from './filter/index.mjs';
|
|
3
3
|
import { SortEngine } from './sort/index.mjs';
|
|
4
|
-
import { C as CollectionItem, S as SortDescriptor, F as FilterCriterion } from './types-
|
|
5
|
-
export { I as IndexableKey, a as SortDirection } from './types-
|
|
4
|
+
import { C as CollectionItem, S as SortDescriptor, F as FilterCriterion } from './types-D24zQWME.mjs';
|
|
5
|
+
export { I as IndexableKey, a as SortDirection } from './types-D24zQWME.mjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* MergeEngines
|
|
9
|
-
* and
|
|
10
|
-
*
|
|
11
|
-
* Design:
|
|
12
|
-
* - The `imports` array declares which sub-engines to activate.
|
|
13
|
-
* - Each sub-engine is initialised lazily only when its constructor appears
|
|
14
|
-
* in `imports` AND the corresponding config section is provided.
|
|
15
|
-
* - Delegates `search`, `sort` and `filter` calls directly to the underlying
|
|
16
|
-
* engines — zero logic duplication.
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```ts
|
|
20
|
-
* import { MergeEngines } from "@devisfuture/mega-collection";
|
|
21
|
-
* import { TextSearchEngine } from "@devisfuture/mega-collection/search";
|
|
22
|
-
* import { SortEngine } from "@devisfuture/mega-collection/sort";
|
|
23
|
-
* import { FilterEngine } from "@devisfuture/mega-collection/filter";
|
|
24
|
-
*
|
|
25
|
-
* const engine = new MergeEngines<User>({
|
|
26
|
-
* imports: [TextSearchEngine, SortEngine, FilterEngine],
|
|
27
|
-
* data: users,
|
|
28
|
-
* search: { fields: ["city", "name"], minQueryLength: 2 },
|
|
29
|
-
* filter: { fields: ["city", "age"] },
|
|
30
|
-
* sort: { fields: ["age", "name", "city"] },
|
|
31
|
-
* });
|
|
32
|
-
*
|
|
33
|
-
* engine.search("john");
|
|
34
|
-
* engine.sort([{ field: "age", direction: "asc" }]);
|
|
35
|
-
* engine.filter([{ field: "city", values: ["Kyiv"] }]);
|
|
36
|
-
* ```
|
|
8
|
+
* MergeEngines class that provides a unified interface for text search,
|
|
9
|
+
* sorting, and filtering operations on collections.
|
|
37
10
|
*/
|
|
38
11
|
|
|
39
|
-
/** Search-specific configuration (excludes `data` — shared at the top level). */
|
|
40
12
|
interface MergeSearchConfig<T extends CollectionItem> {
|
|
41
13
|
fields: (keyof T & string)[];
|
|
42
14
|
minQueryLength?: TextSearchEngineOptions<T>["minQueryLength"];
|
|
43
15
|
}
|
|
44
|
-
/** Filter-specific configuration (excludes `data` — shared at the top level). */
|
|
45
16
|
interface MergeFilterConfig<T extends CollectionItem> {
|
|
46
17
|
fields: (keyof T & string)[];
|
|
47
18
|
filterByPreviousResult?: boolean;
|
|
48
19
|
}
|
|
49
|
-
/** Sort-specific configuration (excludes `data` — shared at the top level). */
|
|
50
20
|
interface MergeSortConfig<T extends CollectionItem> {
|
|
51
21
|
fields: (keyof T & string)[];
|
|
52
22
|
}
|
|
53
|
-
/** Union of the three engine constructors accepted in `imports`. */
|
|
54
23
|
type EngineConstructor = typeof TextSearchEngine | typeof SortEngine | typeof FilterEngine;
|
|
55
24
|
interface MergeEnginesOptions<T extends CollectionItem> {
|
|
56
|
-
/**
|
|
57
|
-
* List of engine classes to activate.
|
|
58
|
-
* Only engines present in this array will be initialised.
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* ```ts
|
|
62
|
-
* imports: [TextSearchEngine, SortEngine, FilterEngine]
|
|
63
|
-
* ```
|
|
64
|
-
*/
|
|
65
25
|
imports: EngineConstructor[];
|
|
66
|
-
/** Shared dataset — passed to every activated engine. */
|
|
67
26
|
data: T[];
|
|
68
|
-
/** Config for TextSearchEngine (requires `TextSearchEngine` in `imports`). */
|
|
69
27
|
search?: MergeSearchConfig<T>;
|
|
70
|
-
/** Config for FilterEngine (requires `FilterEngine` in `imports`). */
|
|
71
28
|
filter?: MergeFilterConfig<T>;
|
|
72
|
-
/** Config for SortEngine (requires `SortEngine` in `imports`). */
|
|
73
29
|
sort?: MergeSortConfig<T>;
|
|
74
30
|
}
|
|
75
31
|
declare class MergeEngines<T extends CollectionItem> {
|
|
@@ -77,33 +33,10 @@ declare class MergeEngines<T extends CollectionItem> {
|
|
|
77
33
|
private readonly sortEngine;
|
|
78
34
|
private readonly filterEngine;
|
|
79
35
|
constructor(options: MergeEnginesOptions<T>);
|
|
80
|
-
/**
|
|
81
|
-
* Search items by substring across all indexed fields.
|
|
82
|
-
*
|
|
83
|
-
* Delegates to `TextSearchEngine.search`.
|
|
84
|
-
*
|
|
85
|
-
* @throws {Error} If `TextSearchEngine` was not included in `imports`.
|
|
86
|
-
*/
|
|
87
36
|
search(query: string): T[];
|
|
88
37
|
search(field: keyof T & string, query: string): T[];
|
|
89
|
-
/**
|
|
90
|
-
* Sort items by one or more fields.
|
|
91
|
-
*
|
|
92
|
-
* Delegates to `SortEngine.sort`.
|
|
93
|
-
* Uses the shared dataset from the constructor when called without `data`.
|
|
94
|
-
*
|
|
95
|
-
* @throws {Error} If `SortEngine` was not included in `imports`.
|
|
96
|
-
*/
|
|
97
38
|
sort(descriptors: SortDescriptor<T>[]): T[];
|
|
98
39
|
sort(data: T[], descriptors: SortDescriptor<T>[], inPlace?: boolean): T[];
|
|
99
|
-
/**
|
|
100
|
-
* Filter items by multiple criteria (AND logic).
|
|
101
|
-
*
|
|
102
|
-
* Delegates to `FilterEngine.filter`.
|
|
103
|
-
* Uses the shared dataset from the constructor when called without `data`.
|
|
104
|
-
*
|
|
105
|
-
* @throws {Error} If `FilterEngine` was not included in `imports`.
|
|
106
|
-
*/
|
|
107
40
|
filter(criteria: FilterCriterion<T>[]): T[];
|
|
108
41
|
filter(data: T[], criteria: FilterCriterion<T>[]): T[];
|
|
109
42
|
}
|
package/dist/merge/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { EngineConstructor, MergeEngines, MergeEnginesOptions, MergeFilterConfig, MergeSearchConfig, MergeSortConfig } from '../index.mjs';
|
|
2
|
-
export { C as CollectionItem, F as FilterCriterion, I as IndexableKey, S as SortDescriptor, a as SortDirection } from '../types-
|
|
2
|
+
export { C as CollectionItem, F as FilterCriterion, I as IndexableKey, S as SortDescriptor, a as SortDirection } from '../types-D24zQWME.mjs';
|
|
3
3
|
import '../search/index.mjs';
|
|
4
4
|
import '../filter/index.mjs';
|
|
5
5
|
import '../sort/index.mjs';
|
package/dist/search/index.d.mts
CHANGED
|
@@ -1,97 +1,27 @@
|
|
|
1
|
-
import { C as CollectionItem } from '../types-
|
|
2
|
-
export { I as IndexableKey } from '../types-
|
|
1
|
+
import { C as CollectionItem } from '../types-D24zQWME.mjs';
|
|
2
|
+
export { I as IndexableKey } from '../types-D24zQWME.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* TextSearchEngine
|
|
6
|
-
*
|
|
7
|
-
* Strategy:
|
|
8
|
-
* 1. **N-gram index (1..3 chars)** — every string is split into overlapping
|
|
9
|
-
* 1/2/3-character grams. Each gram maps to a Set of item indexes.
|
|
10
|
-
* At query time we intersect posting lists to get *candidates*, then verify
|
|
11
|
-
* with `String.includes` (which is very fast on a small candidate set).
|
|
12
|
-
*
|
|
13
|
-
* Building the trigram index is O(n·L) where L is average string length.
|
|
14
|
-
* Query time is roughly O(|candidates| + |postingList intersections|).
|
|
5
|
+
* TextSearchEngine class for performing fast substring search on string fields
|
|
6
|
+
* using n-gram indexing and intersection.
|
|
15
7
|
*/
|
|
16
8
|
|
|
17
9
|
interface TextSearchEngineOptions<T extends CollectionItem = CollectionItem> {
|
|
18
|
-
/**
|
|
19
|
-
* The dataset to index. When provided together with `fields`, all indexes
|
|
20
|
-
* are built automatically inside the constructor — no manual `buildIndex`
|
|
21
|
-
* calls needed.
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```ts
|
|
25
|
-
* const engine = new TextSearchEngine<User>({ data: users, fields: ["name", "city"] });
|
|
26
|
-
* engine.search("john"); // searches both fields, deduplicated
|
|
27
|
-
* ```
|
|
28
|
-
*/
|
|
29
10
|
data?: T[];
|
|
30
|
-
/**
|
|
31
|
-
* Fields to build a trigram index for. Requires `data` to be set as well.
|
|
32
|
-
* When both are present, `buildIndex` is called for each field in the constructor.
|
|
33
|
-
*/
|
|
34
11
|
fields?: (keyof T & string)[];
|
|
35
|
-
/**
|
|
36
|
-
* Minimum number of characters required before a search is executed.
|
|
37
|
-
* Queries shorter than this return an empty array immediately.
|
|
38
|
-
*
|
|
39
|
-
* Why this matters: a single-character query uses 1-grams whose posting
|
|
40
|
-
* lists can span the majority of the dataset (e.g. "a" matches 70–80 % of
|
|
41
|
-
* names/cities), forcing `String.includes` verification over tens of
|
|
42
|
-
* thousands of candidates. Setting this to 2 or 3 dramatically reduces
|
|
43
|
-
* the candidate set and keeps searches fast even with 100 k+ items.
|
|
44
|
-
*
|
|
45
|
-
* @default 1 (backwards-compatible; set to 2 or 3 for better perf)
|
|
46
|
-
*/
|
|
47
12
|
minQueryLength?: number;
|
|
48
13
|
}
|
|
49
14
|
declare class TextSearchEngine<T extends CollectionItem> {
|
|
50
|
-
/**
|
|
51
|
-
* field → ngram → Set<index in data[]>
|
|
52
|
-
* We store *indexes into the data array* (not the objects) to save memory.
|
|
53
|
-
*/
|
|
54
15
|
private ngramIndexes;
|
|
55
|
-
/** Reference to the full dataset (set once via `buildIndex` or the constructor). */
|
|
56
16
|
private data;
|
|
57
|
-
/** Minimum query length before the engine executes a search. */
|
|
58
17
|
private readonly minQueryLength;
|
|
59
18
|
constructor(options?: TextSearchEngineOptions<T>);
|
|
60
|
-
/**
|
|
61
|
-
* Build n-gram index (1..3 chars) for one field. O(n·L).
|
|
62
|
-
*
|
|
63
|
-
* Two call signatures are supported:
|
|
64
|
-
* - `buildIndex(data, field)` — explicit dataset (original API)
|
|
65
|
-
* - `buildIndex(field)` — reuses the dataset supplied in the constructor
|
|
66
|
-
*
|
|
67
|
-
* Trigram extraction is inlined to avoid allocating a temporary array
|
|
68
|
-
* and a deduplication Set per item. Posting lists are `Set<number>`,
|
|
69
|
-
* so duplicate `.add()` calls for the same itemIndex are no-ops — we
|
|
70
|
-
* get correctness without per-item deduplication overhead.
|
|
71
|
-
*
|
|
72
|
-
* For 10 M+ items this eliminates ~20 M transient object allocations
|
|
73
|
-
* and dramatically reduces GC pressure.
|
|
74
|
-
*/
|
|
75
19
|
private buildIndex;
|
|
76
|
-
/**
|
|
77
|
-
* Search items by substring (contains) using the trigram index.
|
|
78
|
-
*
|
|
79
|
-
* Two call signatures are supported:
|
|
80
|
-
* - `search(query)` — searches **all** indexed fields and returns a
|
|
81
|
-
* deduplicated union (preserves field order).
|
|
82
|
-
* - `search(field, query)` — searches a single specific field.
|
|
83
|
-
*
|
|
84
|
-
* Both paths return only items whose field value actually contains the query
|
|
85
|
-
* (trigram candidates are verified with `String.includes`).
|
|
86
|
-
*/
|
|
87
20
|
search(query: string): T[];
|
|
88
21
|
search(field: keyof T & string, query: string): T[];
|
|
89
|
-
/** Search across every indexed field and return a deduplicated union. */
|
|
90
22
|
private searchAllFields;
|
|
91
|
-
/** Core search implementation for a single field. */
|
|
92
23
|
private searchField;
|
|
93
24
|
private searchFieldWithPreparedQuery;
|
|
94
|
-
/** Free memory. */
|
|
95
25
|
clear(): void;
|
|
96
26
|
}
|
|
97
27
|
|
package/dist/sort/index.d.mts
CHANGED
|
@@ -1,105 +1,26 @@
|
|
|
1
|
-
import { C as CollectionItem, S as SortDescriptor } from '../types-
|
|
2
|
-
export { a as SortDirection } from '../types-
|
|
1
|
+
import { C as CollectionItem, S as SortDescriptor } from '../types-D24zQWME.mjs';
|
|
2
|
+
export { a as SortDirection } from '../types-D24zQWME.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* SortEngine
|
|
6
|
-
*
|
|
7
|
-
* Strategy:
|
|
8
|
-
* 1. **Pre-sorted index cache** (fastest): `buildIndex` pre-computes a sorted
|
|
9
|
-
* `Uint32Array` of item positions once — O(n log n). Every subsequent
|
|
10
|
-
* `sort` call on that field is O(n) reconstruction (no comparison at all).
|
|
11
|
-
* Reversing direction is also O(n) — just walk the index backwards.
|
|
12
|
-
*
|
|
13
|
-
* 2. **In-place sort** using the native V8 TimSort (`Array.prototype.sort`)
|
|
14
|
-
* which is O(n log n) and very cache-friendly for large arrays.
|
|
15
|
-
*
|
|
16
|
-
* 3. **Pre-compiled comparator**: we build a single comparator function that
|
|
17
|
-
* handles multi-field sorting with correct direction, avoiding per-compare
|
|
18
|
-
* overhead of dynamic field resolution.
|
|
19
|
-
*
|
|
20
|
-
* 4. **Typed-array radix sort** (fallback for single numeric field):
|
|
21
|
-
* O(n) index-sort using `Float64Array` for extreme speed on numeric data.
|
|
22
|
-
*
|
|
23
|
-
* 5. Returns a **new array** by default to keep the original intact.
|
|
24
|
-
* Pass `inPlace: true` to mutate.
|
|
5
|
+
* SortEngine class for sorting large datasets using pre-built indexes
|
|
6
|
+
* for O(n) performance or fallback to in-place sorting.
|
|
25
7
|
*/
|
|
26
8
|
|
|
27
9
|
interface SortEngineOptions<T extends CollectionItem = CollectionItem> {
|
|
28
|
-
/**
|
|
29
|
-
* The dataset to index. When provided together with `fields`, all indexes
|
|
30
|
-
* are built automatically inside the constructor — no manual `buildIndex`
|
|
31
|
-
* calls needed.
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* ```ts
|
|
35
|
-
* const engine = new SortEngine<User>({ data: users, fields: ["age", "name", "city"] });
|
|
36
|
-
* engine.sort(users, [{ field: "age", direction: "asc" }]);
|
|
37
|
-
* ```
|
|
38
|
-
*/
|
|
39
10
|
data?: T[];
|
|
40
|
-
/**
|
|
41
|
-
* Fields to pre-sort and cache. Requires `data` to be set as well.
|
|
42
|
-
* When both are present, `buildIndex` is called for each field in the constructor.
|
|
43
|
-
*/
|
|
44
11
|
fields?: (keyof T & string)[];
|
|
45
12
|
}
|
|
46
13
|
declare class SortEngine<T extends CollectionItem> {
|
|
47
|
-
/** field → cached ascending sort index */
|
|
48
14
|
private cache;
|
|
49
|
-
/** Reference to the full dataset (set via the constructor or `buildIndex`). */
|
|
50
15
|
private data;
|
|
51
16
|
constructor(options?: SortEngineOptions<T>);
|
|
52
|
-
/**
|
|
53
|
-
* Pre-compute and cache a sorted index for a field.
|
|
54
|
-
*
|
|
55
|
-
* Two call signatures are supported:
|
|
56
|
-
* - `buildIndex(data, field)` — explicit dataset (original API)
|
|
57
|
-
* - `buildIndex(field)` — reuses the dataset supplied in the constructor
|
|
58
|
-
*
|
|
59
|
-
* Call this once per field; all subsequent `sort` calls on that field
|
|
60
|
-
* will use the cache — O(n) instead of O(n log n).
|
|
61
|
-
*
|
|
62
|
-
* @returns `this` for chaining.
|
|
63
|
-
*/
|
|
64
17
|
private buildIndex;
|
|
65
|
-
/**
|
|
66
|
-
* Free all cached sort indexes.
|
|
67
|
-
*/
|
|
68
18
|
clearIndexes(): void;
|
|
69
|
-
/**
|
|
70
|
-
* Sort items by one or more fields.
|
|
71
|
-
*
|
|
72
|
-
* Two call signatures:
|
|
73
|
-
* - `sort(descriptors)` — uses the dataset supplied in the constructor.
|
|
74
|
-
* - `sort(data, descriptors)` — explicit dataset (original API).
|
|
75
|
-
*
|
|
76
|
-
* If `buildIndex` was called for the leading sort field and the dataset
|
|
77
|
-
* reference matches, sorting is O(n) via cached indexes regardless of
|
|
78
|
-
* direction. Otherwise falls back to O(n log n) TimSort.
|
|
79
|
-
*
|
|
80
|
-
* @returns The sorted array.
|
|
81
|
-
*/
|
|
82
19
|
sort(descriptors: SortDescriptor<T>[]): T[];
|
|
83
20
|
sort(data: T[], descriptors: SortDescriptor<T>[], inPlace?: boolean): T[];
|
|
84
|
-
/**
|
|
85
|
-
* Reconstruct a sorted array from a pre-built ascending index.
|
|
86
|
-
* O(n) — no comparisons, just array reads.
|
|
87
|
-
*/
|
|
88
21
|
private reconstructFromIndex;
|
|
89
22
|
private isFieldSnapshotValid;
|
|
90
|
-
/**
|
|
91
|
-
* Build a single comparator function for multi-field sorting.
|
|
92
|
-
* Captures field names and direction multipliers in closure for speed.
|
|
93
|
-
*/
|
|
94
23
|
private buildComparator;
|
|
95
|
-
/**
|
|
96
|
-
* Radix sort for a single numeric field.
|
|
97
|
-
* Uses index-array approach: sort an auxiliary index array by the numeric
|
|
98
|
-
* values, then reorder items by those indexes.
|
|
99
|
-
* O(n) time for integers; O(n) for floats via float-to-int encoding.
|
|
100
|
-
*
|
|
101
|
-
* Falls back to native sort if the range is too large (sparse data).
|
|
102
|
-
*/
|
|
103
24
|
private radixSortNumeric;
|
|
104
25
|
}
|
|
105
26
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type CollectionItem = Record<string, any>;
|
|
2
|
+
type IndexableKey<T> = {
|
|
3
|
+
[K in keyof T]: T[K] extends string | number ? K : never;
|
|
4
|
+
}[keyof T];
|
|
5
|
+
interface FilterCriterion<T extends CollectionItem> {
|
|
6
|
+
field: keyof T & string;
|
|
7
|
+
values: any[];
|
|
8
|
+
}
|
|
9
|
+
type SortDirection = "asc" | "desc";
|
|
10
|
+
interface SortDescriptor<T extends CollectionItem> {
|
|
11
|
+
field: keyof T & string;
|
|
12
|
+
direction: SortDirection;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type { CollectionItem as C, FilterCriterion as F, IndexableKey as I, SortDescriptor as S, SortDirection as a };
|
package/package.json
CHANGED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Core type definitions for MegaCollection.
|
|
3
|
-
*
|
|
4
|
-
* All generics use `T` for the item type and constrain it to `Record<string, any>`
|
|
5
|
-
* so that every item is an indexable plain object.
|
|
6
|
-
*/
|
|
7
|
-
/** Any plain object whose values can be indexed. */
|
|
8
|
-
type CollectionItem = Record<string, any>;
|
|
9
|
-
/**
|
|
10
|
-
* Extract only the keys of T whose values are `string | number`.
|
|
11
|
-
* Used to restrict indexing / sorting to primitive-comparable fields.
|
|
12
|
-
*/
|
|
13
|
-
type IndexableKey<T> = {
|
|
14
|
-
[K in keyof T]: T[K] extends string | number ? K : never;
|
|
15
|
-
}[keyof T];
|
|
16
|
-
/** A single filter criterion: field name → set of acceptable values. */
|
|
17
|
-
interface FilterCriterion<T extends CollectionItem> {
|
|
18
|
-
field: keyof T & string;
|
|
19
|
-
values: any[];
|
|
20
|
-
}
|
|
21
|
-
/** Sorting direction. */
|
|
22
|
-
type SortDirection = "asc" | "desc";
|
|
23
|
-
/** Sorting descriptor. */
|
|
24
|
-
interface SortDescriptor<T extends CollectionItem> {
|
|
25
|
-
field: keyof T & string;
|
|
26
|
-
direction: SortDirection;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export type { CollectionItem as C, FilterCriterion as F, IndexableKey as I, SortDescriptor as S, SortDirection as a };
|