@aiready/doc-drift 0.1.8 → 0.1.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,6 +1,6 @@
1
1
 
2
2
  
3
- > @aiready/doc-drift@0.1.8 build /Users/pengcao/projects/aiready/packages/doc-drift
3
+ > @aiready/doc-drift@0.1.11 build /Users/pengcao/projects/aiready/packages/doc-drift
4
4
  > tsup src/index.ts src/cli.ts --format cjs,esm --dts
5
5
 
6
6
  CLI Building entry: src/cli.ts, src/index.ts
@@ -10,7 +10,7 @@
10
10
  CJS Build start
11
11
  ESM Build start
12
12
 
13
- [12:55:25 AM]  WARN  ▲ [WARNING] The condition "types" here will never be used as it comes after both "import" and "require" [package.json]
13
+ [12:53:09 PM]  WARN  ▲ [WARNING] The condition "types" here will never be used as it comes after both "import" and "require" [package.json]
14
14
 
15
15
  package.json:33:6:
16
16
   33 │ "types": "./dist/index.d.ts"
@@ -31,7 +31,7 @@
31
31
 
32
32
 
33
33
 
34
- [12:55:25 AM]  WARN  ▲ [WARNING] The condition "types" here will never be used as it comes after both "import" and "require" [package.json]
34
+ [12:53:09 PM]  WARN  ▲ [WARNING] The condition "types" here will never be used as it comes after both "import" and "require" [package.json]
35
35
 
36
36
  package.json:33:6:
37
37
   33 │ "types": "./dist/index.d.ts"
@@ -51,15 +51,15 @@
51
51
 
52
52
 
53
53
 
54
- CJS dist/cli.js 7.58 KB
55
- CJS dist/index.js 5.55 KB
56
- CJS ⚡️ Build success in 511ms
57
- ESM dist/chunk-5EFFNN6L.mjs 4.85 KB
58
- ESM dist/index.mjs 88.00 B
59
54
  ESM dist/cli.mjs 1.39 KB
60
- ESM ⚡️ Build success in 495ms
55
+ ESM dist/index.mjs 88.00 B
56
+ ESM dist/chunk-FMK4O4O7.mjs 4.79 KB
57
+ ESM ⚡️ Build success in 182ms
58
+ CJS dist/index.js 5.50 KB
59
+ CJS dist/cli.js 7.52 KB
60
+ CJS ⚡️ Build success in 188ms
61
61
  DTS Build start
62
- DTS ⚡️ Build success in 10279ms
62
+ DTS ⚡️ Build success in 5407ms
63
63
  DTS dist/cli.d.ts 108.00 B
64
64
  DTS dist/index.d.ts 950.00 B
65
65
  DTS dist/cli.d.mts 108.00 B
@@ -1,17 +1,16 @@
1
1
 
2
2
  
3
- > @aiready/doc-drift@0.1.8 test /Users/pengcao/projects/aiready/packages/doc-drift
3
+ > @aiready/doc-drift@0.1.11 test /Users/pengcao/projects/aiready/packages/doc-drift
4
4
  > vitest run
5
5
 
