@specific.dev/cli 0.1.119 → 0.1.121

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.
Files changed (67) hide show
  1. package/dist/admin/404/index.html +1 -1
  2. package/dist/admin/404.html +1 -1
  3. package/dist/admin/__next.!KGRlZmF1bHQp.__PAGE__.txt +1 -1
  4. package/dist/admin/__next.!KGRlZmF1bHQp.txt +1 -1
  5. package/dist/admin/__next._full.txt +1 -1
  6. package/dist/admin/__next._head.txt +1 -1
  7. package/dist/admin/__next._index.txt +1 -1
  8. package/dist/admin/__next._tree.txt +1 -1
  9. package/dist/admin/_not-found/__next._full.txt +1 -1
  10. package/dist/admin/_not-found/__next._head.txt +1 -1
  11. package/dist/admin/_not-found/__next._index.txt +1 -1
  12. package/dist/admin/_not-found/__next._not-found.__PAGE__.txt +1 -1
  13. package/dist/admin/_not-found/__next._not-found.txt +1 -1
  14. package/dist/admin/_not-found/__next._tree.txt +1 -1
  15. package/dist/admin/_not-found/index.html +1 -1
  16. package/dist/admin/_not-found/index.txt +1 -1
  17. package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.__PAGE__.txt +1 -1
  18. package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.txt +1 -1
  19. package/dist/admin/databases/__next.!KGRlZmF1bHQp.txt +1 -1
  20. package/dist/admin/databases/__next._full.txt +1 -1
  21. package/dist/admin/databases/__next._head.txt +1 -1
  22. package/dist/admin/databases/__next._index.txt +1 -1
  23. package/dist/admin/databases/__next._tree.txt +1 -1
  24. package/dist/admin/databases/index.html +1 -1
  25. package/dist/admin/databases/index.txt +1 -1
  26. package/dist/admin/fullscreen/__next._full.txt +1 -1
  27. package/dist/admin/fullscreen/__next._head.txt +1 -1
  28. package/dist/admin/fullscreen/__next._index.txt +1 -1
  29. package/dist/admin/fullscreen/__next._tree.txt +1 -1
  30. package/dist/admin/fullscreen/__next.fullscreen.__PAGE__.txt +1 -1
  31. package/dist/admin/fullscreen/__next.fullscreen.txt +1 -1
  32. package/dist/admin/fullscreen/databases/__next._full.txt +1 -1
  33. package/dist/admin/fullscreen/databases/__next._head.txt +1 -1
  34. package/dist/admin/fullscreen/databases/__next._index.txt +1 -1
  35. package/dist/admin/fullscreen/databases/__next._tree.txt +1 -1
  36. package/dist/admin/fullscreen/databases/__next.fullscreen.databases.__PAGE__.txt +1 -1
  37. package/dist/admin/fullscreen/databases/__next.fullscreen.databases.txt +1 -1
  38. package/dist/admin/fullscreen/databases/__next.fullscreen.txt +1 -1
  39. package/dist/admin/fullscreen/databases/index.html +1 -1
  40. package/dist/admin/fullscreen/databases/index.txt +1 -1
  41. package/dist/admin/fullscreen/index.html +1 -1
  42. package/dist/admin/fullscreen/index.txt +1 -1
  43. package/dist/admin/index.html +1 -1
  44. package/dist/admin/index.txt +1 -1
  45. package/dist/admin/mail/__next.!KGRlZmF1bHQp.mail.__PAGE__.txt +1 -1
  46. package/dist/admin/mail/__next.!KGRlZmF1bHQp.mail.txt +1 -1
  47. package/dist/admin/mail/__next.!KGRlZmF1bHQp.txt +1 -1
  48. package/dist/admin/mail/__next._full.txt +1 -1
  49. package/dist/admin/mail/__next._head.txt +1 -1
  50. package/dist/admin/mail/__next._index.txt +1 -1
  51. package/dist/admin/mail/__next._tree.txt +1 -1
  52. package/dist/admin/mail/index.html +1 -1
  53. package/dist/admin/mail/index.txt +1 -1
  54. package/dist/admin/workflows/__next.!KGRlZmF1bHQp.txt +1 -1
  55. package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.__PAGE__.txt +1 -1
  56. package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.txt +1 -1
  57. package/dist/admin/workflows/__next._full.txt +1 -1
  58. package/dist/admin/workflows/__next._head.txt +1 -1
  59. package/dist/admin/workflows/__next._index.txt +1 -1
  60. package/dist/admin/workflows/__next._tree.txt +1 -1
  61. package/dist/admin/workflows/index.html +1 -1
  62. package/dist/admin/workflows/index.txt +1 -1
  63. package/dist/cli.js +247 -26
  64. package/package.json +1 -1
  65. /package/dist/admin/_next/static/{Jq_9GUFfnF8eZkPZMF_EC → o659XHhGQCjk04D1G3u7n}/_buildManifest.js +0 -0
  66. /package/dist/admin/_next/static/{Jq_9GUFfnF8eZkPZMF_EC → o659XHhGQCjk04D1G3u7n}/_clientMiddlewareManifest.json +0 -0
  67. /package/dist/admin/_next/static/{Jq_9GUFfnF8eZkPZMF_EC → o659XHhGQCjk04D1G3u7n}/_ssgManifest.js +0 -0
