@siteoshq/cli 2.6.1 → 2.7.0

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/cli.js CHANGED
@@ -17,7 +17,7 @@ __export(cookie_verification_exports, {
17
17
  verificationTarget: () => verificationTarget,
18
18
  verifyCookieWebsite: () => verifyCookieWebsite
19
19
  });
20
- import { z as z12 } from "zod";
20
+ import { z as z13 } from "zod";
21
21
  function verificationTarget(websiteUrl, candidate) {
22
22
  const website = new URL(websiteUrl);
23
23
  const target = new URL(candidate ?? websiteUrl, website);
@@ -322,10 +322,10 @@ async function verifyCookieWebsite(input) {
322
322
  detail: "The request limit was reached; this run is incomplete."
323
323
  });
324
324
  const config = envelope;
325
- const status = issues.length ? "failed" : assessment.unknownOrigins.length || assessment.unknownStorage.length || config?.config.integrations.googleConsentMode === "advanced" ? "needs-review" : "passed";
325
+ const status2 = issues.length ? "failed" : assessment.unknownOrigins.length || assessment.unknownStorage.length || config?.config.integrations.googleConsentMode === "advanced" ? "needs-review" : "passed";
326
326
  return {
327
327
  schemaVersion: 1,
328
- status,
328
+ status: status2,
329
329
  startedAt,
330
330
  completedAt: (/* @__PURE__ */ new Date()).toISOString(),
331
331
  expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1e3).toISOString(),
