@teamscale/coverage-collector 0.0.1-beta.4 → 0.0.1-beta.42
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 +1 -6
- package/dist/package.json +14 -5
- package/dist/src/main.d.ts +9 -2
- package/dist/src/main.js +204 -28
- package/dist/src/receiver/CollectingServer.d.ts +1 -1
- package/dist/src/receiver/CollectingServer.js +13 -4
- package/dist/src/receiver/Session.d.ts +6 -4
- package/dist/src/receiver/Session.js +53 -10
- package/dist/src/storage/DataStorage.d.ts +31 -8
- package/dist/src/storage/DataStorage.js +62 -23
- package/dist/src/utils/PrettyFileLogger.d.ts +13 -0
- package/dist/src/utils/PrettyFileLogger.js +24 -0
- package/dist/src/utils/QueryParameters.d.ts +9 -0
- package/dist/src/utils/QueryParameters.js +19 -0
- package/dist/src/utils/StdConsoleLogger.d.ts +5 -0
- package/dist/src/utils/StdConsoleLogger.js +15 -0
- package/package.json +14 -5
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ files in the [Teamscale Simple Coverage Format](https://docs.teamscale.com/refer
|
|
|
9
9
|
The Teamscale JavaScript Profiler consists of this Coverage Collector and the
|
|
10
10
|
[JavaScript Instrumenter](https://www.npmjs.com/package/@teamscale/javascript-instrumenter).
|
|
11
11
|
More details on using them (in combination) can be found
|
|
12
|
-
|
|
12
|
+
in the [Teamscale Documentation](https://docs.teamscale.com/howto/recording-test-coverage-for-javascript/).
|
|
13
13
|
|
|
14
14
|
The JavaScript Coverage Collector starts a server process that listens for
|
|
15
15
|
code coverage information from manually or automatically exercised (tested)
|
|
@@ -49,8 +49,3 @@ for example, by setting a corresponding environment variable.
|
|
|
49
49
|
export NODE_OPTIONS="$NODE_OPTIONS --max-old-space-size=8192"
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
## Publishing
|
|
53
|
-
|
|
54
|
-
The list of files to publish is defined by the `files` attribute in `package.json`.
|
|
55
|
-
The actual files packed by npm can be listed by running `npx npm-packlist`.
|
|
56
|
-
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamscale/coverage-collector",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.42",
|
|
4
4
|
"description": "Collector for JavaScript code coverage information",
|
|
5
5
|
"main": "dist/src/main.js",
|
|
6
6
|
"bin": "dist/src/main.js",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"url": "https://github.com/cqse/teamscale-javascript-profiler.git"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
+
"prepublishOnly": "yarn clean && yarn build",
|
|
15
16
|
"clean": "rimraf dist tsconfig.tsbuildinfo",
|
|
16
17
|
"build": "tsc",
|
|
17
18
|
"collector": "node dist/src/main.js",
|
|
@@ -21,13 +22,19 @@
|
|
|
21
22
|
"dist/**/*"
|
|
22
23
|
],
|
|
23
24
|
"dependencies": {
|
|
24
|
-
"@cqse/commons": "^0.0.1-beta.
|
|
25
|
+
"@cqse/commons": "^0.0.1-beta.26",
|
|
25
26
|
"argparse": "^2.0.1",
|
|
26
|
-
"async": "^3.2.
|
|
27
|
+
"async": "^3.2.4",
|
|
28
|
+
"axios": "^0.24.0",
|
|
29
|
+
"bunyan": "^1.8.15",
|
|
30
|
+
"date-and-time": "^2.3.1",
|
|
31
|
+
"dotenv": "^14.1.0",
|
|
32
|
+
"form-data": "^4.0.0",
|
|
33
|
+
"mkdirp": "^1.0.4",
|
|
27
34
|
"rxjs": "^7.1.0",
|
|
28
35
|
"source-map": "^0.7.3",
|
|
36
|
+
"tmp": "^0.2.1",
|
|
29
37
|
"typescript-optional": "^2.0.1",
|
|
30
|
-
"winston": "^3.3.3",
|
|
31
38
|
"ws": "^7.4.5"
|
|
32
39
|
},
|
|
33
40
|
"devDependencies": {
|
|
@@ -35,10 +42,12 @@
|
|
|
35
42
|
"@babel/preset-env": "^7.14.1",
|
|
36
43
|
"@types/argparse": "^2.0.5",
|
|
37
44
|
"@types/async": "^3.2.6",
|
|
45
|
+
"@types/bunyan": "^1.8.8",
|
|
38
46
|
"@types/jest": "^27.0.1",
|
|
47
|
+
"@types/mkdirp": "^1.0.2",
|
|
39
48
|
"@types/node": "^15.0.1",
|
|
40
49
|
"@types/source-map": "^0.5.7",
|
|
41
|
-
"@types/
|
|
50
|
+
"@types/tmp": "^0.2.3",
|
|
42
51
|
"@types/ws": "^7.4.2",
|
|
43
52
|
"babel-jest": "^27.2.0",
|
|
44
53
|
"esbuild": "^0.13.4",
|
package/dist/src/main.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import 'dotenv/config';
|
|
2
3
|
/**
|
|
3
4
|
* The main class of the Teamscale JavaScript Collector.
|
|
4
|
-
* Used to start
|
|
5
|
+
* Used to start the collector for with a given configuration.
|
|
5
6
|
*/
|
|
6
7
|
export declare class Main {
|
|
8
|
+
private static readonly DEFAULT_COVERAGE_LOCATION;
|
|
7
9
|
/**
|
|
8
10
|
* Construct the object for parsing the command line arguments.
|
|
9
11
|
*/
|
|
@@ -23,9 +25,14 @@ export declare class Main {
|
|
|
23
25
|
/**
|
|
24
26
|
* Start a timer for dumping the data, depending on the configuration.
|
|
25
27
|
*
|
|
26
|
-
* @param config - The config that determines whether
|
|
28
|
+
* @param config - The config that determines whether to do the timed dump or not.
|
|
27
29
|
* @param storage - The storage with the information to dump.
|
|
28
30
|
* @param logger - The logger to use.
|
|
29
31
|
*/
|
|
30
32
|
private static maybeStartDumpTimer;
|
|
33
|
+
private static dumpCoverage;
|
|
34
|
+
private static uploadToTeamscale;
|
|
35
|
+
private static performTeamscaleUpload;
|
|
36
|
+
private static prepareQueryParameters;
|
|
37
|
+
private static prepareFormData;
|
|
31
38
|
}
|
package/dist/src/main.js
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
20
|
+
if (mod && mod.__esModule) return mod;
|
|
21
|
+
var result = {};
|
|
22
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
23
|
+
__setModuleDefault(result, mod);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
3
26
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
27
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
28
|
};
|
|
@@ -7,35 +30,100 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
30
|
exports.Main = void 0;
|
|
8
31
|
const package_json_1 = require("../package.json");
|
|
9
32
|
const argparse_1 = require("argparse");
|
|
10
|
-
const
|
|
33
|
+
const bunyan_1 = __importDefault(require("bunyan"));
|
|
11
34
|
const DataStorage_1 = require("./storage/DataStorage");
|
|
12
35
|
const CollectingServer_1 = require("./receiver/CollectingServer");
|
|
36
|
+
require("dotenv/config");
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const axios_1 = __importDefault(require("axios"));
|
|
39
|
+
const form_data_1 = __importDefault(require("form-data"));
|
|
40
|
+
const QueryParameters_1 = __importDefault(require("./utils/QueryParameters"));
|
|
41
|
+
const util_1 = require("util");
|
|
42
|
+
const mkdirp_1 = __importDefault(require("mkdirp"));
|
|
43
|
+
const path_1 = __importDefault(require("path"));
|
|
44
|
+
const StdConsoleLogger_1 = require("./utils/StdConsoleLogger");
|
|
45
|
+
const PrettyFileLogger_1 = require("./utils/PrettyFileLogger");
|
|
46
|
+
/**
|
|
47
|
+
* Error that is thrown when the upload to Teamscale failed
|
|
48
|
+
*/
|
|
49
|
+
class TeamscaleUploadError extends Error {
|
|
50
|
+
}
|
|
13
51
|
/**
|
|
14
52
|
* The main class of the Teamscale JavaScript Collector.
|
|
15
|
-
* Used to start
|
|
53
|
+
* Used to start the collector for with a given configuration.
|
|
16
54
|
*/
|
|
17
55
|
class Main {
|
|
18
56
|
/**
|
|
19
57
|
* Construct the object for parsing the command line arguments.
|
|
20
58
|
*/
|
|
21
59
|
static buildParser() {
|
|
60
|
+
var _a;
|
|
22
61
|
const parser = new argparse_1.ArgumentParser({
|
|
23
62
|
description: 'Collector of the Teamscale JavaScript Profiler. Collects coverage information from a' +
|
|
24
63
|
'(headless) Web browser that executes code instrumented with our instrumenter.'
|
|
25
64
|
});
|
|
26
65
|
parser.add_argument('-v', '--version', { action: 'version', version: package_json_1.version });
|
|
27
66
|
parser.add_argument('-p', '--port', { help: 'The port to receive coverage information on.', default: 54678 });
|
|
28
|
-
parser.add_argument('-f', '--dump-to-
|
|
67
|
+
parser.add_argument('-f', '--dump-to-folder', {
|
|
68
|
+
help: 'Target folder for coverage files.',
|
|
69
|
+
default: this.DEFAULT_COVERAGE_LOCATION
|
|
70
|
+
});
|
|
71
|
+
parser.add_argument('-k', '--keep-coverage-files', {
|
|
72
|
+
help: 'Whether to keep the coverage files on disk after a successful upload to Teamsacle',
|
|
73
|
+
action: 'store_true',
|
|
74
|
+
default: false
|
|
75
|
+
});
|
|
29
76
|
parser.add_argument('-l', '--log-to-file', { help: 'Log file', default: 'logs/collector-combined.log' });
|
|
30
77
|
parser.add_argument('-e', '--log-level', { help: 'Log level', default: 'info' });
|
|
31
|
-
parser.add_argument('-
|
|
32
|
-
help: 'Dump the coverage information to the target file every N
|
|
33
|
-
default:
|
|
78
|
+
parser.add_argument('-t', '--dump-after-mins', {
|
|
79
|
+
help: 'Dump the coverage information to the target file every N minutes.',
|
|
80
|
+
default: 360
|
|
34
81
|
});
|
|
35
82
|
parser.add_argument('-d', '--debug', {
|
|
36
83
|
help: 'Print received coverage information to the terminal?',
|
|
37
84
|
default: false
|
|
38
85
|
});
|
|
86
|
+
parser.add_argument('-j', '--json-log', {
|
|
87
|
+
help: 'Additional JSON-like log file format.',
|
|
88
|
+
action: 'store_true'
|
|
89
|
+
});
|
|
90
|
+
// Parameters for the upload to Teamscale
|
|
91
|
+
parser.add_argument('-u', '--teamscale-server-url', {
|
|
92
|
+
help: 'Upload the coverage to the given Teamscale server URL, for example, https://teamscale.dev.example.com:8080/production.',
|
|
93
|
+
default: process.env.TEAMSCALE_SERVER_URL
|
|
94
|
+
});
|
|
95
|
+
parser.add_argument('--teamscale-access-token', {
|
|
96
|
+
help: 'The API key to use for uploading to Teamscale.',
|
|
97
|
+
default: process.env.TEAMSCALE_ACCESS_TOKEN
|
|
98
|
+
});
|
|
99
|
+
parser.add_argument('--teamscale-project', {
|
|
100
|
+
help: 'The project ID to upload coverage to.',
|
|
101
|
+
default: process.env.TEAMSCALE_PROJECT
|
|
102
|
+
});
|
|
103
|
+
parser.add_argument('--teamscale-user', {
|
|
104
|
+
help: 'The user for uploading coverage to Teamscale.',
|
|
105
|
+
default: process.env.TEAMSCALE_USER
|
|
106
|
+
});
|
|
107
|
+
parser.add_argument('--teamscale-partition', {
|
|
108
|
+
help: 'The partition to upload coverage to.',
|
|
109
|
+
default: process.env.TEAMSCALE_PARTITION
|
|
110
|
+
});
|
|
111
|
+
parser.add_argument('--teamscale-revision', {
|
|
112
|
+
help: 'The revision (commit hash, version id) to upload coverage for.',
|
|
113
|
+
default: process.env.TEAMSCALE_REVISION
|
|
114
|
+
});
|
|
115
|
+
parser.add_argument('--teamscale-commit', {
|
|
116
|
+
help: 'The branch and timestamp to upload coverage for, separated by colon.',
|
|
117
|
+
default: process.env.TEAMSCALE_COMMIT
|
|
118
|
+
});
|
|
119
|
+
parser.add_argument('--teamscale-repository', {
|
|
120
|
+
help: 'The repository to upload coverage for. Optional: Only needed when uploading via revision to a project that has more than one connector.',
|
|
121
|
+
default: process.env.TEAMSCALE_REPOSITORY
|
|
122
|
+
});
|
|
123
|
+
parser.add_argument('--teamscale-message', {
|
|
124
|
+
help: 'The commit message shown within Teamscale for the coverage upload. Default is "JavaScript coverage upload".',
|
|
125
|
+
default: (_a = process.env.TEAMSCALE_MESSAGE) !== null && _a !== void 0 ? _a : 'JavaScript coverage upload'
|
|
126
|
+
});
|
|
39
127
|
return parser;
|
|
40
128
|
}
|
|
41
129
|
/**
|
|
@@ -49,16 +137,23 @@ class Main {
|
|
|
49
137
|
* Construct the logger.
|
|
50
138
|
*/
|
|
51
139
|
static buildLogger(config) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
140
|
+
const logfilePath = config.log_to_file.trim();
|
|
141
|
+
mkdirp_1.default.sync(path_1.default.dirname(logfilePath));
|
|
142
|
+
const logLevel = config.log_level;
|
|
143
|
+
const logger = bunyan_1.default.createLogger({
|
|
144
|
+
name: 'Collector',
|
|
145
|
+
streams: [
|
|
146
|
+
// console output
|
|
147
|
+
{ level: logLevel, stream: new StdConsoleLogger_1.StdConsoleLogger(), type: 'raw' },
|
|
148
|
+
// default log file
|
|
149
|
+
{ level: logLevel, stream: new PrettyFileLogger_1.PrettyFileLogger(fs.createWriteStream(logfilePath)), type: 'raw' }
|
|
60
150
|
]
|
|
61
151
|
});
|
|
152
|
+
// If the given flag is set, we also log with a JSON-like format
|
|
153
|
+
if (config.json_log) {
|
|
154
|
+
logger.addStream({ level: logLevel, path: `${logfilePath}.json` });
|
|
155
|
+
}
|
|
156
|
+
return logger;
|
|
62
157
|
}
|
|
63
158
|
/**
|
|
64
159
|
* Entry point of the Teamscale JavaScript Profiler.
|
|
@@ -79,7 +174,9 @@ class Main {
|
|
|
79
174
|
// Optionally, start a timer that dumps the coverage after a N seconds
|
|
80
175
|
this.maybeStartDumpTimer(config, storage, logger);
|
|
81
176
|
// Say bye bye on CTRL+C and exit the process
|
|
82
|
-
process.on('SIGINT', () => {
|
|
177
|
+
process.on('SIGINT', async () => {
|
|
178
|
+
// ... and do a final dump before.
|
|
179
|
+
await this.dumpCoverage(config, storage, logger).then();
|
|
83
180
|
logger.info('Bye bye.');
|
|
84
181
|
process.exit();
|
|
85
182
|
});
|
|
@@ -87,32 +184,111 @@ class Main {
|
|
|
87
184
|
/**
|
|
88
185
|
* Start a timer for dumping the data, depending on the configuration.
|
|
89
186
|
*
|
|
90
|
-
* @param config - The config that determines whether
|
|
187
|
+
* @param config - The config that determines whether to do the timed dump or not.
|
|
91
188
|
* @param storage - The storage with the information to dump.
|
|
92
189
|
* @param logger - The logger to use.
|
|
93
190
|
*/
|
|
94
191
|
static maybeStartDumpTimer(config, storage, logger) {
|
|
95
|
-
if (config.
|
|
192
|
+
if (config.dump_after_mins > 0) {
|
|
193
|
+
logger.info(`Will dump coverage information every ${config.dump_after_mins} minute(s).`);
|
|
96
194
|
const timer = setInterval(() => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
logger.info(`Conducted periodic coverage dump with ${lines} lines to ${config.dump_to_file}.`);
|
|
100
|
-
}
|
|
101
|
-
catch (e) {
|
|
102
|
-
logger.error('Timed coverage dump failed.', e);
|
|
103
|
-
}
|
|
104
|
-
}, config.dump_after_secs * 1000);
|
|
195
|
+
this.dumpCoverage(config, storage, logger).then();
|
|
196
|
+
}, config.dump_after_mins * 1000 * 60);
|
|
105
197
|
process.on('SIGINT', () => {
|
|
106
198
|
// Stop the timed file dump
|
|
107
199
|
if (timer) {
|
|
108
200
|
clearInterval(timer);
|
|
109
201
|
}
|
|
110
|
-
// ... and do a final dump
|
|
111
|
-
const written = storage.dumpToSimpleCoverageFile(config.dump_to_file);
|
|
112
|
-
logger.info(`\nCaught interrupt signal. Written ${written} lines of the latest coverage.`);
|
|
113
202
|
});
|
|
114
203
|
}
|
|
115
204
|
}
|
|
205
|
+
static async dumpCoverage(config, storage, logger) {
|
|
206
|
+
try {
|
|
207
|
+
// 1. Write coverage to a file
|
|
208
|
+
const [coverageFile, lines] = storage.dumpToSimpleCoverageFile(config.dump_to_folder, new Date());
|
|
209
|
+
logger.info(`Dumped ${lines} lines of coverage to ${coverageFile}.`);
|
|
210
|
+
// 2. Upload to Teamscale if configured
|
|
211
|
+
if (config.teamscale_server_url) {
|
|
212
|
+
await this.uploadToTeamscale(config, logger, coverageFile, lines);
|
|
213
|
+
// Delete coverage if upload was successful and keeping coverage files on disk was not configure by the user
|
|
214
|
+
if (!config.keep_coverage_files) {
|
|
215
|
+
fs.unlinkSync(coverageFile);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
catch (e) {
|
|
220
|
+
if (e instanceof TeamscaleUploadError) {
|
|
221
|
+
logger.error(`Teamscale upload failed. The coverage files on disk (inside the folder "${config.dump_to_folder}") were not deleted.
|
|
222
|
+
You can still upload them manually.`, e);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
logger.error('Coverage dump failed.', e);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
static async uploadToTeamscale(config, logger, coverageFile, lines) {
|
|
230
|
+
if (!(config.teamscale_access_token && config.teamscale_user && config.teamscale_server_url)) {
|
|
231
|
+
throw new TeamscaleUploadError('API key and user name must be configured!');
|
|
232
|
+
}
|
|
233
|
+
if (lines === 0) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
logger.info('Preparing upload to Teamscale');
|
|
237
|
+
const form = this.prepareFormData(coverageFile);
|
|
238
|
+
const queryParameters = this.prepareQueryParameters(config);
|
|
239
|
+
await this.performTeamscaleUpload(config, queryParameters, form, logger);
|
|
240
|
+
}
|
|
241
|
+
static async performTeamscaleUpload(config, parameters, form, logger) {
|
|
242
|
+
var _a, _b, _c;
|
|
243
|
+
await axios_1.default
|
|
244
|
+
.post(`${(_a = config.teamscale_server_url) === null || _a === void 0 ? void 0 : _a.replace(/\/$/, '')}/api/projects/${config.teamscale_project}/external-analysis/session/auto-create/report?${parameters.toString()}`, form, {
|
|
245
|
+
auth: {
|
|
246
|
+
username: (_b = config.teamscale_user) !== null && _b !== void 0 ? _b : 'no username provided',
|
|
247
|
+
password: (_c = config.teamscale_access_token) !== null && _c !== void 0 ? _c : 'no password provided'
|
|
248
|
+
},
|
|
249
|
+
headers: {
|
|
250
|
+
Accept: '*/*',
|
|
251
|
+
'Content-Type': `multipart/form-data; boundary=${form.getBoundary()}`
|
|
252
|
+
}
|
|
253
|
+
})
|
|
254
|
+
.catch(function (error) {
|
|
255
|
+
if (error.response) {
|
|
256
|
+
const response = error.response;
|
|
257
|
+
if (response.status >= 400) {
|
|
258
|
+
throw new TeamscaleUploadError(`Upload failed with code ${response.status}: ${response.statusText}. Response Data: ${response.data}`);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
logger.info(`Upload with status code ${response.status} finished.`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
else if (error.request) {
|
|
265
|
+
throw new TeamscaleUploadError(`Upload request did not receive a response.`);
|
|
266
|
+
}
|
|
267
|
+
if (error.message) {
|
|
268
|
+
logger.debug(`Something went wrong when uploading data: ${error.message}. Details of the error: ${(0, util_1.inspect)(error)}`);
|
|
269
|
+
throw new TeamscaleUploadError(`Something went wrong when uploading data: ${error.message}`);
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
throw new TeamscaleUploadError(`Something went wrong when uploading data: ${(0, util_1.inspect)(error)}`);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
static prepareQueryParameters(config) {
|
|
277
|
+
const parameters = new QueryParameters_1.default();
|
|
278
|
+
parameters.addIfDefined('format', 'SIMPLE');
|
|
279
|
+
parameters.addIfDefined('message', config.teamscale_message);
|
|
280
|
+
parameters.addIfDefined('repository', config.teamscale_repository);
|
|
281
|
+
parameters.addIfDefined('t', config.teamscale_commit);
|
|
282
|
+
parameters.addIfDefined('revision', config.teamscale_revision);
|
|
283
|
+
parameters.addIfDefined('partition', config.teamscale_partition);
|
|
284
|
+
return parameters;
|
|
285
|
+
}
|
|
286
|
+
static prepareFormData(coverageFile) {
|
|
287
|
+
const form = new form_data_1.default();
|
|
288
|
+
form.append('report', fs.createReadStream(coverageFile), 'coverage.simple');
|
|
289
|
+
return form;
|
|
290
|
+
}
|
|
116
291
|
}
|
|
117
292
|
exports.Main = Main;
|
|
293
|
+
Main.DEFAULT_COVERAGE_LOCATION = 'coverage';
|
|
118
294
|
Main.run();
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
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);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -129,14 +133,19 @@ class WebSocketCollectingServer {
|
|
|
129
133
|
*/
|
|
130
134
|
handleCoverageMessage(session, body) {
|
|
131
135
|
var _a;
|
|
132
|
-
const bodyPattern = /(?<fileId>\S+) (?<positions>((\d+:\d+)
|
|
136
|
+
const bodyPattern = /(?<fileId>\S+) (?<positions>((\d+:\d+(:\d+:\d+)?\s+)*(\d+:\d+(:\d+:\d+)?)))/;
|
|
133
137
|
const matches = bodyPattern.exec(body);
|
|
134
138
|
if (matches === null || matches === void 0 ? void 0 : matches.groups) {
|
|
135
139
|
const fileId = matches.groups.fileId;
|
|
136
140
|
const positions = ((_a = matches.groups.positions) !== null && _a !== void 0 ? _a : '').split(/\s+/);
|
|
137
141
|
for (const position of positions) {
|
|
138
|
-
const
|
|
139
|
-
|
|
142
|
+
const positionParts = position.split(':');
|
|
143
|
+
if (positionParts.length === 2) {
|
|
144
|
+
session.putCoverage(fileId, Number.parseInt(positionParts[0]), Number.parseInt(positionParts[1]), Number.parseInt(positionParts[1]), Number.parseInt(positionParts[2]));
|
|
145
|
+
}
|
|
146
|
+
else if (positionParts.length === 4) {
|
|
147
|
+
session.putCoverage(fileId, Number.parseInt(positionParts[0]), Number.parseInt(positionParts[1]), Number.parseInt(positionParts[2]), Number.parseInt(positionParts[3]));
|
|
148
|
+
}
|
|
140
149
|
}
|
|
141
150
|
}
|
|
142
151
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { Socket } from 'net';
|
|
3
3
|
import { IDataStorage } from '../storage/DataStorage';
|
|
4
|
-
import
|
|
4
|
+
import Logger from 'bunyan';
|
|
5
5
|
/**
|
|
6
6
|
* The session maintains the relevant information for a client.
|
|
7
7
|
* One session is created for each client.
|
|
@@ -43,10 +43,12 @@ export declare class Session {
|
|
|
43
43
|
* This method also conducts the mapping based on the source map.
|
|
44
44
|
*
|
|
45
45
|
* @param fileId - The identifier of the instrumented bundle (file).
|
|
46
|
-
* @param
|
|
47
|
-
* @param
|
|
46
|
+
* @param startLine - The line number within the bundle the range starts.
|
|
47
|
+
* @param startColumn - The column in the given `startLine` on that the range starts (inclusive).
|
|
48
|
+
* @param endLine - The line number within the bundle the range ends.
|
|
49
|
+
* @param endColumn - The column in the given `startLine` on that the range ends (inclusive).
|
|
48
50
|
*/
|
|
49
|
-
putCoverage(fileId: string,
|
|
51
|
+
putCoverage(fileId: string, startLine: number, startColumn: number, endLine: number, endColumn: number): void;
|
|
50
52
|
/**
|
|
51
53
|
* Map to the original file position.
|
|
52
54
|
*
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
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);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -47,16 +51,55 @@ class Session {
|
|
|
47
51
|
* This method also conducts the mapping based on the source map.
|
|
48
52
|
*
|
|
49
53
|
* @param fileId - The identifier of the instrumented bundle (file).
|
|
50
|
-
* @param
|
|
51
|
-
* @param
|
|
54
|
+
* @param startLine - The line number within the bundle the range starts.
|
|
55
|
+
* @param startColumn - The column in the given `startLine` on that the range starts (inclusive).
|
|
56
|
+
* @param endLine - The line number within the bundle the range ends.
|
|
57
|
+
* @param endColumn - The column in the given `startLine` on that the range ends (inclusive).
|
|
52
58
|
*/
|
|
53
|
-
putCoverage(fileId,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
putCoverage(fileId, startLine, startColumn, endLine, endColumn) {
|
|
60
|
+
var _a, _b;
|
|
61
|
+
// Iterate over the lines to scan
|
|
62
|
+
let line = startLine;
|
|
63
|
+
while (line <= endLine) {
|
|
64
|
+
// Determine the column range to consider for this line
|
|
65
|
+
let scanFromColumn;
|
|
66
|
+
if (line === startLine) {
|
|
67
|
+
scanFromColumn = startColumn;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
scanFromColumn = 0;
|
|
71
|
+
}
|
|
72
|
+
let scanToColumn;
|
|
73
|
+
if (line === endLine) {
|
|
74
|
+
scanToColumn = endColumn;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// Since we do not know the length of the different lines, we assume
|
|
78
|
+
// all to end in the lager of `endColumn` and `startColumn`.
|
|
79
|
+
// A better estimate (or the correct value) is supposed to be implemented
|
|
80
|
+
// in context of TS-30077.
|
|
81
|
+
scanToColumn = Math.max(endColumn, startColumn);
|
|
82
|
+
}
|
|
83
|
+
let column = scanFromColumn;
|
|
84
|
+
let lastCoveredLine = -1;
|
|
85
|
+
while (column <= scanToColumn) {
|
|
86
|
+
const originalPosition = this.mapToOriginal(fileId, line, column);
|
|
87
|
+
if (originalPosition.line && originalPosition.source) {
|
|
88
|
+
if (lastCoveredLine !== originalPosition.line) {
|
|
89
|
+
this.storage.putCoverage(this.projectId, originalPosition.source, [originalPosition.line]);
|
|
90
|
+
lastCoveredLine = originalPosition.line;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
this.storage.signalUnmappedCoverage(this.projectId);
|
|
95
|
+
}
|
|
96
|
+
// Step to the next column to map back to the original.
|
|
97
|
+
// `originalPosition.name` is the token on the position, that is, if it is present
|
|
98
|
+
// we increment the column by its length.
|
|
99
|
+
column = column + Math.max(1, (_b = (_a = originalPosition.name) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 1);
|
|
100
|
+
}
|
|
101
|
+
// And the next line
|
|
102
|
+
line++;
|
|
60
103
|
}
|
|
61
104
|
}
|
|
62
105
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Logger from 'bunyan';
|
|
2
2
|
/**
|
|
3
3
|
* Lines covered for the specified file.
|
|
4
4
|
*/
|
|
@@ -21,11 +21,14 @@ export interface IReadableStorage {
|
|
|
21
21
|
*/
|
|
22
22
|
getCoverageBySourceFile(project: string): IterableIterator<FileCoverage> | undefined;
|
|
23
23
|
/**
|
|
24
|
-
* Write the coverage to the specified file.
|
|
24
|
+
* Write the coverage to the specified file. A timestamp will be appended to the provided file path.
|
|
25
25
|
*
|
|
26
|
-
* @param
|
|
26
|
+
* @param coverageFolder - Full path of the file to write the coverage to.
|
|
27
|
+
* @param date - Date to use for the appended timestamp
|
|
28
|
+
*
|
|
29
|
+
* @return The number of lines written
|
|
27
30
|
*/
|
|
28
|
-
dumpToSimpleCoverageFile(
|
|
31
|
+
dumpToSimpleCoverageFile(coverageFolder: string, date: Date): [string, number];
|
|
29
32
|
}
|
|
30
33
|
/**
|
|
31
34
|
* Storage interface for writing information.
|
|
@@ -89,7 +92,7 @@ export declare class DataStorage implements IDataStorage {
|
|
|
89
92
|
/**
|
|
90
93
|
* Coverage information by project.
|
|
91
94
|
*/
|
|
92
|
-
private
|
|
95
|
+
private coverageByProject;
|
|
93
96
|
/**
|
|
94
97
|
* Logger to use.
|
|
95
98
|
*/
|
|
@@ -98,6 +101,10 @@ export declare class DataStorage implements IDataStorage {
|
|
|
98
101
|
* Times unmapped coverage received.
|
|
99
102
|
*/
|
|
100
103
|
private timesUnmappedCoverage;
|
|
104
|
+
/**
|
|
105
|
+
* Date format for the timestamp appended to the coverage files
|
|
106
|
+
*/
|
|
107
|
+
readonly DATE_FORMAT = "YYYY-MM-DD-HH-mm-ss.SSS";
|
|
101
108
|
/**
|
|
102
109
|
* Constructs the data storage.
|
|
103
110
|
*
|
|
@@ -118,7 +125,7 @@ export declare class DataStorage implements IDataStorage {
|
|
|
118
125
|
*
|
|
119
126
|
* @param sourceFile - The file name to normalize, produced by the instrumenter.
|
|
120
127
|
*/
|
|
121
|
-
private normalizeSourceFileName;
|
|
128
|
+
private static normalizeSourceFileName;
|
|
122
129
|
/**
|
|
123
130
|
* {@inheritDoc IWriteableStorage.signalUnmappedCoverage}
|
|
124
131
|
*/
|
|
@@ -128,9 +135,25 @@ export declare class DataStorage implements IDataStorage {
|
|
|
128
135
|
*/
|
|
129
136
|
getCoverageBySourceFile(project: string): IterableIterator<FileCoverage> | undefined;
|
|
130
137
|
/**
|
|
131
|
-
*
|
|
138
|
+
* @inheritDoc
|
|
139
|
+
*/
|
|
140
|
+
dumpToSimpleCoverageFile(coverageFolder: string, date: Date): [string, number];
|
|
141
|
+
/**
|
|
142
|
+
* Set the collected coverage to 0 for all projects
|
|
143
|
+
* @private
|
|
144
|
+
*/
|
|
145
|
+
private resetCoverage;
|
|
146
|
+
/**
|
|
147
|
+
* Appends the timestamp given with date to the coverageFolder (before the file ending if there is one)
|
|
148
|
+
* @param coverageFolder Path to the coverage file
|
|
149
|
+
* @param date Represents the timestamp to be appended with the format {@link DataStorage.DATE_FORMAT}
|
|
150
|
+
* @private
|
|
151
|
+
*/
|
|
152
|
+
private initCoverageFile;
|
|
153
|
+
/**
|
|
154
|
+
* Generate simple coverage format for the collected coverage
|
|
132
155
|
*/
|
|
133
|
-
|
|
156
|
+
private toSimpleCoverage;
|
|
134
157
|
/**
|
|
135
158
|
* {@inheritDoc IReadableStorage.getProjects}
|
|
136
159
|
*/
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
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);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -18,10 +22,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
18
22
|
__setModuleDefault(result, mod);
|
|
19
23
|
return result;
|
|
20
24
|
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
21
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
29
|
exports.DataStorage = exports.ProjectCoverage = void 0;
|
|
23
30
|
const commons_1 = require("@cqse/commons");
|
|
24
31
|
const fs = __importStar(require("fs"));
|
|
32
|
+
const path_1 = __importDefault(require("path"));
|
|
33
|
+
const dat = __importStar(require("date-and-time"));
|
|
25
34
|
/**
|
|
26
35
|
* The coverage information received for one particular project.
|
|
27
36
|
*/
|
|
@@ -77,6 +86,10 @@ class DataStorage {
|
|
|
77
86
|
* @param logger - The logger to use.
|
|
78
87
|
*/
|
|
79
88
|
constructor(logger) {
|
|
89
|
+
/**
|
|
90
|
+
* Date format for the timestamp appended to the coverage files
|
|
91
|
+
*/
|
|
92
|
+
this.DATE_FORMAT = 'YYYY-MM-DD-HH-mm-ss.SSS';
|
|
80
93
|
this.coverageByProject = new Map();
|
|
81
94
|
this.logger = commons_1.Contract.requireDefined(logger);
|
|
82
95
|
this.timesUnmappedCoverage = 0;
|
|
@@ -89,7 +102,7 @@ class DataStorage {
|
|
|
89
102
|
* @param coveredOriginalLines - The lines covered in the file.
|
|
90
103
|
*/
|
|
91
104
|
putCoverage(project, sourceFilePath, coveredOriginalLines) {
|
|
92
|
-
const uniformPath =
|
|
105
|
+
const uniformPath = DataStorage.normalizeSourceFileName(sourceFilePath);
|
|
93
106
|
let projectCoverage = this.coverageByProject.get(project);
|
|
94
107
|
if (!projectCoverage) {
|
|
95
108
|
projectCoverage = new ProjectCoverage(project);
|
|
@@ -104,7 +117,7 @@ class DataStorage {
|
|
|
104
117
|
*
|
|
105
118
|
* @param sourceFile - The file name to normalize, produced by the instrumenter.
|
|
106
119
|
*/
|
|
107
|
-
normalizeSourceFileName(sourceFile) {
|
|
120
|
+
static normalizeSourceFileName(sourceFile) {
|
|
108
121
|
return (0, commons_1.removePrefix)('webpack:///', sourceFile.replace('\\', '/'));
|
|
109
122
|
}
|
|
110
123
|
/**
|
|
@@ -125,29 +138,55 @@ class DataStorage {
|
|
|
125
138
|
return projectCoverage === null || projectCoverage === void 0 ? void 0 : projectCoverage.getCoverage();
|
|
126
139
|
}
|
|
127
140
|
/**
|
|
128
|
-
*
|
|
141
|
+
* @inheritDoc
|
|
129
142
|
*/
|
|
130
|
-
dumpToSimpleCoverageFile(
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
143
|
+
dumpToSimpleCoverageFile(coverageFolder, date) {
|
|
144
|
+
const [lines, content] = this.toSimpleCoverage();
|
|
145
|
+
const coverageFolderTrimmed = coverageFolder.trim();
|
|
146
|
+
const finalFilePath = this.initCoverageFile(coverageFolderTrimmed, date);
|
|
147
|
+
fs.writeFileSync(finalFilePath, content, { flag: 'w', encoding: 'utf8' });
|
|
148
|
+
this.resetCoverage();
|
|
149
|
+
return [finalFilePath, lines];
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Set the collected coverage to 0 for all projects
|
|
153
|
+
* @private
|
|
154
|
+
*/
|
|
155
|
+
resetCoverage() {
|
|
156
|
+
this.coverageByProject = new Map();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Appends the timestamp given with date to the coverageFolder (before the file ending if there is one)
|
|
160
|
+
* @param coverageFolder Path to the coverage file
|
|
161
|
+
* @param date Represents the timestamp to be appended with the format {@link DataStorage.DATE_FORMAT}
|
|
162
|
+
* @private
|
|
163
|
+
*/
|
|
164
|
+
initCoverageFile(coverageFolder, date) {
|
|
165
|
+
if (!fs.existsSync(coverageFolder)) {
|
|
166
|
+
fs.mkdirSync(coverageFolder);
|
|
167
|
+
}
|
|
168
|
+
const formattedDate = dat.format(date, this.DATE_FORMAT);
|
|
169
|
+
return path_1.default.join(coverageFolder, `coverage-${formattedDate}.simple`);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Generate simple coverage format for the collected coverage
|
|
173
|
+
*/
|
|
174
|
+
toSimpleCoverage() {
|
|
175
|
+
const result = [];
|
|
176
|
+
commons_1.Contract.require(this.getProjects().length < 2, 'Only one project supported to be handled in parallel.');
|
|
177
|
+
for (const project of this.getProjects()) {
|
|
178
|
+
const projectCoverage = this.getCoverageBySourceFile(project);
|
|
179
|
+
if (!projectCoverage) {
|
|
180
|
+
return [0, ''];
|
|
181
|
+
}
|
|
182
|
+
for (const entry of projectCoverage) {
|
|
183
|
+
result.push(DataStorage.normalizeSourceFileName(entry.sourceFile));
|
|
184
|
+
for (const lineNo of entry.coveredLines) {
|
|
185
|
+
result.push(String(lineNo));
|
|
144
186
|
}
|
|
145
187
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
const [lines, content] = toSimpleCoverage();
|
|
149
|
-
fs.writeFileSync(filePath.trim(), content, { flag: 'w', encoding: 'utf8' });
|
|
150
|
-
return lines;
|
|
188
|
+
}
|
|
189
|
+
return [result.length, result.join('\n')];
|
|
151
190
|
}
|
|
152
191
|
/**
|
|
153
192
|
* {@inheritDoc IReadableStorage.getProjects}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import 'dotenv/config';
|
|
3
|
+
import { WriteStream } from 'fs';
|
|
4
|
+
/**
|
|
5
|
+
* Class for log4j-like logger. Stream output shows less information than the
|
|
6
|
+
* standard JSON format of the bunyan logger and therefore has better readability.
|
|
7
|
+
*/
|
|
8
|
+
export declare class PrettyFileLogger {
|
|
9
|
+
outputStream: WriteStream;
|
|
10
|
+
constructor(outputStream: WriteStream);
|
|
11
|
+
write(rec: Record<any, any>): void;
|
|
12
|
+
end(): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PrettyFileLogger = void 0;
|
|
7
|
+
const bunyan_1 = __importDefault(require("bunyan"));
|
|
8
|
+
require("dotenv/config");
|
|
9
|
+
/**
|
|
10
|
+
* Class for log4j-like logger. Stream output shows less information than the
|
|
11
|
+
* standard JSON format of the bunyan logger and therefore has better readability.
|
|
12
|
+
*/
|
|
13
|
+
class PrettyFileLogger {
|
|
14
|
+
constructor(outputStream) {
|
|
15
|
+
this.outputStream = outputStream;
|
|
16
|
+
}
|
|
17
|
+
write(rec) {
|
|
18
|
+
this.outputStream.write(`[${rec.time.toISOString()}] ${bunyan_1.default.nameFromLevel[rec.level].toUpperCase()}: ${rec.msg}\n`);
|
|
19
|
+
}
|
|
20
|
+
end() {
|
|
21
|
+
this.outputStream.close();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.PrettyFileLogger = PrettyFileLogger;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Helper class for building HTTP query parameter strings.
|
|
5
|
+
*/
|
|
6
|
+
class QueryParameters extends URLSearchParams {
|
|
7
|
+
/**
|
|
8
|
+
* Adds a parameter if the value is defined.
|
|
9
|
+
*/
|
|
10
|
+
addIfDefined(key, value) {
|
|
11
|
+
if (value) {
|
|
12
|
+
this.append(key, value);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
this.delete(key);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.default = QueryParameters;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.StdConsoleLogger = void 0;
|
|
7
|
+
const bunyan_1 = __importDefault(require("bunyan"));
|
|
8
|
+
require("dotenv/config");
|
|
9
|
+
/** Class for console logger. Doesn't print all information to ensure better readability. */
|
|
10
|
+
class StdConsoleLogger {
|
|
11
|
+
write(rec) {
|
|
12
|
+
console.log(`[${rec.time.toISOString()}] ${bunyan_1.default.nameFromLevel[rec.level].toUpperCase()}: ${rec.msg}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.StdConsoleLogger = StdConsoleLogger;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamscale/coverage-collector",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.42",
|
|
4
4
|
"description": "Collector for JavaScript code coverage information",
|
|
5
5
|
"main": "dist/src/main.js",
|
|
6
6
|
"bin": "dist/src/main.js",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"url": "https://github.com/cqse/teamscale-javascript-profiler.git"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
+
"prepublishOnly": "yarn clean && yarn build",
|
|
15
16
|
"clean": "rimraf dist tsconfig.tsbuildinfo",
|
|
16
17
|
"build": "tsc",
|
|
17
18
|
"collector": "node dist/src/main.js",
|
|
@@ -21,13 +22,19 @@
|
|
|
21
22
|
"dist/**/*"
|
|
22
23
|
],
|
|
23
24
|
"dependencies": {
|
|
24
|
-
"@cqse/commons": "^0.0.1-beta.
|
|
25
|
+
"@cqse/commons": "^0.0.1-beta.26",
|
|
25
26
|
"argparse": "^2.0.1",
|
|
26
|
-
"async": "^3.2.
|
|
27
|
+
"async": "^3.2.4",
|
|
28
|
+
"axios": "^0.24.0",
|
|
29
|
+
"bunyan": "^1.8.15",
|
|
30
|
+
"date-and-time": "^2.3.1",
|
|
31
|
+
"dotenv": "^14.1.0",
|
|
32
|
+
"form-data": "^4.0.0",
|
|
33
|
+
"mkdirp": "^1.0.4",
|
|
27
34
|
"rxjs": "^7.1.0",
|
|
28
35
|
"source-map": "^0.7.3",
|
|
36
|
+
"tmp": "^0.2.1",
|
|
29
37
|
"typescript-optional": "^2.0.1",
|
|
30
|
-
"winston": "^3.3.3",
|
|
31
38
|
"ws": "^7.4.5"
|
|
32
39
|
},
|
|
33
40
|
"devDependencies": {
|
|
@@ -35,10 +42,12 @@
|
|
|
35
42
|
"@babel/preset-env": "^7.14.1",
|
|
36
43
|
"@types/argparse": "^2.0.5",
|
|
37
44
|
"@types/async": "^3.2.6",
|
|
45
|
+
"@types/bunyan": "^1.8.8",
|
|
38
46
|
"@types/jest": "^27.0.1",
|
|
47
|
+
"@types/mkdirp": "^1.0.2",
|
|
39
48
|
"@types/node": "^15.0.1",
|
|
40
49
|
"@types/source-map": "^0.5.7",
|
|
41
|
-
"@types/
|
|
50
|
+
"@types/tmp": "^0.2.3",
|
|
42
51
|
"@types/ws": "^7.4.2",
|
|
43
52
|
"babel-jest": "^27.2.0",
|
|
44
53
|
"esbuild": "^0.13.4",
|