package/dist/cli.js CHANGED
@@ -372288,6 +372288,10 @@ var DevEnvironment = class extends TypedEventEmitter {
372288
372288
  "system:error",
372289
372289
  `Reshape error for "${pg.name}": ${err.message}`
372290
372290
  );
372291
+ this.emit("log", {
372292
+ service: `${pg.name}:reshape`,
372293
+ text: err.message
372294
+ });
372291
372295
  },
372292
372296
  log: (msg) => this.systemLog(`[reshape:${pg.name}] ${msg}`)
372293
372297
  });
@@ -372304,9 +372308,12 @@ var DevEnvironment = class extends TypedEventEmitter {
372304
372308
  }
372305
372309
  startedReshapeWatchers.push(watcher);
372306
372310
  } catch (err) {
372307
- this.systemLog(
372308
- `Failed to initialize Reshape for "${pg.name}": ${err instanceof Error ? err.message : String(err)}`
372309
- );
372311
+ const message = `Failed to initialize Reshape for "${pg.name}": ${err instanceof Error ? err.message : String(err)}`;
372312
+ this.systemLog(message);
372313
+ this.emit("log", {
372314
+ service: `${pg.name}:reshape`,
372315
+ text: message
372316
+ });
372310
372317
  }
372311
372318
  }
372312
372319
  }
@@ -372759,6 +372766,7 @@ import * as crypto3 from "crypto";
372759
372766
  import * as fs3 from "fs";
372760
372767
  import * as path3 from "path";
372761
372768
  var PROJECT_ID_FILE = ".specific/project_id";
372769
+ var ENVIRONMENT_ID_FILE = ".specific/environment_id";
372762
372770
  var ProjectNotLinkedError = class extends Error {
372763
372771
  constructor() {
372764
372772
  super(
@@ -372793,6 +372801,28 @@ function writeProjectId(projectId, projectDir = process.cwd()) {
372793
372801
  }
372794
372802
  fs3.writeFileSync(path3.join(specificDir, "project_id"), projectId + "\n");
372795
372803
  }
372804
+ function readEnvironmentId(projectDir = process.cwd()) {
372805
+ const envIdPath = path3.join(projectDir, ENVIRONMENT_ID_FILE);
372806
+ if (!fs3.existsSync(envIdPath)) {
372807
+ throw new Error(`${ENVIRONMENT_ID_FILE} does not exist`);
372808
+ }
372809
+ const envId = fs3.readFileSync(envIdPath, "utf-8").trim();
372810
+ if (!envId) {
372811
+ throw new Error(`${ENVIRONMENT_ID_FILE} is empty`);
372812
+ }
372813
+ return envId;
372814
+ }
372815
+ function hasEnvironmentId(projectDir = process.cwd()) {
372816
+ const envIdPath = path3.join(projectDir, ENVIRONMENT_ID_FILE);
372817
+ return fs3.existsSync(envIdPath);
372818
+ }
372819
+ function writeEnvironmentId(environmentId, projectDir = process.cwd()) {
372820
+ const specificDir = path3.join(projectDir, ".specific");
372821
+ if (!fs3.existsSync(specificDir)) {
372822
+ fs3.mkdirSync(specificDir, { recursive: true });
372823
+ }
372824
+ fs3.writeFileSync(path3.join(specificDir, "environment_id"), environmentId + "\n");
372825
+ }
372796
372826
 
372797
372827
  // src/lib/auth/credentials.ts
372798
372828
  import * as fs19 from "fs";
@@ -373233,7 +373263,7 @@ function trackEvent(event, properties) {
373233
373263
  event,
373234
373264
  properties: {
373235
373265
  ...properties,
373236
- cli_version: "0.1.119",
373266
+ cli_version: "0.1.121",
373237
373267
  platform: process.platform,
373238
373268
  node_version: process.version,
373239
373269
  project_id: getProjectId()
@@ -374688,7 +374718,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
374688
374718
  }));
374689
374719
  });
