@wispbit/local 1.0.28 → 1.0.29
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/cli.js +155 -95
- package/dist/cli.js.map +4 -4
- package/dist/package.json +1 -1
- package/dist/src/api/WispbitApiClient.d.ts +5 -0
- package/dist/src/api/WispbitApiClient.d.ts.map +1 -1
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/providers/AstGrepAstProvider.d.ts.map +1 -1
- package/dist/src/providers/ScipIntelligenceProvider.d.ts.map +1 -1
- package/dist/src/providers/WispbitRuleProvider.d.ts.map +1 -1
- package/dist/src/steps/FileExecutionContext.d.ts +3 -10
- package/dist/src/steps/FileExecutionContext.d.ts.map +1 -1
- package/dist/src/types.d.ts +1 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/coordinates.d.ts +12 -0
- package/dist/src/utils/coordinates.d.ts.map +1 -0
- package/dist/src/utils/diffValidation.d.ts +24 -0
- package/dist/src/utils/diffValidation.d.ts.map +1 -0
- package/dist/src/utils/diffValidation.test.d.ts +2 -0
- package/dist/src/utils/diffValidation.test.d.ts.map +1 -0
- package/dist/src/utils/formatters.d.ts +3 -0
- package/dist/src/utils/formatters.d.ts.map +1 -1
- package/dist/src/utils/ruleExecution.d.ts +20 -0
- package/dist/src/utils/ruleExecution.d.ts.map +1 -0
- package/dist/src/utils/validateRule.d.ts +1 -1
- package/dist/src/utils/validateRule.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -245,7 +245,8 @@ var GetRulesResponseSchema = z2.object({
|
|
|
245
245
|
message: z2.string(),
|
|
246
246
|
prompt: z2.string(),
|
|
247
247
|
severity: z2.enum(["suggestion", "violation"]),
|
|
248
|
-
schema: z2.any()
|
|
248
|
+
schema: z2.any(),
|
|
249
|
+
execution: z2.enum(["llm", "deterministic"]).optional()
|
|
249
250
|
})
|
|
250
251
|
)
|
|
251
252
|
});
|
|
@@ -1280,6 +1281,7 @@ var WispbitRuleProvider = class {
|
|
|
1280
1281
|
config: {
|
|
1281
1282
|
message: rule.message,
|
|
1282
1283
|
severity: rule.severity,
|
|
1284
|
+
execution: rule.execution || "llm",
|
|
1283
1285
|
steps: rule.schema
|
|
1284
1286
|
},
|
|
1285
1287
|
prompt: rule.prompt,
|
|
@@ -1414,6 +1416,59 @@ import * as fs2 from "fs";
|
|
|
1414
1416
|
import * as path3 from "path";
|
|
1415
1417
|
import { glob } from "glob";
|
|
1416
1418
|
|
|
1419
|
+
// src/utils/diffValidation.ts
|
|
1420
|
+
function isFileValidInDiff(filePath, options) {
|
|
1421
|
+
const { changedFiles } = options;
|
|
1422
|
+
return changedFiles.some((changedFile) => {
|
|
1423
|
+
return filePath === changedFile || filePath.endsWith(changedFile) || changedFile.endsWith(filePath);
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
function isLineRangeValidInDiff(filePath, startLine, endLine, options) {
|
|
1427
|
+
const { fileChangeMap } = options;
|
|
1428
|
+
const fileChange = fileChangeMap.get(filePath);
|
|
1429
|
+
if (!fileChange) {
|
|
1430
|
+
return false;
|
|
1431
|
+
}
|
|
1432
|
+
if (fileChange.status === "added") {
|
|
1433
|
+
return true;
|
|
1434
|
+
}
|
|
1435
|
+
if (fileChange.status === "removed") {
|
|
1436
|
+
return false;
|
|
1437
|
+
}
|
|
1438
|
+
return isLineRangeInPatch(fileChange.patch, startLine, endLine);
|
|
1439
|
+
}
|
|
1440
|
+
function isMatchValidInDiff(match, options) {
|
|
1441
|
+
return isFileValidInDiff(match.filePath, options) && isLineRangeValidInDiff(match.filePath, match.range.start.line, match.range.end.line, options);
|
|
1442
|
+
}
|
|
1443
|
+
function isLineRangeInPatch(patch, startLine, endLine) {
|
|
1444
|
+
const lines = patch.split("\n");
|
|
1445
|
+
let currentNewLine = 0;
|
|
1446
|
+
let inHunk = false;
|
|
1447
|
+
for (const line of lines) {
|
|
1448
|
+
const hunkMatch = line.match(/^@@\s+-\d+(?:,\d+)?\s+\+(\d+)(?:,\d+)?\s+@@/);
|
|
1449
|
+
if (hunkMatch) {
|
|
1450
|
+
currentNewLine = parseInt(hunkMatch[1], 10);
|
|
1451
|
+
inHunk = true;
|
|
1452
|
+
continue;
|
|
1453
|
+
}
|
|
1454
|
+
if (!inHunk) continue;
|
|
1455
|
+
if (line.startsWith("+")) {
|
|
1456
|
+
if (currentNewLine >= startLine && currentNewLine <= endLine) {
|
|
1457
|
+
return true;
|
|
1458
|
+
}
|
|
1459
|
+
currentNewLine++;
|
|
1460
|
+
} else if (line.startsWith("-")) {
|
|
1461
|
+
continue;
|
|
1462
|
+
} else if (!line.startsWith("\\")) {
|
|
1463
|
+
if (currentNewLine >= startLine && currentNewLine <= endLine) {
|
|
1464
|
+
return true;
|
|
1465
|
+
}
|
|
1466
|
+
currentNewLine++;
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
return false;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1417
1472
|
// src/utils/patternMatching.ts
|
|
1418
1473
|
import ignore from "ignore";
|
|
1419
1474
|
function matchesAnyPattern(filePath, patterns) {
|
|
@@ -1703,30 +1758,11 @@ var FileExecutionContext = class _FileExecutionContext {
|
|
|
1703
1758
|
return true;
|
|
1704
1759
|
}
|
|
1705
1760
|
const { filePath } = options;
|
|
1706
|
-
return
|
|
1707
|
-
|
|
1761
|
+
return isFileValidInDiff(filePath, {
|
|
1762
|
+
changedFiles: this.diffMode.changedFiles,
|
|
1763
|
+
fileChangeMap: this.diffMode.fileChangeMap
|
|
1708
1764
|
});
|
|
1709
1765
|
}
|
|
1710
|
-
/**
|
|
1711
|
-
* Check if a specific line range should be processed
|
|
1712
|
-
*/
|
|
1713
|
-
isLineRangeValid(options) {
|
|
1714
|
-
if (this.mode === "check") {
|
|
1715
|
-
return true;
|
|
1716
|
-
}
|
|
1717
|
-
const { filePath, startLine, endLine } = options;
|
|
1718
|
-
const fileChange = this.diffMode.fileChangeMap.get(filePath);
|
|
1719
|
-
if (!fileChange) {
|
|
1720
|
-
return false;
|
|
1721
|
-
}
|
|
1722
|
-
if (fileChange.status === "added") {
|
|
1723
|
-
return true;
|
|
1724
|
-
}
|
|
1725
|
-
if (fileChange.status === "removed") {
|
|
1726
|
-
return false;
|
|
1727
|
-
}
|
|
1728
|
-
return this.isLineRangeInPatch({ patch: fileChange.patch, startLine, endLine });
|
|
1729
|
-
}
|
|
1730
1766
|
/**
|
|
1731
1767
|
* Check if a match should be processed
|
|
1732
1768
|
*/
|
|
@@ -1735,46 +1771,11 @@ var FileExecutionContext = class _FileExecutionContext {
|
|
|
1735
1771
|
return true;
|
|
1736
1772
|
}
|
|
1737
1773
|
const { match } = options;
|
|
1738
|
-
return
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
endLine: match.range.end.line
|
|
1774
|
+
return isMatchValidInDiff(match, {
|
|
1775
|
+
changedFiles: this.diffMode.changedFiles,
|
|
1776
|
+
fileChangeMap: this.diffMode.fileChangeMap
|
|
1742
1777
|
});
|
|
1743
1778
|
}
|
|
1744
|
-
// ===== Helper Methods =====
|
|
1745
|
-
/**
|
|
1746
|
-
* Parse a git patch to determine if a line range intersects with changed lines
|
|
1747
|
-
* Adapted from patchParser.ts logic
|
|
1748
|
-
*/
|
|
1749
|
-
isLineRangeInPatch(options) {
|
|
1750
|
-
const { patch, startLine, endLine } = options;
|
|
1751
|
-
const lines = patch.split("\n");
|
|
1752
|
-
let currentNewLine = 0;
|
|
1753
|
-
let inHunk = false;
|
|
1754
|
-
for (const line of lines) {
|
|
1755
|
-
const hunkMatch = line.match(/^@@\s+-\d+(?:,\d+)?\s+\+(\d+)(?:,\d+)?\s+@@/);
|
|
1756
|
-
if (hunkMatch) {
|
|
1757
|
-
currentNewLine = parseInt(hunkMatch[1], 10);
|
|
1758
|
-
inHunk = true;
|
|
1759
|
-
continue;
|
|
1760
|
-
}
|
|
1761
|
-
if (!inHunk) continue;
|
|
1762
|
-
if (line.startsWith("+")) {
|
|
1763
|
-
if (currentNewLine >= startLine && currentNewLine <= endLine) {
|
|
1764
|
-
return true;
|
|
1765
|
-
}
|
|
1766
|
-
currentNewLine++;
|
|
1767
|
-
} else if (line.startsWith("-")) {
|
|
1768
|
-
continue;
|
|
1769
|
-
} else if (!line.startsWith("\\")) {
|
|
1770
|
-
if (currentNewLine >= startLine && currentNewLine <= endLine) {
|
|
1771
|
-
return true;
|
|
1772
|
-
}
|
|
1773
|
-
currentNewLine++;
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
return false;
|
|
1777
|
-
}
|
|
1778
1779
|
};
|
|
1779
1780
|
|
|
1780
1781
|
// src/steps/FileFilterStep.ts
|
|
@@ -1876,6 +1877,40 @@ import path8 from "path";
|
|
|
1876
1877
|
import { readFile as readFile2 } from "fs/promises";
|
|
1877
1878
|
import path5 from "path";
|
|
1878
1879
|
import { parse as parse2, parseAsync } from "@ast-grep/napi";
|
|
1880
|
+
|
|
1881
|
+
// src/utils/coordinates.ts
|
|
1882
|
+
function matchTo0Indexed(match) {
|
|
1883
|
+
return {
|
|
1884
|
+
...match,
|
|
1885
|
+
range: {
|
|
1886
|
+
start: {
|
|
1887
|
+
line: match.range.start.line - 1,
|
|
1888
|
+
column: match.range.start.column - 1
|
|
1889
|
+
},
|
|
1890
|
+
end: {
|
|
1891
|
+
line: match.range.end.line - 1,
|
|
1892
|
+
column: match.range.end.column - 1
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
};
|
|
1896
|
+
}
|
|
1897
|
+
function matchTo1Indexed(match) {
|
|
1898
|
+
return {
|
|
1899
|
+
...match,
|
|
1900
|
+
range: {
|
|
1901
|
+
start: {
|
|
1902
|
+
line: match.range.start.line + 1,
|
|
1903
|
+
column: match.range.start.column + 1
|
|
1904
|
+
},
|
|
1905
|
+
end: {
|
|
1906
|
+
line: match.range.end.line + 1,
|
|
1907
|
+
column: match.range.end.column + 1
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
};
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
// src/providers/AstGrepAstProvider.ts
|
|
1879
1914
|
var AstGrepAstProvider = class {
|
|
1880
1915
|
environment;
|
|
1881
1916
|
language;
|
|
@@ -1932,7 +1967,7 @@ var AstGrepAstProvider = class {
|
|
|
1932
1967
|
const matches = [];
|
|
1933
1968
|
for (const { filePath, sgNode } of sgNodes) {
|
|
1934
1969
|
const range = sgNode.range();
|
|
1935
|
-
|
|
1970
|
+
const match0Indexed = {
|
|
1936
1971
|
filePath,
|
|
1937
1972
|
text: sgNode.text(),
|
|
1938
1973
|
range: {
|
|
@@ -1948,7 +1983,8 @@ var AstGrepAstProvider = class {
|
|
|
1948
1983
|
// Try to extract symbol if possible
|
|
1949
1984
|
symbol: this.extractSymbol(sgNode),
|
|
1950
1985
|
language: this.language
|
|
1951
|
-
}
|
|
1986
|
+
};
|
|
1987
|
+
matches.push(matchTo1Indexed(match0Indexed));
|
|
1952
1988
|
}
|
|
1953
1989
|
return matches;
|
|
1954
1990
|
}
|
|
@@ -1991,10 +2027,11 @@ var AstGrepAstProvider = class {
|
|
|
1991
2027
|
const absolutePath = path5.resolve(this.environment.getWorkspaceRoot(), match.filePath);
|
|
1992
2028
|
const content = await readFile2(absolutePath, "utf-8");
|
|
1993
2029
|
const root = parse2(this.language, content).root();
|
|
2030
|
+
const match0Indexed = matchTo0Indexed(match);
|
|
1994
2031
|
const nodeAtPosition = this.findNodeAtPosition(
|
|
1995
2032
|
root,
|
|
1996
|
-
|
|
1997
|
-
|
|
2033
|
+
match0Indexed.range.start.line,
|
|
2034
|
+
match0Indexed.range.start.column
|
|
1998
2035
|
);
|
|
1999
2036
|
if (!nodeAtPosition) {
|
|
2000
2037
|
return null;
|
|
@@ -2005,7 +2042,7 @@ var AstGrepAstProvider = class {
|
|
|
2005
2042
|
const kindStr = typeof kindValue === "string" ? kindValue : String(kindValue);
|
|
2006
2043
|
if (targetNodeKinds.has(kindStr)) {
|
|
2007
2044
|
const range = current.range();
|
|
2008
|
-
|
|
2045
|
+
const expandedMatch0Indexed = {
|
|
2009
2046
|
filePath: match.filePath,
|
|
2010
2047
|
text: current.text(),
|
|
2011
2048
|
range: {
|
|
@@ -2015,6 +2052,7 @@ var AstGrepAstProvider = class {
|
|
|
2015
2052
|
symbol: match.symbol,
|
|
2016
2053
|
language: this.language
|
|
2017
2054
|
};
|
|
2055
|
+
return matchTo1Indexed(expandedMatch0Indexed);
|
|
2018
2056
|
}
|
|
2019
2057
|
current = current.parent();
|
|
2020
2058
|
}
|
|
@@ -2215,13 +2253,14 @@ var ScipIntelligenceProvider = class {
|
|
|
2215
2253
|
async findDefinitions(match) {
|
|
2216
2254
|
await this.ensureIndexReady();
|
|
2217
2255
|
if (!this.scipIndex) throw new Error("SCIP index not ready");
|
|
2218
|
-
|
|
2256
|
+
const match0Indexed = matchTo0Indexed(match);
|
|
2257
|
+
this.eventEmitter.startScipMatchLookup(this.language, match0Indexed);
|
|
2219
2258
|
const definitions = [];
|
|
2220
2259
|
const documents = this.scipIndex.documents;
|
|
2221
2260
|
for (const document of documents) {
|
|
2222
|
-
if (document.relative_path !==
|
|
2261
|
+
if (document.relative_path !== match0Indexed.filePath) continue;
|
|
2223
2262
|
this.eventEmitter.scipMatchLookupProgress(this.language, document);
|
|
2224
|
-
const scipOcc = this.findBestOverlappingOccurrence(document.occurrences,
|
|
2263
|
+
const scipOcc = this.findBestOverlappingOccurrence(document.occurrences, match0Indexed);
|
|
2225
2264
|
if (scipOcc) {
|
|
2226
2265
|
if (this.isExternalSymbol(scipOcc.symbol)) {
|
|
2227
2266
|
continue;
|
|
@@ -2229,7 +2268,7 @@ var ScipIntelligenceProvider = class {
|
|
|
2229
2268
|
this.eventEmitter.scipMatchLookupProgress(this.language, scipOcc);
|
|
2230
2269
|
const def = await this.findDefinitionForSymbol(scipOcc.symbol, documents);
|
|
2231
2270
|
if (def) {
|
|
2232
|
-
definitions.push(def);
|
|
2271
|
+
definitions.push(matchTo1Indexed(def));
|
|
2233
2272
|
}
|
|
2234
2273
|
}
|
|
2235
2274
|
}
|
|
@@ -2244,17 +2283,18 @@ var ScipIntelligenceProvider = class {
|
|
|
2244
2283
|
if (!this.scipIndex) {
|
|
2245
2284
|
return [];
|
|
2246
2285
|
}
|
|
2286
|
+
const match0Indexed = matchTo0Indexed(match);
|
|
2247
2287
|
const references = [];
|
|
2248
2288
|
const documents = this.scipIndex.documents;
|
|
2249
2289
|
for (const document of documents) {
|
|
2250
|
-
if (document.relative_path !==
|
|
2251
|
-
const scipOcc = this.findBestOverlappingOccurrence(document.occurrences,
|
|
2290
|
+
if (document.relative_path !== match0Indexed.filePath) continue;
|
|
2291
|
+
const scipOcc = this.findBestOverlappingOccurrence(document.occurrences, match0Indexed);
|
|
2252
2292
|
if (scipOcc) {
|
|
2253
2293
|
if (this.isExternalSymbol(scipOcc.symbol)) {
|
|
2254
2294
|
break;
|
|
2255
2295
|
}
|
|
2256
2296
|
const refs = await this.findReferencesForSymbol(scipOcc.symbol, documents);
|
|
2257
|
-
references.push(...refs);
|
|
2297
|
+
references.push(...refs.map((ref) => matchTo1Indexed(ref)));
|
|
2258
2298
|
break;
|
|
2259
2299
|
}
|
|
2260
2300
|
}
|
|
@@ -3197,14 +3237,21 @@ var VIOLATION_COLOR = "#f87171";
|
|
|
3197
3237
|
var SUGGESTION_COLOR = "#60a5fa";
|
|
3198
3238
|
var SKIPPED_COLOR = "#9b59b6";
|
|
3199
3239
|
var BRAND_COLOR = "#fbbf24";
|
|
3240
|
+
var DETERMINISTIC_COLOR = "#9ca3af";
|
|
3241
|
+
var LLM_COLOR = "#9b59b6";
|
|
3200
3242
|
function formatClickableRuleId(ruleId, internalId) {
|
|
3201
3243
|
if (internalId) {
|
|
3202
3244
|
const url = `https://app.wispbit.com/rules/${internalId}`;
|
|
3203
|
-
|
|
3204
|
-
return link;
|
|
3245
|
+
return `${chalk.dim.underline(ruleId)}${chalk.dim("|")}${chalk.dim.underline(url)}`;
|
|
3205
3246
|
}
|
|
3206
3247
|
return chalk.dim(ruleId);
|
|
3207
3248
|
}
|
|
3249
|
+
function truncateMessage(message, maxWidth) {
|
|
3250
|
+
if (message.length <= maxWidth) {
|
|
3251
|
+
return message;
|
|
3252
|
+
}
|
|
3253
|
+
return message.substring(0, maxWidth - 3) + "...";
|
|
3254
|
+
}
|
|
3208
3255
|
var LINE_NUMBER_BG_COLOR = "#f8f8f8";
|
|
3209
3256
|
var LINE_NUMBER_TEXT_COLOR = "#888888";
|
|
3210
3257
|
var loadingFrames = [
|
|
@@ -3283,9 +3330,9 @@ function printSummary(results, summary) {
|
|
|
3283
3330
|
var _a;
|
|
3284
3331
|
ruleData.matches.push({
|
|
3285
3332
|
filePath: match.filePath,
|
|
3286
|
-
line: match.range.start.line
|
|
3287
|
-
column: match.range.start.column
|
|
3288
|
-
endLine: match.range.end.line !== match.range.start.line ? match.range.end.line
|
|
3333
|
+
line: match.range.start.line,
|
|
3334
|
+
column: match.range.start.column,
|
|
3335
|
+
endLine: match.range.end.line !== match.range.start.line ? match.range.end.line : void 0,
|
|
3289
3336
|
text: match.text
|
|
3290
3337
|
});
|
|
3291
3338
|
if ((_a = match.metadata) == null ? void 0 : _a.llmValidation) {
|
|
@@ -3388,11 +3435,14 @@ function printRulesList(rules) {
|
|
|
3388
3435
|
const tableData = [];
|
|
3389
3436
|
tableData.push([
|
|
3390
3437
|
"",
|
|
3391
|
-
`${"id".padEnd(12)} ${chalk.dim("\u2502")} ${"severity".padEnd(16)} ${chalk.dim("\u2502")} message`
|
|
3438
|
+
`${"id".padEnd(12)} ${chalk.dim("\u2502")} ${"severity".padEnd(16)} ${chalk.dim("\u2502")} ${"execution".padEnd(18)} ${chalk.dim("\u2502")} message`
|
|
3392
3439
|
]);
|
|
3440
|
+
const terminalWidth = process.stdout.columns || 120;
|
|
3441
|
+
const fixedColumnsWidth = 12 + 3 + 16 + 3 + 18 + 3;
|
|
3442
|
+
const messageMaxWidth = Math.max(20, terminalWidth - fixedColumnsWidth - 10);
|
|
3393
3443
|
tableData.push([
|
|
3394
3444
|
"",
|
|
3395
|
-
`${chalk.dim("\u2500".repeat(12))} ${chalk.dim("\u253C")} ${chalk.dim("\u2500".repeat(16))} ${chalk.dim("\u253C")} ${chalk.dim("\u2500".repeat(
|
|
3445
|
+
`${chalk.dim("\u2500".repeat(12))} ${chalk.dim("\u253C")} ${chalk.dim("\u2500".repeat(16))} ${chalk.dim("\u253C")} ${chalk.dim("\u2500".repeat(18))} ${chalk.dim("\u253C")} ${chalk.dim("\u2500".repeat(messageMaxWidth))}`
|
|
3396
3446
|
]);
|
|
3397
3447
|
for (const rule of rules) {
|
|
3398
3448
|
const severityIcon = rule.config.severity === "violation" ? "\u25A0" : "\u25CF";
|
|
@@ -3400,11 +3450,14 @@ function printRulesList(rules) {
|
|
|
3400
3450
|
const severityIconColor = rule.config.severity === "violation" ? chalk.hex(VIOLATION_COLOR) : chalk.hex(SUGGESTION_COLOR);
|
|
3401
3451
|
const severityText = severityIconColor(severityIcon) + " " + severityColor(rule.config.severity);
|
|
3402
3452
|
const ruleId = formatClickableRuleId(rule.id, rule.internalId);
|
|
3453
|
+
const executionText = rule.config.execution === "llm" ? chalk.hex(LLM_COLOR)("\u25C6") + " " + chalk.hex(LLM_COLOR).bold("llm") : chalk.hex(DETERMINISTIC_COLOR)("\u25C6") + " " + chalk.hex(DETERMINISTIC_COLOR).bold("deterministic");
|
|
3454
|
+
const truncatedMessage = truncateMessage(rule.config.message, messageMaxWidth);
|
|
3403
3455
|
const idPadding = Math.max(0, 12 - rule.id.length);
|
|
3404
3456
|
const severityPadding = Math.max(0, 16 - (rule.config.severity.length + 2));
|
|
3457
|
+
const executionPadding = Math.max(0, 18 - (rule.config.execution.length + 2));
|
|
3405
3458
|
tableData.push([
|
|
3406
3459
|
"",
|
|
3407
|
-
`${ruleId}${" ".repeat(idPadding)} ${chalk.dim("\u2502")} ${severityText}${" ".repeat(severityPadding)} ${chalk.dim("\u2502")} ${
|
|
3460
|
+
`${ruleId}${" ".repeat(idPadding)} ${chalk.dim("\u2502")} ${severityText}${" ".repeat(severityPadding)} ${chalk.dim("\u2502")} ${executionText}${" ".repeat(executionPadding)} ${chalk.dim("\u2502")} ${truncatedMessage}`
|
|
3408
3461
|
]);
|
|
3409
3462
|
}
|
|
3410
3463
|
const table = textTable(tableData, {
|
|
@@ -3819,8 +3872,7 @@ async function loadApiKey() {
|
|
|
3819
3872
|
return null;
|
|
3820
3873
|
}
|
|
3821
3874
|
}
|
|
3822
|
-
async function ensureConfigured() {
|
|
3823
|
-
const environment = new Environment();
|
|
3875
|
+
async function ensureConfigured(environment) {
|
|
3824
3876
|
let apiKey = process.env.WISPBIT_API_KEY || null;
|
|
3825
3877
|
if (!apiKey) {
|
|
3826
3878
|
apiKey = await loadApiKey();
|
|
@@ -3851,7 +3903,7 @@ async function ensureConfigured() {
|
|
|
3851
3903
|
const repositoryUrl = await environment.getRepositoryUrl();
|
|
3852
3904
|
console.log(
|
|
3853
3905
|
chalk4.red(
|
|
3854
|
-
`No repository in wispbit found for url: ${repositoryUrl}. If your git remote URL was recently modified, use "git remote set-url origin <new-url>" to update the remote URL.`
|
|
3906
|
+
`No repository in wispbit found for url: ${repositoryUrl}. If you are passing the repository URL as a flag, make sure it is correct. If your git remote URL was recently modified, use "git remote set-url origin <new-url>" to update the remote URL.`
|
|
3855
3907
|
)
|
|
3856
3908
|
);
|
|
3857
3909
|
process.exit(1);
|
|
@@ -3867,7 +3919,7 @@ async function checkForUpdates() {
|
|
|
3867
3919
|
chalk4.bgHex("#b2f5ea").black.bold(` NEW VERSION AVAILABLE: ${latestCliVersion} (current: ${currentVersion}) `)
|
|
3868
3920
|
);
|
|
3869
3921
|
console.log(
|
|
3870
|
-
chalk4.bgHex("#b2f5ea").black.bold(` Run 'pnpm install -g @wispbit/
|
|
3922
|
+
chalk4.bgHex("#b2f5ea").black.bold(` Run 'pnpm install -g @wispbit/local' to update
|
|
3871
3923
|
`)
|
|
3872
3924
|
);
|
|
3873
3925
|
}
|
|
@@ -3915,6 +3967,7 @@ Diff examples:
|
|
|
3915
3967
|
$ wispbit abc123 --include committed Compare against specific commit SHA, show only committed
|
|
3916
3968
|
|
|
3917
3969
|
Global options:
|
|
3970
|
+
--repo-url <url> Override repository URL (default: from git remote)
|
|
3918
3971
|
-v, --version Show version number
|
|
3919
3972
|
-h, --help Show help
|
|
3920
3973
|
`,
|
|
@@ -3932,6 +3985,10 @@ Global options:
|
|
|
3932
3985
|
include: {
|
|
3933
3986
|
type: "string"
|
|
3934
3987
|
},
|
|
3988
|
+
// Repository URL override
|
|
3989
|
+
repoUrl: {
|
|
3990
|
+
type: "string"
|
|
3991
|
+
},
|
|
3935
3992
|
// Debug option
|
|
3936
3993
|
debug: {
|
|
3937
3994
|
type: "boolean",
|
|
@@ -3952,8 +4009,8 @@ Global options:
|
|
|
3952
4009
|
}
|
|
3953
4010
|
);
|
|
3954
4011
|
async function executeCommand(options) {
|
|
3955
|
-
const environment = new Environment();
|
|
3956
|
-
const config = await ensureConfigured();
|
|
4012
|
+
const environment = new Environment({ repositoryUrl: options.repoUrl });
|
|
4013
|
+
const config = await ensureConfigured(environment);
|
|
3957
4014
|
const { ruleId, json: json2, mode, filePath } = options;
|
|
3958
4015
|
let { commitSelector, diffInclude } = options;
|
|
3959
4016
|
if (mode === "diff") {
|
|
@@ -4119,9 +4176,9 @@ async function executeCommand(options) {
|
|
|
4119
4176
|
}
|
|
4120
4177
|
return results;
|
|
4121
4178
|
}
|
|
4122
|
-
async function listRules() {
|
|
4123
|
-
const
|
|
4124
|
-
const
|
|
4179
|
+
async function listRules(repoUrl) {
|
|
4180
|
+
const environment = new Environment({ repositoryUrl: repoUrl });
|
|
4181
|
+
const config = await ensureConfigured(environment);
|
|
4125
4182
|
const ruleProvider = new WispbitRuleProvider(config, environment);
|
|
4126
4183
|
const rules = await ruleProvider.loadAllRules();
|
|
4127
4184
|
printRulesList(rules);
|
|
@@ -4137,7 +4194,8 @@ async function main() {
|
|
|
4137
4194
|
json: cli.flags.json,
|
|
4138
4195
|
debug: cli.flags.debug,
|
|
4139
4196
|
mode: "check",
|
|
4140
|
-
filePath
|
|
4197
|
+
filePath,
|
|
4198
|
+
repoUrl: cli.flags.repoUrl
|
|
4141
4199
|
});
|
|
4142
4200
|
break;
|
|
4143
4201
|
}
|
|
@@ -4165,17 +4223,18 @@ async function main() {
|
|
|
4165
4223
|
debug: cli.flags.debug,
|
|
4166
4224
|
mode: "diff",
|
|
4167
4225
|
diffInclude,
|
|
4168
|
-
commitSelector
|
|
4226
|
+
commitSelector,
|
|
4227
|
+
repoUrl: cli.flags.repoUrl
|
|
4169
4228
|
});
|
|
4170
4229
|
break;
|
|
4171
4230
|
}
|
|
4172
4231
|
case "list": {
|
|
4173
|
-
await listRules();
|
|
4232
|
+
await listRules(cli.flags.repoUrl);
|
|
4174
4233
|
break;
|
|
4175
4234
|
}
|
|
4176
4235
|
case "cache": {
|
|
4177
4236
|
if (subcommand === "purge") {
|
|
4178
|
-
const environment = new Environment();
|
|
4237
|
+
const environment = new Environment({ repositoryUrl: cli.flags.repoUrl });
|
|
4179
4238
|
const storage = new Storage(environment);
|
|
4180
4239
|
const result = await storage.purgeCache();
|
|
4181
4240
|
console.log(
|
|
@@ -4213,7 +4272,8 @@ ${chalk4.green("Cache purged successfully.")} Removed ${result.deletedCount} ite
|
|
|
4213
4272
|
debug: cli.flags.debug,
|
|
4214
4273
|
mode: "diff",
|
|
4215
4274
|
diffInclude,
|
|
4216
|
-
commitSelector
|
|
4275
|
+
commitSelector,
|
|
4276
|
+
repoUrl: cli.flags.repoUrl
|
|
4217
4277
|
});
|
|
4218
4278
|
break;
|
|
4219
4279
|
}
|