@doccov/sdk 0.5.9 → 0.7.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +1153 -524
  2. package/dist/index.js +3253 -2108
  3. package/package.json +2 -2
package/dist/index.d.ts CHANGED
@@ -70,6 +70,608 @@ declare function hasNonAssertionComments(code: string): boolean;
70
70
  */
71
71
  declare function detectExampleAssertionFailures(entry: SpecExport, runtimeResults: Map<number, ExampleRunResult>): SpecDocDrift[];
72
72
  /**
73
+ * Project detection types for I/O-agnostic project analysis.
74
+ * Used by both CLI (NodeFileSystem) and API (SandboxFileSystem).
75
+ */
76
+ /**
77
+ * Minimal filesystem interface for I/O-agnostic detection.
78
+ * Implementations: NodeFileSystem (CLI), SandboxFileSystem (API)
79
+ */
80
+ interface FileSystem {
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
+ }
168
+ /**
169
+ * Detect build configuration and exotic project indicators.
170
+ *
171
+ * @param fs - FileSystem implementation
172
+ * @param packagePath - Path to package directory (default: ".")
173
+ * @returns Build info including scripts and exotic indicators
174
+ */
175
+ declare function detectBuildInfo(fs: FileSystem, packagePath?: string): Promise<BuildInfo>;
176
+ /**
177
+ * Get the primary build script name to run.
178
+ * Prefers 'build' over 'compile' over 'tsc'.
179
+ */
180
+ declare function getPrimaryBuildScript(buildInfo: BuildInfo): string | null;
181
+ /**
182
+ * Detect the TypeScript entry point for a package.
183
+ *
184
+ * Priority order:
185
+ * 1. package.json -> types or typings field
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
190
+ *
191
+ * @param fs - FileSystem implementation
192
+ * @param packagePath - Path to package directory (default: ".")
193
+ * @returns Entry point info
194
+ * @throws Error if no entry point can be found
195
+ */
196
+ declare function detectEntryPoint(fs: FileSystem, packagePath?: string): Promise<EntryPointInfo>;
197
+ import { Sandbox } from "@vercel/sandbox";
198
+ /**
199
+ * Node.js filesystem implementation for CLI usage.
200
+ * Wraps Node.js fs module with a base path.
201
+ */
202
+ declare class NodeFileSystem implements FileSystem {
203
+ private basePath;
204
+ constructor(basePath: string);
205
+ private resolve;
206
+ exists(relativePath: string): Promise<boolean>;
207
+ readFile(relativePath: string): Promise<string>;
208
+ readDir(relativePath: string): Promise<string[]>;
209
+ isDirectory(relativePath: string): Promise<boolean>;
210
+ }
211
+ /**
212
+ * Vercel Sandbox filesystem implementation for API usage.
213
+ * Uses sandbox.runCommand() with shell commands.
214
+ */
215
+ declare class SandboxFileSystem implements FileSystem {
216
+ private sandbox;
217
+ constructor(sandbox: Sandbox);
218
+ exists(path: string): Promise<boolean>;
219
+ readFile(path: string): Promise<string>;
220
+ readDir(path: string): Promise<string[]>;
221
+ isDirectory(path: string): Promise<boolean>;
222
+ }
223
+ /**
224
+ * Detect if a project is a monorepo and list its packages.
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
230
+ */
231
+ declare function detectMonorepo(fs: FileSystem): Promise<MonorepoInfo>;
232
+ /**
233
+ * Find a package by name or path in a list of workspace packages.
234
+ */
235
+ declare function findPackageByName(packages: WorkspacePackage[], nameOrPath: string): WorkspacePackage | undefined;
236
+ /**
237
+ * Format package list for display in error messages.
238
+ */
239
+ declare function formatPackageList(packages: WorkspacePackage[], limit?: number): string;
240
+ /**
241
+ * Detect package manager based on lockfile presence and package.json hints.
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
248
+ */
249
+ declare function detectPackageManager(fs: FileSystem): Promise<PackageManagerInfo>;
250
+ /**
251
+ * Get install command for a package manager.
252
+ * Returns [command, ...args] array.
253
+ */
254
+ declare function getInstallCommand(pm: PackageManagerInfo): string[];
255
+ /**
256
+ * Get run command for a package manager script.
257
+ * Returns [command, ...args, scriptName] array.
258
+ */
259
+ declare function getRunCommand(pm: PackageManagerInfo, script: string): string[];
260
+ /**
261
+ * Safely parse a JSON file, returning null on any error.
262
+ */
263
+ declare function safeParseJson<T = Record<string, unknown>>(fs: FileSystem, path: string): Promise<T | null>;
264
+ /**
265
+ * Standard package.json structure for detection purposes.
266
+ */
267
+ interface PackageJson {
268
+ name?: string;
269
+ version?: string;
270
+ private?: boolean;
271
+ main?: string;
272
+ module?: string;
273
+ types?: string;
274
+ typings?: string;
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
+ }
283
+ /**
284
+ * Package.json exports field structure.
285
+ */
286
+ type PackageExports = string | {
287
+ "."?: string | {
288
+ types?: string;
289
+ import?: string;
290
+ require?: string;
291
+ default?: string;
292
+ };
293
+ [key: string]: unknown;
294
+ };
295
+ /**
296
+ * Read and parse package.json from a directory.
297
+ */
298
+ declare function readPackageJson(fs: FileSystem, dir: string): Promise<PackageJson | null>;
299
+ /**
300
+ * Analyze a project's structure for scanning.
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
+ * ```
327
+ */
328
+ declare function analyzeProject2(fs: FileSystem, options?: AnalyzeProjectOptions): Promise<ProjectInfo>;
329
+ interface DocCovOptions {
330
+ includePrivate?: boolean;
331
+ followImports?: boolean;
332
+ maxDepth?: number;
333
+ resolveExternalTypes?: boolean;
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[];
341
+ }
342
+ /**
343
+ * Configuration types for DocCov.
344
+ * These types are shared between CLI and API.
345
+ */
346
+ /**
347
+ * Documentation configuration options.
348
+ */
349
+ interface DocsConfig {
350
+ /** Glob patterns for markdown docs to include */
351
+ include?: string[];
352
+ /** Glob patterns for markdown docs to exclude */
353
+ exclude?: string[];
354
+ }
355
+ /**
356
+ * Check command configuration options.
357
+ */
358
+ interface CheckConfig {
359
+ /** Enable lint checks (default: true) */
360
+ lint?: boolean;
361
+ /** Enable typecheck for examples (default: true) */
362
+ typecheck?: boolean;
363
+ /** Enable runtime execution of examples (default: false) */
364
+ exec?: boolean;
365
+ }
366
+ /**
367
+ * Lint severity level.
368
+ */
369
+ type LintSeverity = "error" | "warn" | "off";
370
+ /**
371
+ * Lint rules configuration.
372
+ */
373
+ interface LintRulesConfig {
374
+ /** Rule severity overrides */
375
+ rules?: Record<string, LintSeverity>;
376
+ }
377
+ /**
378
+ * Normalized DocCov configuration.
379
+ * This is the parsed/normalized form used by commands.
380
+ */
381
+ interface DocCovConfig {
382
+ /** Export include patterns */
383
+ include?: string[];
384
+ /** Export exclude patterns */
385
+ exclude?: string[];
386
+ /** Plugins (future) */
387
+ plugins?: unknown[];
388
+ /** Documentation configuration */
389
+ docs?: DocsConfig;
390
+ /** Check command configuration */
391
+ check?: CheckConfig;
392
+ /** Lint configuration */
393
+ lint?: LintRulesConfig;
394
+ }
395
+ /**
396
+ * Define a DocCov configuration.
397
+ * Helper function for type-safe configuration in doccov.config.ts.
398
+ *
399
+ * @param config - Configuration object
400
+ * @returns The configuration object (for type inference)
401
+ *
402
+ * @example
403
+ * ```typescript
404
+ * // doccov.config.ts
405
+ * import { defineConfig } from '@doccov/sdk';
406
+ *
407
+ * defineConfig({
408
+ * include: ['MyClass', 'myFunction'],
409
+ * exclude: ['internal*'],
410
+ * docs: {
411
+ * include: ['docs/**\/*.md'],
412
+ * },
413
+ * lint: {
414
+ * rules: {
415
+ * 'require-description': 'error',
416
+ * 'require-example': 'warn',
417
+ * },
418
+ * },
419
+ * });
420
+ * ```
421
+ */
422
+ declare function defineConfig(config: DocCovConfig): DocCovConfig;
423
+ /**
424
+ * Source of filter options.
425
+ */
426
+ type FilterSource = "config" | "override" | "combined";
427
+ /**
428
+ * Resolved filter options after merging config and overrides.
429
+ */
430
+ interface ResolvedFilters {
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
+ }
442
+ /**
443
+ * Parse a comma-separated list flag into an array.
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
+ * ```
454
+ */
455
+ declare function parseListFlag(value?: string | string[]): string[] | undefined;
456
+ /**
457
+ * Merge filter options from config and CLI/API overrides.
458
+ *
459
+ * Merge behavior:
460
+ * - Include: CLI values intersect with config values (narrowing)
461
+ * - Exclude: CLI values are added to config values (expanding)
462
+ *
463
+ * @param config - Configuration (from doccov.config.ts)
464
+ * @param overrides - Override filters (from CLI flags or API params)
465
+ * @returns Merged filter options
466
+ *
467
+ * @example
468
+ * ```typescript
469
+ * const config = { include: ['A', 'B', 'C'] };
470
+ * const overrides = { include: ['B', 'C', 'D'] };
471
+ *
472
+ * const resolved = mergeFilters(config, overrides);
473
+ * // resolved.include = ['B', 'C'] (intersection)
474
+ * ```
475
+ */
476
+ declare function mergeFilters(config: DocCovConfig | null, overrides: FilterOptions): ResolvedFilters;
477
+ import { SpecDocDrift as SpecDocDrift2, SpecExport as SpecExport2 } from "@openpkg-ts/spec";
478
+ import * as TS from "typescript";
479
+ /**
480
+ * Represents a single parameter in a JSDoc patch
481
+ */
482
+ interface JSDocParam {
483
+ name: string;
484
+ type?: string;
485
+ description?: string;
486
+ optional?: boolean;
487
+ }
488
+ /**
489
+ * Represents a return type in a JSDoc patch
490
+ */
491
+ interface JSDocReturn {
492
+ type?: string;
493
+ description?: string;
494
+ }
495
+ /**
496
+ * Represents a generic tag in a JSDoc patch
497
+ */
498
+ interface JSDocTag {
499
+ name: string;
500
+ text: string;
501
+ }
502
+ /**
503
+ * A patchable representation of a JSDoc comment
504
+ */
505
+ interface JSDocPatch {
506
+ description?: string;
507
+ params?: JSDocParam[];
508
+ returns?: JSDocReturn;
509
+ examples?: string[];
510
+ deprecated?: string | false;
511
+ async?: boolean;
512
+ type?: string;
513
+ typeParams?: Array<{
514
+ name: string;
515
+ constraint?: string;
516
+ description?: string;
517
+ }>;
518
+ otherTags?: JSDocTag[];
519
+ }
520
+ /**
521
+ * Represents an edit to be applied to a source file
522
+ */
523
+ interface JSDocEdit {
524
+ filePath: string;
525
+ symbolName: string;
526
+ startLine: number;
527
+ endLine: number;
528
+ hasExisting: boolean;
529
+ existingJSDoc?: string;
530
+ newJSDoc: string;
531
+ indent: string;
532
+ }
533
+ /**
534
+ * Result of applying edits to source files
535
+ */
536
+ interface ApplyEditsResult {
537
+ filesModified: number;
538
+ editsApplied: number;
539
+ errors: Array<{
540
+ file: string;
541
+ error: string;
542
+ }>;
543
+ }
544
+ /**
545
+ * Parse a JSDoc comment string into a patchable structure
546
+ */
547
+ declare function parseJSDocToPatch(jsDocText: string): JSDocPatch;
548
+ /**
549
+ * Apply a partial patch to an existing JSDoc patch, preserving unmodified content
550
+ */
551
+ declare function applyPatchToJSDoc(existing: JSDocPatch, updates: Partial<JSDocPatch>): JSDocPatch;
552
+ /**
553
+ * Serialize a JSDocPatch back to a formatted comment string
554
+ */
555
+ declare function serializeJSDoc(patch: JSDocPatch, indent?: string): string;
556
+ /**
557
+ * Find the JSDoc location for a declaration in a source file
558
+ */
559
+ declare function findJSDocLocation(sourceFile: TS.SourceFile, symbolName: string, approximateLine?: number): {
560
+ startLine: number;
561
+ endLine: number;
562
+ declarationLine: number;
563
+ hasExisting: boolean;
564
+ existingJSDoc?: string;
565
+ indent: string;
566
+ } | null;
567
+ /**
568
+ * Apply a batch of edits to source files
569
+ */
570
+ declare function applyEdits(edits: JSDocEdit[]): Promise<ApplyEditsResult>;
571
+ /**
572
+ * Create a TypeScript source file from a file path
573
+ */
574
+ declare function createSourceFile(filePath: string): TS.SourceFile;
575
+ /**
576
+ * Types of fixes that can be generated
577
+ */
578
+ 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";
579
+ /**
580
+ * A fix suggestion with the patch to apply
581
+ */
582
+ interface FixSuggestion {
583
+ type: FixType;
584
+ driftType: SpecDocDrift2["type"];
585
+ target: string;
586
+ description: string;
587
+ patch: Partial<JSDocPatch>;
588
+ }
589
+ /**
590
+ * Check if a drift type can be fixed deterministically
591
+ */
592
+ declare function isFixableDrift(drift: SpecDocDrift2): boolean;
593
+ /**
594
+ * Generate a fix for a single drift issue
595
+ */
596
+ declare function generateFix(drift: SpecDocDrift2, exportEntry: SpecExport2, existingPatch?: JSDocPatch): FixSuggestion | null;
597
+ /**
598
+ * Generate all fixes for an export's drift issues
599
+ */
600
+ declare function generateFixesForExport(exportEntry: SpecExport2, existingPatch?: JSDocPatch): FixSuggestion[];
601
+ /**
602
+ * Merge multiple fix patches into a single patch
603
+ */
604
+ declare function mergeFixes(fixes: FixSuggestion[], basePatch?: JSDocPatch): JSDocPatch;
605
+ /**
606
+ * Get a summary of fixable vs non-fixable drifts
607
+ */
608
+ declare function categorizeDrifts(drifts: SpecDocDrift2[]): {
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;
656
+ import { SpecDiff } from "@openpkg-ts/spec";
657
+ type MemberChangeType = "added" | "removed" | "signature-changed";
658
+ interface MemberChange {
659
+ /** The class this member belongs to */
660
+ className: string;
661
+ /** The member name (e.g., "evaluateChainhook") */
662
+ memberName: string;
663
+ /** Kind of member */
664
+ memberKind: "method" | "property" | "accessor" | "constructor";
665
+ /** Type of change */
666
+ changeType: MemberChangeType;
667
+ /** Old signature string (for signature changes) */
668
+ oldSignature?: string;
669
+ /** New signature string (for signature changes) */
670
+ newSignature?: string;
671
+ /** Suggested replacement (e.g., "Use replayChainhook instead") */
672
+ suggestion?: string;
673
+ }
674
+ /**
73
675
  * Markdown/MDX documentation analysis types
74
676
  */
75
677
  /**
@@ -120,7 +722,7 @@ type DocsChangeType = "signature-changed" | "removed" | "deprecated" | "method-r
120
722
  /**
121
723
  * Member-level change type
122
724
  */
123
- type MemberChangeType = "added" | "removed" | "signature-changed";
725
+ type MemberChangeType2 = "added" | "removed" | "signature-changed";
124
726
  /**
125
727
  * An impacted reference in a documentation file
126
728
  */
@@ -138,7 +740,7 @@ interface DocsImpactReference {
138
740
  /** Member/method name if this is a member-level change */
139
741
  memberName?: string;
140
742
  /** Type of member change (added, removed, signature-changed) */
141
- memberChangeType?: MemberChangeType;
743
+ memberChangeType?: MemberChangeType2;
142
744
  /** Suggested replacement for removed/changed members */
143
745
  replacementSuggestion?: string;
144
746
  /** True if this is just a class instantiation (new ClassName()) */
@@ -180,60 +782,6 @@ interface DocsImpactResult {
180
782
  };
181
783
  }
182
784
  /**
183
- * Check if a language tag represents executable code
184
- */
185
- declare function isExecutableLang(lang: string | null | undefined): boolean;
186
- /**
187
- * Parse a markdown file and extract code blocks
188
- */
189
- declare function parseMarkdownFile(content: string, filePath: string): MarkdownDocFile;
190
- /**
191
- * Parse multiple markdown files
192
- */
193
- declare function parseMarkdownFiles(files: Array<{
194
- path: string;
195
- content: string;
196
- }>): MarkdownDocFile[];
197
- /**
198
- * Extract import statements from code
199
- * Finds named imports: import { X, Y } from 'pkg'
200
- */
201
- declare function extractImports(code: string): Array<{
202
- name: string;
203
- from: string;
204
- }>;
205
- /**
206
- * Extract function calls from code
207
- * Finds: functionName( or functionName<
208
- */
209
- declare function extractFunctionCalls(code: string): string[];
210
- /**
211
- * Find all references to given names in markdown files
212
- */
213
- declare function findExportReferences(files: MarkdownDocFile[], exportNames: string[]): ExportReference[];
214
- /**
215
- * Check if a code block references any of the given names
216
- */
217
- declare function blockReferencesExport(block: MarkdownCodeBlock, exportName: string): boolean;
218
- import { SpecDiff } from "@openpkg-ts/spec";
219
- type MemberChangeType2 = "added" | "removed" | "signature-changed";
220
- interface MemberChange {
221
- /** The class this member belongs to */
222
- className: string;
223
- /** The member name (e.g., "evaluateChainhook") */
224
- memberName: string;
225
- /** Kind of member */
226
- memberKind: "method" | "property" | "accessor" | "constructor";
227
- /** Type of change */
228
- changeType: MemberChangeType2;
229
- /** Old signature string (for signature changes) */
230
- oldSignature?: string;
231
- /** New signature string (for signature changes) */
232
- newSignature?: string;
233
- /** Suggested replacement (e.g., "Use replayChainhook instead") */
234
- suggestion?: string;
235
- }
236
- /**
237
785
  * Analyze docs impact from a spec diff
238
786
  *
239
787
  * @param diff - The spec diff result
@@ -248,224 +796,121 @@ declare function analyzeDocsImpact(diff: SpecDiff, markdownFiles: MarkdownDocFil
248
796
  declare function findDeprecatedReferences(markdownFiles: MarkdownDocFile[], deprecatedExports: string[]): ExportReference[];
249
797
  /**
250
798
  * Find references to removed exports
251
- */
252
- declare function findRemovedReferences(markdownFiles: MarkdownDocFile[], removedExports: string[]): ExportReference[];
253
- /**
254
- * Check if any docs reference a specific */
255
- declare function hasDocsForExport(markdownFiles: MarkdownDocFile[], exportName: string): boolean;
256
- /**
257
- * Get all exports that have documentation
258
- */
259
- declare function getDocumentedExports(markdownFiles: MarkdownDocFile[], exportNames: string[]): string[];
260
- /**
261
- * Get all exports that lack documentation
262
- */
263
- declare function getUndocumentedExports(markdownFiles: MarkdownDocFile[], exportNames: string[]): string[];
264
- import { CategorizedBreaking, OpenPkg as OpenPkg3, SpecDiff as SpecDiff2 } from "@openpkg-ts/spec";
265
- /**
266
- * Extended spec diff result with docs impact
267
- */
268
- interface SpecDiffWithDocs extends SpecDiff2 {
269
- /** Docs impact analysis (only present if markdown files provided) */
270
- docsImpact?: DocsImpactResult;
271
- /** Member-level changes for classes (methods added/removed/changed) */
272
- memberChanges?: MemberChange[];
273
- /** Breaking changes categorized by severity (high/medium/low) */
274
- categorizedBreaking?: CategorizedBreaking[];
275
- }
276
- /**
277
- * Options for diffSpecWithDocs
278
- */
279
- interface DiffWithDocsOptions {
280
- /** Parsed markdown documentation files */
281
- markdownFiles?: MarkdownDocFile[];
282
- }
283
- /**
284
- * Compute spec diff with optional docs impact analysis
285
- *
286
- * @param oldSpec - Previous version of the spec
287
- * @param newSpec - Current version of the spec
288
- * @param options - Options including markdown files to analyze
289
- * @returns Extended diff result with docs impact
290
- *
291
- * @example
292
- * ```ts
293
- * import { diffSpecWithDocs, parseMarkdownFiles } from '@doccov/sdk';
294
- *
295
- * const markdownFiles = parseMarkdownFiles([
296
- * { path: 'docs/guide.md', content: '...' },
297
- * ]);
298
- *
299
- * const diff = diffSpecWithDocs(oldSpec, newSpec, { markdownFiles });
300
- *
301
- * if (diff.docsImpact?.impactedFiles.length) {
302
- * console.log('Docs need updating!');
303
- * }
304
- * ```
305
- */
306
- declare function diffSpecWithDocs(oldSpec: OpenPkg3, newSpec: OpenPkg3, options?: DiffWithDocsOptions): SpecDiffWithDocs;
307
- /**
308
- * Check if a diff has any docs impact
309
- */
310
- declare function hasDocsImpact(diff: SpecDiffWithDocs): boolean;
311
- /**
312
- * Get summary of docs impact for display
313
- */
314
- declare function getDocsImpactSummary(diff: SpecDiffWithDocs): {
315
- impactedFileCount: number;
316
- impactedReferenceCount: number;
317
- missingDocsCount: number;
318
- totalIssues: number;
319
- memberChangesCount: number;
320
- };
321
- interface DocCovOptions {
322
- includePrivate?: boolean;
323
- followImports?: boolean;
324
- maxDepth?: number;
325
- resolveExternalTypes?: boolean;
326
- }
327
- /** @deprecated Use DocCovOptions instead */
328
- type OpenPkgOptions = DocCovOptions;
329
- declare function extractPackageSpec(entryFile: string, packageDir?: string, content?: string, options?: OpenPkgOptions): Promise<OpenPkgSpec>;
330
- interface FilterOptions {
331
- include?: string[];
332
- exclude?: string[];
333
- }
334
- import { SpecDocDrift as SpecDocDrift2, SpecExport as SpecExport2 } from "@openpkg-ts/spec";
335
- import * as TS from "typescript";
336
- /**
337
- * Represents a single parameter in a JSDoc patch
338
- */
339
- interface JSDocParam {
340
- name: string;
341
- type?: string;
342
- description?: string;
343
- optional?: boolean;
344
- }
345
- /**
346
- * Represents a return type in a JSDoc patch
347
- */
348
- interface JSDocReturn {
349
- type?: string;
350
- description?: string;
351
- }
352
- /**
353
- * Represents a generic tag in a JSDoc patch
354
- */
355
- interface JSDocTag {
356
- name: string;
357
- text: string;
358
- }
359
- /**
360
- * A patchable representation of a JSDoc comment
361
- */
362
- interface JSDocPatch {
363
- description?: string;
364
- params?: JSDocParam[];
365
- returns?: JSDocReturn;
366
- examples?: string[];
367
- deprecated?: string | false;
368
- async?: boolean;
369
- type?: string;
370
- typeParams?: Array<{
371
- name: string;
372
- constraint?: string;
373
- description?: string;
374
- }>;
375
- otherTags?: JSDocTag[];
376
- }
377
- /**
378
- * Represents an edit to be applied to a source file
379
- */
380
- interface JSDocEdit {
381
- filePath: string;
382
- symbolName: string;
383
- startLine: number;
384
- endLine: number;
385
- hasExisting: boolean;
386
- existingJSDoc?: string;
387
- newJSDoc: string;
388
- indent: string;
389
- }
799
+ */
800
+ declare function findRemovedReferences(markdownFiles: MarkdownDocFile[], removedExports: string[]): ExportReference[];
390
801
  /**
391
- * Result of applying edits to source files
802
+ * Check if any docs reference a specific */
803
+ declare function hasDocsForExport(markdownFiles: MarkdownDocFile[], exportName: string): boolean;
804
+ /**
805
+ * Get all exports that have documentation
392
806
  */
393
- interface ApplyEditsResult {
394
- filesModified: number;
395
- editsApplied: number;
396
- errors: Array<{
397
- file: string;
398
- error: string;
399
- }>;
400
- }
807
+ declare function getDocumentedExports(markdownFiles: MarkdownDocFile[], exportNames: string[]): string[];
401
808
  /**
402
- * Parse a JSDoc comment string into a patchable structure
809
+ * Get all exports that lack documentation
403
810
  */
404
- declare function parseJSDocToPatch(jsDocText: string): JSDocPatch;
811
+ declare function getUndocumentedExports(markdownFiles: MarkdownDocFile[], exportNames: string[]): string[];
812
+ import { CategorizedBreaking, OpenPkg as OpenPkg3, SpecDiff as SpecDiff2 } from "@openpkg-ts/spec";
405
813
  /**
406
- * Apply a partial patch to an existing JSDoc patch, preserving unmodified content
814
+ * Extended spec diff result with docs impact
407
815
  */
408
- declare function applyPatchToJSDoc(existing: JSDocPatch, updates: Partial<JSDocPatch>): JSDocPatch;
816
+ interface SpecDiffWithDocs extends SpecDiff2 {
817
+ /** Docs impact analysis (only present if markdown files provided) */
818
+ docsImpact?: DocsImpactResult;
819
+ /** Member-level changes for classes (methods added/removed/changed) */
820
+ memberChanges?: MemberChange[];
821
+ /** Breaking changes categorized by severity (high/medium/low) */
822
+ categorizedBreaking?: CategorizedBreaking[];
823
+ }
409
824
  /**
410
- * Serialize a JSDocPatch back to a formatted comment string
825
+ * Options for diffSpecWithDocs
411
826
  */
412
- declare function serializeJSDoc(patch: JSDocPatch, indent?: string): string;
827
+ interface DiffWithDocsOptions {
828
+ /** Parsed markdown documentation files */
829
+ markdownFiles?: MarkdownDocFile[];
830
+ }
413
831
  /**
414
- * Find the JSDoc location for a declaration in a source file
832
+ * Compute spec diff with optional docs impact analysis
833
+ *
834
+ * @param oldSpec - Previous version of the spec
835
+ * @param newSpec - Current version of the spec
836
+ * @param options - Options including markdown files to analyze
837
+ * @returns Extended diff result with docs impact
838
+ *
839
+ * @example
840
+ * ```ts
841
+ * import { diffSpecWithDocs, parseMarkdownFiles } from '@doccov/sdk';
842
+ * import type { OpenPkg } from '@openpkg-ts/spec';
843
+ *
844
+ * const oldSpec: OpenPkg = { openpkg: '0.2.0', meta: { name: 'my-pkg' }, exports: [] };
845
+ * const newSpec: OpenPkg = { openpkg: '0.2.1', meta: { name: 'my-pkg' }, exports: [] };
846
+ *
847
+ * const markdownFiles = parseMarkdownFiles([
848
+ * { path: 'docs/guide.md', content: '...' },
849
+ * ]);
850
+ *
851
+ * const diff = diffSpecWithDocs(oldSpec, newSpec, { markdownFiles });
852
+ *
853
+ * if (diff.docsImpact?.impactedFiles.length) {
854
+ * console.log('Docs need updating!');
855
+ * }
856
+ * ```
415
857
  */
416
- declare function findJSDocLocation(sourceFile: TS.SourceFile, symbolName: string, approximateLine?: number): {
417
- startLine: number;
418
- endLine: number;
419
- declarationLine: number;
420
- hasExisting: boolean;
421
- existingJSDoc?: string;
422
- indent: string;
423
- } | null;
858
+ declare function diffSpecWithDocs(oldSpec: OpenPkg3, newSpec: OpenPkg3, options?: DiffWithDocsOptions): SpecDiffWithDocs;
424
859
  /**
425
- * Apply a batch of edits to source files
860
+ * Check if a diff has any docs impact
426
861
  */
427
- declare function applyEdits(edits: JSDocEdit[]): Promise<ApplyEditsResult>;
862
+ declare function hasDocsImpact(diff: SpecDiffWithDocs): boolean;
428
863
  /**
429
- * Create a TypeScript source file from a file path
864
+ * Get summary of docs impact for display
430
865
  */
431
- declare function createSourceFile(filePath: string): TS.SourceFile;
866
+ declare function getDocsImpactSummary(diff: SpecDiffWithDocs): {
867
+ impactedFileCount: number;
868
+ impactedReferenceCount: number;
869
+ missingDocsCount: number;
870
+ totalIssues: number;
871
+ memberChangesCount: number;
872
+ };
432
873
  /**
433
- * Types of fixes that can be generated
874
+ * Extract import statements from code (legacy interface).
875
+ * @deprecated Use extractImportsAST for more detailed info.
434
876
  */
435
- 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";
877
+ declare function extractImports(code: string): Array<{
878
+ name: string;
879
+ from: string;
880
+ }>;
436
881
  /**
437
- * A fix suggestion with the patch to apply
882
+ * Extract function calls from code (legacy interface).
883
+ * @deprecated Use extractCallsAST for more detailed info.
438
884
  */
439
- interface FixSuggestion {
440
- type: FixType;
441
- driftType: SpecDocDrift2["type"];
442
- target: string;
443
- description: string;
444
- patch: Partial<JSDocPatch>;
885
+ declare function extractFunctionCalls(code: string): string[];
886
+ /** Options for parsing markdown files */
887
+ interface ParseOptions {
888
+ /** Custom set of executable language tags */
889
+ executableLangs?: string[];
445
890
  }
446
891
  /**
447
- * Check if a drift type can be fixed deterministically
892
+ * Check if a language tag represents executable code
448
893
  */
449
- declare function isFixableDrift(drift: SpecDocDrift2): boolean;
894
+ declare function isExecutableLang(lang: string | null | undefined, customLangs?: Set<string>): boolean;
450
895
  /**
451
- * Generate a fix for a single drift issue
896
+ * Parse a markdown file and extract code blocks
452
897
  */
453
- declare function generateFix(drift: SpecDocDrift2, exportEntry: SpecExport2, existingPatch?: JSDocPatch): FixSuggestion | null;
898
+ declare function parseMarkdownFile(content: string, filePath: string, options?: ParseOptions): MarkdownDocFile;
454
899
  /**
455
- * Generate all fixes for an export's drift issues
900
+ * Parse multiple markdown files
456
901
  */
457
- declare function generateFixesForExport(exportEntry: SpecExport2, existingPatch?: JSDocPatch): FixSuggestion[];
902
+ declare function parseMarkdownFiles(files: Array<{
903
+ path: string;
904
+ content: string;
905
+ }>, options?: ParseOptions): MarkdownDocFile[];
458
906
  /**
459
- * Merge multiple fix patches into a single patch
907
+ * Find all references to given names in markdown files
460
908
  */
461
- declare function mergeFixes(fixes: FixSuggestion[], basePatch?: JSDocPatch): JSDocPatch;
909
+ declare function findExportReferences(files: MarkdownDocFile[], exportNames: string[]): ExportReference[];
462
910
  /**
463
- * Get a summary of fixable vs non-fixable drifts
911
+ * Check if a code block references any of the given names
464
912
  */
465
- declare function categorizeDrifts(drifts: SpecDocDrift2[]): {
466
- fixable: SpecDocDrift2[];
467
- nonFixable: SpecDocDrift2[];
468
- };
913
+ declare function blockReferencesExport(block: MarkdownCodeBlock, exportName: string): boolean;
469
914
  interface Diagnostic {
470
915
  message: string;
471
916
  severity: "error" | "warning" | "info";
@@ -508,338 +953,522 @@ declare function analyze(code: string, options?: AnalyzeOptions): Promise<OpenPk
508
953
  declare function analyzeFile(filePath: string, options?: AnalyzeOptions): Promise<OpenPkgSpec>;
509
954
  /** @deprecated Use DocCov instead */
510
955
  declare const OpenPkg4: typeof DocCov;
956
+ interface ExampleTypeError {
957
+ /** Index of the example in the examples array */
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
+ }
511
982
  /**
512
- * Project detection types for I/O-agnostic project analysis.
513
- * Used by both CLI (NodeFileSystem) and API (SandboxFileSystem).
983
+ * Type-check a single example
514
984
  */
985
+ declare function typecheckExample(example: string, packagePath: string, options?: TypecheckOptions): ExampleTypeError[];
515
986
  /**
516
- * Minimal filesystem interface for I/O-agnostic detection.
517
- * Implementations: NodeFileSystem (CLI), SandboxFileSystem (API)
987
+ * Type-check multiple examples
518
988
  */
519
- interface FileSystem {
520
- /** Check if a file or directory exists */
521
- exists(path: string): Promise<boolean>;
522
- /** Read file contents as string */
523
- readFile(path: string): Promise<string>;
524
- /** List directory contents (file/folder names only) */
525
- readDir(path: string): Promise<string[]>;
526
- /** Check if path is a directory */
527
- isDirectory(path: string): Promise<boolean>;
528
- }
529
- /** Supported package managers */
530
- type PackageManager = "npm" | "yarn" | "pnpm" | "bun";
531
- /** Package manager detection result with install/run commands */
532
- interface PackageManagerInfo {
533
- /** Package manager name */
534
- name: PackageManager;
535
- /** Lockfile that was detected (null if none found) */
536
- lockfile: string | null;
537
- /** Arguments for install command, e.g. ['install', '--frozen-lockfile'] */
538
- installArgs: string[];
539
- /** Prefix for running scripts, e.g. ['npm', 'run'] or ['pnpm'] */
540
- runPrefix: string[];
541
- }
542
- /** Monorepo type based on configuration */
543
- type MonorepoType = "npm-workspaces" | "pnpm-workspaces" | "lerna" | "none";
544
- /** Monorepo detection result */
545
- interface MonorepoInfo {
546
- /** Whether this is a monorepo */
547
- isMonorepo: boolean;
548
- /** Type of monorepo configuration */
549
- type: MonorepoType;
550
- /** Workspace patterns from config (e.g. ['packages/*']) */
551
- patterns: string[];
552
- /** Resolved workspace packages */
553
- packages: WorkspacePackage[];
554
- }
555
- /** A package within a monorepo workspace */
556
- interface WorkspacePackage {
557
- /** Package name from package.json */
558
- name: string;
559
- /** Relative path to package directory */
560
- path: string;
561
- /** Whether the package is marked as private */
562
- private: boolean;
563
- }
564
- /** Entry point source - where the entry was detected from */
565
- type EntryPointSource = "types" | "exports" | "main" | "module" | "fallback";
566
- /** Entry point detection result */
567
- interface EntryPointInfo {
568
- /** Path to entry file (relative to package root) */
569
- path: string;
570
- /** Where the entry point was detected from */
571
- source: EntryPointSource;
572
- /** Whether this is a .d.ts file (no source available) */
573
- isDeclarationOnly: boolean;
574
- }
575
- /** Build configuration detection result */
576
- interface BuildInfo {
577
- /** Build-related script names found (e.g. ['build', 'build:types']) */
578
- scripts: string[];
579
- /** Whether any build script was found */
580
- hasBuildScript: boolean;
581
- /** Whether TypeScript is configured/installed */
582
- hasTypeScript: boolean;
583
- /** Indicators for exotic project types */
584
- exoticIndicators: {
585
- /** WASM project (Cargo.toml or wasm-pack scripts) */
586
- wasm: boolean;
587
- /** napi-rs native addon project */
588
- napi: boolean;
589
- };
590
- }
591
- /** Complete project analysis result */
592
- interface ProjectInfo {
593
- /** Package manager info */
594
- packageManager: PackageManagerInfo;
595
- /** Monorepo info */
596
- monorepo: MonorepoInfo;
597
- /** Entry point info */
598
- entryPoint: EntryPointInfo;
599
- /** Build info */
600
- build: BuildInfo;
601
- }
602
- /** Options for analyzeProject() */
603
- interface AnalyzeProjectOptions {
604
- /** Target package name for monorepos */
605
- targetPackage?: string;
606
- }
607
- import { Sandbox } from "@vercel/sandbox";
989
+ declare function typecheckExamples(examples: string[], packagePath: string, options?: TypecheckOptions): TypecheckResult;
608
990
  /**
609
- * Node.js filesystem implementation for CLI usage.
610
- * Wraps Node.js fs module with a base path.
991
+ * Scan types for CLI, API, and SDK consumers.
992
+ * Single source of truth for scan-related interfaces.
611
993
  */
612
- declare class NodeFileSystem implements FileSystem {
613
- private basePath;
614
- constructor(basePath: string);
615
- private resolve;
616
- exists(relativePath: string): Promise<boolean>;
617
- readFile(relativePath: string): Promise<string>;
618
- readDir(relativePath: string): Promise<string[]>;
619
- isDirectory(relativePath: string): Promise<boolean>;
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[];
620
1019
  }
621
1020
  /**
622
- * Vercel Sandbox filesystem implementation for API usage.
623
- * Uses sandbox.runCommand() with shell commands.
1021
+ * A documentation drift issue.
624
1022
  */
625
- declare class SandboxFileSystem implements FileSystem {
626
- private sandbox;
627
- constructor(sandbox: Sandbox);
628
- exists(path: string): Promise<boolean>;
629
- readFile(path: string): Promise<string>;
630
- readDir(path: string): Promise<string[]>;
631
- isDirectory(path: string): Promise<boolean>;
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;
632
1032
  }
633
1033
  /**
634
- * Detect package manager based on lockfile presence.
635
- *
636
- * Priority order:
637
- * 1. pnpm-lock.yaml
638
- * 2. bun.lock / bun.lockb
639
- * 3. yarn.lock
640
- * 4. package-lock.json
641
- * 5. Default to npm
1034
+ * Options for running a scan.
642
1035
  */
643
- declare function detectPackageManager(fs: FileSystem): Promise<PackageManagerInfo>;
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
+ }
644
1048
  /**
645
- * Get install command for a package manager.
646
- * Returns [command, ...args] array.
1049
+ * Stages of the scan pipeline.
647
1050
  */
648
- declare function getInstallCommand(pm: PackageManagerInfo): string[];
1051
+ type ProgressStage = "cloning" | "detecting" | "installing" | "building" | "analyzing" | "complete";
649
1052
  /**
650
- * Get run command for a package manager script.
651
- * Returns [command, ...args, scriptName] array.
1053
+ * Progress event emitted during scan operations.
652
1054
  */
653
- declare function getRunCommand(pm: PackageManagerInfo, script: string): string[];
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
+ }
654
1063
  /**
655
- * Detect if a project is a monorepo and list its packages.
656
- *
657
- * Detection triggers (in order):
658
- * 1. package.json has workspaces field (npm/yarn)
659
- * 2. pnpm-workspace.yaml exists
660
- * 3. lerna.json exists
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
+ * ```
661
1105
  */
662
- declare function detectMonorepo(fs: FileSystem): Promise<MonorepoInfo>;
1106
+ declare function extractSpecSummary(spec: OpenPkg5): SpecSummary;
1107
+ import { OpenPkg as OpenPkg7 } from "@openpkg-ts/spec";
663
1108
  /**
664
- * Find a package by name or path in a list of workspace packages.
1109
+ * Result of running a command.
665
1110
  */
666
- declare function findPackageByName(packages: WorkspacePackage[], nameOrPath: string): WorkspacePackage | undefined;
1111
+ interface CommandResult {
1112
+ /** Exit code (0 = success) */
1113
+ exitCode: number;
1114
+ /** Standard output */
1115
+ stdout: string;
1116
+ /** Standard error */
1117
+ stderr: string;
1118
+ }
667
1119
  /**
668
- * Format package list for display in error messages.
1120
+ * Function that runs a shell command.
1121
+ * Abstracts the difference between Node.js execSync and Sandbox runCommand.
669
1122
  */
670
- declare function formatPackageList(packages: WorkspacePackage[], limit?: number): string;
1123
+ type CommandRunner = (cmd: string, args: string[], options: {
1124
+ cwd: string;
1125
+ timeout?: number;
1126
+ }) => Promise<CommandResult>;
671
1127
  /**
672
- * Detect the TypeScript entry point for a package.
1128
+ * Result of dependency installation.
1129
+ */
1130
+ interface InstallResult {
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
+ }
1142
+ /**
1143
+ * Options for dependency installation.
1144
+ */
1145
+ interface InstallOptions {
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
+ }
1153
+ /**
1154
+ * Install dependencies for a project.
673
1155
  *
674
- * Priority order:
675
- * 1. package.json -> types or typings field
676
- * 2. package.json -> exports["."].types
677
- * 3. package.json -> main field (resolve to .ts)
678
- * 4. package.json -> module field (resolve to .ts)
679
- * 5. Common fallback paths
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
680
1160
  *
681
- * @param fs - FileSystem implementation
682
- * @param packagePath - Path to package directory (default: ".")
683
- * @returns Entry point info
684
- * @throws Error if no entry point can be found
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
+ * ```
685
1180
  */
686
- declare function detectEntryPoint(fs: FileSystem, packagePath?: string): Promise<EntryPointInfo>;
1181
+ declare function installDependencies(fs: FileSystem, cwd: string, runCommand: CommandRunner, options?: InstallOptions): Promise<InstallResult>;
687
1182
  /**
688
- * Detect build configuration and exotic project indicators.
1183
+ * Create a command runner for Node.js environments using execSync.
1184
+ * This is used by the CLI for local dependency installation.
689
1185
  *
690
- * @param fs - FileSystem implementation
691
- * @param packagePath - Path to package directory (default: ".")
692
- * @returns Build info including scripts and exotic indicators
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
+ * ```
693
1193
  */
694
- declare function detectBuildInfo(fs: FileSystem, packagePath?: string): Promise<BuildInfo>;
1194
+ declare function createNodeCommandRunner(): CommandRunner;
1195
+ import { OpenPkg as OpenPkg6 } from "@openpkg-ts/spec";
695
1196
  /**
696
- * Get the primary build script name to run.
697
- * Prefers 'build' over 'compile' over 'tsc'.
1197
+ * Parsed components of a GitHub URL.
698
1198
  */
699
- declare function getPrimaryBuildScript(buildInfo: BuildInfo): string | null;
1199
+ interface ParsedGitHubUrl {
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
+ }
700
1207
  /**
701
- * Safely parse a JSON file, returning null on any error.
1208
+ * Parse a GitHub URL or shorthand into components.
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
+ * ```
702
1233
  */
703
- declare function safeParseJson<T = Record<string, unknown>>(fs: FileSystem, path: string): Promise<T | null>;
1234
+ declare function parseGitHubUrl(input: string, defaultRef?: string): ParsedGitHubUrl;
704
1235
  /**
705
- * Standard package.json structure for detection purposes.
1236
+ * Build a clone URL from parsed components.
1237
+ *
1238
+ * @param parsed - Parsed GitHub URL components
1239
+ * @returns HTTPS clone URL
1240
+ *
1241
+ * @example
1242
+ * ```typescript
1243
+ * const cloneUrl = buildCloneUrl({ owner: 'vercel', repo: 'next.js', ref: 'main' });
1244
+ * // 'https://github.com/vercel/next.js.git'
1245
+ * ```
706
1246
  */
707
- interface PackageJson {
708
- name?: string;
709
- version?: string;
710
- private?: boolean;
711
- main?: string;
712
- module?: string;
713
- types?: string;
714
- typings?: string;
715
- exports?: PackageExports;
716
- workspaces?: string[] | {
717
- packages: string[];
718
- };
719
- scripts?: Record<string, string>;
720
- dependencies?: Record<string, string>;
721
- devDependencies?: Record<string, string>;
722
- }
1247
+ declare function buildCloneUrl(parsed: ParsedGitHubUrl): string;
723
1248
  /**
724
- * Package.json exports field structure.
1249
+ * Build a display-friendly URL (without protocol or .git suffix).
1250
+ *
1251
+ * @param parsed - Parsed GitHub URL components
1252
+ * @returns Display URL like 'github.com/owner/repo'
1253
+ *
1254
+ * @example
1255
+ * ```typescript
1256
+ * const displayUrl = buildDisplayUrl({ owner: 'vercel', repo: 'next.js', ref: 'main' });
1257
+ * // 'github.com/vercel/next.js'
1258
+ * ```
725
1259
  */
726
- type PackageExports = string | {
727
- "."?: string | {
728
- types?: string;
729
- import?: string;
730
- require?: string;
731
- default?: string;
732
- };
733
- [key: string]: unknown;
734
- };
1260
+ declare function buildDisplayUrl(parsed: ParsedGitHubUrl): string;
735
1261
  /**
736
- * Read and parse package.json from a directory.
1262
+ * Build a raw.githubusercontent.com URL for a file.
1263
+ *
1264
+ * @param parsed - Parsed GitHub URL components
1265
+ * @param filePath - Path to the file in the repo
1266
+ * @returns Raw content URL
737
1267
  */
738
- declare function readPackageJson(fs: FileSystem, dir: string): Promise<PackageJson | null>;
1268
+ declare function buildRawUrl(parsed: ParsedGitHubUrl, filePath: string): string;
739
1269
  /**
740
- * Analyze a project's structure for scanning.
741
- *
742
- * This is the main entry point for project detection. It combines all
743
- * detection functions into a single call that returns complete project info.
1270
+ * Fetch an OpenPkg spec from a GitHub repository.
744
1271
  *
745
- * For monorepos, you must specify the target package via options.targetPackage.
746
- * If not specified and a monorepo is detected, an error is thrown with the
747
- * list of available packages.
1272
+ * Tries the specified ref first, then falls back to 'master' if not found.
748
1273
  *
749
- * @param fs - FileSystem implementation (NodeFileSystem or SandboxFileSystem)
750
- * @param options - Options including targetPackage for monorepos
751
- * @returns Complete project info
752
- * @throws Error if monorepo detected without targetPackage specified
753
- * @throws Error if targetPackage not found in monorepo
1274
+ * @param parsed - Parsed GitHub URL components
1275
+ * @returns The OpenPkg spec, or null if not found
754
1276
  *
755
1277
  * @example
756
1278
  * ```typescript
757
- * // Single package
758
- * const fs = new NodeFileSystem('/path/to/package');
759
- * const project = await analyzeProject(fs);
1279
+ * import { parseGitHubUrl, fetchSpecFromGitHub } from '@doccov/sdk';
760
1280
  *
761
- * // Monorepo with target package
762
- * const fs = new NodeFileSystem('/path/to/monorepo');
763
- * const project = await analyzeProject(fs, { targetPackage: '@scope/core' });
1281
+ * const parsed = parseGitHubUrl('vercel/next.js');
1282
+ * const spec = await fetchSpecFromGitHub(parsed);
1283
+ * if (spec) {
1284
+ * console.log(`Coverage: ${spec.docs?.coverageScore}%`);
1285
+ * }
764
1286
  * ```
765
1287
  */
766
- declare function analyzeProject2(fs: FileSystem, options?: AnalyzeProjectOptions): Promise<ProjectInfo>;
767
- import { SpecExport as SpecExport4 } from "@openpkg-ts/spec";
768
- import { SpecExport as SpecExport3 } from "@openpkg-ts/spec";
769
- type LintSeverity = "error" | "warn" | "off";
770
- interface LintViolation {
771
- rule: string;
772
- severity: "error" | "warn";
773
- message: string;
774
- line?: number;
775
- fixable: boolean;
776
- }
777
- interface LintRule {
778
- name: string;
779
- defaultSeverity: LintSeverity;
780
- check(exp: SpecExport3, rawJSDoc?: string): LintViolation[];
781
- fix?(exp: SpecExport3, rawJSDoc?: string): JSDocPatch | null;
782
- }
783
- interface LintConfig {
784
- rules: Record<string, LintSeverity>;
785
- }
786
- interface LintResult {
787
- violations: LintViolation[];
788
- errorCount: number;
789
- warningCount: number;
790
- fixableCount: number;
1288
+ declare function fetchSpecFromGitHub(parsed: ParsedGitHubUrl): Promise<OpenPkg6 | null>;
1289
+ /**
1290
+ * Fetch an OpenPkg spec from a GitHub repository by owner/repo/branch.
1291
+ *
1292
+ * Convenience function that creates ParsedGitHubUrl internally.
1293
+ *
1294
+ * @param owner - Repository owner
1295
+ * @param repo - Repository name
1296
+ * @param branch - Branch name (default: 'main')
1297
+ * @returns The OpenPkg spec, or null if not found
1298
+ */
1299
+ declare function fetchSpec(owner: string, repo: string, branch?: string): Promise<OpenPkg6 | null>;
1300
+ /**
1301
+ * Options for creating a ScanOrchestrator.
1302
+ */
1303
+ interface ScanOrchestratorOptions {
1304
+ /** Progress callback for status updates */
1305
+ onProgress?: ProgressCallback;
1306
+ /** Command runner for executing shell commands */
1307
+ commandRunner?: CommandRunner;
1308
+ /** Skip external type resolution */
1309
+ skipResolve?: boolean;
791
1310
  }
792
- /** All available lint rules */
793
- declare const allRules: LintRule[];
794
- /** Default configuration with rule defaults */
795
- declare function getDefaultConfig(): LintConfig;
796
- /** Get a rule by name */
797
- declare function getRule(name: string): LintRule | undefined;
798
- /** Lint a single */
799
- declare function lintExport(exp: SpecExport4, rawJSDoc?: string, config?: LintConfig): LintViolation[];
800
- /** Lint multiple exports and aggregate results */
801
- declare function lintExports(exports: Array<{
802
- export: SpecExport4;
803
- rawJSDoc?: string;
804
- }>, config?: LintConfig): LintResult;
805
- /** Merge user config with defaults */
806
- declare function mergeConfig(userConfig: Partial<LintConfig>): LintConfig;
807
- declare const consistentParamStyle: LintRule;
808
- declare const noEmptyReturns: LintRule;
809
- declare const requireDescription: LintRule;
810
- declare const requireExample: LintRule;
811
- interface ExampleTypeError {
812
- /** Index of the example in the examples array */
813
- exampleIndex: number;
814
- /** Line number within the example (1-based) */
815
- line: number;
816
- /** Column number (1-based) */
817
- column: number;
818
- /** Error message from TypeScript */
819
- message: string;
820
- /** TypeScript diagnostic code */
821
- code: number;
1311
+ /**
1312
+ * Context for the current scan operation.
1313
+ */
1314
+ interface ScanContext {
1315
+ /** Parsed GitHub URL info */
1316
+ parsed: ParsedGitHubUrl;
1317
+ /** Target package name for monorepos */
1318
+ packageName?: string;
1319
+ /** Working directory for the scan */
1320
+ workDir: string;
1321
+ /** Entry point file path */
1322
+ entryFile?: string;
822
1323
  }
823
- interface TypecheckResult {
824
- /** All type errors found across examples */
825
- errors: ExampleTypeError[];
826
- /** Number of examples that passed */
827
- passed: number;
828
- /** Number of examples that failed */
829
- failed: number;
1324
+ /**
1325
+ * Orchestrates the scan workflow.
1326
+ *
1327
+ * The orchestrator coordinates:
1328
+ * 1. Repository cloning (for remote URLs)
1329
+ * 2. Monorepo detection and package resolution
1330
+ * 3. Entry point detection
1331
+ * 4. Dependency installation
1332
+ * 5. Build execution (if needed)
1333
+ * 6. Documentation analysis
1334
+ * 7. Summary extraction
1335
+ *
1336
+ * It's designed to be FileSystem-agnostic so it works with both:
1337
+ * - NodeFileSystem (CLI - local execution)
1338
+ * - SandboxFileSystem (API - isolated execution)
1339
+ *
1340
+ * @example
1341
+ * ```typescript
1342
+ * import { ScanOrchestrator, NodeFileSystem, createNodeCommandRunner } from '@doccov/sdk';
1343
+ *
1344
+ * const fs = new NodeFileSystem('/path/to/repo');
1345
+ * const orchestrator = new ScanOrchestrator(fs, {
1346
+ * commandRunner: createNodeCommandRunner(),
1347
+ * onProgress: (event) => console.log(event.message),
1348
+ * });
1349
+ *
1350
+ * const result = await orchestrator.scan({
1351
+ * url: 'https://github.com/owner/repo',
1352
+ * ref: 'main',
1353
+ * });
1354
+ *
1355
+ * console.log(`Coverage: ${result.coverage}%`);
1356
+ * ```
1357
+ */
1358
+ declare class ScanOrchestrator {
1359
+ private readonly fs;
1360
+ private readonly options;
1361
+ constructor(fs: FileSystem, options?: ScanOrchestratorOptions);
1362
+ /**
1363
+ * Emit a progress event.
1364
+ */
1365
+ private emit;
1366
+ /**
1367
+ * Detect monorepo and resolve target package.
1368
+ *
1369
+ * @param packageName - Target package name (required for monorepos)
1370
+ * @returns Target directory path (relative to workDir)
1371
+ * @throws Error if monorepo requires --package flag
1372
+ */
1373
+ detectPackage(packageName?: string): Promise<{
1374
+ targetPath: string;
1375
+ resolvedPackage?: string;
1376
+ }>;
1377
+ /**
1378
+ * Detect entry point for the package.
1379
+ *
1380
+ * @param targetPath - Path to the package directory
1381
+ * @returns Entry point file path (relative to workDir)
1382
+ */
1383
+ detectEntry(targetPath: string): Promise<string>;
1384
+ /**
1385
+ * Install dependencies for the project.
1386
+ *
1387
+ * @param workDir - Working directory (absolute path)
1388
+ * @returns Installation result
1389
+ */
1390
+ install(workDir: string): Promise<InstallResult>;
1391
+ /**
1392
+ * Run build if needed.
1393
+ *
1394
+ * @param workDir - Working directory (absolute path)
1395
+ * @param targetPath - Target package path (relative)
1396
+ */
1397
+ build(workDir: string, targetPath: string): Promise<void>;
1398
+ /**
1399
+ * Run documentation analysis.
1400
+ *
1401
+ * @param entryFile - Path to entry file (absolute)
1402
+ * @returns OpenPkg spec
1403
+ */
1404
+ analyze(entryFile: string): Promise<OpenPkg7>;
1405
+ /**
1406
+ * Run a complete scan workflow.
1407
+ *
1408
+ * @param options - Scan options
1409
+ * @returns Scan result with coverage statistics
1410
+ */
1411
+ scan(options: ScanOptions): Promise<ScanResult>;
830
1412
  }
831
- interface TypecheckOptions {
832
- /** Path to tsconfig.json (auto-detected if not provided) */
833
- tsconfig?: string;
834
- /** Package name for imports (auto-detected from package.json if not provided) */
835
- packageName?: string;
1413
+ /**
1414
+ * Error thrown when a monorepo is detected but no package is specified.
1415
+ */
1416
+ declare class MonorepoRequiresPackageError extends Error {
1417
+ /** Available package names */
1418
+ readonly availablePackages: string[];
1419
+ constructor(availablePackages: string[]);
836
1420
  }
837
1421
  /**
838
- * Type-check a single example
1422
+ * Options for resolving a target package/entry point.
839
1423
  */
840
- declare function typecheckExample(example: string, packagePath: string, options?: TypecheckOptions): ExampleTypeError[];
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
+ }
841
1432
  /**
842
- * Type-check multiple examples
1433
+ * Result of resolving a target package/entry point.
1434
+ */
1435
+ interface ResolvedTarget {
1436
+ /** Resolved directory containing the package */
1437
+ targetDir: string;
1438
+ /** Resolved entry point file path (absolute) */
1439
+ entryFile: string;
1440
+ /** Package info if this is a monorepo package */
1441
+ packageInfo?: WorkspacePackage;
1442
+ /** Entry point detection info */
1443
+ entryPointInfo: EntryPointInfo;
1444
+ }
1445
+ /**
1446
+ * Resolve a target package and entry point.
1447
+ *
1448
+ * This consolidates the repeated pattern from CLI commands:
1449
+ * 1. If --package specified, detect monorepo and find the package
1450
+ * 2. If no entry specified, auto-detect entry point
1451
+ * 3. If entry is a directory, detect entry point within it
1452
+ *
1453
+ * @param fs - FileSystem implementation (NodeFileSystem or SandboxFileSystem)
1454
+ * @param options - Resolution options
1455
+ * @returns Resolved target info
1456
+ * @throws Error if monorepo package not found, or entry point detection fails
1457
+ *
1458
+ * @example
1459
+ * ```typescript
1460
+ * import { NodeFileSystem, resolveTarget } from '@doccov/sdk';
1461
+ *
1462
+ * // Simple usage
1463
+ * const fs = new NodeFileSystem(process.cwd());
1464
+ * const { targetDir, entryFile } = await resolveTarget(fs, { cwd: process.cwd() });
1465
+ *
1466
+ * // With monorepo package
1467
+ * const { targetDir, entryFile, packageInfo } = await resolveTarget(fs, {
1468
+ * cwd: process.cwd(),
1469
+ * package: '@myorg/core',
1470
+ * });
1471
+ * ```
843
1472
  */
844
- declare function typecheckExamples(examples: string[], packagePath: string, options?: TypecheckOptions): TypecheckResult;
845
- export { typecheckExamples, typecheckExample, serializeJSDoc, safeParseJson, runExamplesWithPackage, runExamples, runExample, requireExample, requireDescription, readPackageJson, parseMarkdownFiles, parseMarkdownFile, parseJSDocToPatch, parseAssertions, noEmptyReturns, mergeFixes, mergeConfig, lintExports, lintExport, isFixableDrift, isExecutableLang, hasNonAssertionComments, hasDocsImpact, hasDocsForExport, getUndocumentedExports, getRunCommand, getRule, getPrimaryBuildScript, getInstallCommand, getDocumentedExports, getDocsImpactSummary, getDefaultConfig, generateFixesForExport, generateFix, formatPackageList, findRemovedReferences, findPackageByName, findJSDocLocation, findExportReferences, findDeprecatedReferences, extractPackageSpec, extractImports, extractFunctionCalls, diffSpecWithDocs, detectPackageManager, detectMonorepo, detectExampleRuntimeErrors, detectExampleAssertionFailures, detectEntryPoint, detectBuildInfo, createSourceFile, consistentParamStyle, categorizeDrifts, blockReferencesExport, applyPatchToJSDoc, applyEdits, analyzeProject2 as analyzeProject, analyzeFile, analyzeDocsImpact, analyze, allRules, WorkspacePackage, TypecheckResult, TypecheckOptions, SpecDiffWithDocs, SandboxFileSystem, RunExamplesWithPackageResult, RunExamplesWithPackageOptions, RunExampleOptions, ProjectInfo, PackageManagerInfo, PackageManager, PackageJson, PackageExports, OpenPkgSpec, OpenPkgOptions, OpenPkg4 as OpenPkg, NodeFileSystem, MonorepoType, MonorepoInfo, MemberChange, MarkdownDocFile, MarkdownCodeBlock, LintViolation, LintSeverity, LintRule, LintResult, LintConfig, JSDocTag, JSDocReturn, JSDocPatch, JSDocParam, JSDocEdit, FixType, FixSuggestion, FilterOptions, FileSystem, ExportReference, ExampleTypeError, ExampleRunResult, EntryPointSource, EntryPointInfo, DocsImpactResult, DocsImpactReference, DocsImpact, DocsChangeType, DocCovOptions, DocCov, DiffWithDocsOptions, Diagnostic, BuildInfo, ApplyEditsResult, AnalyzeProjectOptions, AnalyzeOptions, AnalysisResult };
1473
+ declare function resolveTarget(fs: FileSystem, options: ResolveTargetOptions): Promise<ResolvedTarget>;
1474
+ export { typecheckExamples, typecheckExample, serializeJSDoc, safeParseJson, runExamplesWithPackage, runExamples, runExample, resolveTarget, requireExample, requireDescription, readPackageJson, parseMarkdownFiles, parseMarkdownFile, parseListFlag, parseJSDocToPatch, parseGitHubUrl, parseAssertions, noEmptyReturns, mergeFixes, mergeFilters, mergeConfig, lintExports, lintExport, isFixableDrift, isExecutableLang, installDependencies, hasNonAssertionComments, hasDocsImpact, hasDocsForExport, getUndocumentedExports, getRunCommand, getRule, getPrimaryBuildScript, getInstallCommand, getDocumentedExports, getDocsImpactSummary, getDefaultConfig, generateFixesForExport, generateFix, formatPackageList, findRemovedReferences, findPackageByName, findJSDocLocation, findExportReferences, findDeprecatedReferences, fetchSpecFromGitHub, fetchSpec, extractSpecSummary, extractPackageSpec, extractImports, extractFunctionCalls, diffSpecWithDocs, detectPackageManager, detectMonorepo, detectExampleRuntimeErrors, detectExampleAssertionFailures, detectEntryPoint, detectBuildInfo, defineConfig, createSourceFile, createNodeCommandRunner, consistentParamStyle, categorizeDrifts, buildRawUrl, buildDisplayUrl, buildCloneUrl, blockReferencesExport, applyPatchToJSDoc, applyEdits, analyzeProject2 as analyzeProject, analyzeFile, analyzeDocsImpact, analyze, allRules, WorkspacePackage, TypecheckResult, TypecheckOptions, SpecSummary, SpecDiffWithDocs, ScanResult, ScanOrchestratorOptions, ScanOrchestrator, ScanOptions, ScanContext, SandboxFileSystem, RunExamplesWithPackageResult, RunExamplesWithPackageOptions, RunExampleOptions, ResolvedTarget, ResolvedFilters, ResolveTargetOptions, ProjectInfo, ProgressStage, ProgressEvent, ProgressCallback, ParsedGitHubUrl, PackageManagerInfo, PackageManager, PackageJson, PackageExports, OpenPkgSpec, OpenPkgOptions, OpenPkg4 as OpenPkg, NodeFileSystem, MonorepoType, MonorepoRequiresPackageError, MonorepoInfo, MemberChange, MarkdownDocFile, MarkdownCodeBlock, LintViolation, LintSeverity2 as LintSeverity, LintRulesConfig, LintRule, LintResult, LintConfig, JSDocTag, JSDocReturn, JSDocPatch, JSDocParam, JSDocEdit, InstallResult, InstallOptions, FixType, FixSuggestion, FilterSource, FilterOptions, FileSystem, ExportReference, ExampleTypeError, ExampleRunResult, EntryPointSource, EntryPointInfo, DriftIssue, DocsImpactResult, DocsImpactReference, DocsImpact, DocsConfig, DocsChangeType, DocCovOptions, DocCovConfig, DocCov, DiffWithDocsOptions, Diagnostic, CommandRunner, CommandResult, CheckConfig, BuildInfo, ApplyEditsResult, AnalyzeProjectOptions, AnalyzeOptions, AnalysisResult };