diffwiki-core 0.3.0 → 0.4.0-rc.202607220518.0ade9d3
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/dist/chunk-I3PPUXYY.js +474 -0
- package/dist/events-656CR64Q.js +6 -0
- package/dist/index.cjs +1279 -149
- package/dist/index.d.cts +216 -15
- package/dist/index.d.ts +216 -15
- package/dist/index.js +779 -184
- package/package.json +11 -1
package/dist/index.d.cts
CHANGED
|
@@ -12,6 +12,7 @@ interface Registry {
|
|
|
12
12
|
}
|
|
13
13
|
interface Config {
|
|
14
14
|
defaultCollection?: string;
|
|
15
|
+
defaultSearch?: string;
|
|
15
16
|
}
|
|
16
17
|
interface Article {
|
|
17
18
|
title: string;
|
|
@@ -25,6 +26,107 @@ interface RepoConfig {
|
|
|
25
26
|
/** Path to the wiki directory, relative to the repo root. */
|
|
26
27
|
path: string;
|
|
27
28
|
}
|
|
29
|
+
/** A node in a collection's article tree. Branches have `children`; leaves have `slug`. */
|
|
30
|
+
interface ArticleNode {
|
|
31
|
+
/** Segment label — dir name for branches, filename-without-ext for leaves. */
|
|
32
|
+
name: string;
|
|
33
|
+
/** Display title — frontmatter `title` (leaf) or the folder's index title, else `name`. */
|
|
34
|
+
title?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Path within the collection, without extension, e.g. "guide/setup". Set on
|
|
37
|
+
* leaves (the article) and on branches (the folder, navigable to its index).
|
|
38
|
+
*/
|
|
39
|
+
slug?: string;
|
|
40
|
+
/** Branch only: nested nodes. */
|
|
41
|
+
children?: ArticleNode[];
|
|
42
|
+
}
|
|
43
|
+
/** A resolved article's content, returned by `readArticle`. */
|
|
44
|
+
interface ArticleContent {
|
|
45
|
+
coll: string;
|
|
46
|
+
slug: string;
|
|
47
|
+
title: string;
|
|
48
|
+
tags: string[];
|
|
49
|
+
/** Frontmatter-stripped body (md/mdx). */
|
|
50
|
+
body: string;
|
|
51
|
+
/** Absolute path to the file on disk. */
|
|
52
|
+
path: string;
|
|
53
|
+
}
|
|
54
|
+
type PluginKind = 'search';
|
|
55
|
+
declare const NATIVE_ENGINE = "native";
|
|
56
|
+
interface QueryOptions {
|
|
57
|
+
engine?: string;
|
|
58
|
+
collection?: string;
|
|
59
|
+
type?: string;
|
|
60
|
+
limit?: number;
|
|
61
|
+
}
|
|
62
|
+
interface QueryHit {
|
|
63
|
+
collection: string;
|
|
64
|
+
path: string;
|
|
65
|
+
title: string;
|
|
66
|
+
tags: string[];
|
|
67
|
+
snippet?: string;
|
|
68
|
+
score?: number;
|
|
69
|
+
docid?: string;
|
|
70
|
+
}
|
|
71
|
+
type DiagnosticLevel = 'ok' | 'warn' | 'error';
|
|
72
|
+
interface Diagnostic {
|
|
73
|
+
level: DiagnosticLevel;
|
|
74
|
+
message: string;
|
|
75
|
+
}
|
|
76
|
+
interface PluginRecord {
|
|
77
|
+
name: string;
|
|
78
|
+
kind: PluginKind;
|
|
79
|
+
command: string[];
|
|
80
|
+
version?: string;
|
|
81
|
+
enabled: boolean;
|
|
82
|
+
managed?: boolean;
|
|
83
|
+
}
|
|
84
|
+
interface PluginRegistryFile {
|
|
85
|
+
version: number;
|
|
86
|
+
plugins: PluginRecord[];
|
|
87
|
+
}
|
|
88
|
+
interface PluginCapabilities {
|
|
89
|
+
searchTypes: string[];
|
|
90
|
+
collectionFilter: boolean;
|
|
91
|
+
hooks: boolean;
|
|
92
|
+
setup: boolean;
|
|
93
|
+
}
|
|
94
|
+
interface PluginReadiness {
|
|
95
|
+
toolInstalled: boolean;
|
|
96
|
+
modelsPresent: boolean;
|
|
97
|
+
indexBuilt: boolean;
|
|
98
|
+
docsIndexed: number;
|
|
99
|
+
embeddingsPending: number;
|
|
100
|
+
firstSearchCost: 'instant' | 'model-load' | 'model-download';
|
|
101
|
+
}
|
|
102
|
+
interface PluginHealth {
|
|
103
|
+
ready: boolean;
|
|
104
|
+
readiness?: PluginReadiness;
|
|
105
|
+
diagnostics: Diagnostic[];
|
|
106
|
+
}
|
|
107
|
+
interface SearchMode {
|
|
108
|
+
plugin: string;
|
|
109
|
+
type: string;
|
|
110
|
+
label: string;
|
|
111
|
+
}
|
|
112
|
+
type PluginEvent = 'collection-added' | 'collection-removed' | 'article-created' | 'article-updated' | 'article-removed';
|
|
113
|
+
interface SearchProvider {
|
|
114
|
+
name: string;
|
|
115
|
+
capabilities: PluginCapabilities;
|
|
116
|
+
setup(collections: CollectionEntry[], opts?: {
|
|
117
|
+
embed?: boolean;
|
|
118
|
+
prefetchModels?: boolean;
|
|
119
|
+
}): Promise<{
|
|
120
|
+
ready: boolean;
|
|
121
|
+
}>;
|
|
122
|
+
reindex(collections: CollectionEntry[], opts?: {
|
|
123
|
+
embed?: boolean;
|
|
124
|
+
}): Promise<number>;
|
|
125
|
+
search(term: string, collections: CollectionEntry[], opts?: QueryOptions): Promise<QueryHit[]>;
|
|
126
|
+
notify(event: PluginEvent, collection: string, relPath: string | undefined, collections: CollectionEntry[]): Promise<void>;
|
|
127
|
+
health(collections: CollectionEntry[]): Promise<PluginHealth>;
|
|
128
|
+
close(): Promise<void>;
|
|
129
|
+
}
|
|
28
130
|
|
|
29
131
|
/** Base class for all expected, user-facing diffwiki failures. */
|
|
30
132
|
declare class DiffwikiError extends Error {
|
|
@@ -45,6 +147,8 @@ declare class ArticleNotFoundError extends DiffwikiError {
|
|
|
45
147
|
declare class InvalidTargetError extends DiffwikiError {
|
|
46
148
|
constructor(target: string, expected: string);
|
|
47
149
|
}
|
|
150
|
+
declare class PluginError extends DiffwikiError {
|
|
151
|
+
}
|
|
48
152
|
|
|
49
153
|
/** Root of all global diffwiki state. Overridable via DIFFWIKI_HOME (used by tests). */
|
|
50
154
|
declare function resolveHome(): string;
|
|
@@ -52,6 +156,8 @@ declare function registryPath(): string;
|
|
|
52
156
|
declare function configPath(): string;
|
|
53
157
|
declare function collectionsDir(): string;
|
|
54
158
|
declare function collectionDir(name: string): string;
|
|
159
|
+
declare function pluginsDir(): string;
|
|
160
|
+
declare function pluginsRegistryPath(): string;
|
|
55
161
|
|
|
56
162
|
declare function readConfig(): Promise<Config>;
|
|
57
163
|
declare function writeConfig(config: Config): Promise<void>;
|
|
@@ -123,23 +229,118 @@ interface InitOptions {
|
|
|
123
229
|
}
|
|
124
230
|
declare function initRepoWiki(opts: InitOptions): Promise<CollectionEntry>;
|
|
125
231
|
|
|
126
|
-
interface QueryHit {
|
|
127
|
-
collection: string;
|
|
128
|
-
path: string;
|
|
129
|
-
title: string;
|
|
130
|
-
tags: string[];
|
|
131
|
-
}
|
|
132
232
|
/**
|
|
133
|
-
*
|
|
134
|
-
*
|
|
233
|
+
* Built-in JS-native search: BM25-ranked full-text search over an article's
|
|
234
|
+
* title, body, tags, and collection name -- across every registered collection's
|
|
235
|
+
* ABSOLUTE registry path (so in-repo wikis outside ~/.diffwiki are searched too).
|
|
236
|
+
* No `find`/OS shelling -- cross-platform and dependency-free.
|
|
237
|
+
*
|
|
238
|
+
* When `term` is empty, returns all articles unranked (no score) to preserve
|
|
239
|
+
* the "browse all" behavior.
|
|
240
|
+
*/
|
|
241
|
+
declare function nativeSearch(term: string, collections: CollectionEntry[], collection?: string): Promise<QueryHit[]>;
|
|
242
|
+
/**
|
|
243
|
+
* Resolve the engine + type that `query()` would use when the caller passes no
|
|
244
|
+
* explicit engine/type. Mirrors `resolveDefaultEngine`'s precedence and, when the
|
|
245
|
+
* resolved engine is a plugin, prefers the type from `config.defaultSearch`'s
|
|
246
|
+
* `:type` suffix (if that plugin advertises it) else the plugin's first advertised
|
|
247
|
+
* search type. The native engine always resolves to `basic`. UIs use this to
|
|
248
|
+
* pre-select the search-mode dropdown to the engine actually run server-side.
|
|
135
249
|
*/
|
|
136
|
-
declare function
|
|
250
|
+
declare function resolveDefaultSearchMode(): Promise<{
|
|
251
|
+
engine: string;
|
|
252
|
+
type: string;
|
|
253
|
+
}>;
|
|
254
|
+
declare function query(term: string, opts?: QueryOptions): Promise<QueryHit[]>;
|
|
137
255
|
|
|
138
|
-
type DiagnosticLevel = 'ok' | 'warn' | 'error';
|
|
139
|
-
interface Diagnostic {
|
|
140
|
-
level: DiagnosticLevel;
|
|
141
|
-
message: string;
|
|
142
|
-
}
|
|
143
256
|
declare function doctor(): Promise<Diagnostic[]>;
|
|
144
257
|
|
|
145
|
-
|
|
258
|
+
/**
|
|
259
|
+
* Build a nested ArticleNode[] from a flat list of relative file paths.
|
|
260
|
+
* Pure — no I/O. Directories become branches; files become leaves whose `slug`
|
|
261
|
+
* is the relative path without extension. Dirs-first, then alpha (case-insensitive).
|
|
262
|
+
*/
|
|
263
|
+
declare function buildArticleTree(relPaths: string[]): ArticleNode[];
|
|
264
|
+
/**
|
|
265
|
+
* List the article tree of a collection. Walks the collection's registered
|
|
266
|
+
* `entry.path` — so collections living OUTSIDE `~/.diffwiki/collections`
|
|
267
|
+
* (e.g. in-repo wikis registered via `diffwiki init`) work unchanged.
|
|
268
|
+
*/
|
|
269
|
+
declare function listArticleTree(coll: string): Promise<ArticleNode[]>;
|
|
270
|
+
/**
|
|
271
|
+
* Read and resolve a single article by collection + slug (relative path without
|
|
272
|
+
* extension). Tries `.mdx` then `.md`, guards against path traversal, and splits
|
|
273
|
+
* frontmatter. Throws CollectionNotFoundError / ArticleNotFoundError / InvalidTargetError.
|
|
274
|
+
*/
|
|
275
|
+
declare function readArticle(coll: string, slug: string): Promise<ArticleContent>;
|
|
276
|
+
|
|
277
|
+
/** A heading extracted for the table of contents (h2/h3). */
|
|
278
|
+
interface TocItem {
|
|
279
|
+
slug: string;
|
|
280
|
+
text: string;
|
|
281
|
+
depth: number;
|
|
282
|
+
}
|
|
283
|
+
/** The result of rendering an article body to HTML. */
|
|
284
|
+
interface RenderedArticle {
|
|
285
|
+
/** Fully-rendered, Shiki-highlighted HTML — mounted directly on the client (no eval). */
|
|
286
|
+
html: string;
|
|
287
|
+
/** h2/h3 headings collected during render, in document order. */
|
|
288
|
+
toc: TocItem[];
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Render an article body (markdown) to Shiki-highlighted HTML plus its table of
|
|
292
|
+
* contents. Runs entirely server-side; the client mounts the HTML directly with
|
|
293
|
+
* no `eval`/`new Function`, so it works under a strict CSP. Code is highlighted
|
|
294
|
+
* here (dual github-light/github-dark via CSS variables); mermaid fences are
|
|
295
|
+
* marked for client rendering.
|
|
296
|
+
*/
|
|
297
|
+
declare function renderArticle(body: string): Promise<RenderedArticle>;
|
|
298
|
+
|
|
299
|
+
declare function readPluginRegistry(): Promise<PluginRegistryFile>;
|
|
300
|
+
declare function writePluginRegistry(registry: PluginRegistryFile): Promise<void>;
|
|
301
|
+
/** Insert or replace the plugin record with the same name. */
|
|
302
|
+
declare function upsertPlugin(record: PluginRecord): Promise<void>;
|
|
303
|
+
declare function deregisterPlugin(name: string): Promise<void>;
|
|
304
|
+
declare function listEnabledPlugins(kind: PluginKind): Promise<PluginRecord[]>;
|
|
305
|
+
declare function findEnabledPlugin(kind: PluginKind, name?: string): Promise<PluginRecord | undefined>;
|
|
306
|
+
|
|
307
|
+
declare function spawnPluginClient(record: PluginRecord): Promise<SearchProvider>;
|
|
308
|
+
|
|
309
|
+
declare function loadSearchProvider(name?: string): Promise<SearchProvider | null>;
|
|
310
|
+
declare function listSearchModes(): Promise<SearchMode[]>;
|
|
311
|
+
|
|
312
|
+
/** Create the managed plugin root (an isolated npm project) and return its path. */
|
|
313
|
+
declare function ensurePluginRoot(): Promise<string>;
|
|
314
|
+
/**
|
|
315
|
+
* Install an npm spec into the managed root, register the discovered search bin,
|
|
316
|
+
* then (unless opts.setup === false) run the plugin's end-to-end `setup` so the
|
|
317
|
+
* user lands on a warm, working search. A setup failure does not unwind the
|
|
318
|
+
* install -- the record is saved and `doctor` surfaces the problem later.
|
|
319
|
+
*/
|
|
320
|
+
declare function installPlugin(spec: string, opts?: {
|
|
321
|
+
setup?: boolean;
|
|
322
|
+
prefetchModels?: boolean;
|
|
323
|
+
}): Promise<PluginRecord>;
|
|
324
|
+
/**
|
|
325
|
+
* Register an already-present executable as a search plugin. Validates by spawning
|
|
326
|
+
* it (handshake + capability check) and runs its `setup` best-effort.
|
|
327
|
+
*/
|
|
328
|
+
declare function registerPlugin(name: string, command: string[]): Promise<PluginRecord>;
|
|
329
|
+
/** Uninstall a managed plugin's package and deregister it. */
|
|
330
|
+
declare function removePlugin(name: string): Promise<void>;
|
|
331
|
+
/** List every registered plugin, marking whether it currently spawns + handshakes. */
|
|
332
|
+
declare function listPlugins(): Promise<Array<PluginRecord & {
|
|
333
|
+
spawnable: boolean;
|
|
334
|
+
}>>;
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Fire a lifecycle hook at the active search plugin -- best-effort and
|
|
338
|
+
* non-blocking. Callers invoke this as `void emitPluginEvent(...)` and never
|
|
339
|
+
* await it, so a slow or absent plugin can neither stall nor fail a content
|
|
340
|
+
* mutation. Every error is swallowed; the lazy mtime-staleness reindex on
|
|
341
|
+
* `search` remains the correctness guarantee, so a dropped hook only costs a
|
|
342
|
+
* later lazy rebuild, never wrong results.
|
|
343
|
+
*/
|
|
344
|
+
declare function emitPluginEvent(event: PluginEvent, collection: string, relPath?: string): Promise<void>;
|
|
345
|
+
|
|
346
|
+
export { type Article, type ArticleContent, type ArticleNode, ArticleNotFoundError, type CollectionEntry, CollectionExistsError, CollectionNotFoundError, type CollectionType, type Config, type Diagnostic, type DiagnosticLevel, DiffwikiError, type InitOptions, InvalidTargetError, NATIVE_ENGINE, NoDefaultCollectionError, type ParsedArticle, type PluginCapabilities, PluginError, type PluginEvent, type PluginHealth, type PluginKind, type PluginReadiness, type PluginRecord, type PluginRegistryFile, type QueryHit, type QueryOptions, REPO_CONFIG_FILE, type Registry, type RenderedArticle, type RepoConfig, type SearchMode, type SearchProvider, type SerializableArticle, type TocItem, addTags, buildArticleTree, collectionDir, collectionsDir, configPath, createArticle, createCollection, deregisterPlugin, doctor, emitPluginEvent, ensurePluginRoot, findCollection, findEnabledPlugin, getConfigValue, initRepoWiki, installPlugin, listArticleTree, listCollections, listEnabledPlugins, listPlugins, listSearchModes, loadSearchProvider, nativeSearch, parseAddTarget, parseArticle, parsePathTarget, pluginsDir, pluginsRegistryPath, query, readArticle, readConfig, readPluginRegistry, readRegistry, readRepoConfig, registerCollection, registerPlugin, registryPath, removeArticle, removeCollection, removePlugin, removeTags, renderArticle, resolveDefaultSearchMode, resolveHome, serializeArticle, setConfigValue, setTags, slugify, spawnPluginClient, unregisterCollection, updateArticleBody, upsertPlugin, writeConfig, writePluginRegistry, writeRegistry };
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ interface Registry {
|
|
|
12
12
|
}
|
|
13
13
|
interface Config {
|
|
14
14
|
defaultCollection?: string;
|
|
15
|
+
defaultSearch?: string;
|
|
15
16
|
}
|
|
16
17
|
interface Article {
|
|
17
18
|
title: string;
|
|
@@ -25,6 +26,107 @@ interface RepoConfig {
|
|
|
25
26
|
/** Path to the wiki directory, relative to the repo root. */
|
|
26
27
|
path: string;
|
|
27
28
|
}
|
|
29
|
+
/** A node in a collection's article tree. Branches have `children`; leaves have `slug`. */
|
|
30
|
+
interface ArticleNode {
|
|
31
|
+
/** Segment label — dir name for branches, filename-without-ext for leaves. */
|
|
32
|
+
name: string;
|
|
33
|
+
/** Display title — frontmatter `title` (leaf) or the folder's index title, else `name`. */
|
|
34
|
+
title?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Path within the collection, without extension, e.g. "guide/setup". Set on
|
|
37
|
+
* leaves (the article) and on branches (the folder, navigable to its index).
|
|
38
|
+
*/
|
|
39
|
+
slug?: string;
|
|
40
|
+
/** Branch only: nested nodes. */
|
|
41
|
+
children?: ArticleNode[];
|
|
42
|
+
}
|
|
43
|
+
/** A resolved article's content, returned by `readArticle`. */
|
|
44
|
+
interface ArticleContent {
|
|
45
|
+
coll: string;
|
|
46
|
+
slug: string;
|
|
47
|
+
title: string;
|
|
48
|
+
tags: string[];
|
|
49
|
+
/** Frontmatter-stripped body (md/mdx). */
|
|
50
|
+
body: string;
|
|
51
|
+
/** Absolute path to the file on disk. */
|
|
52
|
+
path: string;
|
|
53
|
+
}
|
|
54
|
+
type PluginKind = 'search';
|
|
55
|
+
declare const NATIVE_ENGINE = "native";
|
|
56
|
+
interface QueryOptions {
|
|
57
|
+
engine?: string;
|
|
58
|
+
collection?: string;
|
|
59
|
+
type?: string;
|
|
60
|
+
limit?: number;
|
|
61
|
+
}
|
|
62
|
+
interface QueryHit {
|
|
63
|
+
collection: string;
|
|
64
|
+
path: string;
|
|
65
|
+
title: string;
|
|
66
|
+
tags: string[];
|
|
67
|
+
snippet?: string;
|
|
68
|
+
score?: number;
|
|
69
|
+
docid?: string;
|
|
70
|
+
}
|
|
71
|
+
type DiagnosticLevel = 'ok' | 'warn' | 'error';
|
|
72
|
+
interface Diagnostic {
|
|
73
|
+
level: DiagnosticLevel;
|
|
74
|
+
message: string;
|
|
75
|
+
}
|
|
76
|
+
interface PluginRecord {
|
|
77
|
+
name: string;
|
|
78
|
+
kind: PluginKind;
|
|
79
|
+
command: string[];
|
|
80
|
+
version?: string;
|
|
81
|
+
enabled: boolean;
|
|
82
|
+
managed?: boolean;
|
|
83
|
+
}
|
|
84
|
+
interface PluginRegistryFile {
|
|
85
|
+
version: number;
|
|
86
|
+
plugins: PluginRecord[];
|
|
87
|
+
}
|
|
88
|
+
interface PluginCapabilities {
|
|
89
|
+
searchTypes: string[];
|
|
90
|
+
collectionFilter: boolean;
|
|
91
|
+
hooks: boolean;
|
|
92
|
+
setup: boolean;
|
|
93
|
+
}
|
|
94
|
+
interface PluginReadiness {
|
|
95
|
+
toolInstalled: boolean;
|
|
96
|
+
modelsPresent: boolean;
|
|
97
|
+
indexBuilt: boolean;
|
|
98
|
+
docsIndexed: number;
|
|
99
|
+
embeddingsPending: number;
|
|
100
|
+
firstSearchCost: 'instant' | 'model-load' | 'model-download';
|
|
101
|
+
}
|
|
102
|
+
interface PluginHealth {
|
|
103
|
+
ready: boolean;
|
|
104
|
+
readiness?: PluginReadiness;
|
|
105
|
+
diagnostics: Diagnostic[];
|
|
106
|
+
}
|
|
107
|
+
interface SearchMode {
|
|
108
|
+
plugin: string;
|
|
109
|
+
type: string;
|
|
110
|
+
label: string;
|
|
111
|
+
}
|
|
112
|
+
type PluginEvent = 'collection-added' | 'collection-removed' | 'article-created' | 'article-updated' | 'article-removed';
|
|
113
|
+
interface SearchProvider {
|
|
114
|
+
name: string;
|
|
115
|
+
capabilities: PluginCapabilities;
|
|
116
|
+
setup(collections: CollectionEntry[], opts?: {
|
|
117
|
+
embed?: boolean;
|
|
118
|
+
prefetchModels?: boolean;
|
|
119
|
+
}): Promise<{
|
|
120
|
+
ready: boolean;
|
|
121
|
+
}>;
|
|
122
|
+
reindex(collections: CollectionEntry[], opts?: {
|
|
123
|
+
embed?: boolean;
|
|
124
|
+
}): Promise<number>;
|
|
125
|
+
search(term: string, collections: CollectionEntry[], opts?: QueryOptions): Promise<QueryHit[]>;
|
|
126
|
+
notify(event: PluginEvent, collection: string, relPath: string | undefined, collections: CollectionEntry[]): Promise<void>;
|
|
127
|
+
health(collections: CollectionEntry[]): Promise<PluginHealth>;
|
|
128
|
+
close(): Promise<void>;
|
|
129
|
+
}
|
|
28
130
|
|
|
29
131
|
/** Base class for all expected, user-facing diffwiki failures. */
|
|
30
132
|
declare class DiffwikiError extends Error {
|
|
@@ -45,6 +147,8 @@ declare class ArticleNotFoundError extends DiffwikiError {
|
|
|
45
147
|
declare class InvalidTargetError extends DiffwikiError {
|
|
46
148
|
constructor(target: string, expected: string);
|
|
47
149
|
}
|
|
150
|
+
declare class PluginError extends DiffwikiError {
|
|
151
|
+
}
|
|
48
152
|
|
|
49
153
|
/** Root of all global diffwiki state. Overridable via DIFFWIKI_HOME (used by tests). */
|
|
50
154
|
declare function resolveHome(): string;
|
|
@@ -52,6 +156,8 @@ declare function registryPath(): string;
|
|
|
52
156
|
declare function configPath(): string;
|
|
53
157
|
declare function collectionsDir(): string;
|
|
54
158
|
declare function collectionDir(name: string): string;
|
|
159
|
+
declare function pluginsDir(): string;
|
|
160
|
+
declare function pluginsRegistryPath(): string;
|
|
55
161
|
|
|
56
162
|
declare function readConfig(): Promise<Config>;
|
|
57
163
|
declare function writeConfig(config: Config): Promise<void>;
|
|
@@ -123,23 +229,118 @@ interface InitOptions {
|
|
|
123
229
|
}
|
|
124
230
|
declare function initRepoWiki(opts: InitOptions): Promise<CollectionEntry>;
|
|
125
231
|
|
|
126
|
-
interface QueryHit {
|
|
127
|
-
collection: string;
|
|
128
|
-
path: string;
|
|
129
|
-
title: string;
|
|
130
|
-
tags: string[];
|
|
131
|
-
}
|
|
132
232
|
/**
|
|
133
|
-
*
|
|
134
|
-
*
|
|
233
|
+
* Built-in JS-native search: BM25-ranked full-text search over an article's
|
|
234
|
+
* title, body, tags, and collection name -- across every registered collection's
|
|
235
|
+
* ABSOLUTE registry path (so in-repo wikis outside ~/.diffwiki are searched too).
|
|
236
|
+
* No `find`/OS shelling -- cross-platform and dependency-free.
|
|
237
|
+
*
|
|
238
|
+
* When `term` is empty, returns all articles unranked (no score) to preserve
|
|
239
|
+
* the "browse all" behavior.
|
|
240
|
+
*/
|
|
241
|
+
declare function nativeSearch(term: string, collections: CollectionEntry[], collection?: string): Promise<QueryHit[]>;
|
|
242
|
+
/**
|
|
243
|
+
* Resolve the engine + type that `query()` would use when the caller passes no
|
|
244
|
+
* explicit engine/type. Mirrors `resolveDefaultEngine`'s precedence and, when the
|
|
245
|
+
* resolved engine is a plugin, prefers the type from `config.defaultSearch`'s
|
|
246
|
+
* `:type` suffix (if that plugin advertises it) else the plugin's first advertised
|
|
247
|
+
* search type. The native engine always resolves to `basic`. UIs use this to
|
|
248
|
+
* pre-select the search-mode dropdown to the engine actually run server-side.
|
|
135
249
|
*/
|
|
136
|
-
declare function
|
|
250
|
+
declare function resolveDefaultSearchMode(): Promise<{
|
|
251
|
+
engine: string;
|
|
252
|
+
type: string;
|
|
253
|
+
}>;
|
|
254
|
+
declare function query(term: string, opts?: QueryOptions): Promise<QueryHit[]>;
|
|
137
255
|
|
|
138
|
-
type DiagnosticLevel = 'ok' | 'warn' | 'error';
|
|
139
|
-
interface Diagnostic {
|
|
140
|
-
level: DiagnosticLevel;
|
|
141
|
-
message: string;
|
|
142
|
-
}
|
|
143
256
|
declare function doctor(): Promise<Diagnostic[]>;
|
|
144
257
|
|
|
145
|
-
|
|
258
|
+
/**
|
|
259
|
+
* Build a nested ArticleNode[] from a flat list of relative file paths.
|
|
260
|
+
* Pure — no I/O. Directories become branches; files become leaves whose `slug`
|
|
261
|
+
* is the relative path without extension. Dirs-first, then alpha (case-insensitive).
|
|
262
|
+
*/
|
|
263
|
+
declare function buildArticleTree(relPaths: string[]): ArticleNode[];
|
|
264
|
+
/**
|
|
265
|
+
* List the article tree of a collection. Walks the collection's registered
|
|
266
|
+
* `entry.path` — so collections living OUTSIDE `~/.diffwiki/collections`
|
|
267
|
+
* (e.g. in-repo wikis registered via `diffwiki init`) work unchanged.
|
|
268
|
+
*/
|
|
269
|
+
declare function listArticleTree(coll: string): Promise<ArticleNode[]>;
|
|
270
|
+
/**
|
|
271
|
+
* Read and resolve a single article by collection + slug (relative path without
|
|
272
|
+
* extension). Tries `.mdx` then `.md`, guards against path traversal, and splits
|
|
273
|
+
* frontmatter. Throws CollectionNotFoundError / ArticleNotFoundError / InvalidTargetError.
|
|
274
|
+
*/
|
|
275
|
+
declare function readArticle(coll: string, slug: string): Promise<ArticleContent>;
|
|
276
|
+
|
|
277
|
+
/** A heading extracted for the table of contents (h2/h3). */
|
|
278
|
+
interface TocItem {
|
|
279
|
+
slug: string;
|
|
280
|
+
text: string;
|
|
281
|
+
depth: number;
|
|
282
|
+
}
|
|
283
|
+
/** The result of rendering an article body to HTML. */
|
|
284
|
+
interface RenderedArticle {
|
|
285
|
+
/** Fully-rendered, Shiki-highlighted HTML — mounted directly on the client (no eval). */
|
|
286
|
+
html: string;
|
|
287
|
+
/** h2/h3 headings collected during render, in document order. */
|
|
288
|
+
toc: TocItem[];
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Render an article body (markdown) to Shiki-highlighted HTML plus its table of
|
|
292
|
+
* contents. Runs entirely server-side; the client mounts the HTML directly with
|
|
293
|
+
* no `eval`/`new Function`, so it works under a strict CSP. Code is highlighted
|
|
294
|
+
* here (dual github-light/github-dark via CSS variables); mermaid fences are
|
|
295
|
+
* marked for client rendering.
|
|
296
|
+
*/
|
|
297
|
+
declare function renderArticle(body: string): Promise<RenderedArticle>;
|
|
298
|
+
|
|
299
|
+
declare function readPluginRegistry(): Promise<PluginRegistryFile>;
|
|
300
|
+
declare function writePluginRegistry(registry: PluginRegistryFile): Promise<void>;
|
|
301
|
+
/** Insert or replace the plugin record with the same name. */
|
|
302
|
+
declare function upsertPlugin(record: PluginRecord): Promise<void>;
|
|
303
|
+
declare function deregisterPlugin(name: string): Promise<void>;
|
|
304
|
+
declare function listEnabledPlugins(kind: PluginKind): Promise<PluginRecord[]>;
|
|
305
|
+
declare function findEnabledPlugin(kind: PluginKind, name?: string): Promise<PluginRecord | undefined>;
|
|
306
|
+
|
|
307
|
+
declare function spawnPluginClient(record: PluginRecord): Promise<SearchProvider>;
|
|
308
|
+
|
|
309
|
+
declare function loadSearchProvider(name?: string): Promise<SearchProvider | null>;
|
|
310
|
+
declare function listSearchModes(): Promise<SearchMode[]>;
|
|
311
|
+
|
|
312
|
+
/** Create the managed plugin root (an isolated npm project) and return its path. */
|
|
313
|
+
declare function ensurePluginRoot(): Promise<string>;
|
|
314
|
+
/**
|
|
315
|
+
* Install an npm spec into the managed root, register the discovered search bin,
|
|
316
|
+
* then (unless opts.setup === false) run the plugin's end-to-end `setup` so the
|
|
317
|
+
* user lands on a warm, working search. A setup failure does not unwind the
|
|
318
|
+
* install -- the record is saved and `doctor` surfaces the problem later.
|
|
319
|
+
*/
|
|
320
|
+
declare function installPlugin(spec: string, opts?: {
|
|
321
|
+
setup?: boolean;
|
|
322
|
+
prefetchModels?: boolean;
|
|
323
|
+
}): Promise<PluginRecord>;
|
|
324
|
+
/**
|
|
325
|
+
* Register an already-present executable as a search plugin. Validates by spawning
|
|
326
|
+
* it (handshake + capability check) and runs its `setup` best-effort.
|
|
327
|
+
*/
|
|
328
|
+
declare function registerPlugin(name: string, command: string[]): Promise<PluginRecord>;
|
|
329
|
+
/** Uninstall a managed plugin's package and deregister it. */
|
|
330
|
+
declare function removePlugin(name: string): Promise<void>;
|
|
331
|
+
/** List every registered plugin, marking whether it currently spawns + handshakes. */
|
|
332
|
+
declare function listPlugins(): Promise<Array<PluginRecord & {
|
|
333
|
+
spawnable: boolean;
|
|
334
|
+
}>>;
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Fire a lifecycle hook at the active search plugin -- best-effort and
|
|
338
|
+
* non-blocking. Callers invoke this as `void emitPluginEvent(...)` and never
|
|
339
|
+
* await it, so a slow or absent plugin can neither stall nor fail a content
|
|
340
|
+
* mutation. Every error is swallowed; the lazy mtime-staleness reindex on
|
|
341
|
+
* `search` remains the correctness guarantee, so a dropped hook only costs a
|
|
342
|
+
* later lazy rebuild, never wrong results.
|
|
343
|
+
*/
|
|
344
|
+
declare function emitPluginEvent(event: PluginEvent, collection: string, relPath?: string): Promise<void>;
|
|
345
|
+
|
|
346
|
+
export { type Article, type ArticleContent, type ArticleNode, ArticleNotFoundError, type CollectionEntry, CollectionExistsError, CollectionNotFoundError, type CollectionType, type Config, type Diagnostic, type DiagnosticLevel, DiffwikiError, type InitOptions, InvalidTargetError, NATIVE_ENGINE, NoDefaultCollectionError, type ParsedArticle, type PluginCapabilities, PluginError, type PluginEvent, type PluginHealth, type PluginKind, type PluginReadiness, type PluginRecord, type PluginRegistryFile, type QueryHit, type QueryOptions, REPO_CONFIG_FILE, type Registry, type RenderedArticle, type RepoConfig, type SearchMode, type SearchProvider, type SerializableArticle, type TocItem, addTags, buildArticleTree, collectionDir, collectionsDir, configPath, createArticle, createCollection, deregisterPlugin, doctor, emitPluginEvent, ensurePluginRoot, findCollection, findEnabledPlugin, getConfigValue, initRepoWiki, installPlugin, listArticleTree, listCollections, listEnabledPlugins, listPlugins, listSearchModes, loadSearchProvider, nativeSearch, parseAddTarget, parseArticle, parsePathTarget, pluginsDir, pluginsRegistryPath, query, readArticle, readConfig, readPluginRegistry, readRegistry, readRepoConfig, registerCollection, registerPlugin, registryPath, removeArticle, removeCollection, removePlugin, removeTags, renderArticle, resolveDefaultSearchMode, resolveHome, serializeArticle, setConfigValue, setTags, slugify, spawnPluginClient, unregisterCollection, updateArticleBody, upsertPlugin, writeConfig, writePluginRegistry, writeRegistry };
|