@supercheck/cli 0.1.0-beta.5 → 0.1.0-beta.6
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/dist/bin/supercheck.js +284 -135
- package/dist/bin/supercheck.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/supercheck.js
CHANGED
|
@@ -213,7 +213,7 @@ function requireTriggerKey() {
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
// src/version.ts
|
|
216
|
-
var CLI_VERSION = true ? "0.1.0-beta.
|
|
216
|
+
var CLI_VERSION = true ? "0.1.0-beta.6" : "0.0.0-dev";
|
|
217
217
|
|
|
218
218
|
// src/api/client.ts
|
|
219
219
|
import { ProxyAgent } from "undici";
|
|
@@ -1692,9 +1692,12 @@ function parseIntStrict(value, name, opts) {
|
|
|
1692
1692
|
var jobCommand = new Command5("job").description("Manage jobs");
|
|
1693
1693
|
jobCommand.command("list").description("List all jobs").option("--page <page>", "Page number", "1").option("--limit <limit>", "Items per page", "50").action(async (options) => {
|
|
1694
1694
|
const client = createAuthenticatedClient();
|
|
1695
|
-
const { data } = await
|
|
1696
|
-
"
|
|
1697
|
-
|
|
1695
|
+
const { data } = await withSpinner(
|
|
1696
|
+
"Fetching jobs",
|
|
1697
|
+
() => client.get(
|
|
1698
|
+
"/api/jobs",
|
|
1699
|
+
{ page: options.page, limit: options.limit }
|
|
1700
|
+
)
|
|
1698
1701
|
);
|
|
1699
1702
|
output(data.data, {
|
|
1700
1703
|
columns: [
|
|
@@ -1715,8 +1718,11 @@ Page ${data.pagination.page}/${data.pagination.totalPages} (${data.pagination.to
|
|
|
1715
1718
|
var keysCommand = jobCommand.command("keys").description("Manage job trigger keys");
|
|
1716
1719
|
keysCommand.argument("<jobId>", "Job ID").action(async (jobId) => {
|
|
1717
1720
|
const client = createAuthenticatedClient();
|
|
1718
|
-
const { data } = await
|
|
1719
|
-
|
|
1721
|
+
const { data } = await withSpinner(
|
|
1722
|
+
"Fetching trigger keys",
|
|
1723
|
+
() => client.get(
|
|
1724
|
+
`/api/jobs/${jobId}/api-keys`
|
|
1725
|
+
)
|
|
1720
1726
|
);
|
|
1721
1727
|
output(data.apiKeys ?? [], {
|
|
1722
1728
|
columns: [
|
|
@@ -1735,9 +1741,12 @@ keysCommand.command("create").description("Create a new trigger key for a job").
|
|
|
1735
1741
|
if (options.expiresIn !== void 0) {
|
|
1736
1742
|
body.expiresIn = parseIntStrict(options.expiresIn, "--expires-in", { min: 60 });
|
|
1737
1743
|
}
|
|
1738
|
-
const { data } = await
|
|
1739
|
-
|
|
1740
|
-
|
|
1744
|
+
const { data } = await withSpinner(
|
|
1745
|
+
"Creating trigger key",
|
|
1746
|
+
() => client.post(
|
|
1747
|
+
`/api/jobs/${jobId}/api-keys`,
|
|
1748
|
+
body
|
|
1749
|
+
)
|
|
1741
1750
|
);
|
|
1742
1751
|
logger.success("Trigger key created");
|
|
1743
1752
|
logger.warn("Save the `key` value now. It will only be shown once.");
|
|
@@ -1745,12 +1754,18 @@ keysCommand.command("create").description("Create a new trigger key for a job").
|
|
|
1745
1754
|
});
|
|
1746
1755
|
keysCommand.command("delete").description("Revoke a trigger key").argument("<jobId>", "Job ID").argument("<keyId>", "Key ID").action(async (jobId, keyId) => {
|
|
1747
1756
|
const client = createAuthenticatedClient();
|
|
1748
|
-
await
|
|
1757
|
+
await withSpinner(
|
|
1758
|
+
"Revoking trigger key",
|
|
1759
|
+
() => client.delete(`/api/jobs/${jobId}/api-keys/${keyId}`)
|
|
1760
|
+
);
|
|
1749
1761
|
logger.success(`Trigger key ${keyId} revoked`);
|
|
1750
1762
|
});
|
|
1751
1763
|
jobCommand.command("get <id>").description("Get job details").action(async (id) => {
|
|
1752
1764
|
const client = createAuthenticatedClient();
|
|
1753
|
-
const { data } = await
|
|
1765
|
+
const { data } = await withSpinner(
|
|
1766
|
+
"Fetching job details",
|
|
1767
|
+
() => client.get(`/api/jobs/${id}`)
|
|
1768
|
+
);
|
|
1754
1769
|
outputDetail(data);
|
|
1755
1770
|
});
|
|
1756
1771
|
jobCommand.command("create").description("Create a new job").requiredOption("--name <name>", "Job name").option("--description <description>", "Job description", "").option("--type <type>", "Job type (playwright, k6)").option("--schedule <cron>", "Cron schedule expression").option("--timeout <seconds>", "Timeout in seconds", "300").option("--retries <count>", "Retry count on failure", "0").action(async (options) => {
|
|
@@ -1765,7 +1780,10 @@ jobCommand.command("create").description("Create a new job").requiredOption("--n
|
|
|
1765
1780
|
};
|
|
1766
1781
|
if (options.type) body.jobType = options.type;
|
|
1767
1782
|
if (options.schedule) body.cronSchedule = options.schedule;
|
|
1768
|
-
const { data } = await
|
|
1783
|
+
const { data } = await withSpinner(
|
|
1784
|
+
"Creating job",
|
|
1785
|
+
() => client.post("/api/jobs", body)
|
|
1786
|
+
);
|
|
1769
1787
|
logger.success(`Job "${options.name}" created (${data.id})`);
|
|
1770
1788
|
outputDetail(data);
|
|
1771
1789
|
});
|
|
@@ -1782,7 +1800,10 @@ jobCommand.command("update <id>").description("Update job configuration").option
|
|
|
1782
1800
|
logger.warn("No fields to update. Use --name, --description, --schedule, --timeout, --retries, or --status.");
|
|
1783
1801
|
return;
|
|
1784
1802
|
}
|
|
1785
|
-
const { data } = await
|
|
1803
|
+
const { data } = await withSpinner(
|
|
1804
|
+
"Updating job",
|
|
1805
|
+
() => client.patch(`/api/jobs/${id}`, body)
|
|
1806
|
+
);
|
|
1786
1807
|
logger.success(`Job ${id} updated`);
|
|
1787
1808
|
outputDetail(data);
|
|
1788
1809
|
});
|
|
@@ -1796,13 +1817,19 @@ jobCommand.command("delete <id>").description("Delete a job").option("--force",
|
|
|
1796
1817
|
}
|
|
1797
1818
|
}
|
|
1798
1819
|
const client = createAuthenticatedClient();
|
|
1799
|
-
await
|
|
1820
|
+
await withSpinner(
|
|
1821
|
+
"Deleting job",
|
|
1822
|
+
() => client.delete(`/api/jobs/${id}`)
|
|
1823
|
+
);
|
|
1800
1824
|
logger.success(`Job ${id} deleted`);
|
|
1801
1825
|
});
|
|
1802
1826
|
jobCommand.command("run").description("Run a job immediately").requiredOption("--id <id>", "Job ID to run").action(async (options) => {
|
|
1803
1827
|
const client = createAuthenticatedClient();
|
|
1804
|
-
const { data: jobData } = await
|
|
1805
|
-
|
|
1828
|
+
const { data: jobData } = await withSpinner(
|
|
1829
|
+
"Fetching job details",
|
|
1830
|
+
() => client.get(
|
|
1831
|
+
`/api/jobs/${options.id}`
|
|
1832
|
+
)
|
|
1806
1833
|
);
|
|
1807
1834
|
const tests = Array.isArray(jobData.tests) ? jobData.tests : [];
|
|
1808
1835
|
if (tests.length === 0) {
|
|
@@ -1815,10 +1842,12 @@ jobCommand.command("run").description("Run a job immediately").requiredOption("-
|
|
|
1815
1842
|
id: test.id,
|
|
1816
1843
|
name: test.name ?? test.title ?? ""
|
|
1817
1844
|
}));
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1845
|
+
const { data } = await withSpinner(
|
|
1846
|
+
"Running job",
|
|
1847
|
+
() => client.post(
|
|
1848
|
+
"/api/jobs/run",
|
|
1849
|
+
{ jobId: options.id, tests: payloadTests, trigger: "manual" }
|
|
1850
|
+
)
|
|
1822
1851
|
);
|
|
1823
1852
|
logger.success(`Job started. Run ID: ${data.runId}`);
|
|
1824
1853
|
outputDetail(data);
|
|
@@ -1828,9 +1857,11 @@ jobCommand.command("trigger <id>").description("Trigger a job run").option("--wa
|
|
|
1828
1857
|
token: requireTriggerKey(),
|
|
1829
1858
|
baseUrl: getStoredBaseUrl() ?? void 0
|
|
1830
1859
|
});
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1860
|
+
const { data } = await withSpinner(
|
|
1861
|
+
"Triggering job",
|
|
1862
|
+
() => triggerClient.post(
|
|
1863
|
+
`/api/jobs/${id}/trigger`
|
|
1864
|
+
)
|
|
1834
1865
|
);
|
|
1835
1866
|
logger.success(`Job triggered. Run ID: ${data.runId}`);
|
|
1836
1867
|
if (options.wait) {
|
|
@@ -1919,17 +1950,19 @@ function getProxyEnv(url) {
|
|
|
1919
1950
|
return null;
|
|
1920
1951
|
}
|
|
1921
1952
|
var runCommand = new Command6("run").description("Manage runs");
|
|
1922
|
-
runCommand.command("list").description("List runs").option("--page <page>", "Page number", "1").option("--limit <limit>", "Items per page", "50").option("--
|
|
1953
|
+
runCommand.command("list").description("List runs").option("--page <page>", "Page number", "1").option("--limit <limit>", "Items per page", "50").option("--status <status>", "Filter by status").action(async (options) => {
|
|
1923
1954
|
const client = createAuthenticatedClient();
|
|
1924
1955
|
const params = {
|
|
1925
1956
|
page: options.page,
|
|
1926
1957
|
limit: options.limit
|
|
1927
1958
|
};
|
|
1928
|
-
if (options.job) params.jobId = options.job;
|
|
1929
1959
|
if (options.status) params.status = options.status;
|
|
1930
|
-
const { data } = await
|
|
1931
|
-
"
|
|
1932
|
-
|
|
1960
|
+
const { data } = await withSpinner(
|
|
1961
|
+
"Fetching runs",
|
|
1962
|
+
() => client.get(
|
|
1963
|
+
"/api/runs",
|
|
1964
|
+
params
|
|
1965
|
+
)
|
|
1933
1966
|
);
|
|
1934
1967
|
output(data.data, {
|
|
1935
1968
|
columns: [
|
|
@@ -1937,7 +1970,6 @@ runCommand.command("list").description("List runs").option("--page <page>", "Pag
|
|
|
1937
1970
|
{ key: "jobName", header: "Job" },
|
|
1938
1971
|
{ key: "status", header: "Status" },
|
|
1939
1972
|
{ key: "trigger", header: "Trigger" },
|
|
1940
|
-
{ key: "duration", header: "Duration" },
|
|
1941
1973
|
{ key: "startedAt", header: "Started" }
|
|
1942
1974
|
]
|
|
1943
1975
|
});
|
|
@@ -1950,22 +1982,18 @@ Page ${data.pagination.page}/${data.pagination.totalPages} (${data.pagination.to
|
|
|
1950
1982
|
});
|
|
1951
1983
|
runCommand.command("get <id>").description("Get run details").action(async (id) => {
|
|
1952
1984
|
const client = createAuthenticatedClient();
|
|
1953
|
-
const { data } = await
|
|
1954
|
-
|
|
1955
|
-
})
|
|
1956
|
-
|
|
1957
|
-
const client = createAuthenticatedClient();
|
|
1958
|
-
const { data } = await client.get(`/api/runs/${id}/permissions`);
|
|
1985
|
+
const { data } = await withSpinner(
|
|
1986
|
+
"Fetching run details",
|
|
1987
|
+
() => client.get(`/api/runs/${id}`)
|
|
1988
|
+
);
|
|
1959
1989
|
outputDetail(data);
|
|
1960
1990
|
});
|
|
1961
|
-
runCommand.command("cancel <id>").description("Cancel a running execution").action(async (id) => {
|
|
1962
|
-
const client = createAuthenticatedClient();
|
|
1963
|
-
await client.post(`/api/runs/${id}/cancel`);
|
|
1964
|
-
logger.success(`Run ${id} cancelled`);
|
|
1965
|
-
});
|
|
1966
1991
|
runCommand.command("status <id>").description("Get run status").action(async (id) => {
|
|
1967
1992
|
const client = createAuthenticatedClient();
|
|
1968
|
-
const { data } = await
|
|
1993
|
+
const { data } = await withSpinner(
|
|
1994
|
+
"Fetching run status",
|
|
1995
|
+
() => client.get(`/api/runs/${id}/status`)
|
|
1996
|
+
);
|
|
1969
1997
|
outputDetail(data);
|
|
1970
1998
|
});
|
|
1971
1999
|
runCommand.command("stream <id>").description("Stream live console output from a run").option("--idle-timeout <seconds>", "Abort if no data received within this period", "60").action(async (id, options) => {
|
|
@@ -2030,18 +2058,13 @@ runCommand.command("stream <id>").description("Stream live console output from a
|
|
|
2030
2058
|
process.stdout.write(parsed.line + "\n");
|
|
2031
2059
|
}
|
|
2032
2060
|
break;
|
|
2061
|
+
case "status":
|
|
2062
|
+
logger.info(`Status: ${parsed.status ?? JSON.stringify(parsed)}`);
|
|
2063
|
+
break;
|
|
2033
2064
|
case "complete":
|
|
2034
|
-
logger.
|
|
2035
|
-
if (parsed.status === "completed" || parsed.status === "success") {
|
|
2036
|
-
logger.success(`Run ${id} ${parsed.status}`);
|
|
2037
|
-
} else {
|
|
2038
|
-
logger.warn(`Run ${id} finished with status: ${parsed.status}`);
|
|
2039
|
-
}
|
|
2065
|
+
logger.success(`Run complete: ${parsed.status ?? "done"}`);
|
|
2040
2066
|
if (idleTimer) clearTimeout(idleTimer);
|
|
2041
2067
|
return;
|
|
2042
|
-
case "ready":
|
|
2043
|
-
logger.debug(`Stream ready for run ${parsed.runId ?? id}`);
|
|
2044
|
-
break;
|
|
2045
2068
|
case "error":
|
|
2046
2069
|
logger.error(`Stream error: ${parsed.message ?? JSON.stringify(parsed)}`);
|
|
2047
2070
|
break;
|
|
@@ -2144,9 +2167,12 @@ testCommand.command("list").description("List all tests").option("--page <page>"
|
|
|
2144
2167
|
};
|
|
2145
2168
|
if (options.search) params.search = options.search;
|
|
2146
2169
|
if (options.type) params.type = normalizeTestType(options.type);
|
|
2147
|
-
const { data } = await
|
|
2148
|
-
"
|
|
2149
|
-
|
|
2170
|
+
const { data } = await withSpinner(
|
|
2171
|
+
"Fetching tests",
|
|
2172
|
+
() => client.get(
|
|
2173
|
+
"/api/tests",
|
|
2174
|
+
params
|
|
2175
|
+
)
|
|
2150
2176
|
);
|
|
2151
2177
|
output(data.data, {
|
|
2152
2178
|
columns: [
|
|
@@ -2167,7 +2193,10 @@ testCommand.command("get <id>").description("Get test details").option("--includ
|
|
|
2167
2193
|
const client = createAuthenticatedClient();
|
|
2168
2194
|
const params = {};
|
|
2169
2195
|
if (options.includeScript) params.includeScript = "true";
|
|
2170
|
-
const { data } = await
|
|
2196
|
+
const { data } = await withSpinner(
|
|
2197
|
+
"Fetching test details",
|
|
2198
|
+
() => client.get(`/api/tests/${id}`, params)
|
|
2199
|
+
);
|
|
2171
2200
|
outputDetail(data);
|
|
2172
2201
|
});
|
|
2173
2202
|
testCommand.command("create").description("Create a new test").requiredOption("--title <title>", "Test title").requiredOption("--file <path>", "Path to the test script file").option("--type <type>", "Test type (playwright, k6)", "playwright").option("--description <description>", "Test description").action(async (options) => {
|
|
@@ -2188,7 +2217,10 @@ testCommand.command("create").description("Create a new test").requiredOption("-
|
|
|
2188
2217
|
type: normalizeTestType(options.type)
|
|
2189
2218
|
};
|
|
2190
2219
|
if (options.description) body.description = options.description;
|
|
2191
|
-
const { data } = await
|
|
2220
|
+
const { data } = await withSpinner(
|
|
2221
|
+
"Creating test",
|
|
2222
|
+
() => client.post("/api/tests", body)
|
|
2223
|
+
);
|
|
2192
2224
|
const createdId = data.test?.id ?? data.id;
|
|
2193
2225
|
logger.success(`Test "${options.title}" created${createdId ? ` (${createdId})` : ""}`);
|
|
2194
2226
|
outputDetail(data);
|
|
@@ -2213,7 +2245,10 @@ testCommand.command("update <id>").description("Update a test").option("--title
|
|
|
2213
2245
|
logger.warn("No fields to update. Use --title, --file, or --description.");
|
|
2214
2246
|
return;
|
|
2215
2247
|
}
|
|
2216
|
-
const { data } = await
|
|
2248
|
+
const { data } = await withSpinner(
|
|
2249
|
+
"Updating test",
|
|
2250
|
+
() => client.patch(`/api/tests/${id}`, body)
|
|
2251
|
+
);
|
|
2217
2252
|
logger.success(`Test ${id} updated`);
|
|
2218
2253
|
outputDetail(data);
|
|
2219
2254
|
});
|
|
@@ -2227,19 +2262,28 @@ testCommand.command("delete <id>").description("Delete a test").option("--force"
|
|
|
2227
2262
|
}
|
|
2228
2263
|
}
|
|
2229
2264
|
const client = createAuthenticatedClient();
|
|
2230
|
-
await
|
|
2265
|
+
await withSpinner(
|
|
2266
|
+
"Deleting test",
|
|
2267
|
+
() => client.delete(`/api/tests/${id}`)
|
|
2268
|
+
);
|
|
2231
2269
|
logger.success(`Test ${id} deleted`);
|
|
2232
2270
|
});
|
|
2233
2271
|
testCommand.command("execute <id>").description("Execute a test immediately").option("--location <location>", "Execution location (k6 only)").action(async (id, options) => {
|
|
2234
2272
|
const client = createAuthenticatedClient();
|
|
2235
2273
|
const body = {};
|
|
2236
2274
|
if (options.location) body.location = options.location;
|
|
2237
|
-
const { data } = await
|
|
2275
|
+
const { data } = await withSpinner(
|
|
2276
|
+
"Executing test",
|
|
2277
|
+
() => client.post(`/api/tests/${id}/execute`, body)
|
|
2278
|
+
);
|
|
2238
2279
|
outputDetail(data);
|
|
2239
2280
|
});
|
|
2240
2281
|
testCommand.command("tags <id>").description("Get test tags").action(async (id) => {
|
|
2241
2282
|
const client = createAuthenticatedClient();
|
|
2242
|
-
const { data } = await
|
|
2283
|
+
const { data } = await withSpinner(
|
|
2284
|
+
"Fetching test tags",
|
|
2285
|
+
() => client.get(`/api/tests/${id}/tags`)
|
|
2286
|
+
);
|
|
2243
2287
|
output(data, {
|
|
2244
2288
|
columns: [
|
|
2245
2289
|
{ key: "id", header: "ID" },
|
|
@@ -2259,9 +2303,12 @@ testCommand.command("validate").description("Validate a test script").requiredOp
|
|
|
2259
2303
|
throw new CLIError(`Cannot read file: ${filePath}`, 1 /* GeneralError */);
|
|
2260
2304
|
}
|
|
2261
2305
|
const client = createAuthenticatedClient();
|
|
2262
|
-
const { data } = await
|
|
2263
|
-
"
|
|
2264
|
-
|
|
2306
|
+
const { data } = await withSpinner(
|
|
2307
|
+
"Validating script",
|
|
2308
|
+
() => client.post(
|
|
2309
|
+
"/api/validate-script",
|
|
2310
|
+
{ script, testType: normalizeTestType(options.type) }
|
|
2311
|
+
)
|
|
2265
2312
|
);
|
|
2266
2313
|
if (data.valid) {
|
|
2267
2314
|
logger.success(`Script is valid (${options.type})`);
|
|
@@ -2353,9 +2400,12 @@ import { Command as Command8 } from "commander";
|
|
|
2353
2400
|
var monitorCommand = new Command8("monitor").description("Manage monitors");
|
|
2354
2401
|
monitorCommand.command("list").description("List all monitors").option("--page <page>", "Page number", "1").option("--limit <limit>", "Items per page", "50").action(async (options) => {
|
|
2355
2402
|
const client = createAuthenticatedClient();
|
|
2356
|
-
const { data } = await
|
|
2357
|
-
"
|
|
2358
|
-
|
|
2403
|
+
const { data } = await withSpinner(
|
|
2404
|
+
"Fetching monitors",
|
|
2405
|
+
() => client.get(
|
|
2406
|
+
"/api/monitors",
|
|
2407
|
+
{ page: options.page, limit: options.limit }
|
|
2408
|
+
)
|
|
2359
2409
|
);
|
|
2360
2410
|
output(data.data, {
|
|
2361
2411
|
columns: [
|
|
@@ -2375,14 +2425,20 @@ Page ${data.pagination.page}/${data.pagination.totalPages} (${data.pagination.to
|
|
|
2375
2425
|
});
|
|
2376
2426
|
monitorCommand.command("get <id>").description("Get monitor details").action(async (id) => {
|
|
2377
2427
|
const client = createAuthenticatedClient();
|
|
2378
|
-
const { data } = await
|
|
2428
|
+
const { data } = await withSpinner(
|
|
2429
|
+
"Fetching monitor details",
|
|
2430
|
+
() => client.get(`/api/monitors/${id}`)
|
|
2431
|
+
);
|
|
2379
2432
|
outputDetail(data);
|
|
2380
2433
|
});
|
|
2381
2434
|
monitorCommand.command("results <id>").description("Get monitor check results").option("--limit <limit>", "Number of results", "20").action(async (id, options) => {
|
|
2382
2435
|
const client = createAuthenticatedClient();
|
|
2383
|
-
const { data } = await
|
|
2384
|
-
|
|
2385
|
-
|
|
2436
|
+
const { data } = await withSpinner(
|
|
2437
|
+
"Fetching monitor results",
|
|
2438
|
+
() => client.get(
|
|
2439
|
+
`/api/monitors/${id}/results`,
|
|
2440
|
+
{ limit: options.limit }
|
|
2441
|
+
)
|
|
2386
2442
|
);
|
|
2387
2443
|
output(data.results, {
|
|
2388
2444
|
columns: [
|
|
@@ -2395,12 +2451,18 @@ monitorCommand.command("results <id>").description("Get monitor check results").
|
|
|
2395
2451
|
});
|
|
2396
2452
|
monitorCommand.command("stats <id>").description("Get monitor performance statistics").action(async (id) => {
|
|
2397
2453
|
const client = createAuthenticatedClient();
|
|
2398
|
-
const { data } = await
|
|
2454
|
+
const { data } = await withSpinner(
|
|
2455
|
+
"Fetching monitor statistics",
|
|
2456
|
+
() => client.get(`/api/monitors/${id}/stats`)
|
|
2457
|
+
);
|
|
2399
2458
|
outputDetail(data);
|
|
2400
2459
|
});
|
|
2401
2460
|
monitorCommand.command("status <id>").description("Get current monitor status").action(async (id) => {
|
|
2402
2461
|
const client = createAuthenticatedClient();
|
|
2403
|
-
const { data } = await
|
|
2462
|
+
const { data } = await withSpinner(
|
|
2463
|
+
"Fetching monitor status",
|
|
2464
|
+
() => client.get(`/api/monitors/${id}`)
|
|
2465
|
+
);
|
|
2404
2466
|
const statusInfo = {
|
|
2405
2467
|
id: data.id,
|
|
2406
2468
|
name: data.name,
|
|
@@ -2425,7 +2487,10 @@ monitorCommand.command("create").description("Create a new monitor").requiredOpt
|
|
|
2425
2487
|
method: options.method
|
|
2426
2488
|
}
|
|
2427
2489
|
};
|
|
2428
|
-
const { data } = await
|
|
2490
|
+
const { data } = await withSpinner(
|
|
2491
|
+
"Creating monitor",
|
|
2492
|
+
() => client.post("/api/monitors", body)
|
|
2493
|
+
);
|
|
2429
2494
|
logger.success(`Monitor "${options.name}" created (${data.id})`);
|
|
2430
2495
|
outputDetail(data);
|
|
2431
2496
|
});
|
|
@@ -2447,7 +2512,10 @@ monitorCommand.command("update <id>").description("Update a monitor").option("--
|
|
|
2447
2512
|
logger.warn("No fields to update. Use --name, --url, --interval, --timeout, --method, or --active.");
|
|
2448
2513
|
return;
|
|
2449
2514
|
}
|
|
2450
|
-
const { data } = await
|
|
2515
|
+
const { data } = await withSpinner(
|
|
2516
|
+
"Updating monitor",
|
|
2517
|
+
() => client.patch(`/api/monitors/${id}`, body)
|
|
2518
|
+
);
|
|
2451
2519
|
logger.success(`Monitor ${id} updated`);
|
|
2452
2520
|
outputDetail(data);
|
|
2453
2521
|
});
|
|
@@ -2461,7 +2529,10 @@ monitorCommand.command("delete <id>").description("Delete a monitor").option("--
|
|
|
2461
2529
|
}
|
|
2462
2530
|
}
|
|
2463
2531
|
const client = createAuthenticatedClient();
|
|
2464
|
-
await
|
|
2532
|
+
await withSpinner(
|
|
2533
|
+
"Deleting monitor",
|
|
2534
|
+
() => client.delete(`/api/monitors/${id}`)
|
|
2535
|
+
);
|
|
2465
2536
|
logger.success(`Monitor ${id} deleted`);
|
|
2466
2537
|
});
|
|
2467
2538
|
|
|
@@ -2470,7 +2541,10 @@ import { Command as Command9 } from "commander";
|
|
|
2470
2541
|
var varCommand = new Command9("var").description("Manage project variables");
|
|
2471
2542
|
varCommand.command("list").description("List all variables").action(async () => {
|
|
2472
2543
|
const client = createAuthenticatedClient();
|
|
2473
|
-
const { data } = await
|
|
2544
|
+
const { data } = await withSpinner(
|
|
2545
|
+
"Fetching variables",
|
|
2546
|
+
() => client.get("/api/variables")
|
|
2547
|
+
);
|
|
2474
2548
|
output(data, {
|
|
2475
2549
|
columns: [
|
|
2476
2550
|
{ key: "id", header: "ID" },
|
|
@@ -2482,7 +2556,10 @@ varCommand.command("list").description("List all variables").action(async () =>
|
|
|
2482
2556
|
});
|
|
2483
2557
|
varCommand.command("get <key>").description("Get a variable by key name").action(async (key) => {
|
|
2484
2558
|
const client = createAuthenticatedClient();
|
|
2485
|
-
const { data: variables } = await
|
|
2559
|
+
const { data: variables } = await withSpinner(
|
|
2560
|
+
"Fetching variable",
|
|
2561
|
+
() => client.get("/api/variables")
|
|
2562
|
+
);
|
|
2486
2563
|
const variable = variables.find((v) => v.key === key);
|
|
2487
2564
|
if (!variable) {
|
|
2488
2565
|
throw new CLIError(`Variable "${key}" not found`, 1 /* GeneralError */);
|
|
@@ -2491,29 +2568,41 @@ varCommand.command("get <key>").description("Get a variable by key name").action
|
|
|
2491
2568
|
});
|
|
2492
2569
|
varCommand.command("set <key> <value>").description("Create or update a variable").option("--secret", "Mark as secret (value will be encrypted)").option("--description <description>", "Variable description").action(async (key, value, options) => {
|
|
2493
2570
|
const client = createAuthenticatedClient();
|
|
2494
|
-
const { data: variables } = await
|
|
2571
|
+
const { data: variables } = await withSpinner(
|
|
2572
|
+
"Checking existing variables",
|
|
2573
|
+
() => client.get("/api/variables")
|
|
2574
|
+
);
|
|
2495
2575
|
const existing = variables.find((v) => v.key === key);
|
|
2496
2576
|
if (existing) {
|
|
2497
|
-
await
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2577
|
+
await withSpinner(
|
|
2578
|
+
"Updating variable",
|
|
2579
|
+
() => client.put(`/api/variables/${existing.id}`, {
|
|
2580
|
+
key,
|
|
2581
|
+
value,
|
|
2582
|
+
isSecret: options.secret ?? existing.isSecret,
|
|
2583
|
+
...options.description !== void 0 && { description: options.description }
|
|
2584
|
+
})
|
|
2585
|
+
);
|
|
2503
2586
|
logger.success(`Variable "${key}" updated`);
|
|
2504
2587
|
} else {
|
|
2505
|
-
await
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2588
|
+
await withSpinner(
|
|
2589
|
+
"Creating variable",
|
|
2590
|
+
() => client.post("/api/variables", {
|
|
2591
|
+
key,
|
|
2592
|
+
value,
|
|
2593
|
+
isSecret: options.secret ?? false,
|
|
2594
|
+
...options.description !== void 0 && { description: options.description }
|
|
2595
|
+
})
|
|
2596
|
+
);
|
|
2511
2597
|
logger.success(`Variable "${key}" created`);
|
|
2512
2598
|
}
|
|
2513
2599
|
});
|
|
2514
2600
|
varCommand.command("delete <key>").description("Delete a variable").option("--force", "Skip confirmation").action(async (key, options) => {
|
|
2515
2601
|
const client = createAuthenticatedClient();
|
|
2516
|
-
const { data: variables } = await
|
|
2602
|
+
const { data: variables } = await withSpinner(
|
|
2603
|
+
"Fetching variables",
|
|
2604
|
+
() => client.get("/api/variables")
|
|
2605
|
+
);
|
|
2517
2606
|
const variable = variables.find((v) => v.key === key);
|
|
2518
2607
|
if (!variable) {
|
|
2519
2608
|
throw new CLIError(`Variable "${key}" not found`, 1 /* GeneralError */);
|
|
@@ -2526,7 +2615,10 @@ varCommand.command("delete <key>").description("Delete a variable").option("--fo
|
|
|
2526
2615
|
return;
|
|
2527
2616
|
}
|
|
2528
2617
|
}
|
|
2529
|
-
await
|
|
2618
|
+
await withSpinner(
|
|
2619
|
+
"Deleting variable",
|
|
2620
|
+
() => client.delete(`/api/variables/${variable.id}`)
|
|
2621
|
+
);
|
|
2530
2622
|
logger.success(`Variable "${key}" deleted`);
|
|
2531
2623
|
});
|
|
2532
2624
|
|
|
@@ -2535,7 +2627,10 @@ import { Command as Command10 } from "commander";
|
|
|
2535
2627
|
var tagCommand = new Command10("tag").description("Manage tags");
|
|
2536
2628
|
tagCommand.command("list").description("List all tags").action(async () => {
|
|
2537
2629
|
const client = createAuthenticatedClient();
|
|
2538
|
-
const { data } = await
|
|
2630
|
+
const { data } = await withSpinner(
|
|
2631
|
+
"Fetching tags",
|
|
2632
|
+
() => client.get("/api/tags")
|
|
2633
|
+
);
|
|
2539
2634
|
output(data, {
|
|
2540
2635
|
columns: [
|
|
2541
2636
|
{ key: "id", header: "ID" },
|
|
@@ -2546,10 +2641,13 @@ tagCommand.command("list").description("List all tags").action(async () => {
|
|
|
2546
2641
|
});
|
|
2547
2642
|
tagCommand.command("create <name>").description("Create a new tag").option("--color <color>", "Tag color (hex)").action(async (name, options) => {
|
|
2548
2643
|
const client = createAuthenticatedClient();
|
|
2549
|
-
const { data } = await
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2644
|
+
const { data } = await withSpinner(
|
|
2645
|
+
"Creating tag",
|
|
2646
|
+
() => client.post("/api/tags", {
|
|
2647
|
+
name,
|
|
2648
|
+
color: options.color
|
|
2649
|
+
})
|
|
2650
|
+
);
|
|
2553
2651
|
logger.success(`Tag "${name}" created (${data.id})`);
|
|
2554
2652
|
});
|
|
2555
2653
|
tagCommand.command("delete <id>").description("Delete a tag").option("--force", "Skip confirmation").action(async (id, options) => {
|
|
@@ -2562,7 +2660,10 @@ tagCommand.command("delete <id>").description("Delete a tag").option("--force",
|
|
|
2562
2660
|
}
|
|
2563
2661
|
}
|
|
2564
2662
|
const client = createAuthenticatedClient();
|
|
2565
|
-
await
|
|
2663
|
+
await withSpinner(
|
|
2664
|
+
"Deleting tag",
|
|
2665
|
+
() => client.delete(`/api/tags/${id}`)
|
|
2666
|
+
);
|
|
2566
2667
|
logger.success(`Tag ${id} deleted`);
|
|
2567
2668
|
});
|
|
2568
2669
|
|
|
@@ -3266,17 +3367,44 @@ function buildStatusPageDefinitions(pages) {
|
|
|
3266
3367
|
}
|
|
3267
3368
|
function generateConfigContent(opts) {
|
|
3268
3369
|
const parts = [];
|
|
3370
|
+
parts.push("/**");
|
|
3371
|
+
parts.push(" * Supercheck Configuration");
|
|
3372
|
+
parts.push(" * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
3373
|
+
parts.push(" *");
|
|
3374
|
+
parts.push(" * This file was generated by `supercheck pull`. It is the source of truth");
|
|
3375
|
+
parts.push(" * for your Supercheck project configuration.");
|
|
3376
|
+
parts.push(" *");
|
|
3377
|
+
parts.push(" * Getting Started:");
|
|
3378
|
+
parts.push(" * 1. Review the configuration below and make any changes you need.");
|
|
3379
|
+
parts.push(" * 2. Preview changes: supercheck diff");
|
|
3380
|
+
parts.push(" * 3. Deploy changes: supercheck deploy");
|
|
3381
|
+
parts.push(" * 4. Re-sync: supercheck pull");
|
|
3382
|
+
parts.push(" *");
|
|
3383
|
+
parts.push(" * Useful Commands:");
|
|
3384
|
+
parts.push(" * supercheck test validate Validate local test scripts");
|
|
3385
|
+
parts.push(" * supercheck config validate Validate this config file");
|
|
3386
|
+
parts.push(" * supercheck health Check API connectivity");
|
|
3387
|
+
parts.push(" * supercheck destroy Remove all managed resources from the cloud");
|
|
3388
|
+
parts.push(" *");
|
|
3389
|
+
parts.push(` * Documentation: https://supercheck.io/docs/app/welcome`);
|
|
3390
|
+
parts.push(" */");
|
|
3269
3391
|
parts.push(`import { defineConfig } from '@supercheck/cli'`);
|
|
3270
3392
|
parts.push("");
|
|
3271
3393
|
parts.push("export default defineConfig({");
|
|
3272
3394
|
parts.push(` schemaVersion: '1.0',`);
|
|
3395
|
+
parts.push("");
|
|
3396
|
+
parts.push(" // Project identifiers \u2014 found in Dashboard > Project Settings");
|
|
3273
3397
|
parts.push(" project: {");
|
|
3274
3398
|
parts.push(` organization: '${opts.orgId}',`);
|
|
3275
3399
|
parts.push(` project: '${opts.projectId}',`);
|
|
3276
3400
|
parts.push(" },");
|
|
3401
|
+
parts.push("");
|
|
3402
|
+
parts.push(" // API connection \u2014 set SUPERCHECK_URL env var for self-hosted or staging");
|
|
3277
3403
|
parts.push(" api: {");
|
|
3278
3404
|
parts.push(` baseUrl: process.env.SUPERCHECK_URL ?? '${opts.baseUrl}',`);
|
|
3279
3405
|
parts.push(" },");
|
|
3406
|
+
parts.push("");
|
|
3407
|
+
parts.push(" // Test file patterns \u2014 Playwright (.pw.ts) and k6 (.k6.ts) scripts");
|
|
3280
3408
|
parts.push(" tests: {");
|
|
3281
3409
|
parts.push(" playwright: {");
|
|
3282
3410
|
parts.push(` testMatch: '_supercheck_/tests/**/*.pw.ts',`);
|
|
@@ -3286,42 +3414,33 @@ function generateConfigContent(opts) {
|
|
|
3286
3414
|
parts.push(" },");
|
|
3287
3415
|
parts.push(" },");
|
|
3288
3416
|
if (opts.monitors.length > 0) {
|
|
3417
|
+
parts.push("");
|
|
3418
|
+
parts.push(" // Monitors \u2014 uptime checks, HTTP requests, synthetic tests");
|
|
3289
3419
|
parts.push(` monitors: ${formatArray(opts.monitors, 2)},`);
|
|
3290
3420
|
}
|
|
3291
3421
|
if (opts.jobs.length > 0) {
|
|
3422
|
+
parts.push("");
|
|
3423
|
+
parts.push(" // Jobs \u2014 scheduled or triggered test execution groups");
|
|
3292
3424
|
parts.push(` jobs: ${formatArray(opts.jobs, 2)},`);
|
|
3293
3425
|
}
|
|
3294
3426
|
if (opts.variables.length > 0) {
|
|
3427
|
+
parts.push("");
|
|
3428
|
+
parts.push(" // Variables \u2014 key-value pairs available to tests at runtime");
|
|
3429
|
+
parts.push(" // Secret values use process.env references \u2014 set them in your shell or CI/CD");
|
|
3295
3430
|
parts.push(` variables: ${formatArray(opts.variables, 2)},`);
|
|
3296
3431
|
}
|
|
3297
3432
|
if (opts.tags.length > 0) {
|
|
3433
|
+
parts.push("");
|
|
3434
|
+
parts.push(" // Tags \u2014 labels for organizing tests, monitors, and jobs");
|
|
3298
3435
|
parts.push(` tags: ${formatArray(opts.tags, 2)},`);
|
|
3299
3436
|
}
|
|
3300
3437
|
if (opts.statusPages.length > 0) {
|
|
3438
|
+
parts.push("");
|
|
3439
|
+
parts.push(" // Status Pages \u2014 public dashboards showing monitor health");
|
|
3301
3440
|
parts.push(` statusPages: ${formatArray(opts.statusPages, 2)},`);
|
|
3302
3441
|
}
|
|
3303
3442
|
parts.push("})");
|
|
3304
3443
|
parts.push("");
|
|
3305
|
-
parts.push(`/**`);
|
|
3306
|
-
parts.push(` * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
|
|
3307
|
-
parts.push(` * Getting Started`);
|
|
3308
|
-
parts.push(` * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
|
|
3309
|
-
parts.push(` *`);
|
|
3310
|
-
parts.push(` * 1. Install dependencies:`);
|
|
3311
|
-
parts.push(` * npm install`);
|
|
3312
|
-
parts.push(` * npx playwright install`);
|
|
3313
|
-
parts.push(` *`);
|
|
3314
|
-
parts.push(` * 2. Run tests:`);
|
|
3315
|
-
parts.push(` * npx supercheck test`);
|
|
3316
|
-
parts.push(` *`);
|
|
3317
|
-
parts.push(` * 3. Useful commands:`);
|
|
3318
|
-
parts.push(` * supercheck diff Preview changes against the cloud`);
|
|
3319
|
-
parts.push(` * supercheck deploy Push local config to Supercheck`);
|
|
3320
|
-
parts.push(` * supercheck pull Sync cloud resources locally`);
|
|
3321
|
-
parts.push(` *`);
|
|
3322
|
-
parts.push(` * Documentation: https://docs.supercheck.io`);
|
|
3323
|
-
parts.push(` */`);
|
|
3324
|
-
parts.push("");
|
|
3325
3444
|
return parts.join("\n");
|
|
3326
3445
|
}
|
|
3327
3446
|
function formatArray(arr, baseIndent) {
|
|
@@ -3476,9 +3595,12 @@ var pullCommand = new Command14("pull").description("Pull tests, monitors, jobs,
|
|
|
3476
3595
|
fullTests.push(t);
|
|
3477
3596
|
} else {
|
|
3478
3597
|
try {
|
|
3479
|
-
const { data } = await
|
|
3480
|
-
|
|
3481
|
-
|
|
3598
|
+
const { data } = await withSpinner(
|
|
3599
|
+
`Fetching script for "${t.title}"`,
|
|
3600
|
+
() => client.get(
|
|
3601
|
+
`/api/tests/${t.id}`,
|
|
3602
|
+
{ includeScript: "true" }
|
|
3603
|
+
)
|
|
3482
3604
|
);
|
|
3483
3605
|
fullTests.push(data);
|
|
3484
3606
|
} catch (err) {
|
|
@@ -3607,7 +3729,10 @@ import { Command as Command15 } from "commander";
|
|
|
3607
3729
|
var notificationCommand = new Command15("notification").alias("notifications").description("Manage notification providers");
|
|
3608
3730
|
notificationCommand.command("list").description("List notification providers").action(async () => {
|
|
3609
3731
|
const client = createAuthenticatedClient();
|
|
3610
|
-
const { data } = await
|
|
3732
|
+
const { data } = await withSpinner(
|
|
3733
|
+
"Fetching notification providers",
|
|
3734
|
+
() => client.get("/api/notification-providers")
|
|
3735
|
+
);
|
|
3611
3736
|
output(data, {
|
|
3612
3737
|
columns: [
|
|
3613
3738
|
{ key: "id", header: "ID" },
|
|
@@ -3620,7 +3745,10 @@ notificationCommand.command("list").description("List notification providers").a
|
|
|
3620
3745
|
});
|
|
3621
3746
|
notificationCommand.command("get <id>").description("Get notification provider details").action(async (id) => {
|
|
3622
3747
|
const client = createAuthenticatedClient();
|
|
3623
|
-
const { data } = await
|
|
3748
|
+
const { data } = await withSpinner(
|
|
3749
|
+
"Fetching provider details",
|
|
3750
|
+
() => client.get(`/api/notification-providers/${id}`)
|
|
3751
|
+
);
|
|
3624
3752
|
outputDetail(data);
|
|
3625
3753
|
});
|
|
3626
3754
|
notificationCommand.command("create").description("Create a notification provider").requiredOption("--type <type>", "Provider type (email, slack, webhook, telegram, discord, teams)").requiredOption("--name <name>", "Provider name").option("--config <json>", "Provider config as JSON string").action(async (options) => {
|
|
@@ -3640,11 +3768,14 @@ notificationCommand.command("create").description("Create a notification provide
|
|
|
3640
3768
|
}
|
|
3641
3769
|
}
|
|
3642
3770
|
const client = createAuthenticatedClient();
|
|
3643
|
-
const { data } = await
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3771
|
+
const { data } = await withSpinner(
|
|
3772
|
+
"Creating notification provider",
|
|
3773
|
+
() => client.post("/api/notification-providers", {
|
|
3774
|
+
name: options.name,
|
|
3775
|
+
type: options.type,
|
|
3776
|
+
config: { name: options.name, ...config }
|
|
3777
|
+
})
|
|
3778
|
+
);
|
|
3648
3779
|
logger.success(`Notification provider "${options.name}" created (${data.id})`);
|
|
3649
3780
|
outputDetail(data);
|
|
3650
3781
|
});
|
|
@@ -3654,7 +3785,10 @@ notificationCommand.command("update <id>").description("Update a notification pr
|
|
|
3654
3785
|
logger.warn("No fields to update. Use --name, --type, or --config.");
|
|
3655
3786
|
return;
|
|
3656
3787
|
}
|
|
3657
|
-
const { data: existing } = await
|
|
3788
|
+
const { data: existing } = await withSpinner(
|
|
3789
|
+
"Fetching existing provider",
|
|
3790
|
+
() => client.get(`/api/notification-providers/${id}`)
|
|
3791
|
+
);
|
|
3658
3792
|
let updatedConfig = existing.config ?? {};
|
|
3659
3793
|
if (options.config) {
|
|
3660
3794
|
try {
|
|
@@ -3671,7 +3805,10 @@ notificationCommand.command("update <id>").description("Update a notification pr
|
|
|
3671
3805
|
type: updatedType,
|
|
3672
3806
|
config: updatedConfig
|
|
3673
3807
|
};
|
|
3674
|
-
const { data } = await
|
|
3808
|
+
const { data } = await withSpinner(
|
|
3809
|
+
"Updating notification provider",
|
|
3810
|
+
() => client.put(`/api/notification-providers/${id}`, body)
|
|
3811
|
+
);
|
|
3675
3812
|
logger.success(`Notification provider ${id} updated`);
|
|
3676
3813
|
outputDetail(data);
|
|
3677
3814
|
});
|
|
@@ -3685,7 +3822,10 @@ notificationCommand.command("delete <id>").description("Delete a notification pr
|
|
|
3685
3822
|
}
|
|
3686
3823
|
}
|
|
3687
3824
|
const client = createAuthenticatedClient();
|
|
3688
|
-
await
|
|
3825
|
+
await withSpinner(
|
|
3826
|
+
"Deleting notification provider",
|
|
3827
|
+
() => client.delete(`/api/notification-providers/${id}`)
|
|
3828
|
+
);
|
|
3689
3829
|
logger.success(`Notification provider ${id} deleted`);
|
|
3690
3830
|
});
|
|
3691
3831
|
notificationCommand.command("test").description("Send a test notification to verify provider configuration").requiredOption("--type <type>", "Provider type (email, slack, webhook, telegram, discord, teams)").requiredOption("--config <json>", "Provider config as JSON string").action(async (options) => {
|
|
@@ -3703,9 +3843,12 @@ notificationCommand.command("test").description("Send a test notification to ver
|
|
|
3703
3843
|
throw new CLIError("Invalid JSON in --config", 1 /* GeneralError */);
|
|
3704
3844
|
}
|
|
3705
3845
|
const client = createAuthenticatedClient();
|
|
3706
|
-
const { data } = await
|
|
3707
|
-
"
|
|
3708
|
-
|
|
3846
|
+
const { data } = await withSpinner(
|
|
3847
|
+
"Sending test notification",
|
|
3848
|
+
() => client.post(
|
|
3849
|
+
"/api/notification-providers/test",
|
|
3850
|
+
{ type: options.type, config }
|
|
3851
|
+
)
|
|
3709
3852
|
);
|
|
3710
3853
|
if (data.success) {
|
|
3711
3854
|
logger.success(data.message ?? "Test notification sent successfully");
|
|
@@ -3719,7 +3862,10 @@ import { Command as Command16 } from "commander";
|
|
|
3719
3862
|
var alertCommand = new Command16("alert").alias("alerts").description("View alert history");
|
|
3720
3863
|
alertCommand.command("history").description("Get alert history").option("--page <page>", "Page number", "1").option("--limit <limit>", "Number of results per page", "50").action(async (options) => {
|
|
3721
3864
|
const client = createAuthenticatedClient();
|
|
3722
|
-
const { data } = await
|
|
3865
|
+
const { data } = await withSpinner(
|
|
3866
|
+
"Fetching alert history",
|
|
3867
|
+
() => client.get("/api/alerts/history", { page: options.page, limit: options.limit })
|
|
3868
|
+
);
|
|
3723
3869
|
const items = Array.isArray(data) ? data : data.data;
|
|
3724
3870
|
const pagination = Array.isArray(data) ? null : data.pagination;
|
|
3725
3871
|
output(items, {
|
|
@@ -3750,7 +3896,10 @@ var auditCommand = new Command17("audit").description("View audit logs (admin)")
|
|
|
3750
3896
|
};
|
|
3751
3897
|
if (options.search) params.search = options.search;
|
|
3752
3898
|
if (options.action) params.action = options.action;
|
|
3753
|
-
const { data } = await
|
|
3899
|
+
const { data } = await withSpinner(
|
|
3900
|
+
"Fetching audit logs",
|
|
3901
|
+
() => client.get("/api/audit", params)
|
|
3902
|
+
);
|
|
3754
3903
|
if (!data.success) {
|
|
3755
3904
|
throw new CLIError("Failed to fetch audit logs", 4 /* ApiError */);
|
|
3756
3905
|
}
|