@aiready/doc-drift 0.14.9 → 0.14.11

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.
@@ -1,24 +1,23 @@
1
-
2
- 
3
- > @aiready/doc-drift@0.14.9 build /Users/pengcao/projects/aiready/packages/doc-drift
4
- > tsup src/index.ts src/cli.ts --format cjs,esm --dts
5
-
6
- CLI Building entry: src/cli.ts, src/index.ts
7
- CLI Using tsconfig: tsconfig.json
8
- CLI tsup v8.5.1
9
- CLI Target: es2020
10
- CJS Build start
11
- ESM Build start
12
- ESM dist/cli.mjs 1.07 KB
13
- ESM dist/index.mjs 1.87 KB
14
- ESM dist/chunk-GZDN7B4K.mjs 4.40 KB
15
- ESM ⚡️ Build success in 108ms
16
- CJS dist/index.js 6.98 KB
17
- CJS dist/cli.js 6.71 KB
18
- CJS ⚡️ Build success in 108ms
19
- DTS Build start
20
- DTS ⚡️ Build success in 1576ms
21
- DTS dist/cli.d.ts 108.00 B
22
- DTS dist/index.d.ts 2.83 KB
23
- DTS dist/cli.d.mts 108.00 B
24
- DTS dist/index.d.mts 2.83 KB
1
+
2
+ > @aiready/doc-drift@0.14.9 build /Users/pengcao/projects/aiready/packages/doc-drift
3
+ > tsup src/index.ts src/cli.ts --format cjs,esm --dts
4
+
5
+ CLI Building entry: src/cli.ts, src/index.ts
6
+ CLI Using tsconfig: tsconfig.json
7
+ CLI tsup v8.5.1
8
+ CLI Target: es2020
9
+ CJS Build start
10
+ ESM Build start
11
+ CJS dist/cli.js 6.71 KB
12
+ CJS dist/index.js 6.02 KB
13
+ CJS ⚡️ Build success in 78ms
14
+ ESM dist/cli.mjs 1.07 KB
15
+ ESM dist/index.mjs 972.00 B
16
+ ESM dist/chunk-GZDN7B4K.mjs 4.40 KB
17
+ ESM ⚡️ Build success in 78ms
18
+ DTS Build start
19
+ DTS ⚡️ Build success in 3205ms
20
+ DTS dist/cli.d.ts 108.00 B
21
+ DTS dist/index.d.ts 2.48 KB
22
+ DTS dist/cli.d.mts 108.00 B
23
+ DTS dist/index.d.mts 2.48 KB
package/dist/index.d.mts CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as _aiready_core from '@aiready/core';
2
- import { Issue, IssueType, ScanOptions, DocDriftRisk, ToolScoringOutput } from '@aiready/core';
2
+ import { Issue, IssueType, ScanOptions, DocDriftRisk } from '@aiready/core';
3
3
 
4
4
  /**
5
5
  * Documentation Drift Tool Provider
6
6
  */
7
- declare const DocDriftProvider: _aiready_core.ToolProvider;
7
+ declare const DOC_DRIFT_PROVIDER: _aiready_core.ToolProvider;
8
8
 
9
9
  /**
10
10
  * Options for documentation drift analysis
@@ -68,13 +68,4 @@ interface DocDriftReport {
68
68
  */
69
69
  declare function analyzeDocDrift(options: DocDriftOptions): Promise<DocDriftReport>;
70
70
 
71
- /**
72
- * Convert doc-drift report into a standardized ToolScoringOutput.
73
- *
74
- * @param report - The detailed doc-drift report including raw metrics.
75
- * @returns Standardized scoring and risk factor breakdown.
76
- * @lastUpdated 2026-03-24
77
- */
78
- declare function calculateDocDriftScore(report: DocDriftReport): ToolScoringOutput;
79
-
80
- export { type DocDriftIssue, type DocDriftOptions, DocDriftProvider, type DocDriftReport, analyzeDocDrift, calculateDocDriftScore };
71
+ export { DOC_DRIFT_PROVIDER, type DocDriftIssue, type DocDriftOptions, type DocDriftReport, analyzeDocDrift };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as _aiready_core from '@aiready/core';
2
- import { Issue, IssueType, ScanOptions, DocDriftRisk, ToolScoringOutput } from '@aiready/core';
2
+ import { Issue, IssueType, ScanOptions, DocDriftRisk } from '@aiready/core';
3
3
 
