estatehelm 1.0.3 → 1.0.5

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.js CHANGED
@@ -1454,99 +1454,21 @@ function prompt(question) {
1454
1454
  });
1455
1455
  });
1456
1456
  }
1457
- var ALLOWED_CALLBACK_PORTS = [11033, 11034, 11035];
1458
1457
  async function findAvailablePort() {
1459
- for (const port of ALLOWED_CALLBACK_PORTS) {
1460
- const available = await isPortAvailable(port);
1461
- if (available) {
1462
- return port;
1463
- }
1464
- }
1465
- throw new Error(
1466
- `No available ports for CLI callback. Ports ${ALLOWED_CALLBACK_PORTS.join(", ")} are all in use.`
1467
- );
1468
- }
1469
- function isPortAvailable(port) {
1470
- return new Promise((resolve) => {
1471
- const server = http.createServer();
1472
- server.listen(port, "127.0.0.1", () => {
1473
- server.close(() => resolve(true));
1474
- });
1475
- server.on("error", () => resolve(false));
1476
- });
1477
- }
1478
- function waitForCallback(port) {
1479
1458
  return new Promise((resolve, reject) => {
1480
- const server = http.createServer((req, res) => {
1481
- const url = new URL(req.url || "/", `http://127.0.0.1:${port}`);
1482
- const sessionToken = url.searchParams.get("session_token");
1483
- const error = url.searchParams.get("error");
1484
- const errorDescription = url.searchParams.get("error_description");
1485
- if (error) {
1486
- res.writeHead(400, { "Content-Type": "text/html" });
1487
- res.end(`
1488
- <!DOCTYPE html>
1489
- <html>
1490
- <head>
1491
- <title>Authentication Failed</title>
1492
- <style>
1493
- body { font-family: system-ui, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #fef2f2; }
1494
- .card { background: white; padding: 2rem; border-radius: 1rem; box-shadow: 0 10px 25px rgba(0,0,0,0.1); text-align: center; max-width: 400px; }
1495
- h1 { color: #dc2626; margin: 0 0 0.5rem; }
1496
- p { color: #6b7280; margin: 0.5rem 0; }
1497
- .error { font-family: monospace; background: #f3f4f6; padding: 0.5rem; border-radius: 0.25rem; font-size: 0.875rem; }
1498
- </style>
1499
- </head>
1500
- <body>
1501
- <div class="card">
1502
- <h1>Authentication Failed</h1>
1503
- <p>${errorDescription || error || "An error occurred during authentication."}</p>
1504
- <p class="error">${error}</p>
1505
- </div>
1506
- </body>
1507
- </html>
1508
- `);
1509
- server.close();
1510
- reject(new Error(errorDescription || error || "Authentication failed"));
1511
- return;
1512
- }
1513
- if (sessionToken) {
1514
- res.writeHead(200, { "Content-Type": "text/html" });
1515
- res.end(`
1516
- <!DOCTYPE html>
1517
- <html>
1518
- <head>
1519
- <title>CLI Authentication Successful</title>
1520
- <style>
1521
- body { font-family: system-ui, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: linear-gradient(115deg, #fff1be 28%, #ee87cb 70%, #b060ff 100%); }
1522
- .card { background: white; padding: 2rem; border-radius: 1rem; box-shadow: 0 10px 25px rgba(0,0,0,0.1); text-align: center; }
1523
- h1 { color: #059669; margin: 0 0 0.5rem; }
1524
- p { color: #6b7280; margin: 0; }
1525
- </style>
1526
- </head>
1527
- <body>
1528
- <div class="card">
1529
- <h1>\u2713 Authentication Successful</h1>
1530
- <p>You can close this window and return to your terminal.</p>
1531
- </div>
1532
- </body>
1533
- </html>
1534
- `);
1535
- server.close();
1536
- resolve(sessionToken);
1537
- } else {
1538
- res.writeHead(404, { "Content-Type": "text/plain" });
1539
- res.end("Not found");
1540
- }
1541
- });
1542
- server.listen(port, "127.0.0.1", () => {
1543
- console.log(`Callback server listening on http://127.0.0.1:${port}`);
1459
+ const server = http.createServer();
1460
+ server.listen(0, "127.0.0.1", () => {
1461
+ const address = server.address();
1462
+ const port = typeof address === "object" && address ? address.port : 0;
1463
+ server.close(() => {
1464
+ if (port > 0) {
1465
+ resolve(port);
1466
+ } else {
1467
+ reject(new Error("Failed to find available port"));
1468
+ }
1469
+ });
1544
1470
  });
1545
1471
  server.on("error", reject);
1546
- setTimeout(() => {
1547
- server.close();
1548
- reject(new Error("Authentication timed out. Please try again."));
1549
- }, 5 * 60 * 1e3);
1550
1472
  });
1551
1473
  }
1552
1474
  function createApiClient(token) {
@@ -1618,53 +1540,50 @@ async function decryptDeviceCredentials(encryptedPayload) {
1618
1540
  );
1619
1541
  return new Uint8Array(plaintext);
1620
1542
  }
1621
- async function createNativeLoginFlow(returnTo) {
1622
- const url = `${KRATOS_URL}/self-service/login/api?return_to=${encodeURIComponent(returnTo)}`;
1623
- const response = await fetch(url, {
1624
- method: "GET",
1625
- headers: { Accept: "application/json" }
1626
- });
1627
- if (!response.ok) {
1628
- const error = await response.text();
1629
- throw new Error(`Failed to create login flow: ${response.status} - ${error}`);
1630
- }
1631
- const flow = await response.json();
1632
- return {
1633
- flowId: flow.id,
1634
- flowUrl: flow.request_url || `${KRATOS_URL}/self-service/login?flow=${flow.id}`
1635
- };
1636
- }
1637
- async function initiateOidcFlow(flowId, provider = "google") {
1638
- const url = `${KRATOS_URL}/self-service/login?flow=${flowId}`;
1639
- const response = await fetch(url, {
1640
- method: "POST",
1641
- headers: {
1642
- "Content-Type": "application/json",
1643
- Accept: "application/json"
1644
- },
1645
- body: JSON.stringify({
1646
- method: "oidc",
1647
- provider
1648
- }),
1649
- redirect: "manual"
1650
- // Don't follow redirects
1543
+ function waitForCallback(port) {
1544
+ return new Promise((resolve, reject) => {
1545
+ const server = http.createServer((req, res) => {
1546
+ const url = new URL(req.url || "/", `http://127.0.0.1:${port}`);
1547
+ const sessionToken = url.searchParams.get("session_token");
1548
+ const error = url.searchParams.get("error");
1549
+ if (error) {
1550
+ res.writeHead(400, { "Content-Type": "text/html" });
1551
+ res.end(`
1552
+ <!DOCTYPE html>
1553
+ <html>
1554
+ <head><title>Authentication Failed</title>
1555
+ <style>body{font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:#fef2f2}.card{background:white;padding:2rem;border-radius:1rem;box-shadow:0 10px 25px rgba(0,0,0,0.1);text-align:center}h1{color:#dc2626}</style></head>
1556
+ <body><div class="card"><h1>Authentication Failed</h1><p>${url.searchParams.get("error_description") || error}</p></div></body>
1557
+ </html>
1558
+ `);
1559
+ server.close();
1560
+ reject(new Error(url.searchParams.get("error_description") || error));
1561
+ return;
1562
+ }
1563
+ if (sessionToken) {
1564
+ res.writeHead(200, { "Content-Type": "text/html" });
1565
+ res.end(`
1566
+ <!DOCTYPE html>
1567
+ <html>
1568
+ <head><title>Authentication Successful</title>
1569
+ <style>body{font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:linear-gradient(115deg,#fff1be 28%,#ee87cb 70%,#b060ff 100%)}.card{background:white;padding:2rem;border-radius:1rem;box-shadow:0 10px 25px rgba(0,0,0,0.1);text-align:center}h1{color:#059669}</style></head>
1570
+ <body><div class="card"><h1>\u2713 Authentication Successful</h1><p>You can close this window and return to your terminal.</p></div></body>
1571
+ </html>
1572
+ `);
1573
+ server.close();
1574
+ resolve(sessionToken);
1575
+ return;
1576
+ }
1577
+ res.writeHead(404);
1578
+ res.end();
1579
+ });
1580
+ server.listen(port, "127.0.0.1");
1581
+ server.on("error", reject);
1582
+ setTimeout(() => {
1583
+ server.close();
1584
+ reject(new Error("Authentication timed out"));
1585
+ }, 5 * 60 * 1e3);
1651
1586
  });
1652
- if (response.status === 422) {
1653
- const data = await response.json();
1654
- const redirectUrl = data.redirect_browser_to;
1655
- if (redirectUrl) {
1656
- return redirectUrl;
1657
- }
1658
- throw new Error("No redirect URL in OIDC response");
1659
- }
1660
- if (response.ok) {
1661
- const data = await response.json();
1662
- if (data.session_token) {
1663
- return data.session_token;
1664
- }
1665
- }
1666
- const error = await response.text();
1667
- throw new Error(`Failed to initiate OIDC flow: ${response.status} - ${error}`);
1668
1587
  }
1669
1588
  async function login() {
1670
1589
  console.log("\nEstateHelm Login");
@@ -1672,18 +1591,15 @@ async function login() {
1672
1591
  console.log("Starting authentication server...");
1673
1592
  const port = await findAvailablePort();
1674
1593
  const callbackUrl = `http://127.0.0.1:${port}/callback`;
1675
- console.log("Creating login flow...");
1676
- const { flowId } = await createNativeLoginFlow(callbackUrl);
1677
- console.log("Initiating OAuth flow...");
1678
- const oauthUrl = await initiateOidcFlow(flowId, "google");
1679
- console.log(`
1680
- Opening browser for Google authentication...`);
1681
- console.log(`If the browser doesn't open, visit: ${oauthUrl}
1594
+ const loginUrl = `${APP_URL}/cli-auth?callback=${encodeURIComponent(callbackUrl)}`;
1595
+ console.log("\nOpening browser for authentication...");
1596
+ console.log(`If the browser doesn't open, visit:
1597
+ ${loginUrl}
1682
1598
  `);
1683
- const callbackPromise = waitForCallback(port);
1684
- await (0, import_open.default)(oauthUrl);
1599
+ const tokenPromise = waitForCallback(port);
1600
+ await (0, import_open.default)(loginUrl);
1685
1601
  console.log("Waiting for authentication...");
1686
- const sessionToken = await callbackPromise;
1602
+ const sessionToken = await tokenPromise;
1687
1603
  console.log("Authentication successful!");
1688
1604
  console.log(`Token: ${sanitizeToken(sessionToken)}`);
1689
1605
  await saveBearerToken(sessionToken);