ardent-cli 0.0.16 → 0.0.18

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 (2) hide show
  1. package/dist/index.js +240 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { readFileSync as readFileSync4 } from "fs";
5
- import { Command as Command7 } from "commander";
4
+ import { readFileSync as readFileSync5 } from "fs";
5
+ import { Command as Command8 } from "commander";
6
6
 
7
7
  // src/commands/branch/index.ts
8
8
  import { Command } from "commander";
@@ -700,6 +700,33 @@ async function createAction2(type, url, options) {
700
700
  console.error(` Supported: ${supportedTypes.join(", ")}`);
701
701
  process.exit(1);
702
702
  }
703
+ const deploymentModel = options.deploymentModel ?? "ardent-cloud";
704
+ if (deploymentModel !== "ardent-cloud" && deploymentModel !== "customer-cloud") {
705
+ console.error(`\u2717 Invalid --deployment-model: ${deploymentModel}`);
706
+ console.error(" Supported: ardent-cloud, customer-cloud");
707
+ process.exit(1);
708
+ }
709
+ const isCustomerCloud = deploymentModel === "customer-cloud";
710
+ if (isCustomerCloud) {
711
+ const missing = [];
712
+ if (!options.awsRoleArn) missing.push("--aws-role-arn");
713
+ if (!options.awsExternalId) missing.push("--aws-external-id");
714
+ if (!options.awsRegion) missing.push("--aws-region");
715
+ if (missing.length > 0) {
716
+ console.error(
717
+ `\u2717 ${missing.join(", ")} required when --deployment-model=customer-cloud`
718
+ );
719
+ process.exit(1);
720
+ }
721
+ } else {
722
+ const stray = options.awsRoleArn || options.awsExternalId || options.awsRegion;
723
+ if (stray) {
724
+ console.error(
725
+ "\u2717 --aws-role-arn / --aws-external-id / --aws-region require --deployment-model=customer-cloud"
726
+ );
727
+ process.exit(1);
728
+ }
729
+ }
703
730
  const isByoc = Boolean(options.byoc);