4
4
  /**
5
5
  * Documentation Drift Tool Provider
6
6
  */
7
- declare const DocDriftProvider: _aiready_core.ToolProvider;
7
+ declare const DOC_DRIFT_PROVIDER: _aiready_core.ToolProvider;
8
8
 
9
9
  /**
10
10
  * Options for documentation drift analysis
@@ -68,13 +68,4 @@ interface DocDriftReport {
68
68
  */
69
69
  declare function analyzeDocDrift(options: DocDriftOptions): Promise<DocDriftReport>;
70
70
 
71
- /**
72
- * Convert doc-drift report into a standardized ToolScoringOutput.
73
- *
74
- * @param report - The detailed doc-drift report including raw metrics.
75
- * @returns Standardized scoring and risk factor breakdown.
76
- * @lastUpdated 2026-03-24
77
- */
78
- declare function calculateDocDriftScore(report: DocDriftReport): ToolScoringOutput;
79
-
80
- export { type DocDriftIssue, type DocDriftOptions, DocDriftProvider, type DocDriftReport, analyzeDocDrift, calculateDocDriftScore };
71
+ export { DOC_DRIFT_PROVIDER, type DocDriftIssue, type DocDriftOptions, type DocDriftReport, analyzeDocDrift };
package/dist/index.js CHANGED
@@ -20,12 +20,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- DocDriftProvider: () => DocDriftProvider,
24
- analyzeDocDrift: () => analyzeDocDrift,
25
- calculateDocDriftScore: () => calculateDocDriftScore
23
+ DOC_DRIFT_PROVIDER: () => DOC_DRIFT_PROVIDER,
24
+ analyzeDocDrift: () => analyzeDocDrift
26
25
  });
27
26
  module.exports = __toCommonJS(index_exports);
28
- var import_core4 = require("@aiready/core");
27
+ var import_core3 = require("@aiready/core");
29
28
 
30
29
  // src/provider.ts
31
30
  var import_core2 = require("@aiready/core");
@@ -153,7 +152,7 @@ async function analyzeDocDrift(options) {
153
152
  }
154
153
 
155
154
  // src/provider.ts
