ts-node-client 2.0.0 → 2.1.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/README.md CHANGED
@@ -7,14 +7,12 @@
7
7
 
8
8
  [![npm package](https://nodei.co/npm/ts-node-client.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/ts-node-client/)
9
9
 
10
- TrustSource node client
11
-
12
- > node module to transfer dependency information to TrustSource server.
10
+ > TrustSource node client - node module to transfer dependency information to TrustSource server.
13
11
 
14
12
  ## Requirements
15
-
16
13
  * node >= 8.9.0
17
- * if you are using npm < 8.0.0 we recommend switch to ts-node-client version 1.5.2 until we provide more elegant solution
14
+ * npm < 8.0.0 use **ts-node-client@1.***
15
+ * npm >= 8.0.0 use **ts-node-client@2.***
18
16
 
19
17
  ## Installation
20
18
  Run: `npm install --save-dev ts-node-client` or `yarn add --dev ts-node-client`
@@ -47,8 +45,8 @@ You also may initiate transfer to TrustSource server manually by executing follo
47
45
 
48
46
  ```
49
47
  node_modules/.bin/ts-node-client
50
- node_modules/.bin/ts-node-client -k apiKey -p Project
51
- node_modules/.bin/ts-node-client -c config.json
48
+ node_modules/.bin/ts-node-client -k apiKey -p Project --breakOnWarnings false --breakOnViolations true
49
+ node_modules/.bin/ts-node-client -c config.json
52
50
  ```
53
51
  ```
54
52
  npm / node module to transfer dependency information to TrustSource server.
@@ -61,93 +59,102 @@ Options:
61
59
  --binaryLinks Binary links separated by comma [default: null]
62
60
  --url url [default: null]
63
61
  --config, -c Config path [default: null]
64
- --proxy Proxy url like 'https://user:password@host:port' [default: null]
65
- --version, -v Prints a version [default: false]
62
+ --proxy Proxy url like 'https://user:password@host:port' [default: null]
63
+ --version Prints a version [default: null]
64
+ --saveAs, -o Save as file (file name prefix) [default: null]
65
+ --saveAsFormat, -f Save as format (scan / cydx / spdx) [default: null]
66
66
  --debug [default: null]
67
67
  --simulate [default: null]
68
68
  --includeDevDependencies [default: null]
69
69
  --meteor [default: null]
70
- --brakeOnWarnings [default: null]
71
- --brakeOnViolations [default: null]
70
+ --breakOnWarnings [default: null]
71
+ --breakOnViolations [default: null]
72
72
  --help Prints a usage statement [boolean]
73
+
73
74
  ```
75
+ PLEASE NOTE: if you want to pass param into function
76
+ you should add value, for example:
77
+
78
+ `--breakOnViolations true` or `--saveAs sbom`
79
+
80
+ ## Software bill of materials
81
+
82
+ [View SBOM <img alt="TrustSource" src="https://app.trustsource.io/logo.png" width="70"/>](https://app.trustsource.io/api/v1/public-BoM/ae0832c6-5a55-4aa8-8c45-75528d0833fb)
83
+
84
+ ## Known problems
85
+
86
+ #### Error: The programmatic API was removed in npm v8.0.0
87
+ You should upgrade to 2.* versions of ts-node-client
74
88
 
75
89
  ## Changelog
76
90
 
77
- #### 2.0.0
78
- #### if you are using npm < 8.0.0 we recommend switch to ts-node-client version 1.5.2 until we provide more elegant solution
91
+ #### 2.1.*
92
+ - Migrate 1.6.* - 1.8.* changes to version 2.1
93
+
94
+ #### 2.0.*
95
+ - Support new scan tool and fix problem with programmatic API for >= npm@8.0.0
79
96
  - Stop usage of [`global-npm`](https://github.com/dracupid/global-npm) until we find new resolution
80
97
  - Get back `npm` as local dependency
81
98
 
82
- #### 1.5.2
83
- - Describe `Error: The programmatic API was removed in npm v8.0.0`
99
+ #### 1.8.*
100
+ - SBOM
101
+ - **--saveAs** and **--saveAsFormat**
102
+ - Bump minimist from 1.2.5 to 1.2.6
103
+ - Bump urijs from 1.19.10 to 1.19.11
104
+ - replace packageurl-js with simple local function
105
+ - improve docs
106
+
107
+ #### 1.7.*
108
+ - request -> axios
109
+ - fix dependencies
110
+ - doc fixes
111
+
112
+ #### 1.6.*
113
+ - **--breakOnWarnings** and **--breakOnViolations**
114
+ - Bump devDependencies
84
115
 
85
- #### 1.5.1
116
+ #### 1.5.*
117
+ - Describe `Error: The programmatic API was removed in npm v8.0.0`
86
118
  - Bump devDependencies
87
119
  - Introduce sonarjs
88
120
 
89
- #### 1.4.3
121
+ #### 1.4.*
90
122
  - Bump glob-parent from 5.1.1 to 5.1.2
91
123
  - Bump path-parse from 1.0.6 to 1.0.7
92
-
93
- #### 1.4.2
94
124
  - Bump lodash from 4.17.19 to 4.17.21
95
-
96
- #### 1.4.1
97
125
  - Bump y18n from 4.0.0 to 4.0.1
98
-
99
- #### 1.4.0
100
126
  - Added:
101
127
  - option **--includeDevDependencies**. It is allow to scan dev dependencies
102
128
 
103
- #### 1.3.1
129
+ #### 1.3.*
104
130
  - Use [`global-npm`](https://github.com/dracupid/global-npm) (meaning `npm` is no longer a dependency of `ts-node-client`)
105
131
 
106
- #### 1.2.3
132
+ #### 1.2.*
107
133
  - Added:
108
134
  - option **--brakeOnViolations**. It is fail build in case any violations after scan transferred.
109
135
  - option **--brakeOnWarnings**. It is fail build in case any warning after scan transferred.
110
136
 
111
- #### 1.1.2
137
+ #### 1.1.*
112
138
  - userName is not required param for scans
113
139
  - Support usage of scan meta param binaryLinks inside Options definition
114
140
 
115
-
116
- #### 1.0.0
141
+ #### 1.0.*
117
142
  - Node JS and dependencies updates "node": ">= 8.12.0"
118
143
 
119
- #### 0.3.4 - 0.3.6
144
+ #### 0.3.*
120
145
  - Improve variable usage and tasks migration
121
-
122
- #### 0.3.3
123
146
  - Support usage of scan meta params: branch and tag inside Options definition
124
-
125
- #### 0.3.2
126
147
  - Skip npmDependency without names
127
-
128
- #### 0.3.1
129
148
  - Update travis config
130
-
131
- #### 0.3.0
132
149
  - Update dependency to resolve vulnerabilities
133
150
 
134
- #### 0.2.5
151
+ #### 0.2.*
135
152
  - Added proxy support and config
136
-
137
- #### 0.2.4
138
153
  - Update travis config
139
-
140
- #### 0.2.3
141
154
  - Updated README.md with `app.trustsource.io`
142
-
143
- #### 0.2.2
144
155
  - Updated default url to `app.trustsource.io`
145
-
146
- #### 0.2.1
147
156
  - Added windows support
148
157
  - Fixed json
149
-
150
- #### 0.2.0
151
158
  - **Removed:**
152
159
  - options: **--credentials** and **--credentialsFile** instead you should use **--config**.
153
160
  - option **--baseUrl** instead you should use **--url**.
@@ -54,12 +54,17 @@ const getOptions = () => {
54
54
  },
55
55
  proxy: {
56
56
  default: null,
57
- describe: 'Proxy url'
57
+ describe: 'Proxy url like \'https://user:password@host:port\''
58
58
  },
59
- version: {
60
- alias: 'v',
61
- default: false,
62
- describe: 'Prints a version'
59
+ saveAs: {
60
+ alias: 'o',
61
+ default: null,
62
+ describe: 'Save as file (file name prefix)'
63
+ },
64
+ saveAsFormat: {
65
+ alias: 'f',
66
+ default: null,
67
+ describe: 'Save as format (scan / cydx / spdx)'
63
68
  },
64
69
  debug: {
65
70
  default: null,
@@ -73,19 +78,20 @@ const getOptions = () => {
73
78
  default: null,
74
79
  describe: 'meteor'
75
80
  },
76
- brakeOnWarnings: {
81
+ breakOnWarnings: {
77
82
  default: null,
78
- describe: 'brakeOnWarnings'
83
+ describe: 'breakOnWarnings'
79
84
  },
80
- brakeOnViolations: {
85
+ breakOnViolations: {
81
86
  default: null,
82
- describe: 'brakeOnViolations'
87
+ describe: 'breakOnViolations'
83
88
  },
84
89
  includeDevDependencies: {
85
90
  default: null,
86
91
  describe: 'includeDevDependencies'
87
92
  }
88
93
  })
94
+ .version()
89
95
  .usage(pckgJson.description)
90
96
  .help('help', 'Prints a usage statement')
91
97
  .fail((msg, err, yargsObject) => {
@@ -100,10 +106,10 @@ const getOptions = () => {
100
106
  }
101
107
  options = (({
102
108
  // eslint-disable-next-line max-len
103
- apiKey, project, branch, tag, binaryLinks, config, debug, simulate, meteor, url, proxy, brakeOnWarnings, brakeOnViolations, includeDevDependencies
109
+ apiKey, project, branch, tag, binaryLinks, config, debug, saveAs, saveAsFormat, simulate, meteor, url, proxy, breakOnWarnings, breakOnViolations, includeDevDependencies
104
110
  }) => ({
105
111
  // eslint-disable-next-line max-len
106
- apiKey, project, branch, tag, binaryLinks, config, debug, simulate, scanMeteor: meteor, url, proxy, brakeOnWarnings, brakeOnViolations, includeDevDependencies
112
+ apiKey, project, branch, tag, binaryLinks, config, debug, saveAs, saveAsFormat, simulate, scanMeteor: meteor, url, proxy, breakOnWarnings, breakOnViolations, includeDevDependencies
107
113
  }))(options);
108
114
  Object.keys(options).forEach((key) => options[key] === null && delete options[key]);
109
115
  return options;
@@ -144,19 +150,21 @@ validateOptions(options);
144
150
 
145
151
  if (options.debug) {
146
152
  console.log('invoking ts-node-client: ');
147
- console.log(`${FILL}debug =`, options.debug);
148
- console.log(`${FILL}simulate =`, options.simulate);
149
- console.log(`${FILL}includeDevDependencies =`, options.includeDevDependencies);
150
- console.log(`${FILL}scanMeteor =`, options.scanMeteor);
151
- console.log(`${FILL}brakeOnViolations =`, options.brakeOnViolations);
152
- console.log(`${FILL}brakeOnWarnings =`, options.brakeOnWarnings);
153
- console.log(`${FILL}apiKey = |%s|`, options.apiKey);
154
- console.log(`${FILL}project = |%s|`, options.project);
155
- console.log(`${FILL}branch = |%s|`, options.branch);
156
- console.log(`${FILL}tag = |%s|`, options.tag);
157
- console.log(`${FILL}binaryLinks = |%s|`, options.binaryLinks);
158
- console.log(`${FILL}url = |%s|`, options.url);
159
- console.log(`${FILL}proxy = |%s|`, options.proxy);
153
+ console.log(`${FILL}debug = %s`, options.debug);
154
+ console.log(`${FILL}simulate = %s`, options.simulate);
155
+ console.log(`${FILL}includeDevDependencies = %s`, options.includeDevDependencies);
156
+ console.log(`${FILL}scanMeteor = %s`, options.scanMeteor);
157
+ console.log(`${FILL}saveAs = %s`, options.saveAs);
158
+ console.log(`${FILL}saveAsFormat = %s`, options.saveAsFormat);
159
+ console.log(`${FILL}breakOnViolations = %s`, options.breakOnViolations);
160
+ console.log(`${FILL}breakOnWarnings = %s`, options.breakOnWarnings);
161
+ console.log(`${FILL}apiKey = %s`, options.apiKey);
162
+ console.log(`${FILL}project = %s`, options.project);
163
+ console.log(`${FILL}branch = %s`, options.branch);
164
+ console.log(`${FILL}tag = %s`, options.tag);
165
+ console.log(`${FILL}binaryLinks = %s`, options.binaryLinks);
166
+ console.log(`${FILL}url = %s`, options.url);
167
+ console.log(`${FILL}proxy = %s`, options.proxy);
160
168
  }
161
169
 
162
170
  let exitCode = 0;
package/lib/cli.js CHANGED
@@ -7,6 +7,8 @@
7
7
  /* eslint-enable */
8
8
 
9
9
  const debuglog = (require('debuglog'))('ts-node-client');
10
+ const fs = require('fs');
11
+ const Convertor = require('./convertor');
10
12
 
11
13
  const stdlog = console.log;
12
14
  const MODULE_NAME = 'ts-node-client:cli';
@@ -47,6 +49,22 @@ function scan(options, scanDone) {
47
49
  return undefined;
48
50
  }
49
51
  return scanResult;
52
+ }).then((scanResult) => {
53
+ if (options.saveAs) {
54
+ const date = new Date();
55
+ let printData = JSON.stringify(scanResult, 0, 2);
56
+ let printExt = 'scan';
57
+ if (options.saveAsFormat) {
58
+ const allowedTypes = ['scan', 'spdx', 'cydx'];
59
+ if (allowedTypes.indexOf(options.saveAsFormat) > 0) {
60
+ printData = JSON.stringify(Convertor.scanTo(options.saveAsFormat, scanResult), 0, 2);
61
+ printExt = options.saveAsFormat;
62
+ }
63
+ }
64
+ const formatedDate = date.toISOString().substr(0, 19).split(':').join('-').split('T').join('-');
65
+ fs.writeFileSync(`${options.saveAs || 'ts-scan'}-${formatedDate}-${options.saveAsFormat ? printExt : 'scan'}.json`, printData);
66
+ }
67
+ return scanResult;
50
68
  }).then((scanResult) => {
51
69
  if (scanResult) {
52
70
  return npmScanner.transfer(scanResult);
@@ -0,0 +1,244 @@
1
+ /* eslint-disable */
2
+ /**********************************************************
3
+ * Copyright (c) 2017. Enterprise Architecture Group, EACG
4
+ *
5
+ * SPDX-License-Identifier: Apache-2.0
6
+ *********************************************************/
7
+ /* eslint-enable */
8
+ const PackageURL = require('./pkg');
9
+
10
+ const Convertor = {};
11
+
12
+ Convertor.scanTo = function scanTo(type, scan) {
13
+ if (type.toLowerCase() === 'cydx') {
14
+ return Convertor.scanToCydx(scan);
15
+ }
16
+ if (type.toLowerCase() === 'spdx') {
17
+ return Convertor.scanToSpdx(scan);
18
+ }
19
+ return scan;
20
+ };
21
+
22
+ function ComponentKey(key, parts) {
23
+ if (!key || typeof key.split !== 'function') {
24
+ // throw new Error('key must be a string');
25
+ } else {
26
+ parts = parts || { mgr: true, component: true, version: true };
27
+
28
+ const partsCnt = (parts.mgr ? 1 : 0) + (parts.component ? 1 : 0) + (parts.version ? 1 : 0);
29
+ const splitParts = key.split(':');
30
+ // component may exists of more than one part
31
+ if ((parts.component && splitParts.length < partsCnt) || (!parts.component && splitParts.length !== partsCnt)) {
32
+ // throw new Error('invalid key format:' + key);
33
+ } else {
34
+ let compStartIdx = 0; let
35
+ compEndIdx = splitParts.length;
36
+ if (parts.mgr) {
37
+ // eslint-disable-next-line prefer-destructuring
38
+ this.manager = splitParts[0];
39
+ // eslint-disable-next-line no-plusplus
40
+ compStartIdx++;
41
+ }
42
+ if (parts.version) {
43
+ this.version = splitParts[splitParts.length - 1];
44
+ // eslint-disable-next-line no-plusplus
45
+ compEndIdx--;
46
+ }
47
+ if (parts.component) {
48
+ this.component = '';
49
+ // eslint-disable-next-line no-plusplus
50
+ for (let i = compStartIdx; i < compEndIdx; i++) {
51
+ if (this.component) {
52
+ this.component += ':';
53
+ }
54
+ this.component += splitParts[i];
55
+ }
56
+ }
57
+ }
58
+ }
59
+ }
60
+
61
+ function getPackageUrl(componentKey, version) {
62
+ const result = new ComponentKey(componentKey, { mgr: true, component: true });
63
+ if (result && result.component && result.manager !== 'im') {
64
+ const parts = result.component.split(':');
65
+ const org = parts.length > 1 ? parts[0] : null;
66
+ const key = parts.length > 1 ? parts[1] : parts[0];
67
+ if (key) {
68
+ return PackageURL.get(result.manager, org, key, version);
69
+ }
70
+ return null;
71
+ }
72
+ return null;
73
+ }
74
+
75
+ function getSpdxFormattedKey(componentKey) {
76
+ return componentKey.split(':').join('-');
77
+ }
78
+
79
+ function dependencyToCydxComponent(dependency) {
80
+ const {
81
+ name, key, description, homepageUrl, repoUrl, licenses, versions
82
+ } = dependency;
83
+ const version = versions && versions[0];
84
+ const purl = getPackageUrl(key, version);
85
+ const comp = {
86
+ type: 'library',
87
+ 'bom-ref': purl,
88
+ name,
89
+ version,
90
+ description,
91
+ purl,
92
+ externalReferences: []
93
+ };
94
+ if (licenses && licenses[0] && licenses[0].name) {
95
+ comp.licenses = [
96
+ {
97
+ license: {
98
+ id: licenses[0].name
99
+ }
100
+ }
101
+ ];
102
+ }
103
+ if (repoUrl) {
104
+ comp.externalReferences.push({
105
+ type: 'vcs',
106
+ url: repoUrl
107
+ });
108
+ }
109
+ if (homepageUrl) {
110
+ comp.externalReferences.push({
111
+ type: 'website',
112
+ url: homepageUrl
113
+ });
114
+ }
115
+ return comp;
116
+ }
117
+
118
+ function dependencyToSpdxComponent(dependency) {
119
+ const {
120
+ name, key, homepageUrl, repoUrl, licenses, versions
121
+ } = dependency;
122
+ const version = versions && versions[0];
123
+ const comp = {
124
+ SPDXID: `SPDXRef-${getSpdxFormattedKey(key)}`,
125
+ // TODO implement Copyright meta
126
+ copyrightText: '',
127
+ filesAnalyzed: false,
128
+ name,
129
+ versionInfo: version
130
+ };
131
+ if (licenses && licenses[0] && licenses[0].name) {
132
+ comp.licenseConcluded = licenses[0].name;
133
+ comp.licenseDeclared = licenses[0].name;
134
+ comp.licenseInfoFromFiles = [licenses[0].name];
135
+ }
136
+ if (repoUrl) {
137
+ comp.downloadLocation = repoUrl;
138
+ }
139
+ if (homepageUrl) {
140
+ comp.homepage = homepageUrl;
141
+ }
142
+ return comp;
143
+ }
144
+
145
+ function handleDependency(list, dependency, type, relationships, parent) {
146
+ let component;
147
+ if (type === 'cydx') {
148
+ component = dependencyToCydxComponent(dependency);
149
+ } else if (type === 'spdx') {
150
+ component = dependencyToSpdxComponent(dependency);
151
+ } else {
152
+ component = dependency;
153
+ }
154
+ if (component) {
155
+ const hasComponent = list.find((item) => (item.SPDXID && item.SPDXID === component.SPDXID)
156
+ || (item['bom-ref'] && item['bom-ref'] === component['bom-ref']));
157
+ if (!hasComponent) {
158
+ list.push(component);
159
+ }
160
+ }
161
+ if (relationships && parent) {
162
+ if (parent.creationInfo) {
163
+ relationships.push({
164
+ spdxElementId: parent.SPDXID,
165
+ relatedSpdxElement: component.SPDXID,
166
+ relationshipType: 'DESCRIBES'
167
+ });
168
+ }
169
+ relationships.push({
170
+ spdxElementId: parent.SPDXID,
171
+ relatedSpdxElement: component.SPDXID,
172
+ relationshipType: 'CONTAINS'
173
+ });
174
+ }
175
+ if (dependency.dependencies) {
176
+ dependency.dependencies.forEach((child) => {
177
+ handleDependency(list, child, type, relationships, component);
178
+ });
179
+ }
180
+ }
181
+
182
+ Convertor.scanToCydx = function scanTo(scan) {
183
+ const date = new Date();
184
+ const cydx = {
185
+ bomFormat: 'CycloneDX',
186
+ specVersion: '1.3',
187
+ serialNumber: 'urn:uuid:ea788421-7eb0-448b-833e-b32dd0f39d0c',
188
+ version: 1,
189
+ metadata: {
190
+ timestamp: date.toISOString(),
191
+ tools: [
192
+ {
193
+ vendor: 'CycloneDX',
194
+ name: 'Node.js module',
195
+ version: '3.6.0'
196
+ }
197
+ ]
198
+ },
199
+ components: []
200
+ };
201
+ if (scan.dependencies && scan.dependencies[0]) {
202
+ cydx.components = [];
203
+ handleDependency(cydx.components, scan.dependencies[0], 'cydx');
204
+ if (cydx.components.length > 0) {
205
+ // eslint-disable-next-line prefer-destructuring
206
+ cydx.metadata.component = cydx.components[0];
207
+ cydx.components.shift();
208
+ }
209
+ }
210
+ return cydx;
211
+ };
212
+
213
+ Convertor.scanToSpdx = function scanTo(scan) {
214
+ const date = new Date();
215
+ const spdx = {
216
+ SPDXID: 'SPDXRef-DOCUMENT',
217
+ spdxVersion: 'SPDX-2.0',
218
+ creationInfo: {
219
+ created: date.toISOString(),
220
+ creators: [
221
+ 'Tool: ts-node-client > 1.8.1',
222
+ 'Organization: TrustSource'
223
+ ],
224
+ licenseListVersion: '2.5'
225
+ },
226
+ dataLicense: 'CC0-1.0'
227
+ };
228
+ if (scan.dependencies && scan.dependencies[0]) {
229
+ spdx.packages = [];
230
+ spdx.relationships = [];
231
+ handleDependency(spdx.packages, scan.dependencies[0], 'spdx', spdx.relationships, spdx);
232
+ if (spdx.packages.length > 0) {
233
+ const first = spdx.packages[0];
234
+ spdx.name = first.name;
235
+ spdx.documentDescribes = [first.SPDXID];
236
+ spdx.documentNamespace = `https://app.trustsource.io/spdx/${spdx.name}`;
237
+ }
238
+ }
239
+ return spdx;
240
+ };
241
+
242
+
243
+ module.exports = Convertor;
244
+
package/lib/dependency.js CHANGED
@@ -2,7 +2,7 @@
2
2
  /**********************************************************
3
3
  * Copyright (c) 2017. Enterprise Architecture Group, EACG
4
4
  *
5
- * SPDX-License-Identifier: Apache-2.0
5
+ * SPDX-License-Identifier: Apache-2.0
6
6
  *********************************************************/
7
7
  /* eslint-enable */
8
8
 
@@ -21,7 +21,9 @@ function Dependency(name, version, keyPrefix, description, priv, licenses, homep
21
21
  this.dependencies = [];
22
22
 
23
23
  Object.defineProperty(this, 'versions', {
24
- get() { return versions.sort(compare); },
24
+ get() {
25
+ return versions.sort(compare);
26
+ },
25
27
  enumerable: true
26
28
  });
27
29
 
package/lib/pkg.js ADDED
@@ -0,0 +1,32 @@
1
+ /* eslint-disable */
2
+ /**********************************************************
3
+ * Copyright (c) 2022. Enterprise Architecture Group, EACG
4
+ *
5
+ * SPDX-License-Identifier: Apache-2.0
6
+ *********************************************************/
7
+ /* eslint-enable */
8
+
9
+ const PackageURL = {};
10
+
11
+ PackageURL.get = function get(manager, org, key, version) {
12
+ // scheme:type/namespace/name@version?qualifiers#subpath
13
+ const parts = [];
14
+ let partVersion;
15
+ if (manager) {
16
+ parts.push(encodeURI(manager));
17
+ }
18
+ if (org) {
19
+ parts.push(encodeURI(org).replace('%3A', ':'));
20
+ }
21
+ if (key) {
22
+ parts.push(encodeURI(key).replace('%3A', ':'));
23
+ }
24
+ if (version) {
25
+ partVersion = `@${encodeURI(version).replace('%3A', ':')}`;
26
+ }
27
+ return `pkg:${parts.join('/')}${partVersion}`;
28
+ };
29
+
30
+
31
+ module.exports = PackageURL;
32
+
@@ -5,8 +5,7 @@
5
5
  * SPDX-License-Identifier: Apache-2.0
6
6
  *********************************************************/
7
7
  /* eslint-enable */
8
-
9
- const request = require('request');
8
+ const axios = require('axios').default;
10
9
  const debuglog = (require('debuglog'))('ts-rest-client');
11
10
  const pckgJson = require('../package.json');
12
11
 
@@ -21,7 +20,7 @@ function RestClient(options) {
21
20
  }
22
21
 
23
22
  function checkWarnings(options) {
24
- return options.brakeOnWarnings;
23
+ return options.breakOnWarnings;
25
24
  }
26
25
 
27
26
  function hasWarnings(analysis) {
@@ -30,7 +29,7 @@ function hasWarnings(analysis) {
30
29
  }
31
30
 
32
31
  function checkViolations(options) {
33
- return options.brakeOnViolations;
32
+ return options.breakOnViolations;
34
33
  }
35
34
 
36
35
  function hasViolations(analysis) {
@@ -38,45 +37,42 @@ function hasViolations(analysis) {
38
37
  return stats ? stats.legal.violations + stats.vulnerability.violations + stats.viability.violations + stats.versioning.violations : 0;
39
38
  }
40
39
 
41
- function checkAnalysisResults(options, getReqOpts, cb, error, response, body, i) {
42
- request(getReqOpts, (getError, getResponse, getBody) => {
43
- if (!getError && getResponse && getResponse.statusCode === 200 && getBody.analysisStatus === 'Finished') {
44
- if (checkViolations(options) && hasViolations(getBody)) {
45
- throw new Error(`Analysis found ${hasViolations(getBody)} violations, see more details: ${getBody.url}`);
46
- }
47
- if (checkWarnings(options) && hasWarnings(getBody)) {
48
- throw new Error(`Analysis found ${hasWarnings(getBody)} warnings, see more details: ${getBody.url}`);
49
- }
50
- // eslint-disable-next-line no-underscore-dangle
51
- getBody.scanId = getBody._id;
52
- cb(null, getBody);
53
- } else if (!getError && getResponse && (getResponse.statusCode === 200 || getResponse.statusCode === 404)) {
54
- const retryPeriod = i * 5000;
55
- console.log('Analysis is', (getBody.analysisStatus || 'Scheduled'), 'Retry in ', retryPeriod / 1000, 'sec');
56
- setTimeout(() => {
57
- i += 1;
58
- checkAnalysisResults(options, getReqOpts, cb, error, response, body, i);
59
- }, retryPeriod);
60
- } else {
61
- debuglog('unexpected getResponse: error=', getError, 'response=', getResponse);
62
- const result = {
63
- message: 'unexpected getResponse'
64
- };
65
- if (getError) {
66
- result.error = getError;
67
- }
68
- if (getResponse && getResponse.statusCode) {
69
- result.code = getResponse.statusCode;
70
- }
71
- if (getBody) {
72
- result.body = getBody;
40
+ function checkAnalysisResults(options, getReqOpts, cb, i) {
41
+ axios(getReqOpts)
42
+ .then((response) => {
43
+ const scanData = response && response.data;
44
+ if (response && response.status === 200 && scanData && scanData.analysisStatus === 'Finished') {
45
+ if (checkViolations(options) && hasViolations(scanData)) {
46
+ cb(`Analysis found ${hasViolations(scanData)} violations, see more details: ${response.data.url}`);
47
+ }
48
+ if (checkWarnings(options) && hasWarnings(scanData)) {
49
+ cb(`Analysis found ${hasWarnings(scanData)} warnings, see more details: ${response.data.url}`);
50
+ }
51
+ // eslint-disable-next-line no-underscore-dangle
52
+ cb(null, { scanId: scanData._id });
53
+ } else {
54
+ const retryPeriod = i * 5000;
55
+ console.log('Analysis is', ((scanData && scanData.analysisStatus) || 'Scheduled'), 'Retry in ', retryPeriod / 1000, 'sec');
56
+ setTimeout(() => {
57
+ i += 1;
58
+ checkAnalysisResults(options, getReqOpts, cb, i);
59
+ }, retryPeriod);
73
60
  }
74
- if (!result.code && !getError.error) {
75
- result.response = JSON.stringify(getResponse);
61
+ })
62
+ .catch((error) => {
63
+ const errorData = error && typeof error.toJSON === 'function' ? error.toJSON() : false;
64
+ if (errorData && (errorData.status === 404)) {
65
+ const retryPeriod = i * 5000;
66
+ console.log('Analysis is Scheduled', 'Retry in ', retryPeriod / 1000, 'sec');
67
+ setTimeout(() => {
68
+ i += 1;
69
+ checkAnalysisResults(options, getReqOpts, cb, i);
70
+ }, retryPeriod);
71
+ } else {
72
+ debuglog('unexpected getResponse: error=', error);
73
+ cb(JSON.stringify(error));
76
74
  }
77
- cb(result);
78
- }
79
- });
75
+ });
80
76
  }
81
77
 
82
78
  exports.RestClient = RestClient;
@@ -86,8 +82,8 @@ RestClient.prototype.transfer = function transfer(scan, cb) {
86
82
  debuglog('transfer started, options:', options);
87
83
 
88
84
  const reqOpts = options.requestOptions || {};
89
- reqOpts.method = 'POST';
90
- reqOpts.uri = `${options.url}/api/v1/scans`;
85
+ reqOpts.method = 'post';
86
+ reqOpts.url = `${options.url}/api/v1/scans`;
91
87
  if (options.proxy) {
92
88
  reqOpts.proxy = options.proxy;
93
89
  }
@@ -97,12 +93,12 @@ RestClient.prototype.transfer = function transfer(scan, cb) {
97
93
  'X-ApiKey': options.apiKey
98
94
  };
99
95
  reqOpts.json = true;
100
- reqOpts.body = scan;
96
+ reqOpts.data = scan;
101
97
  if (options.branch) {
102
- reqOpts.body.branch = options.branch;
98
+ reqOpts.data.branch = options.branch;
103
99
  }
104
100
  if (options.tag) {
105
- reqOpts.body.tag = options.tag;
101
+ reqOpts.data.tag = options.tag;
106
102
  }
107
103
  if (options.binaryLinks) {
108
104
  let links = options.binaryLinks.split(',');
@@ -110,40 +106,24 @@ RestClient.prototype.transfer = function transfer(scan, cb) {
110
106
  links = links.map((value) => ({
111
107
  name: value
112
108
  }));
113
- reqOpts.body.binaryLinks = links;
109
+ reqOpts.data.binaryLinks = links;
114
110
  }
115
111
  }
116
-
117
- request(reqOpts, (error, response, body) => {
118
- if (!error && response && response.statusCode === 201) {
119
- if (options.brakeOnWarnings || options.brakeOnViolations) {
112
+ return axios(reqOpts)
113
+ .then((response) => {
114
+ if (options.breakOnWarnings || options.breakOnViolations) {
120
115
  const getReqOpts = reqOpts;
121
- getReqOpts.method = 'GET';
122
- getReqOpts.uri += `/${body.scanId}`;
123
- delete getReqOpts.body;
116
+ getReqOpts.method = 'get';
117
+ getReqOpts.url += `/${response.data.scanId}`;
118
+ delete getReqOpts.data;
124
119
  let i = 1; // eslint-disable-line prefer-const
125
- checkAnalysisResults(options, getReqOpts, cb, error, response, body, i);
120
+ checkAnalysisResults(options, getReqOpts, cb, i);
126
121
  } else {
127
- cb(null, body);
128
- }
129
- } else {
130
- debuglog('unexpected response: error=', error, 'response=', response);
131
- const result = {
132
- message: 'unexpected response'
133
- };
134
- if (error) {
135
- result.error = error;
136
- }
137
- if (response && response.statusCode) {
138
- result.code = response.statusCode;
122
+ cb(null, response.data);
139
123
  }
140
- if (body) {
141
- result.body = body;
142
- }
143
- if (!result.code && !error.error) {
144
- result.response = JSON.stringify(response);
145
- }
146
- cb(result);
147
- }
148
- });
124
+ })
125
+ .catch((error) => {
126
+ debuglog('unexpected response: error=', error);
127
+ cb(JSON.stringify(error));
128
+ });
149
129
  };
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.0.0",
4
+ "version": "2.1.0",
5
5
  "private": false,
6
6
  "homepage": "https://app.trustsource.io/",
7
7
  "author": {
@@ -22,28 +22,27 @@
22
22
  },
23
23
  "scripts": {
24
24
  "scan": "node ./bin/ts-node-client.js",
25
- "scan-with-brakes": "ts-node-client --brakeOnViolations true --brakeOnWarnings true",
26
- "scan-prod": "ts-node-client --debug",
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",
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
- "debuglog": "^1.0.1",
34
- "npm": "6.14.15",
35
- "request": "^2.88.2",
36
- "semver": "^7.3.4",
37
- "yargs": "^15.4.1"
33
+ "npm": "6.14.17",
34
+ "axios": "0.26.1",
35
+ "debuglog": "1.0.1",
36
+ "semver": "7.3.5",
37
+ "yargs": "^17.5.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "eslint": "^7.32.0",
41
41
  "eslint-config-airbnb-base": "^14.2.1",
42
42
  "eslint-plugin-import": "^2.25.2",
43
43
  "eslint-plugin-sonarjs": "^0.10.0",
44
- "mocha": "^9.1.3",
45
- "nock": "^12.0.3",
46
- "ts-node-client": "1.5.2"
44
+ "mocha": "^9.2.2",
45
+ "nock": "^12.0.3"
47
46
  },
48
47
  "keywords": [
49
48
  "node",
@@ -51,6 +50,8 @@
51
50
  "meteor",
52
51
  "plugin",
53
52
  "opensource",
53
+ "cydx",
54
+ "spdx",
54
55
  "dependency-analysis"
55
56
  ]
56
57
  }
@@ -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
 
package/test/rest-test.js CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  const assert = require('assert');
11
11
  const nock = require('nock');
12
- const { RestClient } = require('../lib/rest-client');
12
+ const { RestClient } = require('../lib/rest-client');
13
13
 
14
14
  const JSON_TYPE = 'application/json';
15
15
  const url = 'http://localhost:3000';
@@ -39,10 +39,10 @@ describe('RestClient', () => {
39
39
  let restClient;
40
40
 
41
41
  beforeEach(() => {
42
- restClient = new RestClient({ url: 'http://localhost:3000' });
42
+ restClient = new RestClient({ url: 'http://localhost:3000', apiKey: 'test' });
43
43
  });
44
44
 
45
- it('should call callback with response data if no error orccurs', (done) => {
45
+ it('should call callback with response data if no error occurs', (done) => {
46
46
  nock(url, {
47
47
  reqheaders: {
48
48
  'Content-Type': JSON_TYPE