ardent-cli 0.0.45 → 0.0.46
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 +150 -24
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1911,12 +1911,85 @@ async function handleReplicaIdentityPreflight(connectorId, options, behavior = {
|
|
|
1911
1911
|
return { submitted: true, preflight: refreshed };
|
|
1912
1912
|
}
|
|
1913
1913
|
|
|
1914
|
+
// src/lib/connector_name.ts
|
|
1915
|
+
var SUFFIX_RESERVE = 5;
|
|
1916
|
+
var MAX_BASE_LENGTH = MAX_RESOURCE_NAME_LENGTH - SUFFIX_RESERVE;
|
|
1917
|
+
var MAX_COLLISION_SUFFIX = 1e3;
|
|
1918
|
+
function slugifyToResourceName(input) {
|
|
1919
|
+
const slug = input.normalize("NFKD").replace(new RegExp("\\p{Mn}", "gu"), "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, MAX_BASE_LENGTH).replace(/-+$/g, "");
|
|
1920
|
+
if (slug.length === 0) {
|
|
1921
|
+
return null;
|
|
1922
|
+
}
|
|
1923
|
+
try {
|
|
1924
|
+
validateResourceName(slug);
|
|
1925
|
+
} catch {
|
|
1926
|
+
return null;
|
|
1927
|
+
}
|
|
1928
|
+
return slug;
|
|
1929
|
+
}
|
|
1930
|
+
function deriveConnectorName(options) {
|
|
1931
|
+
let base = null;
|
|
1932
|
+
for (const source of options.sources) {
|
|
1933
|
+
if (!source) {
|
|
1934
|
+
continue;
|
|
1935
|
+
}
|
|
1936
|
+
const candidate = slugifyToResourceName(source);
|
|
1937
|
+
if (candidate) {
|
|
1938
|
+
base = candidate;
|
|
1939
|
+
break;
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
if (base === null) {
|
|
1943
|
+
base = slugifyToResourceName(options.fallbackBase);
|
|
1944
|
+
}
|
|
1945
|
+
if (base === null) {
|
|
1946
|
+
throw new Error(
|
|
1947
|
+
`Could not derive a connector name: fallback base '${options.fallbackBase}' is not a valid resource name`
|
|
1948
|
+
);
|
|
1949
|
+
}
|
|
1950
|
+
const taken = new Set(options.existingNames);
|
|
1951
|
+
if (!taken.has(base)) {
|
|
1952
|
+
return base;
|
|
1953
|
+
}
|
|
1954
|
+
for (let suffix = 2; suffix <= MAX_COLLISION_SUFFIX; suffix++) {
|
|
1955
|
+
const candidate = `${base}-${suffix}`;
|
|
1956
|
+
if (!taken.has(candidate)) {
|
|
1957
|
+
return candidate;
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
throw new Error(
|
|
1961
|
+
`Could not derive a unique connector name from base '${base}' after ${MAX_COLLISION_SUFFIX} attempts; pass --name explicitly`
|
|
1962
|
+
);
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1914
1965
|
// src/commands/connector/create.ts
|
|
1915
1966
|
function printEngineSetupRecoveryHint(connectorName) {
|
|
1916
1967
|
console.error("\u2717 Engine setup did not complete for this connector.");
|
|
1917
1968
|
console.error(" Inspect: ardent connector list");
|
|
1918
1969
|
console.error(` Retry: ardent connector retry-setup ${connectorName}`);
|
|
1919
1970
|
}
|
|
1971
|
+
async function deriveDefaultConnectorName(input) {
|
|
1972
|
+
let existingNames;
|
|
1973
|
+
try {
|
|
1974
|
+
const existing = await api.get(
|
|
1975
|
+
`/v1/cli/connectors?project_id=${input.projectId}`
|
|
1976
|
+
);
|
|
1977
|
+
existingNames = existing.connectors.map((connector) => connector.name);
|
|
1978
|
+
} catch (listErr) {
|
|
1979
|
+
if (isPermissionError(listErr)) {
|
|
1980
|
+
throw listErr;
|
|
1981
|
+
}
|
|
1982
|
+
const detail = listErr instanceof Error ? listErr.message : String(listErr);
|
|
1983
|
+
throw new Error(
|
|
1984
|
+
`Could not look up existing connectors to choose a default name (${detail}). Re-run with --name <name>.`
|
|
1985
|
+
);
|
|
1986
|
+
}
|
|
1987
|
+
return deriveConnectorName({
|
|
1988
|
+
sources: [input.projectName, input.sourceDatabase, input.sourceHost],
|
|
1989
|
+
existingNames,
|
|
1990
|
+
fallbackBase: input.serviceType
|
|
1991
|
+
});
|
|
1992
|
+
}
|
|
1920
1993
|
async function promptForUnsupportedExtensions(connectorId, unsupported, alreadyPersisted) {
|
|
1921
1994
|
function mergeAllowlist(newlyAccepted) {
|
|
1922
1995
|
return Array.from(/* @__PURE__ */ new Set([...alreadyPersisted, ...newlyAccepted])).sort();
|
|
@@ -2027,7 +2100,16 @@ async function createAction2(type, url, options) {
|
|
|
2027
2100
|
process.exit(1);
|
|
2028
2101
|
}
|
|
2029
2102
|
try {
|
|
2030
|
-
|
|
2103
|
+
if (options.name) {
|
|
2104
|
+
try {
|
|
2105
|
+
validateResourceName(options.name);
|
|
2106
|
+
} catch (validationError) {
|
|
2107
|
+
const message = validationError instanceof Error ? validationError.message : String(validationError);
|
|
2108
|
+
trackEvent("CLI: connector create failed", { reason: "invalid_name" });
|
|
2109
|
+
console.error(`\u2717 ${message}`);
|
|
2110
|
+
process.exit(1);
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2031
2113
|
const currentProjectId = getConfig("currentProjectId");
|
|
2032
2114
|
if (!currentProjectId) {
|
|
2033
2115
|
console.error("\u2717 No current project set. Switch to a project first:");
|
|
@@ -2035,6 +2117,22 @@ async function createAction2(type, url, options) {
|
|
|
2035
2117
|
console.error(" ardent project switch <name>");
|
|
2036
2118
|
process.exit(1);
|
|
2037
2119
|
}
|
|
2120
|
+
let parsedUrl;
|
|
2121
|
+
if (!isByocNeon) {
|
|
2122
|
+
parsedUrl = parsePostgresUrl(url);
|
|
2123
|
+
if (!parsedUrl.password) {
|
|
2124
|
+
console.error("\u2717 Password required in connection URL");
|
|
2125
|
+
console.error(" Example: postgresql://user:password@host:5432/db");
|
|
2126
|
+
process.exit(1);
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
const connectorName = options.name ? options.name : await deriveDefaultConnectorName({
|
|
2130
|
+
projectId: currentProjectId,
|
|
2131
|
+
projectName: getConfig("currentProjectName"),
|
|
2132
|
+
sourceDatabase: parsedUrl?.database,
|
|
2133
|
+
sourceHost: parsedUrl?.host,
|
|
2134
|
+
serviceType: type.toLowerCase()
|
|
2135
|
+
});
|
|
2038
2136
|
let createPayload;
|
|
2039
2137
|
if (isByocNeon) {
|
|
2040
2138
|
console.log(
|
|
@@ -2050,12 +2148,7 @@ async function createAction2(type, url, options) {
|
|
|
2050
2148
|
connection_details: {}
|
|
2051
2149
|
};
|
|
2052
2150
|
} else {
|
|
2053
|
-
const parsed =
|
|
2054
|
-
if (!parsed.password) {
|
|
2055
|
-
console.error("\u2717 Password required in connection URL");
|
|
2056
|
-
console.error(" Example: postgresql://user:password@host:5432/db");
|
|
2057
|
-
process.exit(1);
|
|
2058
|
-
}
|
|
2151
|
+
const parsed = parsedUrl;
|
|
2059
2152
|
console.log(
|
|
2060
2153
|
`Creating connector${useByocEnvironment ? " (BYOC environment)" : ""}...`
|
|
2061
2154
|
);
|
|
@@ -2212,6 +2305,7 @@ async function createAction2(type, url, options) {
|
|
|
2212
2305
|
});
|
|
2213
2306
|
if (isDegraded) {
|
|
2214
2307
|
console.log("\u2713 Connector created");
|
|
2308
|
+
console.log(` Name: ${connectorName}`);
|
|
2215
2309
|
console.log(` ID: ${connectorId}`);
|
|
2216
2310
|
console.log("");
|
|
2217
2311
|
let warnings = [];
|
|
@@ -2225,6 +2319,7 @@ async function createAction2(type, url, options) {
|
|
|
2225
2319
|
printDegradedWarnings(warnings);
|
|
2226
2320
|
} else {
|
|
2227
2321
|
console.log("\u2713 Connector created and ready");
|
|
2322
|
+
console.log(` Name: ${connectorName}`);
|
|
2228
2323
|
console.log(` ID: ${connectorId}`);
|
|
2229
2324
|
}
|
|
2230
2325
|
showNextStep();
|
|
@@ -2277,18 +2372,27 @@ function renderConnectorIcon(connector) {
|
|
|
2277
2372
|
}
|
|
2278
2373
|
|
|
2279
2374
|
// src/commands/connector/list.ts
|
|
2375
|
+
function printOtherProjectsHint(summary, currentProjectHasConnectors, dim2, reset2) {
|
|
2376
|
+
if (!summary) return;
|
|
2377
|
+
const connectorWord = summary.connectorCount === 1 ? "connector" : "connectors";
|
|
2378
|
+
const projectWord = summary.projectCount === 1 ? "project" : "projects";
|
|
2379
|
+
const countPhrase = currentProjectHasConnectors ? `${summary.connectorCount} more ${connectorWord}` : `${summary.connectorCount} ${connectorWord}`;
|
|
2380
|
+
console.log(
|
|
2381
|
+
`${dim2}more: ${countPhrase} across ${summary.projectCount} other ${projectWord} \u2014 switch with: ardent project switch <name>${reset2}`
|
|
2382
|
+
);
|
|
2383
|
+
}
|
|
2280
2384
|
async function listAction2() {
|
|
2385
|
+
const currentProjectId = getConfig("currentProjectId");
|
|
2386
|
+
if (!currentProjectId) {
|
|
2387
|
+
console.error("\u2717 No current project set. Switch to a project first:");
|
|
2388
|
+
console.error(" ardent project list");
|
|
2389
|
+
console.error(" ardent project switch <name>");
|
|
2390
|
+
process.exit(1);
|
|
2391
|
+
}
|
|
2281
2392
|
let connectors = [];
|
|
2282
2393
|
let fromCache = false;
|
|
2283
2394
|
let cacheTime = "";
|
|
2284
2395
|
try {
|
|
2285
|
-
const currentProjectId = getConfig("currentProjectId");
|
|
2286
|
-
if (!currentProjectId) {
|
|
2287
|
-
console.error("\u2717 No current project set. Switch to a project first:");
|
|
2288
|
-
console.error(" ardent project list");
|
|
2289
|
-
console.error(" ardent project switch <name>");
|
|
2290
|
-
process.exit(1);
|
|
2291
|
-
}
|
|
2292
2396
|
const result = await api.get(`/v1/cli/connectors?project_id=${currentProjectId}`);
|
|
2293
2397
|
if (!result.connectors) {
|
|
2294
2398
|
throw new Error("API returned invalid response: missing connectors array");
|
|
@@ -2313,26 +2417,47 @@ async function listAction2() {
|
|
|
2313
2417
|
process.exit(1);
|
|
2314
2418
|
}
|
|
2315
2419
|
}
|
|
2420
|
+
let otherProjectsSummary = null;
|
|
2421
|
+
if (!fromCache) {
|
|
2422
|
+
try {
|
|
2423
|
+
const all = await api.get("/v1/cli/connectors");
|
|
2424
|
+
const others = (all.connectors ?? []).filter(
|
|
2425
|
+
(connector) => connector.project_id && connector.project_id !== currentProjectId
|
|
2426
|
+
);
|
|
2427
|
+
if (others.length > 0) {
|
|
2428
|
+
otherProjectsSummary = {
|
|
2429
|
+
connectorCount: others.length,
|
|
2430
|
+
projectCount: new Set(others.map((connector) => connector.project_id)).size
|
|
2431
|
+
};
|
|
2432
|
+
}
|
|
2433
|
+
} catch {
|
|
2434
|
+
otherProjectsSummary = null;
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2316
2437
|
trackEvent("CLI: connector list succeeded", { connector_count: connectors.length, from_cache: fromCache });
|
|
2317
2438
|
if (fromCache) {
|
|
2318
2439
|
console.log(`\u26A0 Offline - showing cached data from ${cacheTime}
|
|
2319
2440
|
`);
|
|
2320
2441
|
}
|
|
2321
|
-
if (connectors.length === 0) {
|
|
2322
|
-
const green3 = "\x1B[32m";
|
|
2323
|
-
const reset3 = "\x1B[0m";
|
|
2324
|
-
console.log("No connectors found");
|
|
2325
|
-
console.log(`${green3} Create one with: ardent connector create postgresql <url>${reset3}`);
|
|
2326
|
-
return;
|
|
2327
|
-
}
|
|
2328
|
-
const selectedConnector = fromCache ? void 0 : reconcileSelectedConnector(connectors);
|
|
2329
|
-
const currentConnectorId = selectedConnector?.id ?? getConfig("currentConnectorId");
|
|
2330
2442
|
const green2 = "\x1B[32m";
|
|
2331
2443
|
const dim2 = "\x1B[2m";
|
|
2332
2444
|
const yellow = "\x1B[33m";
|
|
2333
2445
|
const red = "\x1B[31m";
|
|
2334
2446
|
const reset2 = "\x1B[0m";
|
|
2335
|
-
|
|
2447
|
+
const projectLabel = getConfig("currentProjectName") ?? currentProjectId;
|
|
2448
|
+
console.log(`Project: ${projectLabel}
|
|
2449
|
+
`);
|
|
2450
|
+
if (connectors.length === 0) {
|
|
2451
|
+
console.log(" No connectors in this project.");
|
|
2452
|
+
console.log(`${green2} Create one with: ardent connector create postgresql <url>${reset2}`);
|
|
2453
|
+
if (otherProjectsSummary) {
|
|
2454
|
+
console.log("");
|
|
2455
|
+
printOtherProjectsHint(otherProjectsSummary, false, dim2, reset2);
|
|
2456
|
+
}
|
|
2457
|
+
return;
|
|
2458
|
+
}
|
|
2459
|
+
const selectedConnector = fromCache ? void 0 : reconcileSelectedConnector(connectors);
|
|
2460
|
+
const currentConnectorId = selectedConnector?.id ?? getConfig("currentConnectorId");
|
|
2336
2461
|
let enginePendingCount = 0;
|
|
2337
2462
|
for (const connector of connectors) {
|
|
2338
2463
|
const isCurrent = connector.id === currentConnectorId;
|
|
@@ -2368,6 +2493,7 @@ async function listAction2() {
|
|
|
2368
2493
|
connector_count: connectors.length
|
|
2369
2494
|
});
|
|
2370
2495
|
}
|
|
2496
|
+
printOtherProjectsHint(otherProjectsSummary, true, dim2, reset2);
|
|
2371
2497
|
}
|
|
2372
2498
|
|
|
2373
2499
|
// src/commands/connector/delete.ts
|