@ascendkit/cli 0.3.1 → 0.3.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.
- package/dist/cli.js +142 -20
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -338,6 +338,65 @@ function printSurveySummary(data) {
|
|
|
338
338
|
if (questions != null)
|
|
339
339
|
console.log(`Questions: ${questions}`);
|
|
340
340
|
}
|
|
341
|
+
function printEnvironmentSummary(data) {
|
|
342
|
+
console.log(`${data.name} (${data.id})`);
|
|
343
|
+
console.log(`Tier: ${data.tier}`);
|
|
344
|
+
if (data.description)
|
|
345
|
+
console.log(`Description: ${data.description}`);
|
|
346
|
+
console.log(`Public key: ${data.publicKey}`);
|
|
347
|
+
if (data.secretKey) {
|
|
348
|
+
const masked = data.secretKey.slice(0, 10) + "****";
|
|
349
|
+
console.log(`Secret key: ${masked}`);
|
|
350
|
+
}
|
|
351
|
+
const vars = data.variables && typeof data.variables === "object" ? Object.entries(data.variables) : [];
|
|
352
|
+
if (vars.length > 0) {
|
|
353
|
+
console.log(`Variables:`);
|
|
354
|
+
for (const [k, v] of vars)
|
|
355
|
+
console.log(` ${k}=${v}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
function printPromotionSummary(result) {
|
|
359
|
+
const src = result.source ?? {};
|
|
360
|
+
const tgt = result.target ?? {};
|
|
361
|
+
console.log(`Promoted ${src.tier} → ${tgt.tier} (${tgt.envId})`);
|
|
362
|
+
console.log("");
|
|
363
|
+
const changes = result.changes ?? {};
|
|
364
|
+
const rows = [];
|
|
365
|
+
for (const [key, val] of Object.entries(changes)) {
|
|
366
|
+
const label = key.padEnd(14);
|
|
367
|
+
if (val.action === "unchanged") {
|
|
368
|
+
rows.push([label, "unchanged"]);
|
|
369
|
+
}
|
|
370
|
+
else if (val.action === "skip") {
|
|
371
|
+
rows.push([label, `skipped — ${val.reason}`]);
|
|
372
|
+
}
|
|
373
|
+
else if (val.action === "update" || val.action === "add_only") {
|
|
374
|
+
const fields = Array.isArray(val.fields) && val.fields.length ? ` (${val.fields.join(", ")})` : "";
|
|
375
|
+
rows.push([label, `updated${fields}`]);
|
|
376
|
+
}
|
|
377
|
+
else if (val.items) {
|
|
378
|
+
const counts = Object.entries(val.counts ?? {}).map(([k, v]) => `${v} ${k}`).join(", ");
|
|
379
|
+
rows.push([label, counts || "unchanged"]);
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
rows.push([label, val.action ?? "—"]);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
for (const [label, status] of rows) {
|
|
386
|
+
console.log(` ${label} ${status}`);
|
|
387
|
+
}
|
|
388
|
+
// Only show warnings not already conveyed by a skipped row in the table
|
|
389
|
+
const skippedKeys = new Set(Object.entries(changes)
|
|
390
|
+
.filter(([, v]) => v.action === "skip")
|
|
391
|
+
.map(([k]) => k.toUpperCase()));
|
|
392
|
+
const warnings = (Array.isArray(result.warnings) ? result.warnings : [])
|
|
393
|
+
.filter((w) => !skippedKeys.size || !Array.from(skippedKeys).some(k => w.code?.toUpperCase().includes(k)));
|
|
394
|
+
if (warnings.length > 0) {
|
|
395
|
+
console.log("");
|
|
396
|
+
for (const w of warnings)
|
|
397
|
+
console.log(`⚠ ${w.message}`);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
341
400
|
function printProjectSummary(data) {
|
|
342
401
|
console.log(`Project: ${data.id}`);
|
|
343
402
|
console.log(`Name: ${data.name}`);
|
|
@@ -756,7 +815,7 @@ async function runEnvironment(action, rest) {
|
|
|
756
815
|
}
|
|
757
816
|
switch (action) {
|
|
758
817
|
case "show":
|
|
759
|
-
|
|
818
|
+
printEnvironmentSummary(await platform.getEnvironment(ctx.projectId, ctx.environmentId));
|
|
760
819
|
return;
|
|
761
820
|
case "promote": {
|
|
762
821
|
const envId = rest[0] && !rest[0].startsWith("--") ? rest[0] : ctx.environmentId;
|
|
@@ -767,8 +826,7 @@ async function runEnvironment(action, rest) {
|
|
|
767
826
|
}
|
|
768
827
|
try {
|
|
769
828
|
const result = await platform.promoteEnvironment(envId, target);
|
|
770
|
-
|
|
771
|
-
console.log(JSON.stringify(result, null, 2));
|
|
829
|
+
printPromotionSummary(result);
|
|
772
830
|
}
|
|
773
831
|
catch (err) {
|
|
774
832
|
let message = err instanceof Error ? err.message : String(err);
|
|
@@ -1895,7 +1953,8 @@ async function runEmail(client, action, rest) {
|
|
|
1895
1953
|
break;
|
|
1896
1954
|
}
|
|
1897
1955
|
case "remove-domain":
|
|
1898
|
-
|
|
1956
|
+
await email.removeDomain(client);
|
|
1957
|
+
console.log("Domain removed.");
|
|
1899
1958
|
break;
|
|
1900
1959
|
case "list": {
|
|
1901
1960
|
const result = await email.listIdentities(client);
|
|
@@ -1908,10 +1967,12 @@ async function runEmail(client, action, rest) {
|
|
|
1908
1967
|
console.error("Usage: ascendkit email-identity add <email> [--display-name <name>]");
|
|
1909
1968
|
return await exitCli(1);
|
|
1910
1969
|
}
|
|
1911
|
-
|
|
1970
|
+
const added = await email.createIdentity(client, {
|
|
1912
1971
|
email: identityEmail,
|
|
1913
1972
|
displayName: flags["display-name"],
|
|
1914
|
-
})
|
|
1973
|
+
});
|
|
1974
|
+
printEmailIdentities(added.identities ?? []);
|
|
1975
|
+
console.log("Verification email sent.");
|
|
1915
1976
|
break;
|
|
1916
1977
|
}
|
|
1917
1978
|
case "resend": {
|
|
@@ -1920,7 +1981,8 @@ async function runEmail(client, action, rest) {
|
|
|
1920
1981
|
console.error("Usage: ascendkit email-identity resend <email>");
|
|
1921
1982
|
return await exitCli(1);
|
|
1922
1983
|
}
|
|
1923
|
-
|
|
1984
|
+
await email.resendIdentityVerification(client, identityEmail);
|
|
1985
|
+
console.log(`Verification email sent to ${identityEmail}.`);
|
|
1924
1986
|
break;
|
|
1925
1987
|
}
|
|
1926
1988
|
case "set-default": {
|
|
@@ -1929,10 +1991,11 @@ async function runEmail(client, action, rest) {
|
|
|
1929
1991
|
console.error("Usage: ascendkit email-identity set-default <email> [--display-name <name>]");
|
|
1930
1992
|
return await exitCli(1);
|
|
1931
1993
|
}
|
|
1932
|
-
|
|
1994
|
+
const updated = await email.setDefaultIdentity(client, {
|
|
1933
1995
|
email: identityEmail,
|
|
1934
1996
|
displayName: flags["display-name"],
|
|
1935
|
-
})
|
|
1997
|
+
});
|
|
1998
|
+
printEmailIdentities(updated.identities ?? []);
|
|
1936
1999
|
break;
|
|
1937
2000
|
}
|
|
1938
2001
|
case "remove":
|
|
@@ -1942,7 +2005,9 @@ async function runEmail(client, action, rest) {
|
|
|
1942
2005
|
console.error("Usage: ascendkit email-identity remove <email>");
|
|
1943
2006
|
return await exitCli(1);
|
|
1944
2007
|
}
|
|
1945
|
-
|
|
2008
|
+
const remaining = await email.removeIdentity(client, identityEmail);
|
|
2009
|
+
console.log("Identity removed.");
|
|
2010
|
+
printEmailIdentities(remaining.identities ?? []);
|
|
1946
2011
|
break;
|
|
1947
2012
|
}
|
|
1948
2013
|
case "test": {
|
|
@@ -1951,10 +2016,11 @@ async function runEmail(client, action, rest) {
|
|
|
1951
2016
|
console.error("Usage: ascendkit email-identity test <email> --to <recipient>");
|
|
1952
2017
|
return await exitCli(1);
|
|
1953
2018
|
}
|
|
1954
|
-
|
|
2019
|
+
const testResult = await email.sendTestEmail(client, {
|
|
1955
2020
|
to: flags.to,
|
|
1956
2021
|
fromIdentityEmail: identityEmail,
|
|
1957
|
-
})
|
|
2022
|
+
});
|
|
2023
|
+
console.log(testResult.message ?? "Test email sent.");
|
|
1958
2024
|
break;
|
|
1959
2025
|
}
|
|
1960
2026
|
default:
|
|
@@ -1967,12 +2033,12 @@ run().catch((err) => {
|
|
|
1967
2033
|
exitCli(1, err instanceof Error ? err : new Error(String(err)));
|
|
1968
2034
|
});
|
|
1969
2035
|
async function printEmailSetup(settings) {
|
|
1970
|
-
output(settings);
|
|
1971
2036
|
if (!settings.domain)
|
|
1972
2037
|
return;
|
|
1973
2038
|
const provider = settings.dnsProvider;
|
|
2039
|
+
console.log(`Domain: ${settings.domain}`);
|
|
1974
2040
|
if (provider?.name) {
|
|
1975
|
-
console.log(
|
|
2041
|
+
console.log(`DNS provider: ${provider.name} (${provider.confidence ?? "unknown"})`);
|
|
1976
2042
|
}
|
|
1977
2043
|
if (provider?.portalUrl) {
|
|
1978
2044
|
console.log(`Provider console: ${provider.portalUrl}`);
|
|
@@ -1980,10 +2046,54 @@ async function printEmailSetup(settings) {
|
|
|
1980
2046
|
if (provider?.assistantSetupUrl) {
|
|
1981
2047
|
console.log(`Guided setup: ${provider.assistantSetupUrl}`);
|
|
1982
2048
|
}
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
2049
|
+
const records = Array.isArray(settings.dnsRecords) ? settings.dnsRecords : [];
|
|
2050
|
+
if (records.length > 0) {
|
|
2051
|
+
console.log("\nDNS records to add:");
|
|
2052
|
+
for (const rec of records) {
|
|
2053
|
+
console.log(` ${rec.type.padEnd(6)} ${rec.name} ${rec.value}`);
|
|
2054
|
+
}
|
|
2055
|
+
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
2056
|
+
const defaultFile = `dns-records-${settings.domain}.txt`;
|
|
2057
|
+
const { createInterface } = await import("node:readline/promises");
|
|
2058
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
2059
|
+
try {
|
|
2060
|
+
const answer = (await rl.question(`\nSave records to file [${defaultFile}]: `)).trim();
|
|
2061
|
+
const filename = answer || defaultFile;
|
|
2062
|
+
const { existsSync, writeFileSync } = await import("node:fs");
|
|
2063
|
+
if (existsSync(filename)) {
|
|
2064
|
+
const overwrite = (await rl.question(`${filename} already exists. Overwrite? [y/N] `)).trim().toLowerCase();
|
|
2065
|
+
if (overwrite !== "y" && overwrite !== "yes") {
|
|
2066
|
+
console.log("Skipped.");
|
|
2067
|
+
return;
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
const lines = [
|
|
2071
|
+
`; DNS records for ${settings.domain}`,
|
|
2072
|
+
`; Generated by AscendKit CLI`,
|
|
2073
|
+
"",
|
|
2074
|
+
...records.map(rec => {
|
|
2075
|
+
let value;
|
|
2076
|
+
if (rec.type === "TXT") {
|
|
2077
|
+
value = `"${rec.value}"`;
|
|
2078
|
+
}
|
|
2079
|
+
else if (rec.type === "CNAME" || rec.type === "MX") {
|
|
2080
|
+
// Ensure absolute FQDN with trailing dot to prevent zone-relative expansion
|
|
2081
|
+
const target = rec.type === "MX" ? rec.value.replace(/^(\d+)\s+/, "$1 ") : rec.value;
|
|
2082
|
+
value = target.endsWith(".") ? target : `${target}.`;
|
|
2083
|
+
}
|
|
2084
|
+
else {
|
|
2085
|
+
value = rec.value;
|
|
2086
|
+
}
|
|
2087
|
+
const name = rec.name.endsWith(".") ? rec.name : `${rec.name}.`;
|
|
2088
|
+
return `${name}\t3600\tIN\t${rec.type}\t${value} ; cf_tags=cf-proxied:false`;
|
|
2089
|
+
}),
|
|
2090
|
+
];
|
|
2091
|
+
writeFileSync(filename, lines.join("\n") + "\n");
|
|
2092
|
+
console.log(`Saved to ${filename}`);
|
|
2093
|
+
}
|
|
2094
|
+
finally {
|
|
2095
|
+
rl.close();
|
|
2096
|
+
}
|
|
1987
2097
|
}
|
|
1988
2098
|
}
|
|
1989
2099
|
}
|
|
@@ -2015,8 +2125,20 @@ function printEmailStatusSummary(settings, domainStatus, dnsCheck, identities) {
|
|
|
2015
2125
|
return;
|
|
2016
2126
|
}
|
|
2017
2127
|
console.log(`Domain: ${settings.domain} (${domainStatus.status || settings.verificationStatus || "unknown"})`);
|
|
2018
|
-
if (dnsCheck
|
|
2019
|
-
|
|
2128
|
+
if (dnsCheck) {
|
|
2129
|
+
const { summary, records } = dnsCheck;
|
|
2130
|
+
if (summary.notFound === 0 && summary.mismatch === 0 && summary.errored === 0) {
|
|
2131
|
+
console.log("DNS: all records verified");
|
|
2132
|
+
}
|
|
2133
|
+
else {
|
|
2134
|
+
console.log(`DNS: ${summary.found}/${summary.total} verified`);
|
|
2135
|
+
const pending = records.filter(r => !r.found || r.mismatch);
|
|
2136
|
+
if (pending.length > 0) {
|
|
2137
|
+
console.log("Pending:");
|
|
2138
|
+
for (const r of pending)
|
|
2139
|
+
console.log(` ${r.type.padEnd(6)} ${r.name}`);
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2020
2142
|
}
|
|
2021
2143
|
console.log("");
|
|
2022
2144
|
printEmailIdentities(identities);
|