ts-node-client 2.1.3 → 3.0.1

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 CHANGED
@@ -1,14 +1,28 @@
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
- ## 2.1.3 - 2022-12-26
12
-
13
- ### Changed
14
- * Migrate versions of dependencies
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.1 - 2023-02-08
12
+
13
+ ### Changed
14
+ * docs updated
15
+
16
+
17
+ ## 3.0.0 - 2023-02-08
18
+
19
+ ### Changed
20
+ * `npm.ls` cli -> `package-lock.json` or `package.json` or `yarn.lock` parse
21
+ * npm removed
22
+ * updated dependencies
23
+
24
+
25
+ ## 2.1.3 - 2022-12-26
26
+
27
+ ### Changed
28
+ * Migrate versions of dependencies
package/README.md CHANGED
@@ -9,6 +9,11 @@
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` anymore. The addition has been done due to missing programmatic API in npm >= 8.0.0 and in order to skip deprecated dependencies
14
+
15
+ This change affects the structure of scans slightly, but it heavily improves the scanner.
16
+
12
17
  ## Requirements
13
18
  * node >= 8.9.0
14
19
  * npm < 8.0.0 use **ts-node-client@1.***
@@ -86,7 +91,14 @@ you should add value, for example:
86
91
  #### Error: The programmatic API was removed in npm v8.0.0
87
92
  You should upgrade to 2.* versions of ts-node-client
88
93
 
89
- ## Changelog
94
+ ## Changelog available inside `CHANGELOG.md`
95
+
96
+ ## [DEPRECATED] Changelog
97
+
98
+ #### 3.0.*
99
+ - `npm.ls` cli -> `package-lock.json` parse
100
+ - npm removed
101
+ - updated dependencies
90
102
 
91
103
  #### 2.1.*
92
104
  - Migrate 1.6.* - 1.8.* changes to version 2.1
@@ -6,7 +6,10 @@
6
6
  *********************************************************/
7
7
  /* eslint-enable */
8
8
 
9
- const npm = require('npm');
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
- npm.load({ parseable: true, long: false }, (cberr, cbnpm) => {
27
- if (cberr) {
28
- debuglog('npm.load - error: ', cberr);
29
- cb(cberr);
30
- } else {
31
- debuglog('npm loaded: prefix = %s', cbnpm.prefix);
32
-
33
- cbnpm.commands.ls([], true, (err, data) => {
34
- if (err) {
35
- debuglog('npm.commands.ls - error:', err);
36
- cb(err);
37
- } else {
38
- debuglog('Project: ', data.name, data.version);
39
- const dependency = self.walk(data);
40
- const result = new ScanResult(
41
- options.project,
42
- data.name,
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
- npmDependency.repository ? npmDependency.repository.url : undefined
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 childDependency = npmDependency.dependencies[val];
91
- let child = null;
92
-
93
- // check for errorneous dependencies (e.g a nmp-debug.log file)
94
- if (childDependency.error) {
95
- log('Skipping errorneous dependency on level %d: ', level, val);
96
-
97
- // check for blacklisted dependencies on level 0
98
- } else if (level === 0 && (opts.exclude instanceof Array && opts.exclude.indexOf(val) >= 0 || opts.exclude === val)) {
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}Repsitory type:`, dep.repository.type);
136
- debuglog(`${fill}Repsitory url:`, dep.repository.url);
300
+ debuglog(`${fill}Repository type:`, dep.repository.type);
301
+ debuglog(`${fill}Repository url:`, dep.repository.url);
137
302
  }
138
- debuglog(`${fill}Homdepage: `, dep.homepage);
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": "2.1.3",
4
+ "version": "3.0.1",
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 cydx",
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
- "npm": "6.14.18",
34
- "axios": "1.2.1",
33
+ "@yarnpkg/lockfile": "^1.1.0",
34
+ "axios": "1.2.6",
35
35
  "debuglog": "1.0.1",
36
36
  "semver": "7.3.8",
37
37
  "yargs": "17.6.2"
38
38
  },
39
39
  "devDependencies": {
40
- "eslint": "8.30.0",
40
+ "eslint": "8.33.0",
41
41
  "eslint-config-airbnb-base": "15.0.0",
42
- "eslint-plugin-import": "2.26.0",
43
- "eslint-plugin-sonarjs": "0.17.0",
42
+ "eslint-plugin-import": "2.27.5",
43
+ "eslint-plugin-sonarjs": "0.18.0",
44
44
  "mocha": "10.2.0",
45
- "nock": "13.2.9"
45
+ "nock": "13.3.0"
46
46
  },
47
47
  "keywords": [
48
48
  "node",
@@ -9,7 +9,7 @@
9
9
 
10
10
 
11
11
  const assert = require('assert');
12
- const util = require('util');
12
+ const util = require('util');
13
13
 
14
14
  const SHOULD_CONTAIN = 'should contain \'name\' and \'message\' fields';
15
15