@better-update/cli 0.28.0 → 0.29.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/index.mjs CHANGED
@@ -34,7 +34,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
34
34
 
35
35
  //#endregion
36
36
  //#region package.json
37
- var version = "0.28.0";
37
+ var version = "0.29.0";
38
38
 
39
39
  //#endregion
40
40
  //#region src/lib/interactive-mode.ts
@@ -904,7 +904,7 @@ var AssetsGroup = class extends HttpApiGroup.make("assets").add(HttpApiEndpoint.
904
904
 
905
905
  //#endregion
906
906
  //#region ../../packages/api/src/domain/audit-log.ts
907
- const AuditLogResourceType = Schema.Literal("project", "branch", "channel", "update", "build", "appleCredential", "androidCredential", "iosBundleConfiguration", "envVar", "device", "webhook", "iosAppMetadata", "submission", "vaultAccess", "policy", "group", "policyAttachment", "apiKey", "invitation", "member", "organization");
907
+ const AuditLogResourceType = Schema.Literal("project", "branch", "channel", "update", "environment", "build", "appleCredential", "androidCredential", "iosBundleConfiguration", "envVar", "device", "webhook", "iosAppMetadata", "submission", "vaultAccess", "policy", "group", "policyAttachment", "apiKey", "invitation", "member", "organization");
908
908
  const AuditLogSource = Schema.Literal("session", "api-key");
909
909
  var AuditLog = class extends Schema.Class("AuditLog")({
910
910
  id: Id,
@@ -941,6 +941,7 @@ var Branch = class extends Schema.Class("Branch")({
941
941
  id: Id,
942
942
  projectId: Id,
943
943
  name: Schema.String,
944
+ isBuiltin: Schema.Boolean,
944
945
  createdAt: DateTimeString,
945
946
  updateCount: Schema.Number
946
947
  }) {};
@@ -1231,6 +1232,7 @@ var Channel = class extends Schema.Class("Channel")({
1231
1232
  branchMappingJson: Schema.NullOr(Schema.String),
1232
1233
  cacheVersion: Schema.Number,
1233
1234
  isPaused: Schema.Boolean,
1235
+ isBuiltin: Schema.Boolean,
1234
1236
  createdAt: DateTimeString
1235
1237
  }) {};
1236
1238
  const ChannelSortColumn = Schema.Literal("name", "createdAt");
@@ -1381,11 +1383,32 @@ var DevicesGroup = class extends HttpApiGroup.make("devices").add(HttpApiEndpoin
1381
1383
  description: "Apple device management for ad-hoc builds"
1382
1384
  })) {};
1383
1385
 
1386
+ //#endregion
1387
+ //#region ../../packages/api/src/domain/environment.ts
1388
+ /**
1389
+ * An environment name: lowercase letters, digits and hyphens, starting with a
1390
+ * letter. Shared by the env-var `environment` axis and the environment entity so
1391
+ * a custom environment name and an env var's `environment` use one shape.
1392
+ */
1393
+ const EnvironmentName = Schema.String.pipe(Schema.pattern(/^[a-z][a-z0-9-]*$/u), Schema.maxLength(64));
1394
+ /** An organization environment: a built-in (virtual) or a user-defined row. */
1395
+ var Environment = class extends Schema.Class("Environment")({
1396
+ id: Id,
1397
+ organizationId: Id,
1398
+ name: EnvironmentName,
1399
+ isBuiltin: Schema.Boolean,
1400
+ createdAt: DateTimeString
1401
+ }) {};
1402
+ const EnvironmentListResult = Schema.Struct({ items: Schema.Array(Environment) });
1403
+ const CreateEnvironmentBody = Schema.Struct({ name: EnvironmentName });
1404
+ const RenameEnvironmentBody = Schema.Struct({ name: EnvironmentName });
1405
+ const DeleteEnvironmentResult = Schema.Struct({ deleted: Schema.Number });
1406
+
1384
1407
  //#endregion
1385
1408
  //#region ../../packages/api/src/domain/env-var.ts
1386
1409
  const EnvVarVisibility = Schema.Literal("plaintext", "sensitive");
1387
1410
  const EnvVarScope = Schema.Literal("project", "global");
1388
- const EnvVarEnvironment = Schema.Literal("development", "preview", "production");
1411
+ const EnvVarEnvironment = EnvironmentName;
1389
1412
  const EnvVarListScope = Schema.Literal("all", "project", "global");
1390
1413
  /**
1391
1414
  * A client-sealed env var value. `id` is the revision UUID the CLI bound as the
@@ -1519,6 +1542,27 @@ var EnvVarsGroup = class extends HttpApiGroup.make("env-vars").add(HttpApiEndpoi
1519
1542
  description: "Manage end-to-end encrypted, versioned environment variables for project builds"
1520
1543
  })) {};
1521
1544
 
1545
+ //#endregion
1546
+ //#region ../../packages/api/src/groups/environments.ts
1547
+ /** `:name` path parameter — the environment name (built-in or user-defined). */
1548
+ const nameParam = HttpApiSchema.param("name", Schema.String);
1549
+ var EnvironmentsGroup = class extends HttpApiGroup.make("environments").add(HttpApiEndpoint.get("list", "/api/environments").addSuccess(EnvironmentListResult).annotateContext(OpenApi.annotations({
1550
+ title: "List environments",
1551
+ description: "List the organization's environments: the three built-ins (development, preview, production) followed by user-defined ones."
1552
+ }))).add(HttpApiEndpoint.post("create", "/api/environments").setPayload(CreateEnvironmentBody).addSuccess(Environment, { status: 201 }).addError(Conflict).addError(BadRequest).annotateContext(OpenApi.annotations({
1553
+ title: "Create environment",
1554
+ description: "Create a user-defined environment for the organization. Built-in names are reserved."
1555
+ }))).add(HttpApiEndpoint.patch("rename")`/api/environments/${nameParam}`.setPayload(RenameEnvironmentBody).addSuccess(Environment).addError(Conflict).addError(BadRequest).annotateContext(OpenApi.annotations({
1556
+ title: "Rename environment",
1557
+ description: "Rename a user-defined environment. Built-ins cannot be renamed. Env vars referencing the old name are re-pointed at the new name."
1558
+ }))).add(HttpApiEndpoint.del("delete")`/api/environments/${nameParam}`.addSuccess(DeleteEnvironmentResult).addError(Conflict).annotateContext(OpenApi.annotations({
1559
+ title: "Delete environment",
1560
+ description: "Delete a user-defined environment. Built-ins cannot be deleted, nor can an environment still referenced by env vars."
1561
+ }))).addError(NotFound).addError(Conflict).addError(BadRequest).addError(Forbidden).annotateContext(OpenApi.annotations({
1562
+ title: "Environments",
1563
+ description: "Organization environment management endpoints"
1564
+ })) {};
1565
+
1522
1566
  //#endregion
1523
1567
  //#region ../../packages/api/src/domain/update.ts
1524
1568
  var Update = class extends Schema.Class("Update")({
@@ -2434,7 +2478,7 @@ var WebhooksGroup = class extends HttpApiGroup.make("webhooks").add(HttpApiEndpo
2434
2478
 
2435
2479
  //#endregion
2436
2480
  //#region ../../packages/api/src/api.ts
2437
- var ManagementApi = class extends HttpApi.make("management-api").add(ProjectsGroup).add(BranchesGroup).add(ChannelsGroup).add(UpdatesGroup).add(AssetsGroup).add(AnalyticsGroup).add(BuildsGroup).add(EnvVarsGroup).add(FingerprintsGroup).add(AuditLogsGroup).add(DevicesGroup).add(AppleTeamsGroup).add(AppleDistributionCertificatesGroup).add(ApplePushKeysGroup).add(AscApiKeysGroup).add(AppleProvisioningProfilesGroup).add(GoogleServiceAccountKeysGroup).add(IosBundleConfigurationsGroup).add(IosAppMetadataGroup).add(SubmissionsGroup).add(AndroidApplicationIdentifiersGroup).add(AndroidUploadKeystoresGroup).add(AndroidBuildCredentialsGroup).add(BuildCredentialsGroup).add(UserEncryptionKeysGroup).add(OrgVaultGroup).add(MeGroup).add(WebhooksGroup).add(PoliciesGroup).add(GroupsGroup).add(PolicyAttachmentsGroup).add(ApiKeysGroup).add(InvitationsGroup).add(MembersGroup).add(OrganizationGroup).add(AdminGroup).middleware(Authentication).annotateContext(OpenApi.annotations({
2481
+ var ManagementApi = class extends HttpApi.make("management-api").add(ProjectsGroup).add(BranchesGroup).add(ChannelsGroup).add(EnvironmentsGroup).add(UpdatesGroup).add(AssetsGroup).add(AnalyticsGroup).add(BuildsGroup).add(EnvVarsGroup).add(FingerprintsGroup).add(AuditLogsGroup).add(DevicesGroup).add(AppleTeamsGroup).add(AppleDistributionCertificatesGroup).add(ApplePushKeysGroup).add(AscApiKeysGroup).add(AppleProvisioningProfilesGroup).add(GoogleServiceAccountKeysGroup).add(IosBundleConfigurationsGroup).add(IosAppMetadataGroup).add(SubmissionsGroup).add(AndroidApplicationIdentifiersGroup).add(AndroidUploadKeystoresGroup).add(AndroidBuildCredentialsGroup).add(BuildCredentialsGroup).add(UserEncryptionKeysGroup).add(OrgVaultGroup).add(MeGroup).add(WebhooksGroup).add(PoliciesGroup).add(GroupsGroup).add(PolicyAttachmentsGroup).add(ApiKeysGroup).add(InvitationsGroup).add(MembersGroup).add(OrganizationGroup).add(AdminGroup).middleware(Authentication).annotateContext(OpenApi.annotations({
2438
2482
  title: "Better Update Management API",
2439
2483
  version: "1.0.0",
2440
2484
  description: "Management API for OTA update publishing, deployment, and analytics"
@@ -4789,7 +4833,7 @@ const parseLimit = (raw, defaultValue) => {
4789
4833
 
4790
4834
  //#endregion
4791
4835
  //#region src/commands/audit-logs/list.ts
4792
- const listCommand$9 = defineCommand({
4836
+ const listCommand$10 = defineCommand({
4793
4837
  meta: {
4794
4838
  name: "list",
4795
4839
  description: "List audit log entries"
@@ -4851,7 +4895,7 @@ const auditLogsCommand = defineCommand({
4851
4895
  name: "audit-logs",
4852
4896
  description: "View audit logs"
4853
4897
  },
4854
- subCommands: { list: listCommand$9 }
4898
+ subCommands: { list: listCommand$10 }
4855
4899
  });
4856
4900
 
4857
4901
  //#endregion
@@ -4955,7 +4999,7 @@ const drainPages = (fetchPage) => {
4955
4999
 
4956
5000
  //#endregion
4957
5001
  //#region src/commands/branches.ts
4958
- const listCommand$8 = defineCommand({
5002
+ const listCommand$9 = defineCommand({
4959
5003
  meta: {
4960
5004
  name: "list",
4961
5005
  description: "List branches for the linked project"
@@ -4978,7 +5022,7 @@ const listCommand$8 = defineCommand({
4978
5022
  ]), "No branches found.");
4979
5023
  }))
4980
5024
  });
4981
- const createCommand$4 = defineCommand({
5025
+ const createCommand$5 = defineCommand({
4982
5026
  meta: {
4983
5027
  name: "create",
4984
5028
  description: "Create a branch"
@@ -5033,7 +5077,7 @@ const viewCommand$3 = defineCommand({
5033
5077
  return branch;
5034
5078
  }), { json: "value" })
5035
5079
  });
5036
- const renameCommand$1 = defineCommand({
5080
+ const renameCommand$2 = defineCommand({
5037
5081
  meta: {
5038
5082
  name: "rename",
5039
5083
  description: "Rename a branch"
@@ -5059,7 +5103,7 @@ const renameCommand$1 = defineCommand({
5059
5103
  return branch;
5060
5104
  }), { json: "value" })
5061
5105
  });
5062
- const deleteCommand$6 = defineCommand({
5106
+ const deleteCommand$7 = defineCommand({
5063
5107
  meta: {
5064
5108
  name: "delete",
5065
5109
  description: "Delete a branch"
@@ -5084,11 +5128,11 @@ const branchesCommand = defineCommand({
5084
5128
  description: "Manage branches"
5085
5129
  },
5086
5130
  subCommands: {
5087
- list: listCommand$8,
5131
+ list: listCommand$9,
5088
5132
  view: viewCommand$3,
5089
- create: createCommand$4,
5090
- rename: renameCommand$1,
5091
- delete: deleteCommand$6
5133
+ create: createCommand$5,
5134
+ rename: renameCommand$2,
5135
+ delete: deleteCommand$7
5092
5136
  }
5093
5137
  });
5094
5138
 
@@ -22734,7 +22778,8 @@ const warnIfDevClientMissing = (projectRoot) => Effect.gen(function* () {
22734
22778
 
22735
22779
  //#endregion
22736
22780
  //#region src/lib/env-exporter.ts
22737
- const coerceEnvironment = (raw) => raw === "development" || raw === "preview" || raw === "production" ? raw : void 0;
22781
+ const ENVIRONMENT_NAME_PATTERN$1 = /^[a-z][a-z0-9-]*$/u;
22782
+ const coerceEnvironment = (raw) => ENVIRONMENT_NAME_PATTERN$1.test(raw) && raw.length <= 64 ? raw : void 0;
22738
22783
  /** Decrypt one sealed env var value, re-checking the sealed metadata against the row. */
22739
22784
  const decryptEnvVarValue = (session, item) => openFromDownload({
22740
22785
  session,
@@ -22766,7 +22811,7 @@ const exportDecryptedEnvVars = (api, projectId, environment) => Effect.gen(funct
22766
22811
  */
22767
22812
  const pullEnvVars = (api, { projectId, environment }) => Effect.gen(function* () {
22768
22813
  const validated = coerceEnvironment(environment);
22769
- if (!validated) return yield* new EnvExportError({ message: `Invalid environment "${environment}". Must be one of: development, preview, production.` });
22814
+ if (!validated) return yield* new EnvExportError({ message: `Invalid environment "${environment}": must be lowercase letters, digits, and hyphens, starting with a letter.` });
22770
22815
  const items = yield* exportDecryptedEnvVars(api, projectId, validated);
22771
22816
  return Object.fromEntries(items.map((item) => [item.key, item.value]));
22772
22817
  });
@@ -24536,7 +24581,7 @@ const compatibilityMatrixCommand = defineCommand({
24536
24581
 
24537
24582
  //#endregion
24538
24583
  //#region src/commands/builds/delete.ts
24539
- const deleteCommand$5 = defineCommand({
24584
+ const deleteCommand$6 = defineCommand({
24540
24585
  meta: {
24541
24586
  name: "delete",
24542
24587
  description: "Delete a build"
@@ -24682,7 +24727,7 @@ const DISTRIBUTION_OPTIONS$1 = [
24682
24727
  "play-store",
24683
24728
  "direct"
24684
24729
  ];
24685
- const listCommand$7 = defineCommand({
24730
+ const listCommand$8 = defineCommand({
24686
24731
  meta: {
24687
24732
  name: "list",
24688
24733
  description: "List builds for the linked project"
@@ -25340,9 +25385,9 @@ const buildsCommand = defineCommand({
25340
25385
  description: "Manage builds"
25341
25386
  },
25342
25387
  subCommands: {
25343
- list: listCommand$7,
25388
+ list: listCommand$8,
25344
25389
  get: getCommand$2,
25345
- delete: deleteCommand$5,
25390
+ delete: deleteCommand$6,
25346
25391
  download: downloadCommand$1,
25347
25392
  run: runCommand$1,
25348
25393
  "install-link": installLinkCommand,
@@ -25368,7 +25413,7 @@ const resolveNamedResourceId$1 = (params) => resolveNamedResourceId$2(params, (m
25368
25413
 
25369
25414
  //#endregion
25370
25415
  //#region src/commands/channels/create.ts
25371
- const createCommand$3 = defineCommand({
25416
+ const createCommand$4 = defineCommand({
25372
25417
  meta: {
25373
25418
  name: "create",
25374
25419
  description: "Create a channel"
@@ -25413,7 +25458,7 @@ const createCommand$3 = defineCommand({
25413
25458
 
25414
25459
  //#endregion
25415
25460
  //#region src/commands/channels/delete.ts
25416
- const deleteCommand$4 = defineCommand({
25461
+ const deleteCommand$5 = defineCommand({
25417
25462
  meta: {
25418
25463
  name: "delete",
25419
25464
  description: "Delete a channel"
@@ -25482,7 +25527,7 @@ const insightsCommand$1 = defineCommand({
25482
25527
 
25483
25528
  //#endregion
25484
25529
  //#region src/commands/channels/list.ts
25485
- const listCommand$6 = defineCommand({
25530
+ const listCommand$7 = defineCommand({
25486
25531
  meta: {
25487
25532
  name: "list",
25488
25533
  description: "List channels for the linked project"
@@ -25586,7 +25631,7 @@ const completeCommand$1 = defineCommand({
25586
25631
 
25587
25632
  //#endregion
25588
25633
  //#region src/commands/channels/rollout/create.ts
25589
- const createCommand$2 = defineCommand({
25634
+ const createCommand$3 = defineCommand({
25590
25635
  meta: {
25591
25636
  name: "create",
25592
25637
  description: "Start a branch rollout on a channel"
@@ -25706,7 +25751,7 @@ const rolloutCommand$1 = defineCommand({
25706
25751
  description: "Manage channel branch rollouts"
25707
25752
  },
25708
25753
  subCommands: {
25709
- create: createCommand$2,
25754
+ create: createCommand$3,
25710
25755
  update: updateCommand$3,
25711
25756
  complete: completeCommand$1,
25712
25757
  revert: revertCommand$2
@@ -25818,13 +25863,13 @@ const channelsCommand = defineCommand({
25818
25863
  description: "Manage channels"
25819
25864
  },
25820
25865
  subCommands: {
25821
- list: listCommand$6,
25866
+ list: listCommand$7,
25822
25867
  view: viewCommand$2,
25823
- create: createCommand$3,
25868
+ create: createCommand$4,
25824
25869
  update: updateCommand$2,
25825
25870
  pause: pauseCommand,
25826
25871
  resume: resumeCommand,
25827
- delete: deleteCommand$4,
25872
+ delete: deleteCommand$5,
25828
25873
  rollout: rolloutCommand$1,
25829
25874
  insights: insightsCommand$1
25830
25875
  }
@@ -27239,7 +27284,7 @@ const toRecipientView = (userEncryptionKeyId, key) => ({
27239
27284
  fingerprint: key?.fingerprint
27240
27285
  })
27241
27286
  });
27242
- const listCommand$5 = defineCommand({
27287
+ const listCommand$6 = defineCommand({
27243
27288
  meta: {
27244
27289
  name: "list",
27245
27290
  description: "List recipients that currently hold the org vault key"
@@ -27466,7 +27511,7 @@ const accessCommand = defineCommand({
27466
27511
  description: "Inspect, grant, rotate, revoke, and recover access to the org credential vault"
27467
27512
  },
27468
27513
  subCommands: {
27469
- list: listCommand$5,
27514
+ list: listCommand$6,
27470
27515
  grant: grantCommand,
27471
27516
  rotate: rotateCommand,
27472
27517
  revoke: revokeCommand$1,
@@ -27675,7 +27720,7 @@ const CREDENTIAL_TYPES$3 = [
27675
27720
  "keystore",
27676
27721
  "google-service-account-key"
27677
27722
  ];
27678
- const deleteCommand$3 = defineCommand({
27723
+ const deleteCommand$4 = defineCommand({
27679
27724
  meta: {
27680
27725
  name: "delete",
27681
27726
  description: "Delete a credential"
@@ -27717,7 +27762,7 @@ const deleteCommand$3 = defineCommand({
27717
27762
  //#region src/commands/credentials/device.ts
27718
27763
  /** Self-linking is for your own device keys; recovery/machine keys go through `access grant`. */
27719
27764
  const requireDeviceKind = (target) => target.kind === "device" ? Effect.void : new IdentityError({ message: `Key ${target.id} is a ${target.kind} key, not a device. Use \`better-update credentials access grant\` for recovery/machine keys.` });
27720
- const listCommand$4 = defineCommand({
27765
+ const listCommand$5 = defineCommand({
27721
27766
  meta: {
27722
27767
  name: "list",
27723
27768
  description: "List your registered device keys (the active one is marked)"
@@ -27775,7 +27820,7 @@ const deviceCommand = defineCommand({
27775
27820
  description: "Manage your vault device keys"
27776
27821
  },
27777
27822
  subCommands: {
27778
- list: listCommand$4,
27823
+ list: listCommand$5,
27779
27824
  link: linkCommand
27780
27825
  },
27781
27826
  default: "list"
@@ -28430,7 +28475,7 @@ const printRecipient = (key) => printKeyValue([
28430
28475
  ["Recipient (public key)", key.publicKey],
28431
28476
  ["Fingerprint", key.fingerprint]
28432
28477
  ]);
28433
- const createCommand$1 = defineCommand({
28478
+ const createCommand$2 = defineCommand({
28434
28479
  meta: {
28435
28480
  name: "create",
28436
28481
  description: "Create this device's encryption identity and register it as a recipient"
@@ -28533,7 +28578,7 @@ const identityCommand = defineCommand({
28533
28578
  description: "Manage this device's end-to-end encryption identity"
28534
28579
  },
28535
28580
  subCommands: {
28536
- create: createCommand$1,
28581
+ create: createCommand$2,
28537
28582
  init: initCommand$1,
28538
28583
  register: registerCommand,
28539
28584
  show: showCommand
@@ -28543,7 +28588,7 @@ const identityCommand = defineCommand({
28543
28588
 
28544
28589
  //#endregion
28545
28590
  //#region src/commands/credentials/list.ts
28546
- const listCommand$3 = defineCommand({
28591
+ const listCommand$4 = defineCommand({
28547
28592
  meta: {
28548
28593
  name: "list",
28549
28594
  description: "List credentials across platforms"
@@ -29745,14 +29790,14 @@ const credentialsCommand = defineCommand({
29745
29790
  unlock: unlockCommand,
29746
29791
  lock: lockCommand,
29747
29792
  status: statusCommand$1,
29748
- list: listCommand$3,
29793
+ list: listCommand$4,
29749
29794
  view: viewCommand$1,
29750
29795
  download: downloadCommand,
29751
29796
  upload: uploadCommand,
29752
29797
  "upload-asc-key": uploadAscKeyCommand,
29753
29798
  generate: generateCommand$1,
29754
29799
  "regenerate-profile": regenerateProfileCommand,
29755
- delete: deleteCommand$3,
29800
+ delete: deleteCommand$4,
29756
29801
  remove: removeCommand,
29757
29802
  revoke: revokeCommand,
29758
29803
  configure: configureCommand$1,
@@ -30252,19 +30297,20 @@ const envErrorExtras = {
30252
30297
  SystemError: 6,
30253
30298
  BadArgument: 6
30254
30299
  };
30255
- const isEnvironmentName = (value) => value === "development" || value === "preview" || value === "production";
30300
+ const ENVIRONMENT_NAME_PATTERN = /^[a-z][a-z0-9-]*$/u;
30301
+ const isEnvironmentName = (value) => ENVIRONMENT_NAME_PATTERN.test(value) && value.length <= 64;
30256
30302
  const parseEnvironmentsArg = (raw) => Effect.gen(function* () {
30257
30303
  const tokens = raw.split(",").map((token) => token.trim()).filter((token) => token.length > 0);
30258
- if (tokens.length === 0) return yield* new InvalidArgumentError({ message: "Provide at least one environment (development, preview, production)." });
30304
+ if (tokens.length === 0) return yield* new InvalidArgumentError({ message: "Provide at least one environment (e.g. development, preview, production)." });
30259
30305
  const seen = /* @__PURE__ */ new Set();
30260
30306
  yield* Effect.forEach(tokens, (token) => Effect.gen(function* () {
30261
- if (!isEnvironmentName(token)) return yield* new InvalidArgumentError({ message: `Invalid environment "${token}". Must be one of: development, preview, production.` });
30307
+ if (!isEnvironmentName(token)) return yield* new InvalidArgumentError({ message: `Invalid environment "${token}": must be lowercase letters, digits, and hyphens, starting with a letter.` });
30262
30308
  seen.add(token);
30263
30309
  }), { discard: true });
30264
30310
  return [...seen];
30265
30311
  });
30266
30312
  const parseSingleEnvironmentArg = (raw) => Effect.gen(function* () {
30267
- if (!isEnvironmentName(raw)) return yield* new InvalidArgumentError({ message: `Invalid environment "${raw}". Must be one of: development, preview, production.` });
30313
+ if (!isEnvironmentName(raw)) return yield* new InvalidArgumentError({ message: `Invalid environment "${raw}": must be lowercase letters, digits, and hyphens, starting with a letter.` });
30268
30314
  return raw;
30269
30315
  });
30270
30316
  const formatEnvironments = (environments) => [...environments].toSorted((left, right) => left.localeCompare(right)).join(",");
@@ -30303,7 +30349,7 @@ const findProjectEnvVar = (api, projectId, key, environment) => Effect.gen(funct
30303
30349
 
30304
30350
  //#endregion
30305
30351
  //#region src/commands/env/delete.ts
30306
- const deleteCommand$2 = defineCommand({
30352
+ const deleteCommand$3 = defineCommand({
30307
30353
  meta: {
30308
30354
  name: "delete",
30309
30355
  description: "Delete a project env var (one environment, or every environment by default)"
@@ -30573,7 +30619,7 @@ const importCommand = defineCommand({
30573
30619
 
30574
30620
  //#endregion
30575
30621
  //#region src/commands/env/list.ts
30576
- const listCommand$2 = defineCommand({
30622
+ const listCommand$3 = defineCommand({
30577
30623
  meta: {
30578
30624
  name: "list",
30579
30625
  description: "List environment variable metadata. Values are end-to-end encrypted — read them with `env pull`, `env export`, or `env get`."
@@ -30920,11 +30966,11 @@ const envCommand = defineCommand({
30920
30966
  description: "Manage environment variables"
30921
30967
  },
30922
30968
  subCommands: {
30923
- list: listCommand$2,
30969
+ list: listCommand$3,
30924
30970
  get: getCommand$1,
30925
30971
  set: setCommand$1,
30926
30972
  update: updateCommand$1,
30927
- delete: deleteCommand$2,
30973
+ delete: deleteCommand$3,
30928
30974
  history: historyCommand,
30929
30975
  rollback: rollbackCommand$1,
30930
30976
  import: importCommand,
@@ -30935,6 +30981,93 @@ const envCommand = defineCommand({
30935
30981
  }
30936
30982
  });
30937
30983
 
30984
+ //#endregion
30985
+ //#region src/commands/environments.ts
30986
+ const listCommand$2 = defineCommand({
30987
+ meta: {
30988
+ name: "list",
30989
+ description: "List the organization's environments"
30990
+ },
30991
+ run: async () => runEffect(Effect.gen(function* () {
30992
+ const { items } = yield* (yield* apiClient).environments.list();
30993
+ yield* printList(["Name", "Built-in"], items.map((environment) => [environment.name, environment.isBuiltin ? "yes" : "no"]), "No environments found.");
30994
+ return items;
30995
+ }), { json: "value" })
30996
+ });
30997
+ const createCommand$1 = defineCommand({
30998
+ meta: {
30999
+ name: "create",
31000
+ description: "Create a user-defined environment"
31001
+ },
31002
+ args: { name: {
31003
+ type: "positional",
31004
+ required: true,
31005
+ description: "Environment name (lowercase letters, digits, hyphens)"
31006
+ } },
31007
+ run: async ({ args }) => runEffect(Effect.gen(function* () {
31008
+ const environment = yield* (yield* apiClient).environments.create({ payload: { name: args.name } });
31009
+ yield* printKeyValue([["Name", environment.name], ["Created", environment.createdAt]]);
31010
+ return environment;
31011
+ }), { json: "value" })
31012
+ });
31013
+ const renameCommand$1 = defineCommand({
31014
+ meta: {
31015
+ name: "rename",
31016
+ description: "Rename a user-defined environment"
31017
+ },
31018
+ args: {
31019
+ name: {
31020
+ type: "positional",
31021
+ required: true,
31022
+ description: "Current environment name"
31023
+ },
31024
+ to: {
31025
+ type: "string",
31026
+ required: true,
31027
+ description: "New environment name"
31028
+ }
31029
+ },
31030
+ run: async ({ args }) => runEffect(Effect.gen(function* () {
31031
+ const environment = yield* (yield* apiClient).environments.rename({
31032
+ path: { name: args.name },
31033
+ payload: { name: args.to }
31034
+ });
31035
+ yield* printHuman(`Environment renamed to "${environment.name}".`);
31036
+ return environment;
31037
+ }), { json: "value" })
31038
+ });
31039
+ const deleteCommand$2 = defineCommand({
31040
+ meta: {
31041
+ name: "delete",
31042
+ description: "Delete a user-defined environment"
31043
+ },
31044
+ args: { name: {
31045
+ type: "positional",
31046
+ required: true,
31047
+ description: "Environment name"
31048
+ } },
31049
+ run: async ({ args }) => runEffect(Effect.gen(function* () {
31050
+ yield* (yield* apiClient).environments.delete({ path: { name: args.name } });
31051
+ yield* printHuman(`Environment "${args.name}" deleted.`);
31052
+ return {
31053
+ name: args.name,
31054
+ deleted: true
31055
+ };
31056
+ }), { json: "value" })
31057
+ });
31058
+ const environmentsCommand = defineCommand({
31059
+ meta: {
31060
+ name: "environments",
31061
+ description: "Manage organization environments"
31062
+ },
31063
+ subCommands: {
31064
+ list: listCommand$2,
31065
+ create: createCommand$1,
31066
+ rename: renameCommand$1,
31067
+ delete: deleteCommand$2
31068
+ }
31069
+ });
31070
+
30938
31071
  //#endregion
30939
31072
  //#region src/commands/fingerprint/compare.ts
30940
31073
  /**
@@ -35468,6 +35601,7 @@ const commandRegistry = {
35468
35601
  groups: groupsCommand,
35469
35602
  branches: branchesCommand,
35470
35603
  channels: channelsCommand,
35604
+ environments: environmentsCommand,
35471
35605
  build: buildCommand,
35472
35606
  builds: buildsCommand,
35473
35607
  credentials: credentialsCommand,