@boltic/cli 1.1.1-dev.1 → 1.1.1-dev.2

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.
@@ -74,8 +74,8 @@ const commands = {
74
74
 
75
75
  // Serverless type choices for dropdown
76
76
  const SERVERLESS_TYPE_CHOICES = [
77
- { name: "📝 Code - Write code directly", value: "code" },
78
- { name: "📦 Git - Deploy from Git repository", value: "git" },
77
+ { name: "📦 Git - Deploy from Git repository", value: "git" },
78
+ { name: "📝 Blueprint - Write code directly", value: "code" },
79
79
  { name: "🐳 Container - Deploy Docker container", value: "container" },
80
80
  ];
81
81
 
@@ -347,7 +347,7 @@ async function handleCodeTypeCreate(name, language, version, targetDir) {
347
347
  // Display success message
348
348
  console.log("\n" + chalk.bgGreen.black(" ✓ CREATED ") + "\n");
349
349
  console.log(
350
- chalk.green("📝 Code-based serverless function created successfully!")
350
+ chalk.green("📝 Blueprint serverless function created successfully!")
351
351
  );
352
352
  console.log();
353
353
  console.log(chalk.cyan(" Name: ") + chalk.white(name));
@@ -1563,7 +1563,7 @@ function showHelp() {
1563
1563
  console.log(
1564
1564
  chalk.bold(" --type, -t") +
1565
1565
  chalk.dim(" ") +
1566
- "Serverless type: code, git, or container (prompts if not provided)"
1566
+ "Serverless type: blueprint, git, or container (prompts if not provided)"
1567
1567
  );
1568
1568
  console.log(
1569
1569
  chalk.bold(" --name, -n") +
@@ -1619,9 +1619,9 @@ function showHelp() {
1619
1619
  )
1620
1620
  );
1621
1621
  console.log(" boltic serverless create\n");
1622
- console.log(chalk.dim(" # Create code-based serverless"));
1622
+ console.log(chalk.dim(" # Create blueprint serverless"));
1623
1623
  console.log(
1624
- " boltic serverless create --type code --name my-api --language nodejs\n"
1624
+ " boltic serverless create --type blueprint --name my-api --language nodejs\n"
1625
1625
  );
1626
1626
  console.log(
1627
1627
  chalk.dim(
@@ -1637,7 +1637,7 @@ function showHelp() {
1637
1637
  );
1638
1638
  console.log(chalk.dim(" # With custom directory"));
1639
1639
  console.log(
1640
- " boltic serverless create --type code --name my-function --language python --directory ./projects\n"
1640
+ " boltic serverless create --type blueprint --name my-function --language python --directory ./projects\n"
1641
1641
  );
1642
1642
 
1643
1643
  console.log(chalk.cyan("\nTest Examples:\n"));
@@ -8,6 +8,7 @@ import {
8
8
  adjectives,
9
9
  animals,
10
10
  } from "unique-names-generator";
11
+ import ora from "ora";
11
12
 
12
13
  // Supported languages and their versions
13
14
  export const SUPPORTED_LANGUAGES = ["nodejs", "python", "golang", "java"];
@@ -59,7 +60,12 @@ export function parseCreateArgs(args) {
59
60
  parsed.directory = path.resolve(nextArg);
60
61
  i++;
61
62
  } else if ((arg === "--type" || arg === "-t") && nextArg) {
62
- parsed.type = nextArg.toLowerCase();
63
+ let typeValue = nextArg.toLowerCase();
64
+ // Map "blueprint" to "code" for UI consistency
65
+ if (typeValue === "blueprint") {
66
+ typeValue = "code";
67
+ }
68
+ parsed.type = typeValue;
63
69
  i++;
64
70
  }
65
71
  }
@@ -1526,8 +1532,6 @@ export async function pollServerlessStatus(
1526
1532
  ) {
1527
1533
  const { apiUrl, token, accountId, session } = credentials;
1528
1534
  const startTime = Date.now();
1529
- const spinnerFrames = ["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"];
1530
- let spinnerIndex = 0;
1531
1535
  let initialBuildId = null;
1532
1536
  let sawNewBuild = false;
1533
1537
 
@@ -1540,136 +1544,174 @@ export async function pollServerlessStatus(
1540
1544
  return `${minutes}m ${remainingSecs}s`;
1541
1545
  };
1542
1546
 
1543
- // Get status display
1544
- const getStatusDisplay = (status) => {
1547
+ // Get status text (without chalk for ora)
1548
+ const getStatusText = (status) => {
1545
1549
  switch (status) {
1546
1550
  case "running":
1547
- return chalk.green("Running");
1551
+ return "Running";
1548
1552
  case "building":
1549
- return chalk.yellow("Building");
1553
+ return "Building";
1550
1554
  case "pending":
1551
- return chalk.yellow("Pending");
1555
+ return "Pending";
1552
1556
  case "draft":
1553
- return chalk.blue("Initializing");
1557
+ return "Initializing";
1554
1558
  case "failed":
1555
1559
  case "error":
1556
- return chalk.red("Failed");
1560
+ return "Failed";
1557
1561
  case "success":
1558
1562
  case "successful":
1559
- return chalk.green("Success");
1563
+ return "Success";
1560
1564
  default:
1561
- return chalk.gray(status || "Waiting");
1565
+ return status || "Waiting";
1562
1566
  }
1563
1567
  };
1564
1568
 
1565
1569
  console.log();
1566
1570
  console.log(chalk.cyan(" Deploying serverless function..."));
1571
+ console.log(
1572
+ chalk.dim(" Press Ctrl+C to exit. Check status later with: ") +
1573
+ chalk.white("boltic serverless status -n <name>")
1574
+ );
1567
1575
  console.log();
1568
1576
 
1569
- while (Date.now() - startTime < maxTime) {
1570
- const elapsed = Date.now() - startTime;
1571
- const spinner = spinnerFrames[spinnerIndex % spinnerFrames.length];
1572
- spinnerIndex++;
1577
+ // Track current status for display
1578
+ let status = "pending";
1579
+ let buildStatus = null;
1580
+ let lastServerless = null;
1573
1581
 
1574
- try {
1575
- // Fetch serverless status
1576
- const serverless = await fetchStatus(
1577
- apiUrl,
1578
- token,
1579
- accountId,
1580
- session,
1581
- serverlessId
1582
- );
1582
+ // Create ora spinner
1583
+ const spinner = ora({
1584
+ text: `${getStatusText(status)} (0s)`,
1585
+ spinner: "dots",
1586
+ color: "cyan",
1587
+ }).start();
1583
1588
 
1584
- const status = serverless?.Status || "pending";
1585
- const buildStatus =
1586
- serverless?.LastBuild?.StatusHistory?.slice(-1)[0]?.Status;
1587
- const currentBuildId = serverless?.LastBuild?.ID;
1589
+ // Update elapsed time every second
1590
+ const timerInterval = setInterval(() => {
1591
+ const elapsed = Date.now() - startTime;
1592
+ let text = getStatusText(status);
1593
+ if (buildStatus && buildStatus !== status) {
1594
+ text += ` • Build: ${getStatusText(buildStatus)}`;
1595
+ }
1596
+ text += ` (${formatElapsed(elapsed)})`;
1597
+ spinner.text = text;
1598
+ }, 1000);
1588
1599
 
1589
- // Track if a new build has started (different from initial or is building)
1590
- if (!initialBuildId) {
1591
- initialBuildId = currentBuildId;
1592
- }
1600
+ // Cleanup function
1601
+ const cleanup = () => {
1602
+ clearInterval(timerInterval);
1603
+ };
1593
1604
 
1594
- // Detect new build: either build ID changed or we see "building" status
1595
- if (
1596
- currentBuildId !== initialBuildId ||
1597
- buildStatus === "building" ||
1598
- buildStatus === "created"
1599
- ) {
1600
- sawNewBuild = true;
1601
- }
1605
+ try {
1606
+ while (Date.now() - startTime < maxTime) {
1607
+ try {
1608
+ // Fetch serverless status
1609
+ const serverless = await fetchStatus(
1610
+ apiUrl,
1611
+ token,
1612
+ accountId,
1613
+ session,
1614
+ serverlessId
1615
+ );
1602
1616
 
1603
- // Build status line
1604
- let statusText = getStatusDisplay(status);
1605
- if (buildStatus && buildStatus !== status) {
1606
- statusText +=
1607
- chalk.dim(" Build: ") + getStatusDisplay(buildStatus);
1608
- }
1617
+ lastServerless = serverless;
1618
+ status = serverless?.Status || "pending";
1619
+ buildStatus =
1620
+ serverless?.LastBuild?.StatusHistory?.slice(-1)[0]?.Status;
1621
+ const currentBuildId = serverless?.LastBuild?.ID;
1609
1622
 
1610
- // Update the same line with current status
1611
- process.stdout.write(
1612
- `\r\x1b[K ${chalk.cyan(spinner)} ${statusText} ${chalk.dim(`(${formatElapsed(elapsed)})`)}`
1613
- );
1623
+ // Track if a new build has started
1624
+ if (!initialBuildId) {
1625
+ initialBuildId = currentBuildId;
1626
+ }
1627
+
1628
+ // Detect new build
1629
+ if (
1630
+ currentBuildId !== initialBuildId ||
1631
+ buildStatus === "building" ||
1632
+ buildStatus === "created"
1633
+ ) {
1634
+ sawNewBuild = true;
1635
+ }
1614
1636
 
1615
- // Success condition:
1616
- // 1. We must have seen a new build start (sawNewBuild = true)
1617
- // 2. Build is complete (success)
1618
- // 3. Status is running
1619
- const isBuildComplete =
1620
- buildStatus === "success" || buildStatus === "successful";
1621
- const isRunning = status === "running";
1637
+ // Update spinner color based on status
1638
+ if (status === "running" || buildStatus === "success") {
1639
+ spinner.color = "green";
1640
+ } else if (status === "failed" || buildStatus === "failed") {
1641
+ spinner.color = "red";
1642
+ } else if (
1643
+ status === "building" ||
1644
+ buildStatus === "building"
1645
+ ) {
1646
+ spinner.color = "yellow";
1647
+ }
1622
1648
 
1623
- if (sawNewBuild && isRunning && isBuildComplete) {
1624
- process.stdout.write("\r\x1b[K"); // Clear spinner line
1625
- console.log(
1626
- chalk.green(
1627
- ` ✓ Deployed successfully in ${formatElapsed(elapsed)}`
1628
- )
1629
- );
1630
- console.log();
1631
-
1632
- // Print access URL if available
1633
- const appDomain = serverless?.AppDomain?.[0];
1634
- if (appDomain) {
1635
- const url = `https://${appDomain.DomainName}.${appDomain.BaseUrl || "serverless.boltic.app"}`;
1636
- console.log(chalk.cyan(" 🌐 Your serverless is live at:"));
1637
- console.log(chalk.white.bold(` ${url}`));
1649
+ // Success condition
1650
+ const isBuildComplete =
1651
+ buildStatus === "success" || buildStatus === "successful";
1652
+ const isRunning = status === "running";
1653
+
1654
+ if (sawNewBuild && isRunning && isBuildComplete) {
1655
+ const elapsed = Date.now() - startTime;
1656
+ cleanup();
1657
+ spinner.succeed(
1658
+ chalk.green(
1659
+ `Deployed successfully in ${formatElapsed(elapsed)}`
1660
+ )
1661
+ );
1638
1662
  console.log();
1663
+
1664
+ // Print access URL if available
1665
+ const appDomain = serverless?.AppDomain?.[0];
1666
+ if (appDomain) {
1667
+ const url = `https://${appDomain.DomainName}.${appDomain.BaseUrl || "serverless.boltic.app"}`;
1668
+ console.log(
1669
+ chalk.cyan(" 🌐 Your serverless is live at:")
1670
+ );
1671
+ console.log(chalk.white.bold(` ${url}`));
1672
+ console.log();
1673
+ }
1674
+
1675
+ return { success: true, status, serverless };
1639
1676
  }
1640
1677
 
1641
- return { success: true, status, serverless };
1678
+ // Check for failed status
1679
+ if (status === "failed" || buildStatus === "failed") {
1680
+ const elapsed = Date.now() - startTime;
1681
+ cleanup();
1682
+ spinner.fail(
1683
+ chalk.red(
1684
+ `Deployment failed after ${formatElapsed(elapsed)}`
1685
+ )
1686
+ );
1687
+ console.log();
1688
+ return { success: false, status, serverless };
1689
+ }
1690
+ } catch (error) {
1691
+ // Error during fetch - will retry on next poll
1642
1692
  }
1643
1693
 
1644
- // Check for failed status
1645
- if (status === "failed" || buildStatus === "failed") {
1646
- process.stdout.write("\r\x1b[K"); // Clear spinner line
1647
- console.log(
1648
- chalk.red(
1649
- ` ✗ Deployment failed after ${formatElapsed(elapsed)}`
1650
- )
1651
- );
1652
- console.log();
1653
- return { success: false, status, serverless };
1654
- }
1655
- } catch (error) {
1656
- process.stdout.write(
1657
- `\r\x1b[K ${chalk.yellow("!")} ${chalk.dim("Retrying...")} ${chalk.dim(`(${formatElapsed(elapsed)})`)}`
1658
- );
1694
+ // Wait before next poll
1695
+ await new Promise((r) => setTimeout(r, interval));
1659
1696
  }
1660
1697
 
1661
- // Wait before next poll
1662
- await new Promise((r) => setTimeout(r, interval));
1663
- }
1664
-
1665
- // Timeout reached - clear the spinner line
1666
- process.stdout.write("\r\x1b[K");
1667
- console.log(chalk.yellow(` ⚠ Timeout after ${formatElapsed(maxTime)}`));
1668
- console.log(chalk.dim(" Deployment may still be in progress."));
1669
- console.log(
1670
- chalk.dim(" Check status: boltic serverless status -n <name>")
1671
- );
1672
- console.log();
1698
+ // Timeout reached
1699
+ cleanup();
1700
+ spinner.warn(chalk.yellow(`Timeout after ${formatElapsed(maxTime)}`));
1701
+ console.log(chalk.dim(" Deployment may still be in progress."));
1702
+ console.log(
1703
+ chalk.dim(" Check status: boltic serverless status -n <name>")
1704
+ );
1705
+ console.log();
1673
1706
 
1674
- return { success: false, status: "timeout" };
1707
+ return {
1708
+ success: false,
1709
+ status: "timeout",
1710
+ serverless: lastServerless,
1711
+ };
1712
+ } catch (error) {
1713
+ cleanup();
1714
+ spinner.fail("Polling interrupted");
1715
+ throw error;
1716
+ }
1675
1717
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boltic/cli",
3
- "version": "v1.1.1-dev.1",
3
+ "version": "v1.1.1-dev.2",
4
4
  "description": "A powerful CLI tool for managing Boltic Workflow integrations - create, sync, test, and publish integrations with ease",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -105,6 +105,7 @@
105
105
  "keytar": "^7.9.0",
106
106
  "lodash.isempty": "^4.4.0",
107
107
  "open": "^10.2.0",
108
+ "ora": "^9.0.0",
108
109
  "unique-names-generator": "^4.7.1",
109
110
  "uuid": "^11.1.0"
110
111
  },