@aiready/consistency 0.3.3 → 0.3.5
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/.turbo/turbo-build.log +7 -7
- package/.turbo/turbo-test.log +19 -14
- package/README.md +55 -7
- package/dist/chunk-2BTBNG6X.mjs +814 -0
- package/dist/chunk-Q5XMWG33.mjs +661 -0
- package/dist/chunk-TLVLM3M5.mjs +771 -0
- package/dist/cli.js +358 -52
- package/dist/cli.mjs +1 -1
- package/dist/index.js +355 -49
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
- package/src/__tests__/analyzer.test.ts +41 -1
- package/src/analyzers/naming.ts +250 -65
package/dist/cli.js
CHANGED
|
@@ -31,12 +31,155 @@ var import_core3 = require("@aiready/core");
|
|
|
31
31
|
|
|
32
32
|
// src/analyzers/naming.ts
|
|
33
33
|
var import_core = require("@aiready/core");
|
|
34
|
+
var import_path = require("path");
|
|
35
|
+
var COMMON_SHORT_WORDS = /* @__PURE__ */ new Set([
|
|
36
|
+
// Full English words (1-3 letters)
|
|
37
|
+
"day",
|
|
38
|
+
"key",
|
|
39
|
+
"net",
|
|
40
|
+
"to",
|
|
41
|
+
"go",
|
|
42
|
+
"for",
|
|
43
|
+
"not",
|
|
44
|
+
"new",
|
|
45
|
+
"old",
|
|
46
|
+
"top",
|
|
47
|
+
"end",
|
|
48
|
+
"run",
|
|
49
|
+
"try",
|
|
50
|
+
"use",
|
|
51
|
+
"get",
|
|
52
|
+
"set",
|
|
53
|
+
"add",
|
|
54
|
+
"put",
|
|
55
|
+
"map",
|
|
56
|
+
"log",
|
|
57
|
+
"row",
|
|
58
|
+
"col",
|
|
59
|
+
"tab",
|
|
60
|
+
"box",
|
|
61
|
+
"div",
|
|
62
|
+
"nav",
|
|
63
|
+
"tag",
|
|
64
|
+
"any",
|
|
65
|
+
"all",
|
|
66
|
+
"one",
|
|
67
|
+
"two",
|
|
68
|
+
"out",
|
|
69
|
+
"off",
|
|
70
|
+
"on",
|
|
71
|
+
"yes",
|
|
72
|
+
"no",
|
|
73
|
+
"now",
|
|
74
|
+
"max",
|
|
75
|
+
"min",
|
|
76
|
+
"sum",
|
|
77
|
+
"avg",
|
|
78
|
+
"ref",
|
|
79
|
+
"src",
|
|
80
|
+
"dst",
|
|
81
|
+
"raw",
|
|
82
|
+
"def",
|
|
83
|
+
"sub",
|
|
84
|
+
"pub",
|
|
85
|
+
"pre",
|
|
86
|
+
"mid",
|
|
87
|
+
"alt",
|
|
88
|
+
"opt",
|
|
89
|
+
"tmp",
|
|
90
|
+
"ext",
|
|
91
|
+
"sep",
|
|
92
|
+
// Additional full words commonly flagged
|
|
93
|
+
"tax",
|
|
94
|
+
"cat",
|
|
95
|
+
"dog",
|
|
96
|
+
"car",
|
|
97
|
+
"bus",
|
|
98
|
+
"web",
|
|
99
|
+
"app",
|
|
100
|
+
"war",
|
|
101
|
+
"law",
|
|
102
|
+
"pay",
|
|
103
|
+
"buy",
|
|
104
|
+
"win",
|
|
105
|
+
"cut",
|
|
106
|
+
"hit",
|
|
107
|
+
"hot",
|
|
108
|
+
"pop",
|
|
109
|
+
"job",
|
|
110
|
+
"age",
|
|
111
|
+
"act",
|
|
112
|
+
"let",
|
|
113
|
+
"lot",
|
|
114
|
+
"bad",
|
|
115
|
+
"big",
|
|
116
|
+
"far",
|
|
117
|
+
"few",
|
|
118
|
+
"own",
|
|
119
|
+
"per",
|
|
120
|
+
"red",
|
|
121
|
+
"low",
|
|
122
|
+
"see",
|
|
123
|
+
"six",
|
|
124
|
+
"ten",
|
|
125
|
+
"way",
|
|
126
|
+
"who",
|
|
127
|
+
"why",
|
|
128
|
+
"yet",
|
|
129
|
+
"via",
|
|
130
|
+
"due",
|
|
131
|
+
"fee",
|
|
132
|
+
"fun",
|
|
133
|
+
"gas",
|
|
134
|
+
"gay",
|
|
135
|
+
"god",
|
|
136
|
+
"gun",
|
|
137
|
+
"guy",
|
|
138
|
+
"ice",
|
|
139
|
+
"ill",
|
|
140
|
+
"kid",
|
|
141
|
+
"mad",
|
|
142
|
+
"man",
|
|
143
|
+
"mix",
|
|
144
|
+
"mom",
|
|
145
|
+
"mrs",
|
|
146
|
+
"nor",
|
|
147
|
+
"odd",
|
|
148
|
+
"oil",
|
|
149
|
+
"pan",
|
|
150
|
+
"pet",
|
|
151
|
+
"pit",
|
|
152
|
+
"pot",
|
|
153
|
+
"pow",
|
|
154
|
+
"pro",
|
|
155
|
+
"raw",
|
|
156
|
+
"rep",
|
|
157
|
+
"rid",
|
|
158
|
+
"sad",
|
|
159
|
+
"sea",
|
|
160
|
+
"sit",
|
|
161
|
+
"sky",
|
|
162
|
+
"son",
|
|
163
|
+
"tea",
|
|
164
|
+
"tie",
|
|
165
|
+
"tip",
|
|
166
|
+
"van",
|
|
167
|
+
"war",
|
|
168
|
+
"win",
|
|
169
|
+
"won"
|
|
170
|
+
]);
|
|
34
171
|
var ACCEPTABLE_ABBREVIATIONS = /* @__PURE__ */ new Set([
|
|
35
172
|
// Standard identifiers
|
|
36
173
|
"id",
|
|
37
174
|
"uid",
|
|
38
175
|
"gid",
|
|
39
176
|
"pid",
|
|
177
|
+
// Loop counters and iterators
|
|
178
|
+
"i",
|
|
179
|
+
"j",
|
|
180
|
+
"k",
|
|
181
|
+
"n",
|
|
182
|
+
"m",
|
|
40
183
|
// Web/Network
|
|
41
184
|
"url",
|
|
42
185
|
"uri",
|
|
@@ -54,6 +197,9 @@ var ACCEPTABLE_ABBREVIATIONS = /* @__PURE__ */ new Set([
|
|
|
54
197
|
"rss",
|
|
55
198
|
"xhr",
|
|
56
199
|
"ajax",
|
|
200
|
+
"cors",
|
|
201
|
+
"ws",
|
|
202
|
+
"wss",
|
|
57
203
|
// Data formats
|
|
58
204
|
"json",
|
|
59
205
|
"xml",
|
|
@@ -63,12 +209,27 @@ var ACCEPTABLE_ABBREVIATIONS = /* @__PURE__ */ new Set([
|
|
|
63
209
|
"css",
|
|
64
210
|
"svg",
|
|
65
211
|
"pdf",
|
|
212
|
+
// File types & extensions
|
|
213
|
+
"img",
|
|
214
|
+
"txt",
|
|
215
|
+
"doc",
|
|
216
|
+
"docx",
|
|
217
|
+
"xlsx",
|
|
218
|
+
"ppt",
|
|
219
|
+
"md",
|
|
220
|
+
"rst",
|
|
221
|
+
"jpg",
|
|
222
|
+
"png",
|
|
223
|
+
"gif",
|
|
66
224
|
// Databases
|
|
67
225
|
"db",
|
|
68
226
|
"sql",
|
|
69
227
|
"orm",
|
|
70
228
|
"dao",
|
|
71
229
|
"dto",
|
|
230
|
+
"ddb",
|
|
231
|
+
"rds",
|
|
232
|
+
"nosql",
|
|
72
233
|
// File system
|
|
73
234
|
"fs",
|
|
74
235
|
"dir",
|
|
@@ -85,6 +246,8 @@ var ACCEPTABLE_ABBREVIATIONS = /* @__PURE__ */ new Set([
|
|
|
85
246
|
"cli",
|
|
86
247
|
"cmd",
|
|
87
248
|
"exe",
|
|
249
|
+
"cwd",
|
|
250
|
+
"pwd",
|
|
88
251
|
// UI/UX
|
|
89
252
|
"ui",
|
|
90
253
|
"ux",
|
|
@@ -97,6 +260,7 @@ var ACCEPTABLE_ABBREVIATIONS = /* @__PURE__ */ new Set([
|
|
|
97
260
|
"ctx",
|
|
98
261
|
"err",
|
|
99
262
|
"msg",
|
|
263
|
+
"auth",
|
|
100
264
|
// Mathematics/Computing
|
|
101
265
|
"max",
|
|
102
266
|
"min",
|
|
@@ -114,12 +278,17 @@ var ACCEPTABLE_ABBREVIATIONS = /* @__PURE__ */ new Set([
|
|
|
114
278
|
"var",
|
|
115
279
|
"int",
|
|
116
280
|
"num",
|
|
281
|
+
"idx",
|
|
117
282
|
// Time
|
|
118
283
|
"now",
|
|
119
284
|
"utc",
|
|
120
285
|
"tz",
|
|
121
286
|
"ms",
|
|
122
287
|
"sec",
|
|
288
|
+
"hr",
|
|
289
|
+
"min",
|
|
290
|
+
"yr",
|
|
291
|
+
"mo",
|
|
123
292
|
// Common patterns
|
|
124
293
|
"app",
|
|
125
294
|
"cfg",
|
|
@@ -139,47 +308,169 @@ var ACCEPTABLE_ABBREVIATIONS = /* @__PURE__ */ new Set([
|
|
|
139
308
|
"post",
|
|
140
309
|
"sub",
|
|
141
310
|
"pub",
|
|
311
|
+
// Programming/Framework specific
|
|
312
|
+
"ts",
|
|
313
|
+
"js",
|
|
314
|
+
"jsx",
|
|
315
|
+
"tsx",
|
|
316
|
+
"py",
|
|
317
|
+
"rb",
|
|
318
|
+
"vue",
|
|
319
|
+
"re",
|
|
320
|
+
"fn",
|
|
321
|
+
"fns",
|
|
322
|
+
"mod",
|
|
323
|
+
"opts",
|
|
324
|
+
"dev",
|
|
325
|
+
// Cloud/Infrastructure
|
|
326
|
+
"s3",
|
|
327
|
+
"ec2",
|
|
328
|
+
"sqs",
|
|
329
|
+
"sns",
|
|
330
|
+
"vpc",
|
|
331
|
+
"ami",
|
|
332
|
+
"iam",
|
|
333
|
+
"acl",
|
|
334
|
+
"elb",
|
|
335
|
+
"alb",
|
|
336
|
+
"nlb",
|
|
337
|
+
"aws",
|
|
338
|
+
// Metrics/Performance
|
|
339
|
+
"fcp",
|
|
340
|
+
"lcp",
|
|
341
|
+
"cls",
|
|
342
|
+
"ttfb",
|
|
343
|
+
"tti",
|
|
344
|
+
"fid",
|
|
345
|
+
"fps",
|
|
346
|
+
"qps",
|
|
347
|
+
"rps",
|
|
348
|
+
"tps",
|
|
349
|
+
// Testing & i18n
|
|
350
|
+
"po",
|
|
351
|
+
"e2e",
|
|
352
|
+
"a11y",
|
|
353
|
+
"i18n",
|
|
354
|
+
"l10n",
|
|
355
|
+
// Domain-specific abbreviations (context-aware)
|
|
356
|
+
"sk",
|
|
357
|
+
"fy",
|
|
358
|
+
"faq",
|
|
359
|
+
"og",
|
|
360
|
+
"seo",
|
|
361
|
+
"cta",
|
|
362
|
+
"roi",
|
|
363
|
+
"kpi",
|
|
142
364
|
// Boolean helpers (these are intentional short names)
|
|
143
365
|
"is",
|
|
144
366
|
"has",
|
|
145
367
|
"can",
|
|
146
368
|
"did",
|
|
147
369
|
"was",
|
|
148
|
-
"are"
|
|
370
|
+
"are",
|
|
371
|
+
// Date/Time context (when in date contexts)
|
|
372
|
+
"d",
|
|
373
|
+
"t",
|
|
374
|
+
"dt"
|
|
149
375
|
]);
|
|
150
376
|
async function analyzeNaming(files) {
|
|
151
377
|
const issues = [];
|
|
378
|
+
const rootDir = files.length > 0 ? (0, import_path.dirname)(files[0]) : process.cwd();
|
|
379
|
+
const config = (0, import_core.loadConfig)(rootDir);
|
|
380
|
+
const consistencyConfig = config?.tools?.["consistency"];
|
|
381
|
+
const customAbbreviations = new Set(consistencyConfig?.acceptedAbbreviations || []);
|
|
382
|
+
const customShortWords = new Set(consistencyConfig?.shortWords || []);
|
|
383
|
+
const disabledChecks = new Set(consistencyConfig?.disableChecks || []);
|
|
152
384
|
for (const file of files) {
|
|
153
385
|
const content = await (0, import_core.readFileContent)(file);
|
|
154
|
-
const fileIssues = analyzeFileNaming(file, content);
|
|
386
|
+
const fileIssues = analyzeFileNaming(file, content, customAbbreviations, customShortWords, disabledChecks);
|
|
155
387
|
issues.push(...fileIssues);
|
|
156
388
|
}
|
|
157
389
|
return issues;
|
|
158
390
|
}
|
|
159
|
-
function analyzeFileNaming(file, content) {
|
|
391
|
+
function analyzeFileNaming(file, content, customAbbreviations, customShortWords, disabledChecks) {
|
|
160
392
|
const issues = [];
|
|
393
|
+
const isTestFile = file.match(/\.(test|spec)\.(ts|tsx|js|jsx)$/);
|
|
161
394
|
const lines = content.split("\n");
|
|
395
|
+
const allAbbreviations = /* @__PURE__ */ new Set([...ACCEPTABLE_ABBREVIATIONS, ...customAbbreviations]);
|
|
396
|
+
const allShortWords = /* @__PURE__ */ new Set([...COMMON_SHORT_WORDS, ...customShortWords]);
|
|
397
|
+
const getContextWindow = (index, windowSize = 3) => {
|
|
398
|
+
const start = Math.max(0, index - windowSize);
|
|
399
|
+
const end = Math.min(lines.length, index + windowSize + 1);
|
|
400
|
+
return lines.slice(start, end).join("\n");
|
|
401
|
+
};
|
|
402
|
+
const isShortLivedVariable = (varName, declarationIndex) => {
|
|
403
|
+
const searchRange = 5;
|
|
404
|
+
const endIndex = Math.min(lines.length, declarationIndex + searchRange + 1);
|
|
405
|
+
let usageCount = 0;
|
|
406
|
+
for (let i = declarationIndex; i < endIndex; i++) {
|
|
407
|
+
const regex = new RegExp(`\\b${varName}\\b`, "g");
|
|
408
|
+
const matches = lines[i].match(regex);
|
|
409
|
+
if (matches) {
|
|
410
|
+
usageCount += matches.length;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return usageCount >= 2 && usageCount <= 3;
|
|
414
|
+
};
|
|
162
415
|
lines.forEach((line, index) => {
|
|
163
416
|
const lineNumber = index + 1;
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
417
|
+
const contextWindow = getContextWindow(index);
|
|
418
|
+
if (!disabledChecks.has("single-letter")) {
|
|
419
|
+
const singleLetterMatches = line.matchAll(/\b(?:const|let|var)\s+([a-hm-z])\s*=/gi);
|
|
420
|
+
for (const match of singleLetterMatches) {
|
|
421
|
+
const letter = match[1].toLowerCase();
|
|
422
|
+
const isInLoopContext = line.includes("for") || /\.(map|filter|forEach|reduce|find|some|every)\s*\(/.test(line) || line.includes("=>") || // Arrow function
|
|
423
|
+
/\w+\s*=>\s*/.test(line);
|
|
424
|
+
const isI18nContext = line.includes("useTranslation") || line.includes("i18n.t") || /\bt\s*\(['"]/.test(line);
|
|
425
|
+
const isArrowFunctionParam = /\(\s*[a-z]\s*(?:,\s*[a-z]\s*)*\)\s*=>/.test(line) || // (s) => or (a, b) =>
|
|
426
|
+
/[a-z]\s*=>/.test(line) || // s => on same line
|
|
427
|
+
// Multi-line arrow function detection: look for pattern in context window
|
|
428
|
+
new RegExp(`\\b${letter}\\s*\\)\\s*$`).test(line) && /=>/.test(contextWindow) || // (s)\n =>
|
|
429
|
+
new RegExp(`\\.(?:map|filter|forEach|reduce|find|some|every)\\s*\\(\\s*$`).test(lines[index - 1] || "") && /=>/.test(contextWindow);
|
|
430
|
+
const isShortLived = isShortLivedVariable(letter, index);
|
|
431
|
+
if (!isInLoopContext && !isI18nContext && !isArrowFunctionParam && !isShortLived && !["x", "y", "z", "i", "j", "k", "l", "n", "m"].includes(letter)) {
|
|
432
|
+
if (isTestFile && ["a", "b", "c", "d", "e", "f", "s"].includes(letter)) {
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
issues.push({
|
|
436
|
+
file,
|
|
437
|
+
line: lineNumber,
|
|
438
|
+
type: "poor-naming",
|
|
439
|
+
identifier: match[1],
|
|
440
|
+
severity: "minor",
|
|
441
|
+
suggestion: `Use descriptive variable name instead of single letter '${match[1]}'`
|
|
442
|
+
});
|
|
443
|
+
}
|
|
177
444
|
}
|
|
178
445
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const
|
|
182
|
-
|
|
446
|
+
if (!disabledChecks.has("abbreviation")) {
|
|
447
|
+
const abbreviationMatches = line.matchAll(/\b(?:const|let|var)\s+([a-z]{1,3})(?=[A-Z]|_|\s*=)/g);
|
|
448
|
+
for (const match of abbreviationMatches) {
|
|
449
|
+
const abbrev = match[1].toLowerCase();
|
|
450
|
+
if (allShortWords.has(abbrev)) {
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
if (allAbbreviations.has(abbrev)) {
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
const isArrowFunctionParam = /\(\s*[a-z]\s*(?:,\s*[a-z]\s*)*\)\s*=>/.test(line) || // (s) => or (a, b) =>
|
|
457
|
+
new RegExp(`\\b${abbrev}\\s*=>`).test(line) || // s => on same line
|
|
458
|
+
// Multi-line arrow function: check context window
|
|
459
|
+
new RegExp(`\\b${abbrev}\\s*\\)\\s*$`).test(line) && /=>/.test(contextWindow) || // (s)\n =>
|
|
460
|
+
new RegExp(`\\.(?:map|filter|forEach|reduce|find|some|every)\\s*\\(\\s*$`).test(lines[index - 1] || "") && new RegExp(`^\\s*${abbrev}\\s*=>`).test(line);
|
|
461
|
+
if (isArrowFunctionParam) {
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
if (abbrev.length <= 2) {
|
|
465
|
+
const isDateTimeContext = /date|time|day|hour|minute|second|timestamp/i.test(line);
|
|
466
|
+
if (isDateTimeContext && ["d", "t", "dt"].includes(abbrev)) {
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
const isUserContext = /user|auth|account/i.test(line);
|
|
470
|
+
if (isUserContext && abbrev === "u") {
|
|
471
|
+
continue;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
183
474
|
issues.push({
|
|
184
475
|
file,
|
|
185
476
|
line: lineNumber,
|
|
@@ -190,7 +481,7 @@ function analyzeFileNaming(file, content) {
|
|
|
190
481
|
});
|
|
191
482
|
}
|
|
192
483
|
}
|
|
193
|
-
if (file.match(/\.(ts|tsx|js|jsx)$/)) {
|
|
484
|
+
if (!disabledChecks.has("convention-mix") && file.match(/\.(ts|tsx|js|jsx)$/)) {
|
|
194
485
|
const camelCaseVars = line.match(/\b(?:const|let|var)\s+([a-z][a-zA-Z0-9]*)\s*=/);
|
|
195
486
|
const snakeCaseVars = line.match(/\b(?:const|let|var)\s+([a-z][a-z0-9]*_[a-z0-9_]*)\s*=/);
|
|
196
487
|
if (snakeCaseVars) {
|
|
@@ -204,36 +495,51 @@ function analyzeFileNaming(file, content) {
|
|
|
204
495
|
});
|
|
205
496
|
}
|
|
206
497
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
498
|
+
if (!disabledChecks.has("unclear")) {
|
|
499
|
+
const booleanMatches = line.matchAll(/\b(?:const|let|var)\s+([a-z][a-zA-Z0-9]*)\s*:\s*boolean/gi);
|
|
500
|
+
for (const match of booleanMatches) {
|
|
501
|
+
const name = match[1];
|
|
502
|
+
if (!name.match(/^(is|has|should|can|will|did)/i)) {
|
|
503
|
+
issues.push({
|
|
504
|
+
file,
|
|
505
|
+
line: lineNumber,
|
|
506
|
+
type: "unclear",
|
|
507
|
+
identifier: name,
|
|
508
|
+
severity: "info",
|
|
509
|
+
suggestion: `Boolean variable '${name}' should start with is/has/should/can for clarity`
|
|
510
|
+
});
|
|
511
|
+
}
|
|
219
512
|
}
|
|
220
513
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
514
|
+
if (!disabledChecks.has("unclear")) {
|
|
515
|
+
const functionMatches = line.matchAll(/function\s+([a-z][a-zA-Z0-9]*)/g);
|
|
516
|
+
for (const match of functionMatches) {
|
|
517
|
+
const name = match[1];
|
|
518
|
+
const isKeyword = ["for", "if", "else", "while", "do", "switch", "case", "break", "continue", "return", "throw", "try", "catch", "finally", "with", "yield", "await"].includes(name);
|
|
519
|
+
if (isKeyword) {
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
522
|
+
const isEntryPoint = ["main", "init", "setup", "bootstrap"].includes(name);
|
|
523
|
+
if (isEntryPoint) {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
const isFactoryPattern = name.match(/(Factory|Builder|Creator|Generator)$/);
|
|
527
|
+
const isEventHandler = name.match(/^on[A-Z]/);
|
|
528
|
+
const isDescriptiveLong = name.length > 15;
|
|
529
|
+
const isDescriptivePattern = name.match(/^(default|total|count|sum|avg|max|min|initial|current|previous|next)\w+/) || name.match(/\w+(Count|Total|Sum|Average|List|Map|Set|Config|Settings|Options|Props)$/);
|
|
530
|
+
const capitalCount = (name.match(/[A-Z]/g) || []).length;
|
|
531
|
+
const isCompoundWord = capitalCount >= 3;
|
|
532
|
+
const hasActionVerb = name.match(/^(get|set|is|has|can|should|create|update|delete|fetch|load|save|process|handle|validate|check|find|search|filter|map|reduce|make|do|run|start|stop|build|parse|format|render|calculate|compute|generate|transform|convert|normalize|sanitize|encode|decode|compress|extract|merge|split|join|sort|compare|test|verify|ensure|apply|execute|invoke|call|emit|dispatch|trigger|listen|subscribe|unsubscribe|add|remove|clear|reset|toggle|enable|disable|open|close|connect|disconnect|send|receive|read|write|import|export|register|unregister|mount|unmount)/);
|
|
533
|
+
if (!hasActionVerb && !isFactoryPattern && !isEventHandler && !isDescriptiveLong && !isDescriptivePattern && !isCompoundWord) {
|
|
534
|
+
issues.push({
|
|
535
|
+
file,
|
|
536
|
+
line: lineNumber,
|
|
537
|
+
type: "unclear",
|
|
538
|
+
identifier: name,
|
|
539
|
+
severity: "info",
|
|
540
|
+
suggestion: `Function '${name}' should start with an action verb (get, set, create, etc.)`
|
|
541
|
+
});
|
|
542
|
+
}
|
|
237
543
|
}
|
|
238
544
|
}
|
|
239
545
|
});
|
|
@@ -533,7 +839,7 @@ function generateRecommendations(namingIssues, patternIssues) {
|
|
|
533
839
|
// src/cli.ts
|
|
534
840
|
var import_chalk = __toESM(require("chalk"));
|
|
535
841
|
var import_fs = require("fs");
|
|
536
|
-
var
|
|
842
|
+
var import_path2 = require("path");
|
|
537
843
|
var import_core4 = require("@aiready/core");
|
|
538
844
|
var program = new import_commander.Command();
|
|
539
845
|
program.name("aiready-consistency").description("Detect consistency issues in naming, patterns, and architecture").version("0.1.0").addHelpText("after", `
|
|
@@ -582,7 +888,7 @@ EXAMPLES:
|
|
|
582
888
|
`consistency-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.json`,
|
|
583
889
|
directory
|
|
584
890
|
);
|
|
585
|
-
const dir = (0,
|
|
891
|
+
const dir = (0, import_path2.dirname)(outputPath);
|
|
586
892
|
if (!(0, import_fs.existsSync)(dir)) {
|
|
587
893
|
(0, import_fs.mkdirSync)(dir, { recursive: true });
|
|
588
894
|
}
|
|
@@ -595,7 +901,7 @@ EXAMPLES:
|
|
|
595
901
|
`consistency-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.md`,
|
|
596
902
|
directory
|
|
597
903
|
);
|
|
598
|
-
const dir = (0,
|
|
904
|
+
const dir = (0, import_path2.dirname)(outputPath);
|
|
599
905
|
if (!(0, import_fs.existsSync)(dir)) {
|
|
600
906
|
(0, import_fs.mkdirSync)(dir, { recursive: true });
|
|
601
907
|
}
|