@teamscale/coverage-collector 0.0.1-beta.6 → 0.0.1-beta.60

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.
@@ -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.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
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 = this.normalizeSourceFileName(sourceFilePath);
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
- * {@inheritDoc IReadableStorage.writeToSimpleCoverageFile}
141
+ * @inheritDoc
129
142
  */
130
- dumpToSimpleCoverageFile(filePath) {
131
- const toSimpleCoverage = () => {
132
- const result = [];
133
- commons_1.Contract.require(this.getProjects().length < 2, 'Only one project supported to be handled in parallel.');
134
- for (const project of this.getProjects()) {
135
- const projectCoverage = this.getCoverageBySourceFile(project);
136
- if (!projectCoverage) {
137
- return [0, ''];
138
- }
139
- for (const entry of projectCoverage) {
140
- result.push(this.normalizeSourceFileName(entry.sourceFile));
141
- for (const lineNo of entry.coveredLines) {
142
- result.push(String(lineNo));
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
- return [result.length, result.join('\n')];
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}
@@ -155,5 +194,11 @@ class DataStorage {
155
194
  getProjects() {
156
195
  return Array.from(this.coverageByProject.keys());
157
196
  }
197
+ /**
198
+ * {@inheritDoc IWritableStorage.discardCollectedCoverage}
199
+ */
200
+ discardCollectedCoverage() {
201
+ this.coverageByProject.clear();
202
+ }
158
203
  }
159
204
  exports.DataStorage = DataStorage;
@@ -0,0 +1,6 @@
1
+ import { ConfigParameters } from '../utils/ConfigParameters';
2
+ import Logger from 'bunyan';
3
+ /**
4
+ * Uploads a coverage file to artifactory with the provided configuration.
5
+ */
6
+ export declare function uploadToArtifactory(config: ConfigParameters, logger: Logger, coverageFile: string, lines: number): Promise<void>;
@@ -0,0 +1,66 @@
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.uploadToArtifactory = void 0;
7
+ const CommonUpload_1 = require("./CommonUpload");
8
+ const axios_1 = __importDefault(require("axios"));
9
+ const ProxyUpload_1 = require("./ProxyUpload");
10
+ /**
11
+ * Uploads a coverage file to artifactory with the provided configuration.
12
+ */
13
+ async function uploadToArtifactory(config, logger, coverageFile, lines) {
14
+ if (!(config.artifactory_access_token || (config.artifactory_user && config.artifactory_password))) {
15
+ throw new CommonUpload_1.UploadError('API key or user name and password must be configured!');
16
+ }
17
+ if (lines === 0) {
18
+ return;
19
+ }
20
+ logger.info('Preparing upload to Artifactory');
21
+ const form = (0, CommonUpload_1.prepareFormData)(coverageFile);
22
+ await performArtifactoryUpload(config, form, logger);
23
+ }
24
+ exports.uploadToArtifactory = uploadToArtifactory;
25
+ async function performArtifactoryUpload(config, form, logger) {
26
+ var _a;
27
+ if (!config.teamscale_commit) {
28
+ throw new CommonUpload_1.UploadError('The "--teamscale-commit" option must be set with a valid branch and timestamp.');
29
+ }
30
+ const branchAndTimestamp = config.teamscale_commit.split(':');
31
+ let url = `${(_a = config.artifactory_server_url) === null || _a === void 0 ? void 0 : _a.replace(/\/$/, '')}/uploads/${branchAndTimestamp[0]}/${branchAndTimestamp[1]}`;
32
+ if (config.teamscale_revision) {
33
+ url = url + `-${config.teamscale_revision}`;
34
+ }
35
+ url = url + `/${config.teamscale_partition}/simple`;
36
+ if (config.artifactory_path_suffix !== undefined) {
37
+ url = `${url}/${config.artifactory_path_suffix}`;
38
+ }
39
+ url = `${url}/report.simple`;
40
+ await (0, CommonUpload_1.performUpload)(url, form, prepareArtifactoryConfig(config, form), axios_1.default.put, logger);
41
+ }
42
+ function prepareArtifactoryConfig(config, form) {
43
+ var _a, _b;
44
+ const proxyConfig = (0, ProxyUpload_1.extractProxyOptions)(config);
45
+ if (config.artifactory_access_token) {
46
+ return {
47
+ headers: {
48
+ Accept: '*/*',
49
+ 'X-JFrog-Art-Api': config.artifactory_access_token,
50
+ 'Content-Type': `multipart/form-data; boundary=${form.getBoundary()}`
51
+ },
52
+ proxy: proxyConfig
53
+ };
54
+ }
55
+ return {
56
+ auth: {
57
+ username: (_a = config.artifactory_user) !== null && _a !== void 0 ? _a : 'no username provided',
58
+ password: (_b = config.artifactory_password) !== null && _b !== void 0 ? _b : 'no password provided'
59
+ },
60
+ headers: {
61
+ Accept: '*/*',
62
+ 'Content-Type': `multipart/form-data; boundary=${form.getBoundary()}`
63
+ },
64
+ proxy: proxyConfig
65
+ };
66
+ }
@@ -0,0 +1,16 @@
1
+ import FormData from 'form-data';
2
+ import Logger from 'bunyan';
3
+ import { AxiosRequestConfig, AxiosResponse } from 'axios';
4
+ /**
5
+ * Error that is thrown when the upload failed
6
+ */
7
+ export declare class UploadError extends Error {
8
+ }
9
+ /**
10
+ * Prepares the form data from a given configuration file for the upload.
11
+ */
12
+ export declare function prepareFormData(coverageFile: string): FormData;
13
+ /**
14
+ * Uploads a coverage file with the provided configuration.
15
+ */
16
+ export declare function performUpload(url: string, form: FormData, config: AxiosRequestConfig<FormData>, uploadFunction: <T = unknown, R = AxiosResponse<T>, D = FormData>(url: string, data?: D, config?: AxiosRequestConfig<D>) => Promise<R>, logger: Logger): Promise<void>;
@@ -0,0 +1,56 @@
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.performUpload = exports.prepareFormData = exports.UploadError = void 0;
7
+ const form_data_1 = __importDefault(require("form-data"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const axios_1 = __importDefault(require("axios"));
10
+ const util_1 = require("util");
11
+ /**
12
+ * Error that is thrown when the upload failed
13
+ */
14
+ class UploadError extends Error {
15
+ }
16
+ exports.UploadError = UploadError;
17
+ /**
18
+ * Prepares the form data from a given configuration file for the upload.
19
+ */
20
+ function prepareFormData(coverageFile) {
21
+ const form = new form_data_1.default();
22
+ form.append('report', fs_1.default.readFileSync(coverageFile), 'coverage.simple');
23
+ return form;
24
+ }
25
+ exports.prepareFormData = prepareFormData;
26
+ /**
27
+ * Uploads a coverage file with the provided configuration.
28
+ */
29
+ async function performUpload(url, form, config, uploadFunction, logger) {
30
+ try {
31
+ const response = await uploadFunction(url, form, config);
32
+ logger.info(`Upload finished with code ${response.status}.`);
33
+ }
34
+ catch (error) {
35
+ if (axios_1.default.isAxiosError(error)) {
36
+ if (error.response) {
37
+ const response = error.response;
38
+ if (response.status >= 400) {
39
+ throw new UploadError(`Upload failed with code ${response.status}: ${response.statusText}. Response Data: ${response.data}`);
40
+ }
41
+ else {
42
+ logger.info(`Upload with status code ${response.status} finished.`);
43
+ }
44
+ }
45
+ else if (error.request) {
46
+ throw new UploadError(`Upload request did not receive a response.`);
47
+ }
48
+ if (error.message) {
49
+ logger.debug(`Something went wrong when uploading data: ${error.message}. Details of the error: ${(0, util_1.inspect)(error)}`);
50
+ throw new UploadError(`Something went wrong when uploading data: ${error.message}`);
51
+ }
52
+ }
53
+ throw new UploadError(`Something went wrong when uploading data: ${(0, util_1.inspect)(error)}`);
54
+ }
55
+ }
56
+ exports.performUpload = performUpload;
@@ -0,0 +1,6 @@
1
+ import { ConfigParameters } from "../utils/ConfigParameters";
2
+ import { AxiosProxyConfig } from "axios";
3
+ /**
4
+ * Creates an AxiosProxyConfig object if proxy variables are provided.
5
+ */
6
+ export declare function extractProxyOptions(config: ConfigParameters): AxiosProxyConfig | undefined;
@@ -0,0 +1,30 @@
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.extractProxyOptions = void 0;
7
+ const url_1 = __importDefault(require("url"));
8
+ /**
9
+ * Creates an AxiosProxyConfig object if proxy variables are provided.
10
+ */
11
+ function extractProxyOptions(config) {
12
+ if (config.http_proxy) {
13
+ // Expected format: http://username:password@host:port/
14
+ // See https://nodejs.org/api/url.html#url-strings-and-url-objects for URL parsing
15
+ const proxyAddress = new url_1.default.URL(config.http_proxy);
16
+ const proxyConfig = {
17
+ protocol: proxyAddress.protocol.replace(':', ''),
18
+ host: proxyAddress.hostname,
19
+ port: +proxyAddress.port,
20
+ };
21
+ if (proxyAddress.username && proxyAddress.password) {
22
+ proxyConfig.auth = {
23
+ username: proxyAddress.username,
24
+ password: proxyAddress.password
25
+ };
26
+ }
27
+ return proxyConfig;
28
+ }
29
+ }
30
+ exports.extractProxyOptions = extractProxyOptions;
@@ -0,0 +1,6 @@
1
+ import { ConfigParameters } from '../utils/ConfigParameters';
2
+ import Logger from 'bunyan';
3
+ /**
4
+ * Uploads a coverage file to Teamscale with the provided configuration.
5
+ */
6
+ export declare function uploadToTeamscale(config: ConfigParameters, logger: Logger, coverageFile: string, lines: number): Promise<void>;
@@ -0,0 +1,54 @@
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.uploadToTeamscale = void 0;
7
+ const QueryParameters_1 = __importDefault(require("../utils/QueryParameters"));
8
+ const CommonUpload_1 = require("./CommonUpload");
9
+ const axios_1 = __importDefault(require("axios"));
10
+ const ProxyUpload_1 = require("./ProxyUpload");
11
+ /**
12
+ * Uploads a coverage file to Teamscale with the provided configuration.
13
+ */
14
+ async function uploadToTeamscale(config, logger, coverageFile, lines) {
15
+ if (!(config.teamscale_access_token && config.teamscale_user && config.teamscale_server_url)) {
16
+ throw new CommonUpload_1.UploadError('API key and user name must be configured!');
17
+ }
18
+ if (lines === 0) {
19
+ return;
20
+ }
21
+ logger.info('Preparing upload to Teamscale');
22
+ const form = (0, CommonUpload_1.prepareFormData)(coverageFile);
23
+ const queryParameters = prepareQueryParameters(config);
24
+ await performTeamscaleUpload(config, queryParameters, form, logger);
25
+ }
26
+ exports.uploadToTeamscale = uploadToTeamscale;
27
+ async function performTeamscaleUpload(config, parameters, form, logger) {
28
+ var _a;
29
+ await (0, CommonUpload_1.performUpload)(`${(_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, prepareTeamscaleConfig(config, form), axios_1.default.post, logger);
30
+ }
31
+ function prepareQueryParameters(config) {
32
+ const parameters = new QueryParameters_1.default();
33
+ parameters.addIfDefined('format', 'SIMPLE');
34
+ parameters.addIfDefined('message', config.teamscale_message);
35
+ parameters.addIfDefined('repository', config.teamscale_repository);
36
+ parameters.addIfDefined('t', config.teamscale_commit);
37
+ parameters.addIfDefined('revision', config.teamscale_revision);
38
+ parameters.addIfDefined('partition', config.teamscale_partition);
39
+ return parameters;
40
+ }
41
+ function prepareTeamscaleConfig(config, form) {
42
+ var _a, _b;
43
+ return {
44
+ auth: {
45
+ username: (_a = config.teamscale_user) !== null && _a !== void 0 ? _a : 'no username provided',
46
+ password: (_b = config.teamscale_access_token) !== null && _b !== void 0 ? _b : 'no password provided'
47
+ },
48
+ headers: {
49
+ Accept: '*/*',
50
+ 'Content-Type': `multipart/form-data; boundary=${form.getBoundary()}`
51
+ },
52
+ proxy: (0, ProxyUpload_1.extractProxyOptions)(config)
53
+ };
54
+ }
@@ -0,0 +1,36 @@
1
+ import { ArgumentParser } from 'argparse';
2
+ /**
3
+ * The command line parameters the profiler can be configured with.
4
+ *
5
+ * ATTENTION: We use snake_case here because ArgParse creates
6
+ * the parameters that way---as in Python from which ArgParse stems.
7
+ */
8
+ export type ConfigParameters = {
9
+ dump_to_folder: string;
10
+ log_to_file: string;
11
+ keep_coverage_files: boolean;
12
+ log_level: string;
13
+ dump_after_mins: number;
14
+ port: number;
15
+ json_log: boolean;
16
+ teamscale_server_url?: string;
17
+ teamscale_access_token?: string;
18
+ teamscale_project?: string;
19
+ teamscale_user?: string;
20
+ teamscale_partition?: string;
21
+ teamscale_revision?: string;
22
+ teamscale_commit?: string;
23
+ teamscale_repository?: string;
24
+ teamscale_message?: string;
25
+ artifactory_server_url?: string;
26
+ artifactory_user?: string;
27
+ artifactory_password?: string;
28
+ artifactory_access_token?: string;
29
+ artifactory_path_suffix?: string;
30
+ enable_control_port?: number;
31
+ http_proxy?: string;
32
+ };
33
+ /**
34
+ * Construct the object for parsing the command line arguments.
35
+ */
36
+ export declare function buildParameterParser(): ArgumentParser;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildParameterParser = void 0;
4
+ const argparse_1 = require("argparse");
5
+ const package_json_1 = require("../../package.json");
6
+ /**
7
+ * Construct the object for parsing the command line arguments.
8
+ */
9
+ function buildParameterParser() {
10
+ var _a;
11
+ const parser = new argparse_1.ArgumentParser({
12
+ description: 'Collector of the Teamscale JavaScript Profiler. Collects coverage information from a' +
13
+ '(headless) Web browser that executes code instrumented with our instrumenter.'
14
+ });
15
+ parser.add_argument('-v', '--version', { action: 'version', version: package_json_1.version });
16
+ parser.add_argument('-p', '--port', { help: 'The port to receive coverage information on.', default: 54678 });
17
+ parser.add_argument('-f', '--dump-to-folder', {
18
+ help: 'Target folder for coverage files.',
19
+ default: 'coverage'
20
+ });
21
+ parser.add_argument('-k', '--keep-coverage-files', {
22
+ help: 'Whether to keep the coverage files on disk after a successful upload to Teamsacle',
23
+ action: 'store_true',
24
+ default: false
25
+ });
26
+ parser.add_argument('-l', '--log-to-file', { help: 'Log file', default: 'logs/collector-combined.log' });
27
+ parser.add_argument('-e', '--log-level', { help: 'Log level', default: 'info' });
28
+ parser.add_argument('-c', '--enable-control-port', {
29
+ help: 'Enables the remote control API on the specified port (<=0 means "disabled").',
30
+ default: 0
31
+ });
32
+ parser.add_argument('-t', '--dump-after-mins', {
33
+ help: 'Dump the coverage information to the target file every N minutes.',
34
+ default: 360
35
+ });
36
+ parser.add_argument('-d', '--debug', {
37
+ help: 'Print received coverage information to the terminal?',
38
+ default: false
39
+ });
40
+ parser.add_argument('-j', '--json-log', {
41
+ help: 'Additional JSON-like log file format.',
42
+ action: 'store_true'
43
+ });
44
+ // Parameters for the upload to Teamscale
45
+ parser.add_argument('-u', '--teamscale-server-url', {
46
+ help: 'Upload the coverage to the given Teamscale server URL, for example, https://teamscale.dev.example.com:8080/production.',
47
+ default: process.env.TEAMSCALE_SERVER_URL
48
+ });
49
+ parser.add_argument('--teamscale-access-token', {
50
+ help: 'The API key to use for uploading to Teamscale.',
51
+ default: process.env.TEAMSCALE_ACCESS_TOKEN
52
+ });
53
+ parser.add_argument('--teamscale-project', {
54
+ help: 'The project ID to upload coverage to.',
55
+ default: process.env.TEAMSCALE_PROJECT
56
+ });
57
+ parser.add_argument('--teamscale-user', {
58
+ help: 'The user for uploading coverage to Teamscale.',
59
+ default: process.env.TEAMSCALE_USER
60
+ });
61
+ parser.add_argument('--teamscale-partition', {
62
+ help: 'The partition to upload coverage to.',
63
+ default: process.env.TEAMSCALE_PARTITION
64
+ });
65
+ parser.add_argument('--teamscale-revision', {
66
+ help: 'The revision (commit hash, version id) to upload coverage for.',
67
+ default: process.env.TEAMSCALE_REVISION
68
+ });
69
+ parser.add_argument('--teamscale-commit', {
70
+ help: 'The branch and timestamp to upload coverage for, separated by colon.',
71
+ default: process.env.TEAMSCALE_COMMIT
72
+ });
73
+ parser.add_argument('--teamscale-repository', {
74
+ help: 'The repository to upload coverage for. Optional: Only needed when uploading via revision to a project that has more than one connector.',
75
+ default: process.env.TEAMSCALE_REPOSITORY
76
+ });
77
+ parser.add_argument('--teamscale-message', {
78
+ help: 'The commit message shown within Teamscale for the coverage upload. Default is "JavaScript coverage upload".',
79
+ default: (_a = process.env.TEAMSCALE_MESSAGE) !== null && _a !== void 0 ? _a : 'JavaScript coverage upload'
80
+ });
81
+ parser.add_argument('--artifactory-server-url', {
82
+ help: 'Upload the coverage to the given Artifactory server URL. The URL may include a subpath on the artifactory server, e.g. https://artifactory.acme.com/my-repo/my/subpath',
83
+ default: process.env.ARTIFACTORY_SERVER_URL
84
+ });
85
+ parser.add_argument('--artifactory-user', {
86
+ help: 'The user for uploading coverage to Artifactory. Only needed when not using the --artifactory-access-token option',
87
+ default: process.env.ARTIFACTORY_USER
88
+ });
89
+ parser.add_argument('--artifactory-password', {
90
+ help: 'The password for uploading coverage to Artifactory. Only needed when not using the --artifactory-access-token option',
91
+ default: process.env.ARTIFACTORY_PASSWORD
92
+ });
93
+ parser.add_argument('--artifactory-access-token', {
94
+ help: 'The access_token for uploading coverage to Artifactory.',
95
+ default: process.env.ARTIFACTORY_ACCESS_TOKEN
96
+ });
97
+ parser.add_argument('--artifactory-path-suffix', {
98
+ help: '(optional): The path within the storage location between the default path and the uploaded artifact.',
99
+ default: process.env.ARTIFACTORY_PATH_SUFFIX
100
+ });
101
+ parser.add_argument('--http-proxy', {
102
+ help: '(optional): The HTTP/HTTPS proxy address that should be used in the format: http://host:port/ or http://username:password@host:port/.',
103
+ default: process.env.HTTP_PROXY
104
+ });
105
+ return parser;
106
+ }
107
+ exports.buildParameterParser = buildParameterParser;
@@ -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: any): void;
12
+ end(): void;
13
+ }
@@ -0,0 +1,25 @@
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
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ write(rec) {
19
+ this.outputStream.write(`[${rec.time.toISOString()}] ${bunyan_1.default.nameFromLevel[rec.level].toUpperCase()}: ${rec.msg}\n`);
20
+ }
21
+ end() {
22
+ this.outputStream.close();
23
+ }
24
+ }
25
+ exports.PrettyFileLogger = PrettyFileLogger;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Helper class for building HTTP query parameter strings.
3
+ */
4
+ export default class QueryParameters extends URLSearchParams {
5
+ /**
6
+ * Adds a parameter if the value is defined.
7
+ */
8
+ addIfDefined(key: string, value: string | undefined): void;
9
+ }
@@ -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,5 @@
1
+ import 'dotenv/config';
2
+ /** Class for console logger. Doesn't print all information to ensure better readability. */
3
+ export declare class StdConsoleLogger {
4
+ write(rec: any): void;
5
+ }
@@ -0,0 +1,16 @@
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
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ write(rec) {
13
+ console.log(`[${rec.time.toISOString()}] ${bunyan_1.default.nameFromLevel[rec.level].toUpperCase()}: ${rec.msg}`);
14
+ }
15
+ }
16
+ exports.StdConsoleLogger = StdConsoleLogger;