@testmutant/cli 0.0.1 → 0.0.2
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/LICENSE +21 -0
- package/README.md +91 -0
- package/dist/api-client.d.ts +15 -0
- package/dist/api-client.js +63 -0
- package/dist/api-client.js.map +1 -0
- package/dist/config.d.ts +18 -0
- package/dist/config.js +53 -0
- package/dist/config.js.map +1 -0
- package/dist/generated/api.d.ts +69 -0
- package/dist/generated/api.js +7 -0
- package/dist/generated/api.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/package.json +29 -5
- package/src/index.js +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sleepycat Software LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the “Software”), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# TestMutant CLI
|
|
2
|
+
|
|
3
|
+
Command-line tools for using TestMutant locally and in CI.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Node.js 20 or newer
|
|
8
|
+
- A TestMutant API key
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
Run the CLI without installing it globally:
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
npx @testmutant/cli --help
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Or install it globally:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
npm install -g @testmutant/cli
|
|
22
|
+
testmutant ping
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Configuration
|
|
26
|
+
|
|
27
|
+
The CLI reads configuration from environment variables or command-line flags.
|
|
28
|
+
|
|
29
|
+
| Environment variable | Flag | Description |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| `TESTMUTANT_API_KEY` | `--api-key <key>` | TestMutant API key used to authenticate requests. |
|
|
32
|
+
| `TESTMUTANT_API_URL` | `--api-url <url>` | TestMutant API base URL. Defaults to `http://localhost:5086`. |
|
|
33
|
+
| | `--timeout <ms>` | API request timeout in milliseconds. Defaults to `30000`. |
|
|
34
|
+
| | `--json` | Print command output as JSON. |
|
|
35
|
+
|
|
36
|
+
You can also put environment variables in a `.env` file in the directory where
|
|
37
|
+
you run the CLI:
|
|
38
|
+
|
|
39
|
+
```env
|
|
40
|
+
TESTMUTANT_API_KEY=tm_key_...
|
|
41
|
+
TESTMUTANT_API_URL=http://localhost:5086
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Local Usage
|
|
45
|
+
|
|
46
|
+
Verify that the CLI can connect to TestMutant:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
TESTMUTANT_API_KEY=tm_key_... testmutant ping
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Use a non-default API URL:
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
TESTMUTANT_API_KEY=tm_key_... TESTMUTANT_API_URL=https://api.example.com testmutant ping
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Pass configuration directly as flags:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
testmutant --api-key tm_key_... --api-url http://localhost:5086 ping
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Print machine-readable output:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
testmutant --json ping
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## CI Usage
|
|
71
|
+
|
|
72
|
+
Store `TESTMUTANT_API_KEY` as a secret in your CI provider.
|
|
73
|
+
Example GitHub Actions step:
|
|
74
|
+
|
|
75
|
+
```yaml
|
|
76
|
+
- name: Verify TestMutant connection
|
|
77
|
+
run: npx @testmutant/cli --json ping
|
|
78
|
+
env:
|
|
79
|
+
TESTMUTANT_API_KEY: ${{ secrets.TESTMUTANT_API_KEY }}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Commands
|
|
83
|
+
|
|
84
|
+
### `testmutant ping`
|
|
85
|
+
|
|
86
|
+
Verifies that the CLI can authenticate with the TestMutant API and prints the
|
|
87
|
+
connected organization and CLI API version.
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
MIT. Copyright (c) 2026 Sleepycat Software LLC.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { operations } from "./generated/api";
|
|
2
|
+
export type PingResponse = operations["CliV1_Ping"]["responses"][200]["content"]["application/json"];
|
|
3
|
+
export type TestMutantApiClientOptions = {
|
|
4
|
+
apiKey: string;
|
|
5
|
+
apiUrl: string;
|
|
6
|
+
timeoutMs: number;
|
|
7
|
+
userAgent: string;
|
|
8
|
+
};
|
|
9
|
+
export declare class TestMutantApiClient {
|
|
10
|
+
private readonly options;
|
|
11
|
+
constructor(options: TestMutantApiClientOptions);
|
|
12
|
+
ping(): Promise<PingResponse>;
|
|
13
|
+
private getJson;
|
|
14
|
+
private request;
|
|
15
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TestMutantApiClient = void 0;
|
|
4
|
+
const config_1 = require("./config");
|
|
5
|
+
class TestMutantApiClient {
|
|
6
|
+
options;
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
}
|
|
10
|
+
async ping() {
|
|
11
|
+
return this.getJson("/api/cli/v1/ping");
|
|
12
|
+
}
|
|
13
|
+
async getJson(path) {
|
|
14
|
+
const response = await this.request(path);
|
|
15
|
+
if (response.status === 401) {
|
|
16
|
+
throw new config_1.CliError("Unauthorized. Check your TestMutant API key.", 3);
|
|
17
|
+
}
|
|
18
|
+
if (!response.ok) {
|
|
19
|
+
const body = await response.text();
|
|
20
|
+
const detail = body ? ` ${truncate(body, 500)}` : "";
|
|
21
|
+
throw new config_1.CliError(`TestMutant API request failed with HTTP ${response.status}.${detail}`);
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
return (await response.json());
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new config_1.CliError("TestMutant API returned invalid JSON.");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async request(path) {
|
|
31
|
+
const controller = new AbortController();
|
|
32
|
+
const timeout = setTimeout(() => controller.abort(), this.options.timeoutMs);
|
|
33
|
+
try {
|
|
34
|
+
return await fetch(new URL(path, this.options.apiUrl), {
|
|
35
|
+
method: "GET",
|
|
36
|
+
signal: controller.signal,
|
|
37
|
+
headers: {
|
|
38
|
+
accept: "application/json",
|
|
39
|
+
authorization: `Bearer ${this.options.apiKey}`,
|
|
40
|
+
"user-agent": this.options.userAgent,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
46
|
+
throw new config_1.CliError(`TestMutant API request timed out after ${this.options.timeoutMs} ms.`);
|
|
47
|
+
}
|
|
48
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
49
|
+
throw new config_1.CliError(`Could not reach TestMutant API. ${message}`);
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
clearTimeout(timeout);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.TestMutantApiClient = TestMutantApiClient;
|
|
57
|
+
function truncate(value, maxLength) {
|
|
58
|
+
if (value.length <= maxLength) {
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
return `${value.slice(0, maxLength)}...`;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":";;;AACA,qCAAoC;AAYpC,MAAa,mBAAmB;IACD;IAA7B,YAA6B,OAAmC;QAAnC,YAAO,GAAP,OAAO,CAA4B;IAAG,CAAC;IAEpE,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,OAAO,CAAe,kBAAkB,CAAC,CAAC;IACxD,CAAC;IAEO,KAAK,CAAC,OAAO,CAAI,IAAY;QACnC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE1C,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,iBAAQ,CAAC,8CAA8C,EAAE,CAAC,CAAC,CAAC;QACxE,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,iBAAQ,CAChB,2CAA2C,QAAQ,CAAC,MAAM,IAAI,MAAM,EAAE,CACvE,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAM,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,iBAAQ,CAAC,uCAAuC,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,IAAY;QAChC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAE7E,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;gBACrD,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,OAAO,EAAE;oBACP,MAAM,EAAE,kBAAkB;oBAC1B,aAAa,EAAE,UAAU,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;oBAC9C,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;iBACrC;aACF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC1D,MAAM,IAAI,iBAAQ,CAChB,0CAA0C,IAAI,CAAC,OAAO,CAAC,SAAS,MAAM,CACvE,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,IAAI,iBAAQ,CAAC,mCAAmC,OAAO,EAAE,CAAC,CAAC;QACnE,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;CACF;AAxDD,kDAwDC;AAED,SAAS,QAAQ,CAAC,KAAa,EAAE,SAAiB;IAChD,IAAI,KAAK,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC;AAC3C,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const DEFAULT_API_URL = "http://localhost:5086";
|
|
2
|
+
export declare const API_KEY_ENV_VAR = "TESTMUTANT_API_KEY";
|
|
3
|
+
export declare const API_URL_ENV_VAR = "TESTMUTANT_API_URL";
|
|
4
|
+
export type CliConfig = {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
apiUrl: string;
|
|
7
|
+
timeoutMs: number;
|
|
8
|
+
};
|
|
9
|
+
export type CliConfigInput = {
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
apiUrl?: string;
|
|
12
|
+
timeout?: string;
|
|
13
|
+
};
|
|
14
|
+
export declare class CliError extends Error {
|
|
15
|
+
readonly exitCode: number;
|
|
16
|
+
constructor(message: string, exitCode?: number);
|
|
17
|
+
}
|
|
18
|
+
export declare function resolveConfig(input?: CliConfigInput): CliConfig;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CliError = exports.API_URL_ENV_VAR = exports.API_KEY_ENV_VAR = exports.DEFAULT_API_URL = void 0;
|
|
4
|
+
exports.resolveConfig = resolveConfig;
|
|
5
|
+
exports.DEFAULT_API_URL = "http://localhost:5086";
|
|
6
|
+
exports.API_KEY_ENV_VAR = "TESTMUTANT_API_KEY";
|
|
7
|
+
exports.API_URL_ENV_VAR = "TESTMUTANT_API_URL";
|
|
8
|
+
class CliError extends Error {
|
|
9
|
+
exitCode;
|
|
10
|
+
constructor(message, exitCode = 1) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.exitCode = exitCode;
|
|
13
|
+
this.name = "CliError";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.CliError = CliError;
|
|
17
|
+
function resolveConfig(input = {}) {
|
|
18
|
+
const apiKey = input.apiKey ?? process.env[exports.API_KEY_ENV_VAR];
|
|
19
|
+
const apiUrl = input.apiUrl ?? process.env[exports.API_URL_ENV_VAR] ?? exports.DEFAULT_API_URL;
|
|
20
|
+
const timeoutMs = parseTimeout(input.timeout);
|
|
21
|
+
if (!apiKey) {
|
|
22
|
+
throw new CliError(`Missing API key. Set ${exports.API_KEY_ENV_VAR} or pass --api-key.`, 2);
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
apiKey,
|
|
26
|
+
apiUrl: normalizeApiUrl(apiUrl),
|
|
27
|
+
timeoutMs,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function normalizeApiUrl(value) {
|
|
31
|
+
let url;
|
|
32
|
+
try {
|
|
33
|
+
url = new URL(value);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
throw new CliError(`Invalid API URL: ${value}`, 2);
|
|
37
|
+
}
|
|
38
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
39
|
+
throw new CliError("API URL must start with http:// or https://.", 2);
|
|
40
|
+
}
|
|
41
|
+
return url.toString().replace(/\/$/, "");
|
|
42
|
+
}
|
|
43
|
+
function parseTimeout(value) {
|
|
44
|
+
if (!value) {
|
|
45
|
+
return 30_000;
|
|
46
|
+
}
|
|
47
|
+
const timeoutMs = Number(value);
|
|
48
|
+
if (!Number.isInteger(timeoutMs) || timeoutMs <= 0) {
|
|
49
|
+
throw new CliError("Timeout must be a positive integer in milliseconds.", 2);
|
|
50
|
+
}
|
|
51
|
+
return timeoutMs;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;AA0BA,sCAiBC;AA3CY,QAAA,eAAe,GAAG,uBAAuB,CAAC;AAC1C,QAAA,eAAe,GAAG,oBAAoB,CAAC;AACvC,QAAA,eAAe,GAAG,oBAAoB,CAAC;AAcpD,MAAa,QAAS,SAAQ,KAAK;IAGtB;IAFX,YACE,OAAe,EACN,WAAW,CAAC;QAErB,KAAK,CAAC,OAAO,CAAC,CAAC;QAFN,aAAQ,GAAR,QAAQ,CAAI;QAGrB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AARD,4BAQC;AAED,SAAgB,aAAa,CAAC,QAAwB,EAAE;IACtD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAe,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAe,CAAC,IAAI,uBAAe,CAAC;IAC/E,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,QAAQ,CAChB,wBAAwB,uBAAe,qBAAqB,EAC5D,CAAC,CACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,MAAM;QACN,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC;QAC/B,SAAS;KACV,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,IAAI,GAAQ,CAAC;IAEb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,QAAQ,CAAC,oBAAoB,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1D,MAAM,IAAI,QAAQ,CAAC,8CAA8C,EAAE,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAEhC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,QAAQ,CAAC,qDAAqD,EAAE,CAAC,CAAC,CAAC;IAC/E,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file was auto-generated by openapi-typescript.
|
|
3
|
+
* Do not make direct changes to the file.
|
|
4
|
+
*/
|
|
5
|
+
export interface paths {
|
|
6
|
+
"/api/cli/v1/ping": {
|
|
7
|
+
parameters: {
|
|
8
|
+
query?: never;
|
|
9
|
+
header?: never;
|
|
10
|
+
path?: never;
|
|
11
|
+
cookie?: never;
|
|
12
|
+
};
|
|
13
|
+
get: operations["CliV1_Ping"];
|
|
14
|
+
put?: never;
|
|
15
|
+
post?: never;
|
|
16
|
+
delete?: never;
|
|
17
|
+
options?: never;
|
|
18
|
+
head?: never;
|
|
19
|
+
patch?: never;
|
|
20
|
+
trace?: never;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export type webhooks = Record<string, never>;
|
|
24
|
+
export interface components {
|
|
25
|
+
schemas: {
|
|
26
|
+
CliPingResponse: {
|
|
27
|
+
ok: boolean;
|
|
28
|
+
/** Format: uuid */
|
|
29
|
+
organizationId: string;
|
|
30
|
+
organizationName: string;
|
|
31
|
+
cliApiVersion: string;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
responses: never;
|
|
35
|
+
parameters: never;
|
|
36
|
+
requestBodies: never;
|
|
37
|
+
headers: never;
|
|
38
|
+
pathItems: never;
|
|
39
|
+
}
|
|
40
|
+
export type $defs = Record<string, never>;
|
|
41
|
+
export interface operations {
|
|
42
|
+
CliV1_Ping: {
|
|
43
|
+
parameters: {
|
|
44
|
+
query?: never;
|
|
45
|
+
header?: never;
|
|
46
|
+
path?: never;
|
|
47
|
+
cookie?: never;
|
|
48
|
+
};
|
|
49
|
+
requestBody?: never;
|
|
50
|
+
responses: {
|
|
51
|
+
/** @description OK */
|
|
52
|
+
200: {
|
|
53
|
+
headers: {
|
|
54
|
+
[name: string]: unknown;
|
|
55
|
+
};
|
|
56
|
+
content: {
|
|
57
|
+
"application/json": components["schemas"]["CliPingResponse"];
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
/** @description Unauthorized */
|
|
61
|
+
401: {
|
|
62
|
+
headers: {
|
|
63
|
+
[name: string]: unknown;
|
|
64
|
+
};
|
|
65
|
+
content?: never;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/generated/api.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
require("dotenv/config");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const api_client_1 = require("./api-client");
|
|
9
|
+
const config_1 = require("./config");
|
|
10
|
+
const packageInfo = readPackageInfo();
|
|
11
|
+
const program = new commander_1.Command();
|
|
12
|
+
program
|
|
13
|
+
.name("testmutant")
|
|
14
|
+
.description("Run TestMutant workflows locally or in CI.")
|
|
15
|
+
.version(packageInfo.version)
|
|
16
|
+
.option("-k, --api-key <key>", `TestMutant API key. Defaults to ${config_1.API_KEY_ENV_VAR}.`)
|
|
17
|
+
.option("-u, --api-url <url>", `TestMutant API base URL. Defaults to ${config_1.API_URL_ENV_VAR} or ${config_1.DEFAULT_API_URL}.`)
|
|
18
|
+
.option("--timeout <ms>", "API request timeout in milliseconds.", "30000")
|
|
19
|
+
.option("--json", "Print command output as JSON.");
|
|
20
|
+
program
|
|
21
|
+
.command("ping")
|
|
22
|
+
.description("Verify the CLI can authenticate with the TestMutant API.")
|
|
23
|
+
.action(async () => {
|
|
24
|
+
const options = program.opts();
|
|
25
|
+
const config = (0, config_1.resolveConfig)(options);
|
|
26
|
+
const client = new api_client_1.TestMutantApiClient({
|
|
27
|
+
...config,
|
|
28
|
+
userAgent: `testmutant-cli/${packageInfo.version}`,
|
|
29
|
+
});
|
|
30
|
+
const ping = await client.ping();
|
|
31
|
+
if (options.json) {
|
|
32
|
+
console.log(JSON.stringify(ping, null, 2));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
console.log("Connected to TestMutant.");
|
|
36
|
+
console.log(`Organization: ${ping.organizationName} (${ping.organizationId})`);
|
|
37
|
+
console.log(`CLI API version: ${ping.cliApiVersion}`);
|
|
38
|
+
});
|
|
39
|
+
program.showHelpAfterError();
|
|
40
|
+
program.parseAsync(process.argv).catch((error) => {
|
|
41
|
+
if (error instanceof config_1.CliError) {
|
|
42
|
+
console.error(error.message);
|
|
43
|
+
process.exitCode = error.exitCode;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (error instanceof Error) {
|
|
47
|
+
console.error(error.message);
|
|
48
|
+
process.exitCode = 1;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
console.error(String(error));
|
|
52
|
+
process.exitCode = 1;
|
|
53
|
+
});
|
|
54
|
+
function readPackageInfo() {
|
|
55
|
+
const packageJsonPath = (0, node_path_1.join)(__dirname, "..", "package.json");
|
|
56
|
+
const packageJson = JSON.parse((0, node_fs_1.readFileSync)(packageJsonPath, "utf8"));
|
|
57
|
+
return {
|
|
58
|
+
version: typeof packageJson.version === "string" ? packageJson.version : "0.0.0",
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yBAAuB;AACvB,qCAAuC;AACvC,yCAAiC;AACjC,yCAAoC;AACpC,6CAAmD;AACnD,qCAMkB;AASlB,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;AACtC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,4CAA4C,CAAC;KACzD,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;KAC5B,MAAM,CAAC,qBAAqB,EAAE,mCAAmC,wBAAe,GAAG,CAAC;KACpF,MAAM,CACL,qBAAqB,EACrB,wCAAwC,wBAAe,OAAO,wBAAe,GAAG,CACjF;KACA,MAAM,CAAC,gBAAgB,EAAE,sCAAsC,EAAE,OAAO,CAAC;KACzE,MAAM,CAAC,QAAQ,EAAE,+BAA+B,CAAC,CAAC;AAErD,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,0DAA0D,CAAC;KACvE,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAiB,CAAC;IAC9C,MAAM,MAAM,GAAG,IAAA,sBAAa,EAAC,OAAO,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,gCAAmB,CAAC;QACrC,GAAG,MAAM;QACT,SAAS,EAAE,kBAAkB,WAAW,CAAC,OAAO,EAAE;KACnD,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IAEjC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3C,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,CAAC,gBAAgB,KAAK,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;IAC/E,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;AACxD,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,kBAAkB,EAAE,CAAC;AAE7B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IACxD,IAAI,KAAK,YAAY,iBAAQ,EAAE,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7B,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAClC,OAAO;IACT,CAAC;IAED,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7B,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7B,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,SAAS,eAAe;IACtB,MAAM,eAAe,GAAG,IAAA,gBAAI,EAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;IAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,sBAAY,EAAC,eAAe,EAAE,MAAM,CAAC,CAEnE,CAAC;IAEF,OAAO;QACL,OAAO,EACL,OAAO,WAAW,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;KAC1E,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,19 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testmutant/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "TestMutant CLI.",
|
|
5
5
|
"private": false,
|
|
6
|
+
"main": "dist/index.js",
|
|
6
7
|
"bin": {
|
|
7
|
-
"testmutant": "
|
|
8
|
+
"testmutant": "dist/index.js"
|
|
8
9
|
},
|
|
9
10
|
"scripts": {
|
|
10
|
-
"
|
|
11
|
+
"build": "tsc -p tsconfig.json",
|
|
12
|
+
"dev": "npm run build && node dist/index.js",
|
|
13
|
+
"prepack": "npm run build",
|
|
14
|
+
"test": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=20"
|
|
11
21
|
},
|
|
12
22
|
"keywords": [],
|
|
13
23
|
"author": "",
|
|
14
|
-
"license": "
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/TestMutant/cli.git"
|
|
28
|
+
},
|
|
15
29
|
"type": "commonjs",
|
|
16
30
|
"publishConfig": {
|
|
17
|
-
"access": "public"
|
|
31
|
+
"access": "public",
|
|
32
|
+
"registry": "https://registry.npmjs.org/",
|
|
33
|
+
"provenance": true
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"commander": "^14.0.3",
|
|
37
|
+
"dotenv": "^17.4.2"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^25.9.1",
|
|
41
|
+
"typescript": "^6.0.3"
|
|
18
42
|
}
|
|
19
43
|
}
|
package/src/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
console.log("TestMutant CLI placeholder.");
|