@doccov/sdk 0.28.0 → 0.28.2

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.
@@ -426,9 +426,126 @@ function categorizeDrifts(drifts) {
426
426
  return { fixable, nonFixable };
427
427
  }
428
428
 
429
- // src/fix/jsdoc-writer.ts
429
+ // src/fix/forgotten-exports.ts
430
430
  import * as fs from "node:fs";
431
431
  import * as path from "node:path";
432
+ function generateForgottenExportFixes(apiSurface, options) {
433
+ const { baseDir, entryFile } = options;
434
+ const fixes = [];
435
+ for (const forgotten of apiSurface.forgotten) {
436
+ if (forgotten.isExternal)
437
+ continue;
438
+ if (!forgotten.fix)
439
+ continue;
440
+ const targetFile = forgotten.fix.targetFile ? path.resolve(baseDir, forgotten.fix.targetFile) : path.resolve(baseDir, entryFile);
441
+ fixes.push({
442
+ type: "forgotten-export",
443
+ typeName: forgotten.name,
444
+ targetFile,
445
+ exportStatement: forgotten.fix.exportStatement,
446
+ insertPosition: "append"
447
+ });
448
+ }
449
+ return fixes;
450
+ }
451
+ function groupFixesByFile(fixes) {
452
+ const grouped = new Map;
453
+ for (const fix of fixes) {
454
+ const existing = grouped.get(fix.targetFile) ?? [];
455
+ existing.push(fix);
456
+ grouped.set(fix.targetFile, existing);
457
+ }
458
+ return grouped;
459
+ }
460
+ async function applyForgottenExportFixes(fixes) {
461
+ const result = {
462
+ filesModified: 0,
463
+ fixesApplied: 0,
464
+ errors: []
465
+ };
466
+ const grouped = groupFixesByFile(fixes);
467
+ for (const [filePath, fileFixes] of grouped) {
468
+ try {
469
+ if (!fs.existsSync(filePath)) {
470
+ result.errors.push({
471
+ file: filePath,
472
+ error: "File not found"
473
+ });
474
+ continue;
475
+ }
476
+ const content = await fs.promises.readFile(filePath, "utf8");
477
+ const lines = content.split(`
478
+ `);
479
+ const insertLine = findBestInsertionPoint(lines, fileFixes);
480
+ const statements = fileFixes.map((f) => f.exportStatement);
481
+ const uniqueStatements = [...new Set(statements)];
482
+ const newContent = insertExportStatements(lines, insertLine, uniqueStatements);
483
+ await fs.promises.writeFile(filePath, newContent, "utf8");
484
+ result.filesModified++;
485
+ result.fixesApplied += uniqueStatements.length;
486
+ } catch (err) {
487
+ result.errors.push({
488
+ file: filePath,
489
+ error: err instanceof Error ? err.message : String(err)
490
+ });
491
+ }
492
+ }
493
+ return result;
494
+ }
495
+ function findBestInsertionPoint(lines, _fixes) {
496
+ let lastExportLine = -1;
497
+ let lastReExportLine = -1;
498
+ for (let i = 0;i < lines.length; i++) {
499
+ const line = lines[i].trim();
500
+ if (line.match(/^export\s+(\*|\{[^}]*\})\s+from\s+['"]/)) {
501
+ lastReExportLine = i;
502
+ }
503
+ if (line.startsWith("export ")) {
504
+ lastExportLine = i;
505
+ }
506
+ }
507
+ if (lastReExportLine >= 0) {
508
+ return lastReExportLine + 1;
509
+ }
510
+ if (lastExportLine >= 0) {
511
+ return lastExportLine + 1;
512
+ }
513
+ return lines.length;
514
+ }
515
+ function insertExportStatements(lines, insertLine, statements) {
516
+ const newLines = [...lines];
517
+ const needsBlankBefore = insertLine > 0 && newLines[insertLine - 1]?.trim() !== "" && !newLines[insertLine - 1]?.trim().startsWith("export");
518
+ const insertBlock = statements.join(`
519
+ `);
520
+ if (needsBlankBefore) {
521
+ newLines.splice(insertLine, 0, "", insertBlock);
522
+ } else {
523
+ newLines.splice(insertLine, 0, insertBlock);
524
+ }
525
+ return newLines.join(`
526
+ `);
527
+ }
528
+ function previewForgottenExportFixes(fixes) {
529
+ const previews = new Map;
530
+ const grouped = groupFixesByFile(fixes);
531
+ for (const [filePath, fileFixes] of grouped) {
532
+ try {
533
+ if (!fs.existsSync(filePath))
534
+ continue;
535
+ const content = fs.readFileSync(filePath, "utf8");
536
+ const lines = content.split(`
537
+ `);
538
+ const insertLine = findBestInsertionPoint(lines, fileFixes);
539
+ const statements = [...new Set(fileFixes.map((f) => f.exportStatement))];
540
+ previews.set(filePath, { insertLine, statements });
541
+ } catch {}
542
+ }
543
+ return previews;
544
+ }
545
+
546
+ // src/fix/jsdoc-writer.ts
547
+ import * as fs2 from "node:fs";
548
+ import * as path2 from "node:path";
432
549
 
433
550
  // src/ts-module.ts
434
551
  import * as tsNamespace from "typescript";
@@ -797,7 +914,7 @@ async function applyEdits(edits) {
797
914
  }
798
915
  for (const [filePath, fileEdits] of editsByFile) {
799
916
  try {
800
- const content = fs.readFileSync(filePath, "utf-8");
917
+ const content = fs2.readFileSync(filePath, "utf-8");
801
918
  const lines = content.split(`
802
919
  `);
803
920
  const sortedEdits = [...fileEdits].sort((a, b) => b.startLine - a.startLine);
@@ -811,7 +928,7 @@ async function applyEdits(edits) {
811
928
  }
812
929
  result.editsApplied++;
813
930
  }
814
- fs.writeFileSync(filePath, lines.join(`
931
+ fs2.writeFileSync(filePath, lines.join(`
815
932
  `));
816
933
  result.filesModified++;
817
934
  } catch (error) {
@@ -824,125 +941,8 @@ async function applyEdits(edits) {
824
941
  return result;
825
942
  }
826
943
  function createSourceFile(filePath) {
827
- const content = fs.readFileSync(filePath, "utf-8");
828
- return ts.createSourceFile(path.basename(filePath), content, ts.ScriptTarget.Latest, true, filePath.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
829
- }
830
-
831
- // src/fix/forgotten-exports.ts
832
- import * as fs2 from "node:fs";
833
- import * as path2 from "node:path";
834
- function generateForgottenExportFixes(apiSurface, options) {
835
- const { baseDir, entryFile } = options;
836
- const fixes = [];
837
- for (const forgotten of apiSurface.forgotten) {
838
- if (forgotten.isExternal)
839
- continue;
840
- if (!forgotten.fix)
841
- continue;
842
- const targetFile = forgotten.fix.targetFile ? path2.resolve(baseDir, forgotten.fix.targetFile) : path2.resolve(baseDir, entryFile);
843
- fixes.push({
844
- type: "forgotten-export",
845
- typeName: forgotten.name,
846
- targetFile,
847
- exportStatement: forgotten.fix.exportStatement,
848
- insertPosition: "append"
849
- });
850
- }
851
- return fixes;
852
- }
853
- function groupFixesByFile(fixes) {
854
- const grouped = new Map;
855
- for (const fix of fixes) {
856
- const existing = grouped.get(fix.targetFile) ?? [];
857
- existing.push(fix);
858
- grouped.set(fix.targetFile, existing);
859
- }
860
- return grouped;
861
- }
862
- async function applyForgottenExportFixes(fixes) {
863
- const result = {
864
- filesModified: 0,
865
- fixesApplied: 0,
866
- errors: []
867
- };
868
- const grouped = groupFixesByFile(fixes);
869
- for (const [filePath, fileFixes] of grouped) {
870
- try {
871
- if (!fs2.existsSync(filePath)) {
872
- result.errors.push({
873
- file: filePath,
874
- error: "File not found"
875
- });
876
- continue;
877
- }
878
- const content = await fs2.promises.readFile(filePath, "utf8");
879
- const lines = content.split(`
880
- `);
881
- const insertLine = findBestInsertionPoint(lines, fileFixes);
882
- const statements = fileFixes.map((f) => f.exportStatement);
883
- const uniqueStatements = [...new Set(statements)];
884
- const newContent = insertExportStatements(lines, insertLine, uniqueStatements);
885
- await fs2.promises.writeFile(filePath, newContent, "utf8");
886
- result.filesModified++;
887
- result.fixesApplied += uniqueStatements.length;
888
- } catch (err) {
889
- result.errors.push({
890
- file: filePath,
891
- error: err instanceof Error ? err.message : String(err)
892
- });
893
- }
894
- }
895
- return result;
896
- }
897
- function findBestInsertionPoint(lines, _fixes) {
898
- let lastExportLine = -1;
899
- let lastReExportLine = -1;
900
- for (let i = 0;i < lines.length; i++) {
901
- const line = lines[i].trim();
902
- if (line.match(/^export\s+(\*|\{[^}]*\})\s+from\s+['"]/)) {
903
- lastReExportLine = i;
904
- }
905
- if (line.startsWith("export ")) {
906
- lastExportLine = i;
907
- }
908
- }
909
- if (lastReExportLine >= 0) {
910
- return lastReExportLine + 1;
911
- }
912
- if (lastExportLine >= 0) {
913
- return lastExportLine + 1;
914
- }
915
- return lines.length;
916
- }
917
- function insertExportStatements(lines, insertLine, statements) {
918
- const newLines = [...lines];
919
- const needsBlankBefore = insertLine > 0 && newLines[insertLine - 1]?.trim() !== "" && !newLines[insertLine - 1]?.trim().startsWith("export");
920
- const insertBlock = statements.join(`
921
- `);
922
- if (needsBlankBefore) {
923
- newLines.splice(insertLine, 0, "", insertBlock);
924
- } else {
925
- newLines.splice(insertLine, 0, insertBlock);
926
- }
927
- return newLines.join(`
928
- `);
929
- }
930
- function previewForgottenExportFixes(fixes) {
931
- const previews = new Map;
932
- const grouped = groupFixesByFile(fixes);
933
- for (const [filePath, fileFixes] of grouped) {
934
- try {
935
- if (!fs2.existsSync(filePath))
936
- continue;
937
- const content = fs2.readFileSync(filePath, "utf8");
938
- const lines = content.split(`
939
- `);
940
- const insertLine = findBestInsertionPoint(lines, fileFixes);
941
- const statements = [...new Set(fileFixes.map((f) => f.exportStatement))];
942
- previews.set(filePath, { insertLine, statements });
943
- } catch {}
944
- }
945
- return previews;
944
+ const content = fs2.readFileSync(filePath, "utf-8");
945
+ return ts.createSourceFile(path2.basename(filePath), content, ts.ScriptTarget.Latest, true, filePath.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
946
946
  }
947
947
  // src/analysis/drift/example-drift.ts
948
948
  import ts2 from "typescript";
@@ -2176,7 +2176,7 @@ function computeHealth(input) {
2176
2176
  examples
2177
2177
  } = input;
2178
2178
  const completenessScore = coverageScore;
2179
- const driftRatio = documentedExports > 0 ? driftIssues / documentedExports : 0;
2179
+ const driftRatio = totalExports > 0 ? driftIssues / totalExports : 0;
2180
2180
  const driftPenalty = Math.min(driftRatio * 0.5, 0.5);
2181
2181
  const accuracyScore = Math.round((1 - driftPenalty) * 100);
2182
2182
  let exampleScore;
@@ -2798,18 +2798,18 @@ function renderApiSurface(spec) {
2798
2798
  // src/extract/schema/index.ts
2799
2799
  import {
2800
2800
  arktypeAdapter,
2801
- typeboxAdapter,
2802
- valibotAdapter,
2803
- zodAdapter,
2804
2801
  extractSchemaType,
2805
- findAdapter,
2806
- isSchemaType,
2807
2802
  extractStandardSchemas,
2808
2803
  extractStandardSchemasFromProject,
2804
+ findAdapter,
2805
+ getNonNullableType,
2806
+ isSchemaType,
2809
2807
  isStandardJSONSchema,
2808
+ isTypeReference,
2810
2809
  resolveCompiledPath,
2811
- getNonNullableType,
2812
- isTypeReference
2810
+ typeboxAdapter,
2811
+ valibotAdapter,
2812
+ zodAdapter
2813
2813
  } from "@openpkg-ts/extract";
2814
2814
  import {
2815
2815
  arktypeAdapter as arktypeAdapter2,
@@ -3060,4 +3060,4 @@ function getExtendedTrend(spec, cwd, options) {
3060
3060
  };
3061
3061
  }
3062
3062
 
3063
- export { isFixableDrift, generateFix, generateFixesForExport, mergeFixes, categorizeDrifts, ts, parseJSDocToPatch, applyPatchToJSDoc, serializeJSDoc, findJSDocLocation, applyEdits, createSourceFile, generateForgottenExportFixes, groupFixesByFile, applyForgottenExportFixes, previewForgottenExportFixes, isBuiltInIdentifier, detectExampleRuntimeErrors, parseAssertions, hasNonAssertionComments, detectExampleAssertionFailures, buildExportRegistry, computeDrift, computeExportDrift, computeHealth, buildDocCovSpec, DRIFT_CATEGORIES2 as DRIFT_CATEGORIES, DRIFT_CATEGORY_LABELS, DRIFT_CATEGORY_DESCRIPTIONS, categorizeDrift, groupDriftsByCategory, getDriftSummary, formatDriftSummaryLine, calculateAggregateCoverage, ensureSpecCoverage, getExportAnalysis, getExportScore, getExportDrift, getExportMissing, isExportFullyDocumented, generateReport, generateReportFromDocCov, loadCachedReport, saveReport, isCachedReportValid, renderApiSurface, extractSchemaOutputType, getRegisteredAdapters, getSupportedLibraries, extractSchemaType, findAdapter, isSchemaType, extractStandardSchemas, extractStandardSchemasFromProject, isStandardJSONSchema, resolveCompiledPath, detectRuntimeSchemas, HISTORY_DIR, computeSnapshot, saveSnapshot, loadSnapshots, getTrend, renderSparkline, formatDelta, pruneHistory, loadSnapshotsForDays, generateWeeklySummaries, getExtendedTrend };
3063
+ export { isFixableDrift, generateFix, generateFixesForExport, mergeFixes, categorizeDrifts, generateForgottenExportFixes, groupFixesByFile, applyForgottenExportFixes, previewForgottenExportFixes, ts, parseJSDocToPatch, applyPatchToJSDoc, serializeJSDoc, findJSDocLocation, applyEdits, createSourceFile, isBuiltInIdentifier, detectExampleRuntimeErrors, parseAssertions, hasNonAssertionComments, detectExampleAssertionFailures, buildExportRegistry, computeDrift, computeExportDrift, computeHealth, buildDocCovSpec, DRIFT_CATEGORIES2 as DRIFT_CATEGORIES, DRIFT_CATEGORY_LABELS, DRIFT_CATEGORY_DESCRIPTIONS, categorizeDrift, groupDriftsByCategory, getDriftSummary, formatDriftSummaryLine, calculateAggregateCoverage, ensureSpecCoverage, getExportAnalysis, getExportScore, getExportDrift, getExportMissing, isExportFullyDocumented, generateReport, generateReportFromDocCov, loadCachedReport, saveReport, isCachedReportValid, renderApiSurface, extractSchemaOutputType, getRegisteredAdapters, getSupportedLibraries, extractSchemaType, extractStandardSchemas, extractStandardSchemasFromProject, findAdapter, isSchemaType, isStandardJSONSchema, resolveCompiledPath, detectRuntimeSchemas, HISTORY_DIR, computeSnapshot, saveSnapshot, loadSnapshots, getTrend, renderSparkline, formatDelta, pruneHistory, loadSnapshotsForDays, generateWeeklySummaries, getExtendedTrend };
@@ -145,6 +145,7 @@ declare function parseListFlag(value?: string | string[]): string[] | undefined;
145
145
  * ```
146
146
  */
147
147
  declare function mergeFilters(config: DocCovConfig | null, overrides: FilterOptions): ResolvedFilters;
148
+ import { ApiSurfaceResult, DocumentationHealth } from "@doccov/spec";
148
149
  /**
149
150
  * All possible drift type identifiers.
150
151
  */
@@ -166,7 +167,6 @@ interface CategorizedDrift extends SpecDocDrift {
166
167
  category: DriftCategory;
167
168
  fixable: boolean;
168
169
  }
169
- import { ApiSurfaceResult, DocumentationHealth } from "@doccov/spec";
170
170
  /**
171
171
  * DocCov report schema version.
172
172
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doccov/sdk",
3
- "version": "0.28.0",
3
+ "version": "0.28.2",
4
4
  "description": "DocCov SDK - Documentation coverage and drift detection for TypeScript",
5
5
  "keywords": [
6
6
  "typescript",