@vielzeug/scout 1.1.1
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 +70 -0
- package/dist/_dev.cjs +2 -0
- package/dist/_dev.cjs.map +1 -0
- package/dist/_dev.d.ts +2 -0
- package/dist/_dev.d.ts.map +1 -0
- package/dist/_dev.js +9 -0
- package/dist/_dev.js.map +1 -0
- package/dist/adapters.cjs +2 -0
- package/dist/adapters.cjs.map +1 -0
- package/dist/adapters.d.ts +40 -0
- package/dist/adapters.d.ts.map +1 -0
- package/dist/adapters.js +12 -0
- package/dist/adapters.js.map +1 -0
- package/dist/devtools.cjs +2 -0
- package/dist/devtools.cjs.map +1 -0
- package/dist/devtools.d.ts +38 -0
- package/dist/devtools.d.ts.map +1 -0
- package/dist/devtools.js +21 -0
- package/dist/devtools.js.map +1 -0
- package/dist/errors.cjs +2 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +13 -0
- package/dist/errors.js.map +1 -0
- package/dist/highlight.cjs +2 -0
- package/dist/highlight.cjs.map +1 -0
- package/dist/highlight.d.ts +68 -0
- package/dist/highlight.d.ts.map +1 -0
- package/dist/highlight.js +45 -0
- package/dist/highlight.js.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/reactive.cjs +2 -0
- package/dist/reactive.cjs.map +1 -0
- package/dist/reactive.d.ts +74 -0
- package/dist/reactive.d.ts.map +1 -0
- package/dist/reactive.js +71 -0
- package/dist/reactive.js.map +1 -0
- package/dist/scout-index.cjs +2 -0
- package/dist/scout-index.cjs.map +1 -0
- package/dist/scout-index.d.ts +64 -0
- package/dist/scout-index.d.ts.map +1 -0
- package/dist/scout-index.js +162 -0
- package/dist/scout-index.js.map +1 -0
- package/dist/scout.cjs +2 -0
- package/dist/scout.cjs.map +1 -0
- package/dist/scout.iife.js +2 -0
- package/dist/scout.iife.js.map +1 -0
- package/dist/scout.js +2 -0
- package/dist/scout.js.map +1 -0
- package/dist/segment.cjs +2 -0
- package/dist/segment.cjs.map +1 -0
- package/dist/segment.d.ts +26 -0
- package/dist/segment.d.ts.map +1 -0
- package/dist/segment.js +13 -0
- package/dist/segment.js.map +1 -0
- package/dist/tokenize.cjs +2 -0
- package/dist/tokenize.cjs.map +1 -0
- package/dist/tokenize.d.ts +2 -0
- package/dist/tokenize.d.ts.map +1 -0
- package/dist/tokenize.js +12 -0
- package/dist/tokenize.js.map +1 -0
- package/dist/trigram.cjs +2 -0
- package/dist/trigram.cjs.map +1 -0
- package/dist/trigram.d.ts +2 -0
- package/dist/trigram.d.ts.map +1 -0
- package/dist/trigram.js +16 -0
- package/dist/trigram.js.map +1 -0
- package/dist/types.d.ts +130 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +48 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type { Computed, Signal } from '@vielzeug/ripple';
|
|
2
|
+
/**
|
|
3
|
+
* A single field to include in the index.
|
|
4
|
+
* Pass a string key for default options, or an object to set weight and stringify.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* // Simple — index field 'name' with default weight 1
|
|
9
|
+
* createIndex(users, { fields: ['name'] });
|
|
10
|
+
*
|
|
11
|
+
* // Weighted — 'name' ranks higher than 'bio'
|
|
12
|
+
* createIndex(users, { fields: [{ field: 'name', weight: 2 }, { field: 'bio' }] });
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export type FieldDef<T> = (keyof T & string) | {
|
|
16
|
+
field: keyof T & string;
|
|
17
|
+
/**
|
|
18
|
+
* Custom stringifier for non-string field values.
|
|
19
|
+
* Defaults to `String(value)` for numbers and booleans, empty string otherwise.
|
|
20
|
+
*/
|
|
21
|
+
stringify?: (value: unknown) => string;
|
|
22
|
+
/** Relative ranking weight (default `1`). Higher promotes matches on this field. */
|
|
23
|
+
weight?: number;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Shared search-tuning knobs used by `createIndex()`, `search()`, `createSearch()`,
|
|
27
|
+
* and `createReactiveSearch()`.
|
|
28
|
+
*/
|
|
29
|
+
export type SearchConstraints = {
|
|
30
|
+
/** Maximum results returned. Default: `50`. Negative values are clamped to `0`. */
|
|
31
|
+
limit?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Minimum query length (in characters) before trigram scoring is used.
|
|
34
|
+
* Queries shorter than this value fall back to O(n) substring containment scan.
|
|
35
|
+
* Default: `3`. Increase for large corpora where short queries are too broad;
|
|
36
|
+
* decrease (e.g. `1`) for small corpora or when single-character matching is expected.
|
|
37
|
+
*/
|
|
38
|
+
minQueryLength?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Minimum Dice similarity score `[0, 1]` for a candidate to appear in results. Default: `0.2`.
|
|
41
|
+
* Higher values require a closer match; lower values are more permissive.
|
|
42
|
+
*/
|
|
43
|
+
threshold?: number;
|
|
44
|
+
};
|
|
45
|
+
/** Options accepted by `createIndex()`. */
|
|
46
|
+
export type ScoutIndexOptions<T> = SearchConstraints & {
|
|
47
|
+
/** Fields to index. At least one field is required. */
|
|
48
|
+
fields: ReadonlyArray<FieldDef<T>>;
|
|
49
|
+
};
|
|
50
|
+
/** Options accepted by `createSearch()` and `createReactiveSearch()`. */
|
|
51
|
+
export type CreateSearchOptions = SearchConstraints & {
|
|
52
|
+
/**
|
|
53
|
+
* Milliseconds to wait after a `query` change before updating `results`. Default: `200`.
|
|
54
|
+
* Pass `0` for immediate synchronous updates (no `isSearching` flash).
|
|
55
|
+
*/
|
|
56
|
+
debounce?: number;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Per-field character ranges where the query was found (for highlighting).
|
|
60
|
+
*
|
|
61
|
+
* The generic parameter `F` is the union of valid field names from the index,
|
|
62
|
+
* so `match.field` is constrained to the fields that were actually indexed.
|
|
63
|
+
*/
|
|
64
|
+
export type FieldMatch<F extends string = string> = {
|
|
65
|
+
/** Field name this match belongs to. */
|
|
66
|
+
field: F;
|
|
67
|
+
/**
|
|
68
|
+
* Matched character ranges `[start, end]` in the **original** (pre-lowercase) field value.
|
|
69
|
+
* Pass these directly to `highlight()` or `highlightField()`.
|
|
70
|
+
*/
|
|
71
|
+
ranges: [number, number][];
|
|
72
|
+
};
|
|
73
|
+
/** A single result from `ScoutIndex.search()`. */
|
|
74
|
+
export type SearchResult<T> = {
|
|
75
|
+
/** The original item from the index. */
|
|
76
|
+
item: T;
|
|
77
|
+
/** Per-field match ranges for rendering highlighted snippets. Empty when query is empty. */
|
|
78
|
+
matches: FieldMatch<keyof T & string>[];
|
|
79
|
+
/**
|
|
80
|
+
* Weighted Dice similarity score in `[0, 1]`.
|
|
81
|
+
* `1` when query is empty (all items returned with full score).
|
|
82
|
+
*/
|
|
83
|
+
score: number;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* A text fragment produced by `highlight()` or `highlightField()`.
|
|
87
|
+
* `text` is unescaped, original field content — see `highlight()`'s JSDoc before
|
|
88
|
+
* rendering it as HTML.
|
|
89
|
+
*/
|
|
90
|
+
export type HighlightPart = {
|
|
91
|
+
/** Whether this fragment overlapped a match range. */
|
|
92
|
+
highlighted: boolean;
|
|
93
|
+
/** Original text of this fragment. */
|
|
94
|
+
text: string;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Reactive search state returned by `createSearch()`.
|
|
98
|
+
* Dispose when done to release all reactive subscriptions.
|
|
99
|
+
*/
|
|
100
|
+
export type SearchState<T> = {
|
|
101
|
+
[Symbol.dispose](): void;
|
|
102
|
+
/**
|
|
103
|
+
* Resets `query` to `''` and cancels any pending debounce.
|
|
104
|
+
* `results` and `isSearching` are updated synchronously.
|
|
105
|
+
* @throws {ScoutDisposedError} If called after `dispose()`.
|
|
106
|
+
*/
|
|
107
|
+
clear(): void;
|
|
108
|
+
/** `AbortSignal` aborted when `dispose()` is called. Use to tie other lifecycles to this search. */
|
|
109
|
+
readonly disposalSignal: AbortSignal;
|
|
110
|
+
/** Releases all reactive subscriptions created by this search state. */
|
|
111
|
+
dispose(): void;
|
|
112
|
+
/** `true` after `dispose()` has been called. */
|
|
113
|
+
readonly disposed: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* `true` during the debounce window — between when `query` changes and when `results` updates.
|
|
116
|
+
* Always `false` when `debounce` is `0`.
|
|
117
|
+
*/
|
|
118
|
+
readonly isSearching: Computed<boolean>;
|
|
119
|
+
/**
|
|
120
|
+
* Writable signal holding the current search query.
|
|
121
|
+
* Set `.value` to trigger a (debounced) search.
|
|
122
|
+
*/
|
|
123
|
+
readonly query: Signal<string>;
|
|
124
|
+
/**
|
|
125
|
+
* Read-only computed that holds the latest search results.
|
|
126
|
+
* Updated after the debounce delay whenever `query` changes.
|
|
127
|
+
*/
|
|
128
|
+
readonly results: Computed<SearchResult<T>[]>;
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEzD;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAClB,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GAClB;IACE,KAAK,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC;IACvC,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,2CAA2C;AAC3C,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAAI,iBAAiB,GAAG;IACrD,uDAAuD;IACvD,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;CACpC,CAAC;AAEF,yEAAyE;AACzE,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,GAAG;IACpD;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IAClD,wCAAwC;IACxC,KAAK,EAAE,CAAC,CAAC;IACT;;;OAGG;IACH,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;CAC5B,CAAC;AAEF,kDAAkD;AAClD,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAC5B,wCAAwC;IACxC,IAAI,EAAE,CAAC,CAAC;IACR,4FAA4F;IAC5F,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;IACxC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,sDAAsD;IACtD,WAAW,EAAE,OAAO,CAAC;IACrB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;IACzB;;;;OAIG;IACH,KAAK,IAAI,IAAI,CAAC;IACd,oGAAoG;IACpG,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,wEAAwE;IACxE,OAAO,IAAI,IAAI,CAAC;IAChB,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;CAC/C,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vielzeug/scout",
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "Fast fuzzy-search with a trigram index, per-field weighting, match highlighting, and an optional reactive layer",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
9
|
+
"main": "./dist/index.cjs",
|
|
10
|
+
"module": "./dist/index.js",
|
|
11
|
+
"types": "dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
"./devtools": {
|
|
14
|
+
"source": "./src/devtools.ts",
|
|
15
|
+
"types": "./dist/devtools.d.ts",
|
|
16
|
+
"import": "./dist/devtools.js",
|
|
17
|
+
"require": "./dist/devtools.cjs"
|
|
18
|
+
},
|
|
19
|
+
".": {
|
|
20
|
+
"source": "./src/index.ts",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js",
|
|
23
|
+
"require": "./dist/index.cjs"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "vite build && pnpm run build:bundle && pnpm run build:types",
|
|
28
|
+
"build:types": "tsc -p tsconfig.declarations.json",
|
|
29
|
+
"fix": "eslint --fix src",
|
|
30
|
+
"lint": "eslint src",
|
|
31
|
+
"prepublishOnly": "pnpm run build",
|
|
32
|
+
"test": "vitest",
|
|
33
|
+
"build:bundle": "vite build --config vite.bundle.config.ts"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public",
|
|
37
|
+
"registry": "https://registry.npmjs.org/"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@vielzeug/ripple": "workspace:*"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^26.1.0",
|
|
44
|
+
"typescript": "~6.0.3",
|
|
45
|
+
"vite": "^8.1.3",
|
|
46
|
+
"vitest": "^4.1.9"
|
|
47
|
+
}
|
|
48
|
+
}
|