@doccov/sdk 0.3.2 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -69,6 +69,214 @@ declare function hasNonAssertionComments(code: string): boolean;
69
69
  * Detect assertion failures by comparing stdout to expected values.
70
70
  */
71
71
  declare function detectExampleAssertionFailures(entry: SpecExport, runtimeResults: Map<number, ExampleRunResult>): SpecDocDrift[];
72
+ /**
73
+ * Markdown/MDX documentation analysis types
74
+ */
75
+ /**
76
+ * A code block extracted from a markdown file
77
+ */
78
+ interface MarkdownCodeBlock {
79
+ /** Language tag (ts, typescript, js, javascript, tsx, jsx) */
80
+ lang: string;
81
+ /** The code content */
82
+ code: string;
83
+ /** Raw meta string from code fence (e.g., "title=example.ts") */
84
+ meta?: string;
85
+ /** Starting line number in the markdown file */
86
+ lineStart: number;
87
+ /** Ending line number in the markdown file */
88
+ lineEnd: number;
89
+ }
90
+ /**
91
+ * A parsed markdown documentation file
92
+ */
93
+ interface MarkdownDocFile {
94
+ /** File path relative to project root */
95
+ path: string;
96
+ /** All executable code blocks found */
97
+ codeBlocks: MarkdownCodeBlock[];
98
+ }
99
+ /**
100
+ * A reference to an found in markdown
101
+ */
102
+ interface ExportReference {
103
+ /** The name of the being referenced */
104
+ exportName: string;
105
+ /** File path where the reference was found */
106
+ file: string;
107
+ /** Line number in the file */
108
+ line: number;
109
+ /** Surrounding code/text for context */
110
+ context: string;
111
+ /** Whether this reference is inside a code block */
112
+ inCodeBlock: boolean;
113
+ /** The code block index if inside a code block */
114
+ blockIndex?: number;
115
+ }
116
+ /**
117
+ * Change type for an impacted reference
118
+ */
119
+ type DocsChangeType = "signature-changed" | "removed" | "deprecated";
120
+ /**
121
+ * An impacted reference in a documentation file
122
+ */
123
+ interface DocsImpactReference {
124
+ /** The name that was changed */
125
+ exportName: string;
126
+ /** Line number in the file */
127
+ line: number;
128
+ /** Type of change affecting this reference */
129
+ changeType: DocsChangeType;
130
+ /** Suggested fix (AI-generated or deterministic) */
131
+ suggestion?: string;
132
+ /** Context around the reference */
133
+ context?: string;
134
+ }
135
+ /**
136
+ * Documentation file impact summary
137
+ */
138
+ interface DocsImpact {
139
+ /** File path */
140
+ file: string;
141
+ /** All impacted references in this file */
142
+ references: DocsImpactReference[];
143
+ }
144
+ /**
145
+ * Complete docs impact analysis result
146
+ */
147
+ interface DocsImpactResult {
148
+ /** Files with impacted references */
149
+ impactedFiles: DocsImpact[];
150
+ /** New exports that have no documentation */
151
+ missingDocs: string[];
152
+ /** Statistics */
153
+ stats: {
154
+ /** Total markdown files scanned */
155
+ filesScanned: number;
156
+ /** Total code blocks found */
157
+ codeBlocksFound: number;
158
+ /** Total references found */
159
+ referencesFound: number;
160
+ /** References impacted by changes */
161
+ impactedReferences: number;
162
+ };
163
+ }
164
+ /**
165
+ * Check if a language tag represents executable code
166
+ */
167
+ declare function isExecutableLang(lang: string | null | undefined): boolean;
168
+ /**
169
+ * Parse a markdown file and extract code blocks
170
+ */
171
+ declare function parseMarkdownFile(content: string, filePath: string): MarkdownDocFile;
172
+ /**
173
+ * Parse multiple markdown files
174
+ */
175
+ declare function parseMarkdownFiles(files: Array<{
176
+ path: string;
177
+ content: string;
178
+ }>): MarkdownDocFile[];
179
+ /**
180
+ * Extract import statements from code
181
+ * Finds named imports: import { X, Y } from 'pkg'
182
+ */
183
+ declare function extractImports(code: string): Array<{
184
+ name: string;
185
+ from: string;
186
+ }>;
187
+ /**
188
+ * Extract function calls from code
189
+ * Finds: functionName( or functionName<
190
+ */
191
+ declare function extractFunctionCalls(code: string): string[];
192
+ /**
193
+ * Find all references to given names in markdown files
194
+ */
195
+ declare function findExportReferences(files: MarkdownDocFile[], exportNames: string[]): ExportReference[];
196
+ /**
197
+ * Check if a code block references any of the given names
198
+ */
199
+ declare function blockReferencesExport(block: MarkdownCodeBlock, exportName: string): boolean;
200
+ import { SpecDiff } from "@openpkg-ts/spec";
201
+ /**
202
+ * Analyze docs impact from a spec diff
203
+ *
204
+ * @param diff - The spec diff result
205
+ * @param markdownFiles - Parsed markdown files
206
+ * @param newExportNames - All names in the new spec (for missing docs detection)
207
+ */
208
+ declare function analyzeDocsImpact(diff: SpecDiff, markdownFiles: MarkdownDocFile[], newExportNames?: string[]): DocsImpactResult;
209
+ /**
210
+ * Find references to deprecated exports
211
+ */
212
+ declare function findDeprecatedReferences(markdownFiles: MarkdownDocFile[], deprecatedExports: string[]): ExportReference[];
213
+ /**
214
+ * Find references to removed exports
215
+ */
216
+ declare function findRemovedReferences(markdownFiles: MarkdownDocFile[], removedExports: string[]): ExportReference[];
217
+ /**
218
+ * Check if any docs reference a specific */
219
+ declare function hasDocsForExport(markdownFiles: MarkdownDocFile[], exportName: string): boolean;
220
+ /**
221
+ * Get all exports that have documentation
222
+ */
223
+ declare function getDocumentedExports(markdownFiles: MarkdownDocFile[], exportNames: string[]): string[];
224
+ /**
225
+ * Get all exports that lack documentation
226
+ */
227
+ declare function getUndocumentedExports(markdownFiles: MarkdownDocFile[], exportNames: string[]): string[];
228
+ import { OpenPkg as OpenPkg2, SpecDiff as SpecDiff2 } from "@openpkg-ts/spec";
229
+ /**
230
+ * Extended spec diff result with docs impact
231
+ */
232
+ interface SpecDiffWithDocs extends SpecDiff2 {
233
+ /** Docs impact analysis (only present if markdown files provided) */
234
+ docsImpact?: DocsImpactResult;
235
+ }
236
+ /**
237
+ * Options for diffSpecWithDocs
238
+ */
239
+ interface DiffWithDocsOptions {
240
+ /** Parsed markdown documentation files */
241
+ markdownFiles?: MarkdownDocFile[];
242
+ }
243
+ /**
244
+ * Compute spec diff with optional docs impact analysis
245
+ *
246
+ * @param oldSpec - Previous version of the spec
247
+ * @param newSpec - Current version of the spec
248
+ * @param options - Options including markdown files to analyze
249
+ * @returns Extended diff result with docs impact
250
+ *
251
+ * @example
252
+ * ```ts
253
+ * import { diffSpecWithDocs, parseMarkdownFiles } from '@doccov/sdk';
254
+ *
255
+ * const markdownFiles = parseMarkdownFiles([
256
+ * { path: 'docs/guide.md', content: '...' },
257
+ * ]);
258
+ *
259
+ * const diff = diffSpecWithDocs(oldSpec, newSpec, { markdownFiles });
260
+ *
261
+ * if (diff.docsImpact?.impactedFiles.length) {
262
+ * console.log('Docs need updating!');
263
+ * }
264
+ * ```
265
+ */
266
+ declare function diffSpecWithDocs(oldSpec: OpenPkg2, newSpec: OpenPkg2, options?: DiffWithDocsOptions): SpecDiffWithDocs;
267
+ /**
268
+ * Check if a diff has any docs impact
269
+ */
270
+ declare function hasDocsImpact(diff: SpecDiffWithDocs): boolean;
271
+ /**
272
+ * Get summary of docs impact for display
273
+ */
274
+ declare function getDocsImpactSummary(diff: SpecDiffWithDocs): {
275
+ impactedFileCount: number;
276
+ impactedReferenceCount: number;
277
+ missingDocsCount: number;
278
+ totalIssues: number;
279
+ };
72
280
  interface DocCovOptions {
73
281
  includePrivate?: boolean;
74
282
  followImports?: boolean;
@@ -258,5 +466,261 @@ declare class DocCov {
258
466
  declare function analyze(code: string, options?: AnalyzeOptions): Promise<OpenPkgSpec>;
259
467
  declare function analyzeFile(filePath: string, options?: AnalyzeOptions): Promise<OpenPkgSpec>;
260
468
  /** @deprecated Use DocCov instead */
261
- declare const OpenPkg2: typeof DocCov;
262
- export { serializeJSDoc, runExamplesWithPackage, runExamples, runExample, parseJSDocToPatch, parseAssertions, mergeFixes, isFixableDrift, hasNonAssertionComments, generateFixesForExport, generateFix, findJSDocLocation, extractPackageSpec, detectExampleRuntimeErrors, detectExampleAssertionFailures, createSourceFile, categorizeDrifts, applyPatchToJSDoc, applyEdits, analyzeFile, analyze, RunExamplesWithPackageResult, RunExamplesWithPackageOptions, RunExampleOptions, OpenPkgSpec, OpenPkgOptions, OpenPkg2 as OpenPkg, JSDocTag, JSDocReturn, JSDocPatch, JSDocParam, JSDocEdit, FixType, FixSuggestion, FilterOptions, ExampleRunResult, DocCovOptions, DocCov, Diagnostic, ApplyEditsResult, AnalyzeOptions, AnalysisResult };
469
+ declare const OpenPkg3: typeof DocCov;
470
+ /**
471
+ * Project detection types for I/O-agnostic project analysis.
472
+ * Used by both CLI (NodeFileSystem) and API (SandboxFileSystem).
473
+ */
474
+ /**
475
+ * Minimal filesystem interface for I/O-agnostic detection.
476
+ * Implementations: NodeFileSystem (CLI), SandboxFileSystem (API)
477
+ */
478
+ interface FileSystem {
479
+ /** Check if a file or directory exists */
480
+ exists(path: string): Promise<boolean>;
481
+ /** Read file contents as string */
482
+ readFile(path: string): Promise<string>;
483
+ /** List directory contents (file/folder names only) */
484
+ readDir(path: string): Promise<string[]>;
485
+ /** Check if path is a directory */
486
+ isDirectory(path: string): Promise<boolean>;
487
+ }
488
+ /** Supported package managers */
489
+ type PackageManager = "npm" | "yarn" | "pnpm" | "bun";
490
+ /** Package manager detection result with install/run commands */
491
+ interface PackageManagerInfo {
492
+ /** Package manager name */
493
+ name: PackageManager;
494
+ /** Lockfile that was detected (null if none found) */
495
+ lockfile: string | null;
496
+ /** Arguments for install command, e.g. ['install', '--frozen-lockfile'] */
497
+ installArgs: string[];
498
+ /** Prefix for running scripts, e.g. ['npm', 'run'] or ['pnpm'] */
499
+ runPrefix: string[];
500
+ }
501
+ /** Monorepo type based on configuration */
502
+ type MonorepoType = "npm-workspaces" | "pnpm-workspaces" | "lerna" | "none";
503
+ /** Monorepo detection result */
504
+ interface MonorepoInfo {
505
+ /** Whether this is a monorepo */
506
+ isMonorepo: boolean;
507
+ /** Type of monorepo configuration */
508
+ type: MonorepoType;
509
+ /** Workspace patterns from config (e.g. ['packages/*']) */
510
+ patterns: string[];
511
+ /** Resolved workspace packages */
512
+ packages: WorkspacePackage[];
513
+ }
514
+ /** A package within a monorepo workspace */
515
+ interface WorkspacePackage {
516
+ /** Package name from package.json */
517
+ name: string;
518
+ /** Relative path to package directory */
519
+ path: string;
520
+ /** Whether the package is marked as private */
521
+ private: boolean;
522
+ }
523
+ /** Entry point source - where the entry was detected from */
524
+ type EntryPointSource = "types" | "exports" | "main" | "module" | "fallback";
525
+ /** Entry point detection result */
526
+ interface EntryPointInfo {
527
+ /** Path to entry file (relative to package root) */
528
+ path: string;
529
+ /** Where the entry point was detected from */
530
+ source: EntryPointSource;
531
+ /** Whether this is a .d.ts file (no source available) */
532
+ isDeclarationOnly: boolean;
533
+ }
534
+ /** Build configuration detection result */
535
+ interface BuildInfo {
536
+ /** Build-related script names found (e.g. ['build', 'build:types']) */
537
+ scripts: string[];
538
+ /** Whether any build script was found */
539
+ hasBuildScript: boolean;
540
+ /** Whether TypeScript is configured/installed */
541
+ hasTypeScript: boolean;
542
+ /** Indicators for exotic project types */
543
+ exoticIndicators: {
544
+ /** WASM project (Cargo.toml or wasm-pack scripts) */
545
+ wasm: boolean;
546
+ /** napi-rs native addon project */
547
+ napi: boolean;
548
+ };
549
+ }
550
+ /** Complete project analysis result */
551
+ interface ProjectInfo {
552
+ /** Package manager info */
553
+ packageManager: PackageManagerInfo;
554
+ /** Monorepo info */
555
+ monorepo: MonorepoInfo;
556
+ /** Entry point info */
557
+ entryPoint: EntryPointInfo;
558
+ /** Build info */
559
+ build: BuildInfo;
560
+ }
561
+ /** Options for analyzeProject() */
562
+ interface AnalyzeProjectOptions {
563
+ /** Target package name for monorepos */
564
+ targetPackage?: string;
565
+ }
566
+ import { Sandbox } from "@vercel/sandbox";
567
+ /**
568
+ * Node.js filesystem implementation for CLI usage.
569
+ * Wraps Node.js fs module with a base path.
570
+ */
571
+ declare class NodeFileSystem implements FileSystem {
572
+ private basePath;
573
+ constructor(basePath: string);
574
+ private resolve;
575
+ exists(relativePath: string): Promise<boolean>;
576
+ readFile(relativePath: string): Promise<string>;
577
+ readDir(relativePath: string): Promise<string[]>;
578
+ isDirectory(relativePath: string): Promise<boolean>;
579
+ }
580
+ /**
581
+ * Vercel Sandbox filesystem implementation for API usage.
582
+ * Uses sandbox.runCommand() with shell commands.
583
+ */
584
+ declare class SandboxFileSystem implements FileSystem {
585
+ private sandbox;
586
+ constructor(sandbox: Sandbox);
587
+ exists(path: string): Promise<boolean>;
588
+ readFile(path: string): Promise<string>;
589
+ readDir(path: string): Promise<string[]>;
590
+ isDirectory(path: string): Promise<boolean>;
591
+ }
592
+ /**
593
+ * Detect package manager based on lockfile presence.
594
+ *
595
+ * Priority order:
596
+ * 1. pnpm-lock.yaml
597
+ * 2. bun.lock / bun.lockb
598
+ * 3. yarn.lock
599
+ * 4. package-lock.json
600
+ * 5. Default to npm
601
+ */
602
+ declare function detectPackageManager(fs: FileSystem): Promise<PackageManagerInfo>;
603
+ /**
604
+ * Get install command for a package manager.
605
+ * Returns [command, ...args] array.
606
+ */
607
+ declare function getInstallCommand(pm: PackageManagerInfo): string[];
608
+ /**
609
+ * Get run command for a package manager script.
610
+ * Returns [command, ...args, scriptName] array.
611
+ */
612
+ declare function getRunCommand(pm: PackageManagerInfo, script: string): string[];
613
+ /**
614
+ * Detect if a project is a monorepo and list its packages.
615
+ *
616
+ * Detection triggers (in order):
617
+ * 1. package.json has workspaces field (npm/yarn)
618
+ * 2. pnpm-workspace.yaml exists
619
+ * 3. lerna.json exists
620
+ */
621
+ declare function detectMonorepo(fs: FileSystem): Promise<MonorepoInfo>;
622
+ /**
623
+ * Find a package by name or path in a list of workspace packages.
624
+ */
625
+ declare function findPackageByName(packages: WorkspacePackage[], nameOrPath: string): WorkspacePackage | undefined;
626
+ /**
627
+ * Format package list for display in error messages.
628
+ */
629
+ declare function formatPackageList(packages: WorkspacePackage[], limit?: number): string;
630
+ /**
631
+ * Detect the TypeScript entry point for a package.
632
+ *
633
+ * Priority order:
634
+ * 1. package.json -> types or typings field
635
+ * 2. package.json -> exports["."].types
636
+ * 3. package.json -> main field (resolve to .ts)
637
+ * 4. package.json -> module field (resolve to .ts)
638
+ * 5. Common fallback paths
639
+ *
640
+ * @param fs - FileSystem implementation
641
+ * @param packagePath - Path to package directory (default: ".")
642
+ * @returns Entry point info
643
+ * @throws Error if no entry point can be found
644
+ */
645
+ declare function detectEntryPoint(fs: FileSystem, packagePath?: string): Promise<EntryPointInfo>;
646
+ /**
647
+ * Detect build configuration and exotic project indicators.
648
+ *
649
+ * @param fs - FileSystem implementation
650
+ * @param packagePath - Path to package directory (default: ".")
651
+ * @returns Build info including scripts and exotic indicators
652
+ */
653
+ declare function detectBuildInfo(fs: FileSystem, packagePath?: string): Promise<BuildInfo>;
654
+ /**
655
+ * Get the primary build script name to run.
656
+ * Prefers 'build' over 'compile' over 'tsc'.
657
+ */
658
+ declare function getPrimaryBuildScript(buildInfo: BuildInfo): string | null;
659
+ /**
660
+ * Safely parse a JSON file, returning null on any error.
661
+ */
662
+ declare function safeParseJson<T = Record<string, unknown>>(fs: FileSystem, path: string): Promise<T | null>;
663
+ /**
664
+ * Standard package.json structure for detection purposes.
665
+ */
666
+ interface PackageJson {
667
+ name?: string;
668
+ version?: string;
669
+ private?: boolean;
670
+ main?: string;
671
+ module?: string;
672
+ types?: string;
673
+ typings?: string;
674
+ exports?: PackageExports;
675
+ workspaces?: string[] | {
676
+ packages: string[];
677
+ };
678
+ scripts?: Record<string, string>;
679
+ dependencies?: Record<string, string>;
680
+ devDependencies?: Record<string, string>;
681
+ }
682
+ /**
683
+ * Package.json exports field structure.
684
+ */
685
+ type PackageExports = string | {
686
+ "."?: string | {
687
+ types?: string;
688
+ import?: string;
689
+ require?: string;
690
+ default?: string;
691
+ };
692
+ [key: string]: unknown;
693
+ };
694
+ /**
695
+ * Read and parse package.json from a directory.
696
+ */
697
+ declare function readPackageJson(fs: FileSystem, dir: string): Promise<PackageJson | null>;
698
+ /**
699
+ * Analyze a project's structure for scanning.
700
+ *
701
+ * This is the main entry point for project detection. It combines all
702
+ * detection functions into a single call that returns complete project info.
703
+ *
704
+ * For monorepos, you must specify the target package via options.targetPackage.
705
+ * If not specified and a monorepo is detected, an error is thrown with the
706
+ * list of available packages.
707
+ *
708
+ * @param fs - FileSystem implementation (NodeFileSystem or SandboxFileSystem)
709
+ * @param options - Options including targetPackage for monorepos
710
+ * @returns Complete project info
711
+ * @throws Error if monorepo detected without targetPackage specified
712
+ * @throws Error if targetPackage not found in monorepo
713
+ *
714
+ * @example
715
+ * ```typescript
716
+ * // Single package
717
+ * const fs = new NodeFileSystem('/path/to/package');
718
+ * const project = await analyzeProject(fs);
719
+ *
720
+ * // Monorepo with target package
721
+ * const fs = new NodeFileSystem('/path/to/monorepo');
722
+ * const project = await analyzeProject(fs, { targetPackage: '@scope/core' });
723
+ * ```
724
+ */
725
+ declare function analyzeProject2(fs: FileSystem, options?: AnalyzeProjectOptions): Promise<ProjectInfo>;
726
+ export { serializeJSDoc, safeParseJson, runExamplesWithPackage, runExamples, runExample, readPackageJson, parseMarkdownFiles, parseMarkdownFile, parseJSDocToPatch, parseAssertions, mergeFixes, isFixableDrift, isExecutableLang, hasNonAssertionComments, hasDocsImpact, hasDocsForExport, getUndocumentedExports, getRunCommand, getPrimaryBuildScript, getInstallCommand, getDocumentedExports, getDocsImpactSummary, generateFixesForExport, generateFix, formatPackageList, findRemovedReferences, findPackageByName, findJSDocLocation, findExportReferences, findDeprecatedReferences, extractPackageSpec, extractImports, extractFunctionCalls, diffSpecWithDocs, detectPackageManager, detectMonorepo, detectExampleRuntimeErrors, detectExampleAssertionFailures, detectEntryPoint, detectBuildInfo, createSourceFile, categorizeDrifts, blockReferencesExport, applyPatchToJSDoc, applyEdits, analyzeProject2 as analyzeProject, analyzeFile, analyzeDocsImpact, analyze, WorkspacePackage, SpecDiffWithDocs, SandboxFileSystem, RunExamplesWithPackageResult, RunExamplesWithPackageOptions, RunExampleOptions, ProjectInfo, PackageManagerInfo, PackageManager, PackageJson, PackageExports, OpenPkgSpec, OpenPkgOptions, OpenPkg3 as OpenPkg, NodeFileSystem, MonorepoType, MonorepoInfo, MarkdownDocFile, MarkdownCodeBlock, JSDocTag, JSDocReturn, JSDocPatch, JSDocParam, JSDocEdit, FixType, FixSuggestion, FilterOptions, FileSystem, ExportReference, ExampleRunResult, EntryPointSource, EntryPointInfo, DocsImpactResult, DocsImpactReference, DocsImpact, DocsChangeType, DocCovOptions, DocCov, DiffWithDocsOptions, Diagnostic, BuildInfo, ApplyEditsResult, AnalyzeProjectOptions, AnalyzeOptions, AnalysisResult };