@securecode-ai/mcp 0.2.1 → 0.3.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/dependency/depCache.d.ts +22 -0
- package/dist/dependency/depCache.js +115 -0
- package/dist/dependency/depCache.js.map +1 -0
- package/dist/dependency/dependencyChecker.d.ts +48 -0
- package/dist/dependency/dependencyChecker.js +196 -0
- package/dist/dependency/dependencyChecker.js.map +1 -0
- package/dist/dependency/finding.d.ts +42 -0
- package/dist/dependency/finding.js +13 -0
- package/dist/dependency/finding.js.map +1 -0
- package/dist/dependency/licensePolicy.d.ts +56 -0
- package/dist/dependency/licensePolicy.js +109 -0
- package/dist/dependency/licensePolicy.js.map +1 -0
- package/dist/dependency/minSafeVersion.d.ts +32 -0
- package/dist/dependency/minSafeVersion.js +125 -0
- package/dist/dependency/minSafeVersion.js.map +1 -0
- package/dist/dependency/osvClient.d.ts +45 -0
- package/dist/dependency/osvClient.js +443 -0
- package/dist/dependency/osvClient.js.map +1 -0
- package/dist/dependency/parsers/npm.d.ts +13 -0
- package/dist/dependency/parsers/npm.js +160 -0
- package/dist/dependency/parsers/npm.js.map +1 -0
- package/dist/dependency/parsers/pipfile.d.ts +8 -0
- package/dist/dependency/parsers/pipfile.js +110 -0
- package/dist/dependency/parsers/pipfile.js.map +1 -0
- package/dist/dependency/parsers/pnpm.d.ts +11 -0
- package/dist/dependency/parsers/pnpm.js +148 -0
- package/dist/dependency/parsers/pnpm.js.map +1 -0
- package/dist/dependency/parsers/requirements.d.ts +24 -0
- package/dist/dependency/parsers/requirements.js +153 -0
- package/dist/dependency/parsers/requirements.js.map +1 -0
- package/dist/dependency/parsers/yarn.d.ts +10 -0
- package/dist/dependency/parsers/yarn.js +153 -0
- package/dist/dependency/parsers/yarn.js.map +1 -0
- package/dist/dependency/resolver.d.ts +28 -0
- package/dist/dependency/resolver.js +159 -0
- package/dist/dependency/resolver.js.map +1 -0
- package/dist/dependency/types.d.ts +85 -0
- package/dist/dependency/types.js +11 -0
- package/dist/dependency/types.js.map +1 -0
- package/dist/mcp/server.js +2 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools.js +8 -0
- package/dist/mcp/tools.js.map +1 -1
- package/dist/tools/scanDependencies.d.ts +11 -0
- package/dist/tools/scanDependencies.js +37 -0
- package/dist/tools/scanDependencies.js.map +1 -0
- package/package.json +9 -2
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ParsedLockfile } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a package-lock.json (npm v2/v3, lockfileVersion >= 2).
|
|
4
|
+
*
|
|
5
|
+
* npm lockfiles already contain the fully-resolved transitive tree — every
|
|
6
|
+
* installed package (direct and transitive) is a `packages.*` entry with a
|
|
7
|
+
* resolved `version`. The resolver therefore does not need to hit the
|
|
8
|
+
* network; it just walks `packages`.
|
|
9
|
+
*
|
|
10
|
+
* v1 (lockfileVersion 1) uses a `dependencies` tree instead; we support it
|
|
11
|
+
* too, recursively.
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseNpmLockfile(lockfilePath: string): ParsedLockfile | null;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.parseNpmLockfile = parseNpmLockfile;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
/**
|
|
40
|
+
* Parse a package-lock.json (npm v2/v3, lockfileVersion >= 2).
|
|
41
|
+
*
|
|
42
|
+
* npm lockfiles already contain the fully-resolved transitive tree — every
|
|
43
|
+
* installed package (direct and transitive) is a `packages.*` entry with a
|
|
44
|
+
* resolved `version`. The resolver therefore does not need to hit the
|
|
45
|
+
* network; it just walks `packages`.
|
|
46
|
+
*
|
|
47
|
+
* v1 (lockfileVersion 1) uses a `dependencies` tree instead; we support it
|
|
48
|
+
* too, recursively.
|
|
49
|
+
*/
|
|
50
|
+
function parseNpmLockfile(lockfilePath) {
|
|
51
|
+
let raw;
|
|
52
|
+
try {
|
|
53
|
+
raw = fs.readFileSync(lockfilePath, 'utf8');
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
let data;
|
|
59
|
+
try {
|
|
60
|
+
data = JSON.parse(raw);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const manifestPath = path.join(path.dirname(lockfilePath), 'package.json');
|
|
66
|
+
let projectLicense;
|
|
67
|
+
try {
|
|
68
|
+
const pkg = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
69
|
+
if (typeof pkg.license === 'string')
|
|
70
|
+
projectLicense = pkg.license;
|
|
71
|
+
else if (pkg.license && typeof pkg.license === 'object' && typeof pkg.license.type === 'string') {
|
|
72
|
+
projectLicense = pkg.license.type;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// package.json optional; ignore
|
|
77
|
+
}
|
|
78
|
+
const packages = [];
|
|
79
|
+
const seen = new Set();
|
|
80
|
+
const lockfileVersion = typeof data.lockfileVersion === 'number' ? data.lockfileVersion : 0;
|
|
81
|
+
if (lockfileVersion >= 2 && data.packages) {
|
|
82
|
+
// v2/v3: keyed by install path, `node_modules/<name>`.
|
|
83
|
+
for (const [key, entry] of Object.entries(data.packages)) {
|
|
84
|
+
// The root project itself is keyed by "" — skip it.
|
|
85
|
+
if (key === '')
|
|
86
|
+
continue;
|
|
87
|
+
// Extract the package name from the path. Scoped packages live at
|
|
88
|
+
// `node_modules/@scope/name`. Optional deps may have their own paths.
|
|
89
|
+
const nmIdx = key.indexOf('node_modules/');
|
|
90
|
+
if (nmIdx < 0)
|
|
91
|
+
continue;
|
|
92
|
+
const name = key.slice(nmIdx + 'node_modules/'.length);
|
|
93
|
+
// Nested node_modules paths (e.g. "node_modules/a/node_modules/b")
|
|
94
|
+
// describe a deduped alternative install; the canonical entry is the
|
|
95
|
+
// top-level one. We keep the first occurrence per name+version.
|
|
96
|
+
if (entry.link === true)
|
|
97
|
+
continue; // symlinked, not a real install
|
|
98
|
+
const version = entry.version;
|
|
99
|
+
if (!version)
|
|
100
|
+
continue;
|
|
101
|
+
const id = `${name}@${version}`;
|
|
102
|
+
if (seen.has(id))
|
|
103
|
+
continue;
|
|
104
|
+
seen.add(id);
|
|
105
|
+
packages.push({
|
|
106
|
+
ecosystem: 'npm',
|
|
107
|
+
name,
|
|
108
|
+
version,
|
|
109
|
+
license: typeof entry.license === 'string' ? entry.license : undefined,
|
|
110
|
+
manifestPath,
|
|
111
|
+
direct: entry.dev === undefined && entry.optional === undefined
|
|
112
|
+
? isDirectNpm(key)
|
|
113
|
+
: false,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else if (data.dependencies) {
|
|
118
|
+
// v1: recursive `dependencies` tree.
|
|
119
|
+
walkNpmV1(data.dependencies, '', manifestPath, packages, seen);
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
ecosystem: 'npm',
|
|
123
|
+
lockfilePath,
|
|
124
|
+
manifestPath,
|
|
125
|
+
packages,
|
|
126
|
+
projectLicense,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function walkNpmV1(deps, parentPath, manifestPath, out, seen) {
|
|
130
|
+
for (const [name, entry] of Object.entries(deps || {})) {
|
|
131
|
+
const version = entry && entry.version;
|
|
132
|
+
if (!version)
|
|
133
|
+
continue;
|
|
134
|
+
const id = `${name}@${version}`;
|
|
135
|
+
if (!seen.has(id)) {
|
|
136
|
+
seen.add(id);
|
|
137
|
+
out.push({
|
|
138
|
+
ecosystem: 'npm',
|
|
139
|
+
name,
|
|
140
|
+
version,
|
|
141
|
+
license: entry && typeof entry.license === 'string' ? entry.license : undefined,
|
|
142
|
+
manifestPath,
|
|
143
|
+
direct: parentPath === '',
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
if (entry && entry.dependencies) {
|
|
147
|
+
walkNpmV1(entry.dependencies, `${parentPath}${name}/`, manifestPath, out, seen);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Best-effort: did this `packages` key correspond to a top-level dependency?
|
|
153
|
+
* Top-level keys look exactly like `node_modules/<name>` (no nested node_modules).
|
|
154
|
+
*/
|
|
155
|
+
function isDirectNpm(key) {
|
|
156
|
+
const nmIdx = key.indexOf('node_modules/');
|
|
157
|
+
const tail = key.slice(nmIdx + 'node_modules/'.length);
|
|
158
|
+
return !tail.includes('node_modules/');
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=npm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm.js","sourceRoot":"","sources":["../../../src/dependency/parsers/npm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ParsedLockfile } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a `Pipfile.lock` (Pipenv). It is a JSON document with two top-level
|
|
4
|
+
* sections, `default` and `develop`, each keyed by package name with `version`
|
|
5
|
+
* (without leading `==`) and optional `hashes`. Both sections contain the
|
|
6
|
+
* resolved transitive tree, so we walk them and return everything.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parsePipfileLock(lockfilePath: string): ParsedLockfile | null;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.parsePipfileLock = parsePipfileLock;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const requirements_1 = require("./requirements");
|
|
40
|
+
/**
|
|
41
|
+
* Parse a `Pipfile.lock` (Pipenv). It is a JSON document with two top-level
|
|
42
|
+
* sections, `default` and `develop`, each keyed by package name with `version`
|
|
43
|
+
* (without leading `==`) and optional `hashes`. Both sections contain the
|
|
44
|
+
* resolved transitive tree, so we walk them and return everything.
|
|
45
|
+
*/
|
|
46
|
+
function parsePipfileLock(lockfilePath) {
|
|
47
|
+
let raw;
|
|
48
|
+
try {
|
|
49
|
+
raw = fs.readFileSync(lockfilePath, 'utf8');
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
let data;
|
|
55
|
+
try {
|
|
56
|
+
data = JSON.parse(raw);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
if (!data || typeof data !== 'object')
|
|
62
|
+
return null;
|
|
63
|
+
const manifestPath = path.join(path.dirname(lockfilePath), 'Pipfile');
|
|
64
|
+
let projectLicense;
|
|
65
|
+
try {
|
|
66
|
+
const pipfile = fs.readFileSync(manifestPath, 'utf8');
|
|
67
|
+
// Pipfile is TOML; we don't depend on a TOML parser. Best-effort regex
|
|
68
|
+
// for the top-level `license = "..."` line.
|
|
69
|
+
const m = pipfile.match(/^\s*license\s*=\s*"([^"]+)"/m);
|
|
70
|
+
if (m)
|
|
71
|
+
projectLicense = m[1];
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// optional
|
|
75
|
+
}
|
|
76
|
+
const packages = [];
|
|
77
|
+
const seen = new Set();
|
|
78
|
+
for (const section of ['default', 'develop']) {
|
|
79
|
+
const deps = data[section];
|
|
80
|
+
if (!deps || typeof deps !== 'object')
|
|
81
|
+
continue;
|
|
82
|
+
for (const [rawName, entry] of Object.entries(deps)) {
|
|
83
|
+
const name = (0, requirements_1.normalizePipName)(rawName);
|
|
84
|
+
const version = entry && typeof entry.version === 'string'
|
|
85
|
+
? entry.version.replace(/^==/, '')
|
|
86
|
+
: undefined;
|
|
87
|
+
if (!version)
|
|
88
|
+
continue;
|
|
89
|
+
const id = `${name}@${version}`;
|
|
90
|
+
if (seen.has(id))
|
|
91
|
+
continue;
|
|
92
|
+
seen.add(id);
|
|
93
|
+
packages.push({
|
|
94
|
+
ecosystem: 'pipenv',
|
|
95
|
+
name,
|
|
96
|
+
version,
|
|
97
|
+
manifestPath,
|
|
98
|
+
direct: section === 'default',
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
ecosystem: 'pipenv',
|
|
104
|
+
lockfilePath,
|
|
105
|
+
manifestPath,
|
|
106
|
+
packages,
|
|
107
|
+
projectLicense,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=pipfile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipfile.js","sourceRoot":"","sources":["../../../src/dependency/parsers/pipfile.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,4CA2DC;AAtED,uCAAyB;AACzB,2CAA6B;AAE7B,iDAAkD;AAElD;;;;;GAKG;AACH,SAAgB,gBAAgB,CAAC,YAAoB;IACjD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACD,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,IAAS,CAAC;IACd,IAAI,CAAC;QACD,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAEnD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC,CAAC;IACtE,IAAI,cAAkC,CAAC;IACvC,IAAI,CAAC;QACD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACtD,uEAAuE;QACvE,4CAA4C;QAC5C,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACxD,IAAI,CAAC;YAAE,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACL,WAAW;IACf,CAAC;IAED,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,OAAO,IAAI,CAAC,SAAS,EAAE,SAAS,CAAU,EAAE,CAAC;QACpD,MAAM,IAAI,GAAoC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,SAAS;QAChD,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,GAAG,IAAA,+BAAgB,EAAC,OAAO,CAAC,CAAC;YACvC,MAAM,OAAO,GAAuB,KAAK,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;gBAC1E,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;gBAClC,CAAC,CAAC,SAAS,CAAC;YAChB,IAAI,CAAC,OAAO;gBAAE,SAAS;YACvB,MAAM,EAAE,GAAG,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC;YAChC,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,SAAS;YAC3B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC;gBACV,SAAS,EAAE,QAAQ;gBACnB,IAAI;gBACJ,OAAO;gBACP,YAAY;gBACZ,MAAM,EAAE,OAAO,KAAK,SAAS;aAChC,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,OAAO;QACH,SAAS,EAAE,QAAQ;QACnB,YAAY;QACZ,YAAY;QACZ,QAAQ;QACR,cAAc;KACjB,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ParsedLockfile } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a pnpm-lock.yaml (v6+).
|
|
4
|
+
*
|
|
5
|
+
* pnpm lockfiles contain the resolved transitive tree under `packages`,
|
|
6
|
+
* keyed as `<name>@<version>` (with optional peer suffixes). We walk that
|
|
7
|
+
* section. Importers (`importers`) tell us which deps are direct; we use
|
|
8
|
+
* it to flag direct vs transitive, but every package ends up in the list
|
|
9
|
+
* regardless (transitive deps need scanning too).
|
|
10
|
+
*/
|
|
11
|
+
export declare function parsePnpmLockfile(lockfilePath: string): ParsedLockfile | null;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.parsePnpmLockfile = parsePnpmLockfile;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const yaml_1 = require("yaml");
|
|
40
|
+
/**
|
|
41
|
+
* Parse a pnpm-lock.yaml (v6+).
|
|
42
|
+
*
|
|
43
|
+
* pnpm lockfiles contain the resolved transitive tree under `packages`,
|
|
44
|
+
* keyed as `<name>@<version>` (with optional peer suffixes). We walk that
|
|
45
|
+
* section. Importers (`importers`) tell us which deps are direct; we use
|
|
46
|
+
* it to flag direct vs transitive, but every package ends up in the list
|
|
47
|
+
* regardless (transitive deps need scanning too).
|
|
48
|
+
*/
|
|
49
|
+
function parsePnpmLockfile(lockfilePath) {
|
|
50
|
+
let raw;
|
|
51
|
+
try {
|
|
52
|
+
raw = fs.readFileSync(lockfilePath, 'utf8');
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
let data;
|
|
58
|
+
try {
|
|
59
|
+
data = (0, yaml_1.parse)(raw);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
if (!data || typeof data !== 'object')
|
|
65
|
+
return null;
|
|
66
|
+
const manifestPath = path.join(path.dirname(lockfilePath), 'package.json');
|
|
67
|
+
let projectLicense;
|
|
68
|
+
try {
|
|
69
|
+
const pkg = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
70
|
+
if (typeof pkg.license === 'string')
|
|
71
|
+
projectLicense = pkg.license;
|
|
72
|
+
else if (pkg.license && typeof pkg.license === 'object' && typeof pkg.license.type === 'string') {
|
|
73
|
+
projectLicense = pkg.license.type;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// optional
|
|
78
|
+
}
|
|
79
|
+
// Collect direct dependency names from the lockfile's `importers` section
|
|
80
|
+
// (more reliable than reading package.json for pnpm, since pnpm prunes).
|
|
81
|
+
const directKeys = new Set();
|
|
82
|
+
const importers = data.importers || {};
|
|
83
|
+
for (const importer of Object.values(importers)) {
|
|
84
|
+
for (const cat of ['dependencies', 'devDependencies', 'optionalDependencies']) {
|
|
85
|
+
const deps = importer?.[cat];
|
|
86
|
+
if (deps && typeof deps === 'object') {
|
|
87
|
+
for (const name of Object.keys(deps))
|
|
88
|
+
directKeys.add(name);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const packages = [];
|
|
93
|
+
const seen = new Set();
|
|
94
|
+
const pkgSection = data.packages || {};
|
|
95
|
+
for (const key of Object.keys(pkgSection)) {
|
|
96
|
+
const entry = pkgSection[key];
|
|
97
|
+
// pnpm v6+: key like "lodash@4.17.19" or "/lodash/4.17.19"
|
|
98
|
+
// v9+: key like "lodash@4.17.19(peerdeps...)"
|
|
99
|
+
const { name, version } = parsePnpmPkgKey(key);
|
|
100
|
+
if (!name || !version)
|
|
101
|
+
continue;
|
|
102
|
+
const id = `${name}@${version}`;
|
|
103
|
+
if (seen.has(id))
|
|
104
|
+
continue;
|
|
105
|
+
seen.add(id);
|
|
106
|
+
packages.push({
|
|
107
|
+
ecosystem: 'pnpm',
|
|
108
|
+
name,
|
|
109
|
+
version,
|
|
110
|
+
manifestPath,
|
|
111
|
+
direct: directKeys.has(name),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
ecosystem: 'pnpm',
|
|
116
|
+
lockfilePath,
|
|
117
|
+
manifestPath,
|
|
118
|
+
packages,
|
|
119
|
+
projectLicense,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Parse a pnpm `packages.<key>` entry. Supported forms:
|
|
124
|
+
* "lodash@4.17.19"
|
|
125
|
+
* "/lodash/4.17.19" (older)
|
|
126
|
+
* "@babel/core@7.0.0"
|
|
127
|
+
* "lodash@4.17.19(react@18)" (peer-suffixed; we strip the parens)
|
|
128
|
+
*/
|
|
129
|
+
function parsePnpmPkgKey(key) {
|
|
130
|
+
// Strip peer suffix in parens.
|
|
131
|
+
const parenIdx = key.indexOf('(');
|
|
132
|
+
let k = parenIdx >= 0 ? key.slice(0, parenIdx) : key;
|
|
133
|
+
k = k.trim();
|
|
134
|
+
if (k.startsWith('/'))
|
|
135
|
+
k = k.slice(1);
|
|
136
|
+
// For scoped: leading "@" then name then "@version"
|
|
137
|
+
if (k.startsWith('@')) {
|
|
138
|
+
const at = k.indexOf('@', 1);
|
|
139
|
+
if (at < 0)
|
|
140
|
+
return { name: '', version: '' };
|
|
141
|
+
return { name: k.slice(0, at), version: k.slice(at + 1) };
|
|
142
|
+
}
|
|
143
|
+
const at = k.indexOf('@');
|
|
144
|
+
if (at < 0)
|
|
145
|
+
return { name: '', version: '' };
|
|
146
|
+
return { name: k.slice(0, at), version: k.slice(at + 1) };
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=pnpm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pnpm.js","sourceRoot":"","sources":["../../../src/dependency/parsers/pnpm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ParsedLockfile } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a `requirements.txt` file.
|
|
4
|
+
*
|
|
5
|
+
* Supported pins:
|
|
6
|
+
* name==1.2.3
|
|
7
|
+
* name>=1.2.3
|
|
8
|
+
* name~=1.2.3
|
|
9
|
+
* name>1.0,<2.0
|
|
10
|
+
* name (unpinned — marked unresolved)
|
|
11
|
+
*
|
|
12
|
+
* `#`-comments, blank lines, `-r other.txt`, `-e .`, and VCS/URL specs are
|
|
13
|
+
* skipped (URL specs are treated as unpinned/unresolved under the package
|
|
14
|
+
* name extracted from the URL when possible, otherwise skipped entirely).
|
|
15
|
+
*
|
|
16
|
+
* IMPORTANT: no network calls are made. When a pin is not an exact `==`,
|
|
17
|
+
* the entry is marked `unresolved` and surfaced to the user as such rather
|
|
18
|
+
* than queried against OSV (since the installed version is unknown). A
|
|
19
|
+
* Pipfile.lock alongside the requirements.txt will be preferred when
|
|
20
|
+
* present (handled by the resolver/dependencyChecker, not here).
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseRequirementsTxt(lockfilePath: string): ParsedLockfile | null;
|
|
23
|
+
/** Normalize a PyPI package name per PEP 503 (lowercase, runs of [-_.] -> "-"). */
|
|
24
|
+
export declare function normalizePipName(name: string): string;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.parseRequirementsTxt = parseRequirementsTxt;
|
|
37
|
+
exports.normalizePipName = normalizePipName;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
/**
|
|
40
|
+
* Parse a `requirements.txt` file.
|
|
41
|
+
*
|
|
42
|
+
* Supported pins:
|
|
43
|
+
* name==1.2.3
|
|
44
|
+
* name>=1.2.3
|
|
45
|
+
* name~=1.2.3
|
|
46
|
+
* name>1.0,<2.0
|
|
47
|
+
* name (unpinned — marked unresolved)
|
|
48
|
+
*
|
|
49
|
+
* `#`-comments, blank lines, `-r other.txt`, `-e .`, and VCS/URL specs are
|
|
50
|
+
* skipped (URL specs are treated as unpinned/unresolved under the package
|
|
51
|
+
* name extracted from the URL when possible, otherwise skipped entirely).
|
|
52
|
+
*
|
|
53
|
+
* IMPORTANT: no network calls are made. When a pin is not an exact `==`,
|
|
54
|
+
* the entry is marked `unresolved` and surfaced to the user as such rather
|
|
55
|
+
* than queried against OSV (since the installed version is unknown). A
|
|
56
|
+
* Pipfile.lock alongside the requirements.txt will be preferred when
|
|
57
|
+
* present (handled by the resolver/dependencyChecker, not here).
|
|
58
|
+
*/
|
|
59
|
+
function parseRequirementsTxt(lockfilePath) {
|
|
60
|
+
let raw;
|
|
61
|
+
try {
|
|
62
|
+
raw = fs.readFileSync(lockfilePath, 'utf8');
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const manifestPath = lockfilePath; // requirements.txt IS the manifest
|
|
68
|
+
const packages = [];
|
|
69
|
+
const seen = new Set();
|
|
70
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
71
|
+
let s = line.trim();
|
|
72
|
+
if (!s)
|
|
73
|
+
continue;
|
|
74
|
+
// Strip inline comment.
|
|
75
|
+
const hash = s.indexOf('#');
|
|
76
|
+
if (hash >= 0)
|
|
77
|
+
s = s.slice(0, hash).trim();
|
|
78
|
+
if (!s)
|
|
79
|
+
continue;
|
|
80
|
+
// Skip option lines and recursive includes; we don't follow them.
|
|
81
|
+
if (s.startsWith('-'))
|
|
82
|
+
continue;
|
|
83
|
+
if (s.startsWith('-e ') || s.startsWith('--'))
|
|
84
|
+
continue;
|
|
85
|
+
// Skip VCS / URL specs entirely (we cannot resolve them offline).
|
|
86
|
+
// Examples: git+https://..., https://..., file:///...
|
|
87
|
+
if (/^[a-z]+(\+[a-z]+)?:\/\//i.test(s))
|
|
88
|
+
continue;
|
|
89
|
+
// Strip environment markers: "name==1.0 ; python_version>='3.8'"
|
|
90
|
+
const semi = s.indexOf(';');
|
|
91
|
+
if (semi >= 0)
|
|
92
|
+
s = s.slice(0, semi).trim();
|
|
93
|
+
if (!s)
|
|
94
|
+
continue;
|
|
95
|
+
// Strip extras: "name[extra1,extra2]==1.0"
|
|
96
|
+
const nameMatch = s.match(/^([A-Za-z0-9][A-Za-z0-9._-]*)\s*(\[[^\]]*\])?\s*(.*)$/);
|
|
97
|
+
if (!nameMatch)
|
|
98
|
+
continue;
|
|
99
|
+
const rawName = nameMatch[1];
|
|
100
|
+
const spec = (nameMatch[3] || '').trim();
|
|
101
|
+
const name = normalizePipName(rawName);
|
|
102
|
+
if (seen.has(name))
|
|
103
|
+
continue;
|
|
104
|
+
seen.add(name);
|
|
105
|
+
// Exact pin: "name==1.2.3"
|
|
106
|
+
const exact = spec.match(/^==\s*([A-Za-z0-9_.!+*-]+)$/);
|
|
107
|
+
if (exact) {
|
|
108
|
+
packages.push({
|
|
109
|
+
ecosystem: 'pip',
|
|
110
|
+
name,
|
|
111
|
+
version: exact[1],
|
|
112
|
+
manifestPath,
|
|
113
|
+
direct: true,
|
|
114
|
+
});
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
// Range pins (>=, >, ~=, <=, <, comma-separated): unresolved.
|
|
118
|
+
if (spec && /([<>=~!]=?)/.test(spec)) {
|
|
119
|
+
packages.push({
|
|
120
|
+
ecosystem: 'pip',
|
|
121
|
+
name,
|
|
122
|
+
version: spec, // best-effort: keep the spec for display
|
|
123
|
+
manifestPath,
|
|
124
|
+
direct: true,
|
|
125
|
+
unresolved: true,
|
|
126
|
+
});
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
// Bare "name" (no pin): unresolved.
|
|
130
|
+
if (!spec) {
|
|
131
|
+
packages.push({
|
|
132
|
+
ecosystem: 'pip',
|
|
133
|
+
name,
|
|
134
|
+
version: '',
|
|
135
|
+
manifestPath,
|
|
136
|
+
direct: true,
|
|
137
|
+
unresolved: true,
|
|
138
|
+
});
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
ecosystem: 'pip',
|
|
144
|
+
lockfilePath,
|
|
145
|
+
manifestPath,
|
|
146
|
+
packages,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/** Normalize a PyPI package name per PEP 503 (lowercase, runs of [-_.] -> "-"). */
|
|
150
|
+
function normalizePipName(name) {
|
|
151
|
+
return name.toLowerCase().replace(/[-_.]+/g, '-');
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=requirements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirements.js","sourceRoot":"","sources":["../../../src/dependency/parsers/requirements.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ParsedLockfile } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a yarn v1 `yarn.lock` (the classic format). v2+ (Berry) uses a
|
|
4
|
+
* different text format and is NOT covered here — we deliberately bail in
|
|
5
|
+
* that case so the caller can skip the file gracefully.
|
|
6
|
+
*
|
|
7
|
+
* yarn v1 lockfiles contain the resolved transitive tree: every package
|
|
8
|
+
* entry has a `version` and a `resolved` URL, including transitive deps.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseYarnLockfile(lockfilePath: string): ParsedLockfile | null;
|