374690
374720
  devEnv.on("log", (line) => {
374691
- const color = currentColorMap.get(`svc:${line.service}`) || "cyan";
374721
+ const color = currentColorMap.get(`svc:${line.service}`) || (line.service.endsWith(":reshape") ? "red" : "cyan");
374692
374722
  setState((s) => ({
374693
374723
  ...s,
374694
374724
  output: [
@@ -375208,6 +375238,28 @@ function NameInput({ onSubmit, onCancel }) {
375208
375238
  });
375209
375239
  return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Create new project"), /* @__PURE__ */ React7.createElement(Text7, null, "Enter project name:"), /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, "> "), /* @__PURE__ */ React7.createElement(Text7, null, value), /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, "|")), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "Press Enter to create, Esc to go back"));
375210
375240
  }
375241
+ function EnvironmentSelector({
375242
+ environments,
375243
+ selectedIndex,
375244
+ onSelect,
375245
+ onUp,
375246
+ onDown
375247
+ }) {
375248
+ useInput4((input, key) => {
375249
+ if (key.return) {
375250
+ const env2 = environments[selectedIndex];
375251
+ if (env2) onSelect(env2);
375252
+ } else if (key.upArrow) {
375253
+ onUp();
375254
+ } else if (key.downArrow) {
375255
+ onDown();
375256
+ }
375257
+ });
375258
+ return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Select an environment to deploy to:"), /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, environments.map((env2, index) => {
375259
+ const isSelected = index === selectedIndex;
375260
+ return /* @__PURE__ */ React7.createElement(Text7, { key: env2.id }, isSelected ? /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, " ", "> ") : /* @__PURE__ */ React7.createElement(Text7, null, " "), /* @__PURE__ */ React7.createElement(Text7, null, env2.name));
375261
+ })), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "Use arrow keys to navigate, Enter to select"));
375262
+ }
375211
375263
  function getMissingSecrets(pendingActions) {
375212
375264
  if (!pendingActions) return [];
375213
375265
  const secretAction = pendingActions.find((a) => a.type === "missing_secrets");
@@ -375244,7 +375296,7 @@ function formatErrorCode(code) {
375244
375296
  function StructuredError({ error }) {
375245
375297
  return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, /* @__PURE__ */ React7.createElement(Text7, { color: "red", bold: true }, formatErrorCode(error.code), ": ", error.message), error.resource && /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "Resource: ", error.resource), error.output && /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Output:"), /* @__PURE__ */ React7.createElement(Text7, null, error.output)));
375246
375298
  }
375247
- function DeployUI({ environment, config }) {
375299
+ function DeployUI({ envFlag, config }) {
375248
375300
  const { exit } = useApp3();
375249
375301
  const [state, setState] = useState6({ phase: "checking-auth" });
375250
375302
  const clientRef = React7.useRef(null);
@@ -375254,10 +375306,7 @@ function DeployUI({ environment, config }) {
375254
375306
  if (hasProjectId(projectDir)) {
375255
375307
  const projectId = readProjectId(projectDir);
375256
375308
  if (isLoggedIn()) {
375257
- setState({
375258
- phase: "creating-tarball",
375259
- projectId
375260
- });
375309
+ setState({ phase: "loading-environments", projectId });
375261
375310
  } else {
375262
375311
  setState({ phase: "logging-in", projectId });
375263
375312
  }
@@ -375312,7 +375361,7 @@ function DeployUI({ environment, config }) {
375312
375361
  const successResponse = response;
375313
375362
  await saveCredentialsFromToken(successResponse);
375314
375363
  setState(
375315
- (s) => s.projectId ? { phase: "creating-tarball", projectId: s.projectId } : { phase: "loading-projects" }
375364
+ (s) => s.projectId ? { phase: "loading-environments", projectId: s.projectId } : { phase: "loading-projects" }
375316
375365
  );
375317
375366
  }
375318
375367
  };
@@ -375371,8 +375420,9 @@ function DeployUI({ environment, config }) {
375371
375420
  const proj = project;
375372
375421
  writeProjectId(proj.id);
375373
375422
  setState({
375374
- phase: "creating-tarball",
375375
- projectId: proj.id
375423
+ phase: "loading-environments",
375424
+ projectId: proj.id,
375425
+ environments: proj.environments
375376
375426
  });
375377
375427
  }
375378
375428
  },
@@ -375395,8 +375445,9 @@ function DeployUI({ environment, config }) {
375395
375445
  if (cancelled) return;
375396
375446
  writeProjectId(project.id);
375397
375447
  setState({
375398
- phase: "creating-tarball",
375399
- projectId: project.id
375448
+ phase: "loading-environments",
375449
+ projectId: project.id,
375450
+ environments: project.environments
375400
375451
  });
375401
375452
  } catch (err) {
375402
375453
  if (cancelled) return;
@@ -375411,6 +375462,101 @@ function DeployUI({ environment, config }) {
375411
375462
  cancelled = true;
375412
375463
  };
375413
375464
  }, [state.phase, state.newProjectName]);
375465
+ useEffect6(() => {
375466
+ if (state.phase !== "loading-environments" || !state.projectId) return;
375467
+ let cancelled = false;
375468
+ async function loadEnvironments() {
375469
+ try {
375470
+ let environments = state.environments;
375471
+ if (!environments) {
375472
+ const token = await getValidAccessToken();
375473
+ const client2 = new SpecificClient({ accessToken: token });
375474
+ const projects2 = await client2.listProjects();
375475
+ const project = projects2.find((p) => p.id === state.projectId);
375476
+ environments = project?.environments ?? [];
375477
+ }
375478
+ if (cancelled) return;
375479
+ if (environments.length === 0) {
375480
+ setState((s) => ({
375481
+ ...s,
375482
+ phase: "error",
375483
+ error: "No environments found for this project"
375484
+ }));
375485
+ return;
375486
+ }
375487
+ if (envFlag) {
375488
+ const match = environments.find((e) => e.name === envFlag);
375489
+ if (!match) {
375490
+ setState((s) => ({
375491
+ ...s,
375492
+ phase: "error",
375493
+ error: `Environment "${envFlag}" not found. Available: ${environments.map((e) => e.name).join(", ")}`
375494
+ }));
375495
+ return;
375496
+ }
375497
+ writeEnvironmentId(match.id);
375498
+ setState((s) => ({
375499
+ ...s,
375500
+ phase: "creating-tarball",
375501
+ environmentName: match.name,
375502
+ environments
375503
+ }));
375504
+ return;
375505
+ }
375506
+ const projectDir = process.cwd();
375507
+ if (hasEnvironmentId(projectDir)) {
375508
+ const savedEnvId = readEnvironmentId(projectDir);
375509
+ const match = environments.find((e) => e.id === savedEnvId);
375510
+ if (match) {
375511
+ setState((s) => ({
375512
+ ...s,
375513
+ phase: "creating-tarball",
375514
+ environmentName: match.name,
375515
+ environments
375516
+ }));
375517
+ return;
375518
+ }
375519
+ }
375520
+ if (environments.length === 1) {
375521
+ writeEnvironmentId(environments[0].id);
375522
+ setState((s) => ({
375523
+ ...s,
375524
+ phase: "creating-tarball",
375525
+ environmentName: environments[0].name,
375526
+ environments
375527
+ }));
375528
+ return;
375529
+ }
375530
+ setState((s) => ({
375531
+ ...s,
375532
+ phase: "selecting-environment",
375533
+ environments,
375534
+ environmentSelectedIndex: 0
375535
+ }));
375536
+ } catch (err) {
375537
+ if (cancelled) return;
375538
+ setState({
375539
+ phase: "error",
375540
+ error: err instanceof Error ? err.message : String(err)
375541
+ });
375542
+ }
375543
+ }
375544
+ loadEnvironments();
375545
+ return () => {
375546
+ cancelled = true;
375547
+ };
375548
+ }, [state.phase, state.projectId]);
375549
+ const handleEnvironmentSelect = useCallback3(
375550
+ (env2) => {
375551
+ writeEnvironmentId(env2.id);
375552
+ setState((s) => ({
375553
+ ...s,
375554
+ phase: "creating-tarball",
375555
+ environmentName: env2.name
375556
+ }));
375557
+ },
375558
+ []
375559
+ );
375414
375560
  const handleSecretSubmit = useCallback3((value) => {
375415
375561
  setState((s) => {
375416
375562
  if (!s.missingSecrets || s.currentSecretIndex === void 0) return s;
@@ -375555,12 +375701,13 @@ function DeployUI({ environment, config }) {
375555
375701
  }
375556
375702
  })();
375557
375703
  }, [state]);
375704
+ const environment = state.environmentName || "prod";
375558
375705
  useEffect6(() => {
375559
- if (state.phase !== "creating-tarball" || !state.projectId) return;
375706
+ if (state.phase !== "creating-tarball" || !state.projectId || !state.environmentName) return;
375560
375707
  let cancelled = false;
375561
375708
  async function runDeploy() {
375562
375709
  const projectDir = process.cwd();
375563
- writeLog("deploy", `Starting deployment to "${environment}"`);
375710
+ writeLog("deploy", `Starting deployment to "${state.environmentName}"`);
375564
375711
  writeLog("deploy", `Project directory: ${projectDir}`);
375565
375712
  const client2 = new SpecificClient({ tokenProvider: getValidAccessToken });
375566
375713
  clientRef.current = client2;
@@ -375592,7 +375739,7 @@ function DeployUI({ environment, config }) {
375592
375739
  try {
375593
375740
  writeLog("deploy", `Creating deployment for project ${state.projectId}`);
375594
375741
  const gitInfo = getGitInfo(projectDir);
375595
- deployment2 = await client2.createDeployment(state.projectId, environment, {
375742
+ deployment2 = await client2.createDeployment(state.projectId, state.environmentName, {
375596
375743
  triggeredBy: "cli",
375597
375744
  ...gitInfo && {
375598
375745
  gitCommitSha: gitInfo.commitSha,
@@ -375634,7 +375781,7 @@ function DeployUI({ environment, config }) {
375634
375781
  return () => {
375635
375782
  cancelled = true;
375636
375783
  };
375637
- }, [state.projectId, environment, config.builds]);
375784
+ }, [state.projectId, state.environmentName, config.builds]);
375638
375785
  useEffect6(() => {
375639
375786
  if (state.phase !== "pending" || !state.deployment) return;
375640
375787
  let pollInterval;
@@ -375902,6 +376049,30 @@ function DeployUI({ environment, config }) {
375902
376049
  if (phase === "creating-project") {
375903
376050
  return /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "blue" }, /* @__PURE__ */ React7.createElement(Spinner4, { type: "dots" })), /* @__PURE__ */ React7.createElement(Text7, null, " Creating project..."));
375904
376051
  }
376052
+ if (phase === "loading-environments") {
376053
+ return /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "blue" }, /* @__PURE__ */ React7.createElement(Spinner4, { type: "dots" })), /* @__PURE__ */ React7.createElement(Text7, null, " Loading environments..."));
376054
+ }
376055
+ if (phase === "selecting-environment" && state.environments && state.environmentSelectedIndex !== void 0) {
376056
+ return /* @__PURE__ */ React7.createElement(
376057
+ EnvironmentSelector,
376058
+ {
376059
+ environments: state.environments,
376060
+ selectedIndex: state.environmentSelectedIndex,
376061
+ onSelect: handleEnvironmentSelect,
376062
+ onUp: () => setState((s) => ({
376063
+ ...s,
376064
+ environmentSelectedIndex: Math.max(0, (s.environmentSelectedIndex ?? 0) - 1)
376065
+ })),
376066
+ onDown: () => setState((s) => ({
376067
+ ...s,
376068
+ environmentSelectedIndex: Math.min(
376069
+ (s.environments?.length ?? 1) - 1,
376070
+ (s.environmentSelectedIndex ?? 0) + 1
376071
+ )
376072
+ }))
376073
+ }
376074
+ );
376075
+ }
375905
376076
  const currentSecret = missingSecrets && currentSecretIndex !== void 0 ? missingSecrets[currentSecretIndex] : void 0;
375906
376077
  const currentConfig = missingConfigs && currentConfigIndex !== void 0 ? missingConfigs[currentConfigIndex] : void 0;
375907
376078
  const getDisplayPhase = () => {
@@ -376007,6 +376178,52 @@ async function runDeployPipeline(options2) {
376007
376178
  } else if (!hasProjectId(projectDir)) {
376008
376179
  writeProjectId(projectId);
376009
376180
  }
376181
+ let environmentName;
376182
+ if (options2.env) {
376183
+ environmentName = options2.env;
376184
+ } else if (hasEnvironmentId(projectDir)) {
376185
+ const savedEnvId = readEnvironmentId(projectDir);
376186
+ const projects = await client2.listProjects();
376187
+ const project = projects.find((p) => p.id === projectId);
376188
+ const env2 = project?.environments.find((e) => e.id === savedEnvId);
376189
+ if (env2) {
376190
+ environmentName = env2.name;
376191
+ } else {
376192
+ const environments = project?.environments ?? [];
376193
+ if (environments.length === 1) {
376194
+ environmentName = environments[0].name;
376195
+ writeEnvironmentId(environments[0].id);
376196
+ } else if (environments.length === 0) {
376197
+ console.error("Error: No environments found for this project");
376198
+ process.exit(1);
376199
+ } else {
376200
+ console.error(
376201
+ `Error: Multiple environments available. Specify one with --env.
376202
+ Available: ${environments.map((e) => e.name).join(", ")}
376203
+ Example: specific deploy --env ${environments[0].name}`
376204
+ );
376205
+ process.exit(1);
376206
+ }
376207
+ }
376208
+ } else {
376209
+ const projects = await client2.listProjects();
376210
+ const project = projects.find((p) => p.id === projectId);
376211
+ const environments = project?.environments ?? [];
376212
+ if (environments.length === 1) {
376213
+ environmentName = environments[0].name;
376214
+ writeEnvironmentId(environments[0].id);
376215
+ } else if (environments.length === 0) {
376216
+ console.error("Error: No environments found for this project");
376217
+ process.exit(1);
376218
+ } else {
376219
+ console.error(
376220
+ `Error: Multiple environments available. Specify one with --env.
376221
+ Available: ${environments.map((e) => e.name).join(", ")}
376222
+ Example: specific deploy --env ${environments[0].name}`
376223
+ );
376224
+ process.exit(1);
376225
+ }
376226
+ }
376010
376227
  const parsedSecrets = {};
376011
376228
  if (options2.secrets) {
376012
376229
  for (const s of options2.secrets) {
@@ -376040,7 +376257,7 @@ async function runDeployPipeline(options2) {
376040
376257
  let deployment;
376041
376258
  try {
376042
376259
  const gitInfo = getGitInfo(projectDir);
376043
- deployment = await client2.createDeployment(projectId, "prod", {
376260
+ deployment = await client2.createDeployment(projectId, environmentName, {
376044
376261
  triggeredBy: "cli",
376045
376262
  ...gitInfo && {
376046
376263
  gitCommitSha: gitInfo.commitSha,
@@ -376187,6 +376404,7 @@ async function deployCommand(options2) {
376187
376404
  await runDeployPipeline({
376188
376405
  config,
376189
376406
  projectId: options2.project,
376407
+ env: options2.env,
376190
376408
  secrets: options2.secret,
376191
376409
  configs: options2.config
376192
376410
  });
@@ -376196,7 +376414,7 @@ async function deployCommand(options2) {
376196
376414
  /* @__PURE__ */ React7.createElement(
376197
376415
  DeployUI,
376198
376416
  {
376199
- environment: "prod",
376417
+ envFlag: options2.env,
376200
376418
  config
376201
376419
  }
376202
376420
  )
@@ -377057,7 +377275,7 @@ function compareVersions(a, b) {
377057
377275
  return 0;
377058
377276
  }
377059
377277
  async function checkForUpdate() {
377060
- const currentVersion = "0.1.119";
377278
+ const currentVersion = "0.1.121";
377061
377279
  const response = await fetch(`${BINARIES_BASE_URL}/latest?t=${Date.now()}`);
377062
377280
  if (!response.ok) {
377063
377281
  throw new Error(`Failed to check for updates: HTTP ${response.status}`);
@@ -377306,12 +377524,14 @@ async function projectListCommand() {
377306
377524
  if (!grouped.has(orgName)) {
377307
377525
  grouped.set(orgName, []);
377308
377526
  }
377309
- grouped.get(orgName).push({ id: project.id, name: project.name });
377527
+ grouped.get(orgName).push({ id: project.id, name: project.name, environments: project.environments });
377310
377528
  }
377311
377529
  for (const [orgName, orgProjects] of grouped) {
377312
377530
  console.log(`${orgName}:`);
377313
377531
  for (const project of orgProjects) {
377314
- console.log(` ${project.name} (${project.id})`);
377532
+ const envNames = project.environments.map((e) => e.name).join(", ");
377533
+ const envSuffix = envNames ? ` \u2014 ${envNames}` : "";
377534
+ console.log(` ${project.name} (${project.id})${envSuffix}`);
377315
377535
  }
377316
377536
  }
377317
377537
  } catch (error) {
@@ -377325,7 +377545,7 @@ async function projectListCommand() {
377325
377545
  var program = new Command();
377326
377546
  var env = "production";
377327
377547
  var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
377328
- program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.119").enablePositionalOptions();
377548
+ program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.121").enablePositionalOptions();
377329
377549
  program.command("init").description("Initialize project for use with a coding agent").option("--agent <name...>", "Agents to configure (cursor, claude, codex, other)").addHelpText("after", `
377330
377550
  Examples:
377331
377551
  $ specific init
@@ -377346,9 +377566,10 @@ Examples:
377346
377566
  const key = options2.key ?? getDefaultKey();
377347
377567
  devCommand(key, options2.tunnel ?? false);
377348
377568
  });
377349
- program.command("deploy").description("Deploy to Specific infrastructure").option("--project <id>", "Project ID to deploy to (overrides .projectid file)").option("--secret <key=value...>", "Secret values (repeatable)").option("--config <key=value...>", "Config values (repeatable)").addHelpText("after", `
377569
+ program.command("deploy").description("Deploy to Specific infrastructure").option("--project <id>", "Project ID to deploy to (overrides .projectid file)").option("--env <name>", "Target environment (auto-selected if only one exists)").option("--secret <key=value...>", "Secret values (repeatable)").option("--config <key=value...>", "Config values (repeatable)").addHelpText("after", `
377350
377570
  Examples:
377351
377571
  $ specific deploy
377572
+ $ specific deploy --env staging
377352
377573
  $ specific deploy --project proj_123
377353
377574
  $ specific deploy --secret db_url=postgres://... --config domain=app.com`).action((options2) => {
377354
377575
  deployCommand(options2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specific.dev/cli",
3
- "version": "0.1.119",
3
+ "version": "0.1.121",
4
4
  "description": "CLI for Specific infrastructure-as-code",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",