docorbit 0.1.0
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/LICENSE +21 -0
- package/README.md +660 -0
- package/apps/cli/bin/docorbit.js +8 -0
- package/apps/cli/src/commands/add.ts +44 -0
- package/apps/cli/src/commands/api.ts +38 -0
- package/apps/cli/src/commands/context.ts +47 -0
- package/apps/cli/src/commands/dashboard.ts +55 -0
- package/apps/cli/src/commands/diff.ts +30 -0
- package/apps/cli/src/commands/evaluate.ts +133 -0
- package/apps/cli/src/commands/examples.ts +39 -0
- package/apps/cli/src/commands/export.ts +89 -0
- package/apps/cli/src/commands/impact.ts +31 -0
- package/apps/cli/src/commands/init.ts +69 -0
- package/apps/cli/src/commands/inspect.ts +30 -0
- package/apps/cli/src/commands/mcp.ts +72 -0
- package/apps/cli/src/commands/pitfalls.ts +38 -0
- package/apps/cli/src/commands/recipes.ts +35 -0
- package/apps/cli/src/commands/search.ts +48 -0
- package/apps/cli/src/commands/update.ts +73 -0
- package/apps/cli/src/commands/verify.ts +48 -0
- package/apps/cli/src/formatters/colors.ts +23 -0
- package/apps/cli/src/formatters/inspection.ts +102 -0
- package/apps/cli/src/formatters/knowledge.ts +272 -0
- package/apps/cli/src/formatters/retrieval.ts +74 -0
- package/apps/cli/src/formatters/terminal.ts +6 -0
- package/apps/cli/src/formatters/verification.ts +126 -0
- package/apps/cli/src/index.ts +409 -0
- package/bin/docorbit.js +8 -0
- package/package.json +46 -0
- package/packages/core/src/dashboard/server.ts +314 -0
- package/packages/core/src/dashboard/ui.ts +586 -0
- package/packages/core/src/implementation-service.ts +451 -0
- package/packages/core/src/index.ts +7 -0
- package/packages/core/src/inspector.ts +71 -0
- package/packages/core/src/pipeline.ts +331 -0
- package/packages/crawler/src/config.ts +12 -0
- package/packages/crawler/src/fetcher.ts +185 -0
- package/packages/crawler/src/index.ts +2 -0
- package/packages/discovery/src/index.ts +31 -0
- package/packages/discovery/src/provider.ts +47 -0
- package/packages/discovery/src/providers/generic.ts +98 -0
- package/packages/discovery/src/providers/github.ts +61 -0
- package/packages/discovery/src/providers/llms-txt.ts +73 -0
- package/packages/discovery/src/providers/markdown.ts +48 -0
- package/packages/discovery/src/providers/openapi.ts +91 -0
- package/packages/discovery/src/providers/sitemap.ts +62 -0
- package/packages/discovery/src/providers/skill.ts +54 -0
- package/packages/discovery/src/ranker.ts +123 -0
- package/packages/evaluation/src/dataset.ts +963 -0
- package/packages/evaluation/src/index.ts +8 -0
- package/packages/evaluation/src/runner.ts +241 -0
- package/packages/evaluation/src/strategies/context7-runner.ts +269 -0
- package/packages/evaluation/src/strategies/docorbit-runner.ts +228 -0
- package/packages/evaluation/src/strategies/firecrawl-runner.ts +172 -0
- package/packages/evaluation/src/strategies/web-search-runner.ts +194 -0
- package/packages/evaluation/src/types.ts +34 -0
- package/packages/evaluation/src/version-matcher.ts +73 -0
- package/packages/export/src/agents-md.ts +200 -0
- package/packages/export/src/claude-md.ts +141 -0
- package/packages/export/src/docs-map.ts +150 -0
- package/packages/export/src/index.ts +6 -0
- package/packages/export/src/llms-txt.ts +96 -0
- package/packages/export/src/service.ts +250 -0
- package/packages/export/src/skill-md.ts +128 -0
- package/packages/mcp/src/index.ts +46 -0
- package/packages/mcp/src/resources/index.ts +189 -0
- package/packages/mcp/src/server.ts +278 -0
- package/packages/mcp/src/tools/analyze-impact.ts +74 -0
- package/packages/mcp/src/tools/check-api.ts +86 -0
- package/packages/mcp/src/tools/diff-docs.ts +68 -0
- package/packages/mcp/src/tools/export-context.ts +73 -0
- package/packages/mcp/src/tools/find-api.ts +99 -0
- package/packages/mcp/src/tools/find-example.ts +100 -0
- package/packages/mcp/src/tools/find-pitfall.ts +94 -0
- package/packages/mcp/src/tools/find-recipe.ts +98 -0
- package/packages/mcp/src/tools/get-doc.ts +130 -0
- package/packages/mcp/src/tools/get-docs-map.ts +64 -0
- package/packages/mcp/src/tools/get-version.ts +118 -0
- package/packages/mcp/src/tools/implementation-context.ts +88 -0
- package/packages/mcp/src/tools/index.ts +59 -0
- package/packages/mcp/src/tools/list-sources.ts +85 -0
- package/packages/mcp/src/tools/search-docs.ts +123 -0
- package/packages/mcp/src/tools/types.ts +28 -0
- package/packages/mcp/src/transports/http.ts +256 -0
- package/packages/mcp/src/transports/stdio.ts +105 -0
- package/packages/mcp/src/transports/types.ts +6 -0
- package/packages/mcp/src/types.ts +102 -0
- package/packages/normalizer/src/example-indexer.ts +240 -0
- package/packages/normalizer/src/html.ts +253 -0
- package/packages/normalizer/src/index.ts +8 -0
- package/packages/normalizer/src/llms.ts +83 -0
- package/packages/normalizer/src/openapi/endpoint-parser.ts +406 -0
- package/packages/normalizer/src/openapi/schema-resolver.ts +111 -0
- package/packages/normalizer/src/openapi.ts +2 -0
- package/packages/normalizer/src/page.ts +184 -0
- package/packages/normalizer/src/pitfall-extractor.ts +190 -0
- package/packages/normalizer/src/slicer.ts +455 -0
- package/packages/retrieval/src/engine.ts +120 -0
- package/packages/retrieval/src/index.ts +7 -0
- package/packages/retrieval/src/intent.ts +43 -0
- package/packages/retrieval/src/packer.ts +145 -0
- package/packages/retrieval/src/recipe-engine.ts +313 -0
- package/packages/retrieval/src/scorer.ts +139 -0
- package/packages/retrieval/src/weights.ts +31 -0
- package/packages/security/src/annotations.ts +112 -0
- package/packages/security/src/index.ts +2 -0
- package/packages/security/src/ssrf.ts +153 -0
- package/packages/shared/src/errors.ts +53 -0
- package/packages/shared/src/hashing.ts +23 -0
- package/packages/shared/src/index.ts +3 -0
- package/packages/shared/src/types.ts +881 -0
- package/packages/storage/src/db.ts +72 -0
- package/packages/storage/src/index.ts +11 -0
- package/packages/storage/src/interfaces.ts +115 -0
- package/packages/storage/src/repositories/api-repository.ts +219 -0
- package/packages/storage/src/repositories/chunk-repository.ts +316 -0
- package/packages/storage/src/repositories/example-repository.ts +206 -0
- package/packages/storage/src/repositories/page-repository.ts +205 -0
- package/packages/storage/src/repositories/pitfall-repository.ts +188 -0
- package/packages/storage/src/repositories/source-repository.ts +205 -0
- package/packages/storage/src/repository.ts +256 -0
- package/packages/storage/src/schema.ts +269 -0
- package/packages/storage/src/search-tokens.ts +28 -0
- package/packages/verification/src/diff-engine.ts +258 -0
- package/packages/verification/src/extractor.ts +339 -0
- package/packages/verification/src/impact-scanner.ts +203 -0
- package/packages/verification/src/index.ts +5 -0
- package/packages/verification/src/services.ts +238 -0
- package/packages/verification/src/verifier.ts +375 -0
- package/packages/workspace/src/detector.ts +143 -0
- package/packages/workspace/src/ecosystems/cargo.ts +84 -0
- package/packages/workspace/src/ecosystems/composer.ts +42 -0
- package/packages/workspace/src/ecosystems/go.ts +54 -0
- package/packages/workspace/src/ecosystems/index.ts +34 -0
- package/packages/workspace/src/ecosystems/maven.ts +34 -0
- package/packages/workspace/src/ecosystems/npm.ts +83 -0
- package/packages/workspace/src/ecosystems/pub.ts +40 -0
- package/packages/workspace/src/ecosystems/pypi.ts +100 -0
- package/packages/workspace/src/ecosystems/rubygems.ts +30 -0
- package/packages/workspace/src/ecosystems/types.ts +18 -0
- package/packages/workspace/src/index.ts +5 -0
- package/packages/workspace/src/lockfile.ts +194 -0
- package/packages/workspace/src/resolver.ts +234 -0
- package/packages/workspace/src/semver.ts +259 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DiscoveredSource,
|
|
3
|
+
NormalizedPage,
|
|
4
|
+
DocumentChunk,
|
|
5
|
+
ChunkCode,
|
|
6
|
+
SymbolReference,
|
|
7
|
+
ChunkRelationship,
|
|
8
|
+
ChunkType,
|
|
9
|
+
ApiEndpoint,
|
|
10
|
+
IndexedExample,
|
|
11
|
+
Pitfall,
|
|
12
|
+
PitfallKind,
|
|
13
|
+
} from '../../shared/src/index.ts';
|
|
14
|
+
import type { DocOrbitDb } from './db.ts';
|
|
15
|
+
import type {
|
|
16
|
+
Snapshot,
|
|
17
|
+
ISourceRepository,
|
|
18
|
+
IPageRepository,
|
|
19
|
+
IChunkRepository,
|
|
20
|
+
IApiRepository,
|
|
21
|
+
IExampleRepository,
|
|
22
|
+
IPitfallRepository,
|
|
23
|
+
} from './interfaces.ts';
|
|
24
|
+
import { SourceRepository } from './repositories/source-repository.ts';
|
|
25
|
+
import { PageRepository } from './repositories/page-repository.ts';
|
|
26
|
+
import { ChunkRepository } from './repositories/chunk-repository.ts';
|
|
27
|
+
import { ApiRepository } from './repositories/api-repository.ts';
|
|
28
|
+
import { ExampleRepository } from './repositories/example-repository.ts';
|
|
29
|
+
import { PitfallRepository } from './repositories/pitfall-repository.ts';
|
|
30
|
+
|
|
31
|
+
export type { Snapshot } from './interfaces.ts';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Unified Facade for the DocOrbit database storage layer.
|
|
35
|
+
* Delegates domain responsibilities to specialized sub-repositories:
|
|
36
|
+
* - sources: ISourceRepository (sources, snapshots, snapshot-page links)
|
|
37
|
+
* - pages: IPageRepository (normalized pages, page links, page FTS)
|
|
38
|
+
* - chunks: IChunkRepository (document chunks, code, symbols, relationships, chunk FTS)
|
|
39
|
+
* - apis: IApiRepository (API endpoints, OpenAPI schemas, endpoint FTS)
|
|
40
|
+
* - examples: IExampleRepository (code examples, example FTS)
|
|
41
|
+
* - pitfalls: IPitfallRepository (pitfalls, gotchas, pitfall FTS)
|
|
42
|
+
*/
|
|
43
|
+
export class DocOrbitRepository
|
|
44
|
+
implements
|
|
45
|
+
ISourceRepository,
|
|
46
|
+
IPageRepository,
|
|
47
|
+
IChunkRepository,
|
|
48
|
+
IApiRepository,
|
|
49
|
+
IExampleRepository,
|
|
50
|
+
IPitfallRepository
|
|
51
|
+
{
|
|
52
|
+
public readonly sources: SourceRepository;
|
|
53
|
+
public readonly pages: PageRepository;
|
|
54
|
+
public readonly chunks: ChunkRepository;
|
|
55
|
+
public readonly apis: ApiRepository;
|
|
56
|
+
public readonly examples: ExampleRepository;
|
|
57
|
+
public readonly pitfalls: PitfallRepository;
|
|
58
|
+
|
|
59
|
+
public readonly db: DocOrbitDb;
|
|
60
|
+
|
|
61
|
+
constructor(db: DocOrbitDb) {
|
|
62
|
+
this.db = db;
|
|
63
|
+
this.pages = new PageRepository(db);
|
|
64
|
+
this.sources = new SourceRepository(db, row => this.pages.hydratePage(row));
|
|
65
|
+
this.chunks = new ChunkRepository(db);
|
|
66
|
+
this.apis = new ApiRepository(db);
|
|
67
|
+
this.examples = new ExampleRepository(db);
|
|
68
|
+
this.pitfalls = new PitfallRepository(db);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// --- ISourceRepository Delegations ---
|
|
72
|
+
|
|
73
|
+
saveSource(source: DiscoveredSource): string {
|
|
74
|
+
return this.sources.saveSource(source);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
getSource(id: string): DiscoveredSource | null {
|
|
78
|
+
return this.sources.getSource(id);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
getSourceByUrl(url: string): DiscoveredSource | null {
|
|
82
|
+
return this.sources.getSourceByUrl(url);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
listSources(): DiscoveredSource[] {
|
|
86
|
+
return this.sources.listSources();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
createSnapshot(sourceId: string, metadata?: Record<string, unknown>, docVersion?: string): string {
|
|
90
|
+
return this.sources.createSnapshot(sourceId, metadata, docVersion);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
saveSnapshot(snapshot: Snapshot): void {
|
|
94
|
+
this.sources.saveSnapshot(snapshot);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
getSnapshot(id: string): Snapshot | null {
|
|
98
|
+
return this.sources.getSnapshot(id);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
getLatestSnapshot(sourceId: string): Snapshot | null {
|
|
102
|
+
return this.sources.getLatestSnapshot(sourceId);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
listSnapshots(sourceId: string): Snapshot[] {
|
|
106
|
+
return this.sources.listSnapshots(sourceId);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
linkSnapshotPages(snapshotId: string, pageIds: string[]): void {
|
|
110
|
+
this.sources.linkSnapshotPages(snapshotId, pageIds);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
getSnapshotPages(snapshotId: string): NormalizedPage[] {
|
|
114
|
+
return this.sources.getSnapshotPages(snapshotId);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// --- IPageRepository Delegations ---
|
|
118
|
+
|
|
119
|
+
savePage(page: NormalizedPage): void {
|
|
120
|
+
this.pages.savePage(page);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
getPage(id: string): NormalizedPage | null {
|
|
124
|
+
return this.pages.getPage(id);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
getPageByUrl(normalizedUrl: string): NormalizedPage | null {
|
|
128
|
+
return this.pages.getPageByUrl(normalizedUrl);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
listPages(limit?: number, offset?: number): NormalizedPage[] {
|
|
132
|
+
return this.pages.listPages(limit, offset);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
countPages(sourceId?: string): number {
|
|
136
|
+
return this.pages.countPages(sourceId);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
savePageLinks(pageId: string, targetUrls: string[]): void {
|
|
140
|
+
this.pages.savePageLinks(pageId, targetUrls);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
getPageLinks(pageId: string): string[] {
|
|
144
|
+
return this.pages.getPageLinks(pageId);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
searchPagesFts(query: string, limit: number = 10): NormalizedPage[] {
|
|
148
|
+
return this.pages.searchPagesFts(query, limit);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// --- IChunkRepository Delegations ---
|
|
152
|
+
|
|
153
|
+
saveChunks(
|
|
154
|
+
chunks: DocumentChunk[],
|
|
155
|
+
relationships: ChunkRelationship[] = [],
|
|
156
|
+
codeSnippets: ChunkCode[] = [],
|
|
157
|
+
symbols: SymbolReference[] = []
|
|
158
|
+
): void {
|
|
159
|
+
this.chunks.saveChunks(chunks, relationships, codeSnippets, symbols);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
getChunk(id: string): DocumentChunk | null {
|
|
163
|
+
return this.chunks.getChunk(id);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
getChunksByPage(pageId: string): DocumentChunk[] {
|
|
167
|
+
return this.chunks.getChunksByPage(pageId);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
getChunksBySnapshot(snapshotId: string): DocumentChunk[] {
|
|
171
|
+
return this.chunks.getChunksBySnapshot(snapshotId);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
getChunksByVersion(docVersion: string): DocumentChunk[] {
|
|
175
|
+
return this.chunks.getChunksByVersion(docVersion);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
getChunkCode(chunkId: string): ChunkCode[] {
|
|
179
|
+
return this.chunks.getChunkCode(chunkId);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
getChunkSymbols(chunkId: string): SymbolReference[] {
|
|
183
|
+
return this.chunks.getChunkSymbols(chunkId);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
getChunkRelationships(chunkId: string): ChunkRelationship[] {
|
|
187
|
+
return this.chunks.getChunkRelationships(chunkId);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
countChunks(snapshotId?: string): number {
|
|
191
|
+
return this.chunks.countChunks(snapshotId);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
searchChunksFts(
|
|
195
|
+
query: string,
|
|
196
|
+
options: { limit?: number; snapshotId?: string; chunkType?: ChunkType; docVersion?: string } = {}
|
|
197
|
+
): Array<{ chunk: DocumentChunk; ftsRank: number; symbols: SymbolReference[]; codeSnippets: ChunkCode[] }> {
|
|
198
|
+
return this.chunks.searchChunksFts(query, options);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// --- IApiRepository Delegations ---
|
|
202
|
+
|
|
203
|
+
saveApiEndpoints(endpoints: ApiEndpoint[]): void {
|
|
204
|
+
this.apis.saveApiEndpoints(endpoints);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
getApiEndpoint(id: string): ApiEndpoint | null {
|
|
208
|
+
return this.apis.getApiEndpoint(id);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
getApiEndpointsBySnapshot(snapshotId: string): ApiEndpoint[] {
|
|
212
|
+
return this.apis.getApiEndpointsBySnapshot(snapshotId);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
searchApiEndpoints(
|
|
216
|
+
query: string,
|
|
217
|
+
options: { method?: string; docVersion?: string; limit?: number } = {}
|
|
218
|
+
): ApiEndpoint[] {
|
|
219
|
+
return this.apis.searchApiEndpoints(query, options);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// --- IExampleRepository Delegations ---
|
|
223
|
+
|
|
224
|
+
saveIndexedExamples(examples: IndexedExample[]): void {
|
|
225
|
+
this.examples.saveIndexedExamples(examples);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
getIndexedExamplesBySnapshot(snapshotId: string): IndexedExample[] {
|
|
229
|
+
return this.examples.getIndexedExamplesBySnapshot(snapshotId);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
searchIndexedExamples(
|
|
233
|
+
query: string,
|
|
234
|
+
options: { language?: string; framework?: string; docVersion?: string; limit?: number } = {}
|
|
235
|
+
): IndexedExample[] {
|
|
236
|
+
return this.examples.searchIndexedExamples(query, options);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// --- IPitfallRepository Delegations ---
|
|
240
|
+
|
|
241
|
+
savePitfalls(pitfalls: Pitfall[]): void {
|
|
242
|
+
this.pitfalls.savePitfalls(pitfalls);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
getPitfallsBySnapshot(snapshotId: string): Pitfall[] {
|
|
246
|
+
return this.pitfalls.getPitfallsBySnapshot(snapshotId);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
searchPitfalls(
|
|
250
|
+
query: string,
|
|
251
|
+
options: { kind?: PitfallKind; docVersion?: string; limit?: number } = {}
|
|
252
|
+
): Pitfall[] {
|
|
253
|
+
return this.pitfalls.searchPitfalls(query, options);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
export const SCHEMA_SQL = `
|
|
2
|
+
CREATE TABLE IF NOT EXISTS sources (
|
|
3
|
+
id TEXT PRIMARY KEY,
|
|
4
|
+
url TEXT UNIQUE NOT NULL,
|
|
5
|
+
type TEXT NOT NULL,
|
|
6
|
+
discovered_by TEXT NOT NULL,
|
|
7
|
+
status TEXT NOT NULL,
|
|
8
|
+
content_type TEXT,
|
|
9
|
+
confidence REAL NOT NULL,
|
|
10
|
+
authority TEXT NOT NULL,
|
|
11
|
+
machine_readable INTEGER NOT NULL,
|
|
12
|
+
metadata TEXT,
|
|
13
|
+
created_at TEXT NOT NULL
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
CREATE TABLE IF NOT EXISTS pages (
|
|
17
|
+
id TEXT PRIMARY KEY,
|
|
18
|
+
source_id TEXT NOT NULL,
|
|
19
|
+
title TEXT NOT NULL,
|
|
20
|
+
url TEXT UNIQUE NOT NULL,
|
|
21
|
+
content TEXT NOT NULL,
|
|
22
|
+
content_hash TEXT NOT NULL,
|
|
23
|
+
fetched_at TEXT NOT NULL,
|
|
24
|
+
raw_bytes INTEGER NOT NULL,
|
|
25
|
+
estimated_tokens INTEGER NOT NULL,
|
|
26
|
+
headings_json TEXT,
|
|
27
|
+
security_annotations_json TEXT,
|
|
28
|
+
provenance_json TEXT,
|
|
29
|
+
FOREIGN KEY (source_id) REFERENCES sources(id) ON DELETE CASCADE
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
CREATE TABLE IF NOT EXISTS links (
|
|
33
|
+
id TEXT PRIMARY KEY,
|
|
34
|
+
page_id TEXT NOT NULL,
|
|
35
|
+
text TEXT NOT NULL,
|
|
36
|
+
url TEXT NOT NULL,
|
|
37
|
+
is_external INTEGER NOT NULL,
|
|
38
|
+
FOREIGN KEY (page_id) REFERENCES pages(id) ON DELETE CASCADE
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
CREATE TABLE IF NOT EXISTS code_examples (
|
|
42
|
+
id TEXT PRIMARY KEY,
|
|
43
|
+
page_id TEXT NOT NULL,
|
|
44
|
+
language TEXT NOT NULL,
|
|
45
|
+
code TEXT NOT NULL,
|
|
46
|
+
caption TEXT,
|
|
47
|
+
FOREIGN KEY (page_id) REFERENCES pages(id) ON DELETE CASCADE
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
CREATE TABLE IF NOT EXISTS snapshots (
|
|
51
|
+
id TEXT PRIMARY KEY,
|
|
52
|
+
source_id TEXT NOT NULL,
|
|
53
|
+
snapshot_hash TEXT NOT NULL,
|
|
54
|
+
page_count INTEGER NOT NULL,
|
|
55
|
+
captured_at TEXT NOT NULL,
|
|
56
|
+
doc_version TEXT,
|
|
57
|
+
metadata TEXT,
|
|
58
|
+
FOREIGN KEY (source_id) REFERENCES sources(id) ON DELETE CASCADE
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
CREATE TABLE IF NOT EXISTS snapshot_pages (
|
|
62
|
+
snapshot_id TEXT NOT NULL,
|
|
63
|
+
page_id TEXT NOT NULL,
|
|
64
|
+
content_hash TEXT NOT NULL,
|
|
65
|
+
PRIMARY KEY (snapshot_id, page_id),
|
|
66
|
+
FOREIGN KEY (snapshot_id) REFERENCES snapshots(id) ON DELETE CASCADE,
|
|
67
|
+
FOREIGN KEY (page_id) REFERENCES pages(id) ON DELETE CASCADE
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
CREATE TABLE IF NOT EXISTS chunks (
|
|
71
|
+
id TEXT PRIMARY KEY,
|
|
72
|
+
page_id TEXT NOT NULL,
|
|
73
|
+
snapshot_id TEXT NOT NULL,
|
|
74
|
+
title TEXT,
|
|
75
|
+
section_path_json TEXT NOT NULL,
|
|
76
|
+
content TEXT NOT NULL,
|
|
77
|
+
chunk_type TEXT NOT NULL,
|
|
78
|
+
language TEXT,
|
|
79
|
+
token_estimate INTEGER NOT NULL,
|
|
80
|
+
ordinal INTEGER NOT NULL,
|
|
81
|
+
content_hash TEXT NOT NULL,
|
|
82
|
+
doc_version TEXT,
|
|
83
|
+
provenance_json TEXT,
|
|
84
|
+
created_at TEXT NOT NULL,
|
|
85
|
+
FOREIGN KEY (page_id) REFERENCES pages(id) ON DELETE CASCADE
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
CREATE TABLE IF NOT EXISTS chunk_code (
|
|
89
|
+
id TEXT PRIMARY KEY,
|
|
90
|
+
chunk_id TEXT NOT NULL,
|
|
91
|
+
language TEXT,
|
|
92
|
+
code TEXT NOT NULL,
|
|
93
|
+
FOREIGN KEY (chunk_id) REFERENCES chunks(id) ON DELETE CASCADE
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
CREATE TABLE IF NOT EXISTS symbol_references (
|
|
97
|
+
id TEXT PRIMARY KEY,
|
|
98
|
+
chunk_id TEXT NOT NULL,
|
|
99
|
+
name TEXT NOT NULL,
|
|
100
|
+
kind TEXT NOT NULL,
|
|
101
|
+
FOREIGN KEY (chunk_id) REFERENCES chunks(id) ON DELETE CASCADE
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
CREATE TABLE IF NOT EXISTS chunk_relationships (
|
|
105
|
+
source_chunk_id TEXT NOT NULL,
|
|
106
|
+
target_chunk_id TEXT NOT NULL,
|
|
107
|
+
type TEXT NOT NULL,
|
|
108
|
+
PRIMARY KEY (source_chunk_id, target_chunk_id, type)
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
CREATE INDEX IF NOT EXISTS idx_pages_source_id ON pages(source_id);
|
|
112
|
+
CREATE INDEX IF NOT EXISTS idx_pages_content_hash ON pages(content_hash);
|
|
113
|
+
CREATE INDEX IF NOT EXISTS idx_links_page_id ON links(page_id);
|
|
114
|
+
CREATE INDEX IF NOT EXISTS idx_code_examples_page_id ON code_examples(page_id);
|
|
115
|
+
CREATE INDEX IF NOT EXISTS idx_snapshots_source_id ON snapshots(source_id);
|
|
116
|
+
CREATE INDEX IF NOT EXISTS idx_snapshots_doc_version ON snapshots(doc_version);
|
|
117
|
+
CREATE INDEX IF NOT EXISTS idx_snapshot_pages_snapshot_id ON snapshot_pages(snapshot_id);
|
|
118
|
+
CREATE INDEX IF NOT EXISTS idx_snapshot_pages_page_id ON snapshot_pages(page_id);
|
|
119
|
+
CREATE INDEX IF NOT EXISTS idx_chunks_page_id ON chunks(page_id);
|
|
120
|
+
CREATE INDEX IF NOT EXISTS idx_chunks_snapshot_id ON chunks(snapshot_id);
|
|
121
|
+
CREATE INDEX IF NOT EXISTS idx_chunks_chunk_type ON chunks(chunk_type);
|
|
122
|
+
CREATE INDEX IF NOT EXISTS idx_chunks_content_hash ON chunks(content_hash);
|
|
123
|
+
CREATE INDEX IF NOT EXISTS idx_chunks_doc_version ON chunks(doc_version);
|
|
124
|
+
CREATE INDEX IF NOT EXISTS idx_chunk_code_chunk_id ON chunk_code(chunk_id);
|
|
125
|
+
CREATE INDEX IF NOT EXISTS idx_symbol_references_chunk_id ON symbol_references(chunk_id);
|
|
126
|
+
CREATE INDEX IF NOT EXISTS idx_symbol_references_name ON symbol_references(name);
|
|
127
|
+
CREATE INDEX IF NOT EXISTS idx_chunk_relationships_source ON chunk_relationships(source_chunk_id);
|
|
128
|
+
CREATE INDEX IF NOT EXISTS idx_chunk_relationships_target ON chunk_relationships(target_chunk_id);
|
|
129
|
+
|
|
130
|
+
CREATE TABLE IF NOT EXISTS api_endpoints (
|
|
131
|
+
id TEXT PRIMARY KEY,
|
|
132
|
+
page_id TEXT NOT NULL,
|
|
133
|
+
snapshot_id TEXT NOT NULL,
|
|
134
|
+
method TEXT NOT NULL,
|
|
135
|
+
path TEXT NOT NULL,
|
|
136
|
+
summary TEXT,
|
|
137
|
+
description TEXT,
|
|
138
|
+
operation_id TEXT,
|
|
139
|
+
parameters_json TEXT NOT NULL,
|
|
140
|
+
request_schema_json TEXT,
|
|
141
|
+
response_schema_json TEXT,
|
|
142
|
+
auth_json TEXT NOT NULL,
|
|
143
|
+
errors_json TEXT NOT NULL,
|
|
144
|
+
pagination_json TEXT,
|
|
145
|
+
deprecated INTEGER NOT NULL,
|
|
146
|
+
doc_version TEXT,
|
|
147
|
+
provenance_json TEXT,
|
|
148
|
+
created_at TEXT NOT NULL,
|
|
149
|
+
FOREIGN KEY (page_id) REFERENCES pages(id) ON DELETE CASCADE
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
CREATE INDEX IF NOT EXISTS idx_api_endpoints_page_id ON api_endpoints(page_id);
|
|
153
|
+
CREATE INDEX IF NOT EXISTS idx_api_endpoints_snapshot_id ON api_endpoints(snapshot_id);
|
|
154
|
+
CREATE INDEX IF NOT EXISTS idx_api_endpoints_method ON api_endpoints(method);
|
|
155
|
+
CREATE INDEX IF NOT EXISTS idx_api_endpoints_path ON api_endpoints(path);
|
|
156
|
+
CREATE INDEX IF NOT EXISTS idx_api_endpoints_doc_version ON api_endpoints(doc_version);
|
|
157
|
+
|
|
158
|
+
CREATE TABLE IF NOT EXISTS indexed_examples (
|
|
159
|
+
id TEXT PRIMARY KEY,
|
|
160
|
+
chunk_id TEXT,
|
|
161
|
+
page_id TEXT NOT NULL,
|
|
162
|
+
snapshot_id TEXT NOT NULL,
|
|
163
|
+
language TEXT NOT NULL,
|
|
164
|
+
framework TEXT,
|
|
165
|
+
task TEXT NOT NULL,
|
|
166
|
+
code TEXT NOT NULL,
|
|
167
|
+
source_url TEXT NOT NULL,
|
|
168
|
+
source_authority TEXT NOT NULL,
|
|
169
|
+
related_api TEXT,
|
|
170
|
+
related_symbol TEXT,
|
|
171
|
+
doc_version TEXT,
|
|
172
|
+
provenance_json TEXT,
|
|
173
|
+
created_at TEXT NOT NULL,
|
|
174
|
+
FOREIGN KEY (page_id) REFERENCES pages(id) ON DELETE CASCADE
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
CREATE INDEX IF NOT EXISTS idx_indexed_examples_page_id ON indexed_examples(page_id);
|
|
178
|
+
CREATE INDEX IF NOT EXISTS idx_indexed_examples_snapshot_id ON indexed_examples(snapshot_id);
|
|
179
|
+
CREATE INDEX IF NOT EXISTS idx_indexed_examples_chunk_id ON indexed_examples(chunk_id);
|
|
180
|
+
CREATE INDEX IF NOT EXISTS idx_indexed_examples_language ON indexed_examples(language);
|
|
181
|
+
CREATE INDEX IF NOT EXISTS idx_indexed_examples_framework ON indexed_examples(framework);
|
|
182
|
+
CREATE INDEX IF NOT EXISTS idx_indexed_examples_doc_version ON indexed_examples(doc_version);
|
|
183
|
+
CREATE INDEX IF NOT EXISTS idx_indexed_examples_related_api ON indexed_examples(related_api);
|
|
184
|
+
|
|
185
|
+
CREATE TABLE IF NOT EXISTS pitfalls (
|
|
186
|
+
id TEXT PRIMARY KEY,
|
|
187
|
+
chunk_id TEXT,
|
|
188
|
+
page_id TEXT NOT NULL,
|
|
189
|
+
snapshot_id TEXT NOT NULL,
|
|
190
|
+
kind TEXT NOT NULL,
|
|
191
|
+
title TEXT NOT NULL,
|
|
192
|
+
content TEXT NOT NULL,
|
|
193
|
+
related_api TEXT,
|
|
194
|
+
related_symbol TEXT,
|
|
195
|
+
doc_version TEXT,
|
|
196
|
+
provenance_json TEXT,
|
|
197
|
+
created_at TEXT NOT NULL,
|
|
198
|
+
FOREIGN KEY (page_id) REFERENCES pages(id) ON DELETE CASCADE
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
CREATE INDEX IF NOT EXISTS idx_pitfalls_page_id ON pitfalls(page_id);
|
|
202
|
+
CREATE INDEX IF NOT EXISTS idx_pitfalls_snapshot_id ON pitfalls(snapshot_id);
|
|
203
|
+
CREATE INDEX IF NOT EXISTS idx_pitfalls_chunk_id ON pitfalls(chunk_id);
|
|
204
|
+
CREATE INDEX IF NOT EXISTS idx_pitfalls_kind ON pitfalls(kind);
|
|
205
|
+
CREATE INDEX IF NOT EXISTS idx_pitfalls_doc_version ON pitfalls(doc_version);
|
|
206
|
+
CREATE INDEX IF NOT EXISTS idx_pitfalls_related_api ON pitfalls(related_api);
|
|
207
|
+
`;
|
|
208
|
+
|
|
209
|
+
export const FTS_SCHEMA_SQL = `
|
|
210
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS pages_fts USING fts5(
|
|
211
|
+
page_id UNINDEXED,
|
|
212
|
+
title,
|
|
213
|
+
content
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS chunks_fts USING fts5(
|
|
217
|
+
chunk_id UNINDEXED,
|
|
218
|
+
title,
|
|
219
|
+
section_path,
|
|
220
|
+
content,
|
|
221
|
+
symbols
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
CREATE TRIGGER IF NOT EXISTS trg_chunks_delete AFTER DELETE ON chunks BEGIN
|
|
225
|
+
DELETE FROM chunks_fts WHERE chunk_id = old.id;
|
|
226
|
+
END;
|
|
227
|
+
|
|
228
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS api_endpoints_fts USING fts5(
|
|
229
|
+
endpoint_id UNINDEXED,
|
|
230
|
+
method,
|
|
231
|
+
path,
|
|
232
|
+
summary,
|
|
233
|
+
description,
|
|
234
|
+
parameters
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
CREATE TRIGGER IF NOT EXISTS trg_api_endpoints_delete AFTER DELETE ON api_endpoints BEGIN
|
|
238
|
+
DELETE FROM api_endpoints_fts WHERE endpoint_id = old.id;
|
|
239
|
+
END;
|
|
240
|
+
|
|
241
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS indexed_examples_fts USING fts5(
|
|
242
|
+
example_id UNINDEXED,
|
|
243
|
+
task,
|
|
244
|
+
language,
|
|
245
|
+
framework,
|
|
246
|
+
code,
|
|
247
|
+
related_api,
|
|
248
|
+
related_symbol
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
CREATE TRIGGER IF NOT EXISTS trg_indexed_examples_delete AFTER DELETE ON indexed_examples BEGIN
|
|
252
|
+
DELETE FROM indexed_examples_fts WHERE example_id = old.id;
|
|
253
|
+
END;
|
|
254
|
+
|
|
255
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS pitfalls_fts USING fts5(
|
|
256
|
+
pitfall_id UNINDEXED,
|
|
257
|
+
kind,
|
|
258
|
+
title,
|
|
259
|
+
content,
|
|
260
|
+
related_api,
|
|
261
|
+
related_symbol
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
CREATE TRIGGER IF NOT EXISTS trg_pitfalls_delete AFTER DELETE ON pitfalls BEGIN
|
|
265
|
+
DELETE FROM pitfalls_fts WHERE pitfall_id = old.id;
|
|
266
|
+
END;
|
|
267
|
+
`;
|
|
268
|
+
|
|
269
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const SEARCH_STOPWORDS = new Set([
|
|
2
|
+
'a', 'about', 'above', 'after', 'again', 'against', 'all', 'am', 'an', 'and', 'any', 'are',
|
|
3
|
+
'as', 'at', 'be', 'because', 'been', 'before', 'being', 'below', 'between', 'both', 'but', 'by',
|
|
4
|
+
'can', 'did', 'do', 'does', 'doing', 'down', 'during', 'each', 'few', 'for', 'from',
|
|
5
|
+
'further', 'had', 'has', 'have', 'having', 'he', 'her', 'here', 'hers', 'herself', 'him',
|
|
6
|
+
'himself', 'his', 'how', 'i', 'if', 'in', 'into', 'is', 'it', 'its', 'itself', 'just',
|
|
7
|
+
'me', 'more', 'most', 'my', 'myself', 'no', 'nor', 'not', 'now', 'of', 'off', 'on',
|
|
8
|
+
'once', 'only', 'or', 'other', 'our', 'ours', 'ourselves', 'out', 'over', 'own', 'same',
|
|
9
|
+
'she', 'should', 'so', 'some', 'such', 'than', 'that', 'the', 'their', 'theirs', 'them',
|
|
10
|
+
'themselves', 'then', 'there', 'these', 'they', 'this', 'those', 'through', 'to', 'too',
|
|
11
|
+
'under', 'until', 'up', 'very', 'was', 'we', 'were', 'what', 'when', 'where', 'which',
|
|
12
|
+
'while', 'who', 'whom', 'why', 'with', 'you', 'your', 'yours', 'yourself', 'yourselves'
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Extracts substantive tokens from query text, filtering out common stopwords
|
|
17
|
+
* and short words (< 3 chars), while falling back to short words if query has no substantive words.
|
|
18
|
+
*/
|
|
19
|
+
export function extractSearchTokens(text: string): string[] {
|
|
20
|
+
const words = text
|
|
21
|
+
.replace(/[^\w\s-]/g, ' ')
|
|
22
|
+
.trim()
|
|
23
|
+
.split(/\s+/)
|
|
24
|
+
.filter(w => w.length > 0);
|
|
25
|
+
|
|
26
|
+
const substantive = words.filter(w => w.length >= 3 && !SEARCH_STOPWORDS.has(w.toLowerCase()));
|
|
27
|
+
return substantive.length > 0 ? substantive : words.filter(w => w.length >= 2);
|
|
28
|
+
}
|