@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.
- package/dist/analysis/index.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1455 -1335
- package/dist/shared/{chunk-3p1hd5h3.js → chunk-0048g7g0.js} +131 -131
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
|
@@ -426,9 +426,126 @@ function categorizeDrifts(drifts) {
|
|
|
426
426
|
return { fixable, nonFixable };
|
|
427
427
|
}
|
|
428
428
|
|
|
429
|
-
// src/fix/
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
828
|
-
return ts.createSourceFile(
|
|
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 =
|
|
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
|
-
|
|
2812
|
-
|
|
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,
|
|
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 };
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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
|
*/
|