@anatolykoptev/krolik-cli 0.15.1 → 0.16.0
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/bin/cli.js +199 -17
- package/dist/bin/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -58,7 +58,7 @@ var KROLIK_VERSION, TEMPLATE_VERSION;
|
|
|
58
58
|
var init_version = __esm({
|
|
59
59
|
"src/version.ts"() {
|
|
60
60
|
init_esm_shims();
|
|
61
|
-
KROLIK_VERSION = "0.
|
|
61
|
+
KROLIK_VERSION = "0.16.0";
|
|
62
62
|
TEMPLATE_VERSION = "6.1.0";
|
|
63
63
|
}
|
|
64
64
|
});
|
|
@@ -20779,6 +20779,53 @@ var init_context4 = __esm({
|
|
|
20779
20779
|
});
|
|
20780
20780
|
|
|
20781
20781
|
// src/commands/fix/fixers/console/analyzer.ts
|
|
20782
|
+
function isErrorHandlingContext(lines, lineIndex) {
|
|
20783
|
+
const startIdx = Math.max(0, lineIndex - 5);
|
|
20784
|
+
const endIdx = Math.min(lines.length - 1, lineIndex + 2);
|
|
20785
|
+
for (let i = startIdx; i <= endIdx; i++) {
|
|
20786
|
+
const line = lines[i] ?? "";
|
|
20787
|
+
for (const pattern of ERROR_CONTEXT_PATTERNS) {
|
|
20788
|
+
if (pattern.test(line)) {
|
|
20789
|
+
return true;
|
|
20790
|
+
}
|
|
20791
|
+
}
|
|
20792
|
+
}
|
|
20793
|
+
return false;
|
|
20794
|
+
}
|
|
20795
|
+
function isStructuredLogging(line) {
|
|
20796
|
+
return STRUCTURED_LOGGING_PATTERNS.some((pattern) => pattern.test(line));
|
|
20797
|
+
}
|
|
20798
|
+
function classifyConsole(method, lines, lineIndex) {
|
|
20799
|
+
const isDebugMethod = DEBUG_METHODS.includes(method);
|
|
20800
|
+
const isErrorMethod = ERROR_METHODS.includes(method);
|
|
20801
|
+
const inErrorContext = isErrorHandlingContext(lines, lineIndex);
|
|
20802
|
+
if (isErrorMethod && inErrorContext) {
|
|
20803
|
+
return {
|
|
20804
|
+
severity: "info",
|
|
20805
|
+
shouldFix: false,
|
|
20806
|
+
reason: "Error logging in error handler - likely intentional"
|
|
20807
|
+
};
|
|
20808
|
+
}
|
|
20809
|
+
if (isDebugMethod) {
|
|
20810
|
+
return {
|
|
20811
|
+
severity: "warning",
|
|
20812
|
+
shouldFix: true,
|
|
20813
|
+
reason: "Debug statement should be removed before production"
|
|
20814
|
+
};
|
|
20815
|
+
}
|
|
20816
|
+
if (isErrorMethod) {
|
|
20817
|
+
return {
|
|
20818
|
+
severity: "info",
|
|
20819
|
+
shouldFix: true,
|
|
20820
|
+
reason: "Consider using structured logging instead"
|
|
20821
|
+
};
|
|
20822
|
+
}
|
|
20823
|
+
return {
|
|
20824
|
+
severity: "warning",
|
|
20825
|
+
shouldFix: true,
|
|
20826
|
+
reason: "Remove console statement before production"
|
|
20827
|
+
};
|
|
20828
|
+
}
|
|
20782
20829
|
function analyzeConsole(content, file) {
|
|
20783
20830
|
const issues = [];
|
|
20784
20831
|
const lines = content.split("\n");
|
|
@@ -20786,33 +20833,76 @@ function analyzeConsole(content, file) {
|
|
|
20786
20833
|
const line = lines[i] ?? "";
|
|
20787
20834
|
const trimmed = line.trim();
|
|
20788
20835
|
if (trimmed.startsWith("//") || trimmed.startsWith("*")) continue;
|
|
20836
|
+
if (isStructuredLogging(line)) continue;
|
|
20789
20837
|
CONSOLE_PATTERN.lastIndex = 0;
|
|
20790
20838
|
let match;
|
|
20791
20839
|
while ((match = CONSOLE_PATTERN.exec(line)) !== null) {
|
|
20792
20840
|
if (isInsideLineComment(line, match.index)) continue;
|
|
20793
20841
|
if (isInsideStringLine(line, match.index)) continue;
|
|
20794
20842
|
const method = match[1] ?? "log";
|
|
20795
|
-
|
|
20843
|
+
const classification = classifyConsole(method, lines, i);
|
|
20844
|
+
const issue = {
|
|
20796
20845
|
file,
|
|
20797
20846
|
line: i + 1,
|
|
20798
|
-
severity:
|
|
20847
|
+
severity: classification.severity,
|
|
20799
20848
|
category: "lint",
|
|
20800
|
-
message: `
|
|
20801
|
-
suggestion: "Remove
|
|
20802
|
-
snippet: trimmed.slice(0, 60)
|
|
20803
|
-
|
|
20804
|
-
|
|
20849
|
+
message: `console.${method}: ${classification.reason}`,
|
|
20850
|
+
suggestion: classification.shouldFix ? "Remove or replace with structured logging" : "Review if this logging is necessary",
|
|
20851
|
+
snippet: trimmed.slice(0, 60)
|
|
20852
|
+
};
|
|
20853
|
+
if (classification.shouldFix) {
|
|
20854
|
+
issue.fixerId = "console";
|
|
20855
|
+
}
|
|
20856
|
+
issues.push(issue);
|
|
20805
20857
|
}
|
|
20806
20858
|
}
|
|
20807
20859
|
return issues;
|
|
20808
20860
|
}
|
|
20809
|
-
var
|
|
20861
|
+
var DEBUG_METHODS, ERROR_METHODS, ERROR_CONTEXT_PATTERNS, STRUCTURED_LOGGING_PATTERNS, CONSOLE_PATTERN;
|
|
20810
20862
|
var init_analyzer2 = __esm({
|
|
20811
20863
|
"src/commands/fix/fixers/console/analyzer.ts"() {
|
|
20812
20864
|
init_esm_shims();
|
|
20813
20865
|
init_swc();
|
|
20814
|
-
|
|
20815
|
-
|
|
20866
|
+
DEBUG_METHODS = ["log", "debug", "trace", "dir", "table", "info", "count", "time", "timeEnd"];
|
|
20867
|
+
ERROR_METHODS = ["error", "warn"];
|
|
20868
|
+
ERROR_CONTEXT_PATTERNS = [
|
|
20869
|
+
/\bcatch\s*\(/i,
|
|
20870
|
+
// catch block
|
|
20871
|
+
/\.catch\s*\(/i,
|
|
20872
|
+
// promise catch
|
|
20873
|
+
/\bonError\b/i,
|
|
20874
|
+
// error callback
|
|
20875
|
+
/\bonReject\b/i,
|
|
20876
|
+
// rejection handler
|
|
20877
|
+
/\berror\s*[=:]/i,
|
|
20878
|
+
// error variable assignment
|
|
20879
|
+
/\bhandleError\b/i,
|
|
20880
|
+
// error handler function
|
|
20881
|
+
/\bif\s*\(\s*error\b/i,
|
|
20882
|
+
// error check
|
|
20883
|
+
/\bif\s*\(\s*err\b/i,
|
|
20884
|
+
// err check
|
|
20885
|
+
/throw\s+/i
|
|
20886
|
+
// near throw statement
|
|
20887
|
+
];
|
|
20888
|
+
STRUCTURED_LOGGING_PATTERNS = [
|
|
20889
|
+
/\blogger\./i,
|
|
20890
|
+
// logger.info, logger.error
|
|
20891
|
+
/\blog\./i,
|
|
20892
|
+
// log.info, log.error
|
|
20893
|
+
/(?<!console\.)\bdebug\(/i,
|
|
20894
|
+
// debug() from debug package (not console.debug)
|
|
20895
|
+
/\bwinston\b/i,
|
|
20896
|
+
// winston logger
|
|
20897
|
+
/\bpino\b/i,
|
|
20898
|
+
// pino logger
|
|
20899
|
+
/\bbunyan\b/i
|
|
20900
|
+
// bunyan logger
|
|
20901
|
+
];
|
|
20902
|
+
CONSOLE_PATTERN = new RegExp(
|
|
20903
|
+
`console\\.(${[...DEBUG_METHODS, ...ERROR_METHODS].join("|")})\\s*\\(`,
|
|
20904
|
+
"g"
|
|
20905
|
+
);
|
|
20816
20906
|
}
|
|
20817
20907
|
});
|
|
20818
20908
|
|
|
@@ -24766,6 +24856,27 @@ var init_long_functions = __esm({
|
|
|
24766
24856
|
};
|
|
24767
24857
|
}
|
|
24768
24858
|
});
|
|
24859
|
+
function suggestConstantName(value, lineContent) {
|
|
24860
|
+
const knownName = NUMBER_NAME_SUGGESTIONS.get(value);
|
|
24861
|
+
if (knownName) return knownName;
|
|
24862
|
+
for (const { pattern, nameTemplate } of CONTEXT_PATTERNS) {
|
|
24863
|
+
if (pattern.test(lineContent)) {
|
|
24864
|
+
return nameTemplate(value);
|
|
24865
|
+
}
|
|
24866
|
+
}
|
|
24867
|
+
if (value >= 1e3 && value % 1e3 === 0) {
|
|
24868
|
+
const seconds = value / 1e3;
|
|
24869
|
+
if (seconds < 60) return `${seconds}_SECONDS_MS`;
|
|
24870
|
+
if (seconds < 3600) return `${Math.round(seconds / 60)}_MINUTES_MS`;
|
|
24871
|
+
return `${Math.round(seconds / 3600)}_HOURS_MS`;
|
|
24872
|
+
}
|
|
24873
|
+
if (value >= 1024 && value % 1024 === 0) {
|
|
24874
|
+
const kb = value / 1024;
|
|
24875
|
+
if (kb < 1024) return `${kb}_KB`;
|
|
24876
|
+
return `${Math.round(kb / 1024)}_MB`;
|
|
24877
|
+
}
|
|
24878
|
+
return `CONST_${value}`;
|
|
24879
|
+
}
|
|
24769
24880
|
function analyzeMagicNumbersAST(content, file) {
|
|
24770
24881
|
if (file.includes(".config.") || file.includes(".test.") || file.includes(".spec.") || file.endsWith(".d.ts")) {
|
|
24771
24882
|
return [];
|
|
@@ -24789,13 +24900,14 @@ function analyzeMagicNumbersAST(content, file) {
|
|
|
24789
24900
|
if (shouldSkipNumber(value)) continue;
|
|
24790
24901
|
if (isInAllowedContext2(literal)) continue;
|
|
24791
24902
|
const lineContent = lines[line - 1] ?? "";
|
|
24903
|
+
const suggestedName = suggestConstantName(value, lineContent);
|
|
24792
24904
|
issues.push({
|
|
24793
24905
|
file,
|
|
24794
24906
|
line,
|
|
24795
24907
|
severity: "warning",
|
|
24796
24908
|
category: "hardcoded",
|
|
24797
24909
|
message: `Hardcoded number: ${value}`,
|
|
24798
|
-
suggestion:
|
|
24910
|
+
suggestion: `Extract to constant: const ${suggestedName} = ${value}`,
|
|
24799
24911
|
snippet: lineContent.trim().slice(0, 60),
|
|
24800
24912
|
fixerId: "magic-numbers"
|
|
24801
24913
|
});
|
|
@@ -24892,13 +25004,14 @@ function analyzeMagicNumbersFallback(content, file) {
|
|
|
24892
25004
|
while ((match = MAGIC_NUMBER_PATTERN.exec(codeOnly)) !== null) {
|
|
24893
25005
|
const num = parseInt(match[1] ?? "0", 10);
|
|
24894
25006
|
if (shouldSkipNumber(num)) continue;
|
|
25007
|
+
const suggestedName = suggestConstantName(num, line);
|
|
24895
25008
|
issues.push({
|
|
24896
25009
|
file,
|
|
24897
25010
|
line: i + 1,
|
|
24898
25011
|
severity: "warning",
|
|
24899
25012
|
category: "hardcoded",
|
|
24900
25013
|
message: `Hardcoded number: ${num}`,
|
|
24901
|
-
suggestion:
|
|
25014
|
+
suggestion: `Extract to constant: const ${suggestedName} = ${num}`,
|
|
24902
25015
|
snippet: trimmed.slice(0, 60),
|
|
24903
25016
|
fixerId: "magic-numbers"
|
|
24904
25017
|
});
|
|
@@ -24906,7 +25019,7 @@ function analyzeMagicNumbersFallback(content, file) {
|
|
|
24906
25019
|
}
|
|
24907
25020
|
return issues;
|
|
24908
25021
|
}
|
|
24909
|
-
var ALLOWED_NUMBERS, HTTP_STATUS_CODES2, PORT_NUMBERS, TIME_CONSTANTS;
|
|
25022
|
+
var ALLOWED_NUMBERS, HTTP_STATUS_CODES2, PORT_NUMBERS, TIME_CONSTANTS, NUMBER_NAME_SUGGESTIONS, CONTEXT_PATTERNS;
|
|
24910
25023
|
var init_ast_analyzer4 = __esm({
|
|
24911
25024
|
"src/commands/fix/fixers/magic-numbers/ast-analyzer.ts"() {
|
|
24912
25025
|
init_esm_shims();
|
|
@@ -24944,6 +25057,75 @@ var init_ast_analyzer4 = __esm({
|
|
|
24944
25057
|
864e5
|
|
24945
25058
|
// 1 day
|
|
24946
25059
|
]);
|
|
25060
|
+
NUMBER_NAME_SUGGESTIONS = /* @__PURE__ */ new Map([
|
|
25061
|
+
// Time (milliseconds)
|
|
25062
|
+
[500, "HALF_SECOND_MS"],
|
|
25063
|
+
[1e3, "ONE_SECOND_MS"],
|
|
25064
|
+
[1500, "ONE_AND_HALF_SECONDS_MS"],
|
|
25065
|
+
[2e3, "TWO_SECONDS_MS"],
|
|
25066
|
+
[3e3, "THREE_SECONDS_MS"],
|
|
25067
|
+
[5e3, "FIVE_SECONDS_MS"],
|
|
25068
|
+
[1e4, "TEN_SECONDS_MS"],
|
|
25069
|
+
[15e3, "FIFTEEN_SECONDS_MS"],
|
|
25070
|
+
[3e4, "THIRTY_SECONDS_MS"],
|
|
25071
|
+
[6e4, "ONE_MINUTE_MS"],
|
|
25072
|
+
[12e4, "TWO_MINUTES_MS"],
|
|
25073
|
+
[3e5, "FIVE_MINUTES_MS"],
|
|
25074
|
+
[6e5, "TEN_MINUTES_MS"],
|
|
25075
|
+
[9e5, "FIFTEEN_MINUTES_MS"],
|
|
25076
|
+
[18e5, "THIRTY_MINUTES_MS"],
|
|
25077
|
+
[36e5, "ONE_HOUR_MS"],
|
|
25078
|
+
[72e5, "TWO_HOURS_MS"],
|
|
25079
|
+
[864e5, "ONE_DAY_MS"],
|
|
25080
|
+
[6048e5, "ONE_WEEK_MS"],
|
|
25081
|
+
// Time (seconds)
|
|
25082
|
+
[60, "ONE_MINUTE_SECS"],
|
|
25083
|
+
[120, "TWO_MINUTES_SECS"],
|
|
25084
|
+
[300, "FIVE_MINUTES_SECS"],
|
|
25085
|
+
[600, "TEN_MINUTES_SECS"],
|
|
25086
|
+
[3600, "ONE_HOUR_SECS"],
|
|
25087
|
+
[86400, "ONE_DAY_SECS"],
|
|
25088
|
+
// File sizes
|
|
25089
|
+
[1024, "ONE_KB"],
|
|
25090
|
+
[1048576, "ONE_MB"],
|
|
25091
|
+
[1073741824, "ONE_GB"],
|
|
25092
|
+
[5242880, "FIVE_MB"],
|
|
25093
|
+
[10485760, "TEN_MB"],
|
|
25094
|
+
[52428800, "FIFTY_MB"],
|
|
25095
|
+
[104857600, "HUNDRED_MB"],
|
|
25096
|
+
// Pagination / limits
|
|
25097
|
+
[10, "DEFAULT_PAGE_SIZE"],
|
|
25098
|
+
[20, "DEFAULT_PAGE_SIZE"],
|
|
25099
|
+
[25, "DEFAULT_PAGE_SIZE"],
|
|
25100
|
+
[50, "DEFAULT_PAGE_SIZE"],
|
|
25101
|
+
[100, "DEFAULT_LIMIT"],
|
|
25102
|
+
// Retry / timeout
|
|
25103
|
+
[3, "MAX_RETRIES"],
|
|
25104
|
+
[5, "MAX_RETRIES"],
|
|
25105
|
+
// Animation / UI
|
|
25106
|
+
[150, "ANIMATION_DURATION_MS"],
|
|
25107
|
+
[200, "ANIMATION_DURATION_MS"],
|
|
25108
|
+
[250, "ANIMATION_DURATION_MS"],
|
|
25109
|
+
[300, "ANIMATION_DURATION_MS"],
|
|
25110
|
+
[350, "ANIMATION_DURATION_MS"],
|
|
25111
|
+
[400, "ANIMATION_DURATION_MS"],
|
|
25112
|
+
[500, "ANIMATION_DURATION_MS"]
|
|
25113
|
+
]);
|
|
25114
|
+
CONTEXT_PATTERNS = [
|
|
25115
|
+
// setTimeout/setInterval
|
|
25116
|
+
{ pattern: /setTimeout|setInterval|delay|sleep/, nameTemplate: (v) => `DELAY_${v}MS` },
|
|
25117
|
+
// Width/height
|
|
25118
|
+
{ pattern: /width|height|size/i, nameTemplate: (v) => `SIZE_${v}PX` },
|
|
25119
|
+
// Padding/margin
|
|
25120
|
+
{ pattern: /padding|margin|gap|spacing/i, nameTemplate: (v) => `SPACING_${v}` },
|
|
25121
|
+
// Max/min
|
|
25122
|
+
{ pattern: /max|maximum/i, nameTemplate: (v) => `MAX_${v}` },
|
|
25123
|
+
{ pattern: /min|minimum/i, nameTemplate: (v) => `MIN_${v}` },
|
|
25124
|
+
// Threshold/limit
|
|
25125
|
+
{ pattern: /threshold|limit/i, nameTemplate: (v) => `THRESHOLD_${v}` },
|
|
25126
|
+
// Percentage
|
|
25127
|
+
{ pattern: /percent|opacity|alpha/i, nameTemplate: (v) => `PERCENT_${v}` }
|
|
25128
|
+
];
|
|
24947
25129
|
}
|
|
24948
25130
|
});
|
|
24949
25131
|
function fixMagicNumberAST(issue, content) {
|
|
@@ -27042,7 +27224,7 @@ function analyzeContentSignals(filePath, content) {
|
|
|
27042
27224
|
const exportsJSX = matchesAnyPattern(fileContent, JSX_PATTERNS);
|
|
27043
27225
|
const usesReactHooks = matchesAnyPattern(fileContent, REACT_HOOK_PATTERNS);
|
|
27044
27226
|
const exportsValidationSchema = matchesAnyPattern(fileContent, SCHEMA_PATTERNS);
|
|
27045
|
-
const createsReactContext = matchesAnyPattern(fileContent,
|
|
27227
|
+
const createsReactContext = matchesAnyPattern(fileContent, CONTEXT_PATTERNS2);
|
|
27046
27228
|
const hasAsyncOperations = matchesAnyPattern(fileContent, ASYNC_PATTERNS);
|
|
27047
27229
|
const hasPureIndicators = matchesAnyPattern(fileContent, PURE_FUNCTION_INDICATORS);
|
|
27048
27230
|
const hasSideEffects = matchesAnyPattern(fileContent, SIDE_EFFECT_PATTERNS);
|
|
@@ -27094,7 +27276,7 @@ function detectContentType(signals) {
|
|
|
27094
27276
|
}
|
|
27095
27277
|
return null;
|
|
27096
27278
|
}
|
|
27097
|
-
var SCORES, REACT_HOOK_PATTERNS, JSX_PATTERNS, SCHEMA_PATTERNS,
|
|
27279
|
+
var SCORES, REACT_HOOK_PATTERNS, JSX_PATTERNS, SCHEMA_PATTERNS, CONTEXT_PATTERNS2, PURE_FUNCTION_INDICATORS, SIDE_EFFECT_PATTERNS, ASYNC_PATTERNS;
|
|
27098
27280
|
var init_content = __esm({
|
|
27099
27281
|
"src/lib/@discovery/reusables/signals/content.ts"() {
|
|
27100
27282
|
init_esm_shims();
|
|
@@ -27163,7 +27345,7 @@ var init_content = __esm({
|
|
|
27163
27345
|
/export\s+(?:const|type)\s+\w*Schema/
|
|
27164
27346
|
// export const/type XxxSchema
|
|
27165
27347
|
];
|
|
27166
|
-
|
|
27348
|
+
CONTEXT_PATTERNS2 = [
|
|
27167
27349
|
/createContext\s*\(/,
|
|
27168
27350
|
// React.createContext
|
|
27169
27351
|
/React\.createContext\s*\(/,
|