ts-node-client 2.1.2 → 3.0.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/CHANGELOG.md +22 -0
- package/README.md +15 -1
- package/lib/npm-scanner.js +225 -60
- package/package.json +13 -13
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# ts-node-client
|
|
2
|
+
|
|
3
|
+
## Changelog
|
|
4
|
+
|
|
5
|
+
All notable changes to this project will be documented in this file.
|
|
6
|
+
|
|
7
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
8
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## 3.0.0 - 2023-02-08
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
* `npm.ls` cli -> `package-lock.json` or `package.json` or `yarn.lock` parse
|
|
15
|
+
* npm removed
|
|
16
|
+
* updated dependencies
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## 2.1.3 - 2022-12-26
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
* Migrate versions of dependencies
|
package/README.md
CHANGED
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
|
|
10
10
|
> TrustSource node client - node module to transfer dependency information to TrustSource server.
|
|
11
11
|
|
|
12
|
+
## Release 3.0.0
|
|
13
|
+
Package now is not including `npm`. This was done due to missing programmatic API in npm >= 8.0.0 and in order to skip deprecated dependencies
|
|
14
|
+
|
|
15
|
+
This change affects structure of scans, but improve tool.
|
|
16
|
+
|
|
17
|
+
|
|
12
18
|
## Requirements
|
|
13
19
|
* node >= 8.9.0
|
|
14
20
|
* npm < 8.0.0 use **ts-node-client@1.***
|
|
@@ -86,10 +92,18 @@ you should add value, for example:
|
|
|
86
92
|
#### Error: The programmatic API was removed in npm v8.0.0
|
|
87
93
|
You should upgrade to 2.* versions of ts-node-client
|
|
88
94
|
|
|
89
|
-
## Changelog
|
|
95
|
+
## Changelog available inside `CHANGELOG.md`
|
|
96
|
+
|
|
97
|
+
## [DEPRECATED] Changelog
|
|
98
|
+
|
|
99
|
+
#### 3.0.*
|
|
100
|
+
- `npm.ls` cli -> `package-lock.json` parse
|
|
101
|
+
- npm removed
|
|
102
|
+
- updated dependencies
|
|
90
103
|
|
|
91
104
|
#### 2.1.*
|
|
92
105
|
- Migrate 1.6.* - 1.8.* changes to version 2.1
|
|
106
|
+
- Bump dependencies
|
|
93
107
|
|
|
94
108
|
#### 2.0.*
|
|
95
109
|
- Support new scan tool and fix problem with programmatic API for >= npm@8.0.0
|
package/lib/npm-scanner.js
CHANGED
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
*********************************************************/
|
|
7
7
|
/* eslint-enable */
|
|
8
8
|
|
|
9
|
-
const
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
12
|
+
const lockfile = require('@yarnpkg/lockfile');
|
|
10
13
|
const debuglog = (require('debuglog'))('ts-npm-scanner');
|
|
11
14
|
const ScanResult = require('./scanresult');
|
|
12
15
|
const { RestClient } = require('./rest-client');
|
|
@@ -19,36 +22,94 @@ function Scanner(options) {
|
|
|
19
22
|
this.name = 'ts-npm-scanner';
|
|
20
23
|
}
|
|
21
24
|
|
|
25
|
+
function getPackageJson(self) {
|
|
26
|
+
try {
|
|
27
|
+
const file = path.resolve(process.cwd(), 'package.json');
|
|
28
|
+
const data = fs.readFileSync(file);
|
|
29
|
+
if (data && data.code === 'ENOENT') {
|
|
30
|
+
debuglog('npm.fs.package - error:', data);
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const jsonFile = JSON.parse(data);
|
|
34
|
+
debuglog('Project: ', jsonFile.name, jsonFile.version);
|
|
35
|
+
const dependencies = self.walkPackage(jsonFile, 0, jsonFile);
|
|
36
|
+
return { root: jsonFile, dependencies };
|
|
37
|
+
} catch (e) {
|
|
38
|
+
debuglog('npm.fs.package - error:', e);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function getPackageLockJson(self) {
|
|
43
|
+
try {
|
|
44
|
+
const file = path.resolve(process.cwd(), 'package-lock.json');
|
|
45
|
+
const data = fs.readFileSync(file);
|
|
46
|
+
if (data && data.code === 'ENOENT') {
|
|
47
|
+
debuglog('npm.fs.package-lock - error:', data);
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const jsonFile = JSON.parse(data);
|
|
51
|
+
debuglog('Project: ', jsonFile.name, jsonFile.version);
|
|
52
|
+
const dependencies = self.walk(jsonFile, 0, jsonFile);
|
|
53
|
+
return { root: jsonFile, dependencies };
|
|
54
|
+
} catch (e) {
|
|
55
|
+
debuglog('npm.fs.package-lock - error:', e);
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function getYarnLock(self, packageData) {
|
|
60
|
+
try {
|
|
61
|
+
const file = path.resolve(process.cwd(), 'yarn.lock');
|
|
62
|
+
const data = fs.readFileSync(file);
|
|
63
|
+
if (data && data.code === 'ENOENT') {
|
|
64
|
+
debuglog('npm.fs.yarn-lock - error:', data);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const jsonFile = lockfile.parse(data.toString());
|
|
68
|
+
if (jsonFile.type === 'success') {
|
|
69
|
+
const base = {
|
|
70
|
+
name: (packageData && packageData.root && packageData.root.name) || 'root',
|
|
71
|
+
version: (packageData && packageData.root && packageData.root.version) || '1',
|
|
72
|
+
dependencies: jsonFile.object
|
|
73
|
+
};
|
|
74
|
+
debuglog('Project: ', base.name, base.version);
|
|
75
|
+
const dependencies = self.walkYarn(base, 0, base);
|
|
76
|
+
return { root: jsonFile, dependencies };
|
|
77
|
+
}
|
|
78
|
+
debuglog('npm.fs.yarn-lock - error:', jsonFile);
|
|
79
|
+
return null;
|
|
80
|
+
} catch (e) {
|
|
81
|
+
debuglog('npm.fs.yarn-lock - error:', e);
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function saveResults(cb, options, root, dependencies) {
|
|
87
|
+
const result = new ScanResult(options.project, root.name, `npm:${root.name}`, dependencies);
|
|
88
|
+
debuglog('result: ', JSON.stringify(result));
|
|
89
|
+
cb(undefined, result);
|
|
90
|
+
}
|
|
91
|
+
|
|
22
92
|
Scanner.prototype.scan = function scan(cb) {
|
|
23
93
|
const self = this;
|
|
24
94
|
const { options } = this;
|
|
25
95
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
`npm:${data.name}`,
|
|
44
|
-
dependency
|
|
45
|
-
);
|
|
46
|
-
debuglog('result: ', JSON.stringify(result));
|
|
47
|
-
cb(undefined, result);
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
});
|
|
96
|
+
const packageData = getPackageJson(self);
|
|
97
|
+
const packageLockData = getPackageLockJson(self);
|
|
98
|
+
const yarnLockData = getYarnLock(self, packageData);
|
|
99
|
+
if (packageData && yarnLockData) {
|
|
100
|
+
yarnLockData.root = packageData.root;
|
|
101
|
+
}
|
|
102
|
+
const data = packageLockData || yarnLockData || packageData;
|
|
103
|
+
if (data && data.root) {
|
|
104
|
+
saveResults(cb, options, data.root, data.dependencies);
|
|
105
|
+
} else {
|
|
106
|
+
const err = {
|
|
107
|
+
status: 404,
|
|
108
|
+
message: 'No results found in `package-lock.json` or `package.json` or `yarn.lock`'
|
|
109
|
+
};
|
|
110
|
+
debuglog('result: ', JSON.stringify(err));
|
|
111
|
+
cb(err);
|
|
112
|
+
}
|
|
52
113
|
};
|
|
53
114
|
|
|
54
115
|
Scanner.prototype.transfer = function transfer(scan, cb) {
|
|
@@ -57,11 +118,49 @@ Scanner.prototype.transfer = function transfer(scan, cb) {
|
|
|
57
118
|
};
|
|
58
119
|
|
|
59
120
|
/* eslint-disable no-underscore-dangle, prefer-rest-params, no-mixed-operators */
|
|
60
|
-
Scanner.prototype.walk = function walk(npmDependency, level) {
|
|
121
|
+
Scanner.prototype.walk = function walk(npmDependency, level, root) {
|
|
61
122
|
const self = this;
|
|
62
123
|
const opts = this.options || {};
|
|
63
124
|
level = level || 0;
|
|
64
125
|
|
|
126
|
+
printDependency(npmDependency, level);
|
|
127
|
+
|
|
128
|
+
if (npmDependency.name) {
|
|
129
|
+
let pkg = root && root.packages && root.packages[`node_modules/${npmDependency.name}`];
|
|
130
|
+
if (!pkg) {
|
|
131
|
+
pkg = root && root.packages && root.packages[''];
|
|
132
|
+
}
|
|
133
|
+
let repository = npmDependency.repository && npmDependency.repository.url;
|
|
134
|
+
if (!repository) {
|
|
135
|
+
repository = pkg && pkg.repository && pkg.repository.url;
|
|
136
|
+
}
|
|
137
|
+
const dependency = new Dependency(
|
|
138
|
+
npmDependency.name,
|
|
139
|
+
npmDependency.version,
|
|
140
|
+
'npm',
|
|
141
|
+
npmDependency.description,
|
|
142
|
+
npmDependency.private,
|
|
143
|
+
npmDependency.licenses || npmDependency.license || (pkg && (pkg.licenses || pkg.license)),
|
|
144
|
+
npmDependency.homepage || (pkg && pkg.homepage),
|
|
145
|
+
repository
|
|
146
|
+
);
|
|
147
|
+
if (npmDependency.dependencies) {
|
|
148
|
+
Object.getOwnPropertyNames(npmDependency.dependencies).forEach((val) => {
|
|
149
|
+
const childDependency = npmDependency.dependencies[val];
|
|
150
|
+
if (childDependency) {
|
|
151
|
+
childDependency.name = val;
|
|
152
|
+
}
|
|
153
|
+
checkForChild(self, opts, dependency, childDependency, val, level, root);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return dependency;
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
function checkForChild(self, opts, dependency, childDependency, val, level, root) {
|
|
162
|
+
let child = null;
|
|
163
|
+
|
|
65
164
|
function log() {
|
|
66
165
|
const args = [].slice.call(arguments, 0);
|
|
67
166
|
if (opts.verbose) {
|
|
@@ -70,10 +169,39 @@ Scanner.prototype.walk = function walk(npmDependency, level) {
|
|
|
70
169
|
debuglog.apply(this, args);
|
|
71
170
|
}
|
|
72
171
|
}
|
|
172
|
+
// check for errorneous dependencies (e.g a nmp-debug.log file)
|
|
173
|
+
if (childDependency.error) {
|
|
174
|
+
log('Skipping errorneous dependency on level %d: ', level, val);
|
|
175
|
+
// check for blacklisted dependencies on level 0
|
|
176
|
+
} else if (level === 0 && (opts.exclude instanceof Array && opts.exclude.indexOf(val) >= 0 || opts.exclude === val)) {
|
|
177
|
+
log('Skipping level 0 blacklisted dependency: ', val);
|
|
178
|
+
// include dev dependencies on level 0 if configured
|
|
179
|
+
} else if (level === 0 && opts.includeDevDependencies && childDependency && childDependency.dev) {
|
|
180
|
+
log('Adding level 0 devDependency:', val);
|
|
181
|
+
child = self.walk(childDependency, level + 1, root);
|
|
182
|
+
// include runtime dependencies
|
|
183
|
+
} else if (childDependency && !childDependency.dev) {
|
|
184
|
+
log('Adding dependency on level %d:', level, val);
|
|
185
|
+
child = self.walk(childDependency, level + 1, root);
|
|
186
|
+
} else {
|
|
187
|
+
log('Skipping undeclared dependency on level %d: ', level, val);
|
|
188
|
+
}
|
|
189
|
+
if (child) {
|
|
190
|
+
dependency.addDependency(child);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* eslint-enable no-underscore-dangle, prefer-rest-params, no-mixed-operators */
|
|
195
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
196
|
+
Scanner.prototype.walkPackage = function walkPackage(npmDependency, level) {
|
|
197
|
+
const self = this;
|
|
198
|
+
const opts = this.options || {};
|
|
199
|
+
level = level || 0;
|
|
73
200
|
|
|
74
201
|
printDependency(npmDependency, level);
|
|
75
202
|
|
|
76
203
|
if (npmDependency.name) {
|
|
204
|
+
const repository = npmDependency.repository && npmDependency.repository.url;
|
|
77
205
|
const dependency = new Dependency(
|
|
78
206
|
npmDependency.name,
|
|
79
207
|
npmDependency.version,
|
|
@@ -82,45 +210,82 @@ Scanner.prototype.walk = function walk(npmDependency, level) {
|
|
|
82
210
|
npmDependency.private,
|
|
83
211
|
npmDependency.licenses || npmDependency.license,
|
|
84
212
|
npmDependency.homepage,
|
|
85
|
-
|
|
213
|
+
repository
|
|
86
214
|
);
|
|
215
|
+
if (npmDependency.dependencies) {
|
|
216
|
+
Object.getOwnPropertyNames(npmDependency.dependencies).forEach((val) => {
|
|
217
|
+
const childDependency = {
|
|
218
|
+
name: val,
|
|
219
|
+
version: npmDependency.dependencies[val]
|
|
220
|
+
};
|
|
87
221
|
|
|
222
|
+
checkForChild(self, opts, dependency, childDependency, val, level);
|
|
223
|
+
});
|
|
224
|
+
if (opts.includeDevDependencies) {
|
|
225
|
+
Object.getOwnPropertyNames(npmDependency.devDependencies).forEach((val) => {
|
|
226
|
+
const childDependency = {
|
|
227
|
+
name: val,
|
|
228
|
+
version: npmDependency.devDependencies[val]
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
checkForChild(self, opts, dependency, childDependency, val, level);
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return dependency;
|
|
236
|
+
}
|
|
237
|
+
return null;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
241
|
+
Scanner.prototype.walkYarn = function walkPackage(npmDependency, level) {
|
|
242
|
+
const self = this;
|
|
243
|
+
const opts = this.options || {};
|
|
244
|
+
level = level || 0;
|
|
245
|
+
|
|
246
|
+
printDependency(npmDependency, level);
|
|
247
|
+
|
|
248
|
+
if (npmDependency.name) {
|
|
249
|
+
const repository = npmDependency.repository && npmDependency.repository.url;
|
|
250
|
+
const dependency = new Dependency(
|
|
251
|
+
npmDependency.name,
|
|
252
|
+
npmDependency.version,
|
|
253
|
+
'npm',
|
|
254
|
+
npmDependency.description,
|
|
255
|
+
npmDependency.private,
|
|
256
|
+
npmDependency.licenses || npmDependency.license,
|
|
257
|
+
npmDependency.homepage,
|
|
258
|
+
repository
|
|
259
|
+
);
|
|
88
260
|
if (npmDependency.dependencies) {
|
|
89
261
|
Object.getOwnPropertyNames(npmDependency.dependencies).forEach((val) => {
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
log('Skipping level 0 blacklisted dependency: ', val);
|
|
100
|
-
|
|
101
|
-
// include dev dependencies on level 0 if configured
|
|
102
|
-
} else if (level === 0 && opts.includeDevDependencies
|
|
103
|
-
&& npmDependency.devDependencies && npmDependency.devDependencies[val]) {
|
|
104
|
-
log('Adding level 0 devDependency:', val);
|
|
105
|
-
child = self.walk(npmDependency.dependencies[val], level + 1);
|
|
106
|
-
|
|
107
|
-
// include runtime dependencies
|
|
108
|
-
} else if (npmDependency._dependencies && npmDependency._dependencies[val]) {
|
|
109
|
-
log('Adding dependency on level %d:', level, val);
|
|
110
|
-
child = self.walk(npmDependency.dependencies[val], level + 1);
|
|
111
|
-
} else {
|
|
112
|
-
log('Skipping undeclared dependency on level %d: ', level, val);
|
|
113
|
-
}
|
|
114
|
-
if (child) {
|
|
115
|
-
dependency.addDependency(child);
|
|
116
|
-
}
|
|
262
|
+
const name = val.split('@')[0];
|
|
263
|
+
const depData = npmDependency.dependencies[val];
|
|
264
|
+
const version = (depData && depData.version) || depData;
|
|
265
|
+
const childDependency = {
|
|
266
|
+
name,
|
|
267
|
+
version: version && typeof version === 'string' ? version : null
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
checkForChild(self, opts, dependency, childDependency, val, level);
|
|
117
271
|
});
|
|
272
|
+
if (opts.includeDevDependencies) {
|
|
273
|
+
Object.getOwnPropertyNames(npmDependency.devDependencies).forEach((val) => {
|
|
274
|
+
const depData = npmDependency.devDependencies[val];
|
|
275
|
+
const version = (depData && depData.version) || depData;
|
|
276
|
+
const childDependency = {
|
|
277
|
+
name: val,
|
|
278
|
+
version: version && typeof version === 'string' ? version : null
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
checkForChild(self, opts, dependency, childDependency, val, level);
|
|
282
|
+
});
|
|
283
|
+
}
|
|
118
284
|
}
|
|
119
285
|
return dependency;
|
|
120
286
|
}
|
|
121
287
|
return null;
|
|
122
288
|
};
|
|
123
|
-
/* eslint-enable no-underscore-dangle, prefer-rest-params, no-mixed-operators */
|
|
124
289
|
|
|
125
290
|
function printDependency(dep, level) {
|
|
126
291
|
level = level || 0;
|
|
@@ -132,8 +297,8 @@ function printDependency(dep, level) {
|
|
|
132
297
|
debuglog(`${fill}Private: `, dep.private);
|
|
133
298
|
debuglog(`${fill}Description: `, dep.description);
|
|
134
299
|
if (dep.repository) {
|
|
135
|
-
debuglog(`${fill}
|
|
136
|
-
debuglog(`${fill}
|
|
300
|
+
debuglog(`${fill}Repository type:`, dep.repository.type);
|
|
301
|
+
debuglog(`${fill}Repository url:`, dep.repository.url);
|
|
137
302
|
}
|
|
138
|
-
debuglog(`${fill}
|
|
303
|
+
debuglog(`${fill}Homepage: `, dep.homepage);
|
|
139
304
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-node-client",
|
|
3
3
|
"description": "npm / node module to transfer dependency information to TrustSource server.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "3.0.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"homepage": "https://app.trustsource.io/",
|
|
7
7
|
"author": {
|
|
@@ -21,28 +21,28 @@
|
|
|
21
21
|
"ts-node-client": "./bin/ts-node-client.js"
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
|
-
"scan": "node ./bin/ts-node-client.js",
|
|
24
|
+
"scan": "node ./bin/ts-node-client.js --debug true",
|
|
25
25
|
"scan-with-brakes": "node ./bin/ts-node-client.js --breakOnViolations true --breakOnWarnings false",
|
|
26
|
-
"scan-to-file": "node ./bin/ts-node-client.js --saveAs test --saveAsFormat
|
|
26
|
+
"scan-to-file": "node ./bin/ts-node-client.js --saveAs test --saveAsFormat scan",
|
|
27
27
|
"lint": "eslint bin lib test",
|
|
28
28
|
"lint-fix": "eslint bin lib test --fix",
|
|
29
29
|
"test": "mocha test",
|
|
30
30
|
"precommit": "npm run lint && npm run test"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"
|
|
34
|
-
"axios": "
|
|
33
|
+
"@yarnpkg/lockfile": "^1.1.0",
|
|
34
|
+
"axios": "1.2.6",
|
|
35
35
|
"debuglog": "1.0.1",
|
|
36
|
-
"semver": "7.3.
|
|
37
|
-
"yargs": "
|
|
36
|
+
"semver": "7.3.8",
|
|
37
|
+
"yargs": "17.6.2"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"eslint": "
|
|
41
|
-
"eslint-config-airbnb-base": "
|
|
42
|
-
"eslint-plugin-import": "
|
|
43
|
-
"eslint-plugin-sonarjs": "
|
|
44
|
-
"mocha": "
|
|
45
|
-
"nock": "
|
|
40
|
+
"eslint": "8.33.0",
|
|
41
|
+
"eslint-config-airbnb-base": "15.0.0",
|
|
42
|
+
"eslint-plugin-import": "2.27.5",
|
|
43
|
+
"eslint-plugin-sonarjs": "0.18.0",
|
|
44
|
+
"mocha": "10.2.0",
|
|
45
|
+
"nock": "13.3.0"
|
|
46
46
|
},
|
|
47
47
|
"keywords": [
|
|
48
48
|
"node",
|