This repository was archived by the owner on Oct 15, 2026. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathwiki.ts
More file actions
106 lines (97 loc) · 3.42 KB
/
Copy pathwiki.ts
File metadata and controls
106 lines (97 loc) · 3.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/**
* Commit-pinned documentation catalog, page reads, and gap analysis.
* Search and index implementations live in focused sibling modules.
*/
import { readPinnedFile } from './git';
import { getContextBrief } from './context-brief';
import { EXPECTED_DOCUMENTS, getDocumentationRows } from './documentation-analysis';
import { loadRegistry } from './registry';
import { documentIndex, MAX_DOCUMENT_BYTES, normalizePath } from './wiki-index';
export { searchDocs } from './wiki-search';
export type { DocSearchHit } from './wiki-search';
export interface CatalogEntry {
name: string;
status: 'indexed' | 'empty' | 'unavailable';
docCount: number;
stale: boolean;
hasReadme: boolean;
hasWikiYaml: boolean;
commitSha: string | null;
confidence: 'direct-source' | 'snapshot' | 'unavailable';
message?: string;
}
export interface DocumentPage {
repository: string;
sourcePath: string;
title: string;
body: string;
commitSha: string | null;
confidence: 'direct-source' | 'snapshot';
snapshotGeneratedAt?: string;
}
export function clearWikiCache(): void {
// Retained as a harmless test helper. GitPin deliberately keeps no cache.
}
export async function getCatalog(): Promise<CatalogEntry[]> {
return loadRegistry().map((repository) => {
try {
const index = documentIndex(repository);
return {
name: repository.name,
status: index.paths.length > 0 ? 'indexed' : 'empty',
docCount: index.paths.length,
stale: index.stale,
hasReadme: index.paths.includes('README.md'),
hasWikiYaml: index.hasWikiYaml,
commitSha: index.commitSha,
confidence: index.confidence,
};
} catch (error) {
return {
name: repository.name,
status: 'unavailable',
docCount: 0,
stale: false,
hasReadme: false,
hasWikiYaml: false,
commitSha: null,
confidence: 'unavailable',
message: error instanceof Error ? error.message : 'Repository could not be indexed.',
};
}
});
}
export async function getDocs(repositoryName: string, sourcePath: string): Promise<DocumentPage | null> {
const repository = loadRegistry().find((entry) => entry.name === repositoryName);
if (!repository) return null;
const index = documentIndex(repository);
if (!index.paths.includes(normalizePath(sourcePath))) return null;
try {
const pinned = readPinnedFile(repositoryName, sourcePath);
if (Buffer.byteLength(pinned.body, 'utf-8') > MAX_DOCUMENT_BYTES) return null;
return {
repository: repositoryName,
sourcePath,
title: pinned.body.match(/^#\s+(.+)$/m)?.[1] ?? sourcePath.split('/').pop() ?? sourcePath,
body: pinned.body,
commitSha: typeof pinned.provenance.commitSha === 'string' ? pinned.provenance.commitSha : null,
confidence: index.confidence,
...(typeof pinned.provenance.snapshotGeneratedAt === 'string'
? { snapshotGeneratedAt: pinned.provenance.snapshotGeneratedAt }
: {}),
};
} catch {
return null;
}
}
export async function getDocGaps(operation: 'gaps' | 'compare' | 'brief', repositories?: string[]) {
if (operation === 'brief') return getContextBrief({ repositories });
const rows = getDocumentationRows(repositories).map(({ sourcePaths: _, ...row }) => row);
if (operation === 'compare') {
return {
categories: EXPECTED_DOCUMENTS.map((expected) => expected.label),
rows,
};
}
return rows;
}