704
731
  if (isByoc) {
705
732
  if (!options.apiKey || !options.projectId) {
@@ -727,7 +754,9 @@ async function createAction2(type, url, options) {
727
754
  }
728
755
  let createPayload;
729
756
  if (isByoc) {
730
- console.log("Creating connector (BYOC Neon)...");
757
+ console.log(
758
+ `Creating connector (BYOC Neon${isCustomerCloud ? ", customer-cloud data plane" : ""})...`
759
+ );
731
760
  createPayload = {
732
761
  name: connectorName,
733
762
  service_name: "postgresql",
@@ -744,7 +773,9 @@ async function createAction2(type, url, options) {
744
773
  console.error(" Example: postgresql://user:password@host:5432/db");
745
774
  process.exit(1);
746
775
  }
747
- console.log("Creating connector...");
776
+ console.log(
777
+ `Creating connector${isCustomerCloud ? " (customer-cloud data plane)" : ""}...`
778
+ );
748
779
  createPayload = {
749
780
  name: connectorName,
750
781
  service_name: "postgresql",
@@ -757,6 +788,14 @@ async function createAction2(type, url, options) {
757
788
  }
758
789
  };
759
790
  }
791
+ if (isCustomerCloud) {
792
+ createPayload.deployment_model = "customer-cloud";
793
+ createPayload.byoc_access_credentials = {
794
+ role_arn: options.awsRoleArn,
795
+ external_id: options.awsExternalId,
796
+ region: options.awsRegion
797
+ };
798
+ }
760
799
  const created = await api.post("/v1/connectors", createPayload);
761
800
  const connectorId = created.id;
762
801
  if (isByoc) {
@@ -807,7 +846,11 @@ async function createAction2(type, url, options) {
807
846
  setCacheEntry("connectors", cachedConnectors);
808
847
  setConfig("currentConnectorId", connectorId);
809
848
  setConfig("currentConnectorName", connectorName);
810
- trackEvent("CLI: connector create succeeded", { db_type: type, byoc: isByoc });
849
+ trackEvent("CLI: connector create succeeded", {
850
+ db_type: type,
851
+ byoc: isByoc,
852
+ deployment_model: deploymentModel
853
+ });
811
854
  console.log("\u2713 Connector created and ready");
812
855
  console.log(` ID: ${connectorId}`);
813
856
  showNextStep();
@@ -1009,7 +1052,19 @@ async function switchAction2(name) {
1009
1052
 
1010
1053
  // src/commands/connector/index.ts
1011
1054
  var connectorCommand = new Command2("connector").description("Manage database connectors");
1012
- connectorCommand.command("create <type> [url]").description("Create a new connector").option("-n, --name <name>", "Connector name").option("--byoc <provider>", "Bring your own Neon project (e.g. neon)").option("--api-key <key>", "Neon API key (required with --byoc)").option("--project-id <id>", "Neon project ID (required with --byoc)").action(createAction2);
1055
+ connectorCommand.command("create <type> [url]").description("Create a new connector").option("-n, --name <name>", "Connector name").option("--byoc <provider>", "Bring your own Neon project (e.g. neon)").option("--api-key <key>", "Neon API key (required with --byoc)").option("--project-id <id>", "Neon project ID (required with --byoc)").option(
1056
+ "--deployment-model <model>",
1057
+ "'ardent-cloud' (default) or 'customer-cloud' to route CDC through the customer's AWS account"
1058
+ ).option(
1059
+ "--aws-role-arn <arn>",
1060
+ "ArdentDeployer role ARN in the customer account (required with --deployment-model=customer-cloud)"
1061
+ ).option(
1062
+ "--aws-external-id <id>",
1063
+ "External ID for sts:AssumeRole (required with --deployment-model=customer-cloud)"
1064
+ ).option(
1065
+ "--aws-region <region>",
1066
+ "AWS region of the customer data plane (required with --deployment-model=customer-cloud)"
1067
+ ).action(createAction2);
1013
1068
  connectorCommand.command("list").description("List your connectors").action(listAction2);
1014
1069
  connectorCommand.command("switch <name>").description("Switch to a different connector").action(switchAction2);
1015
1070
  connectorCommand.command("delete <name>").description("Delete a connector by name").action(deleteAction2);
@@ -1385,9 +1440,174 @@ projectCommand.command("create <name>").description("Create a new project").acti
1385
1440
  projectCommand.command("list").description("List your projects").action(listAction4);
1386
1441
  projectCommand.command("switch <name>").description("Switch to a different project").action(switchAction3);
1387
1442
 
1388
- // src/commands/auth/index.ts
1443
+ // src/commands/settings/index.ts
1389
1444
  import { Command as Command6 } from "commander";
1390
1445
 
1446
+ // src/lib/settings.ts
1447
+ import { readFileSync as readFileSync3 } from "fs";
1448
+ var SETTING_KEYS = ["default_db", "branch_sql"];
1449
+ function requireConnectorAndOrg() {
1450
+ const connectorId = getConfig("currentConnectorId");
1451
+ const user = getConfig("user");
1452
+ const orgId = user?.org_id;
1453
+ if (!connectorId) {
1454
+ console.error("\u2717 No connector selected. Run 'ardent connector switch' first.");
1455
+ process.exit(1);
1456
+ }
1457
+ if (!orgId) {
1458
+ console.error("\u2717 Not logged in. Run 'ardent login' first.");
1459
+ process.exit(1);
1460
+ }
1461
+ return {
1462
+ connectorId,
1463
+ connectorName: getConfig("currentConnectorName") ?? connectorId,
1464
+ orgId
1465
+ };
1466
+ }
1467
+ function parseSettingKey(key) {
1468
+ if (!SETTING_KEYS.includes(key)) {
1469
+ console.error(`\u2717 Unknown setting '${key}'. Valid: ${SETTING_KEYS.join(", ")}`);
1470
+ process.exit(1);
1471
+ }
1472
+ return key;
1473
+ }
1474
+ var SETTING_DESCRIPTIONS = {
1475
+ default_db: "Default database in branch URLs",
1476
+ branch_sql: "SQL to run on every new branch after creation"
1477
+ };
1478
+ function settingKeyToPolicyType(key) {
1479
+ if (key === "default_db") return "connection_default_db";
1480
+ if (key === "branch_sql") return "branch_create_hook";
1481
+ throw new Error(`Unknown setting key: ${key}`);
1482
+ }
1483
+ function buildPolicyConfig(key, value) {
1484
+ if (key === "default_db") return { database: value };
1485
+ if (key === "branch_sql") return { sql: value };
1486
+ throw new Error(`Unknown setting key: ${key}`);
1487
+ }
1488
+ function readSettingValue(key, config) {
1489
+ if (key === "default_db") return String(config.database ?? "");
1490
+ if (key === "branch_sql") return String(config.sql ?? "");
1491
+ throw new Error(`Unknown setting key: ${key}`);
1492
+ }
1493
+ function resolveValueFromArg(value) {
1494
+ if (value.startsWith("@")) {
1495
+ const path = value.slice(1);
1496
+ try {
1497
+ return readFileSync3(path, "utf-8");
1498
+ } catch (err) {
1499
+ throw new Error(
1500
+ `Failed to read ${path}: ${err instanceof Error ? err.message : String(err)}`
1501
+ );
1502
+ }
1503
+ }
1504
+ return value;
1505
+ }
1506
+ async function findPolicyForConnector(orgId, connectorId, policyType) {
1507
+ const policies = await api.get(
1508
+ `/v1/policies?org_id=${orgId}&connector_id=${connectorId}`
1509
+ );
1510
+ return policies.find((policy) => policy.type === policyType) ?? null;
1511
+ }
1512
+
1513
+ // src/commands/settings/list.ts
1514
+ async function listAction5() {
1515
+ const { connectorId, connectorName, orgId } = requireConnectorAndOrg();
1516
+ try {
1517
+ console.log(`Connector: ${connectorName}
1518
+ `);
1519
+ for (const key of SETTING_KEYS) {
1520
+ const policy = await findPolicyForConnector(
1521
+ orgId,
1522
+ connectorId,
1523
+ settingKeyToPolicyType(key)
1524
+ );
1525
+ if (policy) {
1526
+ const value = readSettingValue(key, policy.config);
1527
+ const display = value.length > 80 ? value.slice(0, 77) + "..." : value;
1528
+ console.log(` ${key.padEnd(12)} ${display}`);
1529
+ } else {
1530
+ console.log(` ${key.padEnd(12)} (not set) \u2014 ${SETTING_DESCRIPTIONS[key]}`);
1531
+ }
1532
+ }
1533
+ trackEvent("CLI: settings list succeeded");
1534
+ } catch (err) {
1535
+ trackEvent("CLI: settings list failed", { reason: "api_error" });
1536
+ console.error("\u2717 Failed:", err instanceof Error ? err.message : err);
1537
+ process.exit(1);
1538
+ }
1539
+ }
1540
+
1541
+ // src/commands/settings/set.ts
1542
+ async function setAction(key, value) {
1543
+ const settingKey = parseSettingKey(key);
1544
+ const { connectorId, orgId } = requireConnectorAndOrg();
1545
+ let resolvedValue;
1546
+ try {
1547
+ resolvedValue = resolveValueFromArg(value);
1548
+ } catch (err) {
1549
+ console.error("\u2717", err instanceof Error ? err.message : err);
1550
+ process.exit(1);
1551
+ }
1552
+ const policyType = settingKeyToPolicyType(settingKey);
1553
+ const config = buildPolicyConfig(settingKey, resolvedValue);
1554
+ try {
1555
+ const existing = await findPolicyForConnector(orgId, connectorId, policyType);
1556
+ if (existing) {
1557
+ await api.patch(`/v1/policies/${existing.id}`, { config });
1558
+ console.log(`\u2713 Updated ${settingKey}`);
1559
+ trackEvent("CLI: settings set succeeded", { key: settingKey, op: "update" });
1560
+ return;
1561
+ }
1562
+ await api.post("/v1/policies", {
1563
+ org_id: orgId,
1564
+ name: settingKey,
1565
+ type: policyType,
1566
+ config,
1567
+ assign_to_scope: { scope_type: "connectors", scope_id: connectorId }
1568
+ });
1569
+ console.log(`\u2713 Set ${settingKey}`);
1570
+ trackEvent("CLI: settings set succeeded", { key: settingKey, op: "create" });
1571
+ } catch (err) {
1572
+ trackEvent("CLI: settings set failed", { key: settingKey });
1573
+ console.error("\u2717 Failed:", err instanceof Error ? err.message : err);
1574
+ process.exit(1);
1575
+ }
1576
+ }
1577
+
1578
+ // src/commands/settings/remove.ts
1579
+ async function removeAction2(key) {
1580
+ const settingKey = parseSettingKey(key);
1581
+ const { connectorId, orgId } = requireConnectorAndOrg();
1582
+ const policyType = settingKeyToPolicyType(settingKey);
1583
+ try {
1584
+ const existing = await findPolicyForConnector(orgId, connectorId, policyType);
1585
+ if (!existing) {
1586
+ console.log(`${settingKey} is not set`);
1587
+ trackEvent("CLI: settings remove noop", { key: settingKey });
1588
+ return;
1589
+ }
1590
+ await api.delete(`/v1/policies/${existing.id}`);
1591
+ console.log(`\u2713 Removed ${settingKey}`);
1592
+ trackEvent("CLI: settings remove succeeded", { key: settingKey });
1593
+ } catch (err) {
1594
+ trackEvent("CLI: settings remove failed", { key: settingKey });
1595
+ console.error("\u2717 Failed:", err instanceof Error ? err.message : err);
1596
+ process.exit(1);
1597
+ }
1598
+ }
1599
+
1600
+ // src/commands/settings/index.ts
1601
+ var settingsCommand = new Command6("settings").description("Manage settings for the current connector").showHelpAfterError("(run 'ardent settings --help' for valid keys)");
1602
+ settingsCommand.command("list").description("List current settings for the connector").action(listAction5);
1603
+ settingsCommand.command("set <key> <value>").description(
1604
+ "Set a setting. Keys: default_db, branch_sql. For branch_sql, prefix value with @ to read from file."
1605
+ ).action(setAction);
1606
+ settingsCommand.command("remove <key>").description("Remove a setting. Keys: default_db, branch_sql.").action(removeAction2);
1607
+
1608
+ // src/commands/auth/index.ts
1609
+ import { Command as Command7 } from "commander";
1610
+
1391
1611
  // src/commands/auth/login.ts
1392
1612
  async function loginAction(options) {
1393
1613
  if (options.token) {
@@ -1517,12 +1737,12 @@ function statusAction() {
1517
1737
  }
1518
1738
 
1519
1739
  // src/commands/auth/index.ts
1520
- var loginCommand = new Command6("login").description("Login to Ardent").option("-t, --token <token>", "API token (skip browser login)").action(loginAction);
1521
- var logoutCommand = new Command6("logout").description("Logout from Ardent").action(logoutAction);
1522
- var statusCommand = new Command6("status").description("Show status").action(statusAction);
1740
+ var loginCommand = new Command7("login").description("Login to Ardent").option("-t, --token <token>", "API token (skip browser login)").action(loginAction);
1741
+ var logoutCommand = new Command7("logout").description("Logout from Ardent").action(logoutAction);
1742
+ var statusCommand = new Command7("status").description("Show status").action(statusAction);
1523
1743
 
1524
1744
  // src/lib/update-check.ts
1525
- import { existsSync as existsSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
1745
+ import { existsSync as existsSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
1526
1746
  import { join as join2 } from "path";
1527
1747
  import { homedir as homedir2 } from "os";
1528
1748
  var UPDATE_CHECK_FILE = join2(homedir2(), ".ardent", "update-check.json");
@@ -1531,7 +1751,7 @@ var PACKAGE_NAME = "ardent-cli";
1531
1751
  function loadCache() {
1532
1752
  try {
1533
1753
  if (existsSync2(UPDATE_CHECK_FILE)) {
1534
- return JSON.parse(readFileSync3(UPDATE_CHECK_FILE, "utf-8"));
1754
+ return JSON.parse(readFileSync4(UPDATE_CHECK_FILE, "utf-8"));
1535
1755
  }
1536
1756
  } catch {
1537
1757
  }
@@ -1624,6 +1844,11 @@ BRANCHES
1624
1844
  branch delete Delete a branch
1625
1845
  branch switch Switch to a different branch
1626
1846
 
1847
+ SETTINGS
1848
+ settings list List current settings for the connector
1849
+ settings set Set a setting (e.g. default_db testdb)
1850
+ settings remove Remove a setting
1851
+
1627
1852
  TEAM
1628
1853
  invite <email> Invite a user to your organization
1629
1854
  invite list List pending invites
@@ -1644,11 +1869,11 @@ EXAMPLES
1644
1869
  ardent org members
1645
1870
  `;
1646
1871
  var CLI_VERSION2 = getCliVersion2();
1647
- var program = new Command7();
1872
+ var program = new Command8();
1648
1873
  function getCliVersion2() {
1649
1874
  try {
1650
1875
  const packageUrl = new URL("../package.json", import.meta.url);
1651
- const raw = readFileSync4(packageUrl, "utf-8");
1876
+ const raw = readFileSync5(packageUrl, "utf-8");
1652
1877
  const parsed = JSON.parse(raw);
1653
1878
  return parsed.version ?? "unknown";
1654
1879
  } catch {
@@ -1664,6 +1889,7 @@ program.addCommand(statusCommand);
1664
1889
  program.addCommand(projectCommand);
1665
1890
  program.addCommand(connectorCommand);
1666
1891
  program.addCommand(branchCommand);
1892
+ program.addCommand(settingsCommand);
1667
1893
  program.addCommand(inviteCommand);
1668
1894
  program.addCommand(orgCommand);
1669
1895
  program.on("command:*", (operands) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ardent-cli",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "Git for Data infrastructure",
5
5
  "type": "module",
6
6
  "bin": {