@getcodesentinel/codesentinel 1.9.4 → 1.9.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/dist/index.js +117 -90
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -254,6 +254,46 @@ var DEFAULT_EXTERNAL_ANALYSIS_CONFIG = {
|
|
|
254
254
|
maxHighRiskDependencies: 100,
|
|
255
255
|
metadataRequestConcurrency: 8
|
|
256
256
|
};
|
|
257
|
+
var mapWithConcurrency = async (values, limit, handler) => {
|
|
258
|
+
const effectiveLimit = Math.max(1, limit);
|
|
259
|
+
const workerCount = Math.min(effectiveLimit, values.length);
|
|
260
|
+
const results = new Array(values.length);
|
|
261
|
+
let index = 0;
|
|
262
|
+
const workers = Array.from({ length: workerCount }, async () => {
|
|
263
|
+
while (true) {
|
|
264
|
+
const current = index;
|
|
265
|
+
index += 1;
|
|
266
|
+
if (current >= values.length) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const value = values[current];
|
|
270
|
+
if (value !== void 0) {
|
|
271
|
+
results[current] = await handler(value);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
await Promise.all(workers);
|
|
276
|
+
return results;
|
|
277
|
+
};
|
|
278
|
+
var collectDependencyMetadata = async (extraction, metadataProvider, concurrency, onProgress) => {
|
|
279
|
+
const directNames = new Set(extraction.directDependencies.map((dependency) => dependency.name));
|
|
280
|
+
let completed = 0;
|
|
281
|
+
return mapWithConcurrency(extraction.nodes, concurrency, async (node) => {
|
|
282
|
+
const result = {
|
|
283
|
+
key: `${node.name}@${node.version}`,
|
|
284
|
+
metadata: await metadataProvider.getMetadata(node.name, node.version, {
|
|
285
|
+
directDependency: directNames.has(node.name)
|
|
286
|
+
})
|
|
287
|
+
};
|
|
288
|
+
completed += 1;
|
|
289
|
+
onProgress?.({
|
|
290
|
+
completed,
|
|
291
|
+
total: extraction.nodes.length,
|
|
292
|
+
packageName: node.name
|
|
293
|
+
});
|
|
294
|
+
return result;
|
|
295
|
+
});
|
|
296
|
+
};
|
|
257
297
|
var LOCKFILE_CANDIDATES = [
|
|
258
298
|
{ fileName: "pnpm-lock.yaml", kind: "pnpm" },
|
|
259
299
|
{ fileName: "package-lock.json", kind: "npm" },
|
|
@@ -545,6 +585,24 @@ var parseYarnLock = (raw, directSpecs) => {
|
|
|
545
585
|
var parseBunLock = (_raw, _directSpecs) => {
|
|
546
586
|
throw new Error("unsupported_lockfile_format");
|
|
547
587
|
};
|
|
588
|
+
var parseLockfileExtraction = (lockfileKind, lockfileRaw, directSpecs) => {
|
|
589
|
+
switch (lockfileKind) {
|
|
590
|
+
case "pnpm":
|
|
591
|
+
return parsePnpmLockfile(lockfileRaw, directSpecs);
|
|
592
|
+
case "npm":
|
|
593
|
+
case "npm-shrinkwrap":
|
|
594
|
+
return {
|
|
595
|
+
...parsePackageLock(lockfileRaw, directSpecs),
|
|
596
|
+
kind: lockfileKind
|
|
597
|
+
};
|
|
598
|
+
case "yarn":
|
|
599
|
+
return parseYarnLock(lockfileRaw, directSpecs);
|
|
600
|
+
case "bun":
|
|
601
|
+
return parseBunLock(lockfileRaw, directSpecs);
|
|
602
|
+
default:
|
|
603
|
+
throw new Error("unsupported_lockfile_format");
|
|
604
|
+
}
|
|
605
|
+
};
|
|
548
606
|
var parseRetryAfterMs = (value) => {
|
|
549
607
|
if (value === null) {
|
|
550
608
|
return null;
|
|
@@ -977,77 +1035,31 @@ var resolveRegistryGraphFromDirectSpecs = async (directSpecs, options) => {
|
|
|
977
1035
|
truncated
|
|
978
1036
|
};
|
|
979
1037
|
};
|
|
980
|
-
var
|
|
981
|
-
|
|
982
|
-
...overrides
|
|
983
|
-
});
|
|
984
|
-
var parseExtraction = (lockfileKind, lockfileRaw, directSpecs) => {
|
|
985
|
-
switch (lockfileKind) {
|
|
986
|
-
case "pnpm":
|
|
987
|
-
return parsePnpmLockfile(lockfileRaw, directSpecs);
|
|
988
|
-
case "npm":
|
|
989
|
-
case "npm-shrinkwrap":
|
|
990
|
-
return {
|
|
991
|
-
...parsePackageLock(lockfileRaw, directSpecs),
|
|
992
|
-
kind: lockfileKind
|
|
993
|
-
};
|
|
994
|
-
case "yarn":
|
|
995
|
-
return parseYarnLock(lockfileRaw, directSpecs);
|
|
996
|
-
case "bun":
|
|
997
|
-
return parseBunLock(lockfileRaw, directSpecs);
|
|
998
|
-
default:
|
|
999
|
-
throw new Error("unsupported_lockfile_format");
|
|
1000
|
-
}
|
|
1001
|
-
};
|
|
1002
|
-
var mapWithConcurrency = async (values, limit, handler) => {
|
|
1003
|
-
const effectiveLimit = Math.max(1, limit);
|
|
1004
|
-
const workerCount = Math.min(effectiveLimit, values.length);
|
|
1005
|
-
const results = new Array(values.length);
|
|
1006
|
-
let index = 0;
|
|
1007
|
-
const workers = Array.from({ length: workerCount }, async () => {
|
|
1008
|
-
while (true) {
|
|
1009
|
-
const current = index;
|
|
1010
|
-
index += 1;
|
|
1011
|
-
if (current >= values.length) {
|
|
1012
|
-
return;
|
|
1013
|
-
}
|
|
1014
|
-
const value = values[current];
|
|
1015
|
-
if (value !== void 0) {
|
|
1016
|
-
results[current] = await handler(value);
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
});
|
|
1020
|
-
await Promise.all(workers);
|
|
1021
|
-
return results;
|
|
1022
|
-
};
|
|
1023
|
-
var analyzeDependencyExposure = async (input, metadataProvider, onProgress) => {
|
|
1024
|
-
const config = withDefaults(input.config);
|
|
1025
|
-
const packageJson = loadPackageJson(input.repositoryPath);
|
|
1038
|
+
var prepareDependencyExtraction = async (repositoryPath) => {
|
|
1039
|
+
const packageJson = loadPackageJson(repositoryPath);
|
|
1026
1040
|
if (packageJson === null) {
|
|
1027
1041
|
return {
|
|
1028
|
-
targetPath: input.repositoryPath,
|
|
1029
1042
|
available: false,
|
|
1030
1043
|
reason: "package_json_not_found"
|
|
1031
1044
|
};
|
|
1032
1045
|
}
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
const
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
extraction = {
|
|
1046
|
+
const directSpecs = parsePackageJson(packageJson.raw);
|
|
1047
|
+
const lockfile = selectLockfile(repositoryPath);
|
|
1048
|
+
if (lockfile === null) {
|
|
1049
|
+
const resolvedGraph = await resolveRegistryGraphFromDirectSpecs(directSpecs, {
|
|
1050
|
+
maxNodes: 500,
|
|
1051
|
+
maxDepth: 8
|
|
1052
|
+
});
|
|
1053
|
+
if (resolvedGraph.nodes.length === 0) {
|
|
1054
|
+
return {
|
|
1055
|
+
available: false,
|
|
1056
|
+
reason: "lockfile_not_found"
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
return {
|
|
1060
|
+
available: true,
|
|
1061
|
+
lockfileKind: "npm",
|
|
1062
|
+
extraction: {
|
|
1051
1063
|
kind: "npm",
|
|
1052
1064
|
directDependencies: resolvedGraph.directDependencies.map((dependency) => ({
|
|
1053
1065
|
name: dependency.name,
|
|
@@ -1055,46 +1067,61 @@ var analyzeDependencyExposure = async (input, metadataProvider, onProgress) => {
|
|
|
1055
1067
|
scope: dependency.scope
|
|
1056
1068
|
})),
|
|
1057
1069
|
nodes: resolvedGraph.nodes
|
|
1070
|
+
}
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
return {
|
|
1074
|
+
available: true,
|
|
1075
|
+
lockfileKind: lockfile.kind,
|
|
1076
|
+
extraction: parseLockfileExtraction(lockfile.kind, lockfile.raw, directSpecs)
|
|
1077
|
+
};
|
|
1078
|
+
};
|
|
1079
|
+
var withDefaults = (overrides) => ({
|
|
1080
|
+
...DEFAULT_EXTERNAL_ANALYSIS_CONFIG,
|
|
1081
|
+
...overrides
|
|
1082
|
+
});
|
|
1083
|
+
var analyzeDependencyExposure = async (input, metadataProvider, onProgress) => {
|
|
1084
|
+
const config = withDefaults(input.config);
|
|
1085
|
+
try {
|
|
1086
|
+
const prepared = await prepareDependencyExtraction(input.repositoryPath);
|
|
1087
|
+
if (!prepared.available) {
|
|
1088
|
+
return {
|
|
1089
|
+
targetPath: input.repositoryPath,
|
|
1090
|
+
available: false,
|
|
1091
|
+
reason: prepared.reason
|
|
1058
1092
|
};
|
|
1059
|
-
onProgress?.({ stage: "lockfile_selected", kind: "npm" });
|
|
1060
|
-
} else {
|
|
1061
|
-
extraction = parseExtraction(lockfile.kind, lockfile.raw, directSpecs);
|
|
1062
|
-
onProgress?.({ stage: "lockfile_selected", kind: lockfile.kind });
|
|
1063
1093
|
}
|
|
1064
|
-
|
|
1094
|
+
onProgress?.({ stage: "package_json_loaded" });
|
|
1095
|
+
onProgress?.({ stage: "lockfile_selected", kind: prepared.lockfileKind });
|
|
1096
|
+
const { extraction } = prepared;
|
|
1065
1097
|
onProgress?.({
|
|
1066
1098
|
stage: "lockfile_parsed",
|
|
1067
1099
|
dependencyNodes: extraction.nodes.length,
|
|
1068
1100
|
directDependencies: extraction.directDependencies.length
|
|
1069
1101
|
});
|
|
1070
1102
|
onProgress?.({ stage: "metadata_fetch_started", total: extraction.nodes.length });
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1103
|
+
const metadataEntries = await collectDependencyMetadata(
|
|
1104
|
+
extraction,
|
|
1105
|
+
metadataProvider,
|
|
1074
1106
|
config.metadataRequestConcurrency,
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
};
|
|
1082
|
-
completed += 1;
|
|
1083
|
-
onProgress?.({
|
|
1084
|
-
stage: "metadata_fetch_progress",
|
|
1085
|
-
completed,
|
|
1086
|
-
total: extraction.nodes.length,
|
|
1087
|
-
packageName: node.name
|
|
1088
|
-
});
|
|
1089
|
-
return result;
|
|
1090
|
-
}
|
|
1107
|
+
(event) => onProgress?.({
|
|
1108
|
+
stage: "metadata_fetch_progress",
|
|
1109
|
+
completed: event.completed,
|
|
1110
|
+
total: event.total,
|
|
1111
|
+
packageName: event.packageName
|
|
1112
|
+
})
|
|
1091
1113
|
);
|
|
1092
1114
|
onProgress?.({ stage: "metadata_fetch_completed", total: extraction.nodes.length });
|
|
1093
1115
|
const metadataByKey = /* @__PURE__ */ new Map();
|
|
1094
1116
|
for (const entry of metadataEntries) {
|
|
1095
1117
|
metadataByKey.set(entry.key, entry.metadata);
|
|
1096
1118
|
}
|
|
1097
|
-
const summary = buildExternalAnalysisSummary(
|
|
1119
|
+
const summary = buildExternalAnalysisSummary(
|
|
1120
|
+
input.repositoryPath,
|
|
1121
|
+
extraction,
|
|
1122
|
+
metadataByKey,
|
|
1123
|
+
config
|
|
1124
|
+
);
|
|
1098
1125
|
if (summary.available) {
|
|
1099
1126
|
onProgress?.({
|
|
1100
1127
|
stage: "summary_built",
|