@specific.dev/cli 0.1.73 → 0.1.75

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 (68) 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 +201 -357
  64. package/dist/postinstall.js +1 -1
  65. package/package.json +1 -1
  66. /package/dist/admin/_next/static/{2GhRJUspcGN_TKmFF6ihm → ntsk0waJiBFcaeQ8sbm0K}/_buildManifest.js +0 -0
  67. /package/dist/admin/_next/static/{2GhRJUspcGN_TKmFF6ihm → ntsk0waJiBFcaeQ8sbm0K}/_clientMiddlewareManifest.json +0 -0
  68. /package/dist/admin/_next/static/{2GhRJUspcGN_TKmFF6ihm → ntsk0waJiBFcaeQ8sbm0K}/_ssgManifest.js +0 -0
package/dist/cli.js CHANGED
@@ -637,19 +637,19 @@ var init_open = __esm({
637
637
  }
638
638
  const subprocess = childProcess3.spawn(command, cliArguments, childProcessOptions);
639
639
  if (options2.wait) {
640
- return new Promise((resolve10, reject) => {
640
+ return new Promise((resolve9, reject) => {
641
641
  subprocess.once("error", reject);
642
642
  subprocess.once("close", (exitCode) => {
643
643
  if (!options2.allowNonzeroExitCode && exitCode !== 0) {
644
644
  reject(new Error(`Exited with code ${exitCode}`));
645
645
  return;
646
646
  }
647
- resolve10(subprocess);
647
+ resolve9(subprocess);
648
648
  });
649
649
  });
650
650
  }
651
651
  if (isFallbackAttempt) {
652
- return new Promise((resolve10, reject) => {
652
+ return new Promise((resolve9, reject) => {
653
653
  subprocess.once("error", reject);
654
654
  subprocess.once("spawn", () => {
655
655
  subprocess.once("close", (exitCode) => {
@@ -659,17 +659,17 @@ var init_open = __esm({
659
659
  return;
660
660
  }
661
661
  subprocess.unref();
662
- resolve10(subprocess);
662
+ resolve9(subprocess);
663
663
  });
664
664
  });
665
665
  });
666
666
  }
667
667
  subprocess.unref();
668
- return new Promise((resolve10, reject) => {
668
+ return new Promise((resolve9, reject) => {
669
669
  subprocess.once("error", reject);
670
670
  subprocess.once("spawn", () => {
671
671
  subprocess.off("error", reject);
672
- resolve10(subprocess);
672
+ resolve9(subprocess);
673
673
  });
674
674
  });
675
675
  };
@@ -183485,7 +183485,11 @@ function caInstalledInTrustStore() {
183485
183485
  } else if (platform6 === "linux") {
183486
183486
  const trustPaths = [
183487
183487
  "/usr/local/share/ca-certificates/specific-local-ca.crt",
183488
- "/etc/pki/ca-trust/source/anchors/specific-local-ca.crt"
183488
+ // Debian/Ubuntu
183489
+ "/etc/pki/ca-trust/source/anchors/specific-local-ca.crt",
183490
+ // RHEL/Fedora
183491
+ "/etc/ca-certificates/trust-source/anchors/specific-local-ca.crt"
183492
+ // Arch
183489
183493
  ];
183490
183494
  for (const trustPath of trustPaths) {
183491
183495
  if (fs.existsSync(trustPath)) {
@@ -183609,6 +183613,11 @@ function getCAInstallCommands(certPath) {
183609
183613
  `cp "${certPath}" /etc/pki/ca-trust/source/anchors/specific-local-ca.crt`,
183610
183614
  "update-ca-trust extract"
183611
183615
  ];
183616
+ } else if (fs.existsSync("/etc/ca-certificates/trust-source/anchors")) {
183617
+ return [
183618
+ `cp "${certPath}" /etc/ca-certificates/trust-source/anchors/specific-local-ca.crt`,
183619
+ "trust extract-compat"
183620
+ ];
183612
183621
  }
183613
183622
  throw new Error("Could not detect Linux certificate trust mechanism");
183614
183623
  }
@@ -184046,7 +184055,7 @@ async function pollUntilToken(deviceAuth, isCancelled) {
184046
184055
  return null;
184047
184056
  }
184048
184057
  function sleep(ms) {
184049
- return new Promise((resolve10) => setTimeout(resolve10, ms));
184058
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
184050
184059
  }
184051
184060
 
184052
184061
  // src/lib/auth/login.tsx
@@ -184063,7 +184072,7 @@ function LoginUI({
184063
184072
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", gap: 1 }, isReauthentication && /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "Session expired. Please log in again."), /* @__PURE__ */ React.createElement(Text, { bold: true }, "Log in to Specific"), state.phase === "waiting-for-browser" ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, null, "Your authentication code:", " ", /* @__PURE__ */ React.createElement(Text, { color: "cyan", bold: true }, state.userCode))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "blue" }, /* @__PURE__ */ React.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React.createElement(Text, null, " Waiting for authentication in browser...")), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "If the browser didn't open, visit: ", state.verificationUri)) : /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "blue" }, /* @__PURE__ */ React.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React.createElement(Text, null, " Initiating login...")));
184064
184073
  }
184065
184074
  function performLogin(options2 = {}) {
184066
- return new Promise((resolve10) => {
184075
+ return new Promise((resolve9) => {
184067
184076
  let currentState = { phase: "initiating" };
184068
184077
  let flowHandle;
184069
184078
  const instance = render(
@@ -184103,14 +184112,14 @@ function performLogin(options2 = {}) {
184103
184112
  process.off("SIGINT", handleExit);
184104
184113
  process.off("SIGTERM", handleExit);
184105
184114
  instance.unmount();
184106
- resolve10({ success: true, userEmail: newState.email });
184115
+ resolve9({ success: true, userEmail: newState.email });
184107
184116
  }, 100);
184108
184117
  } else if (newState.phase === "error") {
184109
184118
  setTimeout(() => {
184110
184119
  process.off("SIGINT", handleExit);
184111
184120
  process.off("SIGTERM", handleExit);
184112
184121
  instance.unmount();
184113
- resolve10({ success: false, error: new Error(newState.message) });
184122
+ resolve9({ success: false, error: new Error(newState.message) });
184114
184123
  }, 100);
184115
184124
  }
184116
184125
  }
@@ -184362,9 +184371,12 @@ var ApiClient = class {
184362
184371
  }
184363
184372
  return response.json();
184364
184373
  }
184365
- async createProject(name) {
184374
+ async createProject(name, organizationId) {
184366
184375
  const url = `${this.baseUrl}/projects`;
184367
184376
  const requestBody = { name };
184377
+ if (organizationId) {
184378
+ requestBody.organizationId = organizationId;
184379
+ }
184368
184380
  writeLog("api", `POST ${url}`);
184369
184381
  writeLog("api", `Request body: ${JSON.stringify(requestBody)}`);
184370
184382
  const response = await fetch(url, {
@@ -184399,6 +184411,31 @@ var ApiClient = class {
184399
184411
  }
184400
184412
  return response.json();
184401
184413
  }
184414
+ async listOrganizations() {
184415
+ const url = `${this.baseUrl}/user/organizations`;
184416
+ writeLog("api", `GET ${url}`);
184417
+ const response = await fetch(url, {
184418
+ headers: await this.authHeaders()
184419
+ });
184420
+ writeLog("api", `Response: ${response.status} ${response.statusText}`);
184421
+ if (!response.ok) {
184422
+ let errorBody;
184423
+ try {
184424
+ const error = await response.json();
184425
+ errorBody = JSON.stringify(error);
184426
+ writeLog("api:error", `API error: ${error.error} (${error.code})`);
184427
+ throw new Error(`Failed to list organizations: ${error.error} (${error.code})`);
184428
+ } catch (e) {
184429
+ if (e instanceof Error && e.message.startsWith("Failed to list organizations")) {
184430
+ throw e;
184431
+ }
184432
+ errorBody = await response.text();
184433
+ writeLog("api:error", `Failed to parse error response: ${errorBody}`);
184434
+ throw new Error(`Failed to list organizations: ${response.statusText}`);
184435
+ }
184436
+ }
184437
+ return response.json();
184438
+ }
184402
184439
  async getMe(signal) {
184403
184440
  const url = `${this.baseUrl}/users/me`;
184404
184441
  writeLog("api", `GET ${url}`);
@@ -184587,7 +184624,7 @@ function trackEvent(event, properties) {
184587
184624
  event,
184588
184625
  properties: {
184589
184626
  ...properties,
184590
- cli_version: "0.1.73",
184627
+ cli_version: "0.1.75",
184591
184628
  platform: process.platform,
184592
184629
  node_version: process.version,
184593
184630
  project_id: getProjectId()
@@ -186048,10 +186085,10 @@ async function downloadFile(url, destPath, onProgress) {
186048
186085
  });
186049
186086
  }
186050
186087
  }
186051
- await new Promise((resolve10, reject) => {
186088
+ await new Promise((resolve9, reject) => {
186052
186089
  fileStream.end((err) => {
186053
186090
  if (err) reject(err);
186054
- else resolve10();
186091
+ else resolve9();
186055
186092
  });
186056
186093
  });
186057
186094
  fs13.renameSync(partPath, destPath);
@@ -186277,13 +186314,13 @@ async function runReshapeCheck(migrationsDir) {
186277
186314
  try {
186278
186315
  const binary = await ensureBinary(reshapeBinary);
186279
186316
  const reshapePath = binary.executables["reshape"];
186280
- return new Promise((resolve10) => {
186317
+ return new Promise((resolve9) => {
186281
186318
  execFile7(reshapePath, ["check", "--dirs", migrationsDir], (err, _stdout, stderr) => {
186282
186319
  if (err) {
186283
186320
  const errorMsg = stderr.trim() || err.message;
186284
- resolve10({ success: false, error: errorMsg });
186321
+ resolve9({ success: false, error: errorMsg });
186285
186322
  } else {
186286
- resolve10({ success: true });
186323
+ resolve9({ success: true });
186287
186324
  }
186288
186325
  });
186289
186326
  });
@@ -187252,7 +187289,7 @@ var NodeFsHandler = class {
187252
187289
  this._addToNodeFs(path30, initialAdd, wh, depth + 1);
187253
187290
  }
187254
187291
  }).on(EV.ERROR, this._boundHandleError);
187255
- return new Promise((resolve10, reject) => {
187292
+ return new Promise((resolve9, reject) => {
187256
187293
  if (!stream)
187257
187294
  return reject();
187258
187295
  stream.once(STR_END, () => {
@@ -187261,7 +187298,7 @@ var NodeFsHandler = class {
187261
187298
  return;
187262
187299
  }
187263
187300
  const wasThrottled = throttler ? throttler.clear() : false;
187264
- resolve10(void 0);
187301
+ resolve9(void 0);
187265
187302
  previous.getChildren().filter((item) => {
187266
187303
  return item !== directory && !current.has(item);
187267
187304
  }).forEach((item) => {
@@ -188325,7 +188362,7 @@ async function startStorage(storage, port, dataDir) {
188325
188362
  };
188326
188363
  }
188327
188364
  async function runCommand(command, args, env2) {
188328
- return new Promise((resolve10, reject) => {
188365
+ return new Promise((resolve9, reject) => {
188329
188366
  const proc = spawn(command, args, {
188330
188367
  stdio: ["ignore", "pipe", "pipe"],
188331
188368
  env: env2
@@ -188336,7 +188373,7 @@ async function runCommand(command, args, env2) {
188336
188373
  });
188337
188374
  proc.on("close", (code) => {
188338
188375
  if (code === 0) {
188339
- resolve10();
188376
+ resolve9();
188340
188377
  } else {
188341
188378
  reject(new Error(`Command failed with code ${code}: ${stderr}`));
188342
188379
  }
@@ -188345,7 +188382,7 @@ async function runCommand(command, args, env2) {
188345
188382
  });
188346
188383
  }
188347
188384
  async function createPostgresDatabase(postgresPath, dataDir, dbName, env2) {
188348
- return new Promise((resolve10, reject) => {
188385
+ return new Promise((resolve9, reject) => {
188349
188386
  const proc = spawn(
188350
188387
  postgresPath,
188351
188388
  ["--single", "-D", dataDir, "postgres"],
@@ -188359,7 +188396,7 @@ async function createPostgresDatabase(postgresPath, dataDir, dbName, env2) {
188359
188396
  stderr += data.toString();
188360
188397
  });
188361
188398
  proc.on("close", (code) => {
188362
- resolve10();
188399
+ resolve9();
188363
188400
  });
188364
188401
  proc.on("error", reject);
188365
188402
  proc.stdin?.write(`CREATE DATABASE "${dbName}";
@@ -188379,33 +188416,33 @@ async function waitForTcpPort(host, port, timeoutMs = 3e4) {
188379
188416
  throw new Error(`Port ${port} did not become available within timeout`);
188380
188417
  }
188381
188418
  function checkTcpPort(host, port) {
188382
- return new Promise((resolve10) => {
188419
+ return new Promise((resolve9) => {
188383
188420
  const socket = new net.Socket();
188384
188421
  socket.setTimeout(1e3);
188385
188422
  socket.on("connect", () => {
188386
188423
  socket.destroy();
188387
- resolve10(true);
188424
+ resolve9(true);
188388
188425
  });
188389
188426
  socket.on("timeout", () => {
188390
188427
  socket.destroy();
188391
- resolve10(false);
188428
+ resolve9(false);
188392
188429
  });
188393
188430
  socket.on("error", () => {
188394
188431
  socket.destroy();
188395
- resolve10(false);
188432
+ resolve9(false);
188396
188433
  });
188397
188434
  socket.connect(port, host);
188398
188435
  });
188399
188436
  }
188400
188437
  async function stopProcess(proc) {
188401
- return new Promise((resolve10) => {
188438
+ return new Promise((resolve9) => {
188402
188439
  if (proc.killed || proc.exitCode !== null) {
188403
- resolve10();
188440
+ resolve9();
188404
188441
  return;
188405
188442
  }
188406
188443
  proc.once("exit", () => {
188407
188444
  clearTimeout(forceKillTimeout);
188408
- resolve10();
188445
+ resolve9();
188409
188446
  });
188410
188447
  proc.kill("SIGTERM");
188411
188448
  const forceKillTimeout = setTimeout(() => {
@@ -188416,7 +188453,7 @@ async function stopProcess(proc) {
188416
188453
  });
188417
188454
  }
188418
188455
  function sleep2(ms) {
188419
- return new Promise((resolve10) => setTimeout(resolve10, ms));
188456
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
188420
188457
  }
188421
188458
 
188422
188459
  // src/lib/dev/service-runner.ts
@@ -188900,14 +188937,14 @@ function startService(service, resources, secrets, configs, endpointPorts, servi
188900
188937
  ports: endpointPorts,
188901
188938
  process: child,
188902
188939
  async stop() {
188903
- return new Promise((resolve10) => {
188940
+ return new Promise((resolve9) => {
188904
188941
  if (child.killed || child.exitCode !== null) {
188905
- resolve10();
188942
+ resolve9();
188906
188943
  return;
188907
188944
  }
188908
188945
  child.once("exit", () => {
188909
188946
  clearTimeout(forceKillTimeout);
188910
- resolve10();
188947
+ resolve9();
188911
188948
  });
188912
188949
  const pid = child.pid;
188913
188950
  if (pid) {
@@ -189001,7 +189038,7 @@ var InstanceStateManager = class {
189001
189038
  }
189002
189039
  continue;
189003
189040
  }
189004
- await new Promise((resolve10) => setTimeout(resolve10, 100));
189041
+ await new Promise((resolve9) => setTimeout(resolve9, 100));
189005
189042
  } else {
189006
189043
  throw e;
189007
189044
  }
@@ -189334,7 +189371,7 @@ async function startHttpProxy(services, certificate, getState, instanceKey = "de
189334
189371
  handleRequest
189335
189372
  );
189336
189373
  httpsServer.on("upgrade", handleUpgrade);
189337
- return new Promise((resolve10, reject) => {
189374
+ return new Promise((resolve9, reject) => {
189338
189375
  let httpStarted = false;
189339
189376
  let httpsStarted = false;
189340
189377
  let failed = false;
@@ -189345,7 +189382,7 @@ async function startHttpProxy(services, certificate, getState, instanceKey = "de
189345
189382
  "proxy",
189346
189383
  `HTTP/HTTPS proxy started on ports ${HTTP_PORT}/${HTTPS_PORT}`
189347
189384
  );
189348
- resolve10({
189385
+ resolve9({
189349
189386
  httpPort: HTTP_PORT,
189350
189387
  httpsPort: HTTPS_PORT,
189351
189388
  updateServices,
@@ -189357,13 +189394,13 @@ async function startHttpProxy(services, certificate, getState, instanceKey = "de
189357
189394
  writeLog("proxy", "Certificate updated");
189358
189395
  },
189359
189396
  async stop() {
189360
- return new Promise((resolve11) => {
189397
+ return new Promise((resolve10) => {
189361
189398
  let closed = 0;
189362
189399
  const onClose = () => {
189363
189400
  closed++;
189364
189401
  if (closed === 2) {
189365
189402
  clearTimeout(forceCloseTimeout);
189366
- resolve11();
189403
+ resolve10();
189367
189404
  }
189368
189405
  };
189369
189406
  httpServer.close(onClose);
@@ -189371,7 +189408,7 @@ async function startHttpProxy(services, certificate, getState, instanceKey = "de
189371
189408
  const forceCloseTimeout = setTimeout(() => {
189372
189409
  httpServer.closeAllConnections?.();
189373
189410
  httpsServer.closeAllConnections?.();
189374
- resolve11();
189411
+ resolve10();
189375
189412
  }, 2e3);
189376
189413
  });
189377
189414
  }
@@ -189599,7 +189636,7 @@ function serveFileContent(res, filePath, contentType, statusCode = 200) {
189599
189636
  }
189600
189637
  }
189601
189638
  async function startAdminServer(getState) {
189602
- return new Promise((resolve10, reject) => {
189639
+ return new Promise((resolve9, reject) => {
189603
189640
  const server = http.createServer((req, res) => {
189604
189641
  const url = new URL(req.url || "/", "http://localhost");
189605
189642
  res.setHeader("Access-Control-Allow-Origin", "*");
@@ -189631,7 +189668,7 @@ async function startAdminServer(getState) {
189631
189668
  }
189632
189669
  const port = addr.port;
189633
189670
  writeLog("admin", `Admin API server started on port ${port}`);
189634
- resolve10({
189671
+ resolve9({
189635
189672
  port,
189636
189673
  stop: () => new Promise((res, rej) => {
189637
189674
  server.close((err) => err ? rej(err) : res());
@@ -189792,33 +189829,33 @@ async function waitForTcpPort2(host, port, timeoutMs = 3e4) {
189792
189829
  throw new Error(`Electric port ${port} did not become available within timeout`);
189793
189830
  }
189794
189831
  function checkTcpPort2(host, port) {
189795
- return new Promise((resolve10) => {
189832
+ return new Promise((resolve9) => {
189796
189833
  const socket = new net2.Socket();
189797
189834
  socket.setTimeout(1e3);
189798
189835
  socket.on("connect", () => {
189799
189836
  socket.destroy();
189800
- resolve10(true);
189837
+ resolve9(true);
189801
189838
  });
189802
189839
  socket.on("timeout", () => {
189803
189840
  socket.destroy();
189804
- resolve10(false);
189841
+ resolve9(false);
189805
189842
  });
189806
189843
  socket.on("error", () => {
189807
189844
  socket.destroy();
189808
- resolve10(false);
189845
+ resolve9(false);
189809
189846
  });
189810
189847
  socket.connect(port, host);
189811
189848
  });
189812
189849
  }
189813
189850
  async function stopProcess2(proc) {
189814
- return new Promise((resolve10) => {
189851
+ return new Promise((resolve9) => {
189815
189852
  if (proc.killed || proc.exitCode !== null) {
189816
- resolve10();
189853
+ resolve9();
189817
189854
  return;
189818
189855
  }
189819
189856
  proc.once("exit", () => {
189820
189857
  clearTimeout(forceKillTimeout);
189821
- resolve10();
189858
+ resolve9();
189822
189859
  });
189823
189860
  proc.kill("SIGTERM");
189824
189861
  const forceKillTimeout = setTimeout(() => {
@@ -189829,7 +189866,7 @@ async function stopProcess2(proc) {
189829
189866
  });
189830
189867
  }
189831
189868
  function sleep3(ms) {
189832
- return new Promise((resolve10) => setTimeout(resolve10, ms));
189869
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
189833
189870
  }
189834
189871
 
189835
189872
  // src/lib/dev/mail-manager.ts
@@ -189924,20 +189961,20 @@ async function startMailServer(mail, smtpPort, apiPort) {
189924
189961
  res.writeHead(404);
189925
189962
  res.end();
189926
189963
  });
189927
- await new Promise((resolve10, reject) => {
189928
- smtpServer.listen(smtpPort, "127.0.0.1", () => resolve10());
189964
+ await new Promise((resolve9, reject) => {
189965
+ smtpServer.listen(smtpPort, "127.0.0.1", () => resolve9());
189929
189966
  smtpServer.on("error", reject);
189930
189967
  });
189931
- await new Promise((resolve10, reject) => {
189932
- httpServer.listen(apiPort, "127.0.0.1", () => resolve10());
189968
+ await new Promise((resolve9, reject) => {
189969
+ httpServer.listen(apiPort, "127.0.0.1", () => resolve9());
189933
189970
  httpServer.on("error", reject);
189934
189971
  });
189935
189972
  const stop = async () => {
189936
- await new Promise((resolve10) => {
189937
- smtpServer.close(() => resolve10());
189973
+ await new Promise((resolve9) => {
189974
+ smtpServer.close(() => resolve9());
189938
189975
  });
189939
- await new Promise((resolve10) => {
189940
- httpServer.close(() => resolve10());
189976
+ await new Promise((resolve9) => {
189977
+ httpServer.close(() => resolve9());
189941
189978
  });
189942
189979
  };
189943
189980
  const resource = {
@@ -190041,33 +190078,33 @@ async function waitForTcpPort3(host, port, timeoutMs = 3e4) {
190041
190078
  );
190042
190079
  }
190043
190080
  function checkTcpPort3(host, port) {
190044
- return new Promise((resolve10) => {
190081
+ return new Promise((resolve9) => {
190045
190082
  const socket = new net3.Socket();
190046
190083
  socket.setTimeout(1e3);
190047
190084
  socket.on("connect", () => {
190048
190085
  socket.destroy();
190049
- resolve10(true);
190086
+ resolve9(true);
190050
190087
  });
190051
190088
  socket.on("timeout", () => {
190052
190089
  socket.destroy();
190053
- resolve10(false);
190090
+ resolve9(false);
190054
190091
  });
190055
190092
  socket.on("error", () => {
190056
190093
  socket.destroy();
190057
- resolve10(false);
190094
+ resolve9(false);
190058
190095
  });
190059
190096
  socket.connect(port, host);
190060
190097
  });
190061
190098
  }
190062
190099
  async function stopProcess3(proc) {
190063
- return new Promise((resolve10) => {
190100
+ return new Promise((resolve9) => {
190064
190101
  if (proc.killed || proc.exitCode !== null) {
190065
- resolve10();
190102
+ resolve9();
190066
190103
  return;
190067
190104
  }
190068
190105
  proc.once("exit", () => {
190069
190106
  clearTimeout(forceKillTimeout);
190070
- resolve10();
190107
+ resolve9();
190071
190108
  });
190072
190109
  proc.kill("SIGTERM");
190073
190110
  const forceKillTimeout = setTimeout(() => {
@@ -190078,7 +190115,7 @@ async function stopProcess3(proc) {
190078
190115
  });
190079
190116
  }
190080
190117
  function sleep4(ms) {
190081
- return new Promise((resolve10) => setTimeout(resolve10, ms));
190118
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
190082
190119
  }
190083
190120
 
190084
190121
  // src/lib/dev/sync-detector.ts
@@ -190443,38 +190480,38 @@ async function waitForTcpPort4(host, port, timeoutMs = 3e4) {
190443
190480
  if (isOpen) {
190444
190481
  return;
190445
190482
  }
190446
- await new Promise((resolve10) => setTimeout(resolve10, 100));
190483
+ await new Promise((resolve9) => setTimeout(resolve9, 100));
190447
190484
  }
190448
190485
  throw new Error(`Temporal port ${port} did not become available within timeout`);
190449
190486
  }
190450
190487
  function checkTcpPort4(host, port) {
190451
- return new Promise((resolve10) => {
190488
+ return new Promise((resolve9) => {
190452
190489
  const socket = new net4.Socket();
190453
190490
  socket.setTimeout(1e3);
190454
190491
  socket.on("connect", () => {
190455
190492
  socket.destroy();
190456
- resolve10(true);
190493
+ resolve9(true);
190457
190494
  });
190458
190495
  socket.on("timeout", () => {
190459
190496
  socket.destroy();
190460
- resolve10(false);
190497
+ resolve9(false);
190461
190498
  });
190462
190499
  socket.on("error", () => {
190463
190500
  socket.destroy();
190464
- resolve10(false);
190501
+ resolve9(false);
190465
190502
  });
190466
190503
  socket.connect(port, host);
190467
190504
  });
190468
190505
  }
190469
190506
  async function stopProcess4(proc) {
190470
- return new Promise((resolve10) => {
190507
+ return new Promise((resolve9) => {
190471
190508
  if (proc.killed || proc.exitCode !== null) {
190472
- resolve10();
190509
+ resolve9();
190473
190510
  return;
190474
190511
  }
190475
190512
  proc.once("exit", () => {
190476
190513
  clearTimeout(forceKillTimeout);
190477
- resolve10();
190514
+ resolve9();
190478
190515
  });
190479
190516
  proc.kill("SIGTERM");
190480
190517
  const forceKillTimeout = setTimeout(() => {
@@ -190949,7 +190986,7 @@ var ProxyRegistryManager = class {
190949
190986
  * This catches cases where the owner process is alive but the proxy has crashed.
190950
190987
  */
190951
190988
  isProxyListening(port, timeoutMs = 1e3) {
190952
- return new Promise((resolve10) => {
190989
+ return new Promise((resolve9) => {
190953
190990
  const socket = new net6.Socket();
190954
190991
  let resolved = false;
190955
190992
  const cleanup = () => {
@@ -190961,15 +190998,15 @@ var ProxyRegistryManager = class {
190961
190998
  socket.setTimeout(timeoutMs);
190962
190999
  socket.on("connect", () => {
190963
191000
  cleanup();
190964
- resolve10(true);
191001
+ resolve9(true);
190965
191002
  });
190966
191003
  socket.on("timeout", () => {
190967
191004
  cleanup();
190968
- resolve10(false);
191005
+ resolve9(false);
190969
191006
  });
190970
191007
  socket.on("error", () => {
190971
191008
  cleanup();
190972
- resolve10(false);
191009
+ resolve9(false);
190973
191010
  });
190974
191011
  socket.connect(port, "127.0.0.1");
190975
191012
  });
@@ -191020,7 +191057,7 @@ var ProxyRegistryManager = class {
191020
191057
  }
191021
191058
  continue;
191022
191059
  }
191023
- await new Promise((resolve10) => setTimeout(resolve10, 100));
191060
+ await new Promise((resolve9) => setTimeout(resolve9, 100));
191024
191061
  } else {
191025
191062
  throw e;
191026
191063
  }
@@ -192697,186 +192734,6 @@ import Spinner5 from "ink-spinner";
192697
192734
  import * as fs26 from "fs";
192698
192735
  import * as path23 from "path";
192699
192736
 
192700
- // src/lib/deploy/build-tester.ts
192701
- import { spawn as spawn6 } from "child_process";
192702
- import { existsSync as existsSync22 } from "fs";
192703
- import { join as join23, resolve as resolve7 } from "path";
192704
- function getDependencyInstallCommand(build, projectDir) {
192705
- if (!build.base) return null;
192706
- switch (build.base) {
192707
- case "node":
192708
- if (existsSync22(join23(projectDir, "pnpm-lock.yaml"))) {
192709
- return "pnpm install --frozen-lockfile";
192710
- } else if (existsSync22(join23(projectDir, "yarn.lock"))) {
192711
- return "yarn install --frozen-lockfile";
192712
- } else if (existsSync22(join23(projectDir, "package-lock.json"))) {
192713
- return "npm ci";
192714
- } else if (existsSync22(join23(projectDir, "package.json"))) {
192715
- return "npm install";
192716
- }
192717
- return null;
192718
- case "python":
192719
- if (existsSync22(join23(projectDir, "poetry.lock"))) {
192720
- return "poetry install --no-interaction";
192721
- } else if (existsSync22(join23(projectDir, "Pipfile.lock"))) {
192722
- return "pipenv install --deploy";
192723
- } else if (existsSync22(join23(projectDir, "Pipfile"))) {
192724
- return "pipenv install";
192725
- } else if (existsSync22(join23(projectDir, "pyproject.toml"))) {
192726
- return "pip install .";
192727
- } else if (existsSync22(join23(projectDir, "requirements.txt"))) {
192728
- return "pip install -r requirements.txt";
192729
- }
192730
- return null;
192731
- case "go":
192732
- return "go mod download";
192733
- case "rust":
192734
- case "java":
192735
- return null;
192736
- default:
192737
- return null;
192738
- }
192739
- }
192740
- function runCommand2(command, projectDir, buildName) {
192741
- return new Promise((resolve10) => {
192742
- const stdout = [];
192743
- const stderr = [];
192744
- writeLog("build-test", `[${buildName}] Running: ${command}`);
192745
- const child = spawn6(command, {
192746
- shell: true,
192747
- cwd: projectDir,
192748
- env: { ...process.env },
192749
- stdio: ["ignore", "pipe", "pipe"]
192750
- });
192751
- child.stdout?.on("data", (data) => {
192752
- const text = data.toString();
192753
- stdout.push(text);
192754
- for (const line of text.split("\n")) {
192755
- if (line.trim()) {
192756
- writeLog(`build-test:${buildName}`, line);
192757
- }
192758
- }
192759
- });
192760
- child.stderr?.on("data", (data) => {
192761
- const text = data.toString();
192762
- stderr.push(text);
192763
- for (const line of text.split("\n")) {
192764
- if (line.trim()) {
192765
- writeLog(`build-test:${buildName}`, line);
192766
- }
192767
- }
192768
- });
192769
- child.on("error", (err) => {
192770
- writeLog("build-test:error", `[${buildName}] Failed to start: ${err.message}`);
192771
- resolve10({
192772
- success: false,
192773
- output: `Failed to start command: ${err.message}`
192774
- });
192775
- });
192776
- child.on("exit", (code) => {
192777
- const output = [...stdout, ...stderr].join("");
192778
- if (code === 0) {
192779
- writeLog("build-test", `[${buildName}] Command succeeded (exit code 0)`);
192780
- resolve10({ success: true, output });
192781
- } else {
192782
- writeLog("build-test:error", `[${buildName}] Command failed with exit code ${code}`);
192783
- resolve10({
192784
- success: false,
192785
- output: output || `Exit code: ${code}`
192786
- });
192787
- }
192788
- });
192789
- });
192790
- }
192791
- async function testBuild(build, projectDir) {
192792
- const startTime = Date.now();
192793
- if (build.dockerfile) {
192794
- writeLog("build-test", `Skipping test for build "${build.name}" (custom Dockerfile)`);
192795
- return {
192796
- buildName: build.name,
192797
- success: true,
192798
- output: "Skipped: custom Dockerfile build",
192799
- durationMs: Date.now() - startTime
192800
- };
192801
- }
192802
- const outputs = [];
192803
- const workDir = build.root ? resolve7(projectDir, build.root) : projectDir;
192804
- writeLog("build-test", `Starting test for build "${build.name}" (base: ${build.base}, workDir: ${workDir})`);
192805
- const depsCommand = getDependencyInstallCommand(build, workDir);
192806
- if (depsCommand) {
192807
- writeLog("build-test", `[${build.name}] Installing dependencies...`);
192808
- const depsResult = await runCommand2(depsCommand, workDir, build.name);
192809
- outputs.push(`[${depsCommand}]
192810
- ${depsResult.output}`);
192811
- if (!depsResult.success) {
192812
- const duration2 = Date.now() - startTime;
192813
- writeLog("build-test:error", `[${build.name}] Dependency installation failed after ${duration2}ms`);
192814
- return {
192815
- buildName: build.name,
192816
- success: false,
192817
- output: outputs.join("\n\n"),
192818
- durationMs: duration2
192819
- };
192820
- }
192821
- writeLog("build-test", `[${build.name}] Dependencies installed successfully`);
192822
- } else {
192823
- writeLog("build-test", `[${build.name}] No dependency installation needed for base "${build.base}"`);
192824
- }
192825
- if (build.command) {
192826
- writeLog("build-test", `[${build.name}] Running build command...`);
192827
- const buildResult = await runCommand2(build.command, workDir, build.name);
192828
- outputs.push(`[${build.command}]
192829
- ${buildResult.output}`);
192830
- if (!buildResult.success) {
192831
- const duration2 = Date.now() - startTime;
192832
- writeLog("build-test:error", `[${build.name}] Build command failed after ${duration2}ms`);
192833
- return {
192834
- buildName: build.name,
192835
- success: false,
192836
- output: outputs.join("\n\n"),
192837
- durationMs: duration2
192838
- };
192839
- }
192840
- writeLog("build-test", `[${build.name}] Build command completed successfully`);
192841
- } else {
192842
- writeLog("build-test", `[${build.name}] No build command defined, skipping`);
192843
- }
192844
- const duration = Date.now() - startTime;
192845
- writeLog("build-test", `[${build.name}] Build test passed in ${duration}ms`);
192846
- return {
192847
- buildName: build.name,
192848
- success: true,
192849
- output: outputs.join("\n\n"),
192850
- durationMs: duration
192851
- };
192852
- }
192853
- async function testAllBuilds(builds, projectDir) {
192854
- if (builds.length === 0) {
192855
- writeLog("build-test", "No builds to test");
192856
- return { results: [], allPassed: true };
192857
- }
192858
- writeLog("build-test", `Testing ${builds.length} build(s) in parallel: ${builds.map((b) => b.name).join(", ")}`);
192859
- writeLog("build-test", `Project directory: ${projectDir}`);
192860
- const results = await Promise.all(
192861
- builds.map((build) => testBuild(build, projectDir))
192862
- );
192863
- const passed = results.filter((r) => r.success).length;
192864
- const failed = results.filter((r) => !r.success).length;
192865
- const totalDuration = results.reduce((sum, r) => sum + r.durationMs, 0);
192866
- if (failed > 0) {
192867
- writeLog("build-test:error", `Build tests completed: ${passed} passed, ${failed} failed`);
192868
- for (const result of results.filter((r) => !r.success)) {
192869
- writeLog("build-test:error", `Failed build: ${result.buildName}`);
192870
- }
192871
- } else {
192872
- writeLog("build-test", `All ${passed} build(s) passed (total: ${totalDuration}ms)`);
192873
- }
192874
- return {
192875
- results,
192876
- allPassed: results.every((r) => r.success)
192877
- };
192878
- }
192879
-
192880
192737
  // src/lib/tarball/create.ts
192881
192738
  import { execSync as execSync4 } from "child_process";
192882
192739
  import * as fs25 from "fs";
@@ -193017,7 +192874,6 @@ function PhaseIndicator({
193017
192874
  showSpinner = true
193018
192875
  }) {
193019
192876
  const phases = [
193020
- "testing-builds",
193021
192877
  "creating-tarball",
193022
192878
  "creating-deployment",
193023
192879
  "uploading",
@@ -193047,22 +192903,35 @@ function PhaseIndicator({
193047
192903
  }
193048
192904
  return /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, " ", "\u25CB"), " ", /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, label));
193049
192905
  }
192906
+ function buildSelectorItems(projects, organizations) {
192907
+ const items = [];
192908
+ for (const org of organizations) {
192909
+ items.push({ type: "header", orgName: org.name });
192910
+ items.push({ type: "new", orgId: org.id });
192911
+ const orgProjects = projects.filter((p) => p.organizationId === org.id);
192912
+ for (const project of orgProjects) {
192913
+ items.push({ type: "project", project });
192914
+ }
192915
+ }
192916
+ return items;
192917
+ }
193050
192918
  function ProjectSelector({
193051
192919
  projects,
192920
+ organizations,
193052
192921
  selectedIndex,
193053
192922
  onSelect,
193054
192923
  onUp,
193055
192924
  onDown
193056
192925
  }) {
192926
+ const items = buildSelectorItems(projects, organizations);
192927
+ const selectableIndices = items.map((item, index) => item.type !== "header" ? index : -1).filter((i) => i >= 0);
193057
192928
  useInput5((input, key) => {
193058
192929
  if (key.return) {
193059
- if (selectedIndex === 0) {
193060
- onSelect("new");
193061
- } else {
193062
- const project = projects[selectedIndex - 1];
193063
- if (project) {
193064
- onSelect(project);
193065
- }
192930
+ const item = items[selectedIndex];
192931
+ if (item?.type === "new") {
192932
+ onSelect({ type: "new", orgId: item.orgId });
192933
+ } else if (item?.type === "project") {
192934
+ onSelect(item.project);
193066
192935
  }
193067
192936
  } else if (key.upArrow) {
193068
192937
  onUp();
@@ -193070,11 +192939,16 @@ function ProjectSelector({
193070
192939
  onDown();
193071
192940
  }
193072
192941
  });
193073
- const items = [
193074
- { id: "new", name: "Create new project", isNew: true },
193075
- ...projects.map((p) => ({ ...p, isNew: false }))
193076
- ];
193077
- return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Select a project to deploy:"), /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, items.map((item, index) => /* @__PURE__ */ React7.createElement(Text7, { key: item.id }, index === selectedIndex ? /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, "> ") : /* @__PURE__ */ React7.createElement(Text7, null, " "), item.isNew ? /* @__PURE__ */ React7.createElement(Text7, { color: "green" }, item.name) : /* @__PURE__ */ React7.createElement(Text7, null, item.name, " ", /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "(", item.id, ")"))))), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "Use arrow keys to navigate, Enter to select"));
192942
+ return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Select a project to deploy:"), /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, items.map((item, index) => {
192943
+ if (item.type === "header") {
192944
+ return /* @__PURE__ */ React7.createElement(Text7, { key: `header-${item.orgName}` }, index > 0 ? "\n" : "", /* @__PURE__ */ React7.createElement(Text7, { bold: true }, item.orgName));
192945
+ }
192946
+ const isSelected = index === selectedIndex;
192947
+ if (item.type === "new") {
192948
+ return /* @__PURE__ */ React7.createElement(Text7, { key: `new-${item.orgId}` }, isSelected ? /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, " ", "> ") : /* @__PURE__ */ React7.createElement(Text7, null, " "), /* @__PURE__ */ React7.createElement(Text7, { color: "green" }, "Create new project"));
192949
+ }
192950
+ return /* @__PURE__ */ React7.createElement(Text7, { key: item.project.id }, isSelected ? /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, " ", "> ") : /* @__PURE__ */ React7.createElement(Text7, null, " "), /* @__PURE__ */ React7.createElement(Text7, null, item.project.name, " ", /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "(", item.project.id, ")")));
192951
+ })), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "Use arrow keys to navigate, Enter to select"));
193078
192952
  }
193079
192953
  function NameInput({ onSubmit, onCancel }) {
193080
192954
  const [value, setValue] = useState6("");
@@ -193129,7 +193003,7 @@ function formatErrorCode(code) {
193129
193003
  function StructuredError({ error }) {
193130
193004
  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)));
193131
193005
  }
193132
- function DeployUI({ environment, config, skipBuildTest }) {
193006
+ function DeployUI({ environment, config }) {
193133
193007
  const { exit } = useApp3();
193134
193008
  const [state, setState] = useState6({ phase: "checking-auth" });
193135
193009
  const clientRef = React7.useRef(null);
@@ -193140,7 +193014,7 @@ function DeployUI({ environment, config, skipBuildTest }) {
193140
193014
  const projectId = readProjectId(projectDir);
193141
193015
  if (isLoggedIn()) {
193142
193016
  setState({
193143
- phase: "testing-builds",
193017
+ phase: "creating-tarball",
193144
193018
  projectId
193145
193019
  });
193146
193020
  } else {
@@ -193197,7 +193071,7 @@ function DeployUI({ environment, config, skipBuildTest }) {
193197
193071
  const successResponse = response;
193198
193072
  await saveCredentialsFromToken(successResponse);
193199
193073
  setState(
193200
- (s) => s.projectId ? { phase: "testing-builds", projectId: s.projectId } : { phase: "loading-projects" }
193074
+ (s) => s.projectId ? { phase: "creating-tarball", projectId: s.projectId } : { phase: "loading-projects" }
193201
193075
  );
193202
193076
  }
193203
193077
  };
@@ -193221,12 +193095,18 @@ function DeployUI({ environment, config, skipBuildTest }) {
193221
193095
  async function loadProjects() {
193222
193096
  try {
193223
193097
  const client2 = new ApiClient();
193224
- const { projects: projects2 } = await client2.listProjects();
193098
+ const [{ projects: projects2 }, { organizations }] = await Promise.all([
193099
+ client2.listProjects(),
193100
+ client2.listOrganizations()
193101
+ ]);
193225
193102
  if (cancelled) return;
193103
+ const items = buildSelectorItems(projects2, organizations);
193104
+ const firstSelectable = items.findIndex((item) => item.type !== "header");
193226
193105
  setState({
193227
193106
  phase: "selecting-project",
193228
193107
  projects: projects2,
193229
- selectedIndex: 0
193108
+ organizations,
193109
+ selectedIndex: firstSelectable >= 0 ? firstSelectable : 0
193230
193110
  });
193231
193111
  } catch (err) {
193232
193112
  if (cancelled) return;
@@ -193243,13 +193123,14 @@ function DeployUI({ environment, config, skipBuildTest }) {
193243
193123
  }, [state.phase]);
193244
193124
  const handleProjectSelect = useCallback(
193245
193125
  (project) => {
193246
- if (project === "new") {
193247
- setState((s) => ({ ...s, phase: "entering-name" }));
193126
+ if ("type" in project && project.type === "new") {
193127
+ setState((s) => ({ ...s, phase: "entering-name", selectedOrganizationId: project.orgId }));
193248
193128
  } else {
193249
- writeProjectId(project.id);
193129
+ const proj = project;
193130
+ writeProjectId(proj.id);
193250
193131
  setState({
193251
- phase: "testing-builds",
193252
- projectId: project.id
193132
+ phase: "creating-tarball",
193133
+ projectId: proj.id
193253
193134
  });
193254
193135
  }
193255
193136
  },
@@ -193267,11 +193148,11 @@ function DeployUI({ environment, config, skipBuildTest }) {
193267
193148
  async function createProject() {
193268
193149
  try {
193269
193150
  const client2 = new ApiClient();
193270
- const project = await client2.createProject(state.newProjectName);
193151
+ const project = await client2.createProject(state.newProjectName, state.selectedOrganizationId);
193271
193152
  if (cancelled) return;
193272
193153
  writeProjectId(project.id);
193273
193154
  setState({
193274
- phase: "testing-builds",
193155
+ phase: "creating-tarball",
193275
193156
  projectId: project.id
193276
193157
  });
193277
193158
  } catch (err) {
@@ -193432,43 +193313,11 @@ function DeployUI({ environment, config, skipBuildTest }) {
193432
193313
  })();
193433
193314
  }, [state]);
193434
193315
  useEffect4(() => {
193435
- if (state.phase !== "testing-builds" || !state.projectId) return;
193316
+ if (state.phase !== "creating-tarball" || !state.projectId) return;
193436
193317
  let cancelled = false;
193437
- async function runBuildTestsAndDeploy() {
193318
+ async function runDeploy() {
193438
193319
  const projectDir = process.cwd();
193439
193320
  const builds = config.builds || [];
193440
- if (!skipBuildTest && builds.length > 0) {
193441
- writeLog("deploy", `Testing ${builds.length} build(s) locally`);
193442
- try {
193443
- const results = await testAllBuilds(builds, projectDir);
193444
- if (cancelled) return;
193445
- if (!results.allPassed) {
193446
- const failures = results.results.filter((r) => !r.success);
193447
- const errorMsg = failures.map((f) => `Build "${f.buildName}" failed:
193448
- ${f.output}`).join("\n\n");
193449
- writeLog("deploy:error", errorMsg);
193450
- setState({
193451
- phase: "error",
193452
- error: `Build test failed:
193453
- ${errorMsg}`
193454
- });
193455
- return;
193456
- }
193457
- writeLog("deploy", "All builds passed local testing");
193458
- } catch (err) {
193459
- if (cancelled) return;
193460
- const errorMsg = `Build test failed: ${err instanceof Error ? err.message : String(err)}`;
193461
- writeLog("deploy:error", errorMsg);
193462
- setState({
193463
- phase: "error",
193464
- error: errorMsg
193465
- });
193466
- return;
193467
- }
193468
- } else {
193469
- writeLog("deploy", skipBuildTest ? "Skipping build tests (--skip-build-test)" : "No builds to test");
193470
- }
193471
- setState((s) => ({ ...s, phase: "creating-tarball" }));
193472
193321
  writeLog("deploy", `Starting deployment to "${environment}"`);
193473
193322
  writeLog("deploy", `Project directory: ${projectDir}`);
193474
193323
  const client2 = new ApiClient();
@@ -193534,11 +193383,11 @@ ${errorMsg}`
193534
193383
  writeLog("deploy", "Deployment in pending state, waiting for builds to complete");
193535
193384
  setState((s) => ({ ...s, phase: "pending", deployment: deployment2 }));
193536
193385
  }
193537
- runBuildTestsAndDeploy();
193386
+ runDeploy();
193538
193387
  return () => {
193539
193388
  cancelled = true;
193540
193389
  };
193541
- }, [state.projectId, environment, config.builds, skipBuildTest]);
193390
+ }, [state.projectId, environment, config.builds]);
193542
193391
  useEffect4(() => {
193543
193392
  if (state.phase !== "pending" || !state.deployment) return;
193544
193393
  let pollInterval;
@@ -193732,7 +193581,7 @@ ${errorMsg}`
193732
193581
  };
193733
193582
  }, [state.phase, state.deployment?.id]);
193734
193583
  useEffect4(() => {
193735
- if (state.phase === "testing-builds") {
193584
+ if (state.phase === "creating-tarball") {
193736
193585
  trackEvent("deploy_started", { environment });
193737
193586
  }
193738
193587
  }, [state.phase, environment]);
@@ -193775,24 +193624,28 @@ ${errorMsg}`
193775
193624
  if (phase === "loading-projects") {
193776
193625
  return /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "blue" }, /* @__PURE__ */ React7.createElement(Spinner5, { type: "dots" })), /* @__PURE__ */ React7.createElement(Text7, null, " Loading projects..."));
193777
193626
  }
193778
- if (phase === "selecting-project" && projects && selectedIndex !== void 0) {
193627
+ if (phase === "selecting-project" && projects && state.organizations && selectedIndex !== void 0) {
193628
+ const selectorItems = buildSelectorItems(projects, state.organizations);
193629
+ const selectableIndices = selectorItems.map((item, index) => item.type !== "header" ? index : -1).filter((i) => i >= 0);
193779
193630
  return /* @__PURE__ */ React7.createElement(
193780
193631
  ProjectSelector,
193781
193632
  {
193782
193633
  projects,
193634
+ organizations: state.organizations,
193783
193635
  selectedIndex,
193784
193636
  onSelect: handleProjectSelect,
193785
- onUp: () => setState((s) => ({
193786
- ...s,
193787
- selectedIndex: Math.max(0, (s.selectedIndex || 0) - 1)
193788
- })),
193789
- onDown: () => setState((s) => ({
193790
- ...s,
193791
- selectedIndex: Math.min(
193792
- s.projects?.length || 0,
193793
- (s.selectedIndex || 0) + 1
193794
- )
193795
- }))
193637
+ onUp: () => setState((s) => {
193638
+ const idx = s.selectedIndex ?? 0;
193639
+ const currentPos = selectableIndices.indexOf(idx);
193640
+ const prevPos = Math.max(0, currentPos - 1);
193641
+ return { ...s, selectedIndex: selectableIndices[prevPos] ?? idx };
193642
+ }),
193643
+ onDown: () => setState((s) => {
193644
+ const idx = s.selectedIndex ?? 0;
193645
+ const currentPos = selectableIndices.indexOf(idx);
193646
+ const nextPos = Math.min(selectableIndices.length - 1, currentPos + 1);
193647
+ return { ...s, selectedIndex: selectableIndices[nextPos] ?? idx };
193648
+ })
193796
193649
  }
193797
193650
  );
193798
193651
  }
@@ -193827,13 +193680,6 @@ ${errorMsg}`
193827
193680
  return "Preparing";
193828
193681
  };
193829
193682
  return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { bold: true, color: "cyan" }, "Deploying to ", environment), deployment && /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, " (", deployment.id, ")")), /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, /* @__PURE__ */ React7.createElement(
193830
- PhaseIndicator,
193831
- {
193832
- phase: "testing-builds",
193833
- currentPhase: displayPhase,
193834
- label: "Testing builds locally"
193835
- }
193836
- ), /* @__PURE__ */ React7.createElement(
193837
193683
  PhaseIndicator,
193838
193684
  {
193839
193685
  phase: "creating-tarball",
@@ -193887,7 +193733,7 @@ ${errorMsg}`
193887
193733
  }
193888
193734
  ), phase === "error" && /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1, flexDirection: "column" }, deployment?.error ? /* @__PURE__ */ React7.createElement(StructuredError, { error: deployment.error }) : /* @__PURE__ */ React7.createElement(Text7, { color: "red", bold: true }, error), buildOutput && /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Build output:"), /* @__PURE__ */ React7.createElement(Text7, null, buildOutput))), phase === "success" && /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React7.createElement(Text7, { color: "green" }, "Deployment successful!"), deployment?.publicUrls && Object.keys(deployment.publicUrls).length > 0 && /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Public URLs:"), Object.entries(deployment.publicUrls).map(([name, url]) => /* @__PURE__ */ React7.createElement(Text7, { key: name }, " ", name, ": ", /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, url))))));
193889
193735
  }
193890
- async function deployCommand(environment, options2) {
193736
+ async function deployCommand(environment) {
193891
193737
  const configPath = path23.join(process.cwd(), "specific.hcl");
193892
193738
  if (!fs26.existsSync(configPath)) {
193893
193739
  console.error("Error: No specific.hcl found in current directory");
@@ -193902,21 +193748,19 @@ async function deployCommand(environment, options2) {
193902
193748
  process.exit(1);
193903
193749
  }
193904
193750
  const env2 = environment || "prod";
193905
- const skipBuildTest = options2?.skipBuildTest ?? false;
193906
193751
  render5(
193907
193752
  /* @__PURE__ */ React7.createElement(
193908
193753
  DeployUI,
193909
193754
  {
193910
193755
  environment: env2,
193911
- config,
193912
- skipBuildTest
193756
+ config
193913
193757
  }
193914
193758
  )
193915
193759
  );
193916
193760
  }
193917
193761
 
193918
193762
  // src/commands/exec.tsx
193919
- import { spawn as spawn7 } from "child_process";
193763
+ import { spawn as spawn6 } from "child_process";
193920
193764
  import * as fs27 from "fs";
193921
193765
  import * as path24 from "path";
193922
193766
  async function execCommand(serviceName, command, instanceKey = "default") {
@@ -194077,7 +193921,7 @@ async function execCommand(serviceName, command, instanceKey = "default") {
194077
193921
  effectiveCwd = path24.resolve(process.cwd(), build.root);
194078
193922
  }
194079
193923
  }
194080
- child = spawn7(command[0], command.slice(1), {
193924
+ child = spawn6(command[0], command.slice(1), {
194081
193925
  cwd: effectiveCwd,
194082
193926
  env: {
194083
193927
  ...process.env,
@@ -194101,7 +193945,7 @@ async function execCommand(serviceName, command, instanceKey = "default") {
194101
193945
  }
194102
193946
 
194103
193947
  // src/commands/psql.tsx
194104
- import { spawn as spawn8 } from "child_process";
193948
+ import { spawn as spawn7 } from "child_process";
194105
193949
  import * as fs28 from "fs";
194106
193950
  import * as path25 from "path";
194107
193951
  async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []) {
@@ -194224,7 +194068,7 @@ async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []
194224
194068
  };
194225
194069
  process.on("SIGINT", () => handleSignal("SIGINT"));
194226
194070
  process.on("SIGTERM", () => handleSignal("SIGTERM"));
194227
- child = spawn8(psqlPath, ["-h", dbState.host, "-p", String(dbState.port), "-U", dbState.user, "-d", dbState.dbName, ...extraArgs], {
194071
+ child = spawn7(psqlPath, ["-h", dbState.host, "-p", String(dbState.port), "-U", dbState.user, "-d", dbState.dbName, ...extraArgs], {
194228
194072
  cwd: process.cwd(),
194229
194073
  env: {
194230
194074
  ...process.env,
@@ -194249,7 +194093,7 @@ async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []
194249
194093
  }
194250
194094
 
194251
194095
  // src/commands/reshape.tsx
194252
- import { spawn as spawn9 } from "child_process";
194096
+ import { spawn as spawn8 } from "child_process";
194253
194097
  import * as fs29 from "fs";
194254
194098
  import * as path26 from "path";
194255
194099
  var VALID_ACTIONS = ["start", "complete", "status", "abort", "check"];
@@ -194427,7 +194271,7 @@ async function reshapeCommand(action, databaseName, instanceKey = "default") {
194427
194271
  };
194428
194272
  process.on("SIGINT", () => handleSignal("SIGINT"));
194429
194273
  process.on("SIGTERM", () => handleSignal("SIGTERM"));
194430
- child = spawn9(reshapePath, reshapeArgs, {
194274
+ child = spawn8(reshapePath, reshapeArgs, {
194431
194275
  cwd: process.cwd(),
194432
194276
  env: {
194433
194277
  ...process.env,
@@ -194704,7 +194548,7 @@ function compareVersions(a, b) {
194704
194548
  return 0;
194705
194549
  }
194706
194550
  async function checkForUpdate() {
194707
- const currentVersion = "0.1.73";
194551
+ const currentVersion = "0.1.75";
194708
194552
  const response = await fetch(`${BINARIES_BASE_URL}/latest?t=${Date.now()}`);
194709
194553
  if (!response.ok) {
194710
194554
  throw new Error(`Failed to check for updates: HTTP ${response.status}`);
@@ -194754,7 +194598,7 @@ async function performUpdate(version, onProgress) {
194754
194598
  }
194755
194599
 
194756
194600
  // src/lib/background-update.ts
194757
- import { spawn as spawn10 } from "child_process";
194601
+ import { spawn as spawn9 } from "child_process";
194758
194602
  import * as fs32 from "fs";
194759
194603
  import * as path29 from "path";
194760
194604
  import * as os10 from "os";
@@ -194783,7 +194627,7 @@ function maybeStartBackgroundUpdate() {
194783
194627
  if (process.env.SPECIFIC_BACKGROUND_UPDATE === "1") return;
194784
194628
  if (isRateLimited()) return;
194785
194629
  if (!isBinaryWritable()) return;
194786
- const child = spawn10(process.execPath, [], {
194630
+ const child = spawn9(process.execPath, [], {
194787
194631
  detached: true,
194788
194632
  stdio: "ignore",
194789
194633
  env: {
@@ -194903,7 +194747,7 @@ function updateCommand() {
194903
194747
  var program = new Command();
194904
194748
  var env = "production";
194905
194749
  var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
194906
- program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.73").enablePositionalOptions();
194750
+ program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.75").enablePositionalOptions();
194907
194751
  program.command("init").description("Initialize project for use with a coding agent").option("--agent <name...>", "Agents to configure (cursor, claude, codex, other)").action((options2) => initCommand(options2));
194908
194752
  program.command("docs [topic]").description("Fetch LLM-optimized documentation").action(docsCommand);
194909
194753
  program.command("check").description("Validate specific.hcl configuration").action(checkCommand);
@@ -194911,8 +194755,8 @@ program.command("dev").description("Start local development environment").option
194911
194755
  const key = options2.key ?? getDefaultKey();
194912
194756
  devCommand(key, options2.tunnel ?? false);
194913
194757
  });
194914
- program.command("deploy [environment]").description("Deploy to Specific infrastructure").option("--skip-build-test", "Skip local build testing before deploy").action((environment, options2) => {
194915
- deployCommand(environment, options2);
194758
+ program.command("deploy [environment]").description("Deploy to Specific infrastructure").action((environment) => {
194759
+ deployCommand(environment);
194916
194760
  });
194917
194761
  program.command("exec <service> [args...]").description("Run a one-off command with service environment").option("-k, --key <key>", "Dev environment namespace (auto-detected from git worktree if not specified)").passThroughOptions().action(async (service, args, options2) => {
194918
194762
  const filteredArgs = args[0] === "--" ? args.slice(1) : args;