okf-search-native 0.4.0 → 0.5.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 CHANGED
@@ -1,13 +1,9 @@
1
1
  # `okf-search-native`
2
2
 
3
3
  Search [Open Knowledge Format (OKF)](https://github.com/GoogleCloudPlatform/open-knowledge-format)
4
- collections at native speed from Node.js. `okf-search-native` builds an in-memory
5
- index with Rust and Tantivy and returns the best matching section from each
6
- document.
7
-
8
- Use the package root for Markdown files or strings. Most users should start
9
- there. Use `okf-search-native/prepared` only when your application already
10
- produces prepared OKF documents.
4
+ Markdown collections at native speed from Node.js, powered by Rust and Tantivy.
5
+ Get the best matching section from each document, with its source path, line
6
+ numbers, and snippet.
11
7
 
12
8
  ## Install
13
9
 
@@ -15,183 +11,174 @@ produces prepared OKF documents.
15
11
  npm install okf-search-native
16
12
  ```
17
13
 
18
- The package requires Node.js `>=22.19.0` and includes TypeScript declarations.
19
- See [Requirements and tested platforms](#requirements-and-tested-platforms) for
20
- the available native artifacts.
14
+ Requires Node.js `>=22.19.0`. Includes TypeScript declarations and native
15
+ binaries for macOS x64/arm64 and Linux x64 (glibc >= 2.17); Windows x64 is
16
+ experimental. Browsers and Alpine/musl are not supported.
17
+ See the [full platform list](https://github.com/robhowley/okf-search/blob/main/packages/okf-search-native/API.md#requirements-and-tested-platforms).
21
18
 
22
- ## Raw Markdown API
19
+ ## Search a collection
23
20
 
24
- `createOkfSearch(documents)` synchronously indexes Markdown already in memory.
25
- `openOkf(root)` recursively reads lowercase `.md` files from a Node.js
26
- directory. Files named exactly `index.md` or `log.md` are reserved and are not
27
- indexed.
21
+ Given a directory of OKF Markdown files at `./knowledge`:
28
22
 
29
23
  ```js
30
- import {
31
- createOkfSearch,
32
- openOkf,
33
- validateOkfDocument,
34
- } from "okf-search-native";
35
-
36
- const document = {
37
- path: "notes/memory.md",
38
- markdown: "---\ntype: note\n---\nMemory safety matters.\n",
39
- };
24
+ import { openOkf } from "okf-search-native";
40
25
 
41
- const validation = validateOkfDocument(document);
42
- const index = createOkfSearch([document]);
43
- const hits = index.search("memory", { limit: 10, fields: ["body"] });
44
- const stats = index.indexStats();
26
+ const index = await openOkf("./knowledge");
27
+ const hits = index.search("rollback deployment");
45
28
 
46
- const directoryIndex = await openOkf("./knowledge");
47
- directoryIndex.ingest({
48
- path: "notes/new.md",
49
- markdown: "---\ntype: note\n---\nNew material.\n",
50
- });
51
- directoryIndex.remove("notes/new.md");
29
+ for (const hit of hits) {
30
+ console.log(hit.path, hit.headingPath, hit.snippet);
31
+ }
52
32
  ```
53
33
 
54
- Both constructors return an in-memory search handle. `ingest` adds or replaces
55
- one document after successful validation. `remove` changes only the current
56
- index, not its source file. Reopening a directory rebuilds the index from the
57
- files on disk.
34
+ To try this with one document, save the following as
35
+ `knowledge/runbooks/deployment.md` before running the example:
58
36
 
59
- ### Search behavior
37
+ ```markdown
38
+ ---
39
+ type: runbook
40
+ ---
41
+ # Deployment
60
42
 
61
- Search supports any or all term matching, field selection and boosts, fuzzy
62
- matching, final-term prefix matching, and filters for OKF type, tags, status,
63
- trust tier, staleness, and conformance.
43
+ ## Rollback
64
44
 
65
- Results contain at most one hit per document. Each hit represents its
66
- highest-ranked matching section and includes the document path, heading path,
67
- line range, matched fields, and snippet. The handle also provides `listTypes()`
68
- and `listDegradedDocuments()` for inspecting the current collection.
69
-
70
- ### Index statistics
45
+ To rollback a deployment, restore the previous release and check service health.
46
+ ```
71
47
 
72
- `indexStats()` returns a detached, recursively frozen snapshot:
48
+ The result points to the rollback section (selected fields shown):
73
49
 
74
- ```ts
50
+ ```js
75
51
  {
76
- logical: {
77
- documents: {
78
- total: number;
79
- strict: number;
80
- degraded: number;
81
- };
82
- types: readonly {
83
- type: string;
84
- documentCount: number;
85
- }[];
86
- statuses: {
87
- draft: number;
88
- stable: number;
89
- deprecated: number;
90
- unclassified: number;
91
- };
92
- trustTiers: {
93
- unverified: number;
94
- machineConfirmed: number;
95
- humanReviewed: number;
96
- unclassified: number;
97
- };
98
- };
99
- storage: {
100
- kind: "in-memory-index-files";
101
- sizeInBytes: number;
102
- };
52
+ path: "runbooks/deployment.md",
53
+ headingPath: "Deployment > Rollback",
54
+ startLine: 6,
55
+ endLine: 8,
56
+ snippet: "To rollback a deployment, restore the previous release and check service health."
103
57
  }
104
58
  ```
105
59
 
106
- Logical values count documents, not sections, and change only after a successful
107
- `ingest` or `remove`. `types` preserves case and is sorted by type. Missing
108
- effective status or trust-tier metadata counts as `unclassified`.
109
- `sizeInBytes` samples the handle's Tantivy `RamDirectory`; it excludes other
110
- process memory and can change without a logical change.
60
+ Use the path and line numbers to open the source, and the heading and snippet
61
+ to display a preview. Results contain at most one hit per document, ordered by
62
+ relevance. See the [complete result shape](https://github.com/robhowley/okf-search/blob/main/packages/okf-search-native/API.md#results).
63
+
64
+ **Open once and reuse the handle.** Opening reads and indexes the collection
65
+ into memory; every new `openOkf` call rebuilds it. The handle does not watch
66
+ files, write changes to disk, or persist the index. Reopen to pick up filesystem
67
+ changes.
68
+
69
+ `openOkf` recursively reads lowercase `.md` files, excluding files named exactly
70
+ `index.md` or `log.md`.
71
+
72
+ ## Already have Markdown strings?
73
+
74
+ Use `createOkfSearch` instead of reading a directory. It builds the same kind
75
+ of handle synchronously:
76
+
77
+ ```js
78
+ import { createOkfSearch } from "okf-search-native";
79
+
80
+ const index = createOkfSearch([{
81
+ path: "runbooks/deployment.md",
82
+ markdown: "---\ntype: runbook\n---\nTo rollback a deployment, restore the previous release.\n",
83
+ }]);
84
+
85
+ const hits = index.search("rollback deployment");
86
+ ```
87
+
88
+ ## Refine a search
89
+
90
+ Require all query terms and restrict results to runbooks:
111
91
 
112
- ### Validation
92
+ ```js
93
+ index.search("rollback deployment", {
94
+ match: "all",
95
+ where: { types: ["runbook"] },
96
+ });
97
+ ```
113
98
 
114
- `validateOkfDocument` checks one Markdown document without changing an index.
115
- A strict document is valid and indexable. A degraded document remains indexable
116
- and searchable, with diagnostics describing fields that need repair. A document
117
- with a fatal path, parsing, Markdown, or `type` problem is not indexable.
118
- Expected validation failures are returned as diagnostics rather than thrown.
99
+ Enable typo tolerance:
119
100
 
120
- See the [OKF v0.2 specification](https://github.com/GoogleCloudPlatform/open-knowledge-format/blob/ad30107c31c06aec8a7d5636e0d1058118604e6f/SPEC.md)
121
- for the document format and field semantics.
101
+ ```js
102
+ index.search("deploymnt", { fuzzy: true });
103
+ ```
122
104
 
123
- ### Differences from `okf-minisearch`
105
+ By default, searches return up to ten documents, match any query term across
106
+ all searchable fields, and disable fuzzy matching. The final term still
107
+ matches prefixes when it has at least three characters: `"deploy"` can match
108
+ `"deployment"`, even with `fuzzy: false`.
124
109
 
125
- The native backend uses Tantivy, so its ranking, scores, snippets, and fuzzy
126
- candidates can differ from `okf-minisearch`. Browser use is not supported.
127
- `autoSuggest` is also unsupported and throws an `OkfError` with code
128
- `ERR_OKF_UNSUPPORTED`.
110
+ Use `limit` to change the result count and `fields` to restrict where terms
111
+ match. Filters also support tags, status, trust tier, staleness, and conformance.
112
+ See [search options and defaults](https://github.com/robhowley/okf-search/blob/main/packages/okf-search-native/API.md#search)
113
+ for field boosts, filter combinations, and detailed matching rules.
129
114
 
130
- ## Prepared API
115
+ ## Update the in-memory index
131
116
 
132
- Most users can skip this section. Use the prepared API when another part of
133
- your application already produces `PreparedDocument` values and you want to
134
- pass them directly to the native backend.
117
+ `ingest` adds a document or replaces the document with the same path. `remove`
118
+ returns whether the document was present. Neither operation changes files:
135
119
 
136
120
  ```js
137
- import { NativeOkfSearch } from "okf-search-native/prepared";
121
+ index.ingest({
122
+ path: "runbooks/restart.md",
123
+ markdown: "---\ntype: runbook\n---\nRestart the service after draining active requests.\n",
124
+ });
138
125
 
139
- const index = NativeOkfSearch.fromPrepared(preparedDocuments);
140
- const hits = index.search("memory", { limit: 10, fields: ["body"] });
141
- const stats = index.indexStats();
142
- index.ingestPrepared(preparedDocument);
143
- index.removeDocument("docs/old");
126
+ index.remove("runbooks/restart.md");
144
127
  ```
145
128
 
146
- `fromPrepared` builds an index from prepared documents. `ingestPrepared`
147
- replaces every indexed section owned by one document, and `removeDocument`
148
- removes them together. `PreparedDocument` contains document-wide metadata once;
149
- each `PreparedSection` contains only its ID, heading path, text, and line
150
- bounds. The DTO declarations are exported from `okf-search-native/prepared`,
151
- not from the package root. Its `indexStats()` result has the shape above but is
152
- a mutable N-API DTO; the package-root adapter returns the frozen copy.
129
+ Use relative `.md` paths, such as `runbooks/restart.md`. If preparation of a
130
+ replacement fails, the existing document remains searchable.
131
+ See [update results and path rules](https://github.com/robhowley/okf-search/blob/main/packages/okf-search-native/API.md#update-and-reuse-the-handle).
153
132
 
154
- ## Requirements and tested platforms
133
+ ## Check documents and handle failures
155
134
 
156
- Linux x64 and macOS x64/arm64 are fully supported. Windows x64 is experimental.
157
- All targets require Node.js `>=22.19.0` and use Node-API 8.
135
+ Documents with valid OKF metadata are **strict**. Some metadata problems make
136
+ a document **degraded**: it remains searchable, with diagnostics explaining
137
+ what needs repair. Fatal problems, such as missing required `type` metadata,
138
+ prevent indexing.
158
139
 
159
- | Platform | Native artifact |
160
- | --- | --- |
161
- | macOS x64 | `okf-search-native.darwin-x64.node` |
162
- | macOS arm64 | `okf-search-native.darwin-arm64.node` |
163
- | Windows x64 (MSVC) | `okf-search-native.win32-x64-msvc.node` |
164
- | Linux x64 (glibc >= 2.17) | `okf-search-native.linux-x64-gnu.node` |
140
+ Constructors and `ingest` validate automatically. To inspect diagnostics before
141
+ indexing, use `validateOkfDocument`:
165
142
 
166
- Linux musl/Alpine, Linux arm64, Windows arm64, Bun, Deno, browsers, and other
167
- Node versions are not covered by this matrix.
143
+ ```js
144
+ import { validateOkfDocument } from "okf-search-native";
168
145
 
169
- ## Development
146
+ const input = {
147
+ path: "runbooks/draft.md",
148
+ markdown: "---\ntype: runbook\nstatus: not-a-status\n---\nDraft deployment instructions.\n",
149
+ };
150
+ const validation = validateOkfDocument(input);
170
151
 
171
- Development requires Rust `1.88.0`:
152
+ for (const { path, field, message } of validation.errors) {
153
+ console.warn(path, field, message);
154
+ }
172
155
 
173
- ```sh
174
- pnpm install
175
- pnpm --filter okf-search-native run build
176
- pnpm --filter okf-search-native run check:rust
177
- pnpm --filter okf-search-native run test
156
+ if (validation.isIndexable) {
157
+ index.ingest(input); // Degraded documents can still be indexed.
158
+ }
178
159
  ```
179
160
 
180
- ### Build output
161
+ Validation returns expected document problems as diagnostics. Indexing rejects
162
+ fatal document problems with `OkfError`; `openOkf` also rejects unreadable
163
+ files. Invalid search options throw `TypeError`. An `ERR_OKF_INDEX_UNUSABLE`
164
+ error means the handle must be rebuilt, not retried.
165
+ See [validation outcomes and error handling](https://github.com/robhowley/okf-search/blob/main/packages/okf-search-native/API.md#validation-and-failures).
166
+
167
+ To inspect an existing collection:
181
168
 
182
- `napi build` generates `native.cjs`, `native.d.cts`, and the host `.node`
183
- artifact. The package facade build writes `dist/index.cjs`, `dist/index.mjs`,
184
- `dist/index.d.cts`, `dist/index.d.mts`, and `dist/index.d.ts`. Generated native
185
- loader names are internal and are not package-root exports.
169
+ ```js
170
+ console.log(index.indexStats().logical.documents.total);
171
+ console.log(index.listTypes());
172
+ console.log(index.listDegradedDocuments());
173
+ ```
186
174
 
187
- ### Release artifacts
175
+ ## Reference and development
188
176
 
189
- For multi-target candidate assembly, copy the four tested `.node` files into
190
- the package root, then run `pnpm run verify:release-artifacts`. The verifier
191
- derives the required artifact names from the checked-in target list and
192
- rejects missing or extra native files. CI also uses its `glibc <artifact>` mode
193
- to reject Linux addons that import symbols newer than `GLIBC_2.17`.
177
+ - [API reference](https://github.com/robhowley/okf-search/blob/main/packages/okf-search-native/API.md): options, return values, errors, and index statistics.
178
+ - [Prepared API](https://github.com/robhowley/okf-search/blob/main/packages/okf-search-native/API.md#advanced-prepared-api): for applications that already produce prepared documents.
179
+ - [Backend differences](https://github.com/robhowley/okf-search/blob/main/packages/okf-search-native/API.md#backend-differences): Tantivy ranking differs from `okf-minisearch`; `autoSuggest` is unsupported.
180
+ - [Development](https://github.com/robhowley/okf-search/blob/main/packages/okf-search-native/DEVELOPMENT.md): local builds, tests, and release artifacts.
194
181
 
195
182
  ## License
196
183
 
197
- [MIT](../../LICENSE)
184
+ [MIT](https://github.com/robhowley/okf-search/blob/main/packages/okf-search-native/LICENSE)