dsh-locator 0.7.0 → 0.7.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/CHANGELOG.md +30 -0
- package/README-es.md +35 -5
- package/README-hi.md +33 -5
- package/README-pt.md +31 -5
- package/README.en.md +32 -4
- package/README.md +25 -5
- package/client.js +117 -17
- package/cordis.patch.yml +13 -0
- package/lib/config.d.ts +20 -0
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +38 -4
- package/lib/config.js.map +1 -1
- package/lib/content-search-worker.d.ts +8 -0
- package/lib/content-search-worker.d.ts.map +1 -0
- package/lib/content-search-worker.js +54 -0
- package/lib/content-search-worker.js.map +1 -0
- package/lib/content-search.d.ts +15 -0
- package/lib/content-search.d.ts.map +1 -0
- package/lib/content-search.js +38 -0
- package/lib/content-search.js.map +1 -0
- package/lib/content.d.ts +70 -4
- package/lib/content.d.ts.map +1 -1
- package/lib/content.js +423 -77
- package/lib/content.js.map +1 -1
- package/lib/find.d.ts +1 -1
- package/lib/find.d.ts.map +1 -1
- package/lib/find.js +8 -3
- package/lib/find.js.map +1 -1
- package/lib/http.d.ts +1 -1
- package/lib/http.d.ts.map +1 -1
- package/lib/http.js +4 -2
- package/lib/http.js.map +1 -1
- package/lib/index.d.ts +5 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +102 -27
- package/lib/index.js.map +1 -1
- package/lib/reindex.d.ts +1 -1
- package/lib/reindex.d.ts.map +1 -1
- package/lib/reindex.js +2 -1
- package/lib/reindex.js.map +1 -1
- package/package.json +1 -1
- package/src/config.ts +58 -4
- package/src/content-search-worker.ts +52 -0
- package/src/content-search.ts +39 -0
- package/src/content.ts +391 -71
- package/src/find.ts +8 -3
- package/src/http.ts +4 -2
- package/src/index.ts +102 -25
- package/src/reindex.ts +2 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search worker: the FTS5 query runs here so a slow content query can never
|
|
3
|
+
* stall the DSH host's event loop. A read-only connection makes the build's
|
|
4
|
+
* writes in the main thread safe to observe concurrently (WAL).
|
|
5
|
+
* @module dsh-locator/content-search-worker
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { parentPort, workerData } from 'node:worker_threads'
|
|
9
|
+
import { DatabaseSync } from 'node:sqlite'
|
|
10
|
+
import { searchContent } from './content-search.ts'
|
|
11
|
+
import type { ContentHit } from './content.ts'
|
|
12
|
+
|
|
13
|
+
interface Request {
|
|
14
|
+
id: number
|
|
15
|
+
open?: string
|
|
16
|
+
close?: boolean
|
|
17
|
+
query?: string
|
|
18
|
+
limit?: number
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let db: DatabaseSync | null = null
|
|
22
|
+
|
|
23
|
+
function open(path: string): void {
|
|
24
|
+
try { db?.close() } catch { /* ignore */ }
|
|
25
|
+
db = null
|
|
26
|
+
try { db = new DatabaseSync(path, { readOnly: true }) } catch { db = null }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const initial = (workerData as { dbPath?: string } | undefined)?.dbPath
|
|
30
|
+
if (initial !== undefined) open(initial)
|
|
31
|
+
|
|
32
|
+
parentPort?.on('message', (request: Request) => {
|
|
33
|
+
if (request.open !== undefined) {
|
|
34
|
+
open(request.open)
|
|
35
|
+
parentPort?.postMessage({ id: request.id, ok: true })
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
if (request.close === true) {
|
|
39
|
+
try { db?.close() } catch { /* ignore */ }
|
|
40
|
+
db = null
|
|
41
|
+
parentPort?.postMessage({ id: request.id, ok: true })
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
let hits: ContentHit[] = []
|
|
45
|
+
let error = ''
|
|
46
|
+
if (db !== null) {
|
|
47
|
+
try { hits = searchContent(db, request.query ?? '', request.limit ?? 30) } catch (cause) {
|
|
48
|
+
error = cause instanceof Error ? cause.message : String(cause)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
parentPort?.postMessage({ id: request.id, hits, error })
|
|
52
|
+
})
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content FTS5 query shared by the host thread and the search worker.
|
|
3
|
+
* @module dsh-locator/content-search
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { DatabaseSync } from 'node:sqlite'
|
|
7
|
+
import type { ContentHit } from './content.ts'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Run one content query against an open SQLite handle.
|
|
11
|
+
* @param db - open database (read-only in the worker).
|
|
12
|
+
* @param query - user query; shorter than three characters falls back to LIKE.
|
|
13
|
+
* @param limit - maximum hits.
|
|
14
|
+
* @returns hits, ordered by relevance.
|
|
15
|
+
*/
|
|
16
|
+
export function searchContent(db: DatabaseSync, query: string, limit: number): ContentHit[] {
|
|
17
|
+
const text = query.trim()
|
|
18
|
+
if (text === '') return []
|
|
19
|
+
const capped = Math.max(1, Math.min(100, limit))
|
|
20
|
+
let rows: Array<Record<string, unknown>>
|
|
21
|
+
if ([...text].length < 3) {
|
|
22
|
+
rows = db.prepare(`SELECT kind, path, title, session_id, message_id, body, 0 AS score
|
|
23
|
+
FROM docs WHERE body LIKE '%' || ? || '%' LIMIT ?`).all(text, capped) as Array<Record<string, unknown>>
|
|
24
|
+
} else {
|
|
25
|
+
const match = text.split(/\s+/).filter(Boolean).map(term => '"' + term.replace(/"/g, '') + '"').join(' AND ')
|
|
26
|
+
rows = db.prepare(`SELECT kind, path, title, session_id, message_id,
|
|
27
|
+
snippet(docs, 0, char(1), char(2), '…', 16) AS snippet, bm25(docs) AS score
|
|
28
|
+
FROM docs WHERE docs MATCH ? ORDER BY score LIMIT ?`).all(match, capped) as Array<Record<string, unknown>>
|
|
29
|
+
}
|
|
30
|
+
return rows.map(row => ({
|
|
31
|
+
kind: row.kind === 'session' ? 'session' : 'file',
|
|
32
|
+
path: String(row.path ?? ''),
|
|
33
|
+
title: String(row.title ?? ''),
|
|
34
|
+
snippet: String(row.snippet ?? row.body ?? '').replace(/[\u0001\u0002]/g, ''),
|
|
35
|
+
...(row.session_id ? { sessionId: String(row.session_id) } : {}),
|
|
36
|
+
...(row.message_id ? { messageId: String(row.message_id) } : {}),
|
|
37
|
+
score: Number(row.score ?? 0),
|
|
38
|
+
}))
|
|
39
|
+
}
|