ardent-cli 0.0.25 → 0.0.27
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 -76
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -27,7 +27,11 @@ function formatUpgradeRequiredMessage(text) {
|
|
|
27
27
|
try {
|
|
28
28
|
const json = JSON.parse(text);
|
|
29
29
|
if (json.detail) {
|
|
30
|
-
|
|
30
|
+
const detail = formatErrorDetail(json.detail);
|
|
31
|
+
if (detail.includes("npm install -g ardent-cli@latest")) {
|
|
32
|
+
return detail;
|
|
33
|
+
}
|
|
34
|
+
return `${detail}
|
|
31
35
|
|
|
32
36
|
npm install -g ardent-cli@latest`;
|
|
33
37
|
}
|
|
@@ -753,29 +757,125 @@ import { Command as Command2 } from "commander";
|
|
|
753
757
|
var SUCCESS_ENGINE_STATUSES = /* @__PURE__ */ new Set(["healthy", "degraded"]);
|
|
754
758
|
var RETRYABLE_ENGINE_STATUSES = /* @__PURE__ */ new Set(["configuration_verified"]);
|
|
755
759
|
var FAILED_ENGINE_STATUSES = /* @__PURE__ */ new Set(["configuration_failed", "failed_validation"]);
|
|
756
|
-
|
|
760
|
+
var EngineSetupTerminalStatusError = class extends Error {
|
|
761
|
+
kind;
|
|
762
|
+
engineStatus;
|
|
763
|
+
constructor(kind, engineStatus, message) {
|
|
764
|
+
super(message);
|
|
765
|
+
this.name = "EngineSetupTerminalStatusError";
|
|
766
|
+
this.kind = kind;
|
|
767
|
+
this.engineStatus = engineStatus;
|
|
768
|
+
}
|
|
769
|
+
};
|
|
770
|
+
function assertEngineSetupCompleted(operation, connectorName) {
|
|
757
771
|
const result = operation.result;
|
|
758
772
|
if (!result) {
|
|
759
|
-
throw new
|
|
773
|
+
throw new EngineSetupTerminalStatusError(
|
|
774
|
+
"malformed_result",
|
|
775
|
+
null,
|
|
776
|
+
"Engine setup completed without a result payload."
|
|
777
|
+
);
|
|
760
778
|
}
|
|
761
779
|
const engineStatus = result.branching_engine_status;
|
|
762
780
|
if (typeof engineStatus !== "string" || engineStatus.length === 0) {
|
|
763
|
-
throw new
|
|
781
|
+
throw new EngineSetupTerminalStatusError(
|
|
782
|
+
"malformed_result",
|
|
783
|
+
null,
|
|
784
|
+
"Engine setup completed without branching_engine_status in the result."
|
|
785
|
+
);
|
|
764
786
|
}
|
|
765
787
|
if (SUCCESS_ENGINE_STATUSES.has(engineStatus)) {
|
|
766
788
|
return;
|
|
767
789
|
}
|
|
768
790
|
if (RETRYABLE_ENGINE_STATUSES.has(engineStatus)) {
|
|
769
|
-
throw new
|
|
770
|
-
|
|
791
|
+
throw new EngineSetupTerminalStatusError(
|
|
792
|
+
"retryable_engine_status",
|
|
793
|
+
engineStatus,
|
|
794
|
+
`Engine setup needs retry (status: ${engineStatus}). Run \`ardent connector retry-setup ${connectorName}\` to retry, or \`ardent connector list\` to inspect connector state first.`
|
|
771
795
|
);
|
|
772
796
|
}
|
|
773
797
|
if (FAILED_ENGINE_STATUSES.has(engineStatus)) {
|
|
774
|
-
throw new
|
|
798
|
+
throw new EngineSetupTerminalStatusError(
|
|
799
|
+
"failed_engine_status",
|
|
800
|
+
engineStatus,
|
|
775
801
|
`Engine setup failed (status: ${engineStatus}). Run \`ardent connector list\` to inspect connector state.`
|
|
776
802
|
);
|
|
777
803
|
}
|
|
778
|
-
throw new
|
|
804
|
+
throw new EngineSetupTerminalStatusError(
|
|
805
|
+
"unexpected_engine_status",
|
|
806
|
+
engineStatus,
|
|
807
|
+
`Engine setup completed with unexpected status: ${engineStatus}.`
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// src/lib/engine_setup.ts
|
|
812
|
+
var EngineSetupTimeoutError = class extends Error {
|
|
813
|
+
constructor(message) {
|
|
814
|
+
super(message);
|
|
815
|
+
this.name = "EngineSetupTimeoutError";
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
var EngineSetupOperationFailedError = class extends Error {
|
|
819
|
+
operationError;
|
|
820
|
+
constructor(operationError, connectorName) {
|
|
821
|
+
super(
|
|
822
|
+
`Engine setup failed: ${operationError ?? "unknown error"}. Inspect connector state with \`ardent connector list\`, then retry with \`ardent connector retry-setup ${connectorName}\` once the underlying issue is resolved.`
|
|
823
|
+
);
|
|
824
|
+
this.name = "EngineSetupOperationFailedError";
|
|
825
|
+
this.operationError = operationError;
|
|
826
|
+
}
|
|
827
|
+
};
|
|
828
|
+
async function runEngineSetupWithPolling(connectorId, connectorName) {
|
|
829
|
+
let dispatch;
|
|
830
|
+
try {
|
|
831
|
+
dispatch = await api.post(
|
|
832
|
+
`/v1/connectors/${connectorId}/engine-setup`,
|
|
833
|
+
{}
|
|
834
|
+
);
|
|
835
|
+
} catch (err) {
|
|
836
|
+
if (isGatewayTimeoutError(err)) {
|
|
837
|
+
throw new Error(
|
|
838
|
+
"Backend dispatch timed out. The engine-setup endpoint is now async and should respond in under a second; this may indicate a backend incident. Try again, or check `ardent connector list` to see if an operation was created anyway."
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
throw err;
|
|
842
|
+
}
|
|
843
|
+
const operationId = dispatch?.operation_id;
|
|
844
|
+
if (!operationId) {
|
|
845
|
+
return { dispatched: false };
|
|
846
|
+
}
|
|
847
|
+
const startedAt = Date.now();
|
|
848
|
+
const maxWaitMs = 20 * 60 * 1e3;
|
|
849
|
+
const pollIntervalMs = 5 * 1e3;
|
|
850
|
+
let lastStage = null;
|
|
851
|
+
while (Date.now() - startedAt < maxWaitMs) {
|
|
852
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
853
|
+
let op;
|
|
854
|
+
try {
|
|
855
|
+
op = await api.get(`/v1/operations/${operationId}`);
|
|
856
|
+
} catch (pollErr) {
|
|
857
|
+
if (isGatewayTimeoutError(pollErr)) continue;
|
|
858
|
+
throw pollErr;
|
|
859
|
+
}
|
|
860
|
+
if (op.stage && op.stage !== lastStage) {
|
|
861
|
+
const progressLabel = op.progress != null ? ` (${op.progress}%)` : "";
|
|
862
|
+
console.log(` ${op.stage}${progressLabel}`);
|
|
863
|
+
lastStage = op.stage;
|
|
864
|
+
}
|
|
865
|
+
if (op.status === "completed") {
|
|
866
|
+
assertEngineSetupCompleted(
|
|
867
|
+
{ status: op.status, result: op.result },
|
|
868
|
+
connectorName
|
|
869
|
+
);
|
|
870
|
+
return { dispatched: true };
|
|
871
|
+
}
|
|
872
|
+
if (op.status === "failed") {
|
|
873
|
+
throw new EngineSetupOperationFailedError(op.error, connectorName);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
throw new EngineSetupTimeoutError(
|
|
877
|
+
`Engine setup did not complete within ${maxWaitMs / 6e4} minutes. Setup may still be running server-side \u2014 do NOT delete the connector. Check status with: ardent connector list (operation ${operationId})`
|
|
878
|
+
);
|
|
779
879
|
}
|
|
780
880
|
|
|
781
881
|
// src/lib/onboarding.ts
|
|
@@ -888,63 +988,6 @@ Example:
|
|
|
888
988
|
}
|
|
889
989
|
|
|
890
990
|
// src/commands/connector/create.ts
|
|
891
|
-
var EngineSetupTimeoutError = class extends Error {
|
|
892
|
-
constructor(message) {
|
|
893
|
-
super(message);
|
|
894
|
-
this.name = "EngineSetupTimeoutError";
|
|
895
|
-
}
|
|
896
|
-
};
|
|
897
|
-
async function runEngineSetupWithPolling(connectorId) {
|
|
898
|
-
let dispatch;
|
|
899
|
-
try {
|
|
900
|
-
dispatch = await api.post(
|
|
901
|
-
`/v1/connectors/${connectorId}/engine-setup`,
|
|
902
|
-
{}
|
|
903
|
-
);
|
|
904
|
-
} catch (err) {
|
|
905
|
-
if (isGatewayTimeoutError(err)) {
|
|
906
|
-
throw new Error(
|
|
907
|
-
"Backend dispatch timed out. The engine-setup endpoint is now async and should respond in under a second; this may indicate a backend incident. Try again, or check `ardent connector list` to see if an operation was created anyway."
|
|
908
|
-
);
|
|
909
|
-
}
|
|
910
|
-
throw err;
|
|
911
|
-
}
|
|
912
|
-
const operationId = dispatch?.operation_id;
|
|
913
|
-
if (!operationId) {
|
|
914
|
-
return;
|
|
915
|
-
}
|
|
916
|
-
const startedAt = Date.now();
|
|
917
|
-
const maxWaitMs = 20 * 60 * 1e3;
|
|
918
|
-
const pollIntervalMs = 5 * 1e3;
|
|
919
|
-
let lastStage = null;
|
|
920
|
-
while (Date.now() - startedAt < maxWaitMs) {
|
|
921
|
-
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
922
|
-
let op;
|
|
923
|
-
try {
|
|
924
|
-
op = await api.get(`/v1/operations/${operationId}`);
|
|
925
|
-
} catch (pollErr) {
|
|
926
|
-
if (isGatewayTimeoutError(pollErr)) continue;
|
|
927
|
-
throw pollErr;
|
|
928
|
-
}
|
|
929
|
-
if (op.stage && op.stage !== lastStage) {
|
|
930
|
-
const progressLabel = op.progress != null ? ` (${op.progress}%)` : "";
|
|
931
|
-
console.log(` ${op.stage}${progressLabel}`);
|
|
932
|
-
lastStage = op.stage;
|
|
933
|
-
}
|
|
934
|
-
if (op.status === "completed") {
|
|
935
|
-
assertEngineSetupCompleted({ status: op.status, result: op.result });
|
|
936
|
-
return;
|
|
937
|
-
}
|
|
938
|
-
if (op.status === "failed") {
|
|
939
|
-
throw new Error(
|
|
940
|
-
`Engine setup failed: ${op.error ?? "unknown error"}. Run \`ardent connector list\` to inspect connector state, or re-trigger setup once the underlying issue is resolved.`
|
|
941
|
-
);
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
throw new EngineSetupTimeoutError(
|
|
945
|
-
`Engine setup did not complete within ${maxWaitMs / 6e4} minutes. Setup may still be running server-side \u2014 do NOT delete the connector. Check status with: ardent connector list (operation ${operationId})`
|
|
946
|
-
);
|
|
947
|
-
}
|
|
948
991
|
function parsePostgresUrl(url) {
|
|
949
992
|
const atIndex = url.lastIndexOf("@");
|
|
950
993
|
const credentialsPart = atIndex > 0 ? url.substring(0, atIndex) : url;
|
|
@@ -959,6 +1002,11 @@ function parsePostgresUrl(url) {
|
|
|
959
1002
|
if (!username) throw new Error("Username required in connection URL");
|
|
960
1003
|
return { host, port, username, password };
|
|
961
1004
|
}
|
|
1005
|
+
function printEngineSetupRecoveryHint(connectorName) {
|
|
1006
|
+
console.error("\u2717 Engine setup did not complete for this connector.");
|
|
1007
|
+
console.error(" Inspect: ardent connector list");
|
|
1008
|
+
console.error(` Retry: ardent connector retry-setup ${connectorName}`);
|
|
1009
|
+
}
|
|
962
1010
|
async function createAction2(type, url, options) {
|
|
963
1011
|
const supportedTypes = ["postgresql"];
|
|
964
1012
|
if (!supportedTypes.includes(type.toLowerCase())) {
|
|
@@ -1069,11 +1117,10 @@ async function createAction2(type, url, options) {
|
|
|
1069
1117
|
if (isByoc) {
|
|
1070
1118
|
console.log("Setting up branching engine...");
|
|
1071
1119
|
try {
|
|
1072
|
-
await runEngineSetupWithPolling(connectorId);
|
|
1120
|
+
await runEngineSetupWithPolling(connectorId, connectorName);
|
|
1073
1121
|
} catch (setupErr) {
|
|
1074
1122
|
if (!(setupErr instanceof EngineSetupTimeoutError)) {
|
|
1075
|
-
|
|
1076
|
-
console.error(` ardent connector delete ${connectorName}`);
|
|
1123
|
+
printEngineSetupRecoveryHint(connectorName);
|
|
1077
1124
|
}
|
|
1078
1125
|
throw setupErr;
|
|
1079
1126
|
}
|
|
@@ -1100,7 +1147,14 @@ async function createAction2(type, url, options) {
|
|
|
1100
1147
|
const connector = await api.get(`/v1/connectors/${connectorId}`);
|
|
1101
1148
|
if (connector.branching_engine_status === "configuration_verified") {
|
|
1102
1149
|
console.log("Setting up branching engine...");
|
|
1103
|
-
|
|
1150
|
+
try {
|
|
1151
|
+
await runEngineSetupWithPolling(connectorId, connectorName);
|
|
1152
|
+
} catch (setupErr) {
|
|
1153
|
+
if (!(setupErr instanceof EngineSetupTimeoutError)) {
|
|
1154
|
+
printEngineSetupRecoveryHint(connectorName);
|
|
1155
|
+
}
|
|
1156
|
+
throw setupErr;
|
|
1157
|
+
}
|
|
1104
1158
|
}
|
|
1105
1159
|
}
|
|
1106
1160
|
const finalConnector = await api.get(`/v1/connectors/${connectorId}`);
|
|
@@ -1108,7 +1162,9 @@ async function createAction2(type, url, options) {
|
|
|
1108
1162
|
id: connectorId,
|
|
1109
1163
|
name: connectorName,
|
|
1110
1164
|
service_name: "postgresql",
|
|
1111
|
-
status: finalConnector.branching_engine_status ?? finalConnector.connection_status ?? "pending"
|
|
1165
|
+
status: finalConnector.branching_engine_status ?? finalConnector.connection_status ?? "pending",
|
|
1166
|
+
branching_engine_status: finalConnector.branching_engine_status ?? null,
|
|
1167
|
+
connection_error: finalConnector.connection_error ?? null
|
|
1112
1168
|
};
|
|
1113
1169
|
const cached = getCacheEntry("connectors");
|
|
1114
1170
|
const cachedConnectors = cached?.data || [];
|
|
@@ -1140,6 +1196,34 @@ async function createAction2(type, url, options) {
|
|
|
1140
1196
|
}
|
|
1141
1197
|
}
|
|
1142
1198
|
|
|
1199
|
+
// src/lib/connector_render.ts
|
|
1200
|
+
var GREEN = "\x1B[32m";
|
|
1201
|
+
var CYAN = "\x1B[36m";
|
|
1202
|
+
var RED = "\x1B[31m";
|
|
1203
|
+
function pendingHint(state, connectorName) {
|
|
1204
|
+
if (state === "validating") {
|
|
1205
|
+
return `engine setup running \u2014 re-run \`ardent connector list\` to refresh, or \`ardent connector retry-setup ${connectorName}\` if it stays this way`;
|
|
1206
|
+
}
|
|
1207
|
+
return `engine setup not finished \u2014 run: ardent connector retry-setup ${connectorName}`;
|
|
1208
|
+
}
|
|
1209
|
+
var ENGINE_PENDING_STATES = /* @__PURE__ */ new Set(["configuration_verified", "validating"]);
|
|
1210
|
+
function renderConnectorIcon(connector) {
|
|
1211
|
+
const engine = connector.branching_engine_status;
|
|
1212
|
+
const statusAllowsEnginePending = connector.status === "healthy" || ENGINE_PENDING_STATES.has(connector.status);
|
|
1213
|
+
if (engine && ENGINE_PENDING_STATES.has(engine) && statusAllowsEnginePending) {
|
|
1214
|
+
return {
|
|
1215
|
+
kind: "engine_pending",
|
|
1216
|
+
icon: "\u25D0",
|
|
1217
|
+
color: CYAN,
|
|
1218
|
+
hint: pendingHint(engine, connector.name)
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
if (connector.status === "healthy") {
|
|
1222
|
+
return { kind: "ready", icon: "\u25CF", color: GREEN };
|
|
1223
|
+
}
|
|
1224
|
+
return { kind: "broken", icon: "\u25CB", color: RED };
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1143
1227
|
// src/commands/connector/list.ts
|
|
1144
1228
|
async function listAction2() {
|
|
1145
1229
|
let connectors = [];
|
|
@@ -1194,23 +1278,28 @@ async function listAction2() {
|
|
|
1194
1278
|
const green2 = "\x1B[32m";
|
|
1195
1279
|
const dim2 = "\x1B[2m";
|
|
1196
1280
|
const yellow = "\x1B[33m";
|
|
1197
|
-
const reset2 = "\x1B[0m";
|
|
1198
1281
|
const red = "\x1B[31m";
|
|
1282
|
+
const reset2 = "\x1B[0m";
|
|
1199
1283
|
console.log("Connectors:\n");
|
|
1284
|
+
let enginePendingCount = 0;
|
|
1200
1285
|
for (const connector of connectors) {
|
|
1201
1286
|
const isCurrent = connector.id === currentConnectorId;
|
|
1202
|
-
const
|
|
1287
|
+
const render = renderConnectorIcon(connector);
|
|
1288
|
+
if (render.kind === "engine_pending") enginePendingCount += 1;
|
|
1203
1289
|
const warnings = connector.warnings ?? [];
|
|
1204
1290
|
const warningSuffix = warnings.length > 0 ? ` ${yellow}\u26A0 ${warnings.length}${reset2}` : "";
|
|
1205
|
-
const statusSuffix =
|
|
1291
|
+
const statusSuffix = render.kind === "ready" ? "" : ` ${render.color}[${connector.status}]${reset2}`;
|
|
1292
|
+
const nameLine = isCurrent ? `${green2}* ${render.color}${render.icon}${green2} ${connector.name}${reset2}${warningSuffix}${statusSuffix}` : ` ${render.color}${render.icon}${reset2} ${connector.name}${warningSuffix}${statusSuffix}`;
|
|
1293
|
+
console.log(nameLine);
|
|
1206
1294
|
if (isCurrent) {
|
|
1207
|
-
console.log(`${green2}* ${icon} ${connector.name}${reset2}${warningSuffix}${statusSuffix}`);
|
|
1208
1295
|
console.log(`${green2} ${connector.service_name}${reset2}`);
|
|
1209
1296
|
} else {
|
|
1210
|
-
console.log(` ${icon} ${connector.name}${warningSuffix}${statusSuffix}`);
|
|
1211
1297
|
console.log(`${dim2} ${connector.service_name}${reset2}`);
|
|
1212
1298
|
}
|
|
1213
|
-
if (
|
|
1299
|
+
if (render.kind === "engine_pending") {
|
|
1300
|
+
console.log(`${render.color} ${render.hint}${reset2}`);
|
|
1301
|
+
}
|
|
1302
|
+
if (render.kind === "broken" && connector.connection_error) {
|
|
1214
1303
|
for (const line of connector.connection_error.split("\n")) {
|
|
1215
1304
|
if (line.trim().length === 0) continue;
|
|
1216
1305
|
console.log(`${red} ${line}${reset2}`);
|
|
@@ -1221,6 +1310,12 @@ async function listAction2() {
|
|
|
1221
1310
|
}
|
|
1222
1311
|
console.log();
|
|
1223
1312
|
}
|
|
1313
|
+
if (enginePendingCount > 0) {
|
|
1314
|
+
trackEvent("CLI: connector list rendered engine-pending", {
|
|
1315
|
+
engine_pending_count: enginePendingCount,
|
|
1316
|
+
connector_count: connectors.length
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1224
1319
|
}
|
|
1225
1320
|
|
|
1226
1321
|
// src/commands/connector/delete.ts
|
|
@@ -1278,6 +1373,106 @@ async function deleteAction2(name) {
|
|
|
1278
1373
|
}
|
|
1279
1374
|
}
|
|
1280
1375
|
|
|
1376
|
+
// src/commands/connector/retry-setup.ts
|
|
1377
|
+
function connectorRetrySetupFailureTelemetry(err) {
|
|
1378
|
+
if (isPermissionError(err)) {
|
|
1379
|
+
return { reason: "permission_denied" };
|
|
1380
|
+
}
|
|
1381
|
+
if (err instanceof EngineSetupTimeoutError) {
|
|
1382
|
+
return { reason: "polling_timeout" };
|
|
1383
|
+
}
|
|
1384
|
+
if (err instanceof EngineSetupOperationFailedError) {
|
|
1385
|
+
return {
|
|
1386
|
+
reason: "operation_failed",
|
|
1387
|
+
operation_error: err.operationError ?? "unknown error"
|
|
1388
|
+
};
|
|
1389
|
+
}
|
|
1390
|
+
if (err instanceof EngineSetupTerminalStatusError) {
|
|
1391
|
+
return {
|
|
1392
|
+
reason: err.kind,
|
|
1393
|
+
engine_status: err.engineStatus
|
|
1394
|
+
};
|
|
1395
|
+
}
|
|
1396
|
+
return { reason: "api_error" };
|
|
1397
|
+
}
|
|
1398
|
+
async function retrySetupAction(name) {
|
|
1399
|
+
const currentProjectId = getConfig("currentProjectId");
|
|
1400
|
+
if (!currentProjectId) {
|
|
1401
|
+
console.error("\u2717 No current project set. Switch to a project first:");
|
|
1402
|
+
console.error(" ardent project list");
|
|
1403
|
+
console.error(" ardent project switch <name>");
|
|
1404
|
+
process.exit(1);
|
|
1405
|
+
}
|
|
1406
|
+
let connector;
|
|
1407
|
+
try {
|
|
1408
|
+
const result = await api.get(
|
|
1409
|
+
`/v1/cli/connectors?project_id=${currentProjectId}`
|
|
1410
|
+
);
|
|
1411
|
+
if (!result.connectors) {
|
|
1412
|
+
throw new Error("API returned invalid response: missing connectors array");
|
|
1413
|
+
}
|
|
1414
|
+
setCacheEntry("connectors", result.connectors);
|
|
1415
|
+
connector = result.connectors.find((candidate) => candidate.name === name);
|
|
1416
|
+
} catch (err) {
|
|
1417
|
+
if (isNetworkError(err)) {
|
|
1418
|
+
console.error("\u2717 Cannot run connector retry-setup while offline");
|
|
1419
|
+
process.exit(1);
|
|
1420
|
+
}
|
|
1421
|
+
throw err;
|
|
1422
|
+
}
|
|
1423
|
+
if (!connector) {
|
|
1424
|
+
console.error(`\u2717 Connector "${name}" not found`);
|
|
1425
|
+
console.log(" Run: ardent connector list");
|
|
1426
|
+
process.exit(1);
|
|
1427
|
+
}
|
|
1428
|
+
trackEvent("CLI: connector retry-setup initiated", {
|
|
1429
|
+
connector_id: connector.id,
|
|
1430
|
+
starting_engine_status: connector.branching_engine_status ?? null
|
|
1431
|
+
});
|
|
1432
|
+
console.log(`Setting up branching engine for ${name}...`);
|
|
1433
|
+
try {
|
|
1434
|
+
const { dispatched } = await runEngineSetupWithPolling(connector.id, name);
|
|
1435
|
+
if (dispatched) {
|
|
1436
|
+
trackEvent("CLI: connector retry-setup dispatched", {
|
|
1437
|
+
connector_id: connector.id
|
|
1438
|
+
});
|
|
1439
|
+
}
|
|
1440
|
+
trackEvent("CLI: connector retry-setup succeeded", {
|
|
1441
|
+
connector_id: connector.id,
|
|
1442
|
+
dispatched
|
|
1443
|
+
});
|
|
1444
|
+
try {
|
|
1445
|
+
const refreshed = await api.get(
|
|
1446
|
+
`/v1/cli/connectors?project_id=${currentProjectId}`
|
|
1447
|
+
);
|
|
1448
|
+
if (refreshed.connectors) {
|
|
1449
|
+
setCacheEntry("connectors", refreshed.connectors);
|
|
1450
|
+
}
|
|
1451
|
+
} catch {
|
|
1452
|
+
}
|
|
1453
|
+
if (!dispatched) {
|
|
1454
|
+
console.log("\u2713 Engine already set up \u2014 no work needed");
|
|
1455
|
+
} else {
|
|
1456
|
+
console.log("\u2713 Engine setup complete");
|
|
1457
|
+
}
|
|
1458
|
+
} catch (err) {
|
|
1459
|
+
const failureTelemetry = connectorRetrySetupFailureTelemetry(err);
|
|
1460
|
+
if (isPermissionError(err)) {
|
|
1461
|
+
trackEvent("CLI: connector retry-setup failed", failureTelemetry);
|
|
1462
|
+
console.error("\u2717 You don't have permission to run engine setup on this connector.");
|
|
1463
|
+
process.exit(1);
|
|
1464
|
+
}
|
|
1465
|
+
if (err instanceof EngineSetupTimeoutError) {
|
|
1466
|
+
trackEvent("CLI: connector retry-setup failed", failureTelemetry);
|
|
1467
|
+
console.error(`\u2717 ${err.message}`);
|
|
1468
|
+
process.exit(1);
|
|
1469
|
+
}
|
|
1470
|
+
trackEvent("CLI: connector retry-setup failed", failureTelemetry);
|
|
1471
|
+
console.error("\u2717 Failed:", err instanceof Error ? err.message : err);
|
|
1472
|
+
process.exit(1);
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1281
1476
|
// src/commands/connector/switch.ts
|
|
1282
1477
|
async function switchAction2(name) {
|
|
1283
1478
|
const cached = getCacheEntry("connectors");
|
|
@@ -1351,6 +1546,9 @@ connectorCommand.command("create <type> [url]").description("Create a new connec
|
|
|
1351
1546
|
).action(createAction2);
|
|
1352
1547
|
connectorCommand.command("list").description("List your connectors").action(listAction2);
|
|
1353
1548
|
connectorCommand.command("switch <name>").description("Switch to a different connector").action(switchAction2);
|
|
1549
|
+
connectorCommand.command("retry-setup <name>").description(
|
|
1550
|
+
"Retry branching engine setup for a connector that didn't finish (status: configuration_verified or validating)"
|
|
1551
|
+
).action(retrySetupAction);
|
|
1354
1552
|
connectorCommand.command("delete <name>").description("Delete a connector by name").action(deleteAction2);
|
|
1355
1553
|
|
|
1356
1554
|
// src/commands/invite/index.ts
|
|
@@ -2279,6 +2477,7 @@ CONNECTORS
|
|
|
2279
2477
|
connector create Connect a database (postgresql, snowflake, etc.)
|
|
2280
2478
|
connector list List your connectors (* = current)
|
|
2281
2479
|
connector switch Switch to a different connector
|
|
2480
|
+
connector retry-setup Retry branching engine setup for a connector
|
|
2282
2481
|
connector delete Delete a connector
|
|
2283
2482
|
|
|
2284
2483
|
BRANCHES
|