@teamscale/javascript-instrumenter 1.0.0-beta.6 → 1.0.4
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 +0 -25
- package/dist/main.mjs +216 -0
- package/dist/vaccine.js +1 -1
- package/package.json +28 -19
- package/dist/package.json +0 -69
- package/dist/src/App.d.ts +0 -52
- package/dist/src/App.d.ts.map +0 -1
- package/dist/src/App.js +0 -283
- package/dist/src/instrumenter/FileSystem.d.ts +0 -38
- package/dist/src/instrumenter/FileSystem.d.ts.map +0 -1
- package/dist/src/instrumenter/FileSystem.js +0 -134
- package/dist/src/instrumenter/Instrumenter.d.ts +0 -92
- package/dist/src/instrumenter/Instrumenter.d.ts.map +0 -1
- package/dist/src/instrumenter/Instrumenter.js +0 -376
- package/dist/src/instrumenter/InstrumenterConfig.d.ts +0 -37
- package/dist/src/instrumenter/InstrumenterConfig.d.ts.map +0 -1
- package/dist/src/instrumenter/InstrumenterConfig.js +0 -165
- package/dist/src/instrumenter/RelativeCollectorPatternParser.d.ts +0 -8
- package/dist/src/instrumenter/RelativeCollectorPatternParser.d.ts.map +0 -1
- package/dist/src/instrumenter/RelativeCollectorPatternParser.js +0 -53
- package/dist/src/instrumenter/RelativeCollectorPatternParser.test.d.ts +0 -2
- package/dist/src/instrumenter/RelativeCollectorPatternParser.test.d.ts.map +0 -1
- package/dist/src/instrumenter/RelativeCollectorPatternParser.test.js +0 -28
- package/dist/src/instrumenter/Task.d.ts +0 -224
- package/dist/src/instrumenter/Task.d.ts.map +0 -1
- package/dist/src/instrumenter/Task.js +0 -309
- package/dist/src/instrumenter/TaskBuilder.d.ts +0 -75
- package/dist/src/instrumenter/TaskBuilder.d.ts.map +0 -1
- package/dist/src/instrumenter/TaskBuilder.js +0 -228
- package/dist/src/instrumenter/WebToolkit.d.ts +0 -40
- package/dist/src/instrumenter/WebToolkit.d.ts.map +0 -1
- package/dist/src/instrumenter/WebToolkit.js +0 -146
- package/dist/src/main.d.ts +0 -3
- package/dist/src/main.d.ts.map +0 -1
- package/dist/src/main.js +0 -8
- package/dist/src/vaccine/types.d.ts +0 -65
- package/dist/src/vaccine/types.d.ts.map +0 -1
- package/dist/src/vaccine/types.js +0 -2
package/dist/vaccine.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";(()=>{function u(e){let n=new Blob([e],{type:"text/javascript"}),t=URL.createObjectURL(n),a=new Worker(t);return URL.revokeObjectURL(t),a}function h(){return u('var
|
|
1
|
+
"use strict";(()=>{function u(e){let n=new Blob([e],{type:"text/javascript"}),t=URL.createObjectURL(n),a=new Worker(t);return URL.revokeObjectURL(t),a}function h(){return u('var f=Object.defineProperty;var S=(o,e,t)=>e in o?f(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var n=(o,e,t)=>S(o,typeof e!="symbol"?e+"":e,t);var c=class{constructor(){n(this,"url");n(this,"socket");n(this,"cachedMessages");n(this,"messageOnConnect");n(this,"reconnectTimer");this.socket=null,this.url="",this.messageOnConnect="",this.cachedMessages=[],this.reconnectTimer=null}connect(e,t){this.url=e,this.messageOnConnect=t,this.socket=this.createSocket(),this.startReconnectTimer()}createSocket(){let e=new WebSocket(this.url);return e.onopen=()=>this.onopen(),e.onclose=()=>this.onclose(),e}startReconnectTimer(){this.reconnectTimer!==null&&clearInterval(this.reconnectTimer),this.reconnectTimer=setInterval(()=>{this.checkConnectionAndReconnect()},1e4)}checkConnectionAndReconnect(){var e;(this.socket===null||this.socket.readyState!==WebSocket.OPEN)&&((e=this.socket)==null||e.close(),console.log("Connection lost, attempting to reconnect..."),this.socket=this.createSocket())}onclose(){this.socket=this.createSocket()}onopen(){console.log("Connection to Coverage Collector established."),this.socket.send(this.messageOnConnect),this.cachedMessages.forEach(e=>this.socket.send(e)),this.cachedMessages=[]}send(e){if(this.socket!==null&&this.socket.readyState===WebSocket.OPEN)try{this.socket.send(e)}catch(t){console.error("Sending failed. Message will be re-sent when connection is available again.",t),this.addMessageToCache(e)}else this.addMessageToCache(e)}addMessageToCache(e){this.cachedMessages.push(e),this.cachedMessages.length%500===0&&console.log(`More than ${this.cachedMessages.length} messages are queued to be sent.`)}disconnect(){this.reconnectTimer!==null&&(clearInterval(this.reconnectTimer),this.reconnectTimer=null),this.socket!==null&&(this.socket.close(),this.socket=null)}};var a=class{constructor(e,t){this.milliseconds=e;this.onCountedToZero=t;n(this,"timerHandle",null)}restartCountdown(){this.stopCountdown(),this.timerHandle=self.setTimeout(()=>{this.stopCountdown(),this.onCountedToZero()},this.milliseconds)}stopCountdown(){this.timerHandle!==null&&(self.clearTimeout(this.timerHandle),this.timerHandle=null)}};var k=20,E=1e3,b="c",m="b",l=class{constructor(e){n(this,"socket");n(this,"flushCountdown");n(this,"cachedCoveredRanges");n(this,"numberOfCachedPositions");this.socket=e,this.cachedCoveredRanges=new Map,this.numberOfCachedPositions=0,this.flushCountdown=new a(E,()=>this.flush())}addLines(e,t){let s=this.cachedCoveredRanges.get(e);s||(s=new Set,this.cachedCoveredRanges.set(e,s)),t.forEach(i=>s.add(i)),this.numberOfCachedPositions+=1,this.flushCountdown.restartCountdown(),this.numberOfCachedPositions>=k&&this.flush()}arrayToLineCov(e){let t=[];for(let s of e)t.push(`${s}`);return t.join(";")}flush(){if(this.numberOfCachedPositions===0)return;this.flushCountdown.stopCountdown();let e=[];this.cachedCoveredRanges.forEach((t,s)=>{e.push(`@${s}`),e.push(this.arrayToLineCov(t))}),this.socket.send(`${b} ${e.join(";")}`),this.cachedCoveredRanges.clear(),this.numberOfCachedPositions=0}};var h=class o{static resolve(e,t,s){switch(e.type){case"url":return e.url;case"relative":return o.resolveRelative(t,s,e)}}static resolveRelative(e,t,s){var g;let i=e;s.hostReplace&&(i=e.replace(s.hostReplace.search,s.hostReplace.replace));let v=(g=s.scheme)!=null?g:"ws",r;s.port===void 0?r="":s.port==="keep"?r=`:${t}`:r=`:${s.port}`;let d="";s.path&&(d=`/${s.path}`);let u=`${v}://${i}${r}${d}`;return console.debug(`Resolved collector URL ${u} from ${e}:${t}`),u}};console.log("Starting coverage forwarding worker.");var C=new c,p=new l(C);onmessage=o=>{if(Array.isArray(o.data)){let[e,t]=o.data;p.addLines(e,t)}else if(o.data==="unload")p.flush();else if(o.data.type==="location"){let e=o.data,t=h.resolve($COLLECTOR_SPECIFIER,e.hostname,e.port),s=`${m} $BUCKET_SPECIFIER`;C.connect(`${t}/socket`,s)}else console.error(`No handler for message: ${o.data}`)};\n')}function c(){return d()}function d(){return window}function g(e,n){let t=c()[e];return t||(t=n,c()[e]=t),t}function p(e,n){let t=new Map;function a(i){let o=t.get(i);return o||(o={lines:new Set},t.set(i,o),o)}function r(i,o,k=o){let f=a(i).lines;for(let l=o;l<=k;l++)f.add(l);f.size>255&&s()}function s(){n(t),t.clear()}return setInterval(()=>s(),e),{putLineCoverage:r,flush:s}}var v=g("__TS_AGENT",{});function m(){return v._$BcWorker}function b(e){return v._$BcWorker=e,e}var C=p(250,e=>{for(let n of e.entries())m().postMessage([n[0],Array.from(n[1].lines)])});c()._$l=C.putLineCoverage;if(!m()){let e=b(new h),n={type:"location",hostname:document.location.hostname,port:document.location.port};e.postMessage(n),(function(){let a=()=>{C.flush(),e.postMessage("unload")},r=function(i,o){o&&o.addEventListener(i,a,{capture:!0})},s=d();r("blur",s),r("unload",s),r("visibilitychange",s),r("beforeunload",s)})()}})();
|
package/package.json
CHANGED
|
@@ -1,44 +1,53 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamscale/javascript-instrumenter",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "JavaScript coverage instrumenter with coverage forwarding to a collector process",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/main.mjs",
|
|
7
|
+
"bin": "dist/main.mjs",
|
|
8
8
|
"author": "CQSE GmbH",
|
|
9
9
|
"license": "Apache-2.0",
|
|
10
10
|
"homepage": "https://docs.teamscale.com/howto/setting-up-profiler-tga/javascript/",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"javascript",
|
|
13
|
+
"coverage",
|
|
14
|
+
"test coverage",
|
|
15
|
+
"coverage profiler",
|
|
16
|
+
"testing",
|
|
17
|
+
"instrumenter",
|
|
18
|
+
"teamscale"
|
|
19
|
+
],
|
|
11
20
|
"files": [
|
|
12
21
|
"dist/**/*"
|
|
13
22
|
],
|
|
14
23
|
"dependencies": {
|
|
15
|
-
"@babel/generator": "^7.
|
|
16
|
-
"@babel/parser": "^7.
|
|
17
|
-
"@babel/traverse": "^7.
|
|
18
|
-
"@babel/types": "^7.
|
|
19
|
-
"@types/micromatch": "^4.0.
|
|
24
|
+
"@babel/generator": "^7.28.5",
|
|
25
|
+
"@babel/parser": "^7.28.5",
|
|
26
|
+
"@babel/traverse": "^7.28.5",
|
|
27
|
+
"@babel/types": "^7.28.5",
|
|
28
|
+
"@types/micromatch": "^4.0.10",
|
|
20
29
|
"async": "^3.2.6",
|
|
21
30
|
"bunyan": "^1.8.15",
|
|
22
31
|
"convert-source-map": "^2.0.0",
|
|
23
|
-
"foreground-child": "^3.3.
|
|
24
|
-
"glob": "^11.0.1",
|
|
32
|
+
"foreground-child": "^3.3.1",
|
|
25
33
|
"micromatch": "4.0.8",
|
|
26
34
|
"mkdirp": "^3.0.1",
|
|
27
|
-
"source-map": "0.7.
|
|
35
|
+
"source-map": "0.7.6",
|
|
36
|
+
"tinyglobby": "^0.2.15",
|
|
28
37
|
"unload": "^2.4.1",
|
|
29
|
-
"uuid": "^
|
|
38
|
+
"uuid": "^13.0.0",
|
|
30
39
|
"web-worker": "^1.5.0",
|
|
31
|
-
"@cqse/commons": "1.0.
|
|
32
|
-
"@teamscale/lib-instrument": "1.0.
|
|
40
|
+
"@cqse/commons": "1.0.4",
|
|
41
|
+
"@teamscale/lib-instrument": "1.0.4"
|
|
33
42
|
},
|
|
34
43
|
"publishConfig": {
|
|
35
44
|
"access": "public"
|
|
36
45
|
},
|
|
37
46
|
"scripts": {
|
|
38
|
-
"clean": "rimraf dist
|
|
39
|
-
"build": "tsc --
|
|
47
|
+
"clean": "rimraf dist",
|
|
48
|
+
"build": "pnpm tsc --noEmit && pnpm tsdown && pnpm run buildVaccine",
|
|
40
49
|
"buildVaccine": "node esbuild.mjs",
|
|
41
|
-
"instrumenter": "node dist/
|
|
42
|
-
"test": "
|
|
50
|
+
"instrumenter": "node dist/main.mjs",
|
|
51
|
+
"test": "node --import tsx --test test/**/*.test.ts"
|
|
43
52
|
}
|
|
44
53
|
}
|
package/dist/package.json
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@teamscale/javascript-instrumenter",
|
|
3
|
-
"version": "1.0.0-beta.6",
|
|
4
|
-
"description": "JavaScript coverage instrumenter with coverage forwarding to a collector process",
|
|
5
|
-
"main": "dist/src/main.js",
|
|
6
|
-
"bin": "dist/src/main.js",
|
|
7
|
-
"types": "dist/src/main.d.ts",
|
|
8
|
-
"author": "CQSE GmbH",
|
|
9
|
-
"license": "Apache-2.0",
|
|
10
|
-
"homepage": "https://docs.teamscale.com/howto/setting-up-profiler-tga/javascript/",
|
|
11
|
-
"scripts": {
|
|
12
|
-
"prepublishOnly": "pnpm clean && pnpm build",
|
|
13
|
-
"clean": "rimraf dist tsconfig.tsbuildinfo",
|
|
14
|
-
"build": "tsc --project tsconfig.json && pnpm buildVaccine",
|
|
15
|
-
"buildVaccine": "node esbuild.mjs",
|
|
16
|
-
"instrumenter": "node dist/src/main.js",
|
|
17
|
-
"test": "pnpm build && NODE_OPTIONS='--experimental-vm-modules --max-old-space-size=8192' jest --forceExit --coverage --silent=true --detectOpenHandles"
|
|
18
|
-
},
|
|
19
|
-
"files": [
|
|
20
|
-
"dist/**/*"
|
|
21
|
-
],
|
|
22
|
-
"devDependencies": {
|
|
23
|
-
"@babel/core": "^7.26.8",
|
|
24
|
-
"@babel/plugin-transform-modules-commonjs": "^7.26.3",
|
|
25
|
-
"@babel/preset-env": "^7.26.8",
|
|
26
|
-
"@types/async": "^3.2.24",
|
|
27
|
-
"@types/babel__generator": "^7.6.8",
|
|
28
|
-
"@types/babel__traverse": "^7.20.6",
|
|
29
|
-
"@types/bunyan": "^1.8.11",
|
|
30
|
-
"@types/convert-source-map": "^2.0.3",
|
|
31
|
-
"@types/glob": "^9.0.0",
|
|
32
|
-
"@types/jest": "^29.5.14",
|
|
33
|
-
"@types/node": "^22.13.4",
|
|
34
|
-
"@types/ws": "^8.5.14",
|
|
35
|
-
"@types/uuid": "^10.0.0",
|
|
36
|
-
"babel-jest": "^29.7.0",
|
|
37
|
-
"esbuild": "^0.25.0",
|
|
38
|
-
"esbuild-plugin-inline-worker": "^0.1.1",
|
|
39
|
-
"jest": "^29.7.0",
|
|
40
|
-
"rimraf": "^6.0.1",
|
|
41
|
-
"ts-jest": "^29.2.5",
|
|
42
|
-
"ts-node": "^10.9.2",
|
|
43
|
-
"tslib": "^2.8.1",
|
|
44
|
-
"typescript": "^5.7.3"
|
|
45
|
-
},
|
|
46
|
-
"dependencies": {
|
|
47
|
-
"@cqse/commons": "workspace:../cqse-commons",
|
|
48
|
-
"@teamscale/lib-instrument": "workspace:../lib-instrument",
|
|
49
|
-
"@babel/generator": "^7.26.8",
|
|
50
|
-
"@babel/parser": "^7.26.8",
|
|
51
|
-
"@babel/traverse": "^7.26.8",
|
|
52
|
-
"@babel/types": "^7.26.8",
|
|
53
|
-
"@types/micromatch": "^4.0.9",
|
|
54
|
-
"async": "^3.2.6",
|
|
55
|
-
"bunyan": "^1.8.15",
|
|
56
|
-
"convert-source-map": "^2.0.0",
|
|
57
|
-
"foreground-child": "^3.3.0",
|
|
58
|
-
"glob": "^11.0.1",
|
|
59
|
-
"micromatch": "4.0.8",
|
|
60
|
-
"mkdirp": "^3.0.1",
|
|
61
|
-
"source-map": "0.7.4",
|
|
62
|
-
"unload": "^2.4.1",
|
|
63
|
-
"uuid": "^11.1.0",
|
|
64
|
-
"web-worker": "^1.5.0"
|
|
65
|
-
},
|
|
66
|
-
"publishConfig": {
|
|
67
|
-
"access": "public"
|
|
68
|
-
}
|
|
69
|
-
}
|
package/dist/src/App.d.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { TaskResult } from './instrumenter/Task';
|
|
2
|
-
import Logger from 'bunyan';
|
|
3
|
-
import { InstrumenterOptions } from './instrumenter/InstrumenterConfig';
|
|
4
|
-
/**
|
|
5
|
-
* Entry points of the instrumenter, including command line argument parsing.
|
|
6
|
-
*/
|
|
7
|
-
export declare class App {
|
|
8
|
-
/**
|
|
9
|
-
* Main function of the instrumenter.
|
|
10
|
-
* Parses the command line options and the instrumentation accordingly.
|
|
11
|
-
*/
|
|
12
|
-
static run(): Promise<TaskResult>;
|
|
13
|
-
/**
|
|
14
|
-
* Runs the application with for the given command line arguments. Visible for testing.
|
|
15
|
-
*/
|
|
16
|
-
static runForArgv(argv: string[]): Promise<TaskResult>;
|
|
17
|
-
/**
|
|
18
|
-
* Parses the command-line arguments.
|
|
19
|
-
*
|
|
20
|
-
* @param args - Optional. For testing. If given, uses this as the arguments to parse and does not exit the process on errors.
|
|
21
|
-
* If not given, uses the NodeJS process's arguments and exits on errors.
|
|
22
|
-
* @param beforeArgumentCheckCallback - To be executed before the arguments are checked for validity.
|
|
23
|
-
*/
|
|
24
|
-
static parseCommandLine(args?: string[], beforeArgumentCheckCallback?: (options: InstrumenterOptions) => void): InstrumenterOptions;
|
|
25
|
-
/**
|
|
26
|
-
* Sometimes we get inputs from shell environments where the strings are
|
|
27
|
-
* still quoted. We remove those here.
|
|
28
|
-
*/
|
|
29
|
-
static postprocessConfig(config: InstrumenterOptions): void;
|
|
30
|
-
/**
|
|
31
|
-
* Construct the logger.
|
|
32
|
-
*/
|
|
33
|
-
private static buildLogger;
|
|
34
|
-
/**
|
|
35
|
-
* A logger for testing.
|
|
36
|
-
*/
|
|
37
|
-
private static buildDummyLogger;
|
|
38
|
-
/**
|
|
39
|
-
* The instrumenter can also be started by providing the configuration dictionary explicitly.
|
|
40
|
-
*
|
|
41
|
-
* @param config - The dictionary with all configuration arguments.
|
|
42
|
-
* @param logger - The logger to use.
|
|
43
|
-
*/
|
|
44
|
-
static runForConfigArguments(config: InstrumenterOptions, logger?: Logger): Promise<TaskResult>;
|
|
45
|
-
private static createInstrumentationTask;
|
|
46
|
-
private static createInstrumenter;
|
|
47
|
-
/**
|
|
48
|
-
* Processes the task result and produces console outputs, and possibly a process exit with a corresponding code.
|
|
49
|
-
*/
|
|
50
|
-
private static finalizeAppRunWithConsoleOutputs;
|
|
51
|
-
}
|
|
52
|
-
//# sourceMappingURL=App.d.ts.map
|
package/dist/src/App.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/App.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAYtE,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAA4C,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAGlH;;GAEG;AACH,qBAAa,GAAG;IACf;;;OAGG;WACiB,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC;IAI9C;;OAEG;WACiB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;IA2BnE;;;;;;OAMG;WACW,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,2BAA2B,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,GAAG,mBAAmB;IAM1I;;;OAGG;WACW,iBAAiB,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI;IAwClE;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IA+B1B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAI/B;;;;;OAKG;WACW,qBAAqB,CAAC,MAAM,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAqCtG,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAIxC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAcjC;;OAEG;mBACkB,gCAAgC;CAmDrD"}
|
package/dist/src/App.js
DELETED
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = 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);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.App = void 0;
|
|
40
|
-
const Instrumenter_1 = require("./instrumenter/Instrumenter");
|
|
41
|
-
const commons_1 = require("@cqse/commons");
|
|
42
|
-
const TaskBuilder_1 = require("./instrumenter/TaskBuilder");
|
|
43
|
-
const path = __importStar(require("path"));
|
|
44
|
-
const package_json_1 = require("../package.json");
|
|
45
|
-
const fs_1 = require("fs");
|
|
46
|
-
const mkdirp_1 = require("mkdirp");
|
|
47
|
-
const bunyan_1 = __importDefault(require("bunyan"));
|
|
48
|
-
const InstrumenterConfig_1 = require("./instrumenter/InstrumenterConfig");
|
|
49
|
-
const process = __importStar(require("node:process"));
|
|
50
|
-
/**
|
|
51
|
-
* Entry points of the instrumenter, including command line argument parsing.
|
|
52
|
-
*/
|
|
53
|
-
class App {
|
|
54
|
-
/**
|
|
55
|
-
* Main function of the instrumenter.
|
|
56
|
-
* Parses the command line options and the instrumentation accordingly.
|
|
57
|
-
*/
|
|
58
|
-
static async run() {
|
|
59
|
-
return this.runForArgv(process.argv);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Runs the application with for the given command line arguments. Visible for testing.
|
|
63
|
-
*/
|
|
64
|
-
static async runForArgv(argv) {
|
|
65
|
-
const config = this.parseCommandLine(argv.slice(2), options => {
|
|
66
|
-
if (options.collectorOptionsList) {
|
|
67
|
-
const collectorParameters = (0, commons_1.buildReconfigurableCollectorParameters)();
|
|
68
|
-
(0, commons_1.printHelp)(collectorParameters, undefined, true);
|
|
69
|
-
console.log("");
|
|
70
|
-
console.log("ATTENTION:\n" +
|
|
71
|
-
"When specifying credentials of Teamscale or other services via --collector-config-file or --collector-option,\n" +
|
|
72
|
-
"the credentials will be included in the instrumented source code and are thus visible\n" +
|
|
73
|
-
"to anyone that can access your deployed application.\n" +
|
|
74
|
-
"We recommend you instead give these credentials to the collector directly when launching it.\n");
|
|
75
|
-
process.exit(0);
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
// Build the logger
|
|
79
|
-
const logger = this.buildLogger(config);
|
|
80
|
-
logger.trace('Retrieved arguments', process.argv);
|
|
81
|
-
logger.trace('Translated arguments to config', config);
|
|
82
|
-
// Run the instrumenter with the given configuration.
|
|
83
|
-
return this.runForConfigArguments(config, logger);
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Parses the command-line arguments.
|
|
87
|
-
*
|
|
88
|
-
* @param args - Optional. For testing. If given, uses this as the arguments to parse and does not exit the process on errors.
|
|
89
|
-
* If not given, uses the NodeJS process's arguments and exits on errors.
|
|
90
|
-
* @param beforeArgumentCheckCallback - To be executed before the arguments are checked for validity.
|
|
91
|
-
*/
|
|
92
|
-
static parseCommandLine(args, beforeArgumentCheckCallback) {
|
|
93
|
-
const configParameters = (0, InstrumenterConfig_1.buildInstrumenterConfigurationParameters)();
|
|
94
|
-
const appInfos = { about: package_json_1.description, version: package_json_1.version, name: package_json_1.name };
|
|
95
|
-
return (0, commons_1.processCommandLine)(configParameters, appInfos, args, beforeArgumentCheckCallback);
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Sometimes we get inputs from shell environments where the strings are
|
|
99
|
-
* still quoted. We remove those here.
|
|
100
|
-
*/
|
|
101
|
-
static postprocessConfig(config) {
|
|
102
|
-
function unquoteString(originalString) {
|
|
103
|
-
if (originalString === undefined) {
|
|
104
|
-
return originalString;
|
|
105
|
-
}
|
|
106
|
-
const result = originalString.replace(/^["'](.+(?=["']$))["']$/, '$1');
|
|
107
|
-
if (result === originalString) {
|
|
108
|
-
return result;
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
return unquoteString(result);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
function unquoteStringElements(originalArray) {
|
|
115
|
-
if (originalArray === undefined) {
|
|
116
|
-
return undefined;
|
|
117
|
-
}
|
|
118
|
-
return originalArray.map(s => {
|
|
119
|
-
if (typeof s === 'string') {
|
|
120
|
-
return unquoteString(s);
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
return s;
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
for (const [property, value] of Object.entries(config)) {
|
|
128
|
-
if (value === undefined) {
|
|
129
|
-
// In case the value is 'undefined' we can ignore this.
|
|
130
|
-
}
|
|
131
|
-
else if (typeof value === 'string') {
|
|
132
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
133
|
-
config[property] = unquoteString(value);
|
|
134
|
-
}
|
|
135
|
-
else if (Array.isArray(value)) {
|
|
136
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
137
|
-
config[property] = unquoteStringElements(value);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Construct the logger.
|
|
143
|
-
*/
|
|
144
|
-
static buildLogger(config) {
|
|
145
|
-
var _a;
|
|
146
|
-
const logfilePath = 'logs/instrumenter.log';
|
|
147
|
-
mkdirp_1.mkdirp.sync(path.dirname(logfilePath));
|
|
148
|
-
const logLevel = (_a = config.logLevel) !== null && _a !== void 0 ? _a : 'info';
|
|
149
|
-
return bunyan_1.default.createLogger({
|
|
150
|
-
name: 'Instrumenter',
|
|
151
|
-
streams: [
|
|
152
|
-
{
|
|
153
|
-
level: logLevel,
|
|
154
|
-
stream: {
|
|
155
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
156
|
-
write: (rec) => {
|
|
157
|
-
console.log('[%s] %s: %s', rec.time.toISOString(), bunyan_1.default.nameFromLevel[rec.level], rec.msg);
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
type: 'raw'
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
level: logLevel,
|
|
164
|
-
path: logfilePath
|
|
165
|
-
}
|
|
166
|
-
]
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* A logger for testing.
|
|
171
|
-
*/
|
|
172
|
-
static buildDummyLogger() {
|
|
173
|
-
return bunyan_1.default.createLogger({ name: 'Instrumenter' });
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* The instrumenter can also be started by providing the configuration dictionary explicitly.
|
|
177
|
-
*
|
|
178
|
-
* @param config - The dictionary with all configuration arguments.
|
|
179
|
-
* @param logger - The logger to use.
|
|
180
|
-
*/
|
|
181
|
-
static runForConfigArguments(config, logger) {
|
|
182
|
-
this.postprocessConfig(config);
|
|
183
|
-
if (config.collectorConfigFile) {
|
|
184
|
-
if (!(0, fs_1.existsSync)(config.collectorConfigFile)) {
|
|
185
|
-
throw new commons_1.InvalidConfigurationException(`The specified collector configuration file '${config.collectorConfigFile}' does not exist.`);
|
|
186
|
-
}
|
|
187
|
-
config.collectorConfigFileContent = (0, fs_1.readFileSync)(config.collectorConfigFile, 'utf8');
|
|
188
|
-
}
|
|
189
|
-
if (Array.isArray(config.collectorOption)) {
|
|
190
|
-
if (!config.collectorConfigFileContent) {
|
|
191
|
-
config.collectorConfigFileContent = "";
|
|
192
|
-
}
|
|
193
|
-
config.collectorConfigFileContent += `\n${config.collectorOption.join("\n")}`;
|
|
194
|
-
}
|
|
195
|
-
if (config.collectorConfigFileContent) {
|
|
196
|
-
try {
|
|
197
|
-
// We parse the collector config file once, to see if it is valid.
|
|
198
|
-
const collectorParameters = (0, commons_1.buildReconfigurableCollectorParameters)();
|
|
199
|
-
const { options } = (0, commons_1.parseConfigFile)(config.collectorConfigFileContent, collectorParameters);
|
|
200
|
-
if (!(0, commons_1.checkArguments)(collectorParameters, options)) {
|
|
201
|
-
throw new commons_1.InvalidConfigurationException(`Not all required configuration options are specified correctly.`);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
catch (e) {
|
|
205
|
-
throw new commons_1.InvalidConfigurationException(`The specified collector configuration is invalid: ${e.message}`);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
const task = this.createInstrumentationTask(config);
|
|
209
|
-
commons_1.Contract.require(task.elements.length > 0, 'The instrumentation task must not be empty.');
|
|
210
|
-
const instrumentationResult = this.createInstrumenter(logger !== null && logger !== void 0 ? logger : this.buildDummyLogger(), task.collector, task.targetBucket).instrument(task);
|
|
211
|
-
return App.finalizeAppRunWithConsoleOutputs(instrumentationResult);
|
|
212
|
-
}
|
|
213
|
-
static createInstrumentationTask(config) {
|
|
214
|
-
return new TaskBuilder_1.TaskBuilder().addFromConfig(config).build();
|
|
215
|
-
}
|
|
216
|
-
static createInstrumenter(logger, collector, targetBucket) {
|
|
217
|
-
// We have to deal with two different `__dirname` versions,
|
|
218
|
-
// which depends on whether we run from within the IDE or from
|
|
219
|
-
// the command line:
|
|
220
|
-
// dist/src/ OR src/
|
|
221
|
-
const pathVariant1 = path.join(__dirname, '../vaccine.js');
|
|
222
|
-
const pathVariant2 = path.join(__dirname, '../dist/vaccine.js');
|
|
223
|
-
if ((0, fs_1.existsSync)(pathVariant1)) {
|
|
224
|
-
return new Instrumenter_1.IstanbulInstrumenter(pathVariant1, logger, collector, targetBucket);
|
|
225
|
-
}
|
|
226
|
-
else {
|
|
227
|
-
return new Instrumenter_1.IstanbulInstrumenter(pathVariant2, logger, collector, targetBucket);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Processes the task result and produces console outputs, and possibly a process exit with a corresponding code.
|
|
232
|
-
*/
|
|
233
|
-
static async finalizeAppRunWithConsoleOutputs(resultPromise) {
|
|
234
|
-
var _a, _b;
|
|
235
|
-
try {
|
|
236
|
-
const result = await resultPromise;
|
|
237
|
-
console.log('Instrumentation finished.');
|
|
238
|
-
console.log(`\tInstrumented: ${result.translated}`);
|
|
239
|
-
console.log(`\tExcluded: ${result.excluded}`);
|
|
240
|
-
console.log(`\tInstrumented from cache: ${result.translatedFromCache}`);
|
|
241
|
-
console.log(`\tAlready instrumented: ${result.alreadyInstrumented}`);
|
|
242
|
-
console.log(`\tUnsupported: ${result.unsupported}`);
|
|
243
|
-
console.log(`\tWith warning: ${result.warnings}`);
|
|
244
|
-
console.log(`\tFailed: ${result.failed}`);
|
|
245
|
-
if ((_a = result.task) === null || _a === void 0 ? void 0 : _a.originSourcePattern.patternsSpecified()) {
|
|
246
|
-
const stats = (_b = result.task) === null || _b === void 0 ? void 0 : _b.originSourcePattern.retrieveMatchingFiles();
|
|
247
|
-
console.log(`\tSource origin matches`);
|
|
248
|
-
console.log(`\t\tInclude patterns: [${stats.includePatterns}]`);
|
|
249
|
-
console.log(`\t\tExclude patterns: [${stats.excludePatterns}]`);
|
|
250
|
-
console.log(`\t\tInclude matches: ${stats.includeMatches.length}`);
|
|
251
|
-
console.log(`\t\tExclude matches: ${stats.excludeMatches.length}`);
|
|
252
|
-
console.log(`\t\tNeither matches: ${stats.neitherExcludedNorIncluded.length}`);
|
|
253
|
-
if (stats.includeMatches.length === 0 && stats.excludeMatches.length === 0) {
|
|
254
|
-
console.error('\nWARNING: Specified include/exclude patterns are expected to match at least once. ' +
|
|
255
|
-
'None matched for this instrumenter invocation.\n');
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
if (result.translated === 0 && result.translatedFromCache === 0 && result.alreadyInstrumented === 0) {
|
|
259
|
-
console.error('\nWARNING: Each invocation of the JavaScript Instrumenter is supposed to match at \n' +
|
|
260
|
-
'least one file to instrument; no file was matched for instrumentation in this invocation. \n' +
|
|
261
|
-
'Please check the list of input files and the include/exclude patterns.\n');
|
|
262
|
-
}
|
|
263
|
-
if (result.failed > 0) {
|
|
264
|
-
console.error('FAILURE: The instrumentation failed for some files. Please check the log for details.\n');
|
|
265
|
-
}
|
|
266
|
-
return result;
|
|
267
|
-
}
|
|
268
|
-
catch (reason) {
|
|
269
|
-
if (reason instanceof commons_1.InvalidConfigurationException) {
|
|
270
|
-
// Do not print the stack trace for invalid configuration parameters from the user.
|
|
271
|
-
console.error(`Failed: ${reason.message}`);
|
|
272
|
-
}
|
|
273
|
-
else {
|
|
274
|
-
console.error('Failed: ', reason);
|
|
275
|
-
}
|
|
276
|
-
process.exit(1);
|
|
277
|
-
}
|
|
278
|
-
finally {
|
|
279
|
-
console.log('Bye bye.');
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
exports.App = App;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { RawSourceMap } from 'source-map';
|
|
2
|
-
/**
|
|
3
|
-
* Does the given `path` point to an existing file?
|
|
4
|
-
*/
|
|
5
|
-
export declare function isExistingFile(path: string): boolean;
|
|
6
|
-
/**
|
|
7
|
-
* Does the given `path` point to an existing directory?
|
|
8
|
-
*/
|
|
9
|
-
export declare function isExistingDirectory(path: string): boolean;
|
|
10
|
-
/**
|
|
11
|
-
* Ensure that the given directory `path` exists.
|
|
12
|
-
*/
|
|
13
|
-
export declare function ensureExistingDirectory(path: string): void;
|
|
14
|
-
/**
|
|
15
|
-
* Given a root folder find a folder with a given name.
|
|
16
|
-
*/
|
|
17
|
-
export declare function findSubFolders(startFromFolder: string, folderName: string): string[];
|
|
18
|
-
/**
|
|
19
|
-
* Is the given directory empty?
|
|
20
|
-
*/
|
|
21
|
-
export declare function isDirectoryEmpty(path: string): boolean;
|
|
22
|
-
/**
|
|
23
|
-
* Expand a given Glob pattern to a list of files.
|
|
24
|
-
*
|
|
25
|
-
* @param toExpand - The Glob pattern.
|
|
26
|
-
*/
|
|
27
|
-
export declare function expandToFileSet(toExpand: string): string[];
|
|
28
|
-
/**
|
|
29
|
-
* Read a source map from a source map file.
|
|
30
|
-
*
|
|
31
|
-
* @param mapFilePath
|
|
32
|
-
*/
|
|
33
|
-
export declare function sourceMapFromMapFile(mapFilePath: string): RawSourceMap | undefined;
|
|
34
|
-
/**
|
|
35
|
-
* Ensure that the given name works as a file or folder name.
|
|
36
|
-
*/
|
|
37
|
-
export declare function replaceNonFilesystemCharacters(name: string): string;
|
|
38
|
-
//# sourceMappingURL=FileSystem.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FileSystem.d.ts","sourceRoot":"","sources":["../../../src/instrumenter/FileSystem.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAU1D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,eAAe,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBpF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAc1D;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAGlF;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKnE"}
|