@supercheck/cli 0.1.0-beta.7 → 0.1.0-beta.8

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.
@@ -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 = { ...change.local.definition };
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, ...body } = change.local.definition;
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) {