156
- var DocDriftProvider = (0, import_core2.createProvider)({
155
+ var DOC_DRIFT_PROVIDER = (0, import_core2.createProvider)({
157
156
  id: import_core2.ToolName.DocDrift,
158
157
  alias: ["doc-drift", "docs", "jsdoc"],
159
158
  version: "0.9.5",
@@ -177,37 +176,10 @@ var DocDriftProvider = (0, import_core2.createProvider)({
177
176
  }
178
177
  });
179
178
 
180
- // src/scoring.ts
181
- var import_core3 = require("@aiready/core");
182
- function calculateDocDriftScore(report) {
183
- const { rawData, summary } = report;
184
- const riskResult = (0, import_core3.calculateDocDrift)({
185
- uncommentedExports: rawData.uncommentedExports,
186
- totalExports: rawData.totalExports,
187
- outdatedComments: rawData.outdatedComments,
188
- undocumentedComplexity: rawData.undocumentedComplexity,
189
- actualDrift: rawData.actualDrift
190
- });
191
- return (0, import_core3.buildStandardToolScore)({
192
- toolName: import_core3.ToolName.DocDrift,
193
- score: summary.score,
194
- rawData,
195
- dimensions: riskResult.dimensions,
196
- dimensionNames: {
197
- undocumentedComplexityScore: "Undocumented Complexity",
198
- outdatedCommentsScore: "Outdated/Incomplete Comments",
199
- uncommentedExportsScore: "Uncommented Exports"
200
- },
201
- recommendations: riskResult.recommendations,
202
- rating: summary.rating
203
- });
204
- }
205
-
206
179
  // src/index.ts
207
- import_core4.ToolRegistry.register(DocDriftProvider);
180
+ import_core3.ToolRegistry.register(DOC_DRIFT_PROVIDER);
208
181
  // Annotate the CommonJS export names for ESM import in node:
209
182
  0 && (module.exports = {
210
- DocDriftProvider,
211
- analyzeDocDrift,
212
- calculateDocDriftScore
183
+ DOC_DRIFT_PROVIDER,
184
+ analyzeDocDrift
213
185
  });
package/dist/index.mjs CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  groupIssuesByFile,
13
13
  buildSimpleProviderScore
14
14
  } from "@aiready/core";
15
- var DocDriftProvider = createProvider({
15
+ var DOC_DRIFT_PROVIDER = createProvider({
16
16
  id: ToolName.DocDrift,
17
17
  alias: ["doc-drift", "docs", "jsdoc"],
18
18
  version: "0.9.5",
@@ -36,40 +36,9 @@ var DocDriftProvider = createProvider({
36
36
  }
37
37
  });
38
38
 
39
- // src/scoring.ts
40
- import {
41
- calculateDocDrift,
42
- ToolName as ToolName2,
43
- buildStandardToolScore
44
- } from "@aiready/core";
45
- function calculateDocDriftScore(report) {
46
- const { rawData, summary } = report;
47
- const riskResult = calculateDocDrift({
48
- uncommentedExports: rawData.uncommentedExports,
49
- totalExports: rawData.totalExports,
50
- outdatedComments: rawData.outdatedComments,
51
- undocumentedComplexity: rawData.undocumentedComplexity,
52
- actualDrift: rawData.actualDrift
53
- });
54
- return buildStandardToolScore({
55
- toolName: ToolName2.DocDrift,
56
- score: summary.score,
57
- rawData,
58
- dimensions: riskResult.dimensions,
59
- dimensionNames: {
60
- undocumentedComplexityScore: "Undocumented Complexity",
61
- outdatedCommentsScore: "Outdated/Incomplete Comments",
62
- uncommentedExportsScore: "Uncommented Exports"
63
- },
64
- recommendations: riskResult.recommendations,
65
- rating: summary.rating
66
- });
67
- }
68
-
69
39
  // src/index.ts
70
- ToolRegistry.register(DocDriftProvider);
40
+ ToolRegistry.register(DOC_DRIFT_PROVIDER);
71
41
  export {
72
- DocDriftProvider,
73
- analyzeDocDrift,
74
- calculateDocDriftScore
42
+ DOC_DRIFT_PROVIDER,
43
+ analyzeDocDrift
75
44
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/doc-drift",
3
- "version": "0.14.9",
3
+ "version": "0.14.11",
4
4
  "description": "AI-Readiness: Documentation Drift Detection",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -10,7 +10,7 @@
10
10
  "commander": "^14.0.0",
11
11
  "glob": "^13.0.0",
12
12
  "picocolors": "^1.0.0",
13
- "@aiready/core": "0.24.9"
13
+ "@aiready/core": "0.24.12"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@types/node": "^24.0.0",
@@ -1,46 +1,12 @@
1
- import { describe, it, expect, vi } from 'vitest';
2
- import { DocDriftProvider } from '../provider';
3
- import * as analyzer from '../analyzer';
4
-
5
- vi.mock('../analyzer', () => ({
6
- analyzeDocDrift: vi.fn(),
7
- }));
1
+ import { describe, it, expect } from 'vitest';
2
+ import { DOC_DRIFT_PROVIDER } from '../provider';
8
3
 
9
4
  describe('Doc Drift Provider', () => {
10
- it('should analyze and return SpokeOutput', async () => {
11
- vi.mocked(analyzer.analyzeDocDrift).mockResolvedValue({
12
- summary: {
13
- filesAnalyzed: 1,
14
- functionsAnalyzed: 5,
15
- score: 90,
16
- rating: 'minimal',
17
- },
18
- issues: [],
19
- rawData: {
20
- uncommentedExports: 0,
21
- totalExports: 5,
22
- outdatedComments: 0,
23
- undocumentedComplexity: 0,
24
- actualDrift: 0,
25
- },
26
- recommendations: [],
27
- });
28
-
29
- const output = await DocDriftProvider.analyze({ rootDir: '.' });
30
-
31
- expect(output.summary.filesAnalyzed).toBe(1);
32
- expect(output.metadata!.toolName).toBe('doc-drift');
5
+ it('should have correct ID', () => {
6
+ expect(DOC_DRIFT_PROVIDER.id).toBe('doc-drift');
33
7
  });
34
8
 
35
- it('should score an output', () => {
36
- const mockOutput = {
37
- summary: { score: 80, recommendations: ['Fix it'] } as any,
38
- metadata: { rawData: {} },
39
- results: [],
40
- };
41
-
42
- const scoring = DocDriftProvider.score(mockOutput as any, { rootDir: '.' });
43
- expect(scoring.score).toBe(80);
44
- expect(scoring.recommendations[0].action).toBe('Fix it');
9
+ it('should have alias', () => {
10
+ expect(DOC_DRIFT_PROVIDER.alias).toContain('documentation');
45
11
  });
46
12
  });
package/src/index.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  import { ToolRegistry } from '@aiready/core';
2
- import { DocDriftProvider } from './provider';
2
+ import { DOC_DRIFT_PROVIDER } from './provider';
3
3
 
4
4
  // Register with global registry
5
- ToolRegistry.register(DocDriftProvider);
5
+ ToolRegistry.register(DOC_DRIFT_PROVIDER);
6
6
 
7
7
  export * from './types';
8
8
  export * from './analyzer';
9
- export * from './scoring';
10
- export { DocDriftProvider };
9
+ export { DOC_DRIFT_PROVIDER };
package/src/provider.ts CHANGED
@@ -11,7 +11,7 @@ import { DocDriftOptions } from './types';
11
11
  /**
12
12
  * Documentation Drift Tool Provider
13
13
  */
14
- export const DocDriftProvider = createProvider({
14
+ export const DOC_DRIFT_PROVIDER = createProvider({
15
15
  id: ToolName.DocDrift,
16
16
  alias: ['doc-drift', 'docs', 'jsdoc'],
17
17
  version: '0.9.5',
@@ -1,143 +0,0 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
- // src/analyzer.ts
9
- import {
10
- scanFiles,
11
- calculateDocDrift,
12
- getFileCommitTimestamps,
13
- getLineRangeLastModifiedCached,
14
- Severity,
15
- IssueType,
16
- emitProgress,
17
- getParser
18
- } from "@aiready/core";
19
- import { readFileSync } from "fs";
20
- async function analyzeDocDrift(options) {
21
- const files = await scanFiles(options);
22
- const issues = [];
23
- const staleMonths = options.staleMonths ?? 6;
24
- let uncommentedExports = 0;
25
- let totalExports = 0;
26
- let outdatedComments = 0;
27
- let undocumentedComplexity = 0;
28
- let actualDrift = 0;
29
- let processed = 0;
30
- for (const file of files) {
31
- processed++;
32
- emitProgress(
33
- processed,
34
- files.length,
35
- "doc-drift",
36
- "analyzing files",
37
- options.onProgress
38
- );
39
- const parser = getParser(file);
40
- if (!parser) continue;
41
- let code;
42
- try {
43
- code = readFileSync(file, "utf-8");
44
- } catch {
45
- continue;
46
- }
47
- try {
48
- await parser.initialize();
49
- const parseResult = parser.parse(code, file);
50
- let fileLineStamps;
51
- for (const exp of parseResult.exports) {
52
- if (exp.type === "function" || exp.type === "class") {
53
- totalExports++;
54
- if (!exp.documentation) {
55
- uncommentedExports++;
56
- if (exp.loc) {
57
- const lines = exp.loc.end.line - exp.loc.start.line;
58
- if (lines > 20) undocumentedComplexity++;
59
- }
60
- } else {
61
- const doc = exp.documentation;
62
- const docContent = doc.content;
63
- if (exp.type === "function" && exp.parameters) {
64
- const params = exp.parameters;
65
- const missingParams = params.filter((p) => {
66
- const regex = new RegExp(`\\b${p}\\b`, "i");
67
- return !regex.test(docContent);
68
- });
69
- if (missingParams.length > 0) {
70
- outdatedComments++;
71
- issues.push({
72
- type: IssueType.DocDrift,
73
- severity: Severity.Major,
74
- message: `Documentation mismatch: function parameters (${missingParams.join(", ")}) are not mentioned in the docs.`,
75
- location: { file, line: exp.loc?.start.line || 1 }
76
- });
77
- }
78
- }
79
- if (exp.loc && doc.loc) {
80
- if (!fileLineStamps) {
81
- fileLineStamps = getFileCommitTimestamps(file);
82
- }
83
- const bodyModified = getLineRangeLastModifiedCached(
84
- fileLineStamps,
85
- exp.loc.start.line,
86
- exp.loc.end.line
87
- );
88
- const docModified = getLineRangeLastModifiedCached(
89
- fileLineStamps,
90
- doc.loc.start.line,
91
- doc.loc.end.line
92
- );
93
- if (bodyModified > 0 && docModified > 0) {
94
- const DRIFT_THRESHOLD_SECONDS = 24 * 60 * 60;
95
- if (bodyModified - docModified > DRIFT_THRESHOLD_SECONDS) {
96
- actualDrift++;
97
- issues.push({
98
- type: IssueType.DocDrift,
99
- severity: Severity.Major,
100
- message: `Documentation drift: logic was modified on ${new Date(bodyModified * 1e3).toLocaleDateString()} but documentation was last updated on ${new Date(docModified * 1e3).toLocaleDateString()}.`,
101
- location: { file, line: doc.loc.start.line }
102
- });
103
- }
104
- }
105
- }
106
- }
107
- }
108
- }
109
- } catch (error) {
110
- console.warn(`Doc-drift: Failed to parse ${file}: ${error}`);
111
- continue;
112
- }
113
- }
114
- const riskResult = calculateDocDrift({
115
- uncommentedExports,
116
- totalExports,
117
- outdatedComments,
118
- undocumentedComplexity,
119
- actualDrift
120
- });
121
- return {
122
- summary: {
123
- filesAnalyzed: files.length,
124
- functionsAnalyzed: totalExports,
125
- score: riskResult.score,
126
- rating: riskResult.rating
127
- },
128
- issues,
129
- rawData: {
130
- uncommentedExports,
131
- totalExports,
132
- outdatedComments,
133
- undocumentedComplexity,
134
- actualDrift
135
- },
136
- recommendations: riskResult.recommendations
137
- };
138
- }
139
-
140
- export {
141
- __require,
142
- analyzeDocDrift
143
- };
@@ -1,142 +0,0 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
- // src/analyzer.ts
9
- import {
10
- scanFiles,
11
- calculateDocDrift,
12
- getFileCommitTimestamps,
13
- getLineRangeLastModifiedCached,
14
- Severity,
15
- IssueType,
16
- emitProgress,
17
- getParser
18
- } from "@aiready/core";
19
- import { readFileSync } from "fs";
20
- async function analyzeDocDrift(options) {
21
- const files = await scanFiles(options);
22
- const issues = [];
23
- let uncommentedExports = 0;
24
- let totalExports = 0;
25
- let outdatedComments = 0;
26
- let undocumentedComplexity = 0;
27
- let actualDrift = 0;
28
- let processed = 0;
29
- for (const file of files) {
30
- processed++;
31
- emitProgress(
32
- processed,
33
- files.length,
34
- "doc-drift",
35
- "analyzing files",
36
- options.onProgress
37
- );
38
- const parser = getParser(file);
39
- if (!parser) continue;
40
- let code;
41
- try {
42
- code = readFileSync(file, "utf-8");
43
- } catch {
44
- continue;
45
- }
46
- try {
47
- await parser.initialize();
48
- const parseResult = parser.parse(code, file);
49
- let fileLineStamps;
50
- for (const exp of parseResult.exports) {
51
- if (exp.type === "function" || exp.type === "class") {
52
- totalExports++;
53
- if (!exp.documentation) {
54
- uncommentedExports++;
55
- if (exp.loc) {
56
- const lines = exp.loc.end.line - exp.loc.start.line;
57
- if (lines > 20) undocumentedComplexity++;
58
- }
59
- } else {
60
- const doc = exp.documentation;
61
- const docContent = doc.content;
62
- if (exp.type === "function" && exp.parameters) {
63
- const params = exp.parameters;
64
- const missingParams = params.filter((p) => {
65
- const regex = new RegExp(`\\b${p}\\b`);
66
- return !regex.test(docContent);
67
- });
68
- if (missingParams.length > 0) {
69
- outdatedComments++;
70
- issues.push({
71
- type: IssueType.DocDrift,
72
- severity: Severity.Major,
73
- message: `Documentation mismatch: function parameters (${missingParams.join(", ")}) are not mentioned in the docs.`,
74
- location: { file, line: exp.loc?.start.line || 1 }
75
- });
76
- }
77
- }
78
- if (exp.loc && doc.loc) {
79
- if (!fileLineStamps) {
80
- fileLineStamps = getFileCommitTimestamps(file);
81
- }
82
- const bodyModified = getLineRangeLastModifiedCached(
83
- fileLineStamps,
84
- exp.loc.start.line,
85
- exp.loc.end.line
86
- );
87
- const docModified = getLineRangeLastModifiedCached(
88
- fileLineStamps,
89
- doc.loc.start.line,
90
- doc.loc.end.line
91
- );
92
- if (bodyModified > 0 && docModified > 0) {
93
- const DRIFT_THRESHOLD_SECONDS = 24 * 60 * 60;
94
- if (bodyModified - docModified > DRIFT_THRESHOLD_SECONDS) {
95
- actualDrift++;
96
- issues.push({
97
- type: IssueType.DocDrift,
98
- severity: Severity.Major,
99
- message: `Documentation drift: logic was modified on ${new Date(bodyModified * 1e3).toLocaleDateString()} but documentation was last updated on ${new Date(docModified * 1e3).toLocaleDateString()}.`,
100
- location: { file, line: doc.loc.start.line }
101
- });
102
- }
103
- }
104
- }
105
- }
106
- }
107
- }
108
- } catch (error) {
109
- console.warn(`Doc-drift: Failed to parse ${file}: ${error}`);
110
- continue;
111
- }
112
- }
113
- const riskResult = calculateDocDrift({
114
- uncommentedExports,
115
- totalExports,
116
- outdatedComments,
117
- undocumentedComplexity,
118
- actualDrift
119
- });
120
- return {
121
- summary: {
122
- filesAnalyzed: files.length,
123
- functionsAnalyzed: totalExports,
124
- score: riskResult.score,
125
- rating: riskResult.rating
126
- },
127
- issues,
128
- rawData: {
129
- uncommentedExports,
130
- totalExports,
131
- outdatedComments,
132
- undocumentedComplexity,
133
- actualDrift
134
- },
135
- recommendations: riskResult.recommendations
136
- };
137
- }
138
-
139
- export {
140
- __require,
141
- analyzeDocDrift
142
- };
@@ -1,142 +0,0 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
- // src/analyzer.ts
9
- import {
10
- scanFiles,
11
- calculateDocDrift,
12
- getFileCommitTimestamps,
13
- getLineRangeLastModifiedCached,
14
- Severity,
15
- IssueType,
16
- emitProgress,
17
- getParser
18
- } from "@aiready/core";
19
- import { readFileSync } from "fs";
20
- async function analyzeDocDrift(options) {
21
- const files = await scanFiles(options);
22
- const issues = [];
23
- let uncommentedExports = 0;
24
- let totalExports = 0;
25
- let outdatedComments = 0;
26
- let undocumentedComplexity = 0;
27
- let actualDrift = 0;
28
- let processed = 0;
29
- for (const file of files) {
30
- processed++;
31
- emitProgress(
32
- processed,
33
- files.length,
34
- "doc-drift",
35
- "analyzing files",
36
- options.onProgress
37
- );
38
- const parser = getParser(file);
39
- if (!parser) continue;
40
- let code;
41
- try {
42
- code = readFileSync(file, "utf-8");
43
- } catch {
44
- continue;
45
- }
46
- try {
47
- await parser.initialize();
48
- const parseResult = parser.parse(code, file);
49
- let fileLineStamps;
50
- for (const exp of parseResult.exports) {
51
- if (exp.type === "function" || exp.type === "class") {
52
- totalExports++;
53
- if (!exp.documentation) {
54
- uncommentedExports++;
55
- if (exp.loc) {
56
- const lines = exp.loc.end.line - exp.loc.start.line;
57
- if (lines > 20) undocumentedComplexity++;
58
- }
59
- } else {
60
- const doc = exp.documentation;
61
- const docContent = doc.content;
62
- if (exp.type === "function" && exp.parameters) {
63
- const params = exp.parameters;
64
- const missingParams = params.filter((p) => {
65
- const regex = new RegExp(`\\b${p}\\b`, "i");
66
- return !regex.test(docContent);
67
- });
68
- if (missingParams.length > 0) {
69
- outdatedComments++;
70
- issues.push({
71
- type: IssueType.DocDrift,
72
- severity: Severity.Major,
73
- message: `Documentation mismatch: function parameters (${missingParams.join(", ")}) are not mentioned in the docs.`,
74
- location: { file, line: exp.loc?.start.line || 1 }
75
- });
76
- }
77
- }
78
- if (exp.loc && doc.loc) {
79
- if (!fileLineStamps) {
80
- fileLineStamps = getFileCommitTimestamps(file);
81
- }
82
- const bodyModified = getLineRangeLastModifiedCached(
83
- fileLineStamps,
84
- exp.loc.start.line,
85
- exp.loc.end.line
86
- );
87
- const docModified = getLineRangeLastModifiedCached(
88
- fileLineStamps,
89
- doc.loc.start.line,
90
- doc.loc.end.line
91
- );
92
- if (bodyModified > 0 && docModified > 0) {
93
- const DRIFT_THRESHOLD_SECONDS = 24 * 60 * 60;
94
- if (bodyModified - docModified > DRIFT_THRESHOLD_SECONDS) {
95
- actualDrift++;
96
- issues.push({
97
- type: IssueType.DocDrift,
98
- severity: Severity.Major,
99
- message: `Documentation drift: logic was modified on ${new Date(bodyModified * 1e3).toLocaleDateString()} but documentation was last updated on ${new Date(docModified * 1e3).toLocaleDateString()}.`,
100
- location: { file, line: doc.loc.start.line }
101
- });
102
- }
103
- }
104
- }
105
- }
106
- }
107
- }
108
- } catch (error) {
109
- console.warn(`Doc-drift: Failed to parse ${file}: ${error}`);
110
- continue;
111
- }
112
- }
113
- const riskResult = calculateDocDrift({
114
- uncommentedExports,
115
- totalExports,
116
- outdatedComments,
117
- undocumentedComplexity,
118
- actualDrift
119
- });
120
- return {
121
- summary: {
122
- filesAnalyzed: files.length,
123
- functionsAnalyzed: totalExports,
124
- score: riskResult.score,
125
- rating: riskResult.rating
126
- },
127
- issues,
128
- rawData: {
129
- uncommentedExports,
130
- totalExports,
131
- outdatedComments,
132
- undocumentedComplexity,
133
- actualDrift
134
- },
135
- recommendations: riskResult.recommendations
136
- };
137
- }
138
-
139
- export {
140
- __require,
141
- analyzeDocDrift
142
- };
@@ -1,145 +0,0 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
- // src/analyzer.ts
9
- import {
10
- scanFiles,
11
- calculateDocDrift,
12
- getFileCommitTimestamps,
13
- getLineRangeLastModifiedCached,
14
- Severity,
15
- IssueType,
16
- emitProgress,
17
- getParser
18
- } from "@aiready/core";
19
- import { readFileSync } from "fs";
20
- async function analyzeDocDrift(options) {
21
- const files = await scanFiles(options);
22
- const issues = [];
23
- const staleMonths = options.staleMonths ?? 6;
24
- const staleSeconds = staleMonths * 30 * 24 * 60 * 60;
25
- let uncommentedExports = 0;
26
- let totalExports = 0;
27
- let outdatedComments = 0;
28
- let undocumentedComplexity = 0;
29
- let actualDrift = 0;
30
- const now = Math.floor(Date.now() / 1e3);
31
- let processed = 0;
32
- for (const file of files) {
33
- processed++;
34
- emitProgress(
35
- processed,
36
- files.length,
37
- "doc-drift",
38
- "analyzing files",
39
- options.onProgress
40
- );
41
- const parser = getParser(file);
42
- if (!parser) continue;
43
- let code;
44
- try {
45
- code = readFileSync(file, "utf-8");
46
- } catch {
47
- continue;
48
- }
49
- try {
50
- await parser.initialize();
51
- const parseResult = parser.parse(code, file);
52
- let fileLineStamps;
53
- for (const exp of parseResult.exports) {
54
- if (exp.type === "function" || exp.type === "class") {
55
- totalExports++;
56
- if (!exp.documentation) {
57
- uncommentedExports++;
58
- if (exp.loc) {
59
- const lines = exp.loc.end.line - exp.loc.start.line;
60
- if (lines > 20) undocumentedComplexity++;
61
- }
62
- } else {
63
- const doc = exp.documentation;
64
- const docContent = doc.content;
65
- if (exp.type === "function" && exp.parameters) {
66
- const params = exp.parameters;
67
- const missingParams = params.filter((p) => {
68
- const regex = new RegExp(`\\b${p}\\b`, "i");
69
- return !regex.test(docContent);
70
- });
71
- if (missingParams.length > 0) {
72
- outdatedComments++;
73
- issues.push({
74
- type: IssueType.DocDrift,
75
- severity: Severity.Major,
76
- message: `Documentation mismatch: function parameters (${missingParams.join(", ")}) are not mentioned in the docs.`,
77
- location: { file, line: exp.loc?.start.line || 1 }
78
- });
79
- }
80
- }
81
- if (exp.loc && doc.loc) {
82
- if (!fileLineStamps) {
83
- fileLineStamps = getFileCommitTimestamps(file);
84
- }
85
- const bodyModified = getLineRangeLastModifiedCached(
86
- fileLineStamps,
87
- exp.loc.start.line,
88
- exp.loc.end.line
89
- );
90
- const docModified = getLineRangeLastModifiedCached(
91
- fileLineStamps,
92
- doc.loc.start.line,
93
- doc.loc.end.line
94
- );
95
- if (bodyModified > 0 && docModified > 0) {
96
- const DRIFT_THRESHOLD_SECONDS = 24 * 60 * 60;
97
- if (bodyModified - docModified > DRIFT_THRESHOLD_SECONDS) {
98
- actualDrift++;
99
- issues.push({
100
- type: IssueType.DocDrift,
101
- severity: Severity.Major,
102
- message: `Documentation drift: logic was modified on ${new Date(bodyModified * 1e3).toLocaleDateString()} but documentation was last updated on ${new Date(docModified * 1e3).toLocaleDateString()}.`,
103
- location: { file, line: doc.loc.start.line }
104
- });
105
- }
106
- }
107
- }
108
- }
109
- }
110
- }
111
- } catch (error) {
112
- console.warn(`Doc-drift: Failed to parse ${file}: ${error}`);
113
- continue;
114
- }
115
- }
116
- const riskResult = calculateDocDrift({
117
- uncommentedExports,
118
- totalExports,
119
- outdatedComments,
120
- undocumentedComplexity,
121
- actualDrift
122
- });
123
- return {
124
- summary: {
125
- filesAnalyzed: files.length,
126
- functionsAnalyzed: totalExports,
127
- score: riskResult.score,
128
- rating: riskResult.rating
129
- },
130
- issues,
131
- rawData: {
132
- uncommentedExports,
133
- totalExports,
134
- outdatedComments,
135
- undocumentedComplexity,
136
- actualDrift
137
- },
138
- recommendations: riskResult.recommendations
139
- };
140
- }
141
-
142
- export {
143
- __require,
144
- analyzeDocDrift
145
- };