@@ -367,73 +367,73 @@ var Names, Service, Envelope, State, VerificationInstallation;
367
367
  var init_cookie_verification = __esm({
368
368
  "src/services/cookie-verification.ts"() {
369
369
  "use strict";
370
- Names = z12.object({
371
- exact: z12.array(z12.string()),
372
- prefixes: z12.array(z12.string())
370
+ Names = z13.object({
371
+ exact: z13.array(z13.string()),
372
+ prefixes: z13.array(z13.string())
373
373
  });
374
- Service = z12.object({
375
- key: z12.string(),
376
- purposeKey: z12.string(),
377
- lifecycle: z12.object({
378
- scriptOrigins: z12.array(z12.string()),
379
- iframeOrigins: z12.array(z12.string()),
380
- pixelOrigins: z12.array(z12.string()),
374
+ Service = z13.object({
375
+ key: z13.string(),
376
+ purposeKey: z13.string(),
377
+ lifecycle: z13.object({
378
+ scriptOrigins: z13.array(z13.string()),
379
+ iframeOrigins: z13.array(z13.string()),
380
+ pixelOrigins: z13.array(z13.string()),
381
381
  firstPartyCookies: Names,
382
382
  localStorage: Names
383
383
  }).optional()
384
384
  });
385
- Envelope = z12.object({
386
- publicKey: z12.string(),
387
- revision: z12.number(),
388
- ruleKey: z12.string(),
389
- profileKey: z12.string(),
390
- trustedSignals: z12.object({
391
- region: z12.object({
392
- countryCode: z12.string().nullable(),
393
- subdivisionCode: z12.string().nullable()
385
+ Envelope = z13.object({
386
+ publicKey: z13.string(),
387
+ revision: z13.number(),
388
+ ruleKey: z13.string(),
389
+ profileKey: z13.string(),
390
+ trustedSignals: z13.object({
391
+ region: z13.object({
392
+ countryCode: z13.string().nullable(),
393
+ subdivisionCode: z13.string().nullable()
394
394
  }).optional()
395
395
  }).optional(),
396
- config: z12.object({
397
- services: z12.array(Service),
398
- categories: z12.array(z12.object({ key: z12.string(), required: z12.boolean() })),
399
- integrations: z12.object({ googleConsentMode: z12.string() })
396
+ config: z13.object({
397
+ services: z13.array(Service),
398
+ categories: z13.array(z13.object({ key: z13.string(), required: z13.boolean() })),
399
+ integrations: z13.object({ googleConsentMode: z13.string() })
400
400
  })
401
401
  });
402
- State = z12.object({
403
- runtimeVersion: z12.string(),
404
- preview: z12.boolean(),
405
- resolved: z12.object({
406
- publicKey: z12.string(),
407
- revision: z12.number(),
408
- ruleKey: z12.string(),
409
- profileKey: z12.string()
402
+ State = z13.object({
403
+ runtimeVersion: z13.string(),
404
+ preview: z13.boolean(),
405
+ resolved: z13.object({
406
+ publicKey: z13.string(),
407
+ revision: z13.number(),
408
+ ruleKey: z13.string(),
409
+ profileKey: z13.string()
410
410
  }).nullable(),
411
- consent: z12.object({
412
- categories: z12.array(z12.string()),
413
- decision: z12.string(),
414
- globalPrivacyControl: z12.boolean(),
415
- privacyChoices: z12.object({
416
- saleOrShareOptOut: z12.boolean(),
417
- targetedAdvertisingOptOut: z12.boolean()
411
+ consent: z13.object({
412
+ categories: z13.array(z13.string()),
413
+ decision: z13.string(),
414
+ globalPrivacyControl: z13.boolean(),
415
+ privacyChoices: z13.object({
416
+ saleOrShareOptOut: z13.boolean(),
417
+ targetedAdvertisingOptOut: z13.boolean()
418
418
  })
419
419
  }),
420
- services: z12.array(
421
- z12.object({
422
- key: z12.string(),
423
- allowed: z12.boolean(),
424
- footprintPresent: z12.boolean()
420
+ services: z13.array(
421
+ z13.object({
422
+ key: z13.string(),
423
+ allowed: z13.boolean(),
424
+ footprintPresent: z13.boolean()
425
425
  })
426
426
  )
427
427
  });
428
- VerificationInstallation = z12.object({
429
- publicKey: z12.string(),
430
- currentPublishedRevision: z12.number().int().positive(),
431
- delivery: z12.object({
432
- runtimeUrl: z12.string().url(),
433
- configUrl: z12.string().url(),
434
- analyticsUrl: z12.string().url().nullable(),
435
- receiptsUrl: z12.string().url(),
436
- handshakeUrl: z12.string().url()
428
+ VerificationInstallation = z13.object({
429
+ publicKey: z13.string(),
430
+ currentPublishedRevision: z13.number().int().positive(),
431
+ delivery: z13.object({
432
+ runtimeUrl: z13.string().url(),
433
+ configUrl: z13.string().url(),
434
+ analyticsUrl: z13.string().url().nullable(),
435
+ receiptsUrl: z13.string().url(),
436
+ handshakeUrl: z13.string().url()
437
437
  })
438
438
  });
439
439
  }
@@ -1506,7 +1506,7 @@ var OverviewSchema = z4.object({
1506
1506
  });
1507
1507
  function createProjectApi(input) {
1508
1508
  const origin = resolveSiteOSAuthBaseUrl(input.env);
1509
- async function request(path30, schema, body, method) {
1509
+ async function request(path31, schema, body, method) {
1510
1510
  const scope = body === void 0 ? "projects:workspace:read" : "projects:workspace:write";
1511
1511
  const grant = await input.grants.acquire({
1512
1512
  audience: "siteos-projects",
@@ -1520,7 +1520,7 @@ function createProjectApi(input) {
1520
1520
  message: "SiteOS API access is unavailable."
1521
1521
  });
1522
1522
  const response = await input.fetchImpl(
1523
- `${origin}/api/projects/v1/projects${path30}`,
1523
+ `${origin}/api/projects/v1/projects${path31}`,
1524
1524
  {
1525
1525
  method: method ?? (body === void 0 ? "GET" : "POST"),
1526
1526
  headers: {
@@ -1552,26 +1552,26 @@ function createProjectApi(input) {
1552
1552
  }
1553
1553
  return {
1554
1554
  origin,
1555
- async update(id, details) {
1555
+ async update(id2, details) {
1556
1556
  const { value, organizationId } = await request(
1557
- `/${encodeURIComponent(id)}`,
1557
+ `/${encodeURIComponent(id2)}`,
1558
1558
  z4.object({ project: ProjectSchema }),
1559
1559
  details,
1560
1560
  "PATCH"
1561
1561
  );
1562
1562
  checkOrganization(value.project, organizationId);
1563
- if (value.project.id !== id) throw invalidResponse();
1563
+ if (value.project.id !== id2) throw invalidResponse();
1564
1564
  return value.project;
1565
1565
  },
1566
- async updateEnvironment(id, environmentId, details) {
1566
+ async updateEnvironment(id2, environmentId, details) {
1567
1567
  const { value, organizationId } = await request(
1568
- `/${encodeURIComponent(id)}/environments/${encodeURIComponent(environmentId)}`,
1568
+ `/${encodeURIComponent(id2)}/environments/${encodeURIComponent(environmentId)}`,
1569
1569
  z4.object({ project: ProjectSchema }),
1570
1570
  details,
1571
1571
  "PATCH"
1572
1572
  );
1573
1573
  checkOrganization(value.project, organizationId);
1574
- if (value.project.id !== id) throw invalidResponse();
1574
+ if (value.project.id !== id2) throw invalidResponse();
1575
1575
  return value.project;
1576
1576
  },
1577
1577
  async list() {
@@ -1584,14 +1584,14 @@ function createProjectApi(input) {
1584
1584
  );
1585
1585
  return value.projects;
1586
1586
  },
1587
- async get(id, environmentSlug) {
1587
+ async get(id2, environmentSlug) {
1588
1588
  const { value, organizationId } = await request(
1589
- `/${encodeURIComponent(id)}${environmentSlug ? `?env=${encodeURIComponent(environmentSlug)}` : ""}`,
1589
+ `/${encodeURIComponent(id2)}${environmentSlug ? `?env=${encodeURIComponent(environmentSlug)}` : ""}`,
1590
1590
  OverviewSchema
1591
1591
  );
1592
1592
  checkOrganization(value.project, organizationId);
1593
- if (value.project.id !== id || value.services.some(
1594
- (service) => service.attachment && (service.attachment.projectId !== id || service.attachment.service !== service.service)
1593
+ if (value.project.id !== id2 || value.services.some(
1594
+ (service) => service.attachment && (service.attachment.projectId !== id2 || service.attachment.service !== service.service)
1595
1595
  ))
1596
1596
  throw invalidResponse();
1597
1597
  return value;
@@ -1605,33 +1605,33 @@ function createProjectApi(input) {
1605
1605
  checkOrganization(value.project, organizationId);
1606
1606
  return value.project;
1607
1607
  },
1608
- async connect(id, service, resourceId, environmentSlug) {
1608
+ async connect(id2, service, resourceId, environmentSlug) {
1609
1609
  await request(
1610
- `/${encodeURIComponent(id)}/services/${service}${environmentSlug ? `?env=${encodeURIComponent(environmentSlug)}` : ""}`,
1610
+ `/${encodeURIComponent(id2)}/services/${service}${environmentSlug ? `?env=${encodeURIComponent(environmentSlug)}` : ""}`,
1611
1611
  z4.object({
1612
1612
  attachment: z4.object({
1613
1613
  resourceId: z4.string(),
1614
- projectId: z4.literal(id),
1614
+ projectId: z4.literal(id2),
1615
1615
  service: z4.literal(service)
1616
1616
  })
1617
1617
  }),
1618
1618
  resourceId ? { resourceId } : { create: true }
1619
1619
  );
1620
- return this.get(id, environmentSlug);
1620
+ return this.get(id2, environmentSlug);
1621
1621
  },
1622
- async createEnvironment(id, details) {
1622
+ async createEnvironment(id2, details) {
1623
1623
  const { value, organizationId } = await request(
1624
- `/${encodeURIComponent(id)}/environments`,
1624
+ `/${encodeURIComponent(id2)}/environments`,
1625
1625
  z4.object({ project: ProjectSchema }),
1626
1626
  details
1627
1627
  );
1628
1628
  checkOrganization(value.project, organizationId);
1629
- if (value.project.id !== id) throw invalidResponse();
1629
+ if (value.project.id !== id2) throw invalidResponse();
1630
1630
  return value.project;
1631
1631
  },
1632
- async availableEnvironments(id, service) {
1632
+ async availableEnvironments(id2, service) {
1633
1633
  return (await request(
1634
- `/${encodeURIComponent(id)}/services/${service}/environments`,
1634
+ `/${encodeURIComponent(id2)}/services/${service}/environments`,
1635
1635
  z4.object({
1636
1636
  environments: z4.array(
1637
1637
  z4.object({ id: z4.string(), name: z4.string(), slug: z4.string() })
@@ -1639,18 +1639,18 @@ function createProjectApi(input) {
1639
1639
  })
1640
1640
  )).value.environments;
1641
1641
  },
1642
- async connectEnvironment(id, service, environmentId, resourceId) {
1642
+ async connectEnvironment(id2, service, environmentId, resourceId) {
1643
1643
  await request(
1644
- `/${encodeURIComponent(id)}/services/${service}/environments/${encodeURIComponent(environmentId)}`,
1644
+ `/${encodeURIComponent(id2)}/services/${service}/environments/${encodeURIComponent(environmentId)}`,
1645
1645
  z4.object({
1646
1646
  attachment: z4.object({
1647
- projectId: z4.literal(id),
1647
+ projectId: z4.literal(id2),
1648
1648
  service: z4.literal(service)
1649
1649
  })
1650
1650
  }),
1651
1651
  resourceId ? { resourceId } : { create: true }
1652
1652
  );
1653
- return this.get(id);
1653
+ return this.get(id2);
1654
1654
  }
1655
1655
  };
1656
1656
  }
@@ -2575,14 +2575,14 @@ function generateOpaqueValue() {
2575
2575
  function sha256Base64Url(value) {
2576
2576
  return createHash4("sha256").update(value, "utf-8").digest("base64url");
2577
2577
  }
2578
- function sessionResult(session, json, status) {
2578
+ function sessionResult(session, json, status2) {
2579
2579
  if (json) {
2580
2580
  return { exitCode: 0, stdout: JSON.stringify(session, null, 2) };
2581
2581
  }
2582
- if (status === "expired") {
2582
+ if (status2 === "expired") {
2583
2583
  return { exitCode: 0, stdout: "SiteOS CLI session is expired." };
2584
2584
  }
2585
- if (status === "revoked") {
2585
+ if (status2 === "revoked") {
2586
2586
  return { exitCode: 0, stdout: "SiteOS CLI session is revoked." };
2587
2587
  }
2588
2588
  return {
@@ -2692,126 +2692,571 @@ function isCliExitCode(value) {
2692
2692
  return Object.values(CLI_EXIT_CODE).some((exitCode) => exitCode === value);
2693
2693
  }
2694
2694
 
2695
+ // src/forms-workspace-command.ts
2696
+ import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
2697
+ import path9 from "path";
2698
+ import { parseArgs } from "util";
2699
+ import { z as z7 } from "zod";
2700
+ var id = z7.string().min(1).max(255);
2701
+ var revision = z7.number().int().positive();
2702
+ var status = z7.enum(["new", "read", "archived", "spam"]);
2703
+ var purpose = z7.enum(["regular", "test"]);
2704
+ var filters = z7.object({
2705
+ q: z7.string().max(200).optional(),
2706
+ formId: id.optional(),
2707
+ status: z7.enum(["allowed", "blocked", "all"]).optional(),
2708
+ source: z7.enum(["regular", "test", "spam", "all"]).optional(),
2709
+ from: z7.string().datetime().optional(),
2710
+ to: z7.string().datetime().optional(),
2711
+ offset: z7.coerce.number().int().min(0).max(1e5).optional()
2712
+ }).strict().refine((v) => !v.from || !v.to || v.from < v.to);
2713
+ var changes = z7.object({
2714
+ changes: z7.array(
2715
+ z7.object({
2716
+ id,
2717
+ formId: id,
2718
+ expectedStatus: status,
2719
+ expectedPurpose: purpose,
2720
+ status: status.optional(),
2721
+ purpose: purpose.optional()
2722
+ }).strict().refine(
2723
+ (v) => v.status !== void 0 !== (v.purpose !== void 0)
2724
+ )
2725
+ ).min(1).max(100)
2726
+ }).strict().refine((v) => new Set(v.changes.map((c) => c.id)).size === v.changes.length);
2727
+ var inputs = {
2728
+ edit: z7.object({
2729
+ expectedRevision: revision,
2730
+ email: z7.string().email().max(254),
2731
+ name: z7.string().max(255),
2732
+ notes: z7.string().max(4e3)
2733
+ }).strict(),
2734
+ block: z7.object({
2735
+ expectedRevision: revision,
2736
+ blocked: z7.boolean(),
2737
+ reason: z7.string().max(500).optional()
2738
+ }).strict(),
2739
+ merge: z7.object({
2740
+ expectedRevision: revision,
2741
+ targetId: id,
2742
+ targetRevision: revision
2743
+ }).strict(),
2744
+ "mapping-set": z7.object({
2745
+ formId: id,
2746
+ expectedRevision: revision.min(0),
2747
+ emailField: id.nullable(),
2748
+ nameField: id.nullable()
2749
+ }).strict(),
2750
+ "protection-set": z7.object({ enabled: z7.boolean(), expectedRevision: revision.min(0) }).strict(),
2751
+ export: z7.object({
2752
+ filters,
2753
+ ids: z7.array(id).min(1).max(5e3).optional(),
2754
+ format: z7.enum(["csv", "xlsx"]),
2755
+ columns: z7.array(
2756
+ z7.enum([
2757
+ "email",
2758
+ "name",
2759
+ "forms",
2760
+ "submissions",
2761
+ "firstSubmittedAt",
2762
+ "lastSubmittedAt",
2763
+ "status",
2764
+ "notes"
2765
+ ])
2766
+ ).min(1).max(8).refine((v) => new Set(v).size === v.length)
2767
+ }).strict(),
2768
+ bulk: changes
2769
+ };
2770
+ var contact = z7.object({
2771
+ id,
2772
+ email: z7.string(),
2773
+ name: z7.string(),
2774
+ revision,
2775
+ blocked: z7.boolean()
2776
+ }).passthrough();
2777
+ var contactFilters = [
2778
+ "query",
2779
+ "form",
2780
+ "status",
2781
+ "source",
2782
+ "from",
2783
+ "to",
2784
+ "offset"
2785
+ ];
2786
+ var submissionFilters = [
2787
+ "form",
2788
+ "query",
2789
+ "status",
2790
+ "purpose",
2791
+ "from",
2792
+ "to",
2793
+ "version"
2794
+ ];
2795
+ var routes = {
2796
+ "contacts list": {
2797
+ flags: contactFilters,
2798
+ method: "GET",
2799
+ suffix: "",
2800
+ scope: "read"
2801
+ },
2802
+ "contacts read": {
2803
+ flags: ["contact", "offset"],
2804
+ method: "GET",
2805
+ suffix: "",
2806
+ scope: "read"
2807
+ },
2808
+ "contacts edit": {
2809
+ flags: ["contact", "input"],
2810
+ method: "PATCH",
2811
+ suffix: "",
2812
+ scope: "write"
2813
+ },
2814
+ "contacts block": {
2815
+ flags: ["contact", "input"],
2816
+ method: "POST",
2817
+ suffix: "/block",
2818
+ scope: "write"
2819
+ },
2820
+ "contacts merge": {
2821
+ flags: ["contact", "input"],
2822
+ method: "POST",
2823
+ suffix: "/merge",
2824
+ scope: "write"
2825
+ },
2826
+ "contacts import": {
2827
+ flags: [],
2828
+ method: "POST",
2829
+ suffix: "/index",
2830
+ scope: "write"
2831
+ },
2832
+ "contacts mappings": {
2833
+ flags: [],
2834
+ method: "GET",
2835
+ suffix: "/mappings",
2836
+ scope: "read"
2837
+ },
2838
+ "contacts mapping-set": {
2839
+ flags: ["input"],
2840
+ method: "PATCH",
2841
+ suffix: "/mappings",
2842
+ scope: "write"
2843
+ },
2844
+ "contacts protection": {
2845
+ flags: [],
2846
+ method: "GET",
2847
+ suffix: "/protection",
2848
+ scope: "read"
2849
+ },
2850
+ "contacts protection-set": {
2851
+ flags: ["input"],
2852
+ method: "PATCH",
2853
+ suffix: "/protection",
2854
+ scope: "write"
2855
+ },
2856
+ "contacts export": {
2857
+ flags: ["input", "output"],
2858
+ method: "POST",
2859
+ suffix: "/export",
2860
+ scope: "export"
2861
+ },
2862
+ "submissions bulk": {
2863
+ flags: ["input"],
2864
+ method: "POST",
2865
+ suffix: "/bulk",
2866
+ scope: "workspace:write"
2867
+ },
2868
+ "submissions export": {
2869
+ flags: [...submissionFilters, "output"],
2870
+ method: "GET",
2871
+ suffix: "/export",
2872
+ scope: "workspace:write"
2873
+ }
2874
+ };
2875
+ var FORMS_WORKSPACE_HELP = ` siteos forms contacts list [--query <text>] [--form <id>] [--status <allowed|blocked|all>] [--source <regular|test|spam|all>] [--from <ISO>] [--to <ISO>] [--offset <number>] [--environment <slug>] [--json]
2876
+ siteos forms contacts read --contact <id> [--offset <number>] [--environment <slug>] [--json]
2877
+ siteos forms contacts edit --contact <id> --input <json-file> [--environment <slug>] [--json]
2878
+ siteos forms contacts block --contact <id> --input <json-file> [--environment <slug>] [--json]
2879
+ siteos forms contacts merge --contact <id> --input <json-file> [--environment <slug>] [--json]
2880
+ siteos forms contacts import [--environment <slug>] [--json]
2881
+ siteos forms contacts mappings [--environment <slug>] [--json]
2882
+ siteos forms contacts mapping-set --input <json-file> [--environment <slug>] [--json]
2883
+ siteos forms contacts protection [--environment <slug>] [--json]
2884
+ siteos forms contacts protection-set --input <json-file> [--environment <slug>] [--json]
2885
+ siteos forms contacts export --input <json-file> --output <new-file> [--environment <slug>] [--json]
2886
+ siteos forms submissions bulk --input <json-file> [--environment <slug>] [--json]
2887
+ siteos forms submissions export --output <new-file> [--form <id>] [--query <text>] [--status <new|read|archived|spam|inbox>] [--purpose <regular|test|all>] [--from <ISO>] [--to <ISO>] [--version <id>] [--environment <slug>] [--json]
2888
+
2889
+ Contacts reads, writes and exports use separate grants. Writes require owner/admin.
2890
+ Import indexes one bounded batch of earlier submissions; inspect remaining before repeating.
2891
+ Block input: {"expectedRevision":1,"blocked":true,"reason":"Unwanted submissions"}; false unblocks.
2892
+ Protection input: {"expectedRevision":0,"enabled":true}. Enabling blocks disposable domains.
2893
+ Edit/merge/mapping input uses current revisions; reread conflicts before changing the request.
2894
+ Export input: {"filters":{"status":"all","source":"regular"},"format":"csv","columns":["email","name"]}.
2895
+ Bulk input: {"changes":[{"id":"submission-id","formId":"form-id","expectedStatus":"new","expectedPurpose":"regular","status":"archived"}]}.
2896
+ Each bulk item changes either status or purpose (regular/test). Results may contain conflicts.
2897
+ Export uses all matching records (up to 5000), never overwrites files, and does not grant marketing consent.`;
2898
+ async function runFormsWorkspaceCommand(options) {
2899
+ const json = options.args.includes("--json");
2900
+ try {
2901
+ const route = routes[options.args.slice(0, 2).join(" ")];
2902
+ if (!route)
2903
+ throw new Error(
2904
+ "Unknown Forms workspace command. Run siteos forms --help."
2905
+ );
2906
+ const { positionals, values } = parseArgs({
2907
+ args: options.args.slice(2),
2908
+ strict: true,
2909
+ allowPositionals: true,
2910
+ options: {
2911
+ ...Object.fromEntries(
2912
+ ["environment", ...route.flags].map((key) => [
2913
+ key,
2914
+ { type: "string" }
2915
+ ])
2916
+ ),
2917
+ json: { type: "boolean" }
2918
+ }
2919
+ });
2920
+ if (positionals.length) throw new Error("Unexpected positional arguments.");
2921
+ const flags = values;
2922
+ const value = (key) => typeof flags[key] === "string" ? flags[key] : void 0;
2923
+ const action = options.args[1];
2924
+ const contacts = options.args[0] === "contacts";
2925
+ const selectedId = route.flags.includes("contact") ? id.parse(value("contact")) : void 0;
2926
+ const query = new URLSearchParams();
2927
+ if (contacts && action === "list") {
2928
+ const f = filters.parse({
2929
+ ...Object.fromEntries(
2930
+ contactFilters.filter((key) => value(key) !== void 0).map((key) => [
2931
+ key === "query" ? "q" : key === "form" ? "formId" : key,
2932
+ value(key)
2933
+ ])
2934
+ )
2935
+ });
2936
+ for (const [key, v] of Object.entries(f)) query.set(key, String(v));
2937
+ } else if (contacts && action === "read")
2938
+ query.set(
2939
+ "offset",
2940
+ String(
2941
+ z7.coerce.number().int().min(0).max(1e5).parse(value("offset") ?? 0)
2942
+ )
2943
+ );
2944
+ else if (!contacts && action === "export") {
2945
+ for (const key of submissionFilters)
2946
+ if (value(key) !== void 0)
2947
+ query.set(
2948
+ key === "form" ? "formId" : key === "version" ? "versionId" : key,
2949
+ value(key)
2950
+ );
2951
+ if (query.get("purpose") === "all") query.delete("purpose");
2952
+ z7.object({
2953
+ formId: id.optional(),
2954
+ query: z7.string().max(200).optional(),
2955
+ status: z7.enum(["new", "read", "archived", "spam", "inbox"]).optional(),
2956
+ purpose: purpose.optional(),
2957
+ from: z7.string().datetime({ offset: true }).optional(),
2958
+ to: z7.string().datetime({ offset: true }).optional(),
2959
+ versionId: id.optional()
2960
+ }).strict().refine(
2961
+ (v) => !v.from || !v.to || Date.parse(v.from) < Date.parse(v.to)
2962
+ ).parse(Object.fromEntries(query));
2963
+ }
2964
+ let body;
2965
+ if (route.flags.includes("input")) {
2966
+ const file = value("input");
2967
+ if (!file)
2968
+ throw new Error("Provide --input with the reviewed JSON request.");
2969
+ const raw = await readFile4(
2970
+ path9.resolve(options.cwd ?? process.cwd(), file),
2971
+ "utf8"
2972
+ );
2973
+ if (Buffer.byteLength(raw) > 1024 * 1024)
2974
+ throw new Error("Input exceeds 1 MiB.");
2975
+ body = inputs[action].parse(JSON.parse(raw));
2976
+ }
2977
+ const output = route.flags.includes("output") ? value("output") : void 0;
2978
+ if (route.flags.includes("output") && !output)
2979
+ throw new Error("Provide --output with a new file path.");
2980
+ const context = await commonServiceContext(
2981
+ options,
2982
+ "forms",
2983
+ value("environment")
2984
+ );
2985
+ if (!context?.environmentBinding)
2986
+ throw new Error(
2987
+ "Select a Project and connect Forms in the intended environment."
2988
+ );
2989
+ const scope = contacts ? `forms:contacts:${route.scope}` : "forms:workspace:write";
2990
+ const grant = await commonProjectRuntime(options).grants.acquire({
2991
+ audience: "siteos-forms",
2992
+ scopes: [scope]
2993
+ });
2994
+ if (grant.grant.organizationId !== context.overview.project.organizationId || grant.grant.audience !== "siteos-forms" || !grant.grant.scopes.includes(scope))
2995
+ throw new Error(
2996
+ "The Forms grant does not match the selected Organization or required scope."
2997
+ );
2998
+ if (!options.fetchImpl)
2999
+ throw new Error("SiteOS API access is unavailable.");
3000
+ const url = new URL(
3001
+ `/api/v1/forms/environments/${encodeURIComponent(context.environmentBinding.resourceId)}/${contacts ? "contacts" : "submissions"}${selectedId ? `/${encodeURIComponent(selectedId)}` : ""}${route.suffix}`,
3002
+ context.api.origin
3003
+ );
3004
+ url.search = query.toString();
3005
+ const response = await options.fetchImpl(url.href, {
3006
+ method: route.method,
3007
+ headers: {
3008
+ Authorization: `Bearer ${grant.accessToken}`,
3009
+ ...body === void 0 ? {} : { "Content-Type": "application/json" }
3010
+ },
3011
+ ...body === void 0 ? {} : { body: JSON.stringify(body) },
3012
+ signal: AbortSignal.timeout(3e4)
3013
+ });
3014
+ if (!response.ok) {
3015
+ const data2 = await response.json().catch(() => null);
3016
+ throw new Error(
3017
+ `${data2?.error?.code ?? response.status}: ${data2?.error?.message ?? "Forms request failed. Reread current data before retrying a mutation."}`
3018
+ );
3019
+ }
3020
+ if (output) {
3021
+ if (!(response instanceof Response))
3022
+ throw new Error("Export requires a streaming HTTP response.");
3023
+ const contentType = response.headers.get("Content-Type") ?? "";
3024
+ const expectedType = contacts && body.format === "xlsx" ? "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" : "text/csv";
3025
+ if (!contentType.startsWith(expectedType))
3026
+ throw new Error("Unexpected export format.");
3027
+ const reader = response.body?.getReader();
3028
+ if (!reader) throw new Error("Missing export body.");
3029
+ const chunks = [];
3030
+ let size = 0;
3031
+ try {
3032
+ for (; ; ) {
3033
+ const chunk = await reader.read();
3034
+ if (chunk.done) break;
3035
+ size += chunk.value.byteLength;
3036
+ if (size > 25 * 1024 * 1024)
3037
+ throw new Error("Export exceeds 25 MiB.");
3038
+ chunks.push(chunk.value);
3039
+ }
3040
+ } finally {
3041
+ await reader.cancel();
3042
+ }
3043
+ const file = path9.resolve(options.cwd ?? process.cwd(), output);
3044
+ await writeFile4(file, Buffer.concat(chunks), { flag: "wx", mode: 384 });
3045
+ return {
3046
+ exitCode: 0,
3047
+ stdout: JSON.stringify({
3048
+ output: file,
3049
+ bytes: size,
3050
+ environment: context.environment.slug
3051
+ })
3052
+ };
3053
+ }
3054
+ const rawData = await response.json();
3055
+ const data = z7.record(z7.unknown()).parse(
3056
+ action === "mappings" ? {
3057
+ mappings: z7.array(
3058
+ z7.object({
3059
+ formId: id,
3060
+ revision: revision.min(0),
3061
+ emailField: z7.string().nullable(),
3062
+ nameField: z7.string().nullable()
3063
+ })
3064
+ ).parse(rawData)
3065
+ } : rawData
3066
+ );
3067
+ if (contacts && action === "list")
3068
+ z7.object({
3069
+ contacts: z7.array(contact),
3070
+ total: z7.number().int().nonnegative(),
3071
+ nextOffset: z7.number().nullable()
3072
+ }).parse(data);
3073
+ if (contacts && action === "read")
3074
+ z7.object({
3075
+ contact,
3076
+ history: z7.array(z7.unknown()),
3077
+ nextOffset: z7.number().nullable()
3078
+ }).parse(data);
3079
+ if (["edit", "block", "mapping-set", "protection-set"].includes(action))
3080
+ z7.object({ success: z7.literal(true) }).parse(data);
3081
+ if (action === "merge") z7.object({ id }).parse(data);
3082
+ if (action === "import")
3083
+ z7.object({
3084
+ processed: z7.number().int().nonnegative(),
3085
+ linked: z7.number().int().nonnegative(),
3086
+ skipped: z7.number().int().nonnegative(),
3087
+ remaining: z7.number().int().nonnegative()
3088
+ }).parse(data);
3089
+ if (action === "protection")
3090
+ z7.object({
3091
+ enabled: z7.boolean(),
3092
+ revision: revision.min(0),
3093
+ domainCount: z7.number().int().nonnegative()
3094
+ }).parse(data);
3095
+ if (action === "read")
3096
+ z7.literal(selectedId).parse(data.contact.id);
3097
+ if (action === "bulk") {
3098
+ const result = z7.object({
3099
+ results: z7.array(
3100
+ z7.object({
3101
+ id,
3102
+ formId: id,
3103
+ outcome: z7.enum(["updated", "conflict", "not_found"])
3104
+ })
3105
+ )
3106
+ }).parse(data);
3107
+ const expected = body.changes;
3108
+ if (result.results.length !== expected.length || new Set(result.results.map((r) => r.id)).size !== expected.length || result.results.some(
3109
+ (r) => !expected.some((c) => c.id === r.id && c.formId === r.formId)
3110
+ ))
3111
+ throw new Error(
3112
+ "Bulk response does not match the requested submissions. Reread before retrying."
3113
+ );
3114
+ return {
3115
+ exitCode: result.results.every((r) => r.outcome === "updated") ? 0 : 1,
3116
+ stdout: JSON.stringify(data, null, 2)
3117
+ };
3118
+ }
3119
+ return { exitCode: 0, stdout: JSON.stringify(data, null, 2) };
3120
+ } catch (cause) {
3121
+ const message = cause instanceof z7.ZodError ? "Invalid Forms input. Check the documented fields, filters and revisions." : cause instanceof Error ? cause.message : "Forms request failed.";
3122
+ return {
3123
+ exitCode: 2,
3124
+ ...json ? { stdout: JSON.stringify({ error: { message } }) } : { stderr: message }
3125
+ };
3126
+ }
3127
+ }
3128
+
2695
3129
  // src/forms-command.ts
2696
- import { readFile as readFile5 } from "fs/promises";
2697
- import path10 from "path";
3130
+ import { readFile as readFile6 } from "fs/promises";
3131
+ import path11 from "path";
2698
3132
  import { Ajv } from "ajv";
2699
3133
  import addFormats from "ajv-formats";
2700
- import { z as z8 } from "zod";
3134
+ import { z as z9 } from "zod";
2701
3135
 
2702
3136
  // src/siteos-forms-api.ts
2703
- import { z as z7 } from "zod";
2704
- var opaqueIdentifierSchema = z7.string().trim().min(1).max(255);
2705
- var formsEnvironmentSchema = z7.object({
2706
- createdAt: z7.string().datetime({ offset: true }),
3137
+ import { z as z8 } from "zod";
3138
+ var opaqueIdentifierSchema = z8.string().trim().min(1).max(255);
3139
+ var formsEnvironmentSchema = z8.object({
3140
+ createdAt: z8.string().datetime({ offset: true }),
2707
3141
  id: opaqueIdentifierSchema,
2708
- name: z7.string().trim().min(1).max(255),
3142
+ name: z8.string().trim().min(1).max(255),
2709
3143
  projectId: opaqueIdentifierSchema,
2710
- slug: z7.string().trim().min(1).max(120).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
2711
- updatedAt: z7.string().datetime({ offset: true })
3144
+ slug: z8.string().trim().min(1).max(120).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
3145
+ updatedAt: z8.string().datetime({ offset: true })
2712
3146
  }).strict();
2713
- var formsEnvironmentListSchema = z7.object({ environments: z7.array(formsEnvironmentSchema) }).strict();
2714
- var formDefinitionSyncResponseSchema = z7.object({
3147
+ var formsEnvironmentListSchema = z8.object({ environments: z8.array(formsEnvironmentSchema) }).strict();
3148
+ var formDefinitionSyncResponseSchema = z8.object({
2715
3149
  activeVersionId: opaqueIdentifierSchema,
2716
- createdForm: z7.boolean(),
2717
- createdVersion: z7.boolean(),
3150
+ createdForm: z8.boolean(),
3151
+ createdVersion: z8.boolean(),
2718
3152
  formId: opaqueIdentifierSchema,
2719
3153
  formKey: opaqueIdentifierSchema,
2720
- success: z7.literal(true),
2721
- version: z7.number().int().positive()
3154
+ success: z8.literal(true),
3155
+ version: z8.number().int().positive()
2722
3156
  }).strict();
2723
- var definitionSchema = z7.object({
3157
+ var definitionSchema = z8.object({
2724
3158
  id: opaqueIdentifierSchema,
2725
3159
  environmentId: opaqueIdentifierSchema,
2726
3160
  formKey: opaqueIdentifierSchema,
2727
- name: z7.string(),
2728
- sourcePagePath: z7.string().nullable(),
2729
- activeVersion: z7.number().int().positive(),
3161
+ name: z8.string(),
3162
+ sourcePagePath: z8.string().nullable(),
3163
+ activeVersion: z8.number().int().positive(),
2730
3164
  activeVersionId: opaqueIdentifierSchema,
2731
- status: z7.enum(["active", "inactive"]),
2732
- submissionCount: z7.number().int().nonnegative(),
2733
- lastSubmittedAt: z7.string().datetime({ offset: true }).nullable(),
2734
- createdAt: z7.string().datetime({ offset: true }),
2735
- updatedAt: z7.string().datetime({ offset: true })
3165
+ status: z8.enum(["active", "inactive"]),
3166
+ submissionCount: z8.number().int().nonnegative(),
3167
+ unreadCount: z8.number().int().nonnegative().optional(),
3168
+ lastSubmittedAt: z8.string().datetime({ offset: true }).nullable(),
3169
+ createdAt: z8.string().datetime({ offset: true }),
3170
+ updatedAt: z8.string().datetime({ offset: true })
2736
3171
  });
2737
- var definitionListSchema = z7.object({
2738
- definitions: z7.array(definitionSchema)
3172
+ var definitionListSchema = z8.object({
3173
+ definitions: z8.array(definitionSchema)
2739
3174
  });
2740
- var definitionContextSchema = z7.object({
3175
+ var definitionContextSchema = z8.object({
2741
3176
  definition: definitionSchema,
2742
- revision: z7.number().int().positive(),
2743
- canManage: z7.boolean(),
2744
- project: z7.object({ id: opaqueIdentifierSchema, name: z7.string() }),
2745
- environment: z7.object({
3177
+ revision: z8.number().int().positive(),
3178
+ canManage: z8.boolean(),
3179
+ project: z8.object({ id: opaqueIdentifierSchema, name: z8.string() }),
3180
+ environment: z8.object({
2746
3181
  id: opaqueIdentifierSchema,
2747
- name: z7.string(),
2748
- slug: z7.string()
3182
+ name: z8.string(),
3183
+ slug: z8.string()
2749
3184
  })
2750
3185
  });
2751
- var definitionChangeResponseSchema = z7.object({
2752
- deleted: z7.boolean(),
3186
+ var definitionChangeResponseSchema = z8.object({
3187
+ deleted: z8.boolean(),
2753
3188
  formId: opaqueIdentifierSchema
2754
3189
  });
2755
- var formSubmissionResponseSchema = z7.object({
3190
+ var formSubmissionResponseSchema = z8.object({
2756
3191
  formId: opaqueIdentifierSchema,
2757
- receivedAt: z7.string().datetime({ offset: true }),
3192
+ receivedAt: z8.string().datetime({ offset: true }),
2758
3193
  submissionId: opaqueIdentifierSchema,
2759
- success: z7.literal(true)
3194
+ success: z8.literal(true)
2760
3195
  }).strict();
2761
- var formsSubmissionStatusSchema = z7.enum([
3196
+ var formsSubmissionStatusSchema = z8.enum([
2762
3197
  "new",
2763
3198
  "read",
2764
3199
  "archived",
2765
3200
  "spam"
2766
3201
  ]);
2767
- var submissionSummarySchema = z7.object({
3202
+ var submissionSummarySchema = z8.object({
2768
3203
  id: opaqueIdentifierSchema,
2769
3204
  formId: opaqueIdentifierSchema,
2770
- normalized: z7.record(
2771
- z7.union([z7.string(), z7.number(), z7.boolean(), z7.null()])
3205
+ normalized: z8.record(
3206
+ z8.union([z8.string(), z8.number(), z8.boolean(), z8.null()])
2772
3207
  ),
2773
3208
  status: formsSubmissionStatusSchema,
2774
- submittedAt: z7.string().datetime({ offset: true })
3209
+ purpose: z8.enum(["regular", "test"]).optional(),
3210
+ formName: z8.string().optional(),
3211
+ formKey: z8.string().optional(),
3212
+ submittedAt: z8.string().datetime({ offset: true })
2775
3213
  });
2776
3214
  var submissionDetailSchema = submissionSummarySchema.extend({
2777
- payload: z7.record(z7.unknown()),
2778
- fields: z7.array(
2779
- z7.object({
2780
- key: z7.string(),
2781
- label: z7.string().optional(),
2782
- kind: z7.string().optional(),
2783
- displayRole: z7.enum(["primary", "secondary"]).optional(),
2784
- multiple: z7.boolean().optional(),
2785
- options: z7.array(z7.object({ value: z7.string(), label: z7.string() })).optional()
3215
+ sourceUrl: z8.string().nullable().optional(),
3216
+ payload: z8.record(z8.unknown()),
3217
+ fields: z8.array(
3218
+ z8.object({
3219
+ key: z8.string(),
3220
+ label: z8.string().optional(),
3221
+ kind: z8.string().optional(),
3222
+ displayRole: z8.enum(["primary", "secondary"]).optional(),
3223
+ multiple: z8.boolean().optional(),
3224
+ options: z8.array(z8.object({ value: z8.string(), label: z8.string() })).optional()
2786
3225
  })
2787
3226
  ),
2788
- version: z7.number().int().positive(),
3227
+ version: z8.number().int().positive(),
2789
3228
  versionId: opaqueIdentifierSchema
2790
3229
  });
2791
- var submissionPageSchema = z7.object({
2792
- submissions: z7.array(submissionSummarySchema),
2793
- total: z7.number().int().nonnegative(),
2794
- nextCursor: z7.string().nullable()
3230
+ var submissionPageSchema = z8.object({
3231
+ submissions: z8.array(submissionSummarySchema),
3232
+ total: z8.number().int().nonnegative(),
3233
+ nextCursor: z8.string().nullable(),
3234
+ counts: z8.object({
3235
+ inbox: z8.number().int().nonnegative(),
3236
+ archived: z8.number().int().nonnegative(),
3237
+ spam: z8.number().int().nonnegative(),
3238
+ all: z8.number().int().nonnegative()
3239
+ }).optional()
2795
3240
  });
2796
- var submissionDetailResponseSchema = z7.object({
3241
+ var submissionDetailResponseSchema = z8.object({
2797
3242
  submission: submissionDetailSchema
2798
3243
  });
2799
- var formsCredentialMetadataSchema = z7.object({
2800
- createdAt: z7.string().datetime({ offset: true }),
2801
- id: z7.string().trim().min(1).max(255),
2802
- lastUsedAt: z7.string().datetime({ offset: true }).nullable(),
2803
- name: z7.string().trim().min(1).max(255),
2804
- projectEnvironmentId: z7.string().trim().min(1).max(255),
2805
- revokedAt: z7.string().datetime({ offset: true }).nullable(),
2806
- status: z7.enum(["active", "revoked"])
3244
+ var formsCredentialMetadataSchema = z8.object({
3245
+ createdAt: z8.string().datetime({ offset: true }),
3246
+ id: z8.string().trim().min(1).max(255),
3247
+ lastUsedAt: z8.string().datetime({ offset: true }).nullable(),
3248
+ name: z8.string().trim().min(1).max(255),
3249
+ projectEnvironmentId: z8.string().trim().min(1).max(255),
3250
+ revokedAt: z8.string().datetime({ offset: true }).nullable(),
3251
+ status: z8.enum(["active", "revoked"])
2807
3252
  }).strict();
2808
- var formsCredentialListSchema = z7.object({
2809
- tokens: z7.array(formsCredentialMetadataSchema)
3253
+ var formsCredentialListSchema = z8.object({
3254
+ tokens: z8.array(formsCredentialMetadataSchema)
2810
3255
  }).strict();
2811
3256
  var formsCredentialExchangeSchema = formsCredentialMetadataSchema.extend({
2812
- token: z7.string().regex(/^pfs_[A-Za-z0-9_-]{22}$/)
3257
+ token: z8.string().regex(/^pfs_[A-Za-z0-9_-]{22}$/)
2813
3258
  });
2814
- var formsErrorCodeSchema = z7.enum([
3259
+ var formsErrorCodeSchema = z8.enum([
2815
3260
  "AUTHENTICATION_REQUIRED",
2816
3261
  "FORBIDDEN",
2817
3262
  "CONFLICT",
@@ -2859,10 +3304,10 @@ var safeFormsErrorMessages = {
2859
3304
  SERVICE_UNAVAILABLE: "The Forms service is unavailable.",
2860
3305
  INTERNAL_ERROR: "The Forms request could not be completed."
2861
3306
  };
2862
- var apiErrorResponseSchema = z7.object({
2863
- error: z7.object({
3307
+ var apiErrorResponseSchema = z8.object({
3308
+ error: z8.object({
2864
3309
  code: formsErrorCodeSchema,
2865
- message: z7.string().trim().min(1).max(240)
3310
+ message: z8.string().trim().min(1).max(240)
2866
3311
  }).strict()
2867
3312
  }).strict();
2868
3313
  var SiteOSFormsApiError = class extends Error {
@@ -2875,15 +3320,15 @@ var SiteOSFormsApiError = class extends Error {
2875
3320
  this.status = options.status;
2876
3321
  }
2877
3322
  };
2878
- var deploymentResponseSchema = z7.object({
3323
+ var deploymentResponseSchema = z8.object({
2879
3324
  environmentId: opaqueIdentifierSchema,
2880
- forms: z7.array(
2881
- z7.object({
3325
+ forms: z8.array(
3326
+ z8.object({
2882
3327
  formKey: opaqueIdentifierSchema,
2883
3328
  formId: opaqueIdentifierSchema,
2884
- contractVersion: z7.string().regex(/^sha256:[a-f0-9]{64}$/),
3329
+ contractVersion: z8.string().regex(/^sha256:[a-f0-9]{64}$/),
2885
3330
  versionId: opaqueIdentifierSchema,
2886
- version: z7.number().int().positive()
3331
+ version: z8.number().int().positive()
2887
3332
  })
2888
3333
  )
2889
3334
  });
@@ -2932,7 +3377,7 @@ function createSiteOSFormsApiClient(options) {
2932
3377
  fetchImpl: options.fetchImpl,
2933
3378
  headers: managementHeaders(input),
2934
3379
  method: "GET",
2935
- path: `${inboxPath(input)}?${input.filters}`,
3380
+ path: `${input.formId ? inboxPath({ ...input, formId: input.formId }) : `/api/v1/forms/environments/${encodeURIComponent(input.environmentId)}/submissions`}?${input.filters}`,
2936
3381
  responseSchema: submissionPageSchema
2937
3382
  }),
2938
3383
  readSubmission: (input) => requestJson2({
@@ -2960,7 +3405,7 @@ function createSiteOSFormsApiClient(options) {
2960
3405
  method: "POST",
2961
3406
  path: keyCollection(input),
2962
3407
  responseSchema: options.deploymentKeys ? formsCredentialExchangeSchema.extend({
2963
- token: z7.string().regex(/^pfd_[A-Za-z0-9_-]{43}$/)
3408
+ token: z8.string().regex(/^pfd_[A-Za-z0-9_-]{43}$/)
2964
3409
  }) : formsCredentialExchangeSchema
2965
3410
  }),
2966
3411
  listEnvironments: (input) => requestJson2({
@@ -2995,7 +3440,7 @@ function createSiteOSFormsApiClient(options) {
2995
3440
  method: "POST",
2996
3441
  path: credentialRotatePath(input),
2997
3442
  responseSchema: options.deploymentKeys ? formsCredentialExchangeSchema.extend({
2998
- token: z7.string().regex(/^pfd_[A-Za-z0-9_-]{43}$/)
3443
+ token: z8.string().regex(/^pfd_[A-Za-z0-9_-]{43}$/)
2999
3444
  }) : formsCredentialExchangeSchema
3000
3445
  }),
3001
3446
  submitForm: (input) => requestJson2({
@@ -3118,12 +3563,12 @@ import { randomUUID as randomUUID3 } from "crypto";
3118
3563
  import {
3119
3564
  chmod as chmod3,
3120
3565
  lstat as lstat4,
3121
- readFile as readFile4,
3566
+ readFile as readFile5,
3122
3567
  rename as rename4,
3123
3568
  rm as rm3,
3124
- writeFile as writeFile4
3569
+ writeFile as writeFile5
3125
3570
  } from "fs/promises";
3126
- import path9 from "path";
3571
+ import path10 from "path";
3127
3572
  var SITEOS_FORMS_SUBMISSION_CREDENTIAL_ENV = "SITEOS_FORMS_SUBMISSION_CREDENTIAL";
3128
3573
  var SITEOS_FORMS_DEPLOYMENT_KEY_ENV = "SITEOS_FORMS_DEPLOYMENT_KEY";
3129
3574
  var SiteOSFormsCredentialStorageError = class extends Error {
@@ -3139,8 +3584,8 @@ var SiteOSFormsCredentialStorageError = class extends Error {
3139
3584
  async function prepareSiteOSFormsCredentialInstallation(options) {
3140
3585
  const variable = options.deployment ? SITEOS_FORMS_DEPLOYMENT_KEY_ENV : SITEOS_FORMS_SUBMISSION_CREDENTIAL_ENV;
3141
3586
  const credentialPattern = options.deployment ? /^pfd_[A-Za-z0-9_-]{43}$/ : /^pfs_[A-Za-z0-9_-]{22}$/;
3142
- const projectRoot = path9.resolve(options.projectRoot);
3143
- const dotenvPath = path9.join(projectRoot, ".env");
3587
+ const projectRoot = path10.resolve(options.projectRoot);
3588
+ const dotenvPath = path10.join(projectRoot, ".env");
3144
3589
  try {
3145
3590
  await assertSafeProjectRoot(projectRoot);
3146
3591
  if (!await isDotenvIgnored(projectRoot)) {
@@ -3202,7 +3647,7 @@ async function readSafeDotenv(dotenvPath) {
3202
3647
  "FORMS_CREDENTIAL_STORAGE_INVALID"
3203
3648
  );
3204
3649
  }
3205
- const content = dotenvStats ? await readFile4(dotenvPath, "utf8") : "";
3650
+ const content = dotenvStats ? await readFile5(dotenvPath, "utf8") : "";
3206
3651
  if ([
3207
3652
  SITEOS_FORMS_SUBMISSION_CREDENTIAL_ENV,
3208
3653
  SITEOS_FORMS_DEPLOYMENT_KEY_ENV
@@ -3214,12 +3659,12 @@ async function readSafeDotenv(dotenvPath) {
3214
3659
  return content;
3215
3660
  }
3216
3661
  async function writeCredentialAtomically(options) {
3217
- const temporaryPath = path9.join(
3662
+ const temporaryPath = path10.join(
3218
3663
  options.projectRoot,
3219
3664
  `.siteos-forms-credential.${process.pid}.${randomUUID3()}.tmp`
3220
3665
  );
3221
3666
  try {
3222
- await writeFile4(temporaryPath, options.content, {
3667
+ await writeFile5(temporaryPath, options.content, {
3223
3668
  encoding: "utf8",
3224
3669
  flag: "wx",
3225
3670
  mode: 384
@@ -3276,25 +3721,25 @@ var ENVIRONMENT_FLAG = "--environment";
3276
3721
  var INSTALL_FLAG = "--install";
3277
3722
  var NAME_FLAG = "--name";
3278
3723
  var CREDENTIAL_FLAG = "--credential";
3279
- var normalizedFieldOptionSchema = z8.object({
3280
- label: z8.string().trim().min(1).max(255),
3281
- value: z8.string().trim().min(1).max(255)
3724
+ var normalizedFieldOptionSchema = z9.object({
3725
+ label: z9.string().trim().min(1).max(255),
3726
+ value: z9.string().trim().min(1).max(255)
3282
3727
  });
3283
- var normalizedFieldSchema = z8.object({
3284
- key: z8.string().trim().min(1).max(255),
3285
- kind: z8.string().trim().min(1).max(64).optional(),
3286
- label: z8.string().trim().min(1).max(255).optional(),
3287
- displayRole: z8.enum(["primary", "secondary"]).optional(),
3288
- multiple: z8.boolean().optional(),
3289
- options: z8.array(normalizedFieldOptionSchema).max(500).optional()
3728
+ var normalizedFieldSchema = z9.object({
3729
+ key: z9.string().trim().min(1).max(255),
3730
+ kind: z9.string().trim().min(1).max(64).optional(),
3731
+ label: z9.string().trim().min(1).max(255).optional(),
3732
+ displayRole: z9.enum(["primary", "secondary"]).optional(),
3733
+ multiple: z9.boolean().optional(),
3734
+ options: z9.array(normalizedFieldOptionSchema).max(500).optional()
3290
3735
  }).strict();
3291
- var definitionSyncInputSchema = z8.object({
3292
- formKey: z8.string().trim().min(1).max(255),
3293
- name: z8.string().trim().min(1).max(255),
3294
- normalizedFieldsJson: z8.array(normalizedFieldSchema).min(1).max(500),
3295
- schemaJson: z8.record(z8.unknown()),
3296
- sourceExportId: z8.string().trim().min(1).max(255).optional(),
3297
- sourcePagePath: z8.string().trim().min(1).max(2048).optional()
3736
+ var definitionSyncInputSchema = z9.object({
3737
+ formKey: z9.string().trim().min(1).max(255),
3738
+ name: z9.string().trim().min(1).max(255),
3739
+ normalizedFieldsJson: z9.array(normalizedFieldSchema).min(1).max(500),
3740
+ schemaJson: z9.record(z9.unknown()),
3741
+ sourceExportId: z9.string().trim().min(1).max(255).optional(),
3742
+ sourcePagePath: z9.string().trim().min(1).max(2048).optional()
3298
3743
  }).strict().superRefine((definition, context) => {
3299
3744
  const ajv = new Ajv({
3300
3745
  allErrors: true,
@@ -3306,7 +3751,7 @@ var definitionSyncInputSchema = z8.object({
3306
3751
  ajv.compile(definition.schemaJson);
3307
3752
  } catch {
3308
3753
  context.addIssue({
3309
- code: z8.ZodIssueCode.custom,
3754
+ code: z9.ZodIssueCode.custom,
3310
3755
  message: "schemaJson must be an executable JSON Schema supported by SiteOS Forms.",
3311
3756
  path: ["schemaJson"]
3312
3757
  });
@@ -3315,7 +3760,7 @@ var definitionSyncInputSchema = z8.object({
3315
3760
  const duplicateKeys = fields.map((field) => field.key).filter((key, index, keys) => keys.indexOf(key) !== index);
3316
3761
  for (const key of new Set(duplicateKeys)) {
3317
3762
  context.addIssue({
3318
- code: z8.ZodIssueCode.custom,
3763
+ code: z9.ZodIssueCode.custom,
3319
3764
  message: `Field key "${key}" is registered more than once.`,
3320
3765
  path: ["normalizedFieldsJson"]
3321
3766
  });
@@ -3325,7 +3770,7 @@ var definitionSyncInputSchema = z8.object({
3325
3770
  );
3326
3771
  if (primaryFields.length !== 1) {
3327
3772
  context.addIssue({
3328
- code: z8.ZodIssueCode.custom,
3773
+ code: z9.ZodIssueCode.custom,
3329
3774
  message: "Exactly one managed field must use the primary display role.",
3330
3775
  path: ["normalizedFieldsJson"]
3331
3776
  });
@@ -3333,7 +3778,7 @@ var definitionSyncInputSchema = z8.object({
3333
3778
  const schemaProperties = definition.schemaJson.properties;
3334
3779
  if (!isRecord(schemaProperties)) {
3335
3780
  context.addIssue({
3336
- code: z8.ZodIssueCode.custom,
3781
+ code: z9.ZodIssueCode.custom,
3337
3782
  message: "schemaJson.properties must define the managed form fields.",
3338
3783
  path: ["schemaJson", "properties"]
3339
3784
  });
@@ -3343,7 +3788,7 @@ var definitionSyncInputSchema = z8.object({
3343
3788
  for (const key of Object.keys(schemaProperties)) {
3344
3789
  if (!metadataKeys.has(key)) {
3345
3790
  context.addIssue({
3346
- code: z8.ZodIssueCode.custom,
3791
+ code: z9.ZodIssueCode.custom,
3347
3792
  message: `Schema field "${key}" is missing managed field metadata.`,
3348
3793
  path: ["normalizedFieldsJson"]
3349
3794
  });
@@ -3352,7 +3797,7 @@ var definitionSyncInputSchema = z8.object({
3352
3797
  for (const [index, field] of fields.entries()) {
3353
3798
  if (!Object.prototype.hasOwnProperty.call(schemaProperties, field.key)) {
3354
3799
  context.addIssue({
3355
- code: z8.ZodIssueCode.custom,
3800
+ code: z9.ZodIssueCode.custom,
3356
3801
  message: `Managed field "${field.key}" is missing from schemaJson.properties.`,
3357
3802
  path: ["normalizedFieldsJson", index, "key"]
3358
3803
  });
@@ -3362,26 +3807,26 @@ var definitionSyncInputSchema = z8.object({
3362
3807
  const requiredFields = definition.schemaJson.required;
3363
3808
  if (primaryField && (!Array.isArray(requiredFields) || !requiredFields.includes(primaryField.key))) {
3364
3809
  context.addIssue({
3365
- code: z8.ZodIssueCode.custom,
3810
+ code: z9.ZodIssueCode.custom,
3366
3811
  message: `Primary display field "${primaryField.key}" must be required by schemaJson.`,
3367
3812
  path: ["schemaJson", "required"]
3368
3813
  });
3369
3814
  }
3370
3815
  });
3371
- var definitionManifestSchema = z8.object({
3372
- version: z8.literal(1),
3373
- forms: z8.array(z8.string().trim().min(1)).min(1)
3816
+ var definitionManifestSchema = z9.object({
3817
+ version: z9.literal(1),
3818
+ forms: z9.array(z9.string().trim().min(1)).min(1)
3374
3819
  });
3375
- var submitInputSchema = z8.object({
3376
- formKey: z8.string().trim().min(1),
3377
- idempotencyKey: z8.string().trim().min(1),
3378
- ipAddress: z8.string().trim().min(1).optional(),
3379
- payload: z8.record(z8.unknown()),
3380
- sourceUrl: z8.string().trim().min(1).optional(),
3381
- userAgent: z8.string().trim().min(1).optional()
3820
+ var submitInputSchema = z9.object({
3821
+ formKey: z9.string().trim().min(1),
3822
+ idempotencyKey: z9.string().trim().min(1),
3823
+ ipAddress: z9.string().trim().min(1).optional(),
3824
+ payload: z9.record(z9.unknown()),
3825
+ sourceUrl: z9.string().trim().min(1).optional(),
3826
+ userAgent: z9.string().trim().min(1).optional()
3382
3827
  }).passthrough();
3383
- var environmentNameSchema = z8.string().transform((value) => value.trim()).refine((value) => value.length >= 1 && value.length <= 255);
3384
- var projectSlugSchema = z8.string().trim().min(1).max(120).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/);
3828
+ var environmentNameSchema = z9.string().transform((value) => value.trim()).refine((value) => value.length >= 1 && value.length <= 255);
3829
+ var projectSlugSchema = z9.string().trim().min(1).max(120).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/);
3385
3830
  var FORMS_HELP = `Usage:
3386
3831
  siteos forms definition sync --environment <slug> --input <path> [--json]
3387
3832
  siteos forms definition sync --environment <slug> --manifest <path> [--json]
@@ -3396,7 +3841,7 @@ var FORMS_HELP = `Usage:
3396
3841
  siteos forms credential issue --environment <slug> --install [--name <name>] [--json]
3397
3842
  siteos forms credential rotate --environment <slug> --install [--name <name>] [--json]
3398
3843
  siteos forms credential revoke --environment <slug> --credential <credential-id> [--json]
3399
- siteos forms submissions list --environment <slug> --form <form-id> [--query <text>] [--status <status>] [--from <ISO>] [--to <ISO>] [--limit <1-100>] [--cursor <cursor>] [--json]
3844
+ siteos forms submissions list --environment <slug> [--form <form-id>] [--query <text>] [--status <new|read|archived|spam|inbox|all>] [--purpose <regular|test|all>] [--version <id>] [--from <ISO>] [--to <ISO>] [--limit <1-100>] [--cursor <cursor>] [--json]
3400
3845
  siteos forms submissions read --environment <slug> --form <form-id> --submission <id> [--json]
3401
3846
  siteos forms submissions status --environment <slug> --form <form-id> --submission <id> --status <new|read|archived|spam> --expected-status <status> [--json]
3402
3847
  siteos forms deploy --manifest <path> [--json]
@@ -3404,6 +3849,7 @@ var FORMS_HELP = `Usage:
3404
3849
  siteos forms deployment-key list --environment <slug> [--json]
3405
3850
  siteos forms deployment-key revoke --environment <slug> --credential <id> [--json]
3406
3851
  siteos forms submit --input <path> [--json]
3852
+ ${FORMS_WORKSPACE_HELP}
3407
3853
 
3408
3854
  Manage SiteOS Forms Environments, definitions, credentials, and submission smoke tests.`;
3409
3855
  async function runFormsCommand(options) {
@@ -3428,6 +3874,8 @@ async function runFormsCommand(options) {
3428
3874
  );
3429
3875
  if (args2[0] === "deploy")
3430
3876
  return runDeployment({ ...options, args: args2.slice(1) });
3877
+ if (args2[0] === "contacts" || args2[0] === "submissions" && ["bulk", "export"].includes(args2[1] ?? ""))
3878
+ return runFormsWorkspaceCommand({ ...options, args: args2 });
3431
3879
  if (args2[0] !== "submit") {
3432
3880
  try {
3433
3881
  args2 = await commonEnvironmentArguments(options, "forms", args2);
@@ -3478,7 +3926,16 @@ async function runSubmissionsCommand(options) {
3478
3926
  "--environment",
3479
3927
  "--form",
3480
3928
  "--json",
3481
- ...action === "list" ? ["--query", "--status", "--from", "--to", "--limit", "--cursor"] : [
3929
+ ...action === "list" ? [
3930
+ "--query",
3931
+ "--status",
3932
+ "--purpose",
3933
+ "--version",
3934
+ "--from",
3935
+ "--to",
3936
+ "--limit",
3937
+ "--cursor"
3938
+ ] : [
3482
3939
  "--submission",
3483
3940
  ...action === "status" ? ["--status", "--expected-status"] : []
3484
3941
  ]
@@ -3493,22 +3950,34 @@ async function runSubmissionsCommand(options) {
3493
3950
  const environmentSlug = value("environment");
3494
3951
  const formId = value("form");
3495
3952
  const submissionId = value("submission");
3496
- if (!environmentSlug || !isValidEnvironmentSlug(environmentSlug) || !formId || formId.length > 255)
3953
+ if (!environmentSlug || !isValidEnvironmentSlug(environmentSlug) || action !== "list" && !formId || (formId?.length ?? 0) > 255)
3497
3954
  return usageError2("Provide a valid --environment and --form.");
3498
3955
  if (action !== "list" && (!submissionId || submissionId.length > 255))
3499
3956
  return usageError2("Provide --submission.");
3500
- const status = formsSubmissionStatusSchema.safeParse(value("status"));
3957
+ const status2 = formsSubmissionStatusSchema.safeParse(value("status"));
3501
3958
  const expected = formsSubmissionStatusSchema.safeParse(
3502
3959
  value("expected-status")
3503
3960
  );
3504
- if (value("status") && !status.success || action === "status" && (!status.success || !expected.success))
3961
+ if (value("status") && !status2.success && !(action === "list" && ["inbox", "all"].includes(value("status"))) || action === "status" && (!status2.success || !expected.success))
3505
3962
  return usageError2(
3506
3963
  "Use new, read, archived or spam for --status and --expected-status."
3507
3964
  );
3508
- const filters2 = new URLSearchParams();
3509
- for (const key of ["query", "status", "from", "to", "limit", "cursor"]) {
3965
+ const filters3 = new URLSearchParams();
3966
+ if (value("purpose") && !["regular", "test", "all"].includes(value("purpose")))
3967
+ return usageError2("Use regular, test or all for --purpose.");
3968
+ if (value("version")) filters3.set("versionId", value("version"));
3969
+ for (const key of [
3970
+ "query",
3971
+ "status",
3972
+ "purpose",
3973
+ "from",
3974
+ "to",
3975
+ "limit",
3976
+ "cursor"
3977
+ ]) {
3510
3978
  const item = value(key);
3511
- if (item) filters2.set(key, item);
3979
+ if (item && !(["status", "purpose"].includes(key) && item === "all"))
3980
+ filters3.set(key, item);
3512
3981
  }
3513
3982
  const limit = Number(value("limit") ?? 50);
3514
3983
  if (!Number.isInteger(limit) || limit < 1 || limit > 100)
@@ -3516,7 +3985,7 @@ async function runSubmissionsCommand(options) {
3516
3985
  if ((value("query")?.length ?? 0) > 200 || (value("cursor")?.length ?? 0) > 2048)
3517
3986
  return usageError2("The query or cursor is too long.");
3518
3987
  for (const key of ["from", "to"])
3519
- if (value(key) && !z8.string().datetime({ offset: true }).safeParse(value(key)).success)
3988
+ if (value(key) && !z9.string().datetime({ offset: true }).safeParse(value(key)).success)
3520
3989
  return usageError2(
3521
3990
  `--${key} must be an ISO timestamp including a timezone.`
3522
3991
  );
@@ -3545,13 +4014,15 @@ async function runSubmissionsCommand(options) {
3545
4014
  environmentId: environment.id,
3546
4015
  formId
3547
4016
  };
3548
- const response = action === "list" ? await context.client.listSubmissions({ ...input, filters: filters2 }) : action === "read" ? await context.client.readSubmission({
4017
+ const response = action === "list" ? await context.client.listSubmissions({ ...input, filters: filters3 }) : action === "read" ? await context.client.readSubmission({
3549
4018
  ...input,
4019
+ formId,
3550
4020
  submissionId
3551
4021
  }) : await context.client.updateSubmissionStatus({
3552
4022
  ...input,
4023
+ formId,
3553
4024
  submissionId,
3554
- status: status.data,
4025
+ status: status2.data,
3555
4026
  expectedStatus: expected.data
3556
4027
  });
3557
4028
  return { exitCode: 0, stdout: stringifySafeJson(response) };
@@ -3781,14 +4252,14 @@ async function runDefinitionLifecycle(options) {
3781
4252
  const formId = value("form");
3782
4253
  if (!environmentSlug || !isValidEnvironmentSlug(environmentSlug) || action !== "list" && (!formId || formId.length > 255))
3783
4254
  return usageError2("Provide a valid --environment and --form.");
3784
- const status = value("status") ?? "active";
3785
- if (!["active", "inactive", "all"].includes(status))
4255
+ const status2 = value("status") ?? "active";
4256
+ if (!["active", "inactive", "all"].includes(status2))
3786
4257
  return usageError2("Use active, inactive or all for --status.");
3787
4258
  const apply = parsed.flags.get("--apply") === true;
3788
- const revision = Number(value("expected-revision"));
4259
+ const revision2 = Number(value("expected-revision"));
3789
4260
  const count = Number(value("expected-submissions"));
3790
4261
  const confirmKey = value("confirm");
3791
- if ((action === "archive" || action === "restore" || apply) && (!Number.isSafeInteger(revision) || revision < 1))
4262
+ if ((action === "archive" || action === "restore" || apply) && (!Number.isSafeInteger(revision2) || revision2 < 1))
3792
4263
  return usageError2(
3793
4264
  "Read the form first, then provide its --expected-revision."
3794
4265
  );
@@ -3831,7 +4302,7 @@ async function runDefinitionLifecycle(options) {
3831
4302
  stdout: stringifySafeJson(
3832
4303
  await context.client.listDefinitions({
3833
4304
  ...input,
3834
- status
4305
+ status: status2
3835
4306
  })
3836
4307
  )
3837
4308
  };
@@ -3864,11 +4335,11 @@ async function runDefinitionLifecycle(options) {
3864
4335
  change: action === "delete" ? {
3865
4336
  action,
3866
4337
  confirmKey,
3867
- expectedRevision: revision,
4338
+ expectedRevision: revision2,
3868
4339
  expectedSubmissionCount: count
3869
4340
  } : {
3870
4341
  action,
3871
- expectedRevision: revision
4342
+ expectedRevision: revision2
3872
4343
  }
3873
4344
  });
3874
4345
  return {
@@ -4223,7 +4694,7 @@ async function loadFormDefinitions(options) {
4223
4694
  ok: true
4224
4695
  };
4225
4696
  }
4226
- const manifestPath = path10.resolve(
4697
+ const manifestPath = path11.resolve(
4227
4698
  options.cwd ?? process.cwd(),
4228
4699
  options.source.path
4229
4700
  );
@@ -4233,10 +4704,10 @@ async function loadFormDefinitions(options) {
4233
4704
  schema: definitionManifestSchema
4234
4705
  });
4235
4706
  if (!manifest.ok) return manifest;
4236
- const manifestDirectory = path10.dirname(manifestPath);
4707
+ const manifestDirectory = path11.dirname(manifestPath);
4237
4708
  const definitions = [];
4238
4709
  for (const definitionPath of manifest.value.forms) {
4239
- if (path10.isAbsolute(definitionPath)) {
4710
+ if (path11.isAbsolute(definitionPath)) {
4240
4711
  return {
4241
4712
  error: usageError2(
4242
4713
  `Manifest definition paths must be relative: ${definitionPath}`
@@ -4244,9 +4715,9 @@ async function loadFormDefinitions(options) {
4244
4715
  ok: false
4245
4716
  };
4246
4717
  }
4247
- const resolvedPath = path10.resolve(manifestDirectory, definitionPath);
4248
- const relativePath = path10.relative(manifestDirectory, resolvedPath);
4249
- if (relativePath.startsWith(`..${path10.sep}`) || relativePath === "..") {
4718
+ const resolvedPath = path11.resolve(manifestDirectory, definitionPath);
4719
+ const relativePath = path11.relative(manifestDirectory, resolvedPath);
4720
+ if (relativePath.startsWith(`..${path11.sep}`) || relativePath === "..") {
4250
4721
  return {
4251
4722
  error: usageError2(
4252
4723
  `Manifest definition paths must stay inside the manifest directory: ${definitionPath}`
@@ -4309,11 +4780,11 @@ function parseInputFlags(args2, options) {
4309
4780
  };
4310
4781
  }
4311
4782
  async function readInputFile(options) {
4312
- const resolvedInputPath = path10.resolve(
4783
+ const resolvedInputPath = path11.resolve(
4313
4784
  options.cwd ?? process.cwd(),
4314
4785
  options.inputPath
4315
4786
  );
4316
- const rawInput = await readFile5(resolvedInputPath, "utf-8").catch(
4787
+ const rawInput = await readFile6(resolvedInputPath, "utf-8").catch(
4317
4788
  (error) => {
4318
4789
  const message = error instanceof Error ? error.message : String(error);
4319
4790
  return {
@@ -4612,11 +5083,11 @@ async function runDeployment(options) {
4612
5083
 
4613
5084
  // src/package-metadata.ts
4614
5085
  import { readFileSync } from "fs";
4615
- import path11 from "path";
5086
+ import path12 from "path";
4616
5087
  import { fileURLToPath } from "url";
4617
5088
  function readPackageMetadata() {
4618
- const packageJsonPath = path11.resolve(
4619
- path11.dirname(fileURLToPath(import.meta.url)),
5089
+ const packageJsonPath = path12.resolve(
5090
+ path12.dirname(fileURLToPath(import.meta.url)),
4620
5091
  "..",
4621
5092
  "package.json"
4622
5093
  );
@@ -4630,8 +5101,8 @@ function readPackageMetadata() {
4630
5101
  }
4631
5102
 
4632
5103
  // src/pulse-command.ts
4633
- import path22 from "path";
4634
- import { parseArgs } from "util";
5104
+ import path23 from "path";
5105
+ import { parseArgs as parseArgs2 } from "util";
4635
5106
 
4636
5107
  // src/core/errors.ts
4637
5108
  function commandError2(input) {
@@ -4642,29 +5113,29 @@ function commandError2(input) {
4642
5113
  }
4643
5114
 
4644
5115
  // src/pulse/api-client.ts
4645
- import { readFile as readFile6 } from "fs/promises";
4646
- import { z as z9 } from "zod";
4647
- var projectSchema = z9.object({
4648
- baseUrl: z9.string().url().nullable(),
4649
- checkCount: z9.number().int().min(0),
4650
- id: z9.string().trim().min(1).max(120),
4651
- name: z9.string().trim().min(1).max(120),
4652
- slug: z9.string().trim().min(1).max(80).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/)
5116
+ import { readFile as readFile7 } from "fs/promises";
5117
+ import { z as z10 } from "zod";
5118
+ var projectSchema = z10.object({
5119
+ baseUrl: z10.string().url().nullable(),
5120
+ checkCount: z10.number().int().min(0),
5121
+ id: z10.string().trim().min(1).max(120),
5122
+ name: z10.string().trim().min(1).max(120),
5123
+ slug: z10.string().trim().min(1).max(80).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/)
4653
5124
  }).strict();
4654
- var projectResponseSchema = z9.object({ project: projectSchema }).strict();
4655
- var deploymentResponseSchema2 = z9.object({
4656
- checks: z9.array(
4657
- z9.object({
4658
- checkId: z9.string().min(1),
4659
- created: z9.boolean(),
4660
- deploymentId: z9.string().min(1),
4661
- slug: z9.string().min(1),
4662
- version: z9.number().int().positive()
5125
+ var projectResponseSchema = z10.object({ project: projectSchema }).strict();
5126
+ var deploymentResponseSchema2 = z10.object({
5127
+ checks: z10.array(
5128
+ z10.object({
5129
+ checkId: z10.string().min(1),
5130
+ created: z10.boolean(),
5131
+ deploymentId: z10.string().min(1),
5132
+ slug: z10.string().min(1),
5133
+ version: z10.number().int().positive()
4663
5134
  }).strict()
4664
5135
  ),
4665
- checksum: z9.string().min(1),
4666
- dashboardUrl: z9.string().url().nullable().optional(),
4667
- projectId: z9.string().min(1)
5136
+ checksum: z10.string().min(1),
5137
+ dashboardUrl: z10.string().url().nullable().optional(),
5138
+ projectId: z10.string().min(1)
4668
5139
  }).strict();
4669
5140
  function createPulseApiClient(input) {
4670
5141
  const fetchImpl = input.fetchImpl ?? fetch;
@@ -4724,7 +5195,7 @@ function createPulseApiClient(input) {
4724
5195
  );
4725
5196
  form.set(
4726
5197
  "bundle",
4727
- new Blob([await readFile6(options.manifest.archivePath)], {
5198
+ new Blob([await readFile7(options.manifest.archivePath)], {
4728
5199
  type: "application/gzip"
4729
5200
  }),
4730
5201
  "checks-bundle.tgz"
@@ -4739,11 +5210,11 @@ function createPulseApiClient(input) {
4739
5210
  }
4740
5211
  };
4741
5212
  }
4742
- function pulseApiError(body, status) {
5213
+ function pulseApiError(body, status2) {
4743
5214
  const payload = body;
4744
5215
  const candidate = payload?.error;
4745
- const code = candidate && typeof candidate === "object" && typeof candidate.code === "string" ? candidate.code : status === 401 ? "UNAUTHORIZED" : status === 403 ? "FORBIDDEN" : status === 404 ? "NOT_FOUND" : status === 409 ? "CONFLICT" : "API_REJECTED";
4746
- const message = typeof candidate === "string" ? candidate : candidate && typeof candidate === "object" && typeof candidate.message === "string" ? candidate.message : `SiteOS Pulse returned ${status}.`;
5216
+ const code = candidate && typeof candidate === "object" && typeof candidate.code === "string" ? candidate.code : status2 === 401 ? "UNAUTHORIZED" : status2 === 403 ? "FORBIDDEN" : status2 === 404 ? "NOT_FOUND" : status2 === 409 ? "CONFLICT" : "API_REJECTED";
5217
+ const message = typeof candidate === "string" ? candidate : candidate && typeof candidate === "object" && typeof candidate.message === "string" ? candidate.message : `SiteOS Pulse returned ${status2}.`;
4747
5218
  return new CliError(code, message);
4748
5219
  }
4749
5220
 
@@ -4752,18 +5223,18 @@ import { createHash as createHash6, randomUUID as randomUUID4 } from "crypto";
4752
5223
  import {
4753
5224
  access,
4754
5225
  mkdir as mkdir3,
4755
- readFile as readFile8,
5226
+ readFile as readFile9,
4756
5227
  rename as rename5,
4757
5228
  rm as rm4,
4758
- writeFile as writeFile5
5229
+ writeFile as writeFile6
4759
5230
  } from "fs/promises";
4760
- import path13 from "path";
5231
+ import path14 from "path";
4761
5232
  import * as tar from "tar";
4762
5233
 
4763
5234
  // src/pulse/project-files.ts
4764
5235
  import { createHash as createHash5 } from "crypto";
4765
- import { lstat as lstat5, readFile as readFile7 } from "fs/promises";
4766
- import path12 from "path";
5236
+ import { lstat as lstat5, readFile as readFile8 } from "fs/promises";
5237
+ import path13 from "path";
4767
5238
  import fg from "fast-glob";
4768
5239
  var MAX_BUNDLE_FILES = 5e3;
4769
5240
  var MAX_BUNDLE_BYTES = 50 * 1024 * 1024;
@@ -4786,7 +5257,7 @@ function isSensitive(relativePath) {
4786
5257
  return SENSITIVE_FILES.some((pattern) => pattern.test(segments.at(-1) ?? ""));
4787
5258
  }
4788
5259
  async function hashFile(filePath) {
4789
- return createHash5("sha256").update(await readFile7(filePath)).digest("hex");
5260
+ return createHash5("sha256").update(await readFile8(filePath)).digest("hex");
4790
5261
  }
4791
5262
  async function discoverProjectFiles(projectRoot, config) {
4792
5263
  const errors = [];
@@ -4859,9 +5330,9 @@ async function discoverProjectFiles(projectRoot, config) {
4859
5330
  errors.push(`Sensitive path cannot be included: ${relativePath}`);
4860
5331
  continue;
4861
5332
  }
4862
- const absolutePath = path12.resolve(projectRoot, relativePath);
4863
- const relativeToRoot = path12.relative(projectRoot, absolutePath);
4864
- if (relativeToRoot.startsWith("..") || path12.isAbsolute(relativeToRoot)) {
5333
+ const absolutePath = path13.resolve(projectRoot, relativePath);
5334
+ const relativeToRoot = path13.relative(projectRoot, absolutePath);
5335
+ if (relativeToRoot.startsWith("..") || path13.isAbsolute(relativeToRoot)) {
4865
5336
  errors.push(`Included path escapes the project root: ${relativePath}`);
4866
5337
  continue;
4867
5338
  }
@@ -4881,8 +5352,8 @@ async function discoverProjectFiles(projectRoot, config) {
4881
5352
  if (totalBytes > MAX_BUNDLE_BYTES)
4882
5353
  errors.push("The bundle exceeds the 50 MiB size limit.");
4883
5354
  try {
4884
- const packageSource = await readFile7(
4885
- path12.join(projectRoot, "package.json"),
5355
+ const packageSource = await readFile8(
5356
+ path13.join(projectRoot, "package.json"),
4886
5357
  "utf8"
4887
5358
  );
4888
5359
  const packageJson = JSON.parse(packageSource);
@@ -4904,10 +5375,10 @@ async function discoverProjectFiles(projectRoot, config) {
4904
5375
 
4905
5376
  // src/pulse/bundle.ts
4906
5377
  async function hashArchive(archivePath) {
4907
- return createHash6("sha256").update(await readFile8(archivePath)).digest("hex");
5378
+ return createHash6("sha256").update(await readFile9(archivePath)).digest("hex");
4908
5379
  }
4909
5380
  async function createDeploymentBundle(input) {
4910
- const projectRoot = path13.resolve(input.projectRoot);
5381
+ const projectRoot = path14.resolve(input.projectRoot);
4911
5382
  const config = await loadChecksConfig(projectRoot);
4912
5383
  const configFile = await findChecksConfigFile(projectRoot) ?? CONFIG_FILE;
4913
5384
  const report = await discoverProjectFiles(projectRoot, config);
@@ -4920,9 +5391,9 @@ async function createDeploymentBundle(input) {
4920
5391
  }
4921
5392
  );
4922
5393
  }
4923
- const outputDirectory = input.output ? path13.dirname(path13.resolve(projectRoot, input.output)) : path13.join(projectRoot, ".siteos", "pulse", "deployments");
5394
+ const outputDirectory = input.output ? path14.dirname(path14.resolve(projectRoot, input.output)) : path14.join(projectRoot, ".siteos", "pulse", "deployments");
4924
5395
  await mkdir3(outputDirectory, { recursive: true });
4925
- const temporaryPath = path13.join(
5396
+ const temporaryPath = path14.join(
4926
5397
  outputDirectory,
4927
5398
  `.siteos-pulse-${randomUUID4()}.tgz`
4928
5399
  );
@@ -4941,7 +5412,7 @@ async function createDeploymentBundle(input) {
4941
5412
  archiveFiles
4942
5413
  );
4943
5414
  const checksum2 = await hashArchive(temporaryPath);
4944
- const archivePath = input.output ? path13.resolve(projectRoot, input.output) : path13.join(outputDirectory, `siteos-pulse-${checksum2.slice(0, 16)}.tgz`);
5415
+ const archivePath = input.output ? path14.resolve(projectRoot, input.output) : path14.join(outputDirectory, `siteos-pulse-${checksum2.slice(0, 16)}.tgz`);
4945
5416
  try {
4946
5417
  await access(archivePath);
4947
5418
  if (input.output) {
@@ -4971,7 +5442,7 @@ async function createDeploymentBundle(input) {
4971
5442
  files: report.files,
4972
5443
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
4973
5444
  };
4974
- await writeFile5(
5445
+ await writeFile6(
4975
5446
  `${archivePath}.json`,
4976
5447
  `${JSON.stringify(manifest, null, 2)}
4977
5448
  `,
@@ -4981,13 +5452,13 @@ async function createDeploymentBundle(input) {
4981
5452
  }
4982
5453
 
4983
5454
  // src/pulse/init.ts
4984
- import { mkdir as mkdir4, readFile as readFile9, writeFile as writeFile6 } from "fs/promises";
4985
- import path14 from "path";
5455
+ import { mkdir as mkdir4, readFile as readFile10, writeFile as writeFile7 } from "fs/promises";
5456
+ import path15 from "path";
4986
5457
  var SITEOS_PLAYWRIGHT_CONFIG = "siteos.playwright.config.ts";
4987
5458
  var PULSE_CACHE_DIRECTORY = ".siteos/pulse/";
4988
5459
  async function exists(filePath) {
4989
5460
  try {
4990
- await readFile9(filePath);
5461
+ await readFile10(filePath);
4991
5462
  return true;
4992
5463
  } catch (error) {
4993
5464
  if (error.code === "ENOENT") return false;
@@ -5022,7 +5493,7 @@ export default defineConfig({
5022
5493
  `;
5023
5494
  }
5024
5495
  async function createPulsePlaywrightConfig(input) {
5025
- const configPath = path14.join(input.projectRoot, SITEOS_PLAYWRIGHT_CONFIG);
5496
+ const configPath = path15.join(input.projectRoot, SITEOS_PLAYWRIGHT_CONFIG);
5026
5497
  if (await exists(configPath)) {
5027
5498
  throw new CliError(
5028
5499
  "PULSE_PLAYWRIGHT_CONFIG_EXISTS",
@@ -5032,34 +5503,34 @@ async function createPulsePlaywrightConfig(input) {
5032
5503
  }
5033
5504
  );
5034
5505
  }
5035
- await writeFile6(configPath, pulsePlaywrightConfigSource(input), {
5506
+ await writeFile7(configPath, pulsePlaywrightConfigSource(input), {
5036
5507
  encoding: "utf8",
5037
5508
  flag: "wx"
5038
5509
  });
5039
5510
  }
5040
5511
  async function detectPackageName(projectRoot) {
5041
5512
  try {
5042
- const contents = await readFile9(
5043
- path14.join(projectRoot, "package.json"),
5513
+ const contents = await readFile10(
5514
+ path15.join(projectRoot, "package.json"),
5044
5515
  "utf8"
5045
5516
  );
5046
5517
  const parsed = JSON.parse(contents);
5047
- return typeof parsed.name === "string" ? parsed.name : path14.basename(projectRoot);
5518
+ return typeof parsed.name === "string" ? parsed.name : path15.basename(projectRoot);
5048
5519
  } catch {
5049
- return path14.basename(projectRoot);
5520
+ return path15.basename(projectRoot);
5050
5521
  }
5051
5522
  }
5052
5523
  async function ensureGitignore(projectRoot) {
5053
- const gitignorePath = path14.join(projectRoot, ".gitignore");
5524
+ const gitignorePath = path15.join(projectRoot, ".gitignore");
5054
5525
  let contents = "";
5055
5526
  try {
5056
- contents = await readFile9(gitignorePath, "utf8");
5527
+ contents = await readFile10(gitignorePath, "utf8");
5057
5528
  } catch (error) {
5058
5529
  if (error.code !== "ENOENT") throw error;
5059
5530
  }
5060
5531
  if (contents.split(/\r?\n/).includes(PULSE_CACHE_DIRECTORY)) return false;
5061
5532
  const prefix = contents.length > 0 && !contents.endsWith("\n") ? "\n" : "";
5062
- await writeFile6(
5533
+ await writeFile7(
5063
5534
  gitignorePath,
5064
5535
  `${contents}${prefix}${PULSE_CACHE_DIRECTORY}
5065
5536
  `,
@@ -5068,21 +5539,21 @@ async function ensureGitignore(projectRoot) {
5068
5539
  return true;
5069
5540
  }
5070
5541
  async function initializeProject(input) {
5071
- const projectRoot = path14.resolve(input.projectRoot);
5542
+ const projectRoot = path15.resolve(input.projectRoot);
5072
5543
  const existingConfig = await findChecksConfigFile(projectRoot);
5073
5544
  if (existingConfig) {
5074
5545
  throw new CliError("CONFIG_EXISTS", `${existingConfig} already exists.`, {
5075
5546
  hint: "Edit the existing file or run `siteos pulse validate`."
5076
5547
  });
5077
5548
  }
5078
- const configPath = path14.join(projectRoot, CONFIG_FILE);
5549
+ const configPath = path15.join(projectRoot, CONFIG_FILE);
5079
5550
  const created = [];
5080
5551
  const updated = [];
5081
5552
  const testsDir = input.testsDir ?? "tests/siteos";
5082
5553
  const packageName2 = await detectPackageName(projectRoot);
5083
5554
  const projectName = projectDisplayName(input.project ?? packageName2);
5084
5555
  const checkSlug = projectSlug(input.suite ?? "homepage");
5085
- const exampleTest = path14.posix.join(
5556
+ const exampleTest = path15.posix.join(
5086
5557
  testsDir.replaceAll("\\", "/"),
5087
5558
  `${checkSlug}.spec.ts`
5088
5559
  );
@@ -5119,11 +5590,11 @@ async function initializeProject(input) {
5119
5590
  baseUrl: input.baseUrl
5120
5591
  });
5121
5592
  created.push(SITEOS_PLAYWRIGHT_CONFIG);
5122
- const testDirectory = path14.join(projectRoot, testsDir);
5593
+ const testDirectory = path15.join(projectRoot, testsDir);
5123
5594
  await mkdir4(testDirectory, { recursive: true });
5124
- if (!await exists(path14.join(projectRoot, exampleTest))) {
5125
- await writeFile6(
5126
- path14.join(projectRoot, exampleTest),
5595
+ if (!await exists(path15.join(projectRoot, exampleTest))) {
5596
+ await writeFile7(
5597
+ path15.join(projectRoot, exampleTest),
5127
5598
  `import { expect, test } from "@playwright/test";
5128
5599
 
5129
5600
  test(${JSON.stringify(`${projectDisplayName(input.suite ?? "homepage")} is reachable`)}, async ({ page }) => {
@@ -5135,7 +5606,7 @@ test(${JSON.stringify(`${projectDisplayName(input.suite ?? "homepage")} is reach
5135
5606
  );
5136
5607
  created.push(exampleTest);
5137
5608
  }
5138
- await writeFile6(configPath, `${JSON.stringify(config, null, 2)}
5609
+ await writeFile7(configPath, `${JSON.stringify(config, null, 2)}
5139
5610
  `, {
5140
5611
  encoding: "utf8",
5141
5612
  flag: "wx"
@@ -5149,14 +5620,14 @@ test(${JSON.stringify(`${projectDisplayName(input.suite ?? "homepage")} is reach
5149
5620
  import fg4 from "fast-glob";
5150
5621
 
5151
5622
  // src/pulse/interactive/discovery.ts
5152
- import { readFile as readFile11 } from "fs/promises";
5623
+ import { readFile as readFile12 } from "fs/promises";
5153
5624
  import { createRequire } from "module";
5154
- import path16 from "path";
5625
+ import path17 from "path";
5155
5626
  import fg2 from "fast-glob";
5156
5627
 
5157
5628
  // src/pulse/interactive/playwright-config.ts
5158
- import { readFile as readFile10 } from "fs/promises";
5159
- import path15 from "path";
5629
+ import { readFile as readFile11 } from "fs/promises";
5630
+ import path16 from "path";
5160
5631
 
5161
5632
  // src/pulse/interactive/discovery.ts
5162
5633
  var PLAYWRIGHT_SPEC_PATTERN = "**/*.{spec,test}.{js,cjs,mjs,ts,cts,mts,jsx,tsx}";
@@ -5201,11 +5672,11 @@ async function discoverPlaywrightSelectorMatches(projectRoot, selectors, testsDi
5201
5672
  }
5202
5673
 
5203
5674
  // src/pulse/sync-plan.ts
5204
- import path17 from "path";
5675
+ import path18 from "path";
5205
5676
  import fg3 from "fast-glob";
5206
5677
  var PLAYWRIGHT_SPEC_FILE = /\.(?:spec|test)\.(?:[cm]?[jt]sx?)$/;
5207
5678
  function defaultNameFromSpec(specPath) {
5208
- const basename = path17.posix.basename(specPath).replace(/\.(?:spec|test)\.[^.]+$/, "");
5679
+ const basename = path18.posix.basename(specPath).replace(/\.(?:spec|test)\.[^.]+$/, "");
5209
5680
  return basename.split(/[^A-Za-z0-9]+/).filter(Boolean).map((word) => `${word.charAt(0).toUpperCase()}${word.slice(1)}`).join(" ") || "Smoke";
5210
5681
  }
5211
5682
  function normalizedPaths(paths) {
@@ -5263,8 +5734,8 @@ function buildSyncPlan(input) {
5263
5734
 
5264
5735
  // src/pulse/test-imports.ts
5265
5736
  import { builtinModules } from "module";
5266
- import { readFile as readFile12 } from "fs/promises";
5267
- import path18 from "path";
5737
+ import { readFile as readFile13 } from "fs/promises";
5738
+ import path19 from "path";
5268
5739
  import { build } from "esbuild";
5269
5740
  var ALLOWED_PACKAGES = /* @__PURE__ */ new Set(["@playwright/test"]);
5270
5741
  var BUILTINS = /* @__PURE__ */ new Set([
@@ -5278,9 +5749,9 @@ function packageName(importPath) {
5278
5749
  return importPath.split("/")[0] ?? importPath;
5279
5750
  }
5280
5751
  function normalizedRelativePath(projectRoot, inputPath) {
5281
- const absolute = path18.isAbsolute(inputPath) ? inputPath : path18.resolve(projectRoot, inputPath);
5282
- const relative = path18.relative(projectRoot, absolute).replaceAll("\\", "/");
5283
- if (!relative || relative.startsWith("../") || path18.isAbsolute(relative)) {
5752
+ const absolute = path19.isAbsolute(inputPath) ? inputPath : path19.resolve(projectRoot, inputPath);
5753
+ const relative = path19.relative(projectRoot, absolute).replaceAll("\\", "/");
5754
+ if (!relative || relative.startsWith("../") || path19.isAbsolute(relative)) {
5284
5755
  throw new CliError(
5285
5756
  "IMPORT_OUTSIDE_PROJECT",
5286
5757
  `A selected test imports outside the project: ${inputPath}`
@@ -5289,7 +5760,7 @@ function normalizedRelativePath(projectRoot, inputPath) {
5289
5760
  return relative;
5290
5761
  }
5291
5762
  async function analyzeTestImports(input) {
5292
- const projectRoot = path18.resolve(input.projectRoot);
5763
+ const projectRoot = path19.resolve(input.projectRoot);
5293
5764
  const entryFiles = [
5294
5765
  ...new Set(
5295
5766
  input.entryFiles.map((file) => normalizedRelativePath(projectRoot, file))
@@ -5319,7 +5790,7 @@ async function analyzeTestImports(input) {
5319
5790
  }
5320
5791
  );
5321
5792
  }
5322
- const inputs = Object.keys(result.metafile?.inputs ?? {}).map(
5793
+ const inputs2 = Object.keys(result.metafile?.inputs ?? {}).map(
5323
5794
  (file) => normalizedRelativePath(projectRoot, file)
5324
5795
  );
5325
5796
  const entrySet = new Set(entryFiles);
@@ -5347,8 +5818,8 @@ async function analyzeTestImports(input) {
5347
5818
  const environmentVariables = /* @__PURE__ */ new Set();
5348
5819
  const compatibilityIssues = /* @__PURE__ */ new Set();
5349
5820
  await Promise.all(
5350
- inputs.map(async (file) => {
5351
- const source = await readFile12(path18.join(projectRoot, file), "utf8").catch(
5821
+ inputs2.map(async (file) => {
5822
+ const source = await readFile13(path19.join(projectRoot, file), "utf8").catch(
5352
5823
  () => ""
5353
5824
  );
5354
5825
  for (const match of source.matchAll(ENVIRONMENT_PATTERN)) {
@@ -5365,7 +5836,7 @@ async function analyzeTestImports(input) {
5365
5836
  })
5366
5837
  );
5367
5838
  return {
5368
- supportingFiles: inputs.filter((file) => !entrySet.has(file)).sort(),
5839
+ supportingFiles: inputs2.filter((file) => !entrySet.has(file)).sort(),
5369
5840
  externalPackages: [...externalPackages].sort(),
5370
5841
  externalImporters: Object.fromEntries(
5371
5842
  [...externalImporters.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([dependency, importers]) => [dependency, [...importers].sort()])
@@ -5791,12 +6262,12 @@ async function runSyncCli(input) {
5791
6262
  // src/pulse/playwright.ts
5792
6263
  import { spawn as spawn3 } from "child_process";
5793
6264
  import { createRequire as createRequire2 } from "module";
5794
- import path20 from "path";
6265
+ import path21 from "path";
5795
6266
 
5796
6267
  // src/pulse/package-manager.ts
5797
6268
  import { spawn as spawn2 } from "child_process";
5798
- import { access as access2, readFile as readFile13 } from "fs/promises";
5799
- import path19 from "path";
6269
+ import { access as access2, readFile as readFile14 } from "fs/promises";
6270
+ import path20 from "path";
5800
6271
  var LOCKFILES = [
5801
6272
  { packageManager: "pnpm", filenames: ["pnpm-lock.yaml"] },
5802
6273
  { packageManager: "yarn", filenames: ["yarn.lock"] },
@@ -5818,7 +6289,7 @@ async function fileExists2(filePath) {
5818
6289
  async function declaredPackageManager(projectRoot) {
5819
6290
  let contents;
5820
6291
  try {
5821
- contents = await readFile13(path19.join(projectRoot, "package.json"), "utf8");
6292
+ contents = await readFile14(path20.join(projectRoot, "package.json"), "utf8");
5822
6293
  } catch (error) {
5823
6294
  if (error.code === "ENOENT") return null;
5824
6295
  throw error;
@@ -5855,7 +6326,7 @@ async function declaredPackageManager(projectRoot) {
5855
6326
  );
5856
6327
  }
5857
6328
  async function detectPackageManager(projectRoot) {
5858
- const root = path19.resolve(projectRoot);
6329
+ const root = path20.resolve(projectRoot);
5859
6330
  const declared = await declaredPackageManager(root);
5860
6331
  if (declared) return declared;
5861
6332
  const matches = (await Promise.all(
@@ -5864,7 +6335,7 @@ async function detectPackageManager(projectRoot) {
5864
6335
  filenames: (await Promise.all(
5865
6336
  filenames2.map(async (filename) => ({
5866
6337
  filename,
5867
- exists: await fileExists2(path19.join(root, filename))
6338
+ exists: await fileExists2(path20.join(root, filename))
5868
6339
  }))
5869
6340
  )).filter((entry) => entry.exists).map((entry) => entry.filename)
5870
6341
  }))
@@ -5925,12 +6396,12 @@ function isMissingBrowserDiagnostic(output) {
5925
6396
  function resolvePlaywrightCli(projectRoot) {
5926
6397
  try {
5927
6398
  const requireFromProject = createRequire2(
5928
- path20.join(projectRoot, "package.json")
6399
+ path21.join(projectRoot, "package.json")
5929
6400
  );
5930
6401
  const packageJson = requireFromProject.resolve(
5931
6402
  "@playwright/test/package.json"
5932
6403
  );
5933
- return path20.join(path20.dirname(packageJson), "cli.js");
6404
+ return path21.join(path21.dirname(packageJson), "cli.js");
5934
6405
  } catch {
5935
6406
  throw new CliError(
5936
6407
  "PLAYWRIGHT_NOT_INSTALLED",
@@ -5942,7 +6413,7 @@ function resolvePlaywrightCli(projectRoot) {
5942
6413
  }
5943
6414
  }
5944
6415
  async function runProjectTests(input) {
5945
- const projectRoot = path20.resolve(input.projectRoot);
6416
+ const projectRoot = path21.resolve(input.projectRoot);
5946
6417
  const config = await loadChecksConfig(projectRoot);
5947
6418
  const report = await discoverProjectFiles(projectRoot, config);
5948
6419
  if (!report.valid) {
@@ -5999,9 +6470,9 @@ async function runProjectTests(input) {
5999
6470
  }
6000
6471
 
6001
6472
  // src/pulse/validate.ts
6002
- import path21 from "path";
6473
+ import path22 from "path";
6003
6474
  async function validateProject(projectRoot) {
6004
- const root = path21.resolve(projectRoot);
6475
+ const root = path22.resolve(projectRoot);
6005
6476
  const config = await loadChecksConfig(root);
6006
6477
  return discoverProjectFiles(root, config);
6007
6478
  }
@@ -6034,7 +6505,7 @@ async function runPulseCommand(options) {
6034
6505
  }
6035
6506
  }
6036
6507
  async function runInitCommand(options, args2) {
6037
- const { values } = parseArgs({
6508
+ const { values } = parseArgs2({
6038
6509
  args: args2,
6039
6510
  options: {
6040
6511
  "base-url": { type: "string" },
@@ -6063,7 +6534,7 @@ async function runInitCommand(options, args2) {
6063
6534
  };
6064
6535
  }
6065
6536
  async function runValidateCommand(options, args2) {
6066
- const { values } = parseArgs({
6537
+ const { values } = parseArgs2({
6067
6538
  args: args2,
6068
6539
  options: { json: { default: false, type: "boolean" } },
6069
6540
  strict: true
@@ -6075,7 +6546,7 @@ async function runValidateCommand(options, args2) {
6075
6546
  };
6076
6547
  }
6077
6548
  async function runSyncCommand(options, args2) {
6078
- const { values } = parseArgs({
6549
+ const { values } = parseArgs2({
6079
6550
  args: args2,
6080
6551
  options: {
6081
6552
  check: { default: false, type: "boolean" },
@@ -6108,7 +6579,7 @@ async function runTestCommand(options, args2) {
6108
6579
  const separator = args2.indexOf("--");
6109
6580
  const commandArgs = separator === -1 ? args2 : args2.slice(0, separator);
6110
6581
  const passthrough = separator === -1 ? [] : args2.slice(separator + 1);
6111
- const { values } = parseArgs({
6582
+ const { values } = parseArgs2({
6112
6583
  args: commandArgs,
6113
6584
  options: {
6114
6585
  "base-url": { type: "string" },
@@ -6142,7 +6613,7 @@ async function optionalProjectContext(options) {
6142
6613
  return context;
6143
6614
  }
6144
6615
  async function runDeployCommand(options, args2) {
6145
- const { values } = parseArgs({
6616
+ const { values } = parseArgs2({
6146
6617
  args: args2,
6147
6618
  options: {
6148
6619
  "dry-run": { default: false, type: "boolean" },
@@ -6151,7 +6622,7 @@ async function runDeployCommand(options, args2) {
6151
6622
  },
6152
6623
  strict: true
6153
6624
  });
6154
- const projectRoot = path22.resolve(options.cwd ?? process.cwd());
6625
+ const projectRoot = path23.resolve(options.cwd ?? process.cwd());
6155
6626
  const repositoryRoot = await findRepositoryRoot(projectRoot);
6156
6627
  const common = await commonServiceContext(options, "pulse");
6157
6628
  if (common && (!common.environmentBinding?.slug || !common.environment.url))
@@ -6175,7 +6646,7 @@ async function runDeployCommand(options, args2) {
6175
6646
  values.json,
6176
6647
  { dryRun: true, manifest },
6177
6648
  [
6178
- `Bundle: ${path22.relative(projectRoot, manifest.archivePath)}`,
6649
+ `Bundle: ${path23.relative(projectRoot, manifest.archivePath)}`,
6179
6650
  `Checksum: ${manifest.checksum}`,
6180
6651
  `Files: ${manifest.fileCount}`,
6181
6652
  "Dry run complete; nothing was uploaded."
@@ -6217,7 +6688,7 @@ async function runDeployCommand(options, args2) {
6217
6688
  values.json,
6218
6689
  { deployment, dryRun: false, manifest },
6219
6690
  [
6220
- `Bundle: ${path22.relative(projectRoot, manifest.archivePath)}`,
6691
+ `Bundle: ${path23.relative(projectRoot, manifest.archivePath)}`,
6221
6692
  `Checksum: ${manifest.checksum}`,
6222
6693
  `Files: ${manifest.fileCount}`,
6223
6694
  `Project ${deployment.projectId} deployed.`,
@@ -6357,63 +6828,63 @@ function exitCodeForPulseError(error) {
6357
6828
  }
6358
6829
 
6359
6830
  // src/siteos-search-api.ts
6360
- import { z as z10 } from "zod";
6361
- var permissiveObjectSchema = z10.record(z10.unknown());
6362
- var environmentSlugSchema = z10.string().min(2).max(30).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/);
6363
- var searchCredentialMetadataSchema = z10.object({
6364
- createdAt: z10.string().datetime({ offset: true }),
6365
- id: z10.string().trim().min(1).max(255),
6366
- lastUsedAt: z10.string().datetime({ offset: true }).nullable(),
6367
- name: z10.string().trim().min(1).max(255),
6368
- projectEnvironmentId: z10.string().trim().min(1).max(255),
6369
- revokedAt: z10.string().datetime({ offset: true }).nullable(),
6370
- status: z10.enum(["active", "revoked"])
6831
+ import { z as z11 } from "zod";
6832
+ var permissiveObjectSchema = z11.record(z11.unknown());
6833
+ var environmentSlugSchema = z11.string().min(2).max(30).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/);
6834
+ var searchCredentialMetadataSchema = z11.object({
6835
+ createdAt: z11.string().datetime({ offset: true }),
6836
+ id: z11.string().trim().min(1).max(255),
6837
+ lastUsedAt: z11.string().datetime({ offset: true }).nullable(),
6838
+ name: z11.string().trim().min(1).max(255),
6839
+ projectEnvironmentId: z11.string().trim().min(1).max(255),
6840
+ revokedAt: z11.string().datetime({ offset: true }).nullable(),
6841
+ status: z11.enum(["active", "revoked"])
6371
6842
  }).strict();
6372
- var searchCredentialListResponseSchema = z10.object({
6843
+ var searchCredentialListResponseSchema = z11.object({
6373
6844
  environmentSlug: environmentSlugSchema,
6374
- success: z10.literal(true),
6375
- tokens: z10.array(searchCredentialMetadataSchema)
6845
+ success: z11.literal(true),
6846
+ tokens: z11.array(searchCredentialMetadataSchema)
6376
6847
  }).strict();
6377
- var searchCredentialExchangeResponseSchema = z10.object({
6848
+ var searchCredentialExchangeResponseSchema = z11.object({
6378
6849
  environmentSlug: environmentSlugSchema,
6379
- success: z10.literal(true),
6850
+ success: z11.literal(true),
6380
6851
  token: searchCredentialMetadataSchema.extend({
6381
- token: z10.string().regex(/^psq_[A-Za-z0-9_-]{22}$/)
6852
+ token: z11.string().regex(/^psq_[A-Za-z0-9_-]{22}$/)
6382
6853
  })
6383
6854
  }).strict();
6384
- var searchCredentialRevokeResponseSchema = z10.object({
6855
+ var searchCredentialRevokeResponseSchema = z11.object({
6385
6856
  environmentSlug: environmentSlugSchema,
6386
- success: z10.literal(true),
6857
+ success: z11.literal(true),
6387
6858
  token: searchCredentialMetadataSchema
6388
6859
  }).strict();
6389
- var searchIndexingCredentialListResponseSchema = z10.object({
6390
- credentials: z10.array(searchCredentialMetadataSchema),
6860
+ var searchIndexingCredentialListResponseSchema = z11.object({
6861
+ credentials: z11.array(searchCredentialMetadataSchema),
6391
6862
  environmentSlug: environmentSlugSchema,
6392
- success: z10.literal(true)
6863
+ success: z11.literal(true)
6393
6864
  }).strict();
6394
- var searchIndexingCredentialExchangeResponseSchema = z10.object({
6865
+ var searchIndexingCredentialExchangeResponseSchema = z11.object({
6395
6866
  credential: searchCredentialMetadataSchema.extend({
6396
- credential: z10.string().regex(/^psi_[A-Za-z0-9_-]{22}$/)
6867
+ credential: z11.string().regex(/^psi_[A-Za-z0-9_-]{22}$/)
6397
6868
  }).strict(),
6398
6869
  environmentSlug: environmentSlugSchema,
6399
- success: z10.literal(true)
6870
+ success: z11.literal(true)
6400
6871
  }).strict();
6401
- var searchIndexingCredentialRevokeResponseSchema = z10.object({
6872
+ var searchIndexingCredentialRevokeResponseSchema = z11.object({
6402
6873
  credential: searchCredentialMetadataSchema,
6403
6874
  environmentSlug: environmentSlugSchema,
6404
- success: z10.literal(true)
6875
+ success: z11.literal(true)
6405
6876
  }).strict();
6406
- var nestedApiErrorResponseSchema = z10.object({
6407
- error: z10.object({
6408
- code: z10.string().trim().min(1).optional(),
6409
- message: z10.string().trim().min(1),
6410
- nextActions: z10.array(z10.string()).optional()
6877
+ var nestedApiErrorResponseSchema = z11.object({
6878
+ error: z11.object({
6879
+ code: z11.string().trim().min(1).optional(),
6880
+ message: z11.string().trim().min(1),
6881
+ nextActions: z11.array(z11.string()).optional()
6411
6882
  })
6412
6883
  }).passthrough();
6413
- var directApiErrorResponseSchema = z10.object({
6414
- code: z10.string().trim().min(1).optional(),
6415
- message: z10.string().trim().min(1).optional(),
6416
- status: z10.number().int().optional()
6884
+ var directApiErrorResponseSchema = z11.object({
6885
+ code: z11.string().trim().min(1).optional(),
6886
+ message: z11.string().trim().min(1).optional(),
6887
+ status: z11.number().int().optional()
6417
6888
  }).passthrough();
6418
6889
  var SiteOSSearchApiError = class extends Error {
6419
6890
  code;
@@ -6683,12 +7154,12 @@ import { randomUUID as randomUUID5 } from "crypto";
6683
7154
  import {
6684
7155
  chmod as chmod4,
6685
7156
  lstat as lstat6,
6686
- readFile as readFile14,
7157
+ readFile as readFile15,
6687
7158
  rename as rename6,
6688
7159
  rm as rm5,
6689
- writeFile as writeFile7
7160
+ writeFile as writeFile8
6690
7161
  } from "fs/promises";
6691
- import path23 from "path";
7162
+ import path24 from "path";
6692
7163
  var SITEOS_SEARCH_QUERY_CREDENTIAL_ENV = "SITEOS_SEARCH_TOKEN";
6693
7164
  var SITEOS_SEARCH_ENVIRONMENT_ENV = "SITEOS_SEARCH_ENV";
6694
7165
  var SITEOS_SEARCH_INDEXING_CREDENTIAL_ENV = "SITEOS_SEARCH_INDEXING_CREDENTIAL";
@@ -6706,8 +7177,8 @@ var SiteOSSearchCredentialStorageError = class extends Error {
6706
7177
  }
6707
7178
  };
6708
7179
  async function prepareSiteOSSearchCredentialInstallation(options) {
6709
- const projectRoot = path23.resolve(options.projectRoot);
6710
- const dotenvPath = path23.join(projectRoot, ".env");
7180
+ const projectRoot = path24.resolve(options.projectRoot);
7181
+ const dotenvPath = path24.join(projectRoot, ".env");
6711
7182
  try {
6712
7183
  await assertSafeProjectRoot2(projectRoot);
6713
7184
  if (!await isDotenvIgnored2(projectRoot)) {
@@ -6765,8 +7236,8 @@ async function prepareSiteOSSearchCredentialInstallation(options) {
6765
7236
  }
6766
7237
  }
6767
7238
  async function prepareSiteOSSearchIndexingCredentialInstallation(options) {
6768
- const projectRoot = path23.resolve(options.projectRoot);
6769
- const dotenvPath = path23.join(projectRoot, ".env");
7239
+ const projectRoot = path24.resolve(options.projectRoot);
7240
+ const dotenvPath = path24.join(projectRoot, ".env");
6770
7241
  try {
6771
7242
  await assertSafeProjectRoot2(projectRoot);
6772
7243
  if (!await isDotenvIgnored2(projectRoot)) {
@@ -6842,7 +7313,7 @@ async function readSafeDotenv2(dotenvPath, managedEnvironmentNames) {
6842
7313
  "SEARCH_CREDENTIAL_STORAGE_INVALID"
6843
7314
  );
6844
7315
  }
6845
- const content = dotenvStats ? await readFile14(dotenvPath, "utf8") : "";
7316
+ const content = dotenvStats ? await readFile15(dotenvPath, "utf8") : "";
6846
7317
  if (managedEnvironmentNames.some(
6847
7318
  (name) => countManagedEntries(content, name) > 1
6848
7319
  )) {
@@ -6853,12 +7324,12 @@ async function readSafeDotenv2(dotenvPath, managedEnvironmentNames) {
6853
7324
  return content;
6854
7325
  }
6855
7326
  async function writeCredentialAtomically2(options) {
6856
- const temporaryPath = path23.join(
7327
+ const temporaryPath = path24.join(
6857
7328
  options.projectRoot,
6858
7329
  `.siteos-search-credential.${process.pid}.${randomUUID5()}.tmp`
6859
7330
  );
6860
7331
  try {
6861
- await writeFile7(temporaryPath, options.content, {
7332
+ await writeFile8(temporaryPath, options.content, {
6862
7333
  encoding: "utf8",
6863
7334
  flag: "wx",
6864
7335
  mode: 384
@@ -7562,7 +8033,7 @@ ${SEARCH_HELP}` };
7562
8033
  }
7563
8034
 
7564
8035
  // src/projects/project-command.ts
7565
- import { parseArgs as parseArgs2 } from "util";
8036
+ import { parseArgs as parseArgs3 } from "util";
7566
8037
  var PROJECT_HELP = `One Project for your website and all its services.
7567
8038
 
7568
8039
  Usage:
@@ -7593,7 +8064,7 @@ async function runProjectCommand(options) {
7593
8064
  action
7594
8065
  ))
7595
8066
  throw new Error("Unknown Project command.");
7596
- const parsed = parseArgs2({
8067
+ const parsed = parseArgs3({
7597
8068
  args: args2,
7598
8069
  allowPositionals: true,
7599
8070
  strict: true,
@@ -7717,7 +8188,7 @@ async function runEnvironmentCommand(options) {
7717
8188
  action
7718
8189
  ))
7719
8190
  throw new Error("Unknown Project environment command.");
7720
- const { positionals, values } = parseArgs2({
8191
+ const { positionals, values } = parseArgs3({
7721
8192
  args: args2,
7722
8193
  allowPositionals: true,
7723
8194
  strict: true,
@@ -7824,14 +8295,14 @@ async function runEnvironmentCommand(options) {
7824
8295
  }
7825
8296
 
7826
8297
  // src/services/service-command.ts
7827
- import { readFile as readFile15, stat } from "fs/promises";
7828
- import path24 from "path";
7829
- import { parseArgs as parseArgs3 } from "util";
7830
- import { z as z13 } from "zod";
8298
+ import { readFile as readFile16, stat } from "fs/promises";
8299
+ import path25 from "path";
8300
+ import { parseArgs as parseArgs4 } from "util";
8301
+ import { z as z14 } from "zod";
7831
8302
 
7832
8303
  // src/services/trace-explorer-command.ts
7833
- import { z as z11 } from "zod";
7834
- var filters = [
8304
+ import { z as z12 } from "zod";
8305
+ var filters2 = [
7835
8306
  "environment",
7836
8307
  "provider",
7837
8308
  "event",
@@ -7850,16 +8321,16 @@ var TRACE_EXPLORER_FLAGS = {
7850
8321
  "ga4 show": ["environment"],
7851
8322
  "notifications show": ["environment"],
7852
8323
  "notifications destinations": ["environment", "cursor"],
7853
- destinations: filters,
7854
- events: filters,
7855
- properties: filters,
7856
- issues: [...filters, "container-id", "tag-id"],
7857
- observations: [...filters, "container-id", "tag-id", "result"],
8324
+ destinations: filters2,
8325
+ events: filters2,
8326
+ properties: filters2,
8327
+ issues: [...filters2, "container-id", "tag-id"],
8328
+ observations: [...filters2, "container-id", "tag-id", "result"],
7858
8329
  "issue show": ["environment", "id", "cursor"],
7859
8330
  "observation show": ["environment", "batch-id", "event-id"]
7860
8331
  };
7861
- var FilterValues = z11.object({
7862
- provider: z11.enum([
8332
+ var FilterValues = z12.object({
8333
+ provider: z12.enum([
7863
8334
  "siteos_analytics",
7864
8335
  "ga4",
7865
8336
  "google_ads",
@@ -7867,12 +8338,12 @@ var FilterValues = z11.object({
7867
8338
  "meta",
7868
8339
  "custom"
7869
8340
  ]).optional(),
7870
- event: z11.string().min(1).max(160).optional(),
7871
- property: z11.string().min(1).max(160).optional(),
7872
- "page-view": z11.string().uuid().optional(),
7873
- "container-id": z11.string().regex(/^GTM-[A-Z0-9]{4,20}$/u).optional(),
7874
- "tag-id": z11.string().regex(/^[0-9]{1,20}$/u).optional(),
7875
- result: z11.enum([
8341
+ event: z12.string().min(1).max(160).optional(),
8342
+ property: z12.string().min(1).max(160).optional(),
8343
+ "page-view": z12.string().uuid().optional(),
8344
+ "container-id": z12.string().regex(/^GTM-[A-Z0-9]{4,20}$/u).optional(),
8345
+ "tag-id": z12.string().regex(/^[0-9]{1,20}$/u).optional(),
8346
+ result: z12.enum([
7876
8347
  "success",
7877
8348
  "failure",
7878
8349
  "exception",
@@ -7885,8 +8356,8 @@ var FilterValues = z11.object({
7885
8356
  "beacon_accepted",
7886
8357
  "result_unknown"
7887
8358
  ]).optional(),
7888
- search: z11.string().max(160).optional(),
7889
- state: z11.enum([
8359
+ search: z12.string().max(160).optional(),
8360
+ state: z12.enum([
7890
8361
  "all",
7891
8362
  "active",
7892
8363
  "snoozed",
@@ -7896,8 +8367,8 @@ var FilterValues = z11.object({
7896
8367
  "tracked",
7897
8368
  "ignored"
7898
8369
  ]).optional(),
7899
- rule: z11.string().min(1).max(80).optional(),
7900
- kind: z11.enum([
8370
+ rule: z12.string().min(1).max(80).optional(),
8371
+ kind: z12.enum([
7901
8372
  "tag_execution",
7902
8373
  "data_layer",
7903
8374
  "fetch",
@@ -7908,8 +8379,8 @@ var FilterValues = z11.object({
7908
8379
  "heartbeat",
7909
8380
  "runtime_diagnostic"
7910
8381
  ]).optional(),
7911
- period: z11.enum(["24h", "7d"]).optional(),
7912
- cursor: z11.string().min(1).max(4096).optional()
8382
+ period: z12.enum(["24h", "7d"]).optional(),
8383
+ cursor: z12.string().min(1).max(4096).optional()
7913
8384
  });
7914
8385
  function traceExplorerSuffix(route, values) {
7915
8386
  if (!TRACE_EXPLORER_FLAGS[route]) return null;
@@ -7919,11 +8390,11 @@ function traceExplorerSuffix(route, values) {
7919
8390
  for (const key of keys) {
7920
8391
  const value = values[key];
7921
8392
  const plain = key === "id" && typeof value === "string" ? value.replace(/^trc_incident_/u, "") : value;
7922
- if (!z11.string().uuid().safeParse(plain).success)
8393
+ if (!z12.string().uuid().safeParse(plain).success)
7923
8394
  throw new Error(`Use --${key} with the UUID returned by Trace.`);
7924
8395
  }
7925
8396
  if (values.cursor !== void 0) {
7926
- if (!z11.string().uuid().safeParse(
8397
+ if (!z12.string().uuid().safeParse(
7927
8398
  typeof values.cursor === "string" ? values.cursor.replace(/^trc_finding_/u, "") : values.cursor
7928
8399
  ).success)
7929
8400
  throw new Error(
@@ -8047,7 +8518,7 @@ async function runServiceCommand(service, options) {
8047
8518
  if (!options.args.length || options.args.includes("--help") || options.args.includes("-h"))
8048
8519
  return { exitCode: 0, stdout: SERVICE_HELP[service] };
8049
8520
  try {
8050
- const { positionals, values } = parseArgs3({
8521
+ const { positionals, values } = parseArgs4({
8051
8522
  args: options.args,
8052
8523
  allowPositionals: true,
8053
8524
  strict: true,
@@ -8195,8 +8666,8 @@ async function runServiceCommand(service, options) {
8195
8666
  );
8196
8667
  const result2 = await response.json();
8197
8668
  if (!response.ok) {
8198
- const error = z13.object({
8199
- error: z13.object({ code: z13.string(), message: z13.string().max(500) })
8669
+ const error = z14.object({
8670
+ error: z14.object({ code: z14.string(), message: z14.string().max(500) })
8200
8671
  }).safeParse(result2);
8201
8672
  throw new SiteOSAuthApiError({
8202
8673
  code: error.success ? error.data.error.code : "SERVICE_REQUEST_FAILED",
@@ -8209,11 +8680,11 @@ async function runServiceCommand(service, options) {
8209
8680
  async function inputFile() {
8210
8681
  if (!values.input)
8211
8682
  throw new Error("This operation requires --input <json-file>.");
8212
- const filename = path24.resolve(options.cwd ?? process.cwd(), values.input);
8683
+ const filename = path25.resolve(options.cwd ?? process.cwd(), values.input);
8213
8684
  const info = await stat(filename);
8214
8685
  if (!info.isFile() || info.size > 512 * 1024)
8215
8686
  throw new Error("Use a JSON file smaller than 512 KB.");
8216
- return JSON.parse(await readFile15(filename, "utf8"));
8687
+ return JSON.parse(await readFile16(filename, "utf8"));
8217
8688
  }
8218
8689
  const site = common ? `/sites/${encodeURIComponent(common.resourceId)}` : "";
8219
8690
  let result;
@@ -8233,9 +8704,9 @@ async function runServiceCommand(service, options) {
8233
8704
  await inputFile(),
8234
8705
  "cookie:workspace:read"
8235
8706
  );
8236
- const validation = z13.object({
8237
- valid: z13.boolean(),
8238
- draftVersionMatches: z13.boolean().optional()
8707
+ const validation = z14.object({
8708
+ valid: z14.boolean(),
8709
+ draftVersionMatches: z14.boolean().optional()
8239
8710
  }).parse(result);
8240
8711
  if (!validation.valid || validation.draftVersionMatches === false)
8241
8712
  return { exitCode: 2, stdout: JSON.stringify(result, null, 2) };
@@ -8274,11 +8745,11 @@ async function runServiceCommand(service, options) {
8274
8745
  } else if (action === "installation")
8275
8746
  result = await request(`${site}/installation`);
8276
8747
  else if (action === "draft" && subaction === "get" && positionals.length === 2) {
8277
- const response = z13.object({
8278
- name: z13.string(),
8279
- hostname: z13.string(),
8280
- draftVersion: z13.number(),
8281
- draft: z13.unknown()
8748
+ const response = z14.object({
8749
+ name: z14.string(),
8750
+ hostname: z14.string(),
8751
+ draftVersion: z14.number(),
8752
+ draft: z14.unknown()
8282
8753
  }).parse(await request(site));
8283
8754
  result = {
8284
8755
  name: response.name,
@@ -8310,9 +8781,9 @@ async function runServiceCommand(service, options) {
8310
8781
  else if (action === "environments" && positionals.length === 1)
8311
8782
  result = await request(`${site}/environments`);
8312
8783
  else if (action === "ga4" || action === "notifications" || action === "schema" || action === "report" || action === "installation" || action === "tracking-plan" || explorerSuffix !== null) {
8313
- const response = z13.object({
8314
- environments: z13.array(
8315
- z13.object({ id: z13.string(), slug: z13.string() })
8784
+ const response = z14.object({
8785
+ environments: z14.array(
8786
+ z14.object({ id: z14.string(), slug: z14.string() })
8316
8787
  )
8317
8788
  }).parse(await request(`${site}/environments`));
8318
8789
  const environment = common.overview.project.environments.find(
@@ -8351,11 +8822,11 @@ async function runServiceCommand(service, options) {
8351
8822
  await inputFile()
8352
8823
  );
8353
8824
  } else if (action === "report" && positionals.length === 1) {
8354
- const detail = z13.object({
8355
- site: z13.object({
8356
- id: z13.literal(common.resourceId),
8357
- environments: z13.array(
8358
- z13.object({ id: z13.string(), evidence: z13.unknown() })
8825
+ const detail = z14.object({
8826
+ site: z14.object({
8827
+ id: z14.literal(common.resourceId),
8828
+ environments: z14.array(
8829
+ z14.object({ id: z14.string(), evidence: z14.unknown() })
8359
8830
  )
8360
8831
  })
8361
8832
  }).parse(await request(site));
@@ -8413,35 +8884,35 @@ async function runServiceCommand(service, options) {
8413
8884
  } catch (cause) {
8414
8885
  return {
8415
8886
  exitCode: cause instanceof SiteOSAuthApiError ? 1 : 2,
8416
- stderr: cause instanceof SiteOSAuthApiError || !(cause instanceof z13.ZodError) && cause instanceof Error ? cause.message : "The service returned an invalid response."
8887
+ stderr: cause instanceof SiteOSAuthApiError || !(cause instanceof z14.ZodError) && cause instanceof Error ? cause.message : "The service returned an invalid response."
8417
8888
  };
8418
8889
  }
8419
8890
  }
8420
8891
 
8421
8892
  // src/services/analytics-google-csv.ts
8422
- import { z as z14 } from "zod";
8423
- var table = z14.object({
8424
- dimensions: z14.array(z14.string()),
8425
- metrics: z14.array(z14.object({ name: z14.string() })),
8426
- rows: z14.array(
8427
- z14.object({ dimensions: z14.array(z14.string()), metrics: z14.array(z14.string()) })
8893
+ import { z as z15 } from "zod";
8894
+ var table = z15.object({
8895
+ dimensions: z15.array(z15.string()),
8896
+ metrics: z15.array(z15.object({ name: z15.string() })),
8897
+ rows: z15.array(
8898
+ z15.object({ dimensions: z15.array(z15.string()), metrics: z15.array(z15.string()) })
8428
8899
  )
8429
8900
  });
8430
8901
  function googleReportCsv(value, fetchedAt) {
8431
- const report = z14.object({
8432
- request: z14.object({
8433
- kind: z14.string(),
8434
- propertyId: z14.string(),
8435
- streamId: z14.string(),
8436
- startDate: z14.string(),
8437
- endDate: z14.string(),
8438
- filters: z14.array(z14.unknown()),
8439
- minuteRange: z14.unknown().optional(),
8440
- comparison: z14.object({ startDate: z14.string(), endDate: z14.string() }).optional()
8902
+ const report = z15.object({
8903
+ request: z15.object({
8904
+ kind: z15.string(),
8905
+ propertyId: z15.string(),
8906
+ streamId: z15.string(),
8907
+ startDate: z15.string(),
8908
+ endDate: z15.string(),
8909
+ filters: z15.array(z15.unknown()),
8910
+ minuteRange: z15.unknown().optional(),
8911
+ comparison: z15.object({ startDate: z15.string(), endDate: z15.string() }).optional()
8441
8912
  }).passthrough(),
8442
- timeZone: z14.string(),
8443
- limitations: z14.array(z14.string()),
8444
- quality: z14.unknown(),
8913
+ timeZone: z15.string(),
8914
+ limitations: z15.array(z15.string()),
8915
+ quality: z15.unknown(),
8445
8916
  table,
8446
8917
  previous: table.optional()
8447
8918
  }).parse(value);
@@ -8480,10 +8951,10 @@ function googleReportCsv(value, fetchedAt) {
8480
8951
  }
8481
8952
 
8482
8953
  // src/services/analytics-google-command.ts
8483
- import { readFile as readFile16, stat as stat2 } from "fs/promises";
8484
- import path25 from "path";
8485
- import { parseArgs as parseArgs4 } from "util";
8486
- import { z as z15 } from "zod";
8954
+ import { readFile as readFile17, stat as stat2 } from "fs/promises";
8955
+ import path26 from "path";
8956
+ import { parseArgs as parseArgs5 } from "util";
8957
+ import { z as z16 } from "zod";
8487
8958
  var GOOGLE_ANALYTICS_HELP = `Read GA4 reports in the selected Project environment.
8488
8959
 
8489
8960
  Usage:
@@ -8505,7 +8976,7 @@ async function runAnalyticsGoogleCommand(options) {
8505
8976
  if (options.args.length <= 1 || options.args.includes("--help"))
8506
8977
  return { exitCode: 0, stdout: GOOGLE_ANALYTICS_HELP };
8507
8978
  try {
8508
- const { values, positionals } = parseArgs4({
8979
+ const { values, positionals } = parseArgs5({
8509
8980
  args: options.args.slice(1),
8510
8981
  allowPositionals: true,
8511
8982
  strict: true,
@@ -8590,8 +9061,8 @@ async function runAnalyticsGoogleCommand(options) {
8590
9061
  );
8591
9062
  const value = await response.json();
8592
9063
  if (!response.ok) {
8593
- const error = z15.object({
8594
- error: z15.object({ code: z15.string(), message: z15.string().max(500) })
9064
+ const error = z16.object({
9065
+ error: z16.object({ code: z16.string(), message: z16.string().max(500) })
8595
9066
  }).safeParse(value);
8596
9067
  throw new SiteOSAuthApiError({
8597
9068
  code: error.success ? error.data.error.code : "ANALYTICS_REQUEST_FAILED",
@@ -8599,31 +9070,31 @@ async function runAnalyticsGoogleCommand(options) {
8599
9070
  status: response.status
8600
9071
  });
8601
9072
  }
8602
- return z15.object({
8603
- contractVersion: z15.literal(1),
8604
- resourceId: z15.literal(context.resourceId)
9073
+ return z16.object({
9074
+ contractVersion: z16.literal(1),
9075
+ resourceId: z16.literal(context.resourceId)
8605
9076
  }).passthrough().parse(value);
8606
9077
  };
8607
9078
  const file = async () => {
8608
9079
  if (!values.file)
8609
9080
  throw new Error("Provide --file with a report definition.");
8610
- const name = path25.resolve(options.cwd ?? process.cwd(), values.file);
9081
+ const name = path26.resolve(options.cwd ?? process.cwd(), values.file);
8611
9082
  if ((await stat2(name)).size > 16384)
8612
9083
  throw new Error("Definition exceeds 16 KiB.");
8613
- const text = await readFile16(name, "utf8");
9084
+ const text = await readFile17(name, "utf8");
8614
9085
  if (Buffer.byteLength(text) > 16384)
8615
9086
  throw new Error("Definition exceeds 16 KiB.");
8616
- return z15.record(z15.unknown()).parse(JSON.parse(text));
9087
+ return z16.record(z16.unknown()).parse(JSON.parse(text));
8617
9088
  };
8618
9089
  let result;
8619
9090
  if (action === "saved") {
8620
9091
  result = sub === "list" ? await send("/saved") : sub === "save" ? await send("/saved", "POST", await file()) : await send("/saved", "DELETE", {
8621
- id: z15.string().uuid().parse(positionals[2]),
8622
- revision: z15.number().int().positive().parse(Number(values.revision))
9092
+ id: z16.string().uuid().parse(positionals[2]),
9093
+ revision: z16.number().int().positive().parse(Number(values.revision))
8623
9094
  });
8624
9095
  } else {
8625
9096
  const base = await send("");
8626
- const binding = z15.object({ revision: z15.number().int().positive(), state: z15.string() }).parse(base.binding);
9097
+ const binding = z16.object({ revision: z16.number().int().positive(), state: z16.string() }).parse(base.binding);
8627
9098
  if (binding.state === "disconnected")
8628
9099
  throw new Error("Connect GA4 in Analytics Setup first.");
8629
9100
  if (action === "report") {
@@ -8656,16 +9127,16 @@ async function runAnalyticsGoogleCommand(options) {
8656
9127
  result = await send(`?${params}`);
8657
9128
  }
8658
9129
  } else if (action === "realtime") {
8659
- const filters2 = values.filters ? JSON.parse(values.filters) : [];
9130
+ const filters3 = values.filters ? JSON.parse(values.filters) : [];
8660
9131
  const params = new URLSearchParams({
8661
- filters: JSON.stringify(filters2)
9132
+ filters: JSON.stringify(filters3)
8662
9133
  });
8663
9134
  result = await send(`/realtime?${params}`);
8664
9135
  const live = result.realtime;
8665
9136
  if (!live?.report || live.stale) {
8666
9137
  await send("/realtime", "POST", {
8667
9138
  revision: binding.revision,
8668
- filters: filters2
9139
+ filters: filters3
8669
9140
  });
8670
9141
  result = await send(`/realtime?${params}`);
8671
9142
  }
@@ -8699,7 +9170,7 @@ async function runAnalyticsGoogleCommand(options) {
8699
9170
  } catch (cause) {
8700
9171
  const error = {
8701
9172
  code: cause instanceof SiteOSAuthApiError ? cause.code : "ANALYTICS_COMMAND_FAILED",
8702
- message: cause instanceof z15.ZodError ? "The input or server response does not match the GA4 contract." : cause instanceof Error ? cause.message : "GA4 request failed."
9173
+ message: cause instanceof z16.ZodError ? "The input or server response does not match the GA4 contract." : cause instanceof Error ? cause.message : "GA4 request failed."
8703
9174
  };
8704
9175
  return {
8705
9176
  exitCode: cause instanceof SiteOSAuthApiError ? 1 : 2,
@@ -8709,10 +9180,10 @@ async function runAnalyticsGoogleCommand(options) {
8709
9180
  }
8710
9181
 
8711
9182
  // src/services/analytics-command.ts
8712
- import { readFile as readFile17, stat as stat3 } from "fs/promises";
8713
- import path26 from "path";
8714
- import { parseArgs as parseArgs5 } from "util";
8715
- import { z as z16 } from "zod";
9183
+ import { readFile as readFile18, stat as stat3 } from "fs/promises";
9184
+ import path27 from "path";
9185
+ import { parseArgs as parseArgs6 } from "util";
9186
+ import { z as z17 } from "zod";
8716
9187
  var ANALYTICS_HELP = `Set up website Analytics in the selected Project environment.
8717
9188
 
8718
9189
  Usage:
@@ -8744,27 +9215,27 @@ Settings require an owner/admin, the current revision and at least one change.
8744
9215
  Catalog files are bounded JSON using the documented event/campaign/goal/funnel contracts.
8745
9216
  Monitoring preparation creates a Trace draft only; publication remains a separate operation.
8746
9217
  Analytics is Unlimited during early access. No synthetic events are sent by these commands.`;
8747
- var EventInput = z16.object({
8748
- name: z16.string().regex(/^[a-z][a-z0-9_]{0,63}$/u).refine((v) => v !== "pageview" && !v.startsWith("cookie_")),
8749
- label: z16.string().trim().min(1).max(80),
8750
- properties: z16.record(
8751
- z16.string().regex(/^[a-z][a-z0-9_]{0,39}$/u),
8752
- z16.array(
8753
- z16.string().min(1).max(80).regex(/^[a-zA-Z0-9 _./:-]+$/u)
9218
+ var EventInput = z17.object({
9219
+ name: z17.string().regex(/^[a-z][a-z0-9_]{0,63}$/u).refine((v) => v !== "pageview" && !v.startsWith("cookie_")),
9220
+ label: z17.string().trim().min(1).max(80),
9221
+ properties: z17.record(
9222
+ z17.string().regex(/^[a-z][a-z0-9_]{0,39}$/u),
9223
+ z17.array(
9224
+ z17.string().min(1).max(80).regex(/^[a-zA-Z0-9 _./:-]+$/u)
8754
9225
  ).min(1).max(20)
8755
9226
  ).refine((v) => Object.keys(v).length <= 8)
8756
9227
  }).strict();
8757
- var Resource = z16.object({
8758
- id: z16.string(),
8759
- organizationId: z16.string(),
8760
- name: z16.string(),
8761
- slug: z16.string(),
8762
- origin: z16.string().url(),
8763
- publicKey: z16.string(),
8764
- revision: z16.number().int().positive(),
8765
- enabled: z16.boolean(),
8766
- cookieEvents: z16.boolean(),
8767
- minimalRealtime: z16.boolean()
9228
+ var Resource = z17.object({
9229
+ id: z17.string(),
9230
+ organizationId: z17.string(),
9231
+ name: z17.string(),
9232
+ slug: z17.string(),
9233
+ origin: z17.string().url(),
9234
+ publicKey: z17.string(),
9235
+ revision: z17.number().int().positive(),
9236
+ enabled: z17.boolean(),
9237
+ cookieEvents: z17.boolean(),
9238
+ minimalRealtime: z17.boolean()
8768
9239
  });
8769
9240
  var readKeys = [
8770
9241
  "days",
@@ -8816,7 +9287,7 @@ async function runAnalyticsCommand(options) {
8816
9287
  if (options.args[0] === "ga4") return runAnalyticsGoogleCommand(options);
8817
9288
  const json = options.args.includes("--json");
8818
9289
  try {
8819
- const { positionals, values } = parseArgs5({
9290
+ const { positionals, values } = parseArgs6({
8820
9291
  args: options.args,
8821
9292
  strict: true,
8822
9293
  allowPositionals: true,
@@ -8898,7 +9369,7 @@ async function runAnalyticsCommand(options) {
8898
9369
  throw new Error("Use --days 1, 7 or 28.");
8899
9370
  if (values.country && !/^(?:[A-Z]{2}|unknown)$/u.test(values.country))
8900
9371
  throw new Error("Use an uppercase ISO country code or unknown.");
8901
- if (values.campaign) z16.string().uuid().parse(values.campaign);
9372
+ if (values.campaign) z17.string().uuid().parse(values.campaign);
8902
9373
  const setting = route === "settings set", creating = positionals[1] === "create", archive = positionals[1] === "archive";
8903
9374
  let body;
8904
9375
  if (setting) {
@@ -8922,10 +9393,10 @@ async function runAnalyticsCommand(options) {
8922
9393
  } else if (creating) {
8923
9394
  if (!values.file)
8924
9395
  throw new Error("Creation requires --file with a JSON definition.");
8925
- const filename = path26.resolve(options.cwd ?? process.cwd(), values.file);
9396
+ const filename = path27.resolve(options.cwd ?? process.cwd(), values.file);
8926
9397
  if ((await stat3(filename)).size > 16384)
8927
9398
  throw new Error("The definition must not exceed 16 KiB.");
8928
- const text = await readFile17(filename, "utf8");
9399
+ const text = await readFile18(filename, "utf8");
8929
9400
  if (Buffer.byteLength(text) > 16384)
8930
9401
  throw new Error("The definition must not exceed 16 KiB.");
8931
9402
  let definition;
@@ -8934,9 +9405,9 @@ async function runAnalyticsCommand(options) {
8934
9405
  } catch {
8935
9406
  throw new Error("The definition must contain valid JSON.");
8936
9407
  }
8937
- body = z16.record(z16.unknown()).parse(definition);
9408
+ body = z17.record(z17.unknown()).parse(definition);
8938
9409
  if (action === "events") body = EventInput.parse(body);
8939
- } else if (archive) body = { id: z16.string().uuid().parse(positionals[2]) };
9410
+ } else if (archive) body = { id: z17.string().uuid().parse(positionals[2]) };
8940
9411
  const context = await commonServiceContext(
8941
9412
  options,
8942
9413
  "analytics",
@@ -8983,8 +9454,8 @@ async function runAnalyticsCommand(options) {
8983
9454
  );
8984
9455
  const value = await response.json();
8985
9456
  if (!response.ok) {
8986
- const error = z16.object({
8987
- error: z16.object({ code: z16.string(), message: z16.string().max(500) })
9457
+ const error = z17.object({
9458
+ error: z17.object({ code: z17.string(), message: z17.string().max(500) })
8988
9459
  }).safeParse(value);
8989
9460
  throw new SiteOSAuthApiError({
8990
9461
  code: error.success ? error.data.error.code : "ANALYTICS_REQUEST_FAILED",
@@ -8992,9 +9463,9 @@ async function runAnalyticsCommand(options) {
8992
9463
  status: response.status
8993
9464
  });
8994
9465
  }
8995
- const record = z16.object({
8996
- contractVersion: z16.literal(1),
8997
- resourceId: z16.literal(context.resourceId)
9466
+ const record = z17.object({
9467
+ contractVersion: z17.literal(1),
9468
+ resourceId: z17.literal(context.resourceId)
8998
9469
  }).passthrough().parse(value);
8999
9470
  let output;
9000
9471
  if (setting) {
@@ -9013,16 +9484,16 @@ async function runAnalyticsCommand(options) {
9013
9484
  throw new Error("The saved event does not match this definition.");
9014
9485
  } else
9015
9486
  output = {
9016
- id: z16.string().uuid().parse(record.id),
9487
+ id: z17.string().uuid().parse(record.id),
9017
9488
  ...pick(
9018
9489
  record,
9019
9490
  action === "campaigns" ? ["label", "source", "medium", "campaign"] : action === "goals" ? ["label", "match"] : ["label", "steps"]
9020
9491
  )
9021
9492
  };
9022
9493
  } else if (archive)
9023
- output = { archived: z16.literal(true).parse(record.archived) };
9494
+ output = { archived: z17.literal(true).parse(record.archived) };
9024
9495
  else if (route === "monitoring prepare")
9025
- output = { state: z16.literal("prepared").parse(record.state) };
9496
+ output = { state: z17.literal("prepared").parse(record.state) };
9026
9497
  else if (action === "realtime") output = pick(record, liveKeys);
9027
9498
  else {
9028
9499
  const resource = Resource.parse(record.resource);
@@ -9034,8 +9505,8 @@ async function runAnalyticsCommand(options) {
9034
9505
  output = {
9035
9506
  resource,
9036
9507
  lastReceivedAt: record.lastReceivedAt,
9037
- consentSource: z16.object({
9038
- consentSource: z16.enum([
9508
+ consentSource: z17.object({
9509
+ consentSource: z17.enum([
9039
9510
  "cookie",
9040
9511
  "external",
9041
9512
  "waiting_for_cookie",
@@ -9047,11 +9518,11 @@ async function runAnalyticsCommand(options) {
9047
9518
  else if (action === "installation")
9048
9519
  output = {
9049
9520
  resource,
9050
- installation: z16.string().parse(record.installation),
9521
+ installation: z17.string().parse(record.installation),
9051
9522
  configuration: record.configuration
9052
9523
  };
9053
9524
  else if (action === "events") {
9054
- const definitions = z16.array(EventInput).parse(record.definitions);
9525
+ const definitions = z17.array(EventInput).parse(record.definitions);
9055
9526
  if (route === "events snippet") {
9056
9527
  const definition = definitions.find((d) => d.name === positionals[2]);
9057
9528
  if (!definition)
@@ -9065,13 +9536,13 @@ async function runAnalyticsCommand(options) {
9065
9536
  };
9066
9537
  } else output = { definitions, eventCounts: record.eventCounts };
9067
9538
  } else
9068
- output = action === "report" ? pick(record, readKeys) : { [action]: z16.array(z16.unknown()).parse(record[action]) };
9539
+ output = action === "report" ? pick(record, readKeys) : { [action]: z17.array(z17.unknown()).parse(record[action]) };
9069
9540
  }
9070
9541
  return { exitCode: 0, stdout: JSON.stringify(output, null, 2) };
9071
9542
  } catch (cause) {
9072
9543
  const error = cause instanceof SiteOSAuthApiError ? { code: cause.code, message: cause.message } : {
9073
9544
  code: "ANALYTICS_COMMAND_FAILED",
9074
- message: cause instanceof z16.ZodError ? "The Analytics input or response does not match the supported contract." : cause instanceof Error ? cause.message : "The Analytics command failed."
9545
+ message: cause instanceof z17.ZodError ? "The Analytics input or response does not match the supported contract." : cause instanceof Error ? cause.message : "The Analytics command failed."
9075
9546
  };
9076
9547
  return {
9077
9548
  exitCode: cause instanceof SiteOSAuthApiError ? 1 : 2,
@@ -9081,13 +9552,13 @@ async function runAnalyticsCommand(options) {
9081
9552
  }
9082
9553
 
9083
9554
  // src/services/seo-repair-command.ts
9084
- import { parseArgs as parseArgs6 } from "util";
9085
- import { z as z18 } from "zod";
9555
+ import { parseArgs as parseArgs7 } from "util";
9556
+ import { z as z19 } from "zod";
9086
9557
 
9087
9558
  // src/services/seo-report-client.ts
9088
- import { open, writeFile as writeFile8 } from "fs/promises";
9089
- import path27 from "path";
9090
- import { z as z17 } from "zod";
9559
+ import { open, writeFile as writeFile9 } from "fs/promises";
9560
+ import path28 from "path";
9561
+ import { z as z18 } from "zod";
9091
9562
  async function seoReportClient(options, environment) {
9092
9563
  const context = await commonServiceContext(options, "seo", environment);
9093
9564
  if (!context)
@@ -9122,8 +9593,8 @@ async function seoReportClient(options, environment) {
9122
9593
  }
9123
9594
  );
9124
9595
  if (!response.ok) {
9125
- const result = z17.object({
9126
- error: z17.object({ code: z17.string(), message: z17.string().max(500) })
9596
+ const result = z18.object({
9597
+ error: z18.object({ code: z18.string(), message: z18.string().max(500) })
9127
9598
  }).safeParse(await response.json());
9128
9599
  throw new SiteOSAuthApiError({
9129
9600
  code: result.success ? result.data.error.code : "SEO_REQUEST_FAILED",
@@ -9137,9 +9608,9 @@ async function seoReportClient(options, environment) {
9137
9608
  }
9138
9609
  };
9139
9610
  }
9140
- var versionedReport = z17.object({ contractVersion: z17.literal(1) }).passthrough();
9611
+ var versionedReport = z18.object({ contractVersion: z18.literal(1) }).passthrough();
9141
9612
  async function readSeoInput(cwd, filename) {
9142
- const file = await open(path27.resolve(cwd ?? process.cwd(), filename), "r");
9613
+ const file = await open(path28.resolve(cwd ?? process.cwd(), filename), "r");
9143
9614
  try {
9144
9615
  const stat4 = await file.stat();
9145
9616
  if (!stat4.isFile() || stat4.size > 32e3)
@@ -9163,14 +9634,14 @@ async function readSeoInput(cwd, filename) {
9163
9634
  }
9164
9635
  }
9165
9636
  async function writeSeoReport(options, filename, content) {
9166
- const output = path27.resolve(options.cwd ?? process.cwd(), filename);
9167
- await writeFile8(output, content, { flag: "wx", mode: 384 });
9637
+ const output = path28.resolve(options.cwd ?? process.cwd(), filename);
9638
+ await writeFile9(output, content, { flag: "wx", mode: 384 });
9168
9639
  return output;
9169
9640
  }
9170
9641
  function seoReportFailure(cause, json, idempotencyKey) {
9171
9642
  const error = {
9172
9643
  code: cause instanceof SiteOSAuthApiError ? cause.code : "SEO_COMMAND_FAILED",
9173
- message: cause instanceof z17.ZodError ? "The SEO service returned an invalid response." : cause instanceof Error ? cause.message : "The SEO command failed."
9644
+ message: cause instanceof z18.ZodError ? "The SEO service returned an invalid response." : cause instanceof Error ? cause.message : "The SEO command failed."
9174
9645
  };
9175
9646
  return {
9176
9647
  exitCode: cause instanceof SiteOSAuthApiError ? 1 : 2,
@@ -9189,7 +9660,7 @@ function seoReportFailure(cause, json, idempotencyKey) {
9189
9660
  async function runSeoRepairCommand(options) {
9190
9661
  const json = options.args.includes("--json");
9191
9662
  try {
9192
- const { positionals, values } = parseArgs6({
9663
+ const { positionals, values } = parseArgs7({
9193
9664
  args: options.args,
9194
9665
  allowPositionals: true,
9195
9666
  strict: true,
@@ -9234,32 +9705,32 @@ async function runSeoRepairCommand(options) {
9234
9705
  });
9235
9706
  const record = versionedReport.parse(await response.json());
9236
9707
  if (recheck) {
9237
- z18.object({
9238
- id: z18.string(),
9239
- resourceId: z18.literal(client.resourceId),
9240
- organizationId: z18.literal(client.organizationId),
9241
- state: z18.literal("queued")
9708
+ z19.object({
9709
+ id: z19.string(),
9710
+ resourceId: z19.literal(client.resourceId),
9711
+ organizationId: z19.literal(client.organizationId),
9712
+ state: z19.literal("queued")
9242
9713
  }).parse(record.audit);
9243
9714
  return { exitCode: 0, stdout: JSON.stringify(record, null, 2) };
9244
9715
  }
9245
- const brief = z18.object({
9246
- schemaVersion: z18.literal(1),
9247
- context: z18.object({
9248
- auditId: z18.literal(values.audit),
9249
- resourceId: z18.literal(client.resourceId),
9250
- organizationId: z18.literal(client.organizationId),
9251
- selectedUrls: z18.array(z18.string()).min(1).max(20),
9252
- ruleId: z18.literal(values.rule ?? null)
9716
+ const brief = z19.object({
9717
+ schemaVersion: z19.literal(1),
9718
+ context: z19.object({
9719
+ auditId: z19.literal(values.audit),
9720
+ resourceId: z19.literal(client.resourceId),
9721
+ organizationId: z19.literal(client.organizationId),
9722
+ selectedUrls: z19.array(z19.string()).min(1).max(20),
9723
+ ruleId: z19.literal(values.rule ?? null)
9253
9724
  }),
9254
- evidence: z18.array(
9255
- z18.object({
9256
- url: z18.string(),
9257
- findings: z18.array(z18.unknown()).max(12)
9725
+ evidence: z19.array(
9726
+ z19.object({
9727
+ url: z19.string(),
9728
+ findings: z19.array(z19.unknown()).max(12)
9258
9729
  })
9259
9730
  ).min(1).max(20),
9260
- suggestedGroups: z18.array(z18.unknown()),
9261
- verificationCommand: z18.string().min(1),
9262
- text: z18.string().min(1)
9731
+ suggestedGroups: z19.array(z19.unknown()),
9732
+ verificationCommand: z19.string().min(1),
9733
+ text: z19.string().min(1)
9263
9734
  }).parse(record);
9264
9735
  const canonical = (value) => {
9265
9736
  const url = new URL(value);
@@ -9279,16 +9750,16 @@ async function runSeoRepairCommand(options) {
9279
9750
  }
9280
9751
 
9281
9752
  // src/services/seo-command.ts
9282
- import { writeFile as writeFile10 } from "fs/promises";
9283
- import path29 from "path";
9284
- import { parseArgs as parseArgs10 } from "util";
9285
- import { z as z22 } from "zod";
9753
+ import { writeFile as writeFile11 } from "fs/promises";
9754
+ import path30 from "path";
9755
+ import { parseArgs as parseArgs11 } from "util";
9756
+ import { z as z23 } from "zod";
9286
9757
 
9287
9758
  // src/services/seo-research-command.ts
9288
9759
  import { randomUUID as randomUUID6 } from "crypto";
9289
9760
  import { setTimeout as setTimeout2 } from "timers/promises";
9290
- import { isDeepStrictEqual, parseArgs as parseArgs7 } from "util";
9291
- import { z as z19 } from "zod";
9761
+ import { isDeepStrictEqual, parseArgs as parseArgs8 } from "util";
9762
+ import { z as z20 } from "zod";
9292
9763
  var RESEARCH_HELP = `
9293
9764
  siteos seo research summary [--environment <slug>] [--json]
9294
9765
  siteos seo research status --kind <kind> [--environment <slug>] [--json]
@@ -9335,11 +9806,11 @@ var kinds = [
9335
9806
  ];
9336
9807
  var sections = [...kinds, "ai-rankings"];
9337
9808
  var sectionOf = (request) => request.kind === "ai-visibility" && request.category ? "ai-rankings" : request.kind;
9338
- var requestSchema = z19.object({
9339
- kind: z19.enum(["domain", ...kinds]).transform((kind) => kind === "domain" ? "competitors" : kind),
9340
- target: z19.string().min(1).max(253)
9809
+ var requestSchema = z20.object({
9810
+ kind: z20.enum(["domain", ...kinds]).transform((kind) => kind === "domain" ? "competitors" : kind),
9811
+ target: z20.string().min(1).max(253)
9341
9812
  }).passthrough();
9342
- var runStates = z19.enum([
9813
+ var runStates = z20.enum([
9343
9814
  "queued",
9344
9815
  "running",
9345
9816
  "completed",
@@ -9355,7 +9826,7 @@ var csvCell = (value) => {
9355
9826
  async function runSeoResearchCommand(options) {
9356
9827
  let idempotencyKey;
9357
9828
  try {
9358
- const { values, positionals } = parseArgs7({
9829
+ const { values, positionals } = parseArgs8({
9359
9830
  args: options.args.slice(1),
9360
9831
  strict: true,
9361
9832
  allowPositionals: true,
@@ -9374,7 +9845,7 @@ async function runSeoResearchCommand(options) {
9374
9845
  }
9375
9846
  });
9376
9847
  const action = ["saved", "serp"].includes(positionals[0] ?? "") ? positionals.slice(0, 2).join(" ") : positionals[0] ?? "";
9377
- const id = positionals[action.includes(" ") ? 2 : 1];
9848
+ const id2 = positionals[action.includes(" ") ? 2 : 1];
9378
9849
  const operations = {
9379
9850
  "serp show": { args: 3, flags: ["keyword"] },
9380
9851
  "serp ensure": { args: 3, flags: ["keyword"] },
@@ -9437,26 +9908,26 @@ async function runSeoResearchCommand(options) {
9437
9908
  );
9438
9909
  }
9439
9910
  const client = await seoReportClient(options, values.environment);
9440
- const resourceSchema = z19.object({
9441
- id: z19.literal(client.resourceId),
9442
- organizationId: z19.literal(client.organizationId)
9911
+ const resourceSchema = z20.object({
9912
+ id: z20.literal(client.resourceId),
9913
+ organizationId: z20.literal(client.organizationId)
9443
9914
  }).passthrough();
9444
- const runSchema = z19.object({
9445
- id: z19.string(),
9446
- resourceId: z19.literal(client.resourceId),
9447
- organizationId: z19.literal(client.organizationId),
9448
- websiteUrl: z19.string(),
9915
+ const runSchema = z20.object({
9916
+ id: z20.string(),
9917
+ resourceId: z20.literal(client.resourceId),
9918
+ organizationId: z20.literal(client.organizationId),
9919
+ websiteUrl: z20.string(),
9449
9920
  request: requestSchema,
9450
9921
  state: runStates,
9451
- createdAt: z19.string(),
9452
- finishedAt: z19.string().nullable(),
9453
- parts: z19.array(
9454
- z19.object({
9455
- key: z19.string(),
9456
- state: z19.enum(["completed", "failed"]),
9457
- error: z19.string().nullable(),
9458
- dataset: z19.record(z19.unknown()).nullable(),
9459
- observedAt: z19.string()
9922
+ createdAt: z20.string(),
9923
+ finishedAt: z20.string().nullable(),
9924
+ parts: z20.array(
9925
+ z20.object({
9926
+ key: z20.string(),
9927
+ state: z20.enum(["completed", "failed"]),
9928
+ error: z20.string().nullable(),
9929
+ dataset: z20.record(z20.unknown()).nullable(),
9930
+ observedAt: z20.string()
9460
9931
  }).passthrough()
9461
9932
  )
9462
9933
  }).passthrough();
@@ -9470,41 +9941,41 @@ async function runSeoResearchCommand(options) {
9470
9941
  const query = `?kind=${encodeURIComponent(values.kind ?? "rankings")}`;
9471
9942
  let record;
9472
9943
  if (action.startsWith("serp ")) {
9473
- const snapshotSchema = z19.object({
9474
- id: z19.string(),
9475
- organizationId: z19.literal(client.organizationId),
9476
- resourceId: z19.literal(client.resourceId),
9477
- sourceRunId: z19.literal(id),
9944
+ const snapshotSchema = z20.object({
9945
+ id: z20.string(),
9946
+ organizationId: z20.literal(client.organizationId),
9947
+ resourceId: z20.literal(client.resourceId),
9948
+ sourceRunId: z20.literal(id2),
9478
9949
  request: requestSchema,
9479
- keywordKey: z19.literal(
9950
+ keywordKey: z20.literal(
9480
9951
  values.keyword.normalize("NFKC").trim().toLowerCase().replace(/\s+/gu, " ")
9481
9952
  ),
9482
- state: z19.enum([
9953
+ state: z20.enum([
9483
9954
  "queued",
9484
9955
  "running",
9485
9956
  "completed",
9486
9957
  "failed",
9487
9958
  "cancelled"
9488
9959
  ]),
9489
- dataset: z19.object({
9490
- type: z19.literal("serp"),
9491
- keyword: z19.string(),
9492
- country: z19.string(),
9493
- language: z19.string(),
9494
- device: z19.enum(["desktop", "mobile"]),
9495
- observedAt: z19.string(),
9496
- rows: z19.array(
9497
- z19.object({
9498
- position: z19.number(),
9499
- title: z19.string(),
9500
- url: z19.string(),
9501
- domain: z19.string(),
9502
- description: z19.string()
9960
+ dataset: z20.object({
9961
+ type: z20.literal("serp"),
9962
+ keyword: z20.string(),
9963
+ country: z20.string(),
9964
+ language: z20.string(),
9965
+ device: z20.enum(["desktop", "mobile"]),
9966
+ observedAt: z20.string(),
9967
+ rows: z20.array(
9968
+ z20.object({
9969
+ position: z20.number(),
9970
+ title: z20.string(),
9971
+ url: z20.string(),
9972
+ domain: z20.string(),
9973
+ description: z20.string()
9503
9974
  })
9504
9975
  )
9505
9976
  }).nullable()
9506
9977
  }).passthrough();
9507
- const suffix = `/runs/${encodeURIComponent(id)}/serp`;
9978
+ const suffix = `/runs/${encodeURIComponent(id2)}/serp`;
9508
9979
  const read = () => get(`${suffix}?keyword=${encodeURIComponent(values.keyword)}`);
9509
9980
  record = action === "serp ensure" ? await get(suffix, "run", { keyword: values.keyword }) : await read();
9510
9981
  const deadline = Date.now() + timeout * 1e3;
@@ -9543,7 +10014,7 @@ async function runSeoResearchCommand(options) {
9543
10014
  "description"
9544
10015
  ],
9545
10016
  ...(data?.rows.length ? data.rows : [null]).map((row) => [
9546
- id,
10017
+ id2,
9547
10018
  values.keyword,
9548
10019
  data?.country,
9549
10020
  data?.language,
@@ -9560,7 +10031,7 @@ async function runSeoResearchCommand(options) {
9560
10031
  const output = await writeSeoReport(options, values.output, content);
9561
10032
  record = {
9562
10033
  contractVersion: 1,
9563
- runId: id,
10034
+ runId: id2,
9564
10035
  keyword: values.keyword,
9565
10036
  state: snapshot.state,
9566
10037
  format: values.format,
@@ -9573,18 +10044,18 @@ async function runSeoResearchCommand(options) {
9573
10044
  };
9574
10045
  }
9575
10046
  if (action === "retry") {
9576
- const source = await get(`/runs/${encodeURIComponent(id)}`);
10047
+ const source = await get(`/runs/${encodeURIComponent(id2)}`);
9577
10048
  resourceSchema.parse(source.resource);
9578
10049
  const original = runSchema.parse(source.run);
9579
- if (original.id !== id || ["queued", "running"].includes(original.state))
10050
+ if (original.id !== id2 || ["queued", "running"].includes(original.state))
9580
10051
  throw new Error("Choose the exact stopped research report to retry.");
9581
10052
  record = await get("/runs", "run", {
9582
10053
  request: original.request,
9583
- retryOf: id,
10054
+ retryOf: id2,
9584
10055
  idempotencyKey
9585
10056
  });
9586
10057
  const next = runSchema.parse(record.run);
9587
- if (next.retryOf !== id || !isDeepStrictEqual(next.request, original.request))
10058
+ if (next.retryOf !== id2 || !isDeepStrictEqual(next.request, original.request))
9588
10059
  throw new Error(
9589
10060
  "The continued check does not match the original report."
9590
10061
  );
@@ -9609,9 +10080,9 @@ async function runSeoResearchCommand(options) {
9609
10080
  name: values.name.trim(),
9610
10081
  ...values.id ? { id: values.id } : {}
9611
10082
  });
9612
- const saved = z19.object({
9613
- id: z19.string(),
9614
- name: z19.literal(values.name.trim()),
10083
+ const saved = z20.object({
10084
+ id: z20.string(),
10085
+ name: z20.literal(values.name.trim()),
9615
10086
  request: requestSchema
9616
10087
  }).parse(record.saved);
9617
10088
  if (values.id && saved.id !== values.id || !isDeepStrictEqual(saved.request, plan.request))
@@ -9621,27 +10092,27 @@ async function runSeoResearchCommand(options) {
9621
10092
  } else record = plan;
9622
10093
  } else if (action === "cancel" || action === "saved remove") {
9623
10094
  record = await get(
9624
- `/${action === "cancel" ? "runs" : "saved"}/${encodeURIComponent(id)}/${action === "cancel" ? "cancel" : "remove"}`,
10095
+ `/${action === "cancel" ? "runs" : "saved"}/${encodeURIComponent(id2)}/${action === "cancel" ? "cancel" : "remove"}`,
9625
10096
  action === "cancel" ? "run" : "write",
9626
10097
  {}
9627
10098
  );
9628
- z19.literal(true).parse(
10099
+ z20.literal(true).parse(
9629
10100
  record[action === "cancel" ? "cancelled" : "removed"]
9630
10101
  );
9631
10102
  } else if (action === "summary") {
9632
10103
  record = await get("/summary");
9633
10104
  resourceSchema.parse(record.resource);
9634
- z19.array(z19.object({ kind: z19.enum(sections), summary: z19.unknown() })).parse(
10105
+ z20.array(z20.object({ kind: z20.enum(sections), summary: z20.unknown() })).parse(
9635
10106
  record.checks
9636
10107
  );
9637
10108
  } else if (["status", "history", "saved list"].includes(action)) {
9638
10109
  const view = await get(query);
9639
10110
  resourceSchema.parse(view.resource);
9640
- const runs = z19.array(runSchema).parse(view.runs);
9641
- const saved = z19.array(
9642
- z19.object({
9643
- id: z19.string(),
9644
- name: z19.string(),
10111
+ const runs = z20.array(runSchema).parse(view.runs);
10112
+ const saved = z20.array(
10113
+ z20.object({
10114
+ id: z20.string(),
10115
+ name: z20.string(),
9645
10116
  request: requestSchema
9646
10117
  }).passthrough()
9647
10118
  ).parse(view.saved);
@@ -9663,10 +10134,10 @@ async function runSeoResearchCommand(options) {
9663
10134
  } else {
9664
10135
  const deadline = Date.now() + timeout * 1e3;
9665
10136
  while (true) {
9666
- record = await get(`/runs/${encodeURIComponent(id)}`);
10137
+ record = await get(`/runs/${encodeURIComponent(id2)}`);
9667
10138
  resourceSchema.parse(record.resource);
9668
10139
  const run = runSchema.parse(record.run);
9669
- if (run.id !== id)
10140
+ if (run.id !== id2)
9670
10141
  throw new Error(
9671
10142
  "The response does not match the selected research check."
9672
10143
  );
@@ -9756,7 +10227,7 @@ async function runSeoResearchCommand(options) {
9756
10227
  const output = await writeSeoReport(options, values.output, content);
9757
10228
  record = {
9758
10229
  contractVersion: 1,
9759
- runId: id,
10230
+ runId: id2,
9760
10231
  state: run.state,
9761
10232
  format: values.format,
9762
10233
  output
@@ -9776,8 +10247,8 @@ async function runSeoResearchCommand(options) {
9776
10247
  }
9777
10248
 
9778
10249
  // src/services/seo-gsc-command.ts
9779
- import { parseArgs as parseArgs8 } from "util";
9780
- import { z as z20 } from "zod";
10250
+ import { parseArgs as parseArgs9 } from "util";
10251
+ import { z as z21 } from "zod";
9781
10252
  var GSC_HELP = `
9782
10253
  siteos seo gsc status [--environment <slug>] [--json]
9783
10254
  siteos seo gsc report [--dataset <pages|queries>] [--query <text>] [--filter <all|issues|declining>] [--sort <clicks|change|impressions>] [--page <number>] [--url <page-url>] [--environment <slug>] [--json]
@@ -9795,7 +10266,7 @@ Bind/disconnect require a current revision and separate settings authority. Disc
9795
10266
  `;
9796
10267
  async function runSeoGscCommand(options) {
9797
10268
  try {
9798
- const { values, positionals } = parseArgs8({
10269
+ const { values, positionals } = parseArgs9({
9799
10270
  args: options.args.slice(1),
9800
10271
  strict: true,
9801
10272
  allowPositionals: true,
@@ -9877,13 +10348,13 @@ async function runSeoGscCommand(options) {
9877
10348
  `seo:search:${action === "sync" ? "sync" : writing ? "write" : "read"}`,
9878
10349
  body
9879
10350
  );
9880
- const runSchema = z20.object({
9881
- id: z20.string(),
9882
- resourceId: z20.literal(client.resourceId),
9883
- organizationId: z20.literal(client.organizationId),
9884
- websiteUrl: z20.string(),
9885
- siteUrl: z20.string(),
9886
- state: z20.enum([
10351
+ const runSchema = z21.object({
10352
+ id: z21.string(),
10353
+ resourceId: z21.literal(client.resourceId),
10354
+ organizationId: z21.literal(client.organizationId),
10355
+ websiteUrl: z21.string(),
10356
+ siteUrl: z21.string(),
10357
+ state: z21.enum([
9887
10358
  "queued",
9888
10359
  "running",
9889
10360
  "completed",
@@ -9891,32 +10362,32 @@ async function runSeoGscCommand(options) {
9891
10362
  "failed",
9892
10363
  "cancelled"
9893
10364
  ]),
9894
- dates: z20.unknown()
10365
+ dates: z21.unknown()
9895
10366
  }).passthrough();
9896
- const bindingSchema = z20.object({
9897
- resourceId: z20.literal(client.resourceId),
9898
- organizationId: z20.literal(client.organizationId),
9899
- websiteUrl: z20.string(),
9900
- siteUrl: z20.string(),
9901
- revision: z20.number().int().positive()
10367
+ const bindingSchema = z21.object({
10368
+ resourceId: z21.literal(client.resourceId),
10369
+ organizationId: z21.literal(client.organizationId),
10370
+ websiteUrl: z21.string(),
10371
+ siteUrl: z21.string(),
10372
+ revision: z21.number().int().positive()
9902
10373
  }).passthrough();
9903
- const metrics = z20.object({
9904
- clicks: z20.number(),
9905
- impressions: z20.number(),
9906
- ctr: z20.number(),
9907
- position: z20.number()
10374
+ const metrics = z21.object({
10375
+ clicks: z21.number(),
10376
+ impressions: z21.number(),
10377
+ ctr: z21.number(),
10378
+ position: z21.number()
9908
10379
  }).passthrough().nullable();
9909
10380
  const validateView = (data) => {
9910
10381
  const record2 = versionedReport.parse(data);
9911
- z20.literal(client.resourceId).parse(record2.resourceId);
10382
+ z21.literal(client.resourceId).parse(record2.resourceId);
9912
10383
  bindingSchema.nullable().parse(record2.binding);
9913
10384
  runSchema.nullable().parse(record2.latest);
9914
10385
  runSchema.nullable().parse(record2.report);
9915
- z20.array(
9916
- z20.object({ key: z20.string(), current: metrics, previous: metrics }).passthrough()
10386
+ z21.array(
10387
+ z21.object({ key: z21.string(), current: metrics, previous: metrics }).passthrough()
9917
10388
  ).parse(record2.rows);
9918
- z20.number().int().nonnegative().parse(record2.total);
9919
- z20.literal(values.dataset ?? "pages").parse(record2.dataset);
10389
+ z21.number().int().nonnegative().parse(record2.total);
10390
+ z21.literal(values.dataset ?? "pages").parse(record2.dataset);
9920
10391
  return record2;
9921
10392
  };
9922
10393
  if (action === "export") {
@@ -9932,9 +10403,9 @@ async function runSeoGscCommand(options) {
9932
10403
  const text = await response.text();
9933
10404
  if (values.format === "json") {
9934
10405
  const report = validateView(JSON.parse(text));
9935
- z20.literal(reportId).parse(runSchema.parse(report.report).id);
9936
- z20.array(z20.unknown()).length(rows).parse(report.rows);
9937
- z20.literal(truncated === "true").parse(report.truncated);
10406
+ z21.literal(reportId).parse(runSchema.parse(report.report).id);
10407
+ z21.array(z21.unknown()).length(rows).parse(report.rows);
10408
+ z21.literal(truncated === "true").parse(report.truncated);
9938
10409
  }
9939
10410
  const output = await writeSeoReport(options, values.output, text);
9940
10411
  return {
@@ -9955,7 +10426,7 @@ async function runSeoGscCommand(options) {
9955
10426
  };
9956
10427
  }
9957
10428
  const record = versionedReport.parse(await response.json());
9958
- if (action === "disconnect") z20.literal(true).parse(record.unbound);
10429
+ if (action === "disconnect") z21.literal(true).parse(record.unbound);
9959
10430
  else if (writing) {
9960
10431
  runSchema.parse(record.run);
9961
10432
  if (action === "bind") {
@@ -9974,11 +10445,11 @@ async function runSeoGscCommand(options) {
9974
10445
 
9975
10446
  // src/services/seo-performance-command.ts
9976
10447
  import { randomUUID as randomUUID7 } from "crypto";
9977
- import { writeFile as writeFile9 } from "fs/promises";
9978
- import path28 from "path";
10448
+ import { writeFile as writeFile10 } from "fs/promises";
10449
+ import path29 from "path";
9979
10450
  import { setTimeout as setTimeout3 } from "timers/promises";
9980
- import { parseArgs as parseArgs9 } from "util";
9981
- import { z as z21 } from "zod";
10451
+ import { parseArgs as parseArgs10 } from "util";
10452
+ import { z as z22 } from "zod";
9982
10453
  var PERFORMANCE_HELP = `
9983
10454
  siteos seo performance run --audit <id> --url <url> [--url <url>...] [--device <mobile|desktop>] [--idempotency-key <key>] [--environment <slug>] [--json]
9984
10455
  siteos seo performance list [--device <mobile|desktop>] [--environment <slug>] [--json]
@@ -9995,7 +10466,7 @@ Reuse the returned idempotency key after an uncertain run response. Wait default
9995
10466
  async function runSeoPerformanceCommand(options) {
9996
10467
  let idempotencyKey;
9997
10468
  try {
9998
- const { values, positionals } = parseArgs9({
10469
+ const { values, positionals } = parseArgs10({
9999
10470
  args: options.args.slice(1),
10000
10471
  strict: true,
10001
10472
  allowPositionals: true,
@@ -10012,7 +10483,7 @@ async function runSeoPerformanceCommand(options) {
10012
10483
  }
10013
10484
  });
10014
10485
  const action = positionals[0] ?? "";
10015
- const id = positionals[1];
10486
+ const id2 = positionals[1];
10016
10487
  const operations = {
10017
10488
  run: { args: 1, flags: ["audit", "url", "device", "idempotency-key"] },
10018
10489
  list: { args: 1, flags: ["device"] },
@@ -10066,12 +10537,12 @@ async function runSeoPerformanceCommand(options) {
10066
10537
  const runtime = commonProjectRuntime(options);
10067
10538
  const writing = ["run", "cancel"].includes(action);
10068
10539
  const scope = writing ? "seo:audits:write" : "seo:workspace:read";
10069
- const batchSchema = z21.object({
10070
- id: z21.string(),
10071
- resourceId: z21.literal(context.resourceId),
10072
- organizationId: z21.literal(context.overview.project.organizationId),
10073
- sourceAuditId: z21.string(),
10074
- state: z21.enum([
10540
+ const batchSchema = z22.object({
10541
+ id: z22.string(),
10542
+ resourceId: z22.literal(context.resourceId),
10543
+ organizationId: z22.literal(context.overview.project.organizationId),
10544
+ sourceAuditId: z22.string(),
10545
+ state: z22.enum([
10075
10546
  "queued",
10076
10547
  "running",
10077
10548
  "completed",
@@ -10079,13 +10550,13 @@ async function runSeoPerformanceCommand(options) {
10079
10550
  "failed",
10080
10551
  "cancelled"
10081
10552
  ]),
10082
- device: z21.enum(["mobile", "desktop"]),
10083
- urls: z21.array(z21.string()).min(1).max(10)
10553
+ device: z22.enum(["mobile", "desktop"]),
10554
+ urls: z22.array(z22.string()).min(1).max(10)
10084
10555
  }).passthrough();
10085
10556
  const query = new URLSearchParams();
10086
10557
  if (values.device) query.set("device", values.device);
10087
10558
  if (!writing && values.url?.[0]) query.set("pageUrl", values.url[0]);
10088
- const suffix = id ? `/${encodeURIComponent(id)}${action === "cancel" ? "/cancel" : action === "export" ? "/export" : ""}` : "";
10559
+ const suffix = id2 ? `/${encodeURIComponent(id2)}${action === "cancel" ? "/cancel" : action === "export" ? "/export" : ""}` : "";
10089
10560
  if (action === "export") query.set("format", values.format);
10090
10561
  const deadline = Date.now() + timeout * 1e3;
10091
10562
  while (true) {
@@ -10120,7 +10591,7 @@ async function runSeoPerformanceCommand(options) {
10120
10591
  }
10121
10592
  );
10122
10593
  if (action === "export" && response.ok) {
10123
- if (!(response instanceof Response) || response.headers.get("X-SEO-Browser-Id") !== id || !response.headers.get("Content-Type")?.startsWith(
10594
+ if (!(response instanceof Response) || response.headers.get("X-SEO-Browser-Id") !== id2 || !response.headers.get("Content-Type")?.startsWith(
10124
10595
  values.format === "csv" ? "text/csv" : "application/json"
10125
10596
  ))
10126
10597
  throw new Error(
@@ -10128,25 +10599,25 @@ async function runSeoPerformanceCommand(options) {
10128
10599
  );
10129
10600
  const text = await response.text();
10130
10601
  if (values.format === "json") {
10131
- const parsed = z21.object({
10132
- contractVersion: z21.literal(1),
10602
+ const parsed = z22.object({
10603
+ contractVersion: z22.literal(1),
10133
10604
  batch: batchSchema,
10134
- pages: z21.array(z21.unknown())
10605
+ pages: z22.array(z22.unknown())
10135
10606
  }).parse(JSON.parse(text));
10136
- if (parsed.batch.id !== id)
10607
+ if (parsed.batch.id !== id2)
10137
10608
  throw new Error(
10138
10609
  "The export response does not match the selected check."
10139
10610
  );
10140
10611
  }
10141
- const output = path28.resolve(
10612
+ const output = path29.resolve(
10142
10613
  options.cwd ?? process.cwd(),
10143
10614
  values.output
10144
10615
  );
10145
- await writeFile9(output, text, { flag: "wx", mode: 384 });
10616
+ await writeFile10(output, text, { flag: "wx", mode: 384 });
10146
10617
  return {
10147
10618
  exitCode: 0,
10148
10619
  stdout: JSON.stringify(
10149
- { batchId: id, output, format: values.format },
10620
+ { batchId: id2, output, format: values.format },
10150
10621
  null,
10151
10622
  2
10152
10623
  )
@@ -10154,8 +10625,8 @@ async function runSeoPerformanceCommand(options) {
10154
10625
  }
10155
10626
  const data = await response.json();
10156
10627
  if (!response.ok) {
10157
- const error = z21.object({
10158
- error: z21.object({ code: z21.string(), message: z21.string().max(500) })
10628
+ const error = z22.object({
10629
+ error: z22.object({ code: z22.string(), message: z22.string().max(500) })
10159
10630
  }).safeParse(data);
10160
10631
  throw new SiteOSAuthApiError({
10161
10632
  code: error.success ? error.data.error.code : "SEO_REQUEST_FAILED",
@@ -10163,8 +10634,8 @@ async function runSeoPerformanceCommand(options) {
10163
10634
  status: response.status
10164
10635
  });
10165
10636
  }
10166
- const record = z21.object({ contractVersion: z21.literal(1) }).passthrough().parse(data);
10167
- if (action === "cancel") z21.literal(true).parse(record.cancelled);
10637
+ const record = z22.object({ contractVersion: z22.literal(1) }).passthrough().parse(data);
10638
+ if (action === "cancel") z22.literal(true).parse(record.cancelled);
10168
10639
  else if (action === "run") {
10169
10640
  const accepted = batchSchema.parse(record.batch);
10170
10641
  const normalize = (url) => {
@@ -10177,10 +10648,10 @@ async function runSeoPerformanceCommand(options) {
10177
10648
  "The queued check does not match the requested source, device and URLs."
10178
10649
  );
10179
10650
  } else {
10180
- z21.literal(context.resourceId).parse(record.resourceId);
10181
- z21.array(batchSchema).parse(record.batches);
10651
+ z22.literal(context.resourceId).parse(record.resourceId);
10652
+ z22.array(batchSchema).parse(record.batches);
10182
10653
  const selected = batchSchema.nullable().parse(record.batch);
10183
- if (id && selected?.id !== id)
10654
+ if (id2 && selected?.id !== id2)
10184
10655
  throw new Error(
10185
10656
  "The response does not match the selected performance check."
10186
10657
  );
@@ -10205,7 +10676,7 @@ async function runSeoPerformanceCommand(options) {
10205
10676
  } catch (cause) {
10206
10677
  const error = {
10207
10678
  code: cause instanceof SiteOSAuthApiError ? cause.code : "SEO_COMMAND_FAILED",
10208
- message: cause instanceof z21.ZodError ? "The SEO service returned an invalid response." : cause instanceof Error ? cause.message : "The performance command failed."
10679
+ message: cause instanceof z22.ZodError ? "The SEO service returned an invalid response." : cause instanceof Error ? cause.message : "The performance command failed."
10209
10680
  };
10210
10681
  return {
10211
10682
  exitCode: cause instanceof SiteOSAuthApiError ? 1 : 2,
@@ -10245,7 +10716,7 @@ Usage:
10245
10716
  siteos seo recheck --audit <id> --url <url> [--url <url>...] [--resource <expected-id>] [--environment <slug>] [--json]
10246
10717
  siteos seo issue <ignore|restore> --audit <id> --url <url> --rule <id> --reason <text> --revision <number> [--environment <slug>] [--json]
10247
10718
  siteos seo schedule show [--environment <slug>] [--json]
10248
- siteos seo schedule set --enabled <true|false> --weekday <1-7> --time <HH:mm> --timezone <IANA> --revision <number> [--environment <slug>] [--json]
10719
+ siteos seo schedule set --enabled <true|false> (--days <1,2,3|daily|weekdays> | --weekday <1-7>) --time <HH:mm> --timezone <IANA> --revision <number> [--environment <slug>] [--json]
10249
10720
  siteos seo notifications retry <notification-id> [--environment <slug>] [--json]
10250
10721
  siteos seo notifications show [--environment <slug>] [--json]
10251
10722
  siteos seo notifications destinations [--environment <slug>] [--json]
@@ -10277,7 +10748,7 @@ async function runSeoCommand(options) {
10277
10748
  return runSeoRepairCommand(options);
10278
10749
  const json = options.args.includes("--json");
10279
10750
  try {
10280
- const { positionals, values } = parseArgs10({
10751
+ const { positionals, values } = parseArgs11({
10281
10752
  args: options.args,
10282
10753
  strict: true,
10283
10754
  allowPositionals: true,
@@ -10294,6 +10765,7 @@ async function runSeoCommand(options) {
10294
10765
  state: { type: "string" },
10295
10766
  enabled: { type: "string" },
10296
10767
  weekday: { type: "string" },
10768
+ days: { type: "string" },
10297
10769
  time: { type: "string" },
10298
10770
  timezone: { type: "string" },
10299
10771
  destination: { type: "string" },
@@ -10310,7 +10782,7 @@ async function runSeoCommand(options) {
10310
10782
  status: { flags: [], args: 1 },
10311
10783
  "schedule show": { flags: [], args: 2 },
10312
10784
  "schedule set": {
10313
- flags: ["enabled", "weekday", "time", "timezone", "revision"],
10785
+ flags: ["enabled", "weekday", "days", "time", "timezone", "revision"],
10314
10786
  args: 2
10315
10787
  },
10316
10788
  "notifications retry": { flags: [], args: 3 },
@@ -10375,9 +10847,12 @@ async function runSeoCommand(options) {
10375
10847
  const setting = automation && positionals[1] === "set";
10376
10848
  if (setting && (!values.revision || !["true", "false"].includes(values.enabled ?? "")))
10377
10849
  throw new Error("Settings require --enabled true|false and --revision.");
10850
+ const days = values.days === "daily" ? [1, 2, 3, 4, 5, 6, 7] : values.days === "weekdays" ? [1, 2, 3, 4, 5] : values.days?.split(",").map(Number);
10378
10851
  if (route === "schedule set") {
10379
- if (!/^[1-7]$/u.test(values.weekday ?? "") || !/^([01]\d|2[0-3]):[0-5]\d$/u.test(values.time ?? "") || !values.timezone)
10380
- throw new Error("Use weekday 1\u20137, HH:mm and an IANA time zone.");
10852
+ if (values.days !== void 0 === (values.weekday !== void 0) || (days ? !days.length || days.some((day) => !Number.isInteger(day) || day < 1 || day > 7) || new Set(days).size !== days.length : !/^[1-7]$/u.test(values.weekday ?? "")) || !/^([01]\d|2[0-3]):[0-5]\d$/u.test(values.time ?? "") || !values.timezone)
10853
+ throw new Error(
10854
+ "Use --days daily, weekdays or distinct days 1\u20137 (or --weekday), HH:mm and an IANA time zone."
10855
+ );
10381
10856
  try {
10382
10857
  new Intl.DateTimeFormat("en", { timeZone: values.timezone });
10383
10858
  } catch {
@@ -10439,7 +10914,7 @@ async function runSeoCommand(options) {
10439
10914
  const suffix = retryNotification ? "/notification-retries" : automation ? setting ? `/${action}` : route === "notifications destinations" ? "/destinations" : "/automation" : action === "export" ? `/export?${query}` : route === "audit run" ? "/audits" : route === "audit cancel" ? `/audits/${encodeURIComponent(positionals[2])}/cancel` : action === "issue" ? "/dispositions" : `?${query}`;
10440
10915
  const body = retryNotification ? { notificationId: positionals[2] } : route === "schedule set" ? {
10441
10916
  enabled: values.enabled === "true",
10442
- weekday: Number(values.weekday),
10917
+ ...days ? { days: [...days].sort((a, b) => a - b) } : { weekday: Number(values.weekday) },
10443
10918
  time: values.time,
10444
10919
  timeZone: values.timezone,
10445
10920
  expectedRevision: Number(values.revision)
@@ -10483,18 +10958,18 @@ async function runSeoCommand(options) {
10483
10958
  );
10484
10959
  const text = await response.text();
10485
10960
  if (values.format === "json")
10486
- z22.object({
10487
- contractVersion: z22.literal(1),
10488
- audit: z22.object({
10489
- id: z22.literal(values.audit),
10490
- resourceId: z22.literal(context.resourceId)
10961
+ z23.object({
10962
+ contractVersion: z23.literal(1),
10963
+ audit: z23.object({
10964
+ id: z23.literal(values.audit),
10965
+ resourceId: z23.literal(context.resourceId)
10491
10966
  }),
10492
- kind: z22.literal(values.kind),
10493
- totalRows: z22.literal(rows),
10494
- rows: z22.array(z22.unknown()).length(rows)
10967
+ kind: z23.literal(values.kind),
10968
+ totalRows: z23.literal(rows),
10969
+ rows: z23.array(z23.unknown()).length(rows)
10495
10970
  }).parse(JSON.parse(text));
10496
- const output = path29.resolve(options.cwd ?? process.cwd(), values.output);
10497
- await writeFile10(output, text, { flag: "wx", mode: 384 });
10971
+ const output = path30.resolve(options.cwd ?? process.cwd(), values.output);
10972
+ await writeFile11(output, text, { flag: "wx", mode: 384 });
10498
10973
  return {
10499
10974
  exitCode: 0,
10500
10975
  stdout: JSON.stringify(
@@ -10512,8 +10987,8 @@ async function runSeoCommand(options) {
10512
10987
  }
10513
10988
  const data = await response.json();
10514
10989
  if (!response.ok) {
10515
- const result = z22.object({
10516
- error: z22.object({ code: z22.string(), message: z22.string().max(500) })
10990
+ const result = z23.object({
10991
+ error: z23.object({ code: z23.string(), message: z23.string().max(500) })
10517
10992
  }).safeParse(data);
10518
10993
  throw new SiteOSAuthApiError({
10519
10994
  code: result.success ? result.data.error.code : "SEO_REQUEST_FAILED",
@@ -10521,34 +10996,35 @@ async function runSeoCommand(options) {
10521
10996
  status: response.status
10522
10997
  });
10523
10998
  }
10524
- const record = z22.object({ contractVersion: z22.literal(1) }).passthrough().parse(data);
10999
+ const record = z23.object({ contractVersion: z23.literal(1) }).passthrough().parse(data);
10525
11000
  if (automation) {
10526
- z22.literal(context.resourceId).parse(record.resourceId);
10527
- const schedule = z22.object({
10528
- enabled: z22.boolean(),
10529
- weekday: z22.number().int().min(1).max(7),
10530
- time: z22.string(),
10531
- timeZone: z22.string(),
10532
- revision: z22.number().int().min(0),
10533
- nextRunAt: z22.string().nullable()
11001
+ z23.literal(context.resourceId).parse(record.resourceId);
11002
+ const schedule = z23.object({
11003
+ enabled: z23.boolean(),
11004
+ weekday: z23.number().int().min(1).max(7),
11005
+ days: z23.array(z23.number().int().min(1).max(7)).min(1).max(7).optional(),
11006
+ time: z23.string(),
11007
+ timeZone: z23.string(),
11008
+ revision: z23.number().int().min(0),
11009
+ nextRunAt: z23.string().nullable()
10534
11010
  });
10535
- const notificationRoute = z22.object({
10536
- enabled: z22.boolean(),
10537
- minimumSeverity: z22.enum(["error", "warning"]),
10538
- includeFailures: z22.boolean(),
10539
- revision: z22.number().int().min(0),
10540
- destinationId: z22.string().nullable()
11011
+ const notificationRoute = z23.object({
11012
+ enabled: z23.boolean(),
11013
+ minimumSeverity: z23.enum(["error", "warning"]),
11014
+ includeFailures: z23.boolean(),
11015
+ revision: z23.number().int().min(0),
11016
+ destinationId: z23.string().nullable()
10541
11017
  });
10542
11018
  if (retryNotification) {
10543
- z22.literal(true).parse(record.retryQueued);
10544
- z22.literal(positionals[2]).parse(record.notificationId);
11019
+ z23.literal(true).parse(record.retryQueued);
11020
+ z23.literal(positionals[2]).parse(record.notificationId);
10545
11021
  } else if (route === "notifications destinations")
10546
- z22.object({
10547
- candidates: z22.array(
10548
- z22.object({
10549
- candidateId: z22.string(),
10550
- label: z22.string(),
10551
- availability: z22.literal("available")
11022
+ z23.object({
11023
+ candidates: z23.array(
11024
+ z23.object({
11025
+ candidateId: z23.string(),
11026
+ label: z23.string(),
11027
+ availability: z23.literal("available")
10552
11028
  })
10553
11029
  )
10554
11030
  }).parse(record);
@@ -10561,46 +11037,46 @@ async function runSeoCommand(options) {
10561
11037
  notificationRoute.parse(record.route);
10562
11038
  }
10563
11039
  } else if (!writing) {
10564
- const validated = z22.object({
10565
- resource: z22.object({
10566
- id: z22.literal(context.resourceId),
10567
- organizationId: z22.literal(context.overview.project.organizationId)
11040
+ const validated = z23.object({
11041
+ resource: z23.object({
11042
+ id: z23.literal(context.resourceId),
11043
+ organizationId: z23.literal(context.overview.project.organizationId)
10568
11044
  }),
10569
- audits: z22.array(z22.object({ id: z22.string() }).passthrough()),
10570
- audit: z22.object({
10571
- id: z22.string(),
10572
- resourceId: z22.literal(context.resourceId)
11045
+ audits: z23.array(z23.object({ id: z23.string() }).passthrough()),
11046
+ audit: z23.object({
11047
+ id: z23.string(),
11048
+ resourceId: z23.literal(context.resourceId)
10573
11049
  }).passthrough().nullable(),
10574
- pages: z22.array(z22.unknown()),
10575
- issues: z22.array(z22.unknown()),
10576
- changes: z22.array(z22.unknown()),
10577
- totalChanges: z22.number(),
10578
- dispositions: z22.array(z22.unknown())
11050
+ pages: z23.array(z23.unknown()),
11051
+ issues: z23.array(z23.unknown()),
11052
+ changes: z23.array(z23.unknown()),
11053
+ totalChanges: z23.number(),
11054
+ dispositions: z23.array(z23.unknown())
10579
11055
  }).passthrough().parse(record);
10580
11056
  const selected = query.get("audit");
10581
11057
  if (selected && validated.audit?.id !== selected)
10582
11058
  throw new Error("The SEO response does not match the requested audit.");
10583
11059
  } else if (record.audit)
10584
- z22.object({
10585
- id: z22.string(),
10586
- resourceId: z22.literal(context.resourceId),
10587
- organizationId: z22.literal(context.overview.project.organizationId),
10588
- state: z22.literal("queued")
11060
+ z23.object({
11061
+ id: z23.string(),
11062
+ resourceId: z23.literal(context.resourceId),
11063
+ organizationId: z23.literal(context.overview.project.organizationId),
11064
+ state: z23.literal("queued")
10589
11065
  }).parse(record.audit);
10590
- else if (route === "audit cancel") z22.literal(true).parse(record.cancelled);
11066
+ else if (route === "audit cancel") z23.literal(true).parse(record.cancelled);
10591
11067
  else if (action === "issue")
10592
- z22.object({
10593
- url: z22.literal(values.url),
10594
- ruleId: z22.literal(values.rule),
10595
- ignored: z22.literal(positionals[1] === "ignore"),
10596
- revision: z22.literal(Number(values.revision) + 1)
11068
+ z23.object({
11069
+ url: z23.literal(values.url),
11070
+ ruleId: z23.literal(values.rule),
11071
+ ignored: z23.literal(positionals[1] === "ignore"),
11072
+ revision: z23.literal(Number(values.revision) + 1)
10597
11073
  }).parse(record.disposition);
10598
11074
  else throw new Error("The SEO service returned an invalid response.");
10599
11075
  return { exitCode: 0, stdout: JSON.stringify(record, null, 2) };
10600
11076
  } catch (cause) {
10601
11077
  const error = {
10602
11078
  code: cause instanceof SiteOSAuthApiError ? cause.code : "SEO_COMMAND_FAILED",
10603
- message: cause instanceof z22.ZodError ? "The SEO service returned an invalid response." : cause instanceof Error ? cause.message : "The SEO command failed."
11079
+ message: cause instanceof z23.ZodError ? "The SEO service returned an invalid response." : cause instanceof Error ? cause.message : "The SEO command failed."
10604
11080
  };
10605
11081
  return {
10606
11082
  exitCode: cause instanceof SiteOSAuthApiError ? 1 : 2,