seaworthycode 1.2.8 → 1.2.10
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/index.js +76 -45
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -782,6 +782,7 @@ var copy = {
|
|
|
782
782
|
"report.bySeverity": "By severity",
|
|
783
783
|
"report.tierWatermark": (licensedTo) => `\u2693 Pro \xB7 ${licensedTo}`,
|
|
784
784
|
"report.scanProgress.starting": (targetDir) => `\u2693 Scanning ${targetDir}...`,
|
|
785
|
+
"report.scanProgress.checking": (completed, total, checkName) => `\u2693 Running checks... [${completed}/${total}] ${checkName}`,
|
|
785
786
|
"report.scanProgress.category": (label, count) => count > 0 ? ` \u2693 ${label} \u2014 ${count} issue(s)` : ` \u2693 ${label} \u2713`,
|
|
786
787
|
"report.licenseNotice": (licensedTo) => `Licensed to ${licensedTo}`,
|
|
787
788
|
"report.cta.clean": `\u2713 All clear \u2014 your project is shipshape!`,
|
|
@@ -1621,6 +1622,12 @@ var ScanRunner = class {
|
|
|
1621
1622
|
};
|
|
1622
1623
|
const results = [];
|
|
1623
1624
|
const checkResults = /* @__PURE__ */ new Map();
|
|
1625
|
+
const categoryTotals = /* @__PURE__ */ new Map();
|
|
1626
|
+
for (const check2 of checks) {
|
|
1627
|
+
categoryTotals.set(check2.category, (categoryTotals.get(check2.category) ?? 0) + 1);
|
|
1628
|
+
}
|
|
1629
|
+
const categoryCompleted = /* @__PURE__ */ new Map();
|
|
1630
|
+
let completedCount = 0;
|
|
1624
1631
|
await runWithConcurrency(
|
|
1625
1632
|
checks,
|
|
1626
1633
|
async (check2) => {
|
|
@@ -1630,26 +1637,26 @@ var ScanRunner = class {
|
|
|
1630
1637
|
} catch (err) {
|
|
1631
1638
|
console.error(`Check "${check2.id}" failed: ${String(err)}`);
|
|
1632
1639
|
}
|
|
1640
|
+
options.onCheckComplete?.(++completedCount, checks.length, check2.name);
|
|
1641
|
+
if (options.onCategoryComplete) {
|
|
1642
|
+
const catDone = (categoryCompleted.get(check2.category) ?? 0) + 1;
|
|
1643
|
+
categoryCompleted.set(check2.category, catDone);
|
|
1644
|
+
if (catDone === categoryTotals.get(check2.category)) {
|
|
1645
|
+
let catFindingsCount = 0;
|
|
1646
|
+
for (const c of checks) {
|
|
1647
|
+
if (c.category === check2.category) {
|
|
1648
|
+
catFindingsCount += (checkResults.get(c.id) ?? []).length;
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
options.onCategoryComplete(check2.category, catFindingsCount);
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1633
1654
|
},
|
|
1634
1655
|
concurrency
|
|
1635
1656
|
);
|
|
1636
1657
|
for (const check2 of checks) {
|
|
1637
1658
|
results.push(...checkResults.get(check2.id) ?? []);
|
|
1638
1659
|
}
|
|
1639
|
-
if (options.onCategoryComplete) {
|
|
1640
|
-
const findingsPerCategory = /* @__PURE__ */ new Map();
|
|
1641
|
-
for (const check2 of checks) {
|
|
1642
|
-
const count = (checkResults.get(check2.id) ?? []).length;
|
|
1643
|
-
findingsPerCategory.set(check2.category, (findingsPerCategory.get(check2.category) ?? 0) + count);
|
|
1644
|
-
}
|
|
1645
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1646
|
-
for (const check2 of checks) {
|
|
1647
|
-
if (!seen.has(check2.category)) {
|
|
1648
|
-
seen.add(check2.category);
|
|
1649
|
-
options.onCategoryComplete(check2.category, findingsPerCategory.get(check2.category) ?? 0);
|
|
1650
|
-
}
|
|
1651
|
-
}
|
|
1652
|
-
}
|
|
1653
1660
|
ctx.astCache?.clear();
|
|
1654
1661
|
for (const [, promise] of ctx.bashAstCache ?? []) {
|
|
1655
1662
|
try {
|
|
@@ -15996,9 +16003,9 @@ function createCommand(definition, options) {
|
|
|
15996
16003
|
}
|
|
15997
16004
|
|
|
15998
16005
|
// src/commands/scan.ts
|
|
15999
|
-
var
|
|
16000
|
-
var
|
|
16001
|
-
function
|
|
16006
|
+
var FREE_CHECK_IDLE_MS = 6e4;
|
|
16007
|
+
var PRO_CHECK_IDLE_MS = 3e5;
|
|
16008
|
+
function resolveCheckIdleMs(tier) {
|
|
16002
16009
|
const env2 = process.env.SEAWORTHY_SCAN_TIMEOUT_MS;
|
|
16003
16010
|
if (env2) {
|
|
16004
16011
|
const parsed = Number(env2);
|
|
@@ -16006,7 +16013,7 @@ function resolveScanTimeoutMs(tier) {
|
|
|
16006
16013
|
return parsed;
|
|
16007
16014
|
}
|
|
16008
16015
|
}
|
|
16009
|
-
return tier === "free" ?
|
|
16016
|
+
return tier === "free" ? FREE_CHECK_IDLE_MS : PRO_CHECK_IDLE_MS;
|
|
16010
16017
|
}
|
|
16011
16018
|
var CATEGORY_LABELS = {
|
|
16012
16019
|
security: getCopy2("cli.category.security"),
|
|
@@ -16016,17 +16023,29 @@ var CATEGORY_LABELS = {
|
|
|
16016
16023
|
configuration: getCopy2("cli.category.configuration"),
|
|
16017
16024
|
"data-exposure": getCopy2("cli.category.data-exposure")
|
|
16018
16025
|
};
|
|
16019
|
-
function
|
|
16020
|
-
|
|
16021
|
-
|
|
16022
|
-
|
|
16023
|
-
|
|
16024
|
-
|
|
16025
|
-
|
|
16026
|
-
|
|
16027
|
-
|
|
16028
|
-
|
|
16026
|
+
function withIdleTimeout(promise, idleMs, message) {
|
|
16027
|
+
let timerId;
|
|
16028
|
+
let rejectFn = () => {
|
|
16029
|
+
};
|
|
16030
|
+
const heartbeat = () => {
|
|
16031
|
+
clearTimeout(timerId);
|
|
16032
|
+
timerId = setTimeout(() => rejectFn(new Error(message)), idleMs);
|
|
16033
|
+
};
|
|
16034
|
+
const wrappedPromise = new Promise((resolve5, reject) => {
|
|
16035
|
+
rejectFn = reject;
|
|
16036
|
+
heartbeat();
|
|
16037
|
+
promise.then(
|
|
16038
|
+
(value) => {
|
|
16039
|
+
clearTimeout(timerId);
|
|
16040
|
+
resolve5(value);
|
|
16041
|
+
},
|
|
16042
|
+
(err) => {
|
|
16043
|
+
clearTimeout(timerId);
|
|
16044
|
+
reject(err);
|
|
16045
|
+
}
|
|
16046
|
+
);
|
|
16029
16047
|
});
|
|
16048
|
+
return { promise: wrappedPromise, heartbeat };
|
|
16030
16049
|
}
|
|
16031
16050
|
function isInsideDirectory(outputPath, targetDir) {
|
|
16032
16051
|
const resolvedOutput = resolve2(outputPath);
|
|
@@ -16058,24 +16077,36 @@ async function executeScan(args, ctx) {
|
|
|
16058
16077
|
process.stderr.write(getCopy("report.scanProgress.starting", args.targetDir) + "\n");
|
|
16059
16078
|
}
|
|
16060
16079
|
const runner = new ScanRunner();
|
|
16061
|
-
const
|
|
16062
|
-
|
|
16063
|
-
|
|
16064
|
-
|
|
16065
|
-
|
|
16066
|
-
|
|
16067
|
-
|
|
16068
|
-
|
|
16069
|
-
|
|
16070
|
-
|
|
16071
|
-
|
|
16072
|
-
|
|
16073
|
-
|
|
16074
|
-
|
|
16075
|
-
|
|
16076
|
-
|
|
16077
|
-
|
|
16080
|
+
const checkIdleMs = resolveCheckIdleMs(ctx.tier);
|
|
16081
|
+
let heartbeat = () => {
|
|
16082
|
+
};
|
|
16083
|
+
const scanPromise = runner.run({
|
|
16084
|
+
targetDir: args.targetDir,
|
|
16085
|
+
tier: ctx.tier,
|
|
16086
|
+
llm,
|
|
16087
|
+
maxFileSize: args.maxFileSize,
|
|
16088
|
+
debug: args.debug,
|
|
16089
|
+
baseline: args.baseline,
|
|
16090
|
+
minConfidence: args.minConfidence,
|
|
16091
|
+
onCheckComplete: (completed, total, checkName) => {
|
|
16092
|
+
heartbeat();
|
|
16093
|
+
if (showProgress) {
|
|
16094
|
+
process.stderr.write(`\r${getCopy("report.scanProgress.checking", completed, total, checkName)}\x1B[K`);
|
|
16095
|
+
}
|
|
16096
|
+
},
|
|
16097
|
+
onCategoryComplete: showProgress ? (category, count) => {
|
|
16098
|
+
const label = CATEGORY_LABELS[category] ?? category;
|
|
16099
|
+
process.stderr.write(`\r\x1B[K${getCopy("report.scanProgress.category", label, count)}
|
|
16100
|
+
`);
|
|
16101
|
+
} : void 0
|
|
16102
|
+
});
|
|
16103
|
+
const { promise: timedScanPromise, heartbeat: hb } = withIdleTimeout(
|
|
16104
|
+
scanPromise,
|
|
16105
|
+
checkIdleMs,
|
|
16106
|
+
getCopy("errors.scan.timed_out", Math.round(checkIdleMs / 1e3))
|
|
16078
16107
|
);
|
|
16108
|
+
heartbeat = hb;
|
|
16109
|
+
const result = await timedScanPromise;
|
|
16079
16110
|
const reportInput = {
|
|
16080
16111
|
findings: result.findings,
|
|
16081
16112
|
targetDir: args.targetDir,
|