ardent-cli 0.0.18 → 0.0.20
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 +275 -61
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -59,7 +59,9 @@ function getToken() {
|
|
|
59
59
|
}
|
|
60
60
|
function setCacheEntry(key, data) {
|
|
61
61
|
const config = loadConfig();
|
|
62
|
-
if (!config.cache)
|
|
62
|
+
if (!config.cache) {
|
|
63
|
+
config.cache = {};
|
|
64
|
+
}
|
|
63
65
|
config.cache[key] = {
|
|
64
66
|
data,
|
|
65
67
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -75,10 +77,16 @@ function formatCacheTime(isoString) {
|
|
|
75
77
|
const now = /* @__PURE__ */ new Date();
|
|
76
78
|
const diffMs = now.getTime() - date.getTime();
|
|
77
79
|
const diffMins = Math.floor(diffMs / 6e4);
|
|
78
|
-
if (diffMins < 1)
|
|
79
|
-
|
|
80
|
+
if (diffMins < 1) {
|
|
81
|
+
return "just now";
|
|
82
|
+
}
|
|
83
|
+
if (diffMins < 60) {
|
|
84
|
+
return `${diffMins}m ago`;
|
|
85
|
+
}
|
|
80
86
|
const diffHours = Math.floor(diffMins / 60);
|
|
81
|
-
if (diffHours < 24)
|
|
87
|
+
if (diffHours < 24) {
|
|
88
|
+
return `${diffHours}h ago`;
|
|
89
|
+
}
|
|
82
90
|
return date.toLocaleDateString();
|
|
83
91
|
}
|
|
84
92
|
function getCurrentBranch() {
|
|
@@ -94,42 +102,84 @@ function clearCurrentBranch() {
|
|
|
94
102
|
}
|
|
95
103
|
async function bootstrapCache() {
|
|
96
104
|
const token = getToken();
|
|
97
|
-
if (!token)
|
|
105
|
+
if (!token) {
|
|
106
|
+
throw new Error("Not authenticated");
|
|
107
|
+
}
|
|
108
|
+
const staleConfig = loadConfig();
|
|
109
|
+
delete staleConfig.user;
|
|
110
|
+
delete staleConfig.userId;
|
|
111
|
+
delete staleConfig.currentProjectId;
|
|
112
|
+
delete staleConfig.currentProjectName;
|
|
113
|
+
delete staleConfig.currentConnectorId;
|
|
114
|
+
delete staleConfig.currentConnectorName;
|
|
115
|
+
delete staleConfig.currentBranch;
|
|
116
|
+
delete staleConfig.cache;
|
|
117
|
+
saveConfig(staleConfig);
|
|
98
118
|
const apiUrl = getApiUrl();
|
|
99
119
|
const headers = {
|
|
100
120
|
"Content-Type": "application/json",
|
|
101
121
|
"Authorization": `Bearer ${token}`
|
|
102
122
|
};
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
123
|
+
const userInfoResponse = await fetch(`${apiUrl}/v1/cli/me`, { headers });
|
|
124
|
+
if (!userInfoResponse.ok) {
|
|
125
|
+
throw new Error("Failed to fetch user info");
|
|
126
|
+
}
|
|
127
|
+
const user = await userInfoResponse.json();
|
|
128
|
+
setConfig("user", user);
|
|
129
|
+
const bootstrap = { projects: [], connectors: [], branches: [] };
|
|
130
|
+
if (!user.org_id) {
|
|
131
|
+
return bootstrap;
|
|
132
|
+
}
|
|
133
|
+
const projectsResponse = await fetch(`${apiUrl}/v1/projects?org_id=${user.org_id}`, { headers });
|
|
134
|
+
if (projectsResponse.ok) {
|
|
135
|
+
const projectsPayload = await projectsResponse.json();
|
|
136
|
+
if (!Array.isArray(projectsPayload.projects)) {
|
|
137
|
+
throw new Error("API returned invalid response: missing projects array");
|
|
138
|
+
}
|
|
139
|
+
bootstrap.projects = projectsPayload.projects;
|
|
140
|
+
setCacheEntry("projects", bootstrap.projects);
|
|
141
|
+
}
|
|
142
|
+
if (bootstrap.projects.length === 1) {
|
|
143
|
+
const project = bootstrap.projects[0];
|
|
144
|
+
setConfig("currentProjectId", project.id);
|
|
145
|
+
setConfig("currentProjectName", project.name);
|
|
114
146
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
147
|
+
const currentProjectId = getConfig("currentProjectId");
|
|
148
|
+
if (currentProjectId) {
|
|
149
|
+
const connectorsResponse = await fetch(
|
|
150
|
+
`${apiUrl}/v1/cli/connectors?project_id=${currentProjectId}`,
|
|
151
|
+
{ headers }
|
|
152
|
+
);
|
|
153
|
+
if (connectorsResponse.ok) {
|
|
154
|
+
const connectorsPayload = await connectorsResponse.json();
|
|
155
|
+
if (!Array.isArray(connectorsPayload.connectors)) {
|
|
156
|
+
throw new Error("API returned invalid response: missing connectors array");
|
|
157
|
+
}
|
|
158
|
+
bootstrap.connectors = connectorsPayload.connectors;
|
|
159
|
+
setCacheEntry("connectors", bootstrap.connectors);
|
|
160
|
+
}
|
|
161
|
+
if (bootstrap.connectors.length === 1) {
|
|
162
|
+
const connector = bootstrap.connectors[0];
|
|
163
|
+
setConfig("currentConnectorId", connector.id);
|
|
164
|
+
setConfig("currentConnectorName", connector.name);
|
|
165
|
+
}
|
|
118
166
|
}
|
|
119
167
|
const currentConnectorId = getConfig("currentConnectorId");
|
|
120
168
|
if (currentConnectorId) {
|
|
121
|
-
const
|
|
169
|
+
const branchesResponse = await fetch(
|
|
122
170
|
`${apiUrl}/v1/cli/branches?connector_id=${currentConnectorId}`,
|
|
123
171
|
{ headers }
|
|
124
172
|
);
|
|
125
|
-
if (
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
173
|
+
if (branchesResponse.ok) {
|
|
174
|
+
const branchesPayload = await branchesResponse.json();
|
|
175
|
+
if (!Array.isArray(branchesPayload.branches)) {
|
|
176
|
+
throw new Error("API returned invalid response: missing branches array");
|
|
177
|
+
}
|
|
178
|
+
bootstrap.branches = branchesPayload.branches;
|
|
179
|
+
setCacheEntry("branches", bootstrap.branches);
|
|
130
180
|
}
|
|
131
181
|
}
|
|
132
|
-
return
|
|
182
|
+
return bootstrap;
|
|
133
183
|
}
|
|
134
184
|
|
|
135
185
|
// src/lib/api.ts
|
|
@@ -712,6 +762,7 @@ async function createAction2(type, url, options) {
|
|
|
712
762
|
if (!options.awsRoleArn) missing.push("--aws-role-arn");
|
|
713
763
|
if (!options.awsExternalId) missing.push("--aws-external-id");
|
|
714
764
|
if (!options.awsRegion) missing.push("--aws-region");
|
|
765
|
+
if (!options.awsClusterName) missing.push("--aws-cluster-name");
|
|
715
766
|
if (missing.length > 0) {
|
|
716
767
|
console.error(
|
|
717
768
|
`\u2717 ${missing.join(", ")} required when --deployment-model=customer-cloud`
|
|
@@ -719,10 +770,10 @@ async function createAction2(type, url, options) {
|
|
|
719
770
|
process.exit(1);
|
|
720
771
|
}
|
|
721
772
|
} else {
|
|
722
|
-
const stray = options.awsRoleArn || options.awsExternalId || options.awsRegion;
|
|
773
|
+
const stray = options.awsRoleArn || options.awsExternalId || options.awsRegion || options.awsClusterName;
|
|
723
774
|
if (stray) {
|
|
724
775
|
console.error(
|
|
725
|
-
"\u2717 --aws-role-arn / --aws-external-id / --aws-region require --deployment-model=customer-cloud"
|
|
776
|
+
"\u2717 --aws-role-arn / --aws-external-id / --aws-region / --aws-cluster-name require --deployment-model=customer-cloud"
|
|
726
777
|
);
|
|
727
778
|
process.exit(1);
|
|
728
779
|
}
|
|
@@ -793,7 +844,8 @@ async function createAction2(type, url, options) {
|
|
|
793
844
|
createPayload.byoc_access_credentials = {
|
|
794
845
|
role_arn: options.awsRoleArn,
|
|
795
846
|
external_id: options.awsExternalId,
|
|
796
|
-
region: options.awsRegion
|
|
847
|
+
region: options.awsRegion,
|
|
848
|
+
cluster_name: options.awsClusterName
|
|
797
849
|
};
|
|
798
850
|
}
|
|
799
851
|
const created = await api.post("/v1/connectors", createPayload);
|
|
@@ -913,8 +965,10 @@ async function listAction2() {
|
|
|
913
965
|
`);
|
|
914
966
|
}
|
|
915
967
|
if (connectors.length === 0) {
|
|
968
|
+
const green3 = "\x1B[32m";
|
|
969
|
+
const reset3 = "\x1B[0m";
|
|
916
970
|
console.log("No connectors found");
|
|
917
|
-
console.log(
|
|
971
|
+
console.log(`${green3} Create one with: ardent connector create postgresql <url>${reset3}`);
|
|
918
972
|
return;
|
|
919
973
|
}
|
|
920
974
|
const currentConnectorId = getConfig("currentConnectorId");
|
|
@@ -1064,6 +1118,9 @@ connectorCommand.command("create <type> [url]").description("Create a new connec
|
|
|
1064
1118
|
).option(
|
|
1065
1119
|
"--aws-region <region>",
|
|
1066
1120
|
"AWS region of the customer data plane (required with --deployment-model=customer-cloud)"
|
|
1121
|
+
).option(
|
|
1122
|
+
"--aws-cluster-name <name>",
|
|
1123
|
+
"EKS cluster name in the customer account where pgstream pods run (required with --deployment-model=customer-cloud)"
|
|
1067
1124
|
).action(createAction2);
|
|
1068
1125
|
connectorCommand.command("list").description("List your connectors").action(listAction2);
|
|
1069
1126
|
connectorCommand.command("switch <name>").description("Switch to a different connector").action(switchAction2);
|
|
@@ -1285,9 +1342,11 @@ async function createAction3(name) {
|
|
|
1285
1342
|
setCacheEntry("projects", cachedProjects);
|
|
1286
1343
|
setConfig("currentProjectId", project.id);
|
|
1287
1344
|
setConfig("currentProjectName", project.name);
|
|
1345
|
+
setConfig("currentConnectorId", void 0);
|
|
1346
|
+
setConfig("currentConnectorName", void 0);
|
|
1347
|
+
clearCurrentBranch();
|
|
1288
1348
|
trackEvent("CLI: project create succeeded");
|
|
1289
1349
|
console.log(`\u2713 Project '${name}' created`);
|
|
1290
|
-
console.log(` ID: ${project.id}`);
|
|
1291
1350
|
} catch (err) {
|
|
1292
1351
|
if (isNetworkError(err)) {
|
|
1293
1352
|
trackEvent("CLI: project create failed", { reason: "offline" });
|
|
@@ -1363,10 +1422,8 @@ async function listAction4() {
|
|
|
1363
1422
|
const isCurrent = project.id === currentProjectId;
|
|
1364
1423
|
if (isCurrent) {
|
|
1365
1424
|
console.log(`${green2}* ${project.name}${reset2}`);
|
|
1366
|
-
console.log(`${green2} ${project.id}${reset2}`);
|
|
1367
1425
|
} else {
|
|
1368
1426
|
console.log(` ${project.name}`);
|
|
1369
|
-
console.log(`${dim2} ${project.id}${reset2}`);
|
|
1370
1427
|
}
|
|
1371
1428
|
console.log();
|
|
1372
1429
|
}
|
|
@@ -1429,9 +1486,114 @@ async function switchAction3(name) {
|
|
|
1429
1486
|
} else {
|
|
1430
1487
|
console.log(`Switched to project '${name}'`);
|
|
1431
1488
|
}
|
|
1489
|
+
try {
|
|
1490
|
+
const result = await api.get(`/v1/cli/connectors?project_id=${project.id}`);
|
|
1491
|
+
if (!Array.isArray(result.connectors)) {
|
|
1492
|
+
throw new Error("API returned invalid response: missing connectors array");
|
|
1493
|
+
}
|
|
1494
|
+
const connectors = result.connectors;
|
|
1495
|
+
setCacheEntry("connectors", connectors);
|
|
1496
|
+
if (connectors.length === 1) {
|
|
1497
|
+
const connector = connectors[0];
|
|
1498
|
+
setConfig("currentConnectorId", connector.id);
|
|
1499
|
+
setConfig("currentConnectorName", connector.name);
|
|
1500
|
+
console.log("");
|
|
1501
|
+
console.log(` Auto-selected connector '${connector.name}'`);
|
|
1502
|
+
console.log("");
|
|
1503
|
+
} else if (connectors.length === 0) {
|
|
1504
|
+
const green2 = "\x1B[32m";
|
|
1505
|
+
const reset2 = "\x1B[0m";
|
|
1506
|
+
console.log("");
|
|
1507
|
+
console.log(" No connectors found.");
|
|
1508
|
+
console.log(`${green2} Create one with: ardent connector create postgresql <url>${reset2}`);
|
|
1509
|
+
console.log("");
|
|
1510
|
+
}
|
|
1511
|
+
} catch (err) {
|
|
1512
|
+
let reason;
|
|
1513
|
+
if (isNetworkError(err)) {
|
|
1514
|
+
reason = "offline";
|
|
1515
|
+
console.error(" \u26A0 Couldn't fetch connectors (offline). Run 'ardent connector list' when online.");
|
|
1516
|
+
} else if (isPermissionError(err)) {
|
|
1517
|
+
reason = "permission_denied";
|
|
1518
|
+
console.error(" \u26A0 No permission to list connectors in this project.");
|
|
1519
|
+
} else {
|
|
1520
|
+
reason = "api_error";
|
|
1521
|
+
console.error(" \u26A0 Couldn't fetch connectors:", err instanceof Error ? err.message : err);
|
|
1522
|
+
}
|
|
1523
|
+
trackEvent("CLI: project switch autoselect failed", { reason });
|
|
1524
|
+
}
|
|
1432
1525
|
trackEvent("CLI: project switch");
|
|
1433
1526
|
}
|
|
1434
1527
|
|
|
1528
|
+
// src/commands/project/delete.ts
|
|
1529
|
+
async function deleteAction4(name) {
|
|
1530
|
+
const user = getConfig("user");
|
|
1531
|
+
if (!user?.org_id) {
|
|
1532
|
+
console.error("\u2717 No organization found. Run: ardent login");
|
|
1533
|
+
process.exit(1);
|
|
1534
|
+
}
|
|
1535
|
+
const cached = getCacheEntry("projects");
|
|
1536
|
+
let project = cached?.data.find((p) => p.name === name);
|
|
1537
|
+
if (!project) {
|
|
1538
|
+
try {
|
|
1539
|
+
const result = await api.get(`/v1/projects?org_id=${user.org_id}`);
|
|
1540
|
+
if (!Array.isArray(result.projects)) {
|
|
1541
|
+
throw new Error("API returned invalid response: missing projects array");
|
|
1542
|
+
}
|
|
1543
|
+
project = result.projects.find((p) => p.name === name);
|
|
1544
|
+
} catch (err) {
|
|
1545
|
+
if (isNetworkError(err)) {
|
|
1546
|
+
console.error(`\u2717 Project "${name}" not found in cache (offline)`);
|
|
1547
|
+
console.error(" Run 'ardent project list' when online to refresh");
|
|
1548
|
+
process.exit(1);
|
|
1549
|
+
}
|
|
1550
|
+
console.error("\u2717 Failed:", err instanceof Error ? err.message : err);
|
|
1551
|
+
process.exit(1);
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
if (!project) {
|
|
1555
|
+
console.error(`\u2717 Project "${name}" not found`);
|
|
1556
|
+
console.error(" Run: ardent project list");
|
|
1557
|
+
process.exit(1);
|
|
1558
|
+
}
|
|
1559
|
+
const projectId = project.id;
|
|
1560
|
+
const projectName = project.name;
|
|
1561
|
+
try {
|
|
1562
|
+
console.log("Deleting project...");
|
|
1563
|
+
await api.delete(`/v1/projects/${projectId}`);
|
|
1564
|
+
const cachedAfter = getCacheEntry("projects");
|
|
1565
|
+
if (cachedAfter?.data) {
|
|
1566
|
+
const remaining = cachedAfter.data.filter((p) => p.id !== projectId);
|
|
1567
|
+
setCacheEntry("projects", remaining);
|
|
1568
|
+
}
|
|
1569
|
+
const currentId = getConfig("currentProjectId");
|
|
1570
|
+
if (currentId === projectId) {
|
|
1571
|
+
setConfig("currentProjectId", void 0);
|
|
1572
|
+
setConfig("currentProjectName", void 0);
|
|
1573
|
+
setConfig("currentConnectorId", void 0);
|
|
1574
|
+
setConfig("currentConnectorName", void 0);
|
|
1575
|
+
clearCurrentBranch();
|
|
1576
|
+
}
|
|
1577
|
+
trackEvent("CLI: project delete succeeded");
|
|
1578
|
+
console.log("\u2713 Project deleted");
|
|
1579
|
+
console.log(` Name: ${projectName}`);
|
|
1580
|
+
} catch (err) {
|
|
1581
|
+
if (isNetworkError(err)) {
|
|
1582
|
+
trackEvent("CLI: project delete failed", { reason: "offline" });
|
|
1583
|
+
console.error("\u2717 Cannot delete project while offline");
|
|
1584
|
+
process.exit(1);
|
|
1585
|
+
}
|
|
1586
|
+
if (isPermissionError(err)) {
|
|
1587
|
+
trackEvent("CLI: project delete failed", { reason: "permission_denied" });
|
|
1588
|
+
console.error("\u2717 You don't have permission to delete this project.");
|
|
1589
|
+
process.exit(1);
|
|
1590
|
+
}
|
|
1591
|
+
trackEvent("CLI: project delete failed", { reason: "api_error" });
|
|
1592
|
+
console.error("\u2717 Failed:", err instanceof Error ? err.message : err);
|
|
1593
|
+
process.exit(1);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1435
1597
|
// src/commands/project/index.ts
|
|
1436
1598
|
var projectCommand = new Command5("project").description(
|
|
1437
1599
|
"Manage projects"
|
|
@@ -1439,6 +1601,7 @@ var projectCommand = new Command5("project").description(
|
|
|
1439
1601
|
projectCommand.command("create <name>").description("Create a new project").action(createAction3);
|
|
1440
1602
|
projectCommand.command("list").description("List your projects").action(listAction4);
|
|
1441
1603
|
projectCommand.command("switch <name>").description("Switch to a different project").action(switchAction3);
|
|
1604
|
+
projectCommand.command("delete <name>").description("Delete a project by name").action(deleteAction4);
|
|
1442
1605
|
|
|
1443
1606
|
// src/commands/settings/index.ts
|
|
1444
1607
|
import { Command as Command6 } from "commander";
|
|
@@ -1609,26 +1772,82 @@ settingsCommand.command("remove <key>").description("Remove a setting. Keys: def
|
|
|
1609
1772
|
import { Command as Command7 } from "commander";
|
|
1610
1773
|
|
|
1611
1774
|
// src/commands/auth/login.ts
|
|
1775
|
+
function identifyAndTrack(userId) {
|
|
1776
|
+
const user = getConfig("user");
|
|
1777
|
+
const personProperties = {};
|
|
1778
|
+
if (user?.email) {
|
|
1779
|
+
personProperties.email = user.email;
|
|
1780
|
+
}
|
|
1781
|
+
if (user?.full_name) {
|
|
1782
|
+
personProperties.$name = user.full_name;
|
|
1783
|
+
}
|
|
1784
|
+
if (user?.org_name) {
|
|
1785
|
+
personProperties.org_name = user.org_name;
|
|
1786
|
+
}
|
|
1787
|
+
const resolvedUserId = userId || user?.user_id;
|
|
1788
|
+
if (resolvedUserId) {
|
|
1789
|
+
identifyUser(resolvedUserId, personProperties);
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
function printBootstrapFailureGuidance() {
|
|
1793
|
+
console.log("\n Couldn't load your projects. Try:");
|
|
1794
|
+
console.log(" ardent project list");
|
|
1795
|
+
}
|
|
1796
|
+
function printAutoSelection(bootstrap) {
|
|
1797
|
+
const { projects, connectors } = bootstrap;
|
|
1798
|
+
const green2 = "\x1B[32m";
|
|
1799
|
+
const reset2 = "\x1B[0m";
|
|
1800
|
+
if (projects.length === 0) {
|
|
1801
|
+
console.log(`
|
|
1802
|
+
${green2}No projects found. Create one:${reset2}`);
|
|
1803
|
+
console.log(`${green2} ardent project create <name>${reset2}`);
|
|
1804
|
+
return;
|
|
1805
|
+
}
|
|
1806
|
+
if (projects.length === 1) {
|
|
1807
|
+
console.log(` Auto-selected project '${projects[0].name}'`);
|
|
1808
|
+
} else {
|
|
1809
|
+
console.log(`
|
|
1810
|
+
${projects.length} projects found.`);
|
|
1811
|
+
console.log("");
|
|
1812
|
+
console.log(`${green2} Next step: select a project: ardent project switch <name>${reset2}`);
|
|
1813
|
+
console.log("");
|
|
1814
|
+
console.log(` List your projects: ardent project list`);
|
|
1815
|
+
console.log("");
|
|
1816
|
+
return;
|
|
1817
|
+
}
|
|
1818
|
+
if (connectors.length === 0) {
|
|
1819
|
+
console.log(`
|
|
1820
|
+
${green2}No connectors found. Create one:${reset2}`);
|
|
1821
|
+
console.log(`${green2} ardent connector create postgresql <url>${reset2}`);
|
|
1822
|
+
return;
|
|
1823
|
+
}
|
|
1824
|
+
if (connectors.length === 1) {
|
|
1825
|
+
console.log(` Auto-selected connector '${connectors[0].name}'`);
|
|
1826
|
+
console.log(`
|
|
1827
|
+
${green2}Ready to branch:${reset2}`);
|
|
1828
|
+
console.log(`${green2} ardent branch create <name>${reset2}`);
|
|
1829
|
+
} else {
|
|
1830
|
+
console.log(`
|
|
1831
|
+
${connectors.length} connectors found.`);
|
|
1832
|
+
console.log("");
|
|
1833
|
+
console.log(`${green2} Next step: select a connector: ardent connector switch <name>${reset2}`);
|
|
1834
|
+
console.log("");
|
|
1835
|
+
console.log(` List your connectors: ardent connector list`);
|
|
1836
|
+
console.log("");
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1612
1839
|
async function loginAction(options) {
|
|
1613
1840
|
if (options.token) {
|
|
1614
1841
|
setConfig("token", options.token);
|
|
1615
1842
|
console.log("\u2713 Logged in successfully");
|
|
1616
1843
|
trackEvent("CLI: login succeeded", { method: "token" });
|
|
1617
1844
|
try {
|
|
1618
|
-
await bootstrapCache();
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
const tokenPersonProperties = {};
|
|
1622
|
-
if (user.email) tokenPersonProperties.email = user.email;
|
|
1623
|
-
if (user.full_name) tokenPersonProperties.$name = user.full_name;
|
|
1624
|
-
if (user.org_name) tokenPersonProperties.org_name = user.org_name;
|
|
1625
|
-
if (user.user_id) {
|
|
1626
|
-
identifyUser(user.user_id, tokenPersonProperties);
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1845
|
+
const bootstrap = await bootstrapCache();
|
|
1846
|
+
identifyAndTrack(null);
|
|
1847
|
+
printAutoSelection(bootstrap);
|
|
1629
1848
|
} catch {
|
|
1849
|
+
printBootstrapFailureGuidance();
|
|
1630
1850
|
}
|
|
1631
|
-
showNextStep();
|
|
1632
1851
|
return;
|
|
1633
1852
|
}
|
|
1634
1853
|
console.log("Opening browser for authentication...");
|
|
@@ -1660,34 +1879,28 @@ async function loginAction(options) {
|
|
|
1660
1879
|
console.error("\u2717 Poll failed");
|
|
1661
1880
|
process.exit(1);
|
|
1662
1881
|
}
|
|
1663
|
-
const
|
|
1664
|
-
if (
|
|
1665
|
-
setConfig("token",
|
|
1882
|
+
const pollResult = await pollResponse.json();
|
|
1883
|
+
if (pollResult.status === "completed") {
|
|
1884
|
+
setConfig("token", pollResult.token);
|
|
1666
1885
|
console.log("\n\u2713 Logged in successfully");
|
|
1667
1886
|
trackEvent("CLI: login succeeded", { method: "browser" });
|
|
1668
1887
|
try {
|
|
1669
|
-
await bootstrapCache();
|
|
1888
|
+
const bootstrap = await bootstrapCache();
|
|
1889
|
+
identifyAndTrack(pollResult.user_id);
|
|
1890
|
+
printAutoSelection(bootstrap);
|
|
1670
1891
|
} catch {
|
|
1892
|
+
printBootstrapFailureGuidance();
|
|
1671
1893
|
}
|
|
1672
|
-
const user = getConfig("user");
|
|
1673
|
-
const personProperties = {};
|
|
1674
|
-
if (user?.email) personProperties.email = user.email;
|
|
1675
|
-
if (user?.full_name) personProperties.$name = user.full_name;
|
|
1676
|
-
if (user?.org_name) personProperties.org_name = user.org_name;
|
|
1677
|
-
if (result.user_id) {
|
|
1678
|
-
identifyUser(result.user_id, personProperties);
|
|
1679
|
-
}
|
|
1680
|
-
showNextStep();
|
|
1681
1894
|
return;
|
|
1682
1895
|
}
|
|
1683
|
-
if (
|
|
1896
|
+
if (pollResult.status === "expired") {
|
|
1684
1897
|
trackEvent("CLI: login failed", { method: "browser", reason: "expired" });
|
|
1685
1898
|
console.error("\n\u2717 Session expired. Please try again.");
|
|
1686
1899
|
process.exit(1);
|
|
1687
1900
|
}
|
|
1688
|
-
if (
|
|
1901
|
+
if (pollResult.status === "error") {
|
|
1689
1902
|
trackEvent("CLI: login failed", { method: "browser", reason: "error" });
|
|
1690
|
-
console.error("\n\u2717 Error:",
|
|
1903
|
+
console.error("\n\u2717 Error:", pollResult.message);
|
|
1691
1904
|
process.exit(1);
|
|
1692
1905
|
}
|
|
1693
1906
|
process.stdout.write(".");
|
|
@@ -1830,6 +2043,7 @@ PROJECTS
|
|
|
1830
2043
|
project create Create a new project
|
|
1831
2044
|
project list List your projects (* = current)
|
|
1832
2045
|
project switch Switch to a different project
|
|
2046
|
+
project delete Delete a project by name
|
|
1833
2047
|
|
|
1834
2048
|
CONNECTORS
|
|
1835
2049
|
connector create Connect a database (postgresql, snowflake, etc.)
|