@teamscale/coverage-collector 0.0.1-beta.54 → 0.0.1-beta.55
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 +4 -4
- package/dist/package.json +27 -29
- package/dist/src/App.js +2 -2
- package/dist/src/receiver/CollectingServer.js +15 -14
- package/dist/src/receiver/Session.d.ts +2 -1
- package/dist/src/receiver/Session.js +2 -2
- package/dist/src/upload/CommonUpload.d.ts +1 -1
- package/dist/src/upload/CommonUpload.js +17 -16
- package/dist/src/utils/PrettyFileLogger.d.ts +1 -1
- package/dist/src/utils/PrettyFileLogger.js +1 -0
- package/dist/src/utils/StdConsoleLogger.d.ts +1 -1
- package/dist/src/utils/StdConsoleLogger.js +1 -0
- package/package.json +27 -29
package/README.md
CHANGED
|
@@ -19,12 +19,12 @@ information back to the original source code.
|
|
|
19
19
|
## Building
|
|
20
20
|
|
|
21
21
|
The Collector is written in TypeScript/JavaScript. For building and running it,
|
|
22
|
-
NodeJs (>=
|
|
22
|
+
NodeJs (>= v16) and pnpm are needed as prerequisites.
|
|
23
23
|
|
|
24
24
|
```
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
pnpm clean
|
|
26
|
+
pnpm install
|
|
27
|
+
pnpm build
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
## Running the Collector
|
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.55",
|
|
4
4
|
"description": "Collector for JavaScript code coverage information",
|
|
5
5
|
"main": "dist/src/main.js",
|
|
6
6
|
"bin": "dist/src/main.js",
|
|
@@ -12,53 +12,51 @@
|
|
|
12
12
|
"url": "https://github.com/cqse/teamscale-javascript-profiler.git"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
-
"prepublishOnly": "
|
|
15
|
+
"prepublishOnly": "pnpm clean && pnpm build",
|
|
16
16
|
"clean": "rimraf dist tsconfig.tsbuildinfo",
|
|
17
17
|
"build": "tsc",
|
|
18
18
|
"collector": "node dist/src/main.js",
|
|
19
|
-
"test": "
|
|
19
|
+
"test": "pnpm build && NODE_OPTIONS='--experimental-vm-modules' jest --coverage --silent=true --detectOpenHandles --forceExit"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
22
|
"dist/**/*"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@cqse/commons": "^0.0.1-beta.
|
|
25
|
+
"@cqse/commons": "^0.0.1-beta.54",
|
|
26
26
|
"argparse": "^2.0.1",
|
|
27
27
|
"async": "^3.2.4",
|
|
28
|
-
"axios": "^
|
|
28
|
+
"axios": "^1.4.0",
|
|
29
29
|
"bunyan": "^1.8.15",
|
|
30
|
-
"date-and-time": "^
|
|
31
|
-
"dotenv": "^
|
|
32
|
-
"express": "^4.18.
|
|
30
|
+
"date-and-time": "^3.0.2",
|
|
31
|
+
"dotenv": "^16.3.1",
|
|
32
|
+
"express": "^4.18.2",
|
|
33
33
|
"form-data": "^4.0.0",
|
|
34
|
-
"mkdirp": "^
|
|
35
|
-
"rxjs": "^7.1
|
|
34
|
+
"mkdirp": "^3.0.1",
|
|
35
|
+
"rxjs": "^7.8.1",
|
|
36
36
|
"source-map": "^0.7.4",
|
|
37
37
|
"tmp": "^0.2.1",
|
|
38
38
|
"typescript-optional": "^2.0.1",
|
|
39
|
-
"ws": "^
|
|
39
|
+
"ws": "^8.13.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@babel/core": "^7.
|
|
43
|
-
"@babel/preset-env": "^7.
|
|
44
|
-
"@types/argparse": "^2.0.
|
|
45
|
-
"@types/async": "^3.2.
|
|
42
|
+
"@babel/core": "^7.22.8",
|
|
43
|
+
"@babel/preset-env": "^7.22.7",
|
|
44
|
+
"@types/argparse": "^2.0.10",
|
|
45
|
+
"@types/async": "^3.2.20",
|
|
46
46
|
"@types/bunyan": "^1.8.8",
|
|
47
|
-
"@types/express": "^4.17.
|
|
48
|
-
"@types/jest": "^29.5.
|
|
49
|
-
"@types/
|
|
50
|
-
"@types/node": "^15.0.1",
|
|
51
|
-
"@types/source-map": "^0.5.7",
|
|
47
|
+
"@types/express": "^4.17.17",
|
|
48
|
+
"@types/jest": "^29.5.3",
|
|
49
|
+
"@types/node": "^20.4.1",
|
|
52
50
|
"@types/tmp": "^0.2.3",
|
|
53
|
-
"@types/ws": "^
|
|
54
|
-
"babel-jest": "^29.
|
|
55
|
-
"esbuild": "^0.
|
|
56
|
-
"jest": "^29.
|
|
57
|
-
"mockttp": "^3.7.
|
|
58
|
-
"rimraf": "^
|
|
59
|
-
"ts-jest": "^29.1.
|
|
60
|
-
"ts-node": "^10.
|
|
61
|
-
"typescript": "^
|
|
51
|
+
"@types/ws": "^8.5.5",
|
|
52
|
+
"babel-jest": "^29.6.1",
|
|
53
|
+
"esbuild": "^0.18.11",
|
|
54
|
+
"jest": "^29.6.1",
|
|
55
|
+
"mockttp": "^3.7.6",
|
|
56
|
+
"rimraf": "^5.0.1",
|
|
57
|
+
"ts-jest": "^29.1.1",
|
|
58
|
+
"ts-node": "^10.9.1",
|
|
59
|
+
"typescript": "^5.1.6"
|
|
62
60
|
},
|
|
63
61
|
"publishConfig": {
|
|
64
62
|
"access": "public"
|
package/dist/src/App.js
CHANGED
|
@@ -33,7 +33,7 @@ const CollectingServer_1 = require("./receiver/CollectingServer");
|
|
|
33
33
|
require("dotenv/config");
|
|
34
34
|
const fs = __importStar(require("fs"));
|
|
35
35
|
const ConfigParameters_1 = require("./utils/ConfigParameters");
|
|
36
|
-
const mkdirp_1 =
|
|
36
|
+
const mkdirp_1 = require("mkdirp");
|
|
37
37
|
const path_1 = __importDefault(require("path"));
|
|
38
38
|
const StdConsoleLogger_1 = require("./utils/StdConsoleLogger");
|
|
39
39
|
const PrettyFileLogger_1 = require("./utils/PrettyFileLogger");
|
|
@@ -58,7 +58,7 @@ class App {
|
|
|
58
58
|
*/
|
|
59
59
|
static buildLogger(config) {
|
|
60
60
|
const logfilePath = config.log_to_file.trim();
|
|
61
|
-
mkdirp_1.
|
|
61
|
+
mkdirp_1.mkdirp.sync(path_1.default.dirname(logfilePath));
|
|
62
62
|
const logLevel = config.log_level;
|
|
63
63
|
const logger = bunyan_1.default.createLogger({
|
|
64
64
|
name: 'Collector',
|
|
@@ -37,7 +37,7 @@ var ProtocolMessageTypes;
|
|
|
37
37
|
ProtocolMessageTypes["TYPE_SOURCEMAP"] = "s";
|
|
38
38
|
/** A message that provides coverage information */
|
|
39
39
|
ProtocolMessageTypes["TYPE_COVERAGE"] = "c";
|
|
40
|
-
})(ProtocolMessageTypes
|
|
40
|
+
})(ProtocolMessageTypes || (exports.ProtocolMessageTypes = ProtocolMessageTypes = {}));
|
|
41
41
|
/**
|
|
42
42
|
* Separates the instrumentation subject from the coverage information.
|
|
43
43
|
*/
|
|
@@ -58,7 +58,7 @@ class WebSocketCollectingServer {
|
|
|
58
58
|
commons_1.Contract.require(port > 0 && port < 65536, 'Port must be valid (range).');
|
|
59
59
|
this.storage = commons_1.Contract.requireDefined(storage);
|
|
60
60
|
this.logger = commons_1.Contract.requireDefined(logger);
|
|
61
|
-
this.server = new WebSocket.Server({ port
|
|
61
|
+
this.server = new WebSocket.Server({ port });
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
64
|
* Start the server socket, handle sessions and dispatch messages.
|
|
@@ -80,9 +80,9 @@ class WebSocketCollectingServer {
|
|
|
80
80
|
}
|
|
81
81
|
});
|
|
82
82
|
// Handle incoming messages
|
|
83
|
-
webSocket.on('message',
|
|
84
|
-
if (session &&
|
|
85
|
-
|
|
83
|
+
webSocket.on('message', (message) => {
|
|
84
|
+
if (session && Buffer.isBuffer(message)) {
|
|
85
|
+
void this.handleMessage(session, message);
|
|
86
86
|
}
|
|
87
87
|
});
|
|
88
88
|
// Handle errors
|
|
@@ -106,15 +106,16 @@ class WebSocketCollectingServer {
|
|
|
106
106
|
*/
|
|
107
107
|
async handleMessage(session, message) {
|
|
108
108
|
try {
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
const messageType = message.toString('utf8', 0, 1);
|
|
110
|
+
if (messageType.startsWith(ProtocolMessageTypes.TYPE_SOURCEMAP)) {
|
|
111
|
+
await this.handleSourcemapMessage(session, message.subarray(1));
|
|
111
112
|
}
|
|
112
|
-
else if (
|
|
113
|
-
await this.handleCoverageMessage(session, message.
|
|
113
|
+
else if (messageType.startsWith(ProtocolMessageTypes.TYPE_COVERAGE)) {
|
|
114
|
+
await this.handleCoverageMessage(session, message.subarray(1));
|
|
114
115
|
}
|
|
115
116
|
}
|
|
116
117
|
catch (e) {
|
|
117
|
-
this.logger.error(`Error while processing message starting with ${message.
|
|
118
|
+
this.logger.error(`Error while processing message starting with ${message.toString('utf8', 0, Math.min(50, message.length))}`);
|
|
118
119
|
this.logger.error(e.message);
|
|
119
120
|
}
|
|
120
121
|
}
|
|
@@ -125,11 +126,11 @@ class WebSocketCollectingServer {
|
|
|
125
126
|
* @param body - The body of the message (to be parsed).
|
|
126
127
|
*/
|
|
127
128
|
async handleSourcemapMessage(session, body) {
|
|
128
|
-
const fileIdSeparatorPosition = body.indexOf(INSTRUMENTATION_SUBJECT_SEPARATOR);
|
|
129
|
+
const fileIdSeparatorPosition = body.indexOf(INSTRUMENTATION_SUBJECT_SEPARATOR.charCodeAt(0));
|
|
129
130
|
if (fileIdSeparatorPosition > -1) {
|
|
130
|
-
const fileId = body.
|
|
131
|
+
const fileId = body.toString('utf8', 0, fileIdSeparatorPosition).trim();
|
|
131
132
|
this.logger.debug(`Received source map information for ${fileId}`);
|
|
132
|
-
const sourcemap = body.
|
|
133
|
+
const sourcemap = body.subarray(fileIdSeparatorPosition + 1);
|
|
133
134
|
await session.putSourcemap(fileId, sourcemap);
|
|
134
135
|
}
|
|
135
136
|
}
|
|
@@ -142,7 +143,7 @@ class WebSocketCollectingServer {
|
|
|
142
143
|
async handleCoverageMessage(session, body) {
|
|
143
144
|
var _a;
|
|
144
145
|
const bodyPattern = /(?<fileId>\S+) (?<positions>((\d+:\d+(:\d+:\d+)?\s+)*(\d+:\d+(:\d+:\d+)?)))/;
|
|
145
|
-
const matches = bodyPattern.exec(body);
|
|
146
|
+
const matches = bodyPattern.exec(body.toString());
|
|
146
147
|
if (matches === null || matches === void 0 ? void 0 : matches.groups) {
|
|
147
148
|
const fileId = matches.groups.fileId;
|
|
148
149
|
const positions = ((_a = matches.groups.positions) !== null && _a !== void 0 ? _a : '').split(/\s+/);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
2
3
|
import { Socket } from 'net';
|
|
3
4
|
import { IDataStorage } from '../storage/DataStorage';
|
|
4
5
|
import Logger from 'bunyan';
|
|
@@ -78,7 +79,7 @@ export declare class Session {
|
|
|
78
79
|
* @param fileId - The identifier of the file bundle.
|
|
79
80
|
* @param sourceMapText - The actual source map.
|
|
80
81
|
*/
|
|
81
|
-
putSourcemap(fileId: string, sourceMapText:
|
|
82
|
+
putSourcemap(fileId: string, sourceMapText: Buffer): Promise<void>;
|
|
82
83
|
private processUnmappedCoverageOf;
|
|
83
84
|
/**
|
|
84
85
|
* Destroy the session and free the memory it allocates.
|
|
@@ -137,7 +137,7 @@ class Session {
|
|
|
137
137
|
* @param sourceMapText - The actual source map.
|
|
138
138
|
*/
|
|
139
139
|
async putSourcemap(fileId, sourceMapText) {
|
|
140
|
-
const rawSourceMap = JSON.parse(sourceMapText);
|
|
140
|
+
const rawSourceMap = JSON.parse(sourceMapText.toString());
|
|
141
141
|
try {
|
|
142
142
|
const sourceMapConsumer = await new sourceMap.SourceMapConsumer(rawSourceMap);
|
|
143
143
|
this.sourceMaps.set(fileId, sourceMapConsumer);
|
|
@@ -150,7 +150,7 @@ class Session {
|
|
|
150
150
|
processUnmappedCoverageOf(fileId) {
|
|
151
151
|
var _a;
|
|
152
152
|
const unmapped = (_a = this.unmappedCoverage.get(fileId)) !== null && _a !== void 0 ? _a : [];
|
|
153
|
-
unmapped.forEach(
|
|
153
|
+
unmapped.forEach(entry => {
|
|
154
154
|
if (!this.putCoverage(entry.fileId, entry.startLine, entry.startColumn, entry.endLine, entry.endColumn)) {
|
|
155
155
|
this.storage.signalUnmappedCoverage(this.projectId);
|
|
156
156
|
}
|
|
@@ -13,4 +13,4 @@ export declare function prepareFormData(coverageFile: string): FormData;
|
|
|
13
13
|
/**
|
|
14
14
|
* Uploads a coverage file with the provided configuration.
|
|
15
15
|
*/
|
|
16
|
-
export declare function performUpload(url: string, form: FormData, config: AxiosRequestConfig<FormData>, uploadFunction: <T =
|
|
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>;
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.performUpload = exports.prepareFormData = exports.UploadError = void 0;
|
|
7
7
|
const form_data_1 = __importDefault(require("form-data"));
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const axios_1 = __importDefault(require("axios"));
|
|
9
10
|
const util_1 = require("util");
|
|
10
11
|
/**
|
|
11
12
|
* Error that is thrown when the upload failed
|
|
@@ -31,25 +32,25 @@ async function performUpload(url, form, config, uploadFunction, logger) {
|
|
|
31
32
|
logger.info(`Upload finished with code ${response.status}.`);
|
|
32
33
|
}
|
|
33
34
|
catch (error) {
|
|
34
|
-
if (error
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
+
}
|
|
38
44
|
}
|
|
39
|
-
else {
|
|
40
|
-
|
|
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}`);
|
|
41
51
|
}
|
|
42
52
|
}
|
|
43
|
-
|
|
44
|
-
throw new UploadError(`Upload request did not receive a response.`);
|
|
45
|
-
}
|
|
46
|
-
if (error.message) {
|
|
47
|
-
logger.debug(`Something went wrong when uploading data: ${error.message}. Details of the error: ${(0, util_1.inspect)(error)}`);
|
|
48
|
-
throw new UploadError(`Something went wrong when uploading data: ${error.message}`);
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
throw new UploadError(`Something went wrong when uploading data: ${(0, util_1.inspect)(error)}`);
|
|
52
|
-
}
|
|
53
|
+
throw new UploadError(`Something went wrong when uploading data: ${(0, util_1.inspect)(error)}`);
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
exports.performUpload = performUpload;
|
|
@@ -14,6 +14,7 @@ class PrettyFileLogger {
|
|
|
14
14
|
constructor(outputStream) {
|
|
15
15
|
this.outputStream = outputStream;
|
|
16
16
|
}
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
18
|
write(rec) {
|
|
18
19
|
this.outputStream.write(`[${rec.time.toISOString()}] ${bunyan_1.default.nameFromLevel[rec.level].toUpperCase()}: ${rec.msg}\n`);
|
|
19
20
|
}
|
|
@@ -8,6 +8,7 @@ const bunyan_1 = __importDefault(require("bunyan"));
|
|
|
8
8
|
require("dotenv/config");
|
|
9
9
|
/** Class for console logger. Doesn't print all information to ensure better readability. */
|
|
10
10
|
class StdConsoleLogger {
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
12
|
write(rec) {
|
|
12
13
|
console.log(`[${rec.time.toISOString()}] ${bunyan_1.default.nameFromLevel[rec.level].toUpperCase()}: ${rec.msg}`);
|
|
13
14
|
}
|
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.55",
|
|
4
4
|
"description": "Collector for JavaScript code coverage information",
|
|
5
5
|
"main": "dist/src/main.js",
|
|
6
6
|
"bin": "dist/src/main.js",
|
|
@@ -12,53 +12,51 @@
|
|
|
12
12
|
"url": "https://github.com/cqse/teamscale-javascript-profiler.git"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
-
"prepublishOnly": "
|
|
15
|
+
"prepublishOnly": "pnpm clean && pnpm build",
|
|
16
16
|
"clean": "rimraf dist tsconfig.tsbuildinfo",
|
|
17
17
|
"build": "tsc",
|
|
18
18
|
"collector": "node dist/src/main.js",
|
|
19
|
-
"test": "
|
|
19
|
+
"test": "pnpm build && NODE_OPTIONS='--experimental-vm-modules' jest --coverage --silent=true --detectOpenHandles --forceExit"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
22
|
"dist/**/*"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@cqse/commons": "^0.0.1-beta.
|
|
25
|
+
"@cqse/commons": "^0.0.1-beta.54",
|
|
26
26
|
"argparse": "^2.0.1",
|
|
27
27
|
"async": "^3.2.4",
|
|
28
|
-
"axios": "^
|
|
28
|
+
"axios": "^1.4.0",
|
|
29
29
|
"bunyan": "^1.8.15",
|
|
30
|
-
"date-and-time": "^
|
|
31
|
-
"dotenv": "^
|
|
32
|
-
"express": "^4.18.
|
|
30
|
+
"date-and-time": "^3.0.2",
|
|
31
|
+
"dotenv": "^16.3.1",
|
|
32
|
+
"express": "^4.18.2",
|
|
33
33
|
"form-data": "^4.0.0",
|
|
34
|
-
"mkdirp": "^
|
|
35
|
-
"rxjs": "^7.1
|
|
34
|
+
"mkdirp": "^3.0.1",
|
|
35
|
+
"rxjs": "^7.8.1",
|
|
36
36
|
"source-map": "^0.7.4",
|
|
37
37
|
"tmp": "^0.2.1",
|
|
38
38
|
"typescript-optional": "^2.0.1",
|
|
39
|
-
"ws": "^
|
|
39
|
+
"ws": "^8.13.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@babel/core": "^7.
|
|
43
|
-
"@babel/preset-env": "^7.
|
|
44
|
-
"@types/argparse": "^2.0.
|
|
45
|
-
"@types/async": "^3.2.
|
|
42
|
+
"@babel/core": "^7.22.8",
|
|
43
|
+
"@babel/preset-env": "^7.22.7",
|
|
44
|
+
"@types/argparse": "^2.0.10",
|
|
45
|
+
"@types/async": "^3.2.20",
|
|
46
46
|
"@types/bunyan": "^1.8.8",
|
|
47
|
-
"@types/express": "^4.17.
|
|
48
|
-
"@types/jest": "^29.5.
|
|
49
|
-
"@types/
|
|
50
|
-
"@types/node": "^15.0.1",
|
|
51
|
-
"@types/source-map": "^0.5.7",
|
|
47
|
+
"@types/express": "^4.17.17",
|
|
48
|
+
"@types/jest": "^29.5.3",
|
|
49
|
+
"@types/node": "^20.4.1",
|
|
52
50
|
"@types/tmp": "^0.2.3",
|
|
53
|
-
"@types/ws": "^
|
|
54
|
-
"babel-jest": "^29.
|
|
55
|
-
"esbuild": "^0.
|
|
56
|
-
"jest": "^29.
|
|
57
|
-
"mockttp": "^3.7.
|
|
58
|
-
"rimraf": "^
|
|
59
|
-
"ts-jest": "^29.1.
|
|
60
|
-
"ts-node": "^10.
|
|
61
|
-
"typescript": "^
|
|
51
|
+
"@types/ws": "^8.5.5",
|
|
52
|
+
"babel-jest": "^29.6.1",
|
|
53
|
+
"esbuild": "^0.18.11",
|
|
54
|
+
"jest": "^29.6.1",
|
|
55
|
+
"mockttp": "^3.7.6",
|
|
56
|
+
"rimraf": "^5.0.1",
|
|
57
|
+
"ts-jest": "^29.1.1",
|
|
58
|
+
"ts-node": "^10.9.1",
|
|
59
|
+
"typescript": "^5.1.6"
|
|
62
60
|
},
|
|
63
61
|
"publishConfig": {
|
|
64
62
|
"access": "public"
|