@supercheck/cli 0.1.0-beta.7 → 0.1.0-beta.9
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 +159 -52
- 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.9" : "0.0.0-dev";
|
|
217
217
|
|
|
218
218
|
// src/api/client.ts
|
|
219
219
|
import { ProxyAgent } from "undici";
|
|
@@ -643,6 +643,93 @@ function safeId(value) {
|
|
|
643
643
|
if (str === "undefined" || str === "null" || str === "") return void 0;
|
|
644
644
|
return str;
|
|
645
645
|
}
|
|
646
|
+
function normalizeAlertConfig(alert) {
|
|
647
|
+
const normalized = { ...alert };
|
|
648
|
+
if (normalized.customMessage === "" || normalized.customMessage === null) delete normalized.customMessage;
|
|
649
|
+
if (normalized.failureThreshold === 1) delete normalized.failureThreshold;
|
|
650
|
+
if (normalized.recoveryThreshold === 1) delete normalized.recoveryThreshold;
|
|
651
|
+
for (const key of ["alertOnFailure", "alertOnRecovery", "alertOnSslExpiration", "alertOnSuccess", "alertOnTimeout"]) {
|
|
652
|
+
if (normalized[key] === false) delete normalized[key];
|
|
653
|
+
}
|
|
654
|
+
if (Array.isArray(normalized.notificationProviders) && normalized.notificationProviders.length === 0) {
|
|
655
|
+
delete normalized.notificationProviders;
|
|
656
|
+
}
|
|
657
|
+
return Object.keys(normalized).length > 0 ? normalized : void 0;
|
|
658
|
+
}
|
|
659
|
+
function normalizeMonitorConfig(config) {
|
|
660
|
+
const normalized = { ...config };
|
|
661
|
+
delete normalized.sslLastCheckedAt;
|
|
662
|
+
if (normalized.playwrightOptions && typeof normalized.playwrightOptions === "object") {
|
|
663
|
+
const opts = { ...normalized.playwrightOptions };
|
|
664
|
+
if (opts.retries === 0) delete opts.retries;
|
|
665
|
+
if (opts.timeout === 3e5) delete opts.timeout;
|
|
666
|
+
if (opts.headless === true) delete opts.headless;
|
|
667
|
+
normalized.playwrightOptions = Object.keys(opts).length > 0 ? opts : void 0;
|
|
668
|
+
if (!normalized.playwrightOptions) delete normalized.playwrightOptions;
|
|
669
|
+
}
|
|
670
|
+
if (normalized.locationConfig && typeof normalized.locationConfig === "object") {
|
|
671
|
+
const loc = { ...normalized.locationConfig };
|
|
672
|
+
const hasLocations = Array.isArray(loc.locations) && loc.locations.length > 0;
|
|
673
|
+
if (!loc.enabled || !hasLocations) {
|
|
674
|
+
delete normalized.locationConfig;
|
|
675
|
+
} else {
|
|
676
|
+
if (loc.enabled === true) delete loc.enabled;
|
|
677
|
+
if (loc.strategy === "majority") delete loc.strategy;
|
|
678
|
+
if (loc.threshold === 50) delete loc.threshold;
|
|
679
|
+
normalized.locationConfig = Object.keys(loc).length > 0 ? loc : void 0;
|
|
680
|
+
if (!normalized.locationConfig) delete normalized.locationConfig;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
return Object.keys(normalized).length > 0 ? normalized : void 0;
|
|
684
|
+
}
|
|
685
|
+
function normalizeRemoteRaw(type, raw) {
|
|
686
|
+
const normalized = { ...raw };
|
|
687
|
+
delete normalized.createdAt;
|
|
688
|
+
delete normalized.updatedAt;
|
|
689
|
+
delete normalized.projectId;
|
|
690
|
+
delete normalized.organizationId;
|
|
691
|
+
delete normalized.createdByUserId;
|
|
692
|
+
if (type === "monitor") {
|
|
693
|
+
if (normalized.config && typeof normalized.config === "object") {
|
|
694
|
+
normalized.config = normalizeMonitorConfig(normalized.config);
|
|
695
|
+
if (!normalized.config) delete normalized.config;
|
|
696
|
+
}
|
|
697
|
+
if (normalized.alertConfig && typeof normalized.alertConfig === "object") {
|
|
698
|
+
normalized.alertConfig = normalizeAlertConfig(normalized.alertConfig);
|
|
699
|
+
if (!normalized.alertConfig) delete normalized.alertConfig;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
if (type === "job") {
|
|
703
|
+
if (Array.isArray(normalized.tests)) {
|
|
704
|
+
normalized.tests = normalized.tests.map((t) => {
|
|
705
|
+
if (typeof t === "string") return t;
|
|
706
|
+
if (t && typeof t === "object" && t.id) {
|
|
707
|
+
const testType = t.type === "performance" || t.type === "k6" ? "k6" : "pw";
|
|
708
|
+
return `_supercheck_/tests/${t.id}.${testType}.ts`;
|
|
709
|
+
}
|
|
710
|
+
return t;
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
if (normalized.alertConfig && typeof normalized.alertConfig === "object") {
|
|
714
|
+
normalized.alertConfig = normalizeAlertConfig(normalized.alertConfig);
|
|
715
|
+
if (!normalized.alertConfig) delete normalized.alertConfig;
|
|
716
|
+
}
|
|
717
|
+
delete normalized.status;
|
|
718
|
+
}
|
|
719
|
+
if (type === "variable") {
|
|
720
|
+
if (normalized.value === void 0 || normalized.value === null) {
|
|
721
|
+
normalized.value = "";
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
if (type === "statusPage") {
|
|
725
|
+
if (normalized.pageDescription !== void 0 && normalized.description === void 0) {
|
|
726
|
+
normalized.description = normalized.pageDescription;
|
|
727
|
+
}
|
|
728
|
+
delete normalized.pageDescription;
|
|
729
|
+
if (!normalized.description) delete normalized.description;
|
|
730
|
+
}
|
|
731
|
+
return normalized;
|
|
732
|
+
}
|
|
646
733
|
async function fetchRemoteResources(client) {
|
|
647
734
|
const resources = [];
|
|
648
735
|
try {
|
|
@@ -653,7 +740,7 @@ async function fetchRemoteResources(client) {
|
|
|
653
740
|
logger.debug("Skipping job with missing id");
|
|
654
741
|
continue;
|
|
655
742
|
}
|
|
656
|
-
resources.push({ id, type: "job", name: String(job.name ?? ""), raw: job });
|
|
743
|
+
resources.push({ id, type: "job", name: String(job.name ?? ""), raw: normalizeRemoteRaw("job", job) });
|
|
657
744
|
}
|
|
658
745
|
} catch (err) {
|
|
659
746
|
logFetchError("jobs", err);
|
|
@@ -666,7 +753,7 @@ async function fetchRemoteResources(client) {
|
|
|
666
753
|
logger.debug("Skipping test with missing id");
|
|
667
754
|
continue;
|
|
668
755
|
}
|
|
669
|
-
resources.push({ id, type: "test", name: String(test.title ?? ""), raw: test });
|
|
756
|
+
resources.push({ id, type: "test", name: String(test.title ?? ""), raw: normalizeRemoteRaw("test", test) });
|
|
670
757
|
}
|
|
671
758
|
} catch (err) {
|
|
672
759
|
logFetchError("tests", err);
|
|
@@ -679,7 +766,7 @@ async function fetchRemoteResources(client) {
|
|
|
679
766
|
logger.debug("Skipping monitor with missing id");
|
|
680
767
|
continue;
|
|
681
768
|
}
|
|
682
|
-
resources.push({ id, type: "monitor", name: String(monitor.name ?? ""), raw: monitor });
|
|
769
|
+
resources.push({ id, type: "monitor", name: String(monitor.name ?? ""), raw: normalizeRemoteRaw("monitor", monitor) });
|
|
683
770
|
}
|
|
684
771
|
} catch (err) {
|
|
685
772
|
logFetchError("monitors", err);
|
|
@@ -692,7 +779,7 @@ async function fetchRemoteResources(client) {
|
|
|
692
779
|
logger.debug("Skipping variable with missing id");
|
|
693
780
|
continue;
|
|
694
781
|
}
|
|
695
|
-
resources.push({ id, type: "variable", name: String(v.key ?? ""), raw: v });
|
|
782
|
+
resources.push({ id, type: "variable", name: String(v.key ?? ""), raw: normalizeRemoteRaw("variable", v) });
|
|
696
783
|
}
|
|
697
784
|
} catch (err) {
|
|
698
785
|
logFetchError("variables", err);
|
|
@@ -705,7 +792,7 @@ async function fetchRemoteResources(client) {
|
|
|
705
792
|
logger.debug("Skipping tag with missing id");
|
|
706
793
|
continue;
|
|
707
794
|
}
|
|
708
|
-
resources.push({ id, type: "tag", name: String(t.name ?? ""), raw: t });
|
|
795
|
+
resources.push({ id, type: "tag", name: String(t.name ?? ""), raw: normalizeRemoteRaw("tag", t) });
|
|
709
796
|
}
|
|
710
797
|
} catch (err) {
|
|
711
798
|
logFetchError("tags", err);
|
|
@@ -718,7 +805,7 @@ async function fetchRemoteResources(client) {
|
|
|
718
805
|
logger.debug("Skipping status page with missing id");
|
|
719
806
|
continue;
|
|
720
807
|
}
|
|
721
|
-
resources.push({ id, type: "statusPage", name: String(sp.name ?? ""), raw: sp });
|
|
808
|
+
resources.push({ id, type: "statusPage", name: String(sp.name ?? ""), raw: normalizeRemoteRaw("statusPage", sp) });
|
|
722
809
|
}
|
|
723
810
|
} catch (err) {
|
|
724
811
|
logFetchError("status-pages", err);
|
|
@@ -2822,18 +2909,37 @@ var diffCommand = new Command11("diff").description("Preview changes between loc
|
|
|
2822
2909
|
// src/commands/deploy.ts
|
|
2823
2910
|
import { Command as Command12 } from "commander";
|
|
2824
2911
|
import pc4 from "picocolors";
|
|
2912
|
+
function prepareBodyForApi(type, body) {
|
|
2913
|
+
const payload = { ...body };
|
|
2914
|
+
if (type === "job") {
|
|
2915
|
+
if (Array.isArray(payload.tests)) {
|
|
2916
|
+
payload.tests = payload.tests.map((t) => {
|
|
2917
|
+
const match = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/i.exec(t);
|
|
2918
|
+
return match ? match[1] : t;
|
|
2919
|
+
});
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2922
|
+
if (type === "statusPage") {
|
|
2923
|
+
if (payload.description) {
|
|
2924
|
+
payload.pageDescription = payload.description;
|
|
2925
|
+
delete payload.description;
|
|
2926
|
+
}
|
|
2927
|
+
}
|
|
2928
|
+
return payload;
|
|
2929
|
+
}
|
|
2825
2930
|
async function applyChange(client, change) {
|
|
2826
2931
|
try {
|
|
2827
2932
|
const endpoint = getApiEndpoint(change.type);
|
|
2828
2933
|
switch (change.action) {
|
|
2829
2934
|
case "create": {
|
|
2830
|
-
const body =
|
|
2935
|
+
const body = prepareBodyForApi(change.type, change.local.definition);
|
|
2831
2936
|
await client.post(endpoint, body);
|
|
2832
2937
|
return { success: true };
|
|
2833
2938
|
}
|
|
2834
2939
|
case "update": {
|
|
2835
2940
|
const id = change.id ?? change.remote.id;
|
|
2836
|
-
const { id: _id, ...
|
|
2941
|
+
const { id: _id, ...rawBody } = change.local.definition;
|
|
2942
|
+
const body = prepareBodyForApi(change.type, rawBody);
|
|
2837
2943
|
await client.put(`${endpoint}/${id}`, body);
|
|
2838
2944
|
return { success: true };
|
|
2839
2945
|
}
|
|
@@ -3358,49 +3464,6 @@ function buildStatusPageDefinitions(pages) {
|
|
|
3358
3464
|
}
|
|
3359
3465
|
function generateConfigContent(opts) {
|
|
3360
3466
|
const parts = [];
|
|
3361
|
-
parts.push("/**");
|
|
3362
|
-
parts.push(" * Supercheck Configuration");
|
|
3363
|
-
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");
|
|
3364
|
-
parts.push(" *");
|
|
3365
|
-
parts.push(" * This file was generated by `supercheck pull`. It is the source of truth");
|
|
3366
|
-
parts.push(" * for your Supercheck project configuration.");
|
|
3367
|
-
parts.push(" *");
|
|
3368
|
-
parts.push(" * Getting Started:");
|
|
3369
|
-
parts.push(" * 1. Install dependencies:");
|
|
3370
|
-
parts.push(" * npm install -D @supercheck/cli typescript @types/node");
|
|
3371
|
-
parts.push(" * # If using Playwright tests, also install:");
|
|
3372
|
-
parts.push(" * npm install -D @playwright/test");
|
|
3373
|
-
parts.push(" * # If using k6 tests, install k6: https://grafana.com/docs/k6/latest/set-up/install-k6/");
|
|
3374
|
-
parts.push(" *");
|
|
3375
|
-
parts.push(" * 2. Review the configuration below and make any changes you need.");
|
|
3376
|
-
parts.push(" * 3. Preview what will change: npx supercheck diff");
|
|
3377
|
-
parts.push(" * 4. Deploy your changes: npx supercheck deploy");
|
|
3378
|
-
parts.push(" * 5. Re-sync from cloud: npx supercheck pull");
|
|
3379
|
-
parts.push(" *");
|
|
3380
|
-
parts.push(" * CLI Commands:");
|
|
3381
|
-
parts.push(" * supercheck pull Pull remote config & test scripts to local");
|
|
3382
|
-
parts.push(" * supercheck diff Compare local config vs remote");
|
|
3383
|
-
parts.push(" * supercheck deploy Deploy local config to the cloud");
|
|
3384
|
-
parts.push(" * supercheck destroy Remove all managed resources from the cloud");
|
|
3385
|
-
parts.push(" *");
|
|
3386
|
-
parts.push(" * supercheck test list List all tests");
|
|
3387
|
-
parts.push(" * supercheck test validate Validate a local test script");
|
|
3388
|
-
parts.push(" * supercheck test execute <id> Execute a test immediately");
|
|
3389
|
-
parts.push(" *");
|
|
3390
|
-
parts.push(" * supercheck monitor list List all monitors");
|
|
3391
|
-
parts.push(" * supercheck job list List all jobs");
|
|
3392
|
-
parts.push(" * supercheck job run --id <id> Run a job immediately");
|
|
3393
|
-
parts.push(" *");
|
|
3394
|
-
parts.push(" * supercheck config validate Validate this config file");
|
|
3395
|
-
parts.push(" * supercheck health Check API connectivity");
|
|
3396
|
-
parts.push(" * supercheck whoami Show current authentication info");
|
|
3397
|
-
parts.push(" *");
|
|
3398
|
-
parts.push(" * CI/CD Integration:");
|
|
3399
|
-
parts.push(" * Set the SUPERCHECK_TOKEN environment variable in your CI/CD pipeline");
|
|
3400
|
-
parts.push(" * and run `supercheck deploy` to push changes automatically.");
|
|
3401
|
-
parts.push(" *");
|
|
3402
|
-
parts.push(` * Documentation: https://supercheck.io/docs/app/welcome`);
|
|
3403
|
-
parts.push(" */");
|
|
3404
3467
|
parts.push(`import { defineConfig } from '@supercheck/cli'`);
|
|
3405
3468
|
parts.push("");
|
|
3406
3469
|
parts.push("export default defineConfig({");
|
|
@@ -3454,6 +3517,50 @@ function generateConfigContent(opts) {
|
|
|
3454
3517
|
}
|
|
3455
3518
|
parts.push("})");
|
|
3456
3519
|
parts.push("");
|
|
3520
|
+
parts.push("/**");
|
|
3521
|
+
parts.push(" * Supercheck \u2014 Getting Started");
|
|
3522
|
+
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");
|
|
3523
|
+
parts.push(" *");
|
|
3524
|
+
parts.push(" * This file was generated by `supercheck pull`. It is the source of truth");
|
|
3525
|
+
parts.push(" * for your Supercheck project configuration.");
|
|
3526
|
+
parts.push(" *");
|
|
3527
|
+
parts.push(" * Getting Started:");
|
|
3528
|
+
parts.push(" * 1. Install dependencies:");
|
|
3529
|
+
parts.push(" * npm install -D @supercheck/cli typescript @types/node");
|
|
3530
|
+
parts.push(" * # If using Playwright tests, also install:");
|
|
3531
|
+
parts.push(" * npm install -D @playwright/test");
|
|
3532
|
+
parts.push(" * # If using k6 tests, install k6: https://grafana.com/docs/k6/latest/set-up/install-k6/");
|
|
3533
|
+
parts.push(" *");
|
|
3534
|
+
parts.push(" * 2. Review the configuration above and make any changes you need.");
|
|
3535
|
+
parts.push(" * 3. Preview what will change: npx supercheck diff");
|
|
3536
|
+
parts.push(" * 4. Deploy your changes: npx supercheck deploy");
|
|
3537
|
+
parts.push(" * 5. Re-sync from cloud: npx supercheck pull");
|
|
3538
|
+
parts.push(" *");
|
|
3539
|
+
parts.push(" * CLI Commands:");
|
|
3540
|
+
parts.push(" * supercheck pull Pull remote config & test scripts to local");
|
|
3541
|
+
parts.push(" * supercheck diff Compare local config vs remote");
|
|
3542
|
+
parts.push(" * supercheck deploy Deploy local config to the cloud");
|
|
3543
|
+
parts.push(" * supercheck destroy Remove all managed resources from the cloud");
|
|
3544
|
+
parts.push(" *");
|
|
3545
|
+
parts.push(" * supercheck test list List all tests");
|
|
3546
|
+
parts.push(" * supercheck test validate Validate a local test script");
|
|
3547
|
+
parts.push(" * supercheck test execute <id> Execute a test immediately");
|
|
3548
|
+
parts.push(" *");
|
|
3549
|
+
parts.push(" * supercheck monitor list List all monitors");
|
|
3550
|
+
parts.push(" * supercheck job list List all jobs");
|
|
3551
|
+
parts.push(" * supercheck job run --id <id> Run a job immediately");
|
|
3552
|
+
parts.push(" *");
|
|
3553
|
+
parts.push(" * supercheck config validate Validate this config file");
|
|
3554
|
+
parts.push(" * supercheck health Check API connectivity");
|
|
3555
|
+
parts.push(" * supercheck whoami Show current authentication info");
|
|
3556
|
+
parts.push(" *");
|
|
3557
|
+
parts.push(" * CI/CD Integration:");
|
|
3558
|
+
parts.push(" * Set the SUPERCHECK_TOKEN environment variable in your CI/CD pipeline");
|
|
3559
|
+
parts.push(" * and run `supercheck deploy` to push changes automatically.");
|
|
3560
|
+
parts.push(" *");
|
|
3561
|
+
parts.push(` * Documentation: https://supercheck.io/docs/app/welcome`);
|
|
3562
|
+
parts.push(" */");
|
|
3563
|
+
parts.push("");
|
|
3457
3564
|
return parts.join("\n");
|
|
3458
3565
|
}
|
|
3459
3566
|
function formatArray(arr, baseIndent) {
|