@doccov/sdk 0.8.0 → 0.10.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/dist/index.d.ts +1632 -820
- package/dist/index.js +5732 -4814
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SpecDocDrift, SpecExport } from "@openpkg-ts/spec";
|
|
1
|
+
import { DriftCategory, SpecDocDrift, SpecExport } from "@openpkg-ts/spec";
|
|
2
2
|
interface ExampleRunResult {
|
|
3
3
|
success: boolean;
|
|
4
4
|
stdout: string;
|
|
@@ -48,6 +48,37 @@ declare function runExamplesWithPackage(examples: string[], options: RunExamples
|
|
|
48
48
|
import { OpenPkg } from "@openpkg-ts/spec";
|
|
49
49
|
type OpenPkgSpec = OpenPkg;
|
|
50
50
|
/**
|
|
51
|
+
* Result of computing drift for a single export.
|
|
52
|
+
*/
|
|
53
|
+
type ExportDriftResult = {
|
|
54
|
+
id: string;
|
|
55
|
+
drift: SpecDocDrift[];
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Result of computing drift for all exports.
|
|
59
|
+
*/
|
|
60
|
+
type DriftResult = {
|
|
61
|
+
exports: Map<string, SpecDocDrift[]>;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Build a registry of all export/type names for cross-reference validation.
|
|
65
|
+
*/
|
|
66
|
+
declare function buildExportRegistry(spec: OpenPkgSpec): Set<string>;
|
|
67
|
+
/**
|
|
68
|
+
* Compute drift for all exports in a spec.
|
|
69
|
+
*
|
|
70
|
+
* @param spec - The OpenPkg spec to analyze
|
|
71
|
+
* @returns Drift results per */
|
|
72
|
+
declare function computeDrift(spec: OpenPkgSpec): DriftResult;
|
|
73
|
+
/**
|
|
74
|
+
* Compute drift for a single export.
|
|
75
|
+
*
|
|
76
|
+
* @param entry - The to analyze
|
|
77
|
+
* @param exportRegistry - Registry of known names for link validation
|
|
78
|
+
* @returns Array of drift issues detected
|
|
79
|
+
*/
|
|
80
|
+
declare function computeExportDrift(entry: SpecExport, exportRegistry?: Set<string>): SpecDocDrift[];
|
|
81
|
+
/**
|
|
51
82
|
* Detect runtime errors in @example blocks.
|
|
52
83
|
* Results are provided externally after running examples via runExamples().
|
|
53
84
|
*/
|
|
@@ -70,589 +101,1585 @@ declare function hasNonAssertionComments(code: string): boolean;
|
|
|
70
101
|
*/
|
|
71
102
|
declare function detectExampleAssertionFailures(entry: SpecExport, runtimeResults: Map<number, ExampleRunResult>): SpecDocDrift[];
|
|
72
103
|
/**
|
|
73
|
-
*
|
|
74
|
-
* Used by both CLI (NodeFileSystem) and API (SandboxFileSystem).
|
|
104
|
+
* Extended drift with category and fixability metadata.
|
|
75
105
|
*/
|
|
106
|
+
interface CategorizedDrift extends SpecDocDrift {
|
|
107
|
+
category: DriftCategory;
|
|
108
|
+
fixable: boolean;
|
|
109
|
+
}
|
|
76
110
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
111
|
+
* Categorize a single drift issue.
|
|
112
|
+
*
|
|
113
|
+
* @param drift - The drift to categorize
|
|
114
|
+
* @returns The drift with category and fixable metadata
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```ts
|
|
118
|
+
* const drift: SpecDocDrift = {
|
|
119
|
+
* type: 'param-type-mismatch',
|
|
120
|
+
* target: 'userId',
|
|
121
|
+
* issue: 'Type mismatch'
|
|
122
|
+
* };
|
|
123
|
+
* const categorized = categorizeDrift(drift);
|
|
124
|
+
* console.log(categorized.category); // => 'structural'
|
|
125
|
+
* console.log(categorized.fixable); // => true
|
|
126
|
+
* ```
|
|
79
127
|
*/
|
|
80
|
-
|
|
81
|
-
/** Check if a file or directory exists */
|
|
82
|
-
exists(path: string): Promise<boolean>;
|
|
83
|
-
/** Read file contents as string */
|
|
84
|
-
readFile(path: string): Promise<string>;
|
|
85
|
-
/** List directory contents (file/folder names only) */
|
|
86
|
-
readDir(path: string): Promise<string[]>;
|
|
87
|
-
/** Check if path is a directory */
|
|
88
|
-
isDirectory(path: string): Promise<boolean>;
|
|
89
|
-
}
|
|
90
|
-
/** Supported package managers */
|
|
91
|
-
type PackageManager = "npm" | "yarn" | "pnpm" | "bun";
|
|
92
|
-
/** Package manager detection result with install/run commands */
|
|
93
|
-
interface PackageManagerInfo {
|
|
94
|
-
/** Package manager name */
|
|
95
|
-
name: PackageManager;
|
|
96
|
-
/** Lockfile that was detected (null if none found) */
|
|
97
|
-
lockfile: string | null;
|
|
98
|
-
/** Arguments for install command, e.g. ['install', '--frozen-lockfile'] */
|
|
99
|
-
installArgs: string[];
|
|
100
|
-
/** Prefix for running scripts, e.g. ['npm', 'run'] or ['pnpm'] */
|
|
101
|
-
runPrefix: string[];
|
|
102
|
-
}
|
|
103
|
-
/** Monorepo type based on configuration */
|
|
104
|
-
type MonorepoType = "npm-workspaces" | "pnpm-workspaces" | "lerna" | "none";
|
|
105
|
-
/** Monorepo detection result */
|
|
106
|
-
interface MonorepoInfo {
|
|
107
|
-
/** Whether this is a monorepo */
|
|
108
|
-
isMonorepo: boolean;
|
|
109
|
-
/** Type of monorepo configuration */
|
|
110
|
-
type: MonorepoType;
|
|
111
|
-
/** Workspace patterns from config (e.g. ['packages/*']) */
|
|
112
|
-
patterns: string[];
|
|
113
|
-
/** Resolved workspace packages */
|
|
114
|
-
packages: WorkspacePackage[];
|
|
115
|
-
}
|
|
116
|
-
/** A package within a monorepo workspace */
|
|
117
|
-
interface WorkspacePackage {
|
|
118
|
-
/** Package name from package.json */
|
|
119
|
-
name: string;
|
|
120
|
-
/** Relative path to package directory */
|
|
121
|
-
path: string;
|
|
122
|
-
/** Whether the package is marked as private */
|
|
123
|
-
private: boolean;
|
|
124
|
-
}
|
|
125
|
-
/** Entry point source - where the entry was detected from */
|
|
126
|
-
type EntryPointSource = "types" | "exports" | "main" | "module" | "fallback";
|
|
127
|
-
/** Entry point detection result */
|
|
128
|
-
interface EntryPointInfo {
|
|
129
|
-
/** Path to entry file (relative to package root) */
|
|
130
|
-
path: string;
|
|
131
|
-
/** Where the entry point was detected from */
|
|
132
|
-
source: EntryPointSource;
|
|
133
|
-
/** Whether this is a .d.ts file (no source available) */
|
|
134
|
-
isDeclarationOnly: boolean;
|
|
135
|
-
}
|
|
136
|
-
/** Build configuration detection result */
|
|
137
|
-
interface BuildInfo {
|
|
138
|
-
/** Build-related script names found (e.g. ['build', 'build:types']) */
|
|
139
|
-
scripts: string[];
|
|
140
|
-
/** Whether any build script was found */
|
|
141
|
-
hasBuildScript: boolean;
|
|
142
|
-
/** Whether TypeScript is configured/installed */
|
|
143
|
-
hasTypeScript: boolean;
|
|
144
|
-
/** Indicators for exotic project types */
|
|
145
|
-
exoticIndicators: {
|
|
146
|
-
/** WASM project (Cargo.toml or wasm-pack scripts) */
|
|
147
|
-
wasm: boolean;
|
|
148
|
-
/** napi-rs native addon project */
|
|
149
|
-
napi: boolean;
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
/** Complete project analysis result */
|
|
153
|
-
interface ProjectInfo {
|
|
154
|
-
/** Package manager info */
|
|
155
|
-
packageManager: PackageManagerInfo;
|
|
156
|
-
/** Monorepo info */
|
|
157
|
-
monorepo: MonorepoInfo;
|
|
158
|
-
/** Entry point info */
|
|
159
|
-
entryPoint: EntryPointInfo;
|
|
160
|
-
/** Build info */
|
|
161
|
-
build: BuildInfo;
|
|
162
|
-
}
|
|
163
|
-
/** Options for analyzeProject() */
|
|
164
|
-
interface AnalyzeProjectOptions {
|
|
165
|
-
/** Target package name for monorepos */
|
|
166
|
-
targetPackage?: string;
|
|
167
|
-
}
|
|
128
|
+
declare function categorizeDrift(drift: SpecDocDrift): CategorizedDrift;
|
|
168
129
|
/**
|
|
169
|
-
*
|
|
130
|
+
* Group drifts by category.
|
|
170
131
|
*
|
|
171
|
-
* @param
|
|
172
|
-
* @
|
|
173
|
-
*
|
|
132
|
+
* @param drifts - Array of drift issues to group
|
|
133
|
+
* @returns Drifts organized by category
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* const grouped = groupDriftsByCategory(spec.docs.drift ?? []);
|
|
138
|
+
* console.log(grouped.structural.length); // Number of structural issues
|
|
139
|
+
* console.log(grouped.semantic.length); // Number of semantic issues
|
|
140
|
+
* console.log(grouped.example.length); // Number of example issues
|
|
141
|
+
* ```
|
|
174
142
|
*/
|
|
175
|
-
declare function
|
|
143
|
+
declare function groupDriftsByCategory(drifts: SpecDocDrift[]): Record<DriftCategory, CategorizedDrift[]>;
|
|
176
144
|
/**
|
|
177
|
-
*
|
|
178
|
-
* Prefers 'build' over 'compile' over 'tsc'.
|
|
145
|
+
* Summary of drift issues by category.
|
|
179
146
|
*/
|
|
180
|
-
|
|
147
|
+
interface DriftSummary {
|
|
148
|
+
total: number;
|
|
149
|
+
byCategory: Record<DriftCategory, number>;
|
|
150
|
+
fixable: number;
|
|
151
|
+
}
|
|
181
152
|
/**
|
|
182
|
-
*
|
|
153
|
+
* Get drift summary counts by category.
|
|
183
154
|
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
* 2. package.json -> exports["."].types
|
|
187
|
-
* 3. package.json -> main field (resolve to .ts)
|
|
188
|
-
* 4. package.json -> module field (resolve to .ts)
|
|
189
|
-
* 5. Common fallback paths
|
|
155
|
+
* @param drifts - Array of drift issues
|
|
156
|
+
* @returns Summary with totals, category breakdown, and fixable count
|
|
190
157
|
*
|
|
191
|
-
* @
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* const summary = getDriftSummary(exportEntry.docs?.drift ?? []);
|
|
161
|
+
* console.log(`${summary.total} issues: ${summary.fixable} fixable`);
|
|
162
|
+
* // => "5 issues: 3 fixable"
|
|
163
|
+
* ```
|
|
195
164
|
*/
|
|
196
|
-
declare function
|
|
197
|
-
import { Sandbox } from "@vercel/sandbox";
|
|
165
|
+
declare function getDriftSummary(drifts: SpecDocDrift[]): DriftSummary;
|
|
198
166
|
/**
|
|
199
|
-
*
|
|
200
|
-
*
|
|
167
|
+
* Format drift summary for CLI output (single line).
|
|
168
|
+
*
|
|
169
|
+
* @param summary - Drift summary to format
|
|
170
|
+
* @returns Human-readable summary string
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```ts
|
|
174
|
+
* const summary = getDriftSummary(drifts);
|
|
175
|
+
* console.log(formatDriftSummaryLine(summary));
|
|
176
|
+
* // => "5 issues (3 structural, 1 semantic, 1 example)"
|
|
177
|
+
* ```
|
|
201
178
|
*/
|
|
202
|
-
declare
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
179
|
+
declare function formatDriftSummaryLine(summary: DriftSummary): string;
|
|
180
|
+
import { OpenPkg as OpenPkg2, SpecDocDrift as SpecDocDrift2, SpecDocsMetadata, SpecExport as SpecExport3 } from "@openpkg-ts/spec";
|
|
181
|
+
import { SpecExport as SpecExport2, SpecExportKind } from "@openpkg-ts/spec";
|
|
182
|
+
import * as TS from "typescript";
|
|
183
|
+
/**
|
|
184
|
+
* Represents a single parameter in a JSDoc patch
|
|
185
|
+
*/
|
|
186
|
+
interface JSDocParam {
|
|
187
|
+
name: string;
|
|
188
|
+
type?: string;
|
|
189
|
+
description?: string;
|
|
190
|
+
optional?: boolean;
|
|
210
191
|
}
|
|
211
192
|
/**
|
|
212
|
-
*
|
|
213
|
-
* Uses sandbox.runCommand() with shell commands.
|
|
193
|
+
* Represents a return type in a JSDoc patch
|
|
214
194
|
*/
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
exists(path: string): Promise<boolean>;
|
|
219
|
-
readFile(path: string): Promise<string>;
|
|
220
|
-
readDir(path: string): Promise<string[]>;
|
|
221
|
-
isDirectory(path: string): Promise<boolean>;
|
|
195
|
+
interface JSDocReturn {
|
|
196
|
+
type?: string;
|
|
197
|
+
description?: string;
|
|
222
198
|
}
|
|
223
199
|
/**
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
* Detection triggers (in order):
|
|
227
|
-
* 1. package.json has workspaces field (npm/yarn)
|
|
228
|
-
* 2. pnpm-workspace.yaml exists
|
|
229
|
-
* 3. lerna.json exists
|
|
200
|
+
* Represents a generic tag in a JSDoc patch
|
|
230
201
|
*/
|
|
231
|
-
|
|
202
|
+
interface JSDocTag {
|
|
203
|
+
name: string;
|
|
204
|
+
text: string;
|
|
205
|
+
}
|
|
232
206
|
/**
|
|
233
|
-
*
|
|
207
|
+
* A patchable representation of a JSDoc comment
|
|
234
208
|
*/
|
|
235
|
-
|
|
209
|
+
interface JSDocPatch {
|
|
210
|
+
description?: string;
|
|
211
|
+
params?: JSDocParam[];
|
|
212
|
+
returns?: JSDocReturn;
|
|
213
|
+
examples?: string[];
|
|
214
|
+
deprecated?: string | false;
|
|
215
|
+
async?: boolean;
|
|
216
|
+
type?: string;
|
|
217
|
+
typeParams?: Array<{
|
|
218
|
+
name: string;
|
|
219
|
+
constraint?: string;
|
|
220
|
+
description?: string;
|
|
221
|
+
}>;
|
|
222
|
+
otherTags?: JSDocTag[];
|
|
223
|
+
}
|
|
236
224
|
/**
|
|
237
|
-
*
|
|
225
|
+
* Represents an edit to be applied to a source file
|
|
238
226
|
*/
|
|
239
|
-
|
|
227
|
+
interface JSDocEdit {
|
|
228
|
+
filePath: string;
|
|
229
|
+
symbolName: string;
|
|
230
|
+
startLine: number;
|
|
231
|
+
endLine: number;
|
|
232
|
+
hasExisting: boolean;
|
|
233
|
+
existingJSDoc?: string;
|
|
234
|
+
newJSDoc: string;
|
|
235
|
+
indent: string;
|
|
236
|
+
}
|
|
240
237
|
/**
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
* Resolution order:
|
|
244
|
-
* 1. packageManager field in package.json (e.g., "pnpm@9.0.0")
|
|
245
|
-
* 2. Most recently modified lockfile (when multiple exist)
|
|
246
|
-
* 3. Static priority order: pnpm > bun > yarn > npm
|
|
247
|
-
* 4. Default to npm
|
|
238
|
+
* Result of applying edits to source files
|
|
248
239
|
*/
|
|
249
|
-
|
|
240
|
+
interface ApplyEditsResult {
|
|
241
|
+
filesModified: number;
|
|
242
|
+
editsApplied: number;
|
|
243
|
+
errors: Array<{
|
|
244
|
+
file: string;
|
|
245
|
+
error: string;
|
|
246
|
+
}>;
|
|
247
|
+
}
|
|
250
248
|
/**
|
|
251
|
-
*
|
|
252
|
-
* Returns [command, ...args] array.
|
|
249
|
+
* Parse a JSDoc comment string into a patchable structure
|
|
253
250
|
*/
|
|
254
|
-
declare function
|
|
251
|
+
declare function parseJSDocToPatch(jsDocText: string): JSDocPatch;
|
|
255
252
|
/**
|
|
256
|
-
*
|
|
257
|
-
* Returns [command, ...args, scriptName] array.
|
|
253
|
+
* Apply a partial patch to an existing JSDoc patch, preserving unmodified content
|
|
258
254
|
*/
|
|
259
|
-
declare function
|
|
255
|
+
declare function applyPatchToJSDoc(existing: JSDocPatch, updates: Partial<JSDocPatch>): JSDocPatch;
|
|
260
256
|
/**
|
|
261
|
-
*
|
|
257
|
+
* Serialize a JSDocPatch back to a formatted comment string
|
|
262
258
|
*/
|
|
263
|
-
declare function
|
|
259
|
+
declare function serializeJSDoc(patch: JSDocPatch, indent?: string): string;
|
|
264
260
|
/**
|
|
265
|
-
*
|
|
261
|
+
* Find the JSDoc location for a declaration in a source file
|
|
266
262
|
*/
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
exports?: PackageExports;
|
|
276
|
-
workspaces?: string[] | {
|
|
277
|
-
packages: string[];
|
|
278
|
-
};
|
|
279
|
-
scripts?: Record<string, string>;
|
|
280
|
-
dependencies?: Record<string, string>;
|
|
281
|
-
devDependencies?: Record<string, string>;
|
|
282
|
-
}
|
|
263
|
+
declare function findJSDocLocation(sourceFile: TS.SourceFile, symbolName: string, approximateLine?: number): {
|
|
264
|
+
startLine: number;
|
|
265
|
+
endLine: number;
|
|
266
|
+
declarationLine: number;
|
|
267
|
+
hasExisting: boolean;
|
|
268
|
+
existingJSDoc?: string;
|
|
269
|
+
indent: string;
|
|
270
|
+
} | null;
|
|
283
271
|
/**
|
|
284
|
-
*
|
|
272
|
+
* Apply a batch of edits to source files
|
|
285
273
|
*/
|
|
286
|
-
|
|
287
|
-
"."?: string | {
|
|
288
|
-
types?: string;
|
|
289
|
-
import?: string;
|
|
290
|
-
require?: string;
|
|
291
|
-
default?: string;
|
|
292
|
-
};
|
|
293
|
-
[key: string]: unknown;
|
|
294
|
-
};
|
|
274
|
+
declare function applyEdits(edits: JSDocEdit[]): Promise<ApplyEditsResult>;
|
|
295
275
|
/**
|
|
296
|
-
*
|
|
276
|
+
* Create a TypeScript source file from a file path
|
|
297
277
|
*/
|
|
298
|
-
declare function
|
|
278
|
+
declare function createSourceFile(filePath: string): TS.SourceFile;
|
|
299
279
|
/**
|
|
300
|
-
*
|
|
301
|
-
*
|
|
302
|
-
* This is the main entry point for project detection. It combines all
|
|
303
|
-
* detection functions into a single call that returns complete project info.
|
|
304
|
-
*
|
|
305
|
-
* For monorepos, you must specify the target package via options.targetPackage.
|
|
306
|
-
* If not specified and a monorepo is detected, an error is thrown with the
|
|
307
|
-
* list of available packages.
|
|
308
|
-
*
|
|
309
|
-
* @param fs - FileSystem implementation (NodeFileSystem or SandboxFileSystem)
|
|
310
|
-
* @param options - Options including targetPackage for monorepos
|
|
311
|
-
* @returns Complete project info
|
|
312
|
-
* @throws Error if monorepo detected without targetPackage specified
|
|
313
|
-
* @throws Error if targetPackage not found in monorepo
|
|
314
|
-
*
|
|
315
|
-
* @example
|
|
316
|
-
* ```typescript
|
|
317
|
-
* import { NodeFileSystem, analyzeProject } from '@doccov/sdk';
|
|
318
|
-
*
|
|
319
|
-
* // Single package
|
|
320
|
-
* const singleFs = new NodeFileSystem('/path/to/package');
|
|
321
|
-
* const singleProject = await analyzeProject(singleFs);
|
|
322
|
-
*
|
|
323
|
-
* // Monorepo with target package
|
|
324
|
-
* const monoFs = new NodeFileSystem('/path/to/monorepo');
|
|
325
|
-
* const monoProject = await analyzeProject(monoFs, { targetPackage: '@scope/core' });
|
|
326
|
-
* ```
|
|
280
|
+
* Quality rule severity levels.
|
|
327
281
|
*/
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
/** @deprecated Use DocCovOptions instead */
|
|
336
|
-
type OpenPkgOptions = DocCovOptions;
|
|
337
|
-
declare function extractPackageSpec(entryFile: string, packageDir?: string, content?: string, options?: OpenPkgOptions): Promise<OpenPkgSpec>;
|
|
338
|
-
interface FilterOptions {
|
|
339
|
-
include?: string[];
|
|
340
|
-
exclude?: string[];
|
|
282
|
+
type QualitySeverity = "error" | "warn" | "off";
|
|
283
|
+
/**
|
|
284
|
+
* Context passed to quality rule checks.
|
|
285
|
+
*/
|
|
286
|
+
interface RuleContext {
|
|
287
|
+
export: SpecExport2;
|
|
288
|
+
rawJSDoc?: string;
|
|
341
289
|
}
|
|
342
290
|
/**
|
|
343
|
-
*
|
|
344
|
-
* These types are shared between CLI and API.
|
|
291
|
+
* A violation reported by a quality rule.
|
|
345
292
|
*/
|
|
293
|
+
interface QualityViolation {
|
|
294
|
+
ruleId: string;
|
|
295
|
+
severity: "error" | "warn";
|
|
296
|
+
message: string;
|
|
297
|
+
line?: number;
|
|
298
|
+
fixable: boolean;
|
|
299
|
+
}
|
|
346
300
|
/**
|
|
347
|
-
*
|
|
301
|
+
* A quality rule checks one aspect of documentation quality.
|
|
302
|
+
* Rules can contribute to coverage score, lint violations, or both.
|
|
348
303
|
*/
|
|
349
|
-
interface
|
|
350
|
-
/**
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
|
|
304
|
+
interface QualityRule {
|
|
305
|
+
/** Unique rule identifier */
|
|
306
|
+
id: string;
|
|
307
|
+
/** Human-readable name */
|
|
308
|
+
name: string;
|
|
309
|
+
/** What this rule checks */
|
|
310
|
+
description: string;
|
|
311
|
+
/**
|
|
312
|
+
* Which kinds this rule applies to.
|
|
313
|
+
* If undefined, applies to all kinds.
|
|
314
|
+
*/
|
|
315
|
+
appliesTo?: SpecExportKind[];
|
|
316
|
+
/**
|
|
317
|
+
* Does this rule contribute to coverage score?
|
|
318
|
+
* If true, the rule is counted as a "signal" for coverage calculation.
|
|
319
|
+
*/
|
|
320
|
+
affectsCoverage: boolean;
|
|
321
|
+
/**
|
|
322
|
+
* Default lint severity. Set to 'off' if rule is coverage-only.
|
|
323
|
+
*/
|
|
324
|
+
defaultSeverity: QualitySeverity;
|
|
325
|
+
/**
|
|
326
|
+
* Check if the satisfies this rule.
|
|
327
|
+
* Returns true if satisfied, false if not.
|
|
328
|
+
*/
|
|
329
|
+
check(ctx: RuleContext): boolean;
|
|
330
|
+
/**
|
|
331
|
+
* Get detailed violation info when check returns false.
|
|
332
|
+
* Only called if check() returns false and severity !== 'off'.
|
|
333
|
+
*/
|
|
334
|
+
getViolation?(ctx: RuleContext): QualityViolation;
|
|
335
|
+
/**
|
|
336
|
+
* Generate a fix for the violation.
|
|
337
|
+
* Only called if check() returns false and fix is requested.
|
|
338
|
+
*/
|
|
339
|
+
fix?(ctx: RuleContext): JSDocPatch | null;
|
|
354
340
|
}
|
|
355
341
|
/**
|
|
356
|
-
*
|
|
342
|
+
* User configuration for quality rules.
|
|
357
343
|
*/
|
|
358
|
-
interface
|
|
359
|
-
|
|
360
|
-
lint?: boolean;
|
|
361
|
-
/** Enable typecheck for examples (default: true) */
|
|
362
|
-
typecheck?: boolean;
|
|
363
|
-
/** Enable runtime execution of examples (default: false) */
|
|
364
|
-
exec?: boolean;
|
|
344
|
+
interface QualityConfig {
|
|
345
|
+
rules: Record<string, QualitySeverity>;
|
|
365
346
|
}
|
|
366
347
|
/**
|
|
367
|
-
*
|
|
348
|
+
* Result of evaluating quality for a single export.
|
|
368
349
|
*/
|
|
369
|
-
|
|
350
|
+
interface QualityResult {
|
|
351
|
+
/** Coverage score (0-100) */
|
|
352
|
+
coverageScore: number;
|
|
353
|
+
/** Coverage details */
|
|
354
|
+
coverage: {
|
|
355
|
+
/** Rule IDs that passed */
|
|
356
|
+
satisfied: string[];
|
|
357
|
+
/** Rule IDs that failed */
|
|
358
|
+
missing: string[];
|
|
359
|
+
/** All applicable rule IDs */
|
|
360
|
+
applicable: string[];
|
|
361
|
+
};
|
|
362
|
+
/** Lint violations (only for rules with severity !== 'off') */
|
|
363
|
+
violations: QualityViolation[];
|
|
364
|
+
/** Summary counts */
|
|
365
|
+
summary: {
|
|
366
|
+
errorCount: number;
|
|
367
|
+
warningCount: number;
|
|
368
|
+
fixableCount: number;
|
|
369
|
+
};
|
|
370
|
+
}
|
|
370
371
|
/**
|
|
371
|
-
*
|
|
372
|
+
* Aggregate result for multiple exports.
|
|
372
373
|
*/
|
|
373
|
-
interface
|
|
374
|
-
|
|
375
|
-
|
|
374
|
+
interface AggregateQualityResult {
|
|
375
|
+
byExport: Map<string, QualityResult>;
|
|
376
|
+
overall: {
|
|
377
|
+
coverageScore: number;
|
|
378
|
+
totalViolations: number;
|
|
379
|
+
errorCount: number;
|
|
380
|
+
warningCount: number;
|
|
381
|
+
};
|
|
376
382
|
}
|
|
377
383
|
/**
|
|
378
|
-
*
|
|
379
|
-
*
|
|
384
|
+
* An enriched with computed documentation metadata.
|
|
385
|
+
* Extends SpecExport with the `docs` field for coverage analysis.
|
|
380
386
|
*/
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
387
|
+
type EnrichedExport = SpecExport3 & {
|
|
388
|
+
docs?: EnrichedDocsMetadata;
|
|
389
|
+
};
|
|
390
|
+
/**
|
|
391
|
+
* Extended docs metadata with quality violations.
|
|
392
|
+
*/
|
|
393
|
+
type EnrichedDocsMetadata = SpecDocsMetadata & {
|
|
394
|
+
violations?: QualityViolation[];
|
|
395
|
+
};
|
|
396
|
+
/**
|
|
397
|
+
* An enriched OpenPkg spec with computed documentation metadata.
|
|
398
|
+
* Extends OpenPkg with per-and aggregate coverage data.
|
|
399
|
+
*/
|
|
400
|
+
type EnrichedOpenPkg = Omit<OpenPkg2, "exports"> & {
|
|
401
|
+
exports: EnrichedExport[];
|
|
402
|
+
docs?: EnrichedDocsMetadata;
|
|
403
|
+
/** Drift summary with category breakdown (if drift exists) */
|
|
404
|
+
driftSummary?: DriftSummary;
|
|
405
|
+
};
|
|
406
|
+
interface EnrichOptions {
|
|
407
|
+
/**
|
|
408
|
+
* Per-drift issues to include in enrichment.
|
|
409
|
+
* Map from ID to drift issues.
|
|
410
|
+
*/
|
|
411
|
+
driftByExport?: Map<string, SpecDocDrift2[]>;
|
|
412
|
+
/**
|
|
413
|
+
* Quality configuration with rule severities.
|
|
414
|
+
*/
|
|
415
|
+
qualityConfig?: QualityConfig;
|
|
416
|
+
/**
|
|
417
|
+
* Per-raw JSDoc text for style rule checks.
|
|
418
|
+
* Map from ID to raw JSDoc string.
|
|
419
|
+
*/
|
|
420
|
+
rawJSDocByExport?: Map<string, string>;
|
|
394
421
|
}
|
|
395
422
|
/**
|
|
396
|
-
*
|
|
397
|
-
* Helper function for type-safe configuration in doccov.config.ts.
|
|
423
|
+
* Enrich an OpenPkg spec with documentation coverage metadata.
|
|
398
424
|
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
425
|
+
* This function computes coverage scores using quality rules,
|
|
426
|
+
* detects drift issues, and produces an EnrichedOpenPkg.
|
|
427
|
+
*
|
|
428
|
+
* @param spec - The pure OpenPkg spec to enrich
|
|
429
|
+
* @param options - Optional enrichment configuration
|
|
430
|
+
* @returns An enriched spec with documentation metadata
|
|
401
431
|
*
|
|
402
432
|
* @example
|
|
403
|
-
* ```
|
|
404
|
-
*
|
|
405
|
-
* import { defineConfig } from '@doccov/sdk';
|
|
433
|
+
* ```ts
|
|
434
|
+
* import { DocCov, enrichSpec } from '@doccov/sdk';
|
|
406
435
|
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
* rules: {
|
|
415
|
-
* 'require-description': 'error',
|
|
416
|
-
* 'require-example': 'warn',
|
|
417
|
-
* },
|
|
418
|
-
* },
|
|
419
|
-
* });
|
|
436
|
+
* const doccov = new DocCov();
|
|
437
|
+
* const { spec } = await doccov.analyzeFileWithDiagnostics('src/index.ts');
|
|
438
|
+
*
|
|
439
|
+
* // Enrich with coverage data
|
|
440
|
+
* const enriched = enrichSpec(spec);
|
|
441
|
+
* console.log(enriched.docs?.coverageScore); // e.g., 85
|
|
442
|
+
* console.log(enriched.docs?.missing); // e.g., ['has-examples']
|
|
420
443
|
* ```
|
|
421
444
|
*/
|
|
422
|
-
declare function
|
|
445
|
+
declare function enrichSpec(spec: OpenPkg2, options?: EnrichOptions): EnrichedOpenPkg;
|
|
446
|
+
import { OpenPkg as OpenPkg3 } from "@openpkg-ts/spec";
|
|
447
|
+
import { DriftCategory as DriftCategory2, SpecDocDrift as SpecDocDrift3 } from "@openpkg-ts/spec";
|
|
423
448
|
/**
|
|
424
|
-
*
|
|
449
|
+
* DocCov report schema version.
|
|
425
450
|
*/
|
|
426
|
-
|
|
451
|
+
declare const REPORT_VERSION = "1.0.0";
|
|
427
452
|
/**
|
|
428
|
-
*
|
|
453
|
+
* Default directory for DocCov outputs.
|
|
429
454
|
*/
|
|
430
|
-
|
|
431
|
-
/** Include patterns */
|
|
432
|
-
include?: string[];
|
|
433
|
-
/** Exclude patterns */
|
|
434
|
-
exclude?: string[];
|
|
435
|
-
/** Source of the filters */
|
|
436
|
-
source?: FilterSource;
|
|
437
|
-
/** Whether filters were applied from config */
|
|
438
|
-
fromConfig: boolean;
|
|
439
|
-
/** Whether filters were applied from overrides */
|
|
440
|
-
fromOverride: boolean;
|
|
441
|
-
}
|
|
455
|
+
declare const DEFAULT_REPORT_DIR = ".doccov";
|
|
442
456
|
/**
|
|
443
|
-
*
|
|
444
|
-
*
|
|
445
|
-
* @param value - String or string array from CLI flag
|
|
446
|
-
* @returns Parsed array, or undefined if empty
|
|
447
|
-
*
|
|
448
|
-
* @example
|
|
449
|
-
* ```typescript
|
|
450
|
-
* parseListFlag('a,b,c'); // ['a', 'b', 'c']
|
|
451
|
-
* parseListFlag(['a,b', 'c']); // ['a', 'b', 'c']
|
|
452
|
-
* parseListFlag(undefined); // undefined
|
|
453
|
-
* ```
|
|
457
|
+
* Default path for cached DocCov reports.
|
|
454
458
|
*/
|
|
455
|
-
declare
|
|
459
|
+
declare const DEFAULT_REPORT_PATH = ".doccov/report.json";
|
|
456
460
|
/**
|
|
457
|
-
*
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
*
|
|
461
|
+
* File extensions for each report format.
|
|
462
|
+
*/
|
|
463
|
+
declare const REPORT_EXTENSIONS: Record<string, string>;
|
|
464
|
+
/**
|
|
465
|
+
* Get the default report path for a given format.
|
|
462
466
|
*
|
|
463
|
-
* @param
|
|
464
|
-
* @param
|
|
465
|
-
* @returns
|
|
467
|
+
* @param format - The report format (json, markdown, html, github)
|
|
468
|
+
* @param dir - The output directory (defaults to .doccov)
|
|
469
|
+
* @returns The full path to the report file
|
|
466
470
|
*
|
|
467
471
|
* @example
|
|
468
|
-
* ```
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
*
|
|
472
|
-
* const resolved = mergeFilters(config, overrides);
|
|
473
|
-
* // resolved.include = ['B', 'C'] (intersection)
|
|
472
|
+
* ```ts
|
|
473
|
+
* getReportPath('markdown'); // '.doccov/report.md'
|
|
474
|
+
* getReportPath('html', 'reports'); // 'reports/report.html'
|
|
474
475
|
* ```
|
|
475
476
|
*/
|
|
476
|
-
declare function
|
|
477
|
-
import { SpecDocDrift as SpecDocDrift2, SpecExport as SpecExport2 } from "@openpkg-ts/spec";
|
|
478
|
-
import * as TS from "typescript";
|
|
477
|
+
declare function getReportPath(format: string, dir?: string): string;
|
|
479
478
|
/**
|
|
480
|
-
*
|
|
479
|
+
* Drift summary with category breakdown.
|
|
481
480
|
*/
|
|
482
|
-
interface
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
481
|
+
interface DriftReportSummary {
|
|
482
|
+
/**
|
|
483
|
+
* Total number of drift issues.
|
|
484
|
+
*/
|
|
485
|
+
total: number;
|
|
486
|
+
/**
|
|
487
|
+
* Count of issues per category.
|
|
488
|
+
*/
|
|
489
|
+
byCategory: Record<DriftCategory2, number>;
|
|
490
|
+
/**
|
|
491
|
+
* Number of auto-fixable issues.
|
|
492
|
+
*/
|
|
493
|
+
fixable: number;
|
|
487
494
|
}
|
|
488
495
|
/**
|
|
489
|
-
*
|
|
496
|
+
* Drift report with progressive disclosure structure.
|
|
497
|
+
*
|
|
498
|
+
* Provides three levels of detail:
|
|
499
|
+
* 1. Summary - total counts by category
|
|
500
|
+
* 2. By category - grouped drift issues
|
|
501
|
+
* 3. All - flat list for backward compatibility
|
|
490
502
|
*/
|
|
491
|
-
interface
|
|
492
|
-
|
|
493
|
-
|
|
503
|
+
interface DriftReport {
|
|
504
|
+
/**
|
|
505
|
+
* High-level summary counts.
|
|
506
|
+
*/
|
|
507
|
+
summary: DriftReportSummary;
|
|
508
|
+
/**
|
|
509
|
+
* Issues grouped by category.
|
|
510
|
+
*/
|
|
511
|
+
byCategory: Record<DriftCategory2, CategorizedDrift[]>;
|
|
512
|
+
/**
|
|
513
|
+
* Flat list of all drift issues (backward compatible).
|
|
514
|
+
*/
|
|
515
|
+
all: CategorizedDrift[];
|
|
494
516
|
}
|
|
495
517
|
/**
|
|
496
|
-
*
|
|
518
|
+
* Coverage summary for an entire package or project.
|
|
497
519
|
*/
|
|
498
|
-
interface
|
|
499
|
-
|
|
500
|
-
|
|
520
|
+
interface CoverageSummary {
|
|
521
|
+
/**
|
|
522
|
+
* Overall coverage score (0-100).
|
|
523
|
+
*/
|
|
524
|
+
score: number;
|
|
525
|
+
/**
|
|
526
|
+
* Total number of exports analyzed.
|
|
527
|
+
*/
|
|
528
|
+
totalExports: number;
|
|
529
|
+
/**
|
|
530
|
+
* Number of fully documented exports.
|
|
531
|
+
*/
|
|
532
|
+
documentedExports: number;
|
|
533
|
+
/**
|
|
534
|
+
* Breakdown of missing documentation by rule ID.
|
|
535
|
+
*/
|
|
536
|
+
missingByRule: Record<string, number>;
|
|
537
|
+
/**
|
|
538
|
+
* Total number of drift issues detected.
|
|
539
|
+
*/
|
|
540
|
+
driftCount: number;
|
|
541
|
+
/**
|
|
542
|
+
* Drift summary with category breakdown.
|
|
543
|
+
*/
|
|
544
|
+
driftSummary?: DriftReportSummary;
|
|
501
545
|
}
|
|
502
546
|
/**
|
|
503
|
-
*
|
|
547
|
+
* Coverage data for a single export.
|
|
504
548
|
*/
|
|
505
|
-
interface
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
549
|
+
interface ExportCoverageData {
|
|
550
|
+
/**
|
|
551
|
+
* Export name.
|
|
552
|
+
*/
|
|
553
|
+
name: string;
|
|
554
|
+
/**
|
|
555
|
+
* Export kind (function, class, etc.).
|
|
556
|
+
*/
|
|
557
|
+
kind: string;
|
|
558
|
+
/**
|
|
559
|
+
* Coverage score for this (0-100).
|
|
560
|
+
*/
|
|
561
|
+
coverageScore: number;
|
|
562
|
+
/**
|
|
563
|
+
* Missing documentation rule IDs.
|
|
564
|
+
*/
|
|
565
|
+
missing?: string[];
|
|
566
|
+
/**
|
|
567
|
+
* Drift issues for this export.
|
|
568
|
+
*/
|
|
569
|
+
drift?: SpecDocDrift3[];
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* DocCov report - a persistable coverage analysis result.
|
|
573
|
+
*
|
|
574
|
+
* This is the format saved to `.doccov/report.json` and returned
|
|
575
|
+
* by the `check` command with `--format json`.
|
|
576
|
+
*/
|
|
577
|
+
interface DocCovReport {
|
|
578
|
+
/**
|
|
579
|
+
* JSON Schema reference for validation.
|
|
580
|
+
*/
|
|
581
|
+
$schema: string;
|
|
582
|
+
/**
|
|
583
|
+
* Report format version.
|
|
584
|
+
*/
|
|
585
|
+
version: string;
|
|
586
|
+
/**
|
|
587
|
+
* ISO 8601 timestamp when report was generated.
|
|
588
|
+
*/
|
|
589
|
+
generatedAt: string;
|
|
590
|
+
/**
|
|
591
|
+
* Package/project metadata.
|
|
592
|
+
*/
|
|
593
|
+
spec: {
|
|
514
594
|
name: string;
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
595
|
+
version?: string;
|
|
596
|
+
};
|
|
597
|
+
/**
|
|
598
|
+
* Aggregate coverage summary.
|
|
599
|
+
*/
|
|
600
|
+
coverage: CoverageSummary;
|
|
601
|
+
/**
|
|
602
|
+
* Per-coverage data, keyed by ID.
|
|
603
|
+
*/
|
|
604
|
+
exports: Record<string, ExportCoverageData>;
|
|
519
605
|
}
|
|
520
606
|
/**
|
|
521
|
-
*
|
|
607
|
+
* Generate a DocCov report from an OpenPkg spec.
|
|
608
|
+
*
|
|
609
|
+
* @param spec - The pure OpenPkg spec to analyze
|
|
610
|
+
* @returns A DocCov report with coverage analysis
|
|
611
|
+
*
|
|
612
|
+
* @example
|
|
613
|
+
* ```ts
|
|
614
|
+
* import { DocCov, generateReport } from '@doccov/sdk';
|
|
615
|
+
*
|
|
616
|
+
* const doccov = new DocCov();
|
|
617
|
+
* const { spec } = await doccov.analyzeFileWithDiagnostics('src/index.ts');
|
|
618
|
+
* const report = generateReport(spec);
|
|
619
|
+
*
|
|
620
|
+
* console.log(`Coverage: ${report.coverage.score}%`);
|
|
621
|
+
* ```
|
|
522
622
|
*/
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
623
|
+
declare function generateReport(spec: OpenPkg3): DocCovReport;
|
|
624
|
+
/**
|
|
625
|
+
* Generate a DocCov report from an already-enriched spec.
|
|
626
|
+
*
|
|
627
|
+
* Use this when you've already called enrichSpec() and want to avoid
|
|
628
|
+
* recomputing coverage data.
|
|
629
|
+
*
|
|
630
|
+
* @param enriched - The enriched OpenPkg spec
|
|
631
|
+
* @returns A DocCov report with coverage analysis
|
|
632
|
+
*/
|
|
633
|
+
declare function generateReportFromEnriched(enriched: EnrichedOpenPkg): DocCovReport;
|
|
634
|
+
/**
|
|
635
|
+
* Load a cached DocCov report from disk.
|
|
636
|
+
*
|
|
637
|
+
* @param reportPath - Path to the report file (defaults to .doccov/report.json)
|
|
638
|
+
* @returns The cached report, or null if not found
|
|
639
|
+
*/
|
|
640
|
+
declare function loadCachedReport(reportPath?: string): DocCovReport | null;
|
|
641
|
+
/**
|
|
642
|
+
* Save a DocCov report to disk.
|
|
643
|
+
*
|
|
644
|
+
* @param report - The report to save
|
|
645
|
+
* @param reportPath - Path to save the report (defaults to .doccov/report.json)
|
|
646
|
+
*/
|
|
647
|
+
declare function saveReport(report: DocCovReport, reportPath?: string): void;
|
|
648
|
+
/**
|
|
649
|
+
* Check if a cached report is still valid.
|
|
650
|
+
*
|
|
651
|
+
* A report is considered stale if:
|
|
652
|
+
* - It doesn't exist
|
|
653
|
+
* - The spec version has changed
|
|
654
|
+
* - Source files have been modified since generation
|
|
655
|
+
*
|
|
656
|
+
* @param reportPath - Path to the report file
|
|
657
|
+
* @param sourceFiles - Source files to check modification times against
|
|
658
|
+
* @returns True if the cached report is still valid
|
|
659
|
+
*/
|
|
660
|
+
declare function isCachedReportValid(reportPath?: string, sourceFiles?: string[]): boolean;
|
|
661
|
+
/**
|
|
662
|
+
* Compute a hash of file contents.
|
|
663
|
+
* Uses truncated SHA-256 for balance of speed and collision resistance.
|
|
664
|
+
*
|
|
665
|
+
* @param filePath - Absolute path to the file
|
|
666
|
+
* @returns 16-character hex hash, or null if file doesn't exist
|
|
667
|
+
*/
|
|
668
|
+
declare function hashFile(filePath: string): string | null;
|
|
669
|
+
/**
|
|
670
|
+
* Hash a string value.
|
|
671
|
+
*
|
|
672
|
+
* @param content - String to hash
|
|
673
|
+
* @returns 16-character hex hash
|
|
674
|
+
*/
|
|
675
|
+
declare function hashString(content: string): string;
|
|
676
|
+
/**
|
|
677
|
+
* Hash multiple files and return a map of relative paths to hashes.
|
|
678
|
+
*
|
|
679
|
+
* @param filePaths - Array of absolute file paths
|
|
680
|
+
* @param cwd - Base directory for relative path calculation
|
|
681
|
+
* @returns Map of relative paths to their content hashes
|
|
682
|
+
*/
|
|
683
|
+
declare function hashFiles(filePaths: string[], cwd: string): Record<string, string>;
|
|
684
|
+
/**
|
|
685
|
+
* Compare two hash maps and return changed files.
|
|
686
|
+
*
|
|
687
|
+
* @param cached - Hash map from cache
|
|
688
|
+
* @param current - Current hash map
|
|
689
|
+
* @returns Array of file paths that changed, were added, or were removed
|
|
690
|
+
*/
|
|
691
|
+
declare function diffHashes(cached: Record<string, string>, current: Record<string, string>): string[];
|
|
692
|
+
import { OpenPkg as OpenPkg4 } from "@openpkg-ts/spec";
|
|
693
|
+
/** Current cache format version */
|
|
694
|
+
declare const CACHE_VERSION = "1.0.0";
|
|
695
|
+
/** Default cache file path */
|
|
696
|
+
declare const SPEC_CACHE_FILE = ".doccov/spec.cache.json";
|
|
697
|
+
/**
|
|
698
|
+
* Configuration that affects spec generation output.
|
|
699
|
+
*/
|
|
700
|
+
interface SpecCacheConfig {
|
|
701
|
+
resolveExternalTypes: boolean;
|
|
532
702
|
}
|
|
533
703
|
/**
|
|
534
|
-
*
|
|
704
|
+
* Cached spec with validation metadata.
|
|
535
705
|
*/
|
|
536
|
-
interface
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
706
|
+
interface SpecCache {
|
|
707
|
+
/** Cache format version for migrations */
|
|
708
|
+
cacheVersion: string;
|
|
709
|
+
/** When cache was generated (ISO timestamp) */
|
|
710
|
+
generatedAt: string;
|
|
711
|
+
/** OpenPkg spec version (e.g., "0.3.0") */
|
|
712
|
+
specVersion: string;
|
|
713
|
+
/** Entry file that was analyzed (relative path) */
|
|
714
|
+
entryFile: string;
|
|
715
|
+
/** Hash validation data */
|
|
716
|
+
hashes: {
|
|
717
|
+
/** Hash of tsconfig.json content (null if not found) */
|
|
718
|
+
tsconfig: string | null;
|
|
719
|
+
/** Hash of package.json content */
|
|
720
|
+
packageJson: string;
|
|
721
|
+
/** Source file hashes: relative filepath → content hash */
|
|
722
|
+
sourceFiles: Record<string, string>;
|
|
723
|
+
};
|
|
724
|
+
/** Analysis configuration that affects output */
|
|
725
|
+
config: SpecCacheConfig;
|
|
726
|
+
/** The cached OpenPkg spec */
|
|
727
|
+
spec: OpenPkg4;
|
|
543
728
|
}
|
|
544
729
|
/**
|
|
545
|
-
*
|
|
730
|
+
* Result of cache validation.
|
|
546
731
|
*/
|
|
547
|
-
|
|
732
|
+
interface CacheValidationResult {
|
|
733
|
+
/** Whether the cache is valid */
|
|
734
|
+
valid: boolean;
|
|
735
|
+
/** Reason for invalidation (if invalid) */
|
|
736
|
+
reason?: "cache-version-mismatch" | "entry-file-changed" | "config-changed" | "tsconfig-changed" | "package-json-changed" | "source-files-changed";
|
|
737
|
+
/** Files that changed (if reason is source-files-changed) */
|
|
738
|
+
changedFiles?: string[];
|
|
739
|
+
}
|
|
548
740
|
/**
|
|
549
|
-
*
|
|
741
|
+
* Context needed for cache operations.
|
|
550
742
|
*/
|
|
551
|
-
|
|
743
|
+
interface CacheContext {
|
|
744
|
+
/** Entry file being analyzed (absolute path) */
|
|
745
|
+
entryFile: string;
|
|
746
|
+
/** Source files included in analysis (absolute paths) */
|
|
747
|
+
sourceFiles: string[];
|
|
748
|
+
/** Path to tsconfig.json (absolute, or null if not found) */
|
|
749
|
+
tsconfigPath: string | null;
|
|
750
|
+
/** Path to package.json (absolute) */
|
|
751
|
+
packageJsonPath: string;
|
|
752
|
+
/** Configuration that affects output */
|
|
753
|
+
config: SpecCacheConfig;
|
|
754
|
+
/** Working directory */
|
|
755
|
+
cwd: string;
|
|
756
|
+
}
|
|
552
757
|
/**
|
|
553
|
-
*
|
|
758
|
+
* Load cached spec from disk.
|
|
759
|
+
*
|
|
760
|
+
* @param cwd - Working directory
|
|
761
|
+
* @returns Cached spec, or null if not found or invalid JSON
|
|
554
762
|
*/
|
|
555
|
-
declare function
|
|
763
|
+
declare function loadSpecCache(cwd: string): SpecCache | null;
|
|
556
764
|
/**
|
|
557
|
-
*
|
|
765
|
+
* Save spec to cache.
|
|
766
|
+
*
|
|
767
|
+
* @param spec - OpenPkg spec to cache
|
|
768
|
+
* @param context - Cache context with file paths and config
|
|
558
769
|
*/
|
|
559
|
-
declare function
|
|
560
|
-
startLine: number;
|
|
561
|
-
endLine: number;
|
|
562
|
-
declarationLine: number;
|
|
563
|
-
hasExisting: boolean;
|
|
564
|
-
existingJSDoc?: string;
|
|
565
|
-
indent: string;
|
|
566
|
-
} | null;
|
|
770
|
+
declare function saveSpecCache(spec: OpenPkg4, context: CacheContext): void;
|
|
567
771
|
/**
|
|
568
|
-
*
|
|
772
|
+
* Validate if cached spec is still valid.
|
|
773
|
+
*
|
|
774
|
+
* Checks:
|
|
775
|
+
* 1. Cache version matches
|
|
776
|
+
* 2. Entry file matches
|
|
777
|
+
* 3. Config matches
|
|
778
|
+
* 4. tsconfig.json hash matches
|
|
779
|
+
* 5. package.json hash matches
|
|
780
|
+
* 6. All source file hashes match
|
|
781
|
+
*
|
|
782
|
+
* @param cache - Cached spec to validate
|
|
783
|
+
* @param context - Current cache context
|
|
784
|
+
* @returns Validation result
|
|
569
785
|
*/
|
|
570
|
-
declare function
|
|
786
|
+
declare function validateSpecCache(cache: SpecCache, context: CacheContext): CacheValidationResult;
|
|
571
787
|
/**
|
|
572
|
-
*
|
|
788
|
+
* Clear the spec cache.
|
|
789
|
+
*
|
|
790
|
+
* @param cwd - Working directory
|
|
791
|
+
* @returns True if cache was deleted, false if it didn't exist
|
|
573
792
|
*/
|
|
574
|
-
declare function
|
|
793
|
+
declare function clearSpecCache(cwd: string): boolean;
|
|
575
794
|
/**
|
|
576
|
-
*
|
|
795
|
+
* Get cache file path for a given working directory.
|
|
796
|
+
*
|
|
797
|
+
* @param cwd - Working directory
|
|
798
|
+
* @returns Absolute path to cache file
|
|
577
799
|
*/
|
|
578
|
-
|
|
800
|
+
declare function getSpecCachePath(cwd: string): string;
|
|
579
801
|
/**
|
|
580
|
-
*
|
|
802
|
+
* Configuration types for DocCov.
|
|
803
|
+
* These types are shared between CLI and API.
|
|
581
804
|
*/
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
805
|
+
/**
|
|
806
|
+
* Documentation configuration options.
|
|
807
|
+
*/
|
|
808
|
+
interface DocsConfig {
|
|
809
|
+
/** Glob patterns for markdown docs to include */
|
|
810
|
+
include?: string[];
|
|
811
|
+
/** Glob patterns for markdown docs to exclude */
|
|
812
|
+
exclude?: string[];
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Example validation modes.
|
|
816
|
+
*/
|
|
817
|
+
type ExampleValidationMode = "presence" | "typecheck" | "run";
|
|
818
|
+
/**
|
|
819
|
+
* Check command configuration options.
|
|
820
|
+
*/
|
|
821
|
+
interface CheckConfig {
|
|
822
|
+
/**
|
|
823
|
+
* Example validation modes to run.
|
|
824
|
+
* Can be a single mode, array of modes, or comma-separated string.
|
|
825
|
+
* - 'presence': Check that @example blocks exist on exports
|
|
826
|
+
* - 'typecheck': Compile examples with TypeScript
|
|
827
|
+
* - 'run': Execute examples and validate assertions
|
|
828
|
+
*/
|
|
829
|
+
examples?: ExampleValidationMode | ExampleValidationMode[] | string;
|
|
830
|
+
/** Minimum coverage percentage required (0-100) */
|
|
831
|
+
minCoverage?: number;
|
|
832
|
+
/** Maximum drift percentage allowed (0-100) */
|
|
833
|
+
maxDrift?: number;
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* Quality rule severity level.
|
|
837
|
+
*/
|
|
838
|
+
type QualitySeverity2 = "error" | "warn" | "off";
|
|
839
|
+
/**
|
|
840
|
+
* Quality rules configuration.
|
|
841
|
+
*/
|
|
842
|
+
interface QualityRulesConfig {
|
|
843
|
+
/** Rule severity overrides */
|
|
844
|
+
rules?: Record<string, QualitySeverity2>;
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* Normalized DocCov configuration.
|
|
848
|
+
* This is the parsed/normalized form used by commands.
|
|
849
|
+
*/
|
|
850
|
+
interface DocCovConfig {
|
|
851
|
+
/** Export include patterns */
|
|
852
|
+
include?: string[];
|
|
853
|
+
/** Export exclude patterns */
|
|
854
|
+
exclude?: string[];
|
|
855
|
+
/** Plugins (future) */
|
|
856
|
+
plugins?: unknown[];
|
|
857
|
+
/** Documentation configuration */
|
|
858
|
+
docs?: DocsConfig;
|
|
859
|
+
/** Check command configuration */
|
|
860
|
+
check?: CheckConfig;
|
|
861
|
+
/** Quality rules configuration */
|
|
862
|
+
quality?: QualityRulesConfig;
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Define a DocCov configuration.
|
|
866
|
+
* Helper function for type-safe configuration in doccov.config.ts.
|
|
867
|
+
*
|
|
868
|
+
* @param config - Configuration object
|
|
869
|
+
* @returns The configuration object (for type inference)
|
|
870
|
+
*
|
|
871
|
+
* @example
|
|
872
|
+
* ```typescript
|
|
873
|
+
* // doccov.config.ts
|
|
874
|
+
* import { defineConfig } from '@doccov/sdk';
|
|
875
|
+
*
|
|
876
|
+
* defineConfig({
|
|
877
|
+
* include: ['MyClass', 'myFunction'],
|
|
878
|
+
* exclude: ['internal*'],
|
|
879
|
+
* docs: {
|
|
880
|
+
* include: ['docs/**\/*.md'],
|
|
881
|
+
* },
|
|
882
|
+
* quality: {
|
|
883
|
+
* rules: {
|
|
884
|
+
* 'has-description': 'error',
|
|
885
|
+
* 'has-examples': 'warn',
|
|
886
|
+
* },
|
|
887
|
+
* },
|
|
888
|
+
* });
|
|
889
|
+
* ```
|
|
890
|
+
*/
|
|
891
|
+
declare function defineConfig(config: DocCovConfig): DocCovConfig;
|
|
892
|
+
/**
|
|
893
|
+
* Project detection types for I/O-agnostic project analysis.
|
|
894
|
+
* Used by both CLI (NodeFileSystem) and API (SandboxFileSystem).
|
|
895
|
+
*/
|
|
896
|
+
/**
|
|
897
|
+
* Minimal filesystem interface for I/O-agnostic detection.
|
|
898
|
+
* Implementations: NodeFileSystem (CLI), SandboxFileSystem (API)
|
|
899
|
+
*/
|
|
900
|
+
interface FileSystem {
|
|
901
|
+
/** Check if a file or directory exists */
|
|
902
|
+
exists(path: string): Promise<boolean>;
|
|
903
|
+
/** Read file contents as string */
|
|
904
|
+
readFile(path: string): Promise<string>;
|
|
905
|
+
/** List directory contents (file/folder names only) */
|
|
906
|
+
readDir(path: string): Promise<string[]>;
|
|
907
|
+
/** Check if path is a directory */
|
|
908
|
+
isDirectory(path: string): Promise<boolean>;
|
|
909
|
+
}
|
|
910
|
+
/** Supported package managers */
|
|
911
|
+
type PackageManager = "npm" | "yarn" | "pnpm" | "bun";
|
|
912
|
+
/** Package manager detection result with install/run commands */
|
|
913
|
+
interface PackageManagerInfo {
|
|
914
|
+
/** Package manager name */
|
|
915
|
+
name: PackageManager;
|
|
916
|
+
/** Lockfile that was detected (null if none found) */
|
|
917
|
+
lockfile: string | null;
|
|
918
|
+
/** Arguments for install command, e.g. ['install', '--frozen-lockfile'] */
|
|
919
|
+
installArgs: string[];
|
|
920
|
+
/** Prefix for running scripts, e.g. ['npm', 'run'] or ['pnpm'] */
|
|
921
|
+
runPrefix: string[];
|
|
922
|
+
}
|
|
923
|
+
/** Monorepo type based on configuration */
|
|
924
|
+
type MonorepoType = "npm-workspaces" | "pnpm-workspaces" | "lerna" | "none";
|
|
925
|
+
/** Monorepo detection result */
|
|
926
|
+
interface MonorepoInfo {
|
|
927
|
+
/** Whether this is a monorepo */
|
|
928
|
+
isMonorepo: boolean;
|
|
929
|
+
/** Type of monorepo configuration */
|
|
930
|
+
type: MonorepoType;
|
|
931
|
+
/** Workspace patterns from config (e.g. ['packages/*']) */
|
|
932
|
+
patterns: string[];
|
|
933
|
+
/** Resolved workspace packages */
|
|
934
|
+
packages: WorkspacePackage[];
|
|
935
|
+
}
|
|
936
|
+
/** A package within a monorepo workspace */
|
|
937
|
+
interface WorkspacePackage {
|
|
938
|
+
/** Package name from package.json */
|
|
939
|
+
name: string;
|
|
940
|
+
/** Relative path to package directory */
|
|
941
|
+
path: string;
|
|
942
|
+
/** Whether the package is marked as private */
|
|
943
|
+
private: boolean;
|
|
944
|
+
}
|
|
945
|
+
/** Entry point source - where the entry was detected from */
|
|
946
|
+
type EntryPointSource = "types" | "exports" | "main" | "module" | "fallback";
|
|
947
|
+
/** Entry point detection result */
|
|
948
|
+
interface EntryPointInfo {
|
|
949
|
+
/** Path to entry file (relative to package root) */
|
|
950
|
+
path: string;
|
|
951
|
+
/** Where the entry point was detected from */
|
|
952
|
+
source: EntryPointSource;
|
|
953
|
+
/** Whether this is a .d.ts file (no source available) */
|
|
954
|
+
isDeclarationOnly: boolean;
|
|
955
|
+
}
|
|
956
|
+
/** Build configuration detection result */
|
|
957
|
+
interface BuildInfo {
|
|
958
|
+
/** Build-related script names found (e.g. ['build', 'build:types']) */
|
|
959
|
+
scripts: string[];
|
|
960
|
+
/** Whether any build script was found */
|
|
961
|
+
hasBuildScript: boolean;
|
|
962
|
+
/** Whether TypeScript is configured/installed */
|
|
963
|
+
hasTypeScript: boolean;
|
|
964
|
+
/** Indicators for exotic project types */
|
|
965
|
+
exoticIndicators: {
|
|
966
|
+
/** WASM project (Cargo.toml or wasm-pack scripts) */
|
|
967
|
+
wasm: boolean;
|
|
968
|
+
/** napi-rs native addon project */
|
|
969
|
+
napi: boolean;
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
/** Complete project analysis result */
|
|
973
|
+
interface ProjectInfo {
|
|
974
|
+
/** Package manager info */
|
|
975
|
+
packageManager: PackageManagerInfo;
|
|
976
|
+
/** Monorepo info */
|
|
977
|
+
monorepo: MonorepoInfo;
|
|
978
|
+
/** Entry point info */
|
|
979
|
+
entryPoint: EntryPointInfo;
|
|
980
|
+
/** Build info */
|
|
981
|
+
build: BuildInfo;
|
|
982
|
+
}
|
|
983
|
+
/** Options for analyzeProject() */
|
|
984
|
+
interface AnalyzeProjectOptions {
|
|
985
|
+
/** Target package name for monorepos */
|
|
986
|
+
targetPackage?: string;
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* Detect build configuration and exotic project indicators.
|
|
990
|
+
*
|
|
991
|
+
* @param fs - FileSystem implementation
|
|
992
|
+
* @param packagePath - Path to package directory (default: ".")
|
|
993
|
+
* @returns Build info including scripts and exotic indicators
|
|
994
|
+
*/
|
|
995
|
+
declare function detectBuildInfo(fs: FileSystem, packagePath?: string): Promise<BuildInfo>;
|
|
996
|
+
/**
|
|
997
|
+
* Get the primary build script name to run.
|
|
998
|
+
* Prefers 'build' over 'compile' over 'tsc'.
|
|
999
|
+
*/
|
|
1000
|
+
declare function getPrimaryBuildScript(buildInfo: BuildInfo): string | null;
|
|
1001
|
+
/**
|
|
1002
|
+
* Detect the TypeScript entry point for a package.
|
|
1003
|
+
*
|
|
1004
|
+
* Priority order:
|
|
1005
|
+
* 1. package.json -> types or typings field
|
|
1006
|
+
* 2. package.json -> exports["."].types
|
|
1007
|
+
* 3. package.json -> main field (resolve to .ts)
|
|
1008
|
+
* 4. package.json -> module field (resolve to .ts)
|
|
1009
|
+
* 5. Common fallback paths
|
|
1010
|
+
*
|
|
1011
|
+
* @param fs - FileSystem implementation
|
|
1012
|
+
* @param packagePath - Path to package directory (default: ".")
|
|
1013
|
+
* @returns Entry point info
|
|
1014
|
+
* @throws Error if no entry point can be found
|
|
1015
|
+
*/
|
|
1016
|
+
declare function detectEntryPoint(fs: FileSystem, packagePath?: string): Promise<EntryPointInfo>;
|
|
1017
|
+
import { Sandbox } from "@vercel/sandbox";
|
|
1018
|
+
/**
|
|
1019
|
+
* Node.js filesystem implementation for CLI usage.
|
|
1020
|
+
* Wraps Node.js fs module with a base path.
|
|
1021
|
+
*/
|
|
1022
|
+
declare class NodeFileSystem implements FileSystem {
|
|
1023
|
+
private basePath;
|
|
1024
|
+
constructor(basePath: string);
|
|
1025
|
+
private resolve;
|
|
1026
|
+
exists(relativePath: string): Promise<boolean>;
|
|
1027
|
+
readFile(relativePath: string): Promise<string>;
|
|
1028
|
+
readDir(relativePath: string): Promise<string[]>;
|
|
1029
|
+
isDirectory(relativePath: string): Promise<boolean>;
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Vercel Sandbox filesystem implementation for API usage.
|
|
1033
|
+
* Uses sandbox.runCommand() with shell commands.
|
|
1034
|
+
*/
|
|
1035
|
+
declare class SandboxFileSystem implements FileSystem {
|
|
1036
|
+
private sandbox;
|
|
1037
|
+
constructor(sandbox: Sandbox);
|
|
1038
|
+
exists(path: string): Promise<boolean>;
|
|
1039
|
+
readFile(path: string): Promise<string>;
|
|
1040
|
+
readDir(path: string): Promise<string[]>;
|
|
1041
|
+
isDirectory(path: string): Promise<boolean>;
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Detect if a project is a monorepo and list its packages.
|
|
1045
|
+
*
|
|
1046
|
+
* Detection triggers (in order):
|
|
1047
|
+
* 1. package.json has workspaces field (npm/yarn)
|
|
1048
|
+
* 2. pnpm-workspace.yaml exists
|
|
1049
|
+
* 3. lerna.json exists
|
|
1050
|
+
*/
|
|
1051
|
+
declare function detectMonorepo(fs: FileSystem): Promise<MonorepoInfo>;
|
|
1052
|
+
/**
|
|
1053
|
+
* Find a package by name or path in a list of workspace packages.
|
|
1054
|
+
*/
|
|
1055
|
+
declare function findPackageByName(packages: WorkspacePackage[], nameOrPath: string): WorkspacePackage | undefined;
|
|
1056
|
+
/**
|
|
1057
|
+
* Format package list for display in error messages.
|
|
1058
|
+
*/
|
|
1059
|
+
declare function formatPackageList(packages: WorkspacePackage[], limit?: number): string;
|
|
1060
|
+
/**
|
|
1061
|
+
* Detect package manager based on lockfile presence and package.json hints.
|
|
1062
|
+
*
|
|
1063
|
+
* Resolution order:
|
|
1064
|
+
* 1. packageManager field in package.json (e.g., "pnpm@9.0.0")
|
|
1065
|
+
* 2. Most recently modified lockfile (when multiple exist)
|
|
1066
|
+
* 3. Static priority order: pnpm > bun > yarn > npm
|
|
1067
|
+
* 4. Default to npm
|
|
1068
|
+
*/
|
|
1069
|
+
declare function detectPackageManager(fs: FileSystem): Promise<PackageManagerInfo>;
|
|
1070
|
+
/**
|
|
1071
|
+
* Get install command for a package manager.
|
|
1072
|
+
* Returns [command, ...args] array.
|
|
1073
|
+
*/
|
|
1074
|
+
declare function getInstallCommand(pm: PackageManagerInfo): string[];
|
|
1075
|
+
/**
|
|
1076
|
+
* Get run command for a package manager script.
|
|
1077
|
+
* Returns [command, ...args, scriptName] array.
|
|
1078
|
+
*/
|
|
1079
|
+
declare function getRunCommand(pm: PackageManagerInfo, script: string): string[];
|
|
1080
|
+
/**
|
|
1081
|
+
* Safely parse a JSON file, returning null on any error.
|
|
1082
|
+
*/
|
|
1083
|
+
declare function safeParseJson<T = Record<string, unknown>>(fs: FileSystem, path: string): Promise<T | null>;
|
|
1084
|
+
/**
|
|
1085
|
+
* Standard package.json structure for detection purposes.
|
|
1086
|
+
*/
|
|
1087
|
+
interface PackageJson {
|
|
1088
|
+
name?: string;
|
|
1089
|
+
version?: string;
|
|
1090
|
+
private?: boolean;
|
|
1091
|
+
main?: string;
|
|
1092
|
+
module?: string;
|
|
1093
|
+
types?: string;
|
|
1094
|
+
typings?: string;
|
|
1095
|
+
exports?: PackageExports;
|
|
1096
|
+
workspaces?: string[] | {
|
|
1097
|
+
packages: string[];
|
|
1098
|
+
};
|
|
1099
|
+
scripts?: Record<string, string>;
|
|
1100
|
+
dependencies?: Record<string, string>;
|
|
1101
|
+
devDependencies?: Record<string, string>;
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Package.json exports field structure.
|
|
1105
|
+
*/
|
|
1106
|
+
type PackageExports = string | {
|
|
1107
|
+
"."?: string | {
|
|
1108
|
+
types?: string;
|
|
1109
|
+
import?: string;
|
|
1110
|
+
require?: string;
|
|
1111
|
+
default?: string;
|
|
1112
|
+
};
|
|
1113
|
+
[key: string]: unknown;
|
|
1114
|
+
};
|
|
1115
|
+
/**
|
|
1116
|
+
* Read and parse package.json from a directory.
|
|
1117
|
+
*/
|
|
1118
|
+
declare function readPackageJson(fs: FileSystem, dir: string): Promise<PackageJson | null>;
|
|
1119
|
+
/**
|
|
1120
|
+
* Analyze a project's structure for scanning.
|
|
1121
|
+
*
|
|
1122
|
+
* This is the main entry point for project detection. It combines all
|
|
1123
|
+
* detection functions into a single call that returns complete project info.
|
|
1124
|
+
*
|
|
1125
|
+
* For monorepos, you must specify the target package via options.targetPackage.
|
|
1126
|
+
* If not specified and a monorepo is detected, an error is thrown with the
|
|
1127
|
+
* list of available packages.
|
|
1128
|
+
*
|
|
1129
|
+
* @param fs - FileSystem implementation (NodeFileSystem or SandboxFileSystem)
|
|
1130
|
+
* @param options - Options including targetPackage for monorepos
|
|
1131
|
+
* @returns Complete project info
|
|
1132
|
+
* @throws Error if monorepo detected without targetPackage specified
|
|
1133
|
+
* @throws Error if targetPackage not found in monorepo
|
|
1134
|
+
*
|
|
1135
|
+
* @example
|
|
1136
|
+
* ```typescript
|
|
1137
|
+
* import { NodeFileSystem, analyzeProject } from '@doccov/sdk';
|
|
1138
|
+
*
|
|
1139
|
+
* // Single package
|
|
1140
|
+
* const singleFs = new NodeFileSystem('/path/to/package');
|
|
1141
|
+
* const singleProject = await analyzeProject(singleFs);
|
|
1142
|
+
*
|
|
1143
|
+
* // Monorepo with target package
|
|
1144
|
+
* const monoFs = new NodeFileSystem('/path/to/monorepo');
|
|
1145
|
+
* const monoProject = await analyzeProject(monoFs, { targetPackage: '@scope/core' });
|
|
1146
|
+
* ```
|
|
1147
|
+
*/
|
|
1148
|
+
declare function analyzeProject2(fs: FileSystem, options?: AnalyzeProjectOptions): Promise<ProjectInfo>;
|
|
1149
|
+
/**
|
|
1150
|
+
* Example validation types and utilities.
|
|
1151
|
+
*/
|
|
1152
|
+
/**
|
|
1153
|
+
* Individual example validations that can be run.
|
|
1154
|
+
*/
|
|
1155
|
+
type ExampleValidation = "presence" | "typecheck" | "run";
|
|
1156
|
+
/**
|
|
1157
|
+
* All validations (used when --examples is passed without values).
|
|
1158
|
+
*/
|
|
1159
|
+
declare const ALL_VALIDATIONS: ExampleValidation[];
|
|
1160
|
+
/**
|
|
1161
|
+
* Describes what each validation does.
|
|
1162
|
+
*/
|
|
1163
|
+
declare const VALIDATION_INFO: Record<ExampleValidation, {
|
|
1164
|
+
label: string;
|
|
1165
|
+
description: string;
|
|
1166
|
+
}>;
|
|
1167
|
+
/**
|
|
1168
|
+
* Parse --examples flag value into validation set.
|
|
1169
|
+
*
|
|
1170
|
+
* @example
|
|
1171
|
+
* parseExamplesFlag(true) // ['presence', 'typecheck', 'run']
|
|
1172
|
+
* parseExamplesFlag('presence') // ['presence']
|
|
1173
|
+
* parseExamplesFlag('typecheck,run') // ['typecheck', 'run']
|
|
1174
|
+
* parseExamplesFlag(undefined) // [] (no validation)
|
|
1175
|
+
*/
|
|
1176
|
+
declare function parseExamplesFlag(value: boolean | string | undefined): ExampleValidation[];
|
|
1177
|
+
/**
|
|
1178
|
+
* Check if a specific validation is enabled.
|
|
1179
|
+
*/
|
|
1180
|
+
declare function shouldValidate(validations: ExampleValidation[], check: ExampleValidation): boolean;
|
|
1181
|
+
import { SpecExport as SpecExport4 } from "@openpkg-ts/spec";
|
|
1182
|
+
interface ExampleTypeError {
|
|
1183
|
+
/** Index of the example in the examples array */
|
|
1184
|
+
exampleIndex: number;
|
|
1185
|
+
/** Line number within the example (1-based) */
|
|
1186
|
+
line: number;
|
|
1187
|
+
/** Column number (1-based) */
|
|
1188
|
+
column: number;
|
|
1189
|
+
/** Error message from TypeScript */
|
|
1190
|
+
message: string;
|
|
1191
|
+
/** TypeScript diagnostic code */
|
|
1192
|
+
code: number;
|
|
1193
|
+
}
|
|
1194
|
+
interface TypecheckResult {
|
|
1195
|
+
/** All type errors found across examples */
|
|
1196
|
+
errors: ExampleTypeError[];
|
|
1197
|
+
/** Number of examples that passed */
|
|
1198
|
+
passed: number;
|
|
1199
|
+
/** Number of examples that failed */
|
|
1200
|
+
failed: number;
|
|
1201
|
+
}
|
|
1202
|
+
interface TypecheckOptions {
|
|
1203
|
+
/** Path to tsconfig.json (auto-detected if not provided) */
|
|
1204
|
+
tsconfig?: string;
|
|
1205
|
+
/** Package name for imports (auto-detected from package.json if not provided) */
|
|
1206
|
+
packageName?: string;
|
|
1207
|
+
/** Export names to include in the virtual import statement */
|
|
1208
|
+
exportNames?: string[];
|
|
1209
|
+
}
|
|
1210
|
+
/**
|
|
1211
|
+
* Options for example validation.
|
|
1212
|
+
*/
|
|
1213
|
+
interface ExampleValidationOptions {
|
|
1214
|
+
/** Which validations to run */
|
|
1215
|
+
validations: ExampleValidation[];
|
|
1216
|
+
/** Path to the package being validated */
|
|
1217
|
+
packagePath: string;
|
|
1218
|
+
/** Package name (for import resolution) */
|
|
1219
|
+
packageName?: string;
|
|
1220
|
+
/** All names (for import statements in typecheck) */
|
|
1221
|
+
exportNames?: string[];
|
|
1222
|
+
/** Timeout for runtime execution (ms) */
|
|
1223
|
+
timeout?: number;
|
|
1224
|
+
/** Timeout for package installation (ms) */
|
|
1225
|
+
installTimeout?: number;
|
|
1226
|
+
/** Callback for LLM assertion parsing fallback */
|
|
1227
|
+
llmAssertionParser?: (example: string) => Promise<{
|
|
1228
|
+
hasAssertions: boolean;
|
|
1229
|
+
assertions: LLMAssertion[];
|
|
1230
|
+
} | null>;
|
|
1231
|
+
}
|
|
1232
|
+
/**
|
|
1233
|
+
* LLM-parsed assertion from non-standard comment syntax.
|
|
1234
|
+
*/
|
|
1235
|
+
interface LLMAssertion {
|
|
1236
|
+
expected: string;
|
|
1237
|
+
suggestedSyntax: string;
|
|
1238
|
+
}
|
|
1239
|
+
/**
|
|
1240
|
+
* Result of a single example type error.
|
|
1241
|
+
*/
|
|
1242
|
+
interface ExampleValidationTypeError {
|
|
1243
|
+
exportName: string;
|
|
1244
|
+
exampleIndex: number;
|
|
1245
|
+
error: ExampleTypeError;
|
|
1246
|
+
}
|
|
1247
|
+
/**
|
|
1248
|
+
* Result of example presence validation.
|
|
1249
|
+
*/
|
|
1250
|
+
interface PresenceResult {
|
|
1251
|
+
total: number;
|
|
1252
|
+
withExamples: number;
|
|
1253
|
+
missing: string[];
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Result of example typecheck validation.
|
|
1257
|
+
*/
|
|
1258
|
+
interface TypecheckValidationResult {
|
|
1259
|
+
passed: number;
|
|
1260
|
+
failed: number;
|
|
1261
|
+
errors: ExampleValidationTypeError[];
|
|
1262
|
+
}
|
|
1263
|
+
/**
|
|
1264
|
+
* Runtime drift issue (runtime error or assertion failure).
|
|
1265
|
+
*/
|
|
1266
|
+
interface RuntimeDrift {
|
|
1267
|
+
exportName: string;
|
|
1268
|
+
issue: string;
|
|
1269
|
+
suggestion?: string;
|
|
1270
|
+
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Result of example runtime validation.
|
|
1273
|
+
*/
|
|
1274
|
+
interface RunValidationResult {
|
|
1275
|
+
passed: number;
|
|
1276
|
+
failed: number;
|
|
1277
|
+
drifts: RuntimeDrift[];
|
|
1278
|
+
installSuccess: boolean;
|
|
1279
|
+
installError?: string;
|
|
1280
|
+
}
|
|
1281
|
+
/**
|
|
1282
|
+
* Unified result from example validation.
|
|
1283
|
+
*/
|
|
1284
|
+
interface ExampleValidationResult {
|
|
1285
|
+
/** Which validations were run */
|
|
1286
|
+
validations: ExampleValidation[];
|
|
1287
|
+
/** Presence validation results (if run) */
|
|
1288
|
+
presence?: PresenceResult;
|
|
1289
|
+
/** Typecheck validation results (if run) */
|
|
1290
|
+
typecheck?: TypecheckValidationResult;
|
|
1291
|
+
/** Runtime validation results (if run) */
|
|
1292
|
+
run?: RunValidationResult;
|
|
1293
|
+
/** Total number of issues found */
|
|
1294
|
+
totalIssues: number;
|
|
1295
|
+
}
|
|
1296
|
+
/**
|
|
1297
|
+
* Validate examples across exports.
|
|
1298
|
+
*
|
|
1299
|
+
* Runs only the validations specified. Each validation is independent:
|
|
1300
|
+
* - `presence`: checks examples exist (doesn't require typecheck or run)
|
|
1301
|
+
* - `typecheck`: type-checks examples (doesn't require presence or run)
|
|
1302
|
+
* - `run`: executes examples (doesn't require presence or typecheck)
|
|
1303
|
+
*/
|
|
1304
|
+
declare function validateExamples(exports: SpecExport4[], options: ExampleValidationOptions): Promise<ExampleValidationResult>;
|
|
1305
|
+
interface DocCovOptions {
|
|
1306
|
+
includePrivate?: boolean;
|
|
1307
|
+
followImports?: boolean;
|
|
1308
|
+
maxDepth?: number;
|
|
1309
|
+
resolveExternalTypes?: boolean;
|
|
1310
|
+
/** Enable spec caching (default: true) */
|
|
1311
|
+
useCache?: boolean;
|
|
1312
|
+
/** Working directory for cache operations (default: process.cwd()) */
|
|
1313
|
+
cwd?: string;
|
|
1314
|
+
}
|
|
1315
|
+
/** @deprecated Use DocCovOptions instead */
|
|
1316
|
+
type OpenPkgOptions = DocCovOptions;
|
|
1317
|
+
declare function extractPackageSpec(entryFile: string, packageDir?: string, content?: string, options?: OpenPkgOptions): Promise<OpenPkgSpec>;
|
|
1318
|
+
interface FilterOptions {
|
|
1319
|
+
include?: string[];
|
|
1320
|
+
exclude?: string[];
|
|
1321
|
+
}
|
|
1322
|
+
/**
|
|
1323
|
+
* Source of filter options.
|
|
1324
|
+
*/
|
|
1325
|
+
type FilterSource = "config" | "override" | "combined";
|
|
1326
|
+
/**
|
|
1327
|
+
* Resolved filter options after merging config and overrides.
|
|
1328
|
+
*/
|
|
1329
|
+
interface ResolvedFilters {
|
|
1330
|
+
/** Include patterns */
|
|
1331
|
+
include?: string[];
|
|
1332
|
+
/** Exclude patterns */
|
|
1333
|
+
exclude?: string[];
|
|
1334
|
+
/** Source of the filters */
|
|
1335
|
+
source?: FilterSource;
|
|
1336
|
+
/** Whether filters were applied from config */
|
|
1337
|
+
fromConfig: boolean;
|
|
1338
|
+
/** Whether filters were applied from overrides */
|
|
1339
|
+
fromOverride: boolean;
|
|
1340
|
+
}
|
|
1341
|
+
/**
|
|
1342
|
+
* Parse a comma-separated list flag into an array.
|
|
1343
|
+
*
|
|
1344
|
+
* @param value - String or string array from CLI flag
|
|
1345
|
+
* @returns Parsed array, or undefined if empty
|
|
1346
|
+
*
|
|
1347
|
+
* @example
|
|
1348
|
+
* ```typescript
|
|
1349
|
+
* parseListFlag('a,b,c'); // ['a', 'b', 'c']
|
|
1350
|
+
* parseListFlag(['a,b', 'c']); // ['a', 'b', 'c']
|
|
1351
|
+
* parseListFlag(undefined); // undefined
|
|
1352
|
+
* ```
|
|
1353
|
+
*/
|
|
1354
|
+
declare function parseListFlag(value?: string | string[]): string[] | undefined;
|
|
1355
|
+
/**
|
|
1356
|
+
* Merge filter options from config and CLI/API overrides.
|
|
1357
|
+
*
|
|
1358
|
+
* Merge behavior:
|
|
1359
|
+
* - Include: CLI values intersect with config values (narrowing)
|
|
1360
|
+
* - Exclude: CLI values are added to config values (expanding)
|
|
1361
|
+
*
|
|
1362
|
+
* @param config - Configuration (from doccov.config.ts)
|
|
1363
|
+
* @param overrides - Override filters (from CLI flags or API params)
|
|
1364
|
+
* @returns Merged filter options
|
|
1365
|
+
*
|
|
1366
|
+
* @example
|
|
1367
|
+
* ```typescript
|
|
1368
|
+
* const config = { include: ['A', 'B', 'C'] };
|
|
1369
|
+
* const overrides = { include: ['B', 'C', 'D'] };
|
|
1370
|
+
*
|
|
1371
|
+
* const resolved = mergeFilters(config, overrides);
|
|
1372
|
+
* // resolved.include = ['B', 'C'] (intersection)
|
|
1373
|
+
* ```
|
|
1374
|
+
*/
|
|
1375
|
+
declare function mergeFilters(config: DocCovConfig | null, overrides: FilterOptions): ResolvedFilters;
|
|
1376
|
+
import { SpecDocDrift as SpecDocDrift4, SpecExport as SpecExport5 } from "@openpkg-ts/spec";
|
|
1377
|
+
/**
|
|
1378
|
+
* Types of fixes that can be generated
|
|
1379
|
+
*/
|
|
1380
|
+
type FixType = "add-param" | "remove-param" | "update-param-type" | "update-param-optionality" | "update-return-type" | "update-assertion" | "add-template" | "update-template-constraint" | "add-deprecated" | "remove-deprecated" | "add-async" | "remove-async" | "update-property-type";
|
|
1381
|
+
/**
|
|
1382
|
+
* A fix suggestion with the patch to apply
|
|
1383
|
+
*/
|
|
1384
|
+
interface FixSuggestion {
|
|
1385
|
+
type: FixType;
|
|
1386
|
+
driftType: SpecDocDrift4["type"];
|
|
1387
|
+
target: string;
|
|
1388
|
+
description: string;
|
|
1389
|
+
patch: Partial<JSDocPatch>;
|
|
1390
|
+
}
|
|
1391
|
+
/**
|
|
1392
|
+
* Check if a drift type can be fixed deterministically
|
|
1393
|
+
*/
|
|
1394
|
+
declare function isFixableDrift(drift: SpecDocDrift4): boolean;
|
|
1395
|
+
/**
|
|
1396
|
+
* Generate a fix for a single drift issue
|
|
1397
|
+
*/
|
|
1398
|
+
declare function generateFix(drift: SpecDocDrift4, exportEntry: SpecExport5, existingPatch?: JSDocPatch): FixSuggestion | null;
|
|
1399
|
+
/**
|
|
1400
|
+
* Generate all fixes for an export's drift issues
|
|
1401
|
+
*/
|
|
1402
|
+
declare function generateFixesForExport(exportEntry: SpecExport5, existingPatch?: JSDocPatch): FixSuggestion[];
|
|
1403
|
+
/**
|
|
1404
|
+
* Merge multiple fix patches into a single patch
|
|
1405
|
+
*/
|
|
1406
|
+
declare function mergeFixes(fixes: FixSuggestion[], basePatch?: JSDocPatch): JSDocPatch;
|
|
1407
|
+
/**
|
|
1408
|
+
* Get a summary of fixable vs non-fixable drifts
|
|
1409
|
+
*/
|
|
1410
|
+
declare function categorizeDrifts(drifts: SpecDocDrift4[]): {
|
|
1411
|
+
fixable: SpecDocDrift4[];
|
|
1412
|
+
nonFixable: SpecDocDrift4[];
|
|
1413
|
+
};
|
|
1414
|
+
import { OpenPkg as OpenPkg5 } from "@openpkg-ts/spec";
|
|
1415
|
+
/**
|
|
1416
|
+
* Parsed components of a GitHub URL.
|
|
1417
|
+
*/
|
|
1418
|
+
interface ParsedGitHubUrl {
|
|
1419
|
+
/** Repository owner (user or org) */
|
|
1420
|
+
owner: string;
|
|
1421
|
+
/** Repository name */
|
|
1422
|
+
repo: string;
|
|
1423
|
+
/** Git ref (branch or tag) */
|
|
1424
|
+
ref: string;
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Parse a GitHub URL or shorthand into components.
|
|
1428
|
+
*
|
|
1429
|
+
* Supported formats:
|
|
1430
|
+
* - https://github.com/owner/repo
|
|
1431
|
+
* - https://github.com/owner/repo/tree/branch
|
|
1432
|
+
* - https://github.com/owner/repo/tree/v1.0.0
|
|
1433
|
+
* - github.com/owner/repo
|
|
1434
|
+
* - owner/repo (shorthand)
|
|
1435
|
+
* - git@github.com:owner/repo.git
|
|
1436
|
+
*
|
|
1437
|
+
* @param input - GitHub URL or shorthand
|
|
1438
|
+
* @param defaultRef - Default ref if not specified in URL (default: 'main')
|
|
1439
|
+
* @returns Parsed components
|
|
1440
|
+
* @throws Error if the URL format is invalid
|
|
1441
|
+
*
|
|
1442
|
+
* @example
|
|
1443
|
+
* ```typescript
|
|
1444
|
+
* import { parseGitHubUrl } from '@doccov/sdk';
|
|
1445
|
+
*
|
|
1446
|
+
* const parsed = parseGitHubUrl('https://github.com/vercel/next.js/tree/canary');
|
|
1447
|
+
* // { owner: 'vercel', repo: 'next.js', ref: 'canary' }
|
|
1448
|
+
*
|
|
1449
|
+
* const shorthand = parseGitHubUrl('vercel/next.js');
|
|
1450
|
+
* // { owner: 'vercel', repo: 'next.js', ref: 'main' }
|
|
1451
|
+
* ```
|
|
1452
|
+
*/
|
|
1453
|
+
declare function parseGitHubUrl(input: string, defaultRef?: string): ParsedGitHubUrl;
|
|
1454
|
+
/**
|
|
1455
|
+
* Build a clone URL from parsed components.
|
|
1456
|
+
*
|
|
1457
|
+
* @param parsed - Parsed GitHub URL components
|
|
1458
|
+
* @returns HTTPS clone URL
|
|
1459
|
+
*
|
|
1460
|
+
* @example
|
|
1461
|
+
* ```typescript
|
|
1462
|
+
* const cloneUrl = buildCloneUrl({ owner: 'vercel', repo: 'next.js', ref: 'main' });
|
|
1463
|
+
* // 'https://github.com/vercel/next.js.git'
|
|
1464
|
+
* ```
|
|
1465
|
+
*/
|
|
1466
|
+
declare function buildCloneUrl(parsed: ParsedGitHubUrl): string;
|
|
1467
|
+
/**
|
|
1468
|
+
* Build a display-friendly URL (without protocol or .git suffix).
|
|
1469
|
+
*
|
|
1470
|
+
* @param parsed - Parsed GitHub URL components
|
|
1471
|
+
* @returns Display URL like 'github.com/owner/repo'
|
|
1472
|
+
*
|
|
1473
|
+
* @example
|
|
1474
|
+
* ```typescript
|
|
1475
|
+
* const displayUrl = buildDisplayUrl({ owner: 'vercel', repo: 'next.js', ref: 'main' });
|
|
1476
|
+
* // 'github.com/vercel/next.js'
|
|
1477
|
+
* ```
|
|
1478
|
+
*/
|
|
1479
|
+
declare function buildDisplayUrl(parsed: ParsedGitHubUrl): string;
|
|
1480
|
+
/**
|
|
1481
|
+
* Build a raw.githubusercontent.com URL for a file.
|
|
1482
|
+
*
|
|
1483
|
+
* @param parsed - Parsed GitHub URL components
|
|
1484
|
+
* @param filePath - Path to the file in the repo
|
|
1485
|
+
* @returns Raw content URL
|
|
1486
|
+
*/
|
|
1487
|
+
declare function buildRawUrl(parsed: ParsedGitHubUrl, filePath: string): string;
|
|
1488
|
+
/**
|
|
1489
|
+
* Fetch an OpenPkg spec from a GitHub repository.
|
|
1490
|
+
*
|
|
1491
|
+
* Tries the specified ref first, then falls back to 'master' if not found.
|
|
1492
|
+
*
|
|
1493
|
+
* @param parsed - Parsed GitHub URL components
|
|
1494
|
+
* @returns The OpenPkg spec, or null if not found
|
|
1495
|
+
*
|
|
1496
|
+
* @example
|
|
1497
|
+
* ```typescript
|
|
1498
|
+
* import { parseGitHubUrl, fetchSpecFromGitHub } from '@doccov/sdk';
|
|
1499
|
+
*
|
|
1500
|
+
* const parsed = parseGitHubUrl('vercel/next.js');
|
|
1501
|
+
* const spec = await fetchSpecFromGitHub(parsed);
|
|
1502
|
+
* if (spec) {
|
|
1503
|
+
* console.log(`Coverage: ${spec.docs?.coverageScore}%`);
|
|
1504
|
+
* }
|
|
1505
|
+
* ```
|
|
1506
|
+
*/
|
|
1507
|
+
declare function fetchSpecFromGitHub(parsed: ParsedGitHubUrl): Promise<OpenPkg5 | null>;
|
|
1508
|
+
/**
|
|
1509
|
+
* Fetch an OpenPkg spec from a GitHub repository by owner/repo/branch.
|
|
1510
|
+
*
|
|
1511
|
+
* Convenience function that creates ParsedGitHubUrl internally.
|
|
1512
|
+
*
|
|
1513
|
+
* @param owner - Repository owner
|
|
1514
|
+
* @param repo - Repository name
|
|
1515
|
+
* @param branch - Branch name (default: 'main')
|
|
1516
|
+
* @returns The OpenPkg spec, or null if not found
|
|
1517
|
+
*/
|
|
1518
|
+
declare function fetchSpec(owner: string, repo: string, branch?: string): Promise<OpenPkg5 | null>;
|
|
1519
|
+
/**
|
|
1520
|
+
* Scan types for CLI, API, and SDK consumers.
|
|
1521
|
+
* Single source of truth for scan-related interfaces.
|
|
1522
|
+
*/
|
|
1523
|
+
/**
|
|
1524
|
+
* Result of scanning a repository for documentation coverage.
|
|
1525
|
+
* Used by CLI scan command, API endpoints, and SDK consumers.
|
|
1526
|
+
*/
|
|
1527
|
+
interface ScanResult {
|
|
1528
|
+
/** GitHub repository owner */
|
|
1529
|
+
owner: string;
|
|
1530
|
+
/** GitHub repository name */
|
|
1531
|
+
repo: string;
|
|
1532
|
+
/** Git ref (branch/tag) that was scanned */
|
|
1533
|
+
ref: string;
|
|
1534
|
+
/** Package name if scanning a monorepo package */
|
|
1535
|
+
packageName?: string;
|
|
1536
|
+
/** Overall documentation coverage percentage (0-100) */
|
|
1537
|
+
coverage: number;
|
|
1538
|
+
/** Number of public exports analyzed */
|
|
1539
|
+
exportCount: number;
|
|
1540
|
+
/** Number of types analyzed */
|
|
1541
|
+
typeCount: number;
|
|
1542
|
+
/** Number of documentation drift issues found */
|
|
1543
|
+
driftCount: number;
|
|
1544
|
+
/** Names of exports missing documentation */
|
|
1545
|
+
undocumented: string[];
|
|
1546
|
+
/** Drift issues found during analysis */
|
|
1547
|
+
drift: DriftIssue[];
|
|
1548
|
+
}
|
|
1549
|
+
/**
|
|
1550
|
+
* A documentation drift issue.
|
|
1551
|
+
*/
|
|
1552
|
+
interface DriftIssue {
|
|
1553
|
+
/** Name of the with drift */
|
|
1554
|
+
export: string;
|
|
1555
|
+
/** Type of drift (e.g., 'param-mismatch', 'return-type') */
|
|
1556
|
+
type: string;
|
|
1557
|
+
/** Human-readable description of the issue */
|
|
1558
|
+
issue: string;
|
|
1559
|
+
/** Optional suggestion for fixing the issue */
|
|
1560
|
+
suggestion?: string;
|
|
1561
|
+
}
|
|
1562
|
+
/**
|
|
1563
|
+
* Options for running a scan.
|
|
1564
|
+
*/
|
|
1565
|
+
interface ScanOptions {
|
|
1566
|
+
/** GitHub URL or owner/repo shorthand */
|
|
1567
|
+
url: string;
|
|
1568
|
+
/** Git ref (branch/tag) to scan */
|
|
1569
|
+
ref?: string;
|
|
1570
|
+
/** Target package name for monorepos */
|
|
1571
|
+
package?: string;
|
|
1572
|
+
/** Skip dependency installation */
|
|
1573
|
+
skipInstall?: boolean;
|
|
1574
|
+
/** Skip external type resolution */
|
|
1575
|
+
skipResolve?: boolean;
|
|
1576
|
+
}
|
|
1577
|
+
/**
|
|
1578
|
+
* Stages of the scan pipeline.
|
|
1579
|
+
*/
|
|
1580
|
+
type ProgressStage = "cloning" | "detecting" | "installing" | "building" | "analyzing" | "complete";
|
|
1581
|
+
/**
|
|
1582
|
+
* Progress event emitted during scan operations.
|
|
1583
|
+
*/
|
|
1584
|
+
interface ProgressEvent {
|
|
1585
|
+
/** Current stage of the scan */
|
|
1586
|
+
stage: ProgressStage;
|
|
1587
|
+
/** Human-readable message */
|
|
1588
|
+
message: string;
|
|
1589
|
+
/** Progress percentage (0-100), if known */
|
|
1590
|
+
progress?: number;
|
|
1591
|
+
}
|
|
1592
|
+
/**
|
|
1593
|
+
* Callback for receiving progress events.
|
|
1594
|
+
*/
|
|
1595
|
+
type ProgressCallback = (event: ProgressEvent) => void;
|
|
1596
|
+
/**
|
|
1597
|
+
* Result of running a command.
|
|
1598
|
+
*/
|
|
1599
|
+
interface CommandResult {
|
|
1600
|
+
/** Exit code (0 = success) */
|
|
1601
|
+
exitCode: number;
|
|
1602
|
+
/** Standard output */
|
|
1603
|
+
stdout: string;
|
|
1604
|
+
/** Standard error */
|
|
1605
|
+
stderr: string;
|
|
588
1606
|
}
|
|
589
1607
|
/**
|
|
590
|
-
*
|
|
1608
|
+
* Function that runs a shell command.
|
|
1609
|
+
* Abstracts the difference between Node.js execSync and Sandbox runCommand.
|
|
591
1610
|
*/
|
|
592
|
-
|
|
1611
|
+
type CommandRunner = (cmd: string, args: string[], options: {
|
|
1612
|
+
cwd: string;
|
|
1613
|
+
timeout?: number;
|
|
1614
|
+
}) => Promise<CommandResult>;
|
|
593
1615
|
/**
|
|
594
|
-
*
|
|
1616
|
+
* Result of dependency installation.
|
|
595
1617
|
*/
|
|
596
|
-
|
|
1618
|
+
interface InstallResult {
|
|
1619
|
+
/** Whether installation succeeded */
|
|
1620
|
+
success: boolean;
|
|
1621
|
+
/** Package manager that was used */
|
|
1622
|
+
packageManager: PackageManager;
|
|
1623
|
+
/** If a fallback was used, which one */
|
|
1624
|
+
fallbackUsed?: PackageManager;
|
|
1625
|
+
/** Error message if installation failed */
|
|
1626
|
+
error?: string;
|
|
1627
|
+
/** Detailed error messages from each attempt */
|
|
1628
|
+
errors?: string[];
|
|
1629
|
+
}
|
|
597
1630
|
/**
|
|
598
|
-
*
|
|
1631
|
+
* Options for dependency installation.
|
|
599
1632
|
*/
|
|
600
|
-
|
|
1633
|
+
interface InstallOptions {
|
|
1634
|
+
/** Timeout in milliseconds for install commands (default: 180000) */
|
|
1635
|
+
timeout?: number;
|
|
1636
|
+
/** Order of fallback package managers to try */
|
|
1637
|
+
fallbackOrder?: PackageManager[];
|
|
1638
|
+
/** Progress callback for status updates */
|
|
1639
|
+
onProgress?: ProgressCallback;
|
|
1640
|
+
}
|
|
601
1641
|
/**
|
|
602
|
-
*
|
|
1642
|
+
* Install dependencies for a project.
|
|
1643
|
+
*
|
|
1644
|
+
* This consolidates the install logic from CLI scan.ts and API scan-stream.ts:
|
|
1645
|
+
* 1. Detect package manager from lockfile
|
|
1646
|
+
* 2. Try primary install command
|
|
1647
|
+
* 3. Fall back to other package managers if primary fails
|
|
1648
|
+
*
|
|
1649
|
+
* @param fs - FileSystem implementation for package manager detection
|
|
1650
|
+
* @param cwd - Working directory to install in
|
|
1651
|
+
* @param runCommand - Function to run shell commands
|
|
1652
|
+
* @param options - Installation options
|
|
1653
|
+
* @returns Result of the installation attempt
|
|
1654
|
+
*
|
|
1655
|
+
* @example
|
|
1656
|
+
* ```typescript
|
|
1657
|
+
* import { NodeFileSystem, installDependencies, createNodeCommandRunner } from '@doccov/sdk';
|
|
1658
|
+
*
|
|
1659
|
+
* const fs = new NodeFileSystem('/path/to/repo');
|
|
1660
|
+
* const result = await installDependencies(fs, '/path/to/repo', createNodeCommandRunner());
|
|
1661
|
+
*
|
|
1662
|
+
* if (result.success) {
|
|
1663
|
+
* console.log(`Installed using ${result.packageManager}`);
|
|
1664
|
+
* } else {
|
|
1665
|
+
* console.error(`Install failed: ${result.error}`);
|
|
1666
|
+
* }
|
|
1667
|
+
* ```
|
|
603
1668
|
*/
|
|
604
|
-
declare function
|
|
1669
|
+
declare function installDependencies(fs: FileSystem, cwd: string, runCommand: CommandRunner, options?: InstallOptions): Promise<InstallResult>;
|
|
605
1670
|
/**
|
|
606
|
-
*
|
|
1671
|
+
* Create a command runner for Node.js environments using execSync.
|
|
1672
|
+
* This is used by the CLI for local dependency installation.
|
|
1673
|
+
*
|
|
1674
|
+
* @returns CommandRunner that uses child_process.execSync
|
|
1675
|
+
*
|
|
1676
|
+
* @example
|
|
1677
|
+
* ```typescript
|
|
1678
|
+
* const runner = createNodeCommandRunner();
|
|
1679
|
+
* const result = await runner('npm', ['install'], { cwd: '/path/to/repo' });
|
|
1680
|
+
* ```
|
|
607
1681
|
*/
|
|
608
|
-
declare function
|
|
609
|
-
fixable: SpecDocDrift2[];
|
|
610
|
-
nonFixable: SpecDocDrift2[];
|
|
611
|
-
};
|
|
612
|
-
import { SpecExport as SpecExport4 } from "@openpkg-ts/spec";
|
|
613
|
-
import { SpecExport as SpecExport3 } from "@openpkg-ts/spec";
|
|
614
|
-
type LintSeverity2 = "error" | "warn" | "off";
|
|
615
|
-
interface LintViolation {
|
|
616
|
-
rule: string;
|
|
617
|
-
severity: "error" | "warn";
|
|
618
|
-
message: string;
|
|
619
|
-
line?: number;
|
|
620
|
-
fixable: boolean;
|
|
621
|
-
}
|
|
622
|
-
interface LintRule {
|
|
623
|
-
name: string;
|
|
624
|
-
defaultSeverity: LintSeverity2;
|
|
625
|
-
check(exp: SpecExport3, rawJSDoc?: string): LintViolation[];
|
|
626
|
-
fix?(exp: SpecExport3, rawJSDoc?: string): JSDocPatch | null;
|
|
627
|
-
}
|
|
628
|
-
interface LintConfig {
|
|
629
|
-
rules: Record<string, LintSeverity2>;
|
|
630
|
-
}
|
|
631
|
-
interface LintResult {
|
|
632
|
-
violations: LintViolation[];
|
|
633
|
-
errorCount: number;
|
|
634
|
-
warningCount: number;
|
|
635
|
-
fixableCount: number;
|
|
636
|
-
}
|
|
637
|
-
/** All available lint rules */
|
|
638
|
-
declare const allRules: LintRule[];
|
|
639
|
-
/** Default configuration with rule defaults */
|
|
640
|
-
declare function getDefaultConfig(): LintConfig;
|
|
641
|
-
/** Get a rule by name */
|
|
642
|
-
declare function getRule(name: string): LintRule | undefined;
|
|
643
|
-
/** Lint a single */
|
|
644
|
-
declare function lintExport(exp: SpecExport4, rawJSDoc?: string, config?: LintConfig): LintViolation[];
|
|
645
|
-
/** Lint multiple exports and aggregate results */
|
|
646
|
-
declare function lintExports(exports: Array<{
|
|
647
|
-
export: SpecExport4;
|
|
648
|
-
rawJSDoc?: string;
|
|
649
|
-
}>, config?: LintConfig): LintResult;
|
|
650
|
-
/** Merge user config with defaults */
|
|
651
|
-
declare function mergeConfig(userConfig: Partial<LintConfig>): LintConfig;
|
|
652
|
-
declare const consistentParamStyle: LintRule;
|
|
653
|
-
declare const noEmptyReturns: LintRule;
|
|
654
|
-
declare const requireDescription: LintRule;
|
|
655
|
-
declare const requireExample: LintRule;
|
|
1682
|
+
declare function createNodeCommandRunner(): CommandRunner;
|
|
656
1683
|
import { SpecDiff } from "@openpkg-ts/spec";
|
|
657
1684
|
type MemberChangeType = "added" | "removed" | "signature-changed";
|
|
658
1685
|
interface MemberChange {
|
|
@@ -809,7 +1836,7 @@ declare function getDocumentedExports(markdownFiles: MarkdownDocFile[], exportNa
|
|
|
809
1836
|
* Get all exports that lack documentation
|
|
810
1837
|
*/
|
|
811
1838
|
declare function getUndocumentedExports(markdownFiles: MarkdownDocFile[], exportNames: string[]): string[];
|
|
812
|
-
import { CategorizedBreaking, OpenPkg as
|
|
1839
|
+
import { CategorizedBreaking, OpenPkg as OpenPkg7, SpecDiff as SpecDiff2 } from "@openpkg-ts/spec";
|
|
813
1840
|
/**
|
|
814
1841
|
* Extended spec diff result with docs impact
|
|
815
1842
|
*/
|
|
@@ -855,7 +1882,7 @@ interface DiffWithDocsOptions {
|
|
|
855
1882
|
* }
|
|
856
1883
|
* ```
|
|
857
1884
|
*/
|
|
858
|
-
declare function diffSpecWithDocs(oldSpec:
|
|
1885
|
+
declare function diffSpecWithDocs(oldSpec: OpenPkg7, newSpec: OpenPkg7, options?: DiffWithDocsOptions): SpecDiffWithDocs;
|
|
859
1886
|
/**
|
|
860
1887
|
* Check if a diff has any docs impact
|
|
861
1888
|
*/
|
|
@@ -925,6 +1952,10 @@ interface AnalysisResult {
|
|
|
925
1952
|
spec: OpenPkgSpec;
|
|
926
1953
|
diagnostics: Diagnostic[];
|
|
927
1954
|
metadata: AnalysisMetadata;
|
|
1955
|
+
/** True if result came from cache (no fresh analysis) */
|
|
1956
|
+
fromCache?: boolean;
|
|
1957
|
+
/** Cache validation details (if cache was checked) */
|
|
1958
|
+
cacheStatus?: CacheValidationResult;
|
|
928
1959
|
}
|
|
929
1960
|
interface AnalysisMetadata {
|
|
930
1961
|
baseDir: string;
|
|
@@ -932,6 +1963,8 @@ interface AnalysisMetadata {
|
|
|
932
1963
|
packageJsonPath?: string;
|
|
933
1964
|
hasNodeModules: boolean;
|
|
934
1965
|
resolveExternalTypes: boolean;
|
|
1966
|
+
/** Source files included in analysis (for caching) */
|
|
1967
|
+
sourceFiles?: string[];
|
|
935
1968
|
}
|
|
936
1969
|
interface AnalyzeOptions {
|
|
937
1970
|
filters?: FilterOptions;
|
|
@@ -944,6 +1977,23 @@ declare class DocCov {
|
|
|
944
1977
|
analyzeProject(entryPath: string, analyzeOptions?: AnalyzeOptions): Promise<OpenPkgSpec>;
|
|
945
1978
|
analyzeWithDiagnostics(code: string, fileName?: string, analyzeOptions?: AnalyzeOptions): Promise<AnalysisResult>;
|
|
946
1979
|
analyzeFileWithDiagnostics(filePath: string, analyzeOptions?: AnalyzeOptions): Promise<AnalysisResult>;
|
|
1980
|
+
/**
|
|
1981
|
+
* Try to load spec from cache.
|
|
1982
|
+
* Returns null if cache is invalid or doesn't exist.
|
|
1983
|
+
*/
|
|
1984
|
+
private tryLoadFromCache;
|
|
1985
|
+
/**
|
|
1986
|
+
* Save analysis result to cache.
|
|
1987
|
+
*/
|
|
1988
|
+
private saveToCache;
|
|
1989
|
+
/**
|
|
1990
|
+
* Find tsconfig.json starting from a directory.
|
|
1991
|
+
*/
|
|
1992
|
+
private findTsConfig;
|
|
1993
|
+
/**
|
|
1994
|
+
* Find package.json starting from a directory.
|
|
1995
|
+
*/
|
|
1996
|
+
private findPackageJson;
|
|
947
1997
|
private normalizeDiagnostic;
|
|
948
1998
|
private mapSeverity;
|
|
949
1999
|
private normalizeMetadata;
|
|
@@ -952,351 +2002,118 @@ declare class DocCov {
|
|
|
952
2002
|
declare function analyze(code: string, options?: AnalyzeOptions): Promise<OpenPkgSpec>;
|
|
953
2003
|
declare function analyzeFile(filePath: string, options?: AnalyzeOptions): Promise<OpenPkgSpec>;
|
|
954
2004
|
/** @deprecated Use DocCov instead */
|
|
955
|
-
declare const
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
exampleIndex: number;
|
|
959
|
-
/** Line number within the example (1-based) */
|
|
960
|
-
line: number;
|
|
961
|
-
/** Column number (1-based) */
|
|
962
|
-
column: number;
|
|
963
|
-
/** Error message from TypeScript */
|
|
964
|
-
message: string;
|
|
965
|
-
/** TypeScript diagnostic code */
|
|
966
|
-
code: number;
|
|
967
|
-
}
|
|
968
|
-
interface TypecheckResult {
|
|
969
|
-
/** All type errors found across examples */
|
|
970
|
-
errors: ExampleTypeError[];
|
|
971
|
-
/** Number of examples that passed */
|
|
972
|
-
passed: number;
|
|
973
|
-
/** Number of examples that failed */
|
|
974
|
-
failed: number;
|
|
975
|
-
}
|
|
976
|
-
interface TypecheckOptions {
|
|
977
|
-
/** Path to tsconfig.json (auto-detected if not provided) */
|
|
978
|
-
tsconfig?: string;
|
|
979
|
-
/** Package name for imports (auto-detected from package.json if not provided) */
|
|
980
|
-
packageName?: string;
|
|
981
|
-
}
|
|
982
|
-
/**
|
|
983
|
-
* Type-check a single example
|
|
984
|
-
*/
|
|
985
|
-
declare function typecheckExample(example: string, packagePath: string, options?: TypecheckOptions): ExampleTypeError[];
|
|
986
|
-
/**
|
|
987
|
-
* Type-check multiple examples
|
|
988
|
-
*/
|
|
989
|
-
declare function typecheckExamples(examples: string[], packagePath: string, options?: TypecheckOptions): TypecheckResult;
|
|
990
|
-
/**
|
|
991
|
-
* Scan types for CLI, API, and SDK consumers.
|
|
992
|
-
* Single source of truth for scan-related interfaces.
|
|
993
|
-
*/
|
|
994
|
-
/**
|
|
995
|
-
* Result of scanning a repository for documentation coverage.
|
|
996
|
-
* Used by CLI scan command, API endpoints, and SDK consumers.
|
|
997
|
-
*/
|
|
998
|
-
interface ScanResult {
|
|
999
|
-
/** GitHub repository owner */
|
|
1000
|
-
owner: string;
|
|
1001
|
-
/** GitHub repository name */
|
|
1002
|
-
repo: string;
|
|
1003
|
-
/** Git ref (branch/tag) that was scanned */
|
|
1004
|
-
ref: string;
|
|
1005
|
-
/** Package name if scanning a monorepo package */
|
|
1006
|
-
packageName?: string;
|
|
1007
|
-
/** Overall documentation coverage percentage (0-100) */
|
|
1008
|
-
coverage: number;
|
|
1009
|
-
/** Number of public exports analyzed */
|
|
1010
|
-
exportCount: number;
|
|
1011
|
-
/** Number of types analyzed */
|
|
1012
|
-
typeCount: number;
|
|
1013
|
-
/** Number of documentation drift issues found */
|
|
1014
|
-
driftCount: number;
|
|
1015
|
-
/** Names of exports missing documentation */
|
|
1016
|
-
undocumented: string[];
|
|
1017
|
-
/** Drift issues found during analysis */
|
|
1018
|
-
drift: DriftIssue[];
|
|
1019
|
-
}
|
|
1020
|
-
/**
|
|
1021
|
-
* A documentation drift issue.
|
|
1022
|
-
*/
|
|
1023
|
-
interface DriftIssue {
|
|
1024
|
-
/** Name of the with drift */
|
|
1025
|
-
export: string;
|
|
1026
|
-
/** Type of drift (e.g., 'param-mismatch', 'return-type') */
|
|
1027
|
-
type: string;
|
|
1028
|
-
/** Human-readable description of the issue */
|
|
1029
|
-
issue: string;
|
|
1030
|
-
/** Optional suggestion for fixing the issue */
|
|
1031
|
-
suggestion?: string;
|
|
1032
|
-
}
|
|
1033
|
-
/**
|
|
1034
|
-
* Options for running a scan.
|
|
1035
|
-
*/
|
|
1036
|
-
interface ScanOptions {
|
|
1037
|
-
/** GitHub URL or owner/repo shorthand */
|
|
1038
|
-
url: string;
|
|
1039
|
-
/** Git ref (branch/tag) to scan */
|
|
1040
|
-
ref?: string;
|
|
1041
|
-
/** Target package name for monorepos */
|
|
1042
|
-
package?: string;
|
|
1043
|
-
/** Skip dependency installation */
|
|
1044
|
-
skipInstall?: boolean;
|
|
1045
|
-
/** Skip external type resolution */
|
|
1046
|
-
skipResolve?: boolean;
|
|
1047
|
-
}
|
|
1048
|
-
/**
|
|
1049
|
-
* Stages of the scan pipeline.
|
|
1050
|
-
*/
|
|
1051
|
-
type ProgressStage = "cloning" | "detecting" | "installing" | "building" | "analyzing" | "complete";
|
|
1052
|
-
/**
|
|
1053
|
-
* Progress event emitted during scan operations.
|
|
1054
|
-
*/
|
|
1055
|
-
interface ProgressEvent {
|
|
1056
|
-
/** Current stage of the scan */
|
|
1057
|
-
stage: ProgressStage;
|
|
1058
|
-
/** Human-readable message */
|
|
1059
|
-
message: string;
|
|
1060
|
-
/** Progress percentage (0-100), if known */
|
|
1061
|
-
progress?: number;
|
|
1062
|
-
}
|
|
1063
|
-
/**
|
|
1064
|
-
* Callback for receiving progress events.
|
|
1065
|
-
*/
|
|
1066
|
-
type ProgressCallback = (event: ProgressEvent) => void;
|
|
1067
|
-
import { OpenPkg as OpenPkg5 } from "@openpkg-ts/spec";
|
|
1068
|
-
/**
|
|
1069
|
-
* Summary of a spec's documentation coverage.
|
|
1070
|
-
* Simpler than full ReportStats - focused on scan output.
|
|
1071
|
-
*/
|
|
1072
|
-
interface SpecSummary {
|
|
1073
|
-
/** Overall coverage percentage */
|
|
1074
|
-
coverage: number;
|
|
1075
|
-
/** Number of exports */
|
|
1076
|
-
exportCount: number;
|
|
1077
|
-
/** Number of types */
|
|
1078
|
-
typeCount: number;
|
|
1079
|
-
/** Number of drift issues */
|
|
1080
|
-
driftCount: number;
|
|
1081
|
-
/** Names of undocumented or partially documented exports */
|
|
1082
|
-
undocumented: string[];
|
|
1083
|
-
/** Drift issues */
|
|
1084
|
-
drift: DriftIssue[];
|
|
1085
|
-
}
|
|
1086
|
-
/**
|
|
1087
|
-
* Extract a summary from an OpenPkg spec.
|
|
1088
|
-
*
|
|
1089
|
-
* This consolidates the logic previously duplicated in:
|
|
1090
|
-
* - CLI scan.ts (drift collection)
|
|
1091
|
-
* - CLI reports/stats.ts (computeStats)
|
|
1092
|
-
* - API scan-stream.ts (inline extraction script)
|
|
1093
|
-
*
|
|
1094
|
-
* @param spec - The OpenPkg spec to summarize
|
|
1095
|
-
* @returns Summary of documentation coverage
|
|
1096
|
-
*
|
|
1097
|
-
* @example
|
|
1098
|
-
* ```typescript
|
|
1099
|
-
* import { extractSpecSummary } from '@doccov/sdk';
|
|
1100
|
-
*
|
|
1101
|
-
* const summary = extractSpecSummary(spec);
|
|
1102
|
-
* console.log(`Coverage: ${summary.coverage}%`);
|
|
1103
|
-
* console.log(`Undocumented: ${summary.undocumented.length}`);
|
|
1104
|
-
* ```
|
|
1105
|
-
*/
|
|
1106
|
-
declare function extractSpecSummary(spec: OpenPkg5): SpecSummary;
|
|
1107
|
-
import { OpenPkg as OpenPkg7 } from "@openpkg-ts/spec";
|
|
1108
|
-
/**
|
|
1109
|
-
* Result of running a command.
|
|
1110
|
-
*/
|
|
1111
|
-
interface CommandResult {
|
|
1112
|
-
/** Exit code (0 = success) */
|
|
1113
|
-
exitCode: number;
|
|
1114
|
-
/** Standard output */
|
|
1115
|
-
stdout: string;
|
|
1116
|
-
/** Standard error */
|
|
1117
|
-
stderr: string;
|
|
1118
|
-
}
|
|
2005
|
+
declare const OpenPkg8: typeof DocCov;
|
|
2006
|
+
import { SpecExport as SpecExport6 } from "@openpkg-ts/spec";
|
|
2007
|
+
import { SpecExportKind as SpecExportKind2 } from "@openpkg-ts/spec";
|
|
1119
2008
|
/**
|
|
1120
|
-
*
|
|
1121
|
-
* Abstracts the difference between Node.js execSync and Sandbox runCommand.
|
|
2009
|
+
* Core quality rules - these affect coverage score.
|
|
1122
2010
|
*/
|
|
1123
|
-
|
|
1124
|
-
cwd: string;
|
|
1125
|
-
timeout?: number;
|
|
1126
|
-
}) => Promise<CommandResult>;
|
|
2011
|
+
declare const CORE_RULES: QualityRule[];
|
|
1127
2012
|
/**
|
|
1128
|
-
*
|
|
2013
|
+
* Style rules - these don't affect coverage, only lint.
|
|
1129
2014
|
*/
|
|
1130
|
-
|
|
1131
|
-
/** Whether installation succeeded */
|
|
1132
|
-
success: boolean;
|
|
1133
|
-
/** Package manager that was used */
|
|
1134
|
-
packageManager: PackageManager;
|
|
1135
|
-
/** If a fallback was used, which one */
|
|
1136
|
-
fallbackUsed?: PackageManager;
|
|
1137
|
-
/** Error message if installation failed */
|
|
1138
|
-
error?: string;
|
|
1139
|
-
/** Detailed error messages from each attempt */
|
|
1140
|
-
errors?: string[];
|
|
1141
|
-
}
|
|
2015
|
+
declare const STYLE_RULES: QualityRule[];
|
|
1142
2016
|
/**
|
|
1143
|
-
*
|
|
2017
|
+
* All built-in quality rules.
|
|
1144
2018
|
*/
|
|
1145
|
-
|
|
1146
|
-
/** Timeout in milliseconds for install commands (default: 180000) */
|
|
1147
|
-
timeout?: number;
|
|
1148
|
-
/** Order of fallback package managers to try */
|
|
1149
|
-
fallbackOrder?: PackageManager[];
|
|
1150
|
-
/** Progress callback for status updates */
|
|
1151
|
-
onProgress?: ProgressCallback;
|
|
1152
|
-
}
|
|
2019
|
+
declare const BUILTIN_RULES: QualityRule[];
|
|
1153
2020
|
/**
|
|
1154
|
-
*
|
|
1155
|
-
*
|
|
1156
|
-
* This consolidates the install logic from CLI scan.ts and API scan-stream.ts:
|
|
1157
|
-
* 1. Detect package manager from lockfile
|
|
1158
|
-
* 2. Try primary install command
|
|
1159
|
-
* 3. Fall back to other package managers if primary fails
|
|
1160
|
-
*
|
|
1161
|
-
* @param fs - FileSystem implementation for package manager detection
|
|
1162
|
-
* @param cwd - Working directory to install in
|
|
1163
|
-
* @param runCommand - Function to run shell commands
|
|
1164
|
-
* @param options - Installation options
|
|
1165
|
-
* @returns Result of the installation attempt
|
|
1166
|
-
*
|
|
1167
|
-
* @example
|
|
1168
|
-
* ```typescript
|
|
1169
|
-
* import { NodeFileSystem, installDependencies, createNodeCommandRunner } from '@doccov/sdk';
|
|
1170
|
-
*
|
|
1171
|
-
* const fs = new NodeFileSystem('/path/to/repo');
|
|
1172
|
-
* const result = await installDependencies(fs, '/path/to/repo', createNodeCommandRunner());
|
|
1173
|
-
*
|
|
1174
|
-
* if (result.success) {
|
|
1175
|
-
* console.log(`Installed using ${result.packageManager}`);
|
|
1176
|
-
* } else {
|
|
1177
|
-
* console.error(`Install failed: ${result.error}`);
|
|
1178
|
-
* }
|
|
1179
|
-
* ```
|
|
2021
|
+
* Get rules that affect coverage calculation.
|
|
1180
2022
|
*/
|
|
1181
|
-
declare function
|
|
2023
|
+
declare function getCoverageRules(): QualityRule[];
|
|
1182
2024
|
/**
|
|
1183
|
-
*
|
|
1184
|
-
* This is used by the CLI for local dependency installation.
|
|
1185
|
-
*
|
|
1186
|
-
* @returns CommandRunner that uses child_process.execSync
|
|
1187
|
-
*
|
|
1188
|
-
* @example
|
|
1189
|
-
* ```typescript
|
|
1190
|
-
* const runner = createNodeCommandRunner();
|
|
1191
|
-
* const result = await runner('npm', ['install'], { cwd: '/path/to/repo' });
|
|
1192
|
-
* ```
|
|
2025
|
+
* Get rules applicable to a specific kind.
|
|
1193
2026
|
*/
|
|
1194
|
-
declare function
|
|
1195
|
-
import { OpenPkg as OpenPkg6 } from "@openpkg-ts/spec";
|
|
2027
|
+
declare function getRulesForKind(kind: SpecExportKind2): QualityRule[];
|
|
1196
2028
|
/**
|
|
1197
|
-
*
|
|
2029
|
+
* Get a rule by ID.
|
|
1198
2030
|
*/
|
|
1199
|
-
|
|
1200
|
-
/** Repository owner (user or org) */
|
|
1201
|
-
owner: string;
|
|
1202
|
-
/** Repository name */
|
|
1203
|
-
repo: string;
|
|
1204
|
-
/** Git ref (branch or tag) */
|
|
1205
|
-
ref: string;
|
|
1206
|
-
}
|
|
2031
|
+
declare function getRule(id: string): QualityRule | undefined;
|
|
1207
2032
|
/**
|
|
1208
|
-
*
|
|
1209
|
-
*
|
|
1210
|
-
* Supported formats:
|
|
1211
|
-
* - https://github.com/owner/repo
|
|
1212
|
-
* - https://github.com/owner/repo/tree/branch
|
|
1213
|
-
* - https://github.com/owner/repo/tree/v1.0.0
|
|
1214
|
-
* - github.com/owner/repo
|
|
1215
|
-
* - owner/repo (shorthand)
|
|
1216
|
-
* - git@github.com:owner/repo.git
|
|
1217
|
-
*
|
|
1218
|
-
* @param input - GitHub URL or shorthand
|
|
1219
|
-
* @param defaultRef - Default ref if not specified in URL (default: 'main')
|
|
1220
|
-
* @returns Parsed components
|
|
1221
|
-
* @throws Error if the URL format is invalid
|
|
1222
|
-
*
|
|
1223
|
-
* @example
|
|
1224
|
-
* ```typescript
|
|
1225
|
-
* import { parseGitHubUrl } from '@doccov/sdk';
|
|
1226
|
-
*
|
|
1227
|
-
* const parsed = parseGitHubUrl('https://github.com/vercel/next.js/tree/canary');
|
|
1228
|
-
* // { owner: 'vercel', repo: 'next.js', ref: 'canary' }
|
|
1229
|
-
*
|
|
1230
|
-
* const shorthand = parseGitHubUrl('vercel/next.js');
|
|
1231
|
-
* // { owner: 'vercel', repo: 'next.js', ref: 'main' }
|
|
1232
|
-
* ```
|
|
2033
|
+
* Get default configuration with all rule defaults.
|
|
1233
2034
|
*/
|
|
1234
|
-
declare function
|
|
2035
|
+
declare function getDefaultConfig(): Record<string, QualitySeverity>;
|
|
1235
2036
|
/**
|
|
1236
|
-
*
|
|
2037
|
+
* Evaluate quality for a single export.
|
|
1237
2038
|
*
|
|
1238
|
-
* @param
|
|
1239
|
-
* @
|
|
1240
|
-
*
|
|
1241
|
-
* @
|
|
1242
|
-
* ```typescript
|
|
1243
|
-
* const cloneUrl = buildCloneUrl({ owner: 'vercel', repo: 'next.js', ref: 'main' });
|
|
1244
|
-
* // 'https://github.com/vercel/next.js.git'
|
|
1245
|
-
* ```
|
|
2039
|
+
* @param exp - The to evaluate
|
|
2040
|
+
* @param rawJSDoc - Optional raw JSDoc text for regex-based checks
|
|
2041
|
+
* @param config - Quality configuration with rule severities
|
|
2042
|
+
* @returns Quality result with coverage score and violations
|
|
1246
2043
|
*/
|
|
1247
|
-
declare function
|
|
2044
|
+
declare function evaluateExportQuality(exp: SpecExport6, rawJSDoc?: string, config?: QualityConfig): QualityResult;
|
|
1248
2045
|
/**
|
|
1249
|
-
*
|
|
1250
|
-
*
|
|
1251
|
-
* @param parsed - Parsed GitHub URL components
|
|
1252
|
-
* @returns Display URL like 'github.com/owner/repo'
|
|
2046
|
+
* Evaluate quality for multiple exports.
|
|
1253
2047
|
*
|
|
1254
|
-
* @
|
|
1255
|
-
*
|
|
1256
|
-
*
|
|
1257
|
-
* // 'github.com/vercel/next.js'
|
|
1258
|
-
* ```
|
|
2048
|
+
* @param exports - Array of exports with optional raw JSDoc
|
|
2049
|
+
* @param config - Quality configuration with rule severities
|
|
2050
|
+
* @returns Aggregate result with per-and overall scores
|
|
1259
2051
|
*/
|
|
1260
|
-
declare function
|
|
2052
|
+
declare function evaluateQuality(exports: Array<{
|
|
2053
|
+
export: SpecExport6;
|
|
2054
|
+
rawJSDoc?: string;
|
|
2055
|
+
}>, config?: QualityConfig): AggregateQualityResult;
|
|
1261
2056
|
/**
|
|
1262
|
-
*
|
|
2057
|
+
* Merge user configuration with defaults.
|
|
1263
2058
|
*
|
|
1264
|
-
* @param
|
|
1265
|
-
* @
|
|
1266
|
-
* @returns Raw content URL
|
|
2059
|
+
* @param userConfig - Partial user configuration
|
|
2060
|
+
* @returns Complete configuration with defaults filled in
|
|
1267
2061
|
*/
|
|
1268
|
-
declare function
|
|
2062
|
+
declare function mergeConfig(userConfig: Partial<QualityConfig>): QualityConfig;
|
|
1269
2063
|
/**
|
|
1270
|
-
*
|
|
2064
|
+
* Options for resolving a target package/entry point.
|
|
2065
|
+
*/
|
|
2066
|
+
interface ResolveTargetOptions {
|
|
2067
|
+
/** Working directory (usually process.cwd()) */
|
|
2068
|
+
cwd: string;
|
|
2069
|
+
/** Target package name for monorepos */
|
|
2070
|
+
package?: string;
|
|
2071
|
+
/** Explicit entry point path (relative to cwd or package dir) */
|
|
2072
|
+
entry?: string;
|
|
2073
|
+
}
|
|
2074
|
+
/**
|
|
2075
|
+
* Result of resolving a target package/entry point.
|
|
2076
|
+
*/
|
|
2077
|
+
interface ResolvedTarget {
|
|
2078
|
+
/** Resolved directory containing the package */
|
|
2079
|
+
targetDir: string;
|
|
2080
|
+
/** Resolved entry point file path (absolute) */
|
|
2081
|
+
entryFile: string;
|
|
2082
|
+
/** Package info if this is a monorepo package */
|
|
2083
|
+
packageInfo?: WorkspacePackage;
|
|
2084
|
+
/** Entry point detection info */
|
|
2085
|
+
entryPointInfo: EntryPointInfo;
|
|
2086
|
+
}
|
|
2087
|
+
/**
|
|
2088
|
+
* Resolve a target package and entry point.
|
|
1271
2089
|
*
|
|
1272
|
-
*
|
|
2090
|
+
* This consolidates the repeated pattern from CLI commands:
|
|
2091
|
+
* 1. If --package specified, detect monorepo and find the package
|
|
2092
|
+
* 2. If no entry specified, auto-detect entry point
|
|
2093
|
+
* 3. If entry is a directory, detect entry point within it
|
|
1273
2094
|
*
|
|
1274
|
-
* @param
|
|
1275
|
-
* @
|
|
2095
|
+
* @param fs - FileSystem implementation (NodeFileSystem or SandboxFileSystem)
|
|
2096
|
+
* @param options - Resolution options
|
|
2097
|
+
* @returns Resolved target info
|
|
2098
|
+
* @throws Error if monorepo package not found, or entry point detection fails
|
|
1276
2099
|
*
|
|
1277
2100
|
* @example
|
|
1278
2101
|
* ```typescript
|
|
1279
|
-
* import {
|
|
1280
|
-
*
|
|
1281
|
-
* const parsed = parseGitHubUrl('vercel/next.js');
|
|
1282
|
-
* const spec = await fetchSpecFromGitHub(parsed);
|
|
1283
|
-
* if (spec) {
|
|
1284
|
-
* console.log(`Coverage: ${spec.docs?.coverageScore}%`);
|
|
1285
|
-
* }
|
|
1286
|
-
* ```
|
|
1287
|
-
*/
|
|
1288
|
-
declare function fetchSpecFromGitHub(parsed: ParsedGitHubUrl): Promise<OpenPkg6 | null>;
|
|
1289
|
-
/**
|
|
1290
|
-
* Fetch an OpenPkg spec from a GitHub repository by owner/repo/branch.
|
|
2102
|
+
* import { NodeFileSystem, resolveTarget } from '@doccov/sdk';
|
|
1291
2103
|
*
|
|
1292
|
-
*
|
|
2104
|
+
* // Simple usage
|
|
2105
|
+
* const fs = new NodeFileSystem(process.cwd());
|
|
2106
|
+
* const { targetDir, entryFile } = await resolveTarget(fs, { cwd: process.cwd() });
|
|
1293
2107
|
*
|
|
1294
|
-
*
|
|
1295
|
-
*
|
|
1296
|
-
*
|
|
1297
|
-
* @
|
|
2108
|
+
* // With monorepo package
|
|
2109
|
+
* const { targetDir, entryFile, packageInfo } = await resolveTarget(fs, {
|
|
2110
|
+
* cwd: process.cwd(),
|
|
2111
|
+
* package: '@myorg/core',
|
|
2112
|
+
* });
|
|
2113
|
+
* ```
|
|
1298
2114
|
*/
|
|
1299
|
-
declare function
|
|
2115
|
+
declare function resolveTarget(fs: FileSystem, options: ResolveTargetOptions): Promise<ResolvedTarget>;
|
|
2116
|
+
import { OpenPkg as OpenPkg9 } from "@openpkg-ts/spec";
|
|
1300
2117
|
/**
|
|
1301
2118
|
* Options for creating a ScanOrchestrator.
|
|
1302
2119
|
*/
|
|
@@ -1401,7 +2218,7 @@ declare class ScanOrchestrator {
|
|
|
1401
2218
|
* @param entryFile - Path to entry file (absolute)
|
|
1402
2219
|
* @returns OpenPkg spec
|
|
1403
2220
|
*/
|
|
1404
|
-
analyze(entryFile: string): Promise<
|
|
2221
|
+
analyze(entryFile: string): Promise<OpenPkg9>;
|
|
1405
2222
|
/**
|
|
1406
2223
|
* Run a complete scan workflow.
|
|
1407
2224
|
*
|
|
@@ -1419,56 +2236,51 @@ declare class MonorepoRequiresPackageError extends Error {
|
|
|
1419
2236
|
constructor(availablePackages: string[]);
|
|
1420
2237
|
}
|
|
1421
2238
|
/**
|
|
1422
|
-
*
|
|
1423
|
-
|
|
1424
|
-
interface ResolveTargetOptions {
|
|
1425
|
-
/** Working directory (usually process.cwd()) */
|
|
1426
|
-
cwd: string;
|
|
1427
|
-
/** Target package name for monorepos */
|
|
1428
|
-
package?: string;
|
|
1429
|
-
/** Explicit entry point path (relative to cwd or package dir) */
|
|
1430
|
-
entry?: string;
|
|
1431
|
-
}
|
|
1432
|
-
/**
|
|
1433
|
-
* Result of resolving a target package/entry point.
|
|
2239
|
+
* Summary of a spec's documentation coverage.
|
|
2240
|
+
* Simpler than full ReportStats - focused on scan output.
|
|
1434
2241
|
*/
|
|
1435
|
-
interface
|
|
1436
|
-
/**
|
|
1437
|
-
|
|
1438
|
-
/**
|
|
1439
|
-
|
|
1440
|
-
/**
|
|
1441
|
-
|
|
1442
|
-
/**
|
|
1443
|
-
|
|
2242
|
+
interface SpecSummary {
|
|
2243
|
+
/** Overall coverage percentage */
|
|
2244
|
+
coverage: number;
|
|
2245
|
+
/** Number of exports */
|
|
2246
|
+
exportCount: number;
|
|
2247
|
+
/** Number of types */
|
|
2248
|
+
typeCount: number;
|
|
2249
|
+
/** Number of drift issues */
|
|
2250
|
+
driftCount: number;
|
|
2251
|
+
/** Names of undocumented or partially documented exports */
|
|
2252
|
+
undocumented: string[];
|
|
2253
|
+
/** Drift issues */
|
|
2254
|
+
drift: DriftIssue[];
|
|
1444
2255
|
}
|
|
1445
2256
|
/**
|
|
1446
|
-
*
|
|
2257
|
+
* Extract a summary from an enriched OpenPkg spec.
|
|
1447
2258
|
*
|
|
1448
|
-
* This consolidates the
|
|
1449
|
-
*
|
|
1450
|
-
*
|
|
1451
|
-
*
|
|
2259
|
+
* This consolidates the logic previously duplicated in:
|
|
2260
|
+
* - CLI scan.ts (drift collection)
|
|
2261
|
+
* - CLI reports/stats.ts (computeStats)
|
|
2262
|
+
* - API scan-stream.ts (inline extraction script)
|
|
1452
2263
|
*
|
|
1453
|
-
* @param
|
|
1454
|
-
* @
|
|
1455
|
-
* @returns Resolved target info
|
|
1456
|
-
* @throws Error if monorepo package not found, or entry point detection fails
|
|
2264
|
+
* @param spec - The enriched OpenPkg spec to summarize (must be enriched via enrichSpec())
|
|
2265
|
+
* @returns Summary of documentation coverage
|
|
1457
2266
|
*
|
|
1458
2267
|
* @example
|
|
1459
2268
|
* ```typescript
|
|
1460
|
-
* import {
|
|
1461
|
-
*
|
|
1462
|
-
* // Simple usage
|
|
1463
|
-
* const fs = new NodeFileSystem(process.cwd());
|
|
1464
|
-
* const { targetDir, entryFile } = await resolveTarget(fs, { cwd: process.cwd() });
|
|
2269
|
+
* import { enrichSpec, extractSpecSummary } from '@doccov/sdk';
|
|
1465
2270
|
*
|
|
1466
|
-
*
|
|
1467
|
-
* const
|
|
1468
|
-
*
|
|
1469
|
-
*
|
|
1470
|
-
* });
|
|
2271
|
+
* const enriched = enrichSpec(spec);
|
|
2272
|
+
* const summary = extractSpecSummary(enriched);
|
|
2273
|
+
* console.log(`Coverage: ${summary.coverage}%`);
|
|
2274
|
+
* console.log(`Undocumented: ${summary.undocumented.length}`);
|
|
1471
2275
|
* ```
|
|
1472
2276
|
*/
|
|
1473
|
-
declare function
|
|
1474
|
-
|
|
2277
|
+
declare function extractSpecSummary(spec: EnrichedOpenPkg): SpecSummary;
|
|
2278
|
+
/**
|
|
2279
|
+
* Type-check a single example
|
|
2280
|
+
*/
|
|
2281
|
+
declare function typecheckExample(example: string, packagePath: string, options?: TypecheckOptions): ExampleTypeError[];
|
|
2282
|
+
/**
|
|
2283
|
+
* Type-check multiple examples
|
|
2284
|
+
*/
|
|
2285
|
+
declare function typecheckExamples(examples: string[], packagePath: string, options?: TypecheckOptions): TypecheckResult;
|
|
2286
|
+
export { validateSpecCache, validateExamples, typecheckExamples, typecheckExample, shouldValidate, serializeJSDoc, saveSpecCache, saveReport, safeParseJson, runExamplesWithPackage, runExamples, runExample, resolveTarget, readPackageJson, parseMarkdownFiles, parseMarkdownFile, parseListFlag, parseJSDocToPatch, parseGitHubUrl, parseExamplesFlag, parseAssertions, mergeFixes, mergeFilters, mergeConfig, loadSpecCache, loadCachedReport, isFixableDrift, isExecutableLang, isCachedReportValid, installDependencies, hashString, hashFiles, hashFile, hasNonAssertionComments, hasDocsImpact, hasDocsForExport, groupDriftsByCategory, getUndocumentedExports, getSpecCachePath, getRunCommand, getRulesForKind, getRule, getReportPath, getPrimaryBuildScript, getInstallCommand, getDriftSummary, getDocumentedExports, getDocsImpactSummary, getDefaultConfig, getCoverageRules, generateReportFromEnriched, generateReport, generateFixesForExport, generateFix, formatPackageList, formatDriftSummaryLine, findRemovedReferences, findPackageByName, findJSDocLocation, findExportReferences, findDeprecatedReferences, fetchSpecFromGitHub, fetchSpec, extractSpecSummary, extractPackageSpec, extractImports, extractFunctionCalls, evaluateQuality, evaluateExportQuality, enrichSpec, diffSpecWithDocs, diffHashes, detectPackageManager, detectMonorepo, detectExampleRuntimeErrors, detectExampleAssertionFailures, detectEntryPoint, detectBuildInfo, defineConfig, createSourceFile, createNodeCommandRunner, computeExportDrift, computeDrift, clearSpecCache, categorizeDrifts, categorizeDrift, buildRawUrl, buildExportRegistry, buildDisplayUrl, buildCloneUrl, blockReferencesExport, applyPatchToJSDoc, applyEdits, analyzeProject2 as analyzeProject, analyzeFile, analyzeDocsImpact, analyze, WorkspacePackage, VALIDATION_INFO, TypecheckValidationResult, TypecheckResult, TypecheckOptions, SpecSummary, SpecDiffWithDocs, SpecCacheConfig, SpecCache, ScanResult, ScanOrchestratorOptions, ScanOrchestrator, ScanOptions, ScanContext, SandboxFileSystem, STYLE_RULES, SPEC_CACHE_FILE, RuntimeDrift, RunValidationResult, RunExamplesWithPackageResult, RunExamplesWithPackageOptions, RunExampleOptions, RuleContext, ResolvedTarget, ResolvedFilters, ResolveTargetOptions, REPORT_VERSION, REPORT_EXTENSIONS, QualityViolation, QualitySeverity2 as QualitySeverity, QualityRulesConfig, QualityRule, QualityResult, QualityConfig, ProjectInfo, ProgressStage, ProgressEvent, ProgressCallback, PresenceResult, ParsedGitHubUrl, PackageManagerInfo, PackageManager, PackageJson, PackageExports, OpenPkgSpec, OpenPkgOptions, OpenPkg8 as OpenPkg, NodeFileSystem, MonorepoType, MonorepoRequiresPackageError, MonorepoInfo, MemberChange, MarkdownDocFile, MarkdownCodeBlock, LLMAssertion, JSDocTag, JSDocReturn, JSDocPatch, JSDocParam, JSDocEdit, InstallResult, InstallOptions, FixType, FixSuggestion, FilterSource, FilterOptions, FileSystem, ExportReference, ExportDriftResult, ExportCoverageData, ExampleValidationTypeError, ExampleValidationResult, ExampleValidationOptions, ExampleValidationMode, ExampleValidation, ExampleTypeError, ExampleRunResult, EntryPointSource, EntryPointInfo, EnrichedOpenPkg, EnrichedExport, EnrichedDocsMetadata, EnrichOptions, DriftSummary, DriftResult, DriftReportSummary, DriftReport, DriftIssue, DocsImpactResult, DocsImpactReference, DocsImpact, DocsConfig, DocsChangeType, DocCovReport, DocCovOptions, DocCovConfig, DocCov, DiffWithDocsOptions, Diagnostic, DEFAULT_REPORT_PATH, DEFAULT_REPORT_DIR, CoverageSummary, CommandRunner, CommandResult, CheckConfig, CategorizedDrift, CacheValidationResult, CacheContext, CORE_RULES, CACHE_VERSION, BuildInfo, BUILTIN_RULES, ApplyEditsResult, AnalyzeProjectOptions, AnalyzeOptions, AnalysisResult, AggregateQualityResult, ALL_VALIDATIONS };
|