6
6
  [?25l
7
7
   RUN  v4.0.18 /Users/pengcao/projects/aiready/packages/doc-drift
8
8
 
9
- ✓ src/__tests__/analyzer.test.ts (1 test) 364ms
10
- ✓ detects missing param documentation and uncommented complexity  361ms
9
+ ✓ src/__tests__/analyzer.test.ts (1 test) 28ms
11
10
 
12
11
   Test Files  1 passed (1)
13
12
   Tests  1 passed (1)
14
-  Start at  00:56:24
15
-  Duration  5.43s (transform 957ms, setup 0ms, import 3.81s, tests 364ms, environment 0ms)
13
+  Start at  12:53:40
14
+  Duration  727ms (transform 196ms, setup 0ms, import 525ms, tests 28ms, environment 0ms)
16
15
 
17
16
  [?25h
@@ -0,0 +1,143 @@
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
+ } from "@aiready/core";
15
+ import { readFileSync } from "fs";
16
+ import { parse } from "@typescript-eslint/typescript-estree";
17
+ async function analyzeDocDrift(options) {
18
+ const files = await scanFiles(options);
19
+ const issues = [];
20
+ const staleMonths = options.staleMonths ?? 6;
21
+ const staleSeconds = staleMonths * 30 * 24 * 60 * 60;
22
+ let uncommentedExports = 0;
23
+ let totalExports = 0;
24
+ let outdatedComments = 0;
25
+ let undocumentedComplexity = 0;
26
+ const now = Math.floor(Date.now() / 1e3);
27
+ let processed = 0;
28
+ for (const file of files) {
29
+ processed++;
30
+ options.onProgress?.(processed, files.length, `doc-drift: analyzing files`);
31
+ let code;
32
+ try {
33
+ code = readFileSync(file, "utf-8");
34
+ } catch {
35
+ continue;
36
+ }
37
+ let ast;
38
+ try {
39
+ ast = parse(code, {
40
+ jsx: file.endsWith(".tsx") || file.endsWith(".jsx"),
41
+ loc: true,
42
+ comment: true
43
+ });
44
+ } catch {
45
+ continue;
46
+ }
47
+ const comments = ast.comments || [];
48
+ let fileLineStamps;
49
+ for (const node of ast.body) {
50
+ if (node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration") {
51
+ const decl = node.declaration;
52
+ if (!decl) continue;
53
+ if (decl.type === "FunctionDeclaration" || decl.type === "ClassDeclaration" || decl.type === "VariableDeclaration") {
54
+ totalExports++;
55
+ const nodeLine = node.loc.start.line;
56
+ const jsdocs = comments.filter(
57
+ (c) => c.type === "Block" && c.value.startsWith("*") && c.loc.end.line === nodeLine - 1
58
+ );
59
+ if (jsdocs.length === 0) {
60
+ uncommentedExports++;
61
+ if (decl.type === "FunctionDeclaration" && decl.body?.loc) {
62
+ const lines = decl.body.loc.end.line - decl.body.loc.start.line;
63
+ if (lines > 20) undocumentedComplexity++;
64
+ }
65
+ } else {
66
+ const jsdoc = jsdocs[0];
67
+ const jsdocText = jsdoc.value;
68
+ if (decl.type === "FunctionDeclaration") {
69
+ const params = decl.params.map((p) => p.name || p.left && p.left.name).filter(Boolean);
70
+ const paramTags = Array.from(
71
+ jsdocText.matchAll(/@param\s+(?:\{[^}]+\}\s+)?([a-zA-Z0-9_]+)/g)
72
+ ).map((m) => m[1]);
73
+ const missingParams = params.filter(
74
+ (p) => !paramTags.includes(p)
75
+ );
76
+ if (missingParams.length > 0) {
77
+ outdatedComments++;
78
+ issues.push({
79
+ type: "doc-drift",
80
+ severity: "major",
81
+ message: `JSDoc @param mismatch: function has parameters (${missingParams.join(", ")}) not documented in JSDoc.`,
82
+ location: { file, line: nodeLine }
83
+ });
84
+ continue;
85
+ }
86
+ }
87
+ if (!fileLineStamps) {
88
+ fileLineStamps = getFileCommitTimestamps(file);
89
+ }
90
+ const commentModified = getLineRangeLastModifiedCached(
91
+ fileLineStamps,
92
+ jsdoc.loc.start.line,
93
+ jsdoc.loc.end.line
94
+ );
95
+ const bodyModified = getLineRangeLastModifiedCached(
96
+ fileLineStamps,
97
+ decl.loc.start.line,
98
+ decl.loc.end.line
99
+ );
100
+ if (commentModified > 0 && bodyModified > 0) {
101
+ if (now - commentModified > staleSeconds && bodyModified - commentModified > staleSeconds / 2) {
102
+ outdatedComments++;
103
+ issues.push({
104
+ type: "doc-drift",
105
+ severity: "minor",
106
+ message: `JSDoc is significantly older than the function body implementation. Code may have drifted.`,
107
+ location: { file, line: jsdoc.loc.start.line }
108
+ });
109
+ }
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+ const riskResult = calculateDocDrift({
117
+ uncommentedExports,
118
+ totalExports,
119
+ outdatedComments,
120
+ undocumentedComplexity
121
+ });
122
+ return {
123
+ summary: {
124
+ filesAnalyzed: files.length,
125
+ functionsAnalyzed: totalExports,
126
+ score: riskResult.score,
127
+ rating: riskResult.rating
128
+ },
129
+ issues,
130
+ rawData: {
131
+ uncommentedExports,
132
+ totalExports,
133
+ outdatedComments,
134
+ undocumentedComplexity
135
+ },
136
+ recommendations: riskResult.recommendations
137
+ };
138
+ }
139
+
140
+ export {
141
+ __require,
142
+ analyzeDocDrift
143
+ };
package/dist/cli.js CHANGED
@@ -40,10 +40,8 @@ var import_core = require("@aiready/core");
40
40
  var import_fs = require("fs");
41
41
  var import_typescript_estree = require("@typescript-eslint/typescript-estree");
42
42
  async function analyzeDocDrift(options) {
43
- const rootDir = options.rootDir;
44
43
  const files = await (0, import_core.scanFiles)(options);
45
44
  const issues = [];
46
- const results = [];
47
45
  const staleMonths = options.staleMonths ?? 6;
48
46
  const staleSeconds = staleMonths * 30 * 24 * 60 * 60;
49
47
  let uncommentedExports = 0;
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  __require,
3
3
  analyzeDocDrift
4
- } from "./chunk-5EFFNN6L.mjs";
4
+ } from "./chunk-FMK4O4O7.mjs";
5
5
 
6
6
  // src/cli.ts
7
7
  import { Command } from "commander";
package/dist/index.js CHANGED
@@ -29,10 +29,8 @@ var import_core = require("@aiready/core");
29
29
  var import_fs = require("fs");
30
30
  var import_typescript_estree = require("@typescript-eslint/typescript-estree");
31
31
  async function analyzeDocDrift(options) {
32
- const rootDir = options.rootDir;
33
32
  const files = await (0, import_core.scanFiles)(options);
34
33
  const issues = [];
35
- const results = [];
36
34
  const staleMonths = options.staleMonths ?? 6;
37
35
  const staleSeconds = staleMonths * 30 * 24 * 60 * 60;
38
36
  let uncommentedExports = 0;
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  analyzeDocDrift
3
- } from "./chunk-5EFFNN6L.mjs";
3
+ } from "./chunk-FMK4O4O7.mjs";
4
4
  export {
5
5
  analyzeDocDrift
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/doc-drift",
3
- "version": "0.1.8",
3
+ "version": "0.1.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.9.35"
13
+ "@aiready/core": "0.9.38"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@types/node": "^24.0.0",
package/src/analyzer.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  scanFiles,
3
- readFileContent,
4
3
  calculateDocDrift,
5
4
  getFileCommitTimestamps,
6
5
  getLineRangeLastModifiedCached,
@@ -13,11 +12,9 @@ import type { TSESTree } from '@typescript-eslint/types';
13
12
  export async function analyzeDocDrift(
14
13
  options: DocDriftOptions
15
14
  ): Promise<DocDriftReport> {
16
- const rootDir = options.rootDir;
17
15
  // Use core scanFiles which respects .gitignore recursively
18
16
  const files = await scanFiles(options);
19
17
  const issues: DocDriftIssue[] = [];
20
- const results: DocDriftIssue[] = [];
21
18
  const staleMonths = options.staleMonths ?? 6;
22
19
  const staleSeconds = staleMonths * 30 * 24 * 60 * 60;
23
20