Sign In

@cross-deck/cli

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cross-deck/cli - npm Package Compare versions

Comparing version
1.2.0
to
1.3.0
+273
-16
dist/cli.cjs

@@ -103,6 +103,6 @@ #!/usr/bin/env node

}
function printCheck(label, ok2, detail) {
function printCheck(label2, ok2, detail) {
const icon = ok2 ? "\u2713" : "\u2717";
const stream = ok2 ? process.stdout : process.stderr;
stream.write(` ${icon} ${label}
stream.write(` ${icon} ${label2}
`);

@@ -646,4 +646,4 @@ if (detail) stream.write(` ${detail}

if (!res.ok) {
const desc = data.error_description || data.error || text || `HTTP ${res.status}`;
throw new Error(desc);
const desc3 = data.error_description || data.error || text || `HTTP ${res.status}`;
throw new Error(desc3);
}

@@ -703,6 +703,6 @@ return data;

function openBrowser(url) {
const cmd = (0, import_node_os2.platform)() === "darwin" ? "open" : (0, import_node_os2.platform)() === "win32" ? "cmd" : "xdg-open";
const cmd2 = (0, import_node_os2.platform)() === "darwin" ? "open" : (0, import_node_os2.platform)() === "win32" ? "cmd" : "xdg-open";
const args = (0, import_node_os2.platform)() === "win32" ? ["/c", "start", "", url] : [url];
try {
const child = (0, import_node_child_process.spawn)(cmd, args, { stdio: "ignore", detached: true });
const child = (0, import_node_child_process.spawn)(cmd2, args, { stdio: "ignore", detached: true });
child.on("error", () => {

@@ -759,2 +759,13 @@ });

});
let email;
try {
const res = await fetch(`${baseUrl}/v1/workspace/projects`, {
headers: { Authorization: `Bearer ${tokens.accessToken}`, Accept: "application/json" }
});
if (res.ok) {
const body = await res.json();
email = body.data?.account?.email ?? void 0;
}
} catch {
}
const store = credentialStore();

@@ -766,6 +777,7 @@ store.save({

baseUrl,
loggedInAt: (/* @__PURE__ */ new Date()).toISOString()
loggedInAt: (/* @__PURE__ */ new Date()).toISOString(),
email
});
process.stdout.write(`
\u2713 Signed in. Access renews automatically for ~30 days.
\u2713 Signed in${email ? ` as ${email}` : ""}. Access renews automatically for ~30 days.
`);

@@ -818,3 +830,5 @@ process.stdout.write(` Scopes: ${tokens.scope || scope}

baseUrl,
loggedInAt: creds.loggedInAt
loggedInAt: creds.loggedInAt,
email: creds.email
// preserve the cached identity across refresh rotations
});

@@ -829,2 +843,3 @@ return { accessToken: tokens.accessToken, baseUrl, scope: tokens.scope || creds.scope };

let projectCount = null;
let email = null;
try {

@@ -837,2 +852,3 @@ const res = await fetch(`${session.baseUrl}/v1/workspace/projects`, {

projectCount = Array.isArray(body.data?.projects) ? body.data.projects.length : null;
email = body.data?.account?.email ?? null;
}

@@ -844,2 +860,4 @@ } catch {

`);
if (email) process.stdout.write(` Account: ${email}
`);
process.stdout.write(` API: ${session.baseUrl}

@@ -872,9 +890,37 @@ `);

const store = credentialStore();
const had = store.load() !== null;
let creds;
try {
creds = store.load();
} catch {
store.clear();
process.stdout.write("\n\u2713 Signed out on this machine \u2014 the stored credential was wiped.\n\n");
return 0;
}
if (!creds) {
process.stdout.write("\nYou weren't signed in. Nothing to do.\n\n");
return 0;
}
let serverRevoked = false;
try {
const url = `${creds.baseUrl.replace(/\/+$/, "")}/oauth/revoke`;
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
token: creds.refreshToken,
token_type_hint: "refresh_token",
client_id: creds.clientId
})
});
serverRevoked = res.ok;
} catch {
serverRevoked = false;
}
store.clear();
if (had) {
if (serverRevoked) {
process.stdout.write("\n\u2713 Signed out \u2014 this session was revoked server-side and wiped from this machine.\n");
process.stdout.write(" Manage every connected machine from Settings \u2192 Developer in the dashboard.\n\n");
} else {
process.stdout.write("\n\u2713 Signed out on this machine \u2014 the stored credential was wiped.\n");
process.stdout.write(" To revoke it everywhere, use Settings \u2192 Developer in the dashboard.\n\n");
} else {
process.stdout.write("\nYou weren't signed in. Nothing to do.\n\n");
process.stdout.write(" Couldn't confirm the server-side revoke (offline?). Revoke it anywhere from Settings \u2192 Developer in the dashboard.\n\n");
}

@@ -1339,8 +1385,200 @@ return 0;

// src/launcher.ts
var isTTY = !!process.stdout.isTTY;
var useColor2 = isTTY && !process.env.NO_COLOR;
var truecolor = useColor2 && /truecolor|24bit/i.test(process.env.COLORTERM ?? "");
var X_FROM = [255, 61, 46];
var X_TO = [255, 154, 61];
var CORAL = [255, 107, 84];
var WORD = [241, 234, 226];
var DESC = [140, 131, 123];
var OKGREEN = [111, 207, 155];
var FAINT = [92, 83, 75];
var tc = (rgb, s) => truecolor ? `\x1B[38;2;${rgb[0]};${rgb[1]};${rgb[2]}m${s}\x1B[0m` : useColor2 ? `\x1B[91m${s}\x1B[0m` : s;
var ansi = (code, s) => useColor2 ? `\x1B[${code}m${s}\x1B[0m` : s;
var dim = (s) => ansi("2", s);
var coral = (s) => tc(CORAL, s);
var desc = (s) => truecolor ? tc(DESC, s) : dim(s);
var X_ART = [
"\u2588\u2588\u2557 \u2588\u2588\u2557",
"\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D",
" \u255A\u2588\u2588\u2588\u2554\u255D ",
" \u2588\u2588\u2554\u2588\u2588\u2557 ",
"\u2588\u2588\u2554\u255D \u2588\u2588\u2557",
"\u255A\u2550\u255D \u255A\u2550\u255D"
];
function brandX() {
const n = X_ART.length - 1;
return X_ART.map((row, i) => {
const t = n === 0 ? 0 : i / n;
const rgb = [
Math.round(X_FROM[0] + (X_TO[0] - X_FROM[0]) * t),
Math.round(X_FROM[1] + (X_TO[1] - X_FROM[1]) * t),
Math.round(X_FROM[2] + (X_TO[2] - X_FROM[2]) * t)
];
return " " + tc(rgb, row);
}).join("\n");
}
function wordmark() {
return ` ${tc(WORD, "crossdeck")} ${coral("CLI")} ${desc(`\xB7 v${version()}`)}`;
}
var TAGLINE = "The platform that joins revenue, errors, and identity \u2014 by identity \u2014 now in your terminal.";
function label(text) {
return ` ${desc(text.toUpperCase())}`;
}
function cmd(name, description, pad) {
return ` ${coral(name.padEnd(pad))} ${desc(description)}`;
}
var CLI_VERSION = "0.0.0";
function setLauncherVersion(v) {
CLI_VERSION = v;
}
function version() {
return CLI_VERSION;
}
function renderLauncher() {
const creds = safeLoad();
const out = [];
out.push("");
out.push(brandX());
out.push("");
out.push(wordmark());
out.push(` ${desc(TAGLINE)}`);
out.push("");
if (!creds) {
out.push(` ${truecolor ? tc(FAINT, "\u25CB") : dim("\u25CB")} Not signed in.`);
out.push("");
out.push(label("Get started"));
out.push(cmd("crossdeck login", "Sign in \u2014 opens your browser", 24));
out.push(cmd("crossdeck login --key \u2026", "Non-interactive (CI): use a project secret key", 24));
out.push("");
out.push(` ${desc("Docs")} ${tc(WORD, "cross-deck.com/docs")}`);
out.push(` ${desc("Dashboard")} ${tc(WORD, "app.cross-deck.com")}`);
out.push("");
out.push(` ${desc("New here? Run 'crossdeck login' to connect this machine.")}`);
} else {
const who = creds.email ? `Signed in as ${creds.email}` : "Signed in";
out.push(` ${tc(OKGREEN, "\u2713")} ${who}`);
const active = getActiveProject();
if (active) {
out.push(` ${coral("\u25CF")} ${active}`);
} else {
out.push(` ${truecolor ? tc(FAINT, "\u25CB") : dim("\u25CB")} ${desc("No active project \u2014 run 'crossdeck use <id>'")}`);
}
out.push("");
out.push(label("Stand up the engine"));
out.push(cmd("crossdeck init", "Create a project + app, mint keys", 24));
out.push(cmd("crossdeck apps create", "Add an app to a project", 24));
out.push(cmd("crossdeck use", "Switch the active project", 24));
out.push("");
out.push(label("Read the facts"));
out.push(cmd("crossdeck revenue", "MRR & recognised cash", 24));
out.push(cmd("crossdeck analytics", "Traffic & acquisition", 24));
out.push(cmd("crossdeck errors", "An issue, stitched to who it hit", 24));
out.push("");
out.push(` ${desc("Docs")} ${tc(WORD, "cross-deck.com/docs")}`);
out.push(` ${desc("Run 'crossdeck help' for the full command tree.")}`);
}
out.push("");
process.stdout.write(out.join("\n") + "\n");
}
function safeLoad() {
try {
return credentialStore().load();
} catch {
return null;
}
}
// src/help.ts
var isTTY2 = !!process.stdout.isTTY;
var useColor3 = isTTY2 && !process.env.NO_COLOR;
var truecolor2 = useColor3 && /truecolor|24bit/i.test(process.env.COLORTERM ?? "");
var CORAL2 = [255, 107, 84];
var WORD2 = [241, 234, 226];
var DESC2 = [140, 131, 123];
var tc2 = (rgb, s) => truecolor2 ? `\x1B[38;2;${rgb[0]};${rgb[1]};${rgb[2]}m${s}\x1B[0m` : useColor3 ? `\x1B[91m${s}\x1B[0m` : s;
var ansi2 = (code, s) => useColor3 ? `\x1B[${code}m${s}\x1B[0m` : s;
var dim2 = (s) => ansi2("2", s);
var bold = (s) => ansi2("1", s);
var coral2 = (s) => tc2(CORAL2, s);
var desc2 = (s) => truecolor2 ? tc2(DESC2, s) : dim2(s);
var GROUPS = [
{
title: "Account",
note: "Sign in with your browser (OAuth). Grants this machine provisioning + read access.",
cmds: [
{ name: "login", desc: "Sign in \u2014 opens your browser (--read-only, --no-browser)" },
{ name: "whoami", desc: "Show the active session \u2014 API, scopes, portfolio size" },
{ name: "logout", desc: "Sign out \u2014 revokes this machine server-side" }
]
},
{
title: "Stand up the engine",
cmds: [
{ name: "init", desc: "Zero to installed: project + app, mint keys, print the SDK snippet" },
{ name: "projects create", desc: "Create a project (-n name, --business-model, --activate)" },
{ name: "projects list", desc: "List the projects you own" },
{ name: "apps create", desc: "Create an app + mint publishable keys (-P web|ios|android)" },
{ name: "apps list", desc: "List apps (all, or one project's with -p)" },
{ name: "use", desc: "Set (or show) the active project for later commands" }
]
},
{
title: "Read the facts",
note: "Read-only. Every number is self-describing \u2014 coverage and semantics travel with it.",
cmds: [
{ name: "revenue", desc: "Recognised cash for a project (GET /v1/revenue)" },
{ name: "analytics", desc: "Signup acquisition sources (GET /v1/acquisition)" },
{ name: "errors", desc: "One issue, stitched to who it hit (-i <fingerprint>)" }
]
},
{
title: "Source maps \xB7 CI",
note: "Key-based (cd_sk_\u2026), no login. What the Errors tab means by 'install the CLI'.",
cmds: [
{ name: "sourcemaps upload", desc: "Upload .map files so the dashboard resolves minified frames" },
{ name: "upload-sourcemaps", desc: "Permanent alias for `sourcemaps upload`" },
{ name: "doctor", desc: "Validate auth + API reachability without uploading" }
]
}
];
var CLI_VERSION2 = "0.0.0";
function setHelpVersion(v) {
CLI_VERSION2 = v;
}
function renderHelp() {
const pad = Math.max(
...GROUPS.flatMap((g) => g.cmds.map((c2) => c2.name.length))
);
const out = [];
out.push("");
out.push(` ${bold(tc2(WORD2, "crossdeck"))} ${coral2("CLI")} ${desc2(`\xB7 v${CLI_VERSION2}`)}`);
out.push(` ${desc2("Sign in, provision projects & apps, and read the facts \u2014 from your terminal.")}`);
out.push("");
out.push(` ${desc2("Usage:")} crossdeck ${coral2("<command>")} ${desc2("[options]")}`);
out.push(` crossdeck ${desc2("# the launcher")}`);
out.push(` crossdeck help ${coral2("<command>")} ${desc2("# flags for one command")}`);
for (const g of GROUPS) {
out.push("");
out.push(` ${desc2(g.title.toUpperCase())}`);
if (g.note) out.push(` ${dim2(g.note)}`);
for (const c2 of g.cmds) {
out.push(` ${coral2(c2.name.padEnd(pad))} ${desc2(c2.desc)}`);
}
}
out.push("");
out.push(` ${desc2("Docs")} ${tc2(WORD2, "cross-deck.com/docs/cli")} ${desc2("Global flags:")} --json, --base-url <url>`);
out.push("");
process.stdout.write(out.join("\n") + "\n");
}
// src/cli.ts
var VERSION = "1.2.0";
var VERSION = "1.3.0";
setLauncherVersion(VERSION);
setHelpVersion(VERSION);
var program = new import_commander.Command();
program.name("crossdeck").description(
"Crossdeck CLI \u2014 sign in, provision projects & apps, and monitor errors, analytics, and revenue from your terminal."
).version(VERSION);
).version(VERSION).helpCommand(false);
program.command("login").description("Sign in to Crossdeck in your browser (OAuth). Grants this machine provisioning + read access.").option("--read-only", "Request read-only scope (no project/app/key creation).", false).option("--scope <scope>", "Override the exact space-separated OAuth scope to request.").option("--no-browser", "Print the sign-in URL instead of opening a browser (headless machines).").option("--base-url <url>", "Crossdeck API base URL. Defaults to https://api.cross-deck.com.").action(async (opts) => {

@@ -1430,2 +1668,21 @@ process.exit(

});
program.command("help").argument("[command]", "Show flags for one command instead of the whole tree.").description("Show the command tree, or one command's flags.").action((command) => {
if (!command) {
renderHelp();
process.exit(0);
}
const target = program.commands.find((cmd2) => cmd2.name() === command);
if (target) {
target.outputHelp();
process.exit(0);
}
process.stderr.write(`Unknown command: ${command}
`);
renderHelp();
process.exit(1);
});
if (process.argv.length <= 2) {
renderLauncher();
process.exit(0);
}
program.parseAsync(process.argv).catch((err) => {

@@ -1432,0 +1689,0 @@ console.error(err instanceof Error ? err.message : String(err));

@@ -100,6 +100,6 @@ // src/cli.ts

}
function printCheck(label, ok2, detail) {
function printCheck(label2, ok2, detail) {
const icon = ok2 ? "\u2713" : "\u2717";
const stream = ok2 ? process.stdout : process.stderr;
stream.write(` ${icon} ${label}
stream.write(` ${icon} ${label2}
`);

@@ -643,4 +643,4 @@ if (detail) stream.write(` ${detail}

if (!res.ok) {
const desc = data.error_description || data.error || text || `HTTP ${res.status}`;
throw new Error(desc);
const desc3 = data.error_description || data.error || text || `HTTP ${res.status}`;
throw new Error(desc3);
}

@@ -700,6 +700,6 @@ return data;

function openBrowser(url) {
const cmd = platform2() === "darwin" ? "open" : platform2() === "win32" ? "cmd" : "xdg-open";
const cmd2 = platform2() === "darwin" ? "open" : platform2() === "win32" ? "cmd" : "xdg-open";
const args = platform2() === "win32" ? ["/c", "start", "", url] : [url];
try {
const child = spawn(cmd, args, { stdio: "ignore", detached: true });
const child = spawn(cmd2, args, { stdio: "ignore", detached: true });
child.on("error", () => {

@@ -756,2 +756,13 @@ });

});
let email;
try {
const res = await fetch(`${baseUrl}/v1/workspace/projects`, {
headers: { Authorization: `Bearer ${tokens.accessToken}`, Accept: "application/json" }
});
if (res.ok) {
const body = await res.json();
email = body.data?.account?.email ?? void 0;
}
} catch {
}
const store = credentialStore();

@@ -763,6 +774,7 @@ store.save({

baseUrl,
loggedInAt: (/* @__PURE__ */ new Date()).toISOString()
loggedInAt: (/* @__PURE__ */ new Date()).toISOString(),
email
});
process.stdout.write(`
\u2713 Signed in. Access renews automatically for ~30 days.
\u2713 Signed in${email ? ` as ${email}` : ""}. Access renews automatically for ~30 days.
`);

@@ -815,3 +827,5 @@ process.stdout.write(` Scopes: ${tokens.scope || scope}

baseUrl,
loggedInAt: creds.loggedInAt
loggedInAt: creds.loggedInAt,
email: creds.email
// preserve the cached identity across refresh rotations
});

@@ -826,2 +840,3 @@ return { accessToken: tokens.accessToken, baseUrl, scope: tokens.scope || creds.scope };

let projectCount = null;
let email = null;
try {

@@ -834,2 +849,3 @@ const res = await fetch(`${session.baseUrl}/v1/workspace/projects`, {

projectCount = Array.isArray(body.data?.projects) ? body.data.projects.length : null;
email = body.data?.account?.email ?? null;
}

@@ -841,2 +857,4 @@ } catch {

`);
if (email) process.stdout.write(` Account: ${email}
`);
process.stdout.write(` API: ${session.baseUrl}

@@ -869,9 +887,37 @@ `);

const store = credentialStore();
const had = store.load() !== null;
let creds;
try {
creds = store.load();
} catch {
store.clear();
process.stdout.write("\n\u2713 Signed out on this machine \u2014 the stored credential was wiped.\n\n");
return 0;
}
if (!creds) {
process.stdout.write("\nYou weren't signed in. Nothing to do.\n\n");
return 0;
}
let serverRevoked = false;
try {
const url = `${creds.baseUrl.replace(/\/+$/, "")}/oauth/revoke`;
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
token: creds.refreshToken,
token_type_hint: "refresh_token",
client_id: creds.clientId
})
});
serverRevoked = res.ok;
} catch {
serverRevoked = false;
}
store.clear();
if (had) {
if (serverRevoked) {
process.stdout.write("\n\u2713 Signed out \u2014 this session was revoked server-side and wiped from this machine.\n");
process.stdout.write(" Manage every connected machine from Settings \u2192 Developer in the dashboard.\n\n");
} else {
process.stdout.write("\n\u2713 Signed out on this machine \u2014 the stored credential was wiped.\n");
process.stdout.write(" To revoke it everywhere, use Settings \u2192 Developer in the dashboard.\n\n");
} else {
process.stdout.write("\nYou weren't signed in. Nothing to do.\n\n");
process.stdout.write(" Couldn't confirm the server-side revoke (offline?). Revoke it anywhere from Settings \u2192 Developer in the dashboard.\n\n");
}

@@ -1336,8 +1382,200 @@ return 0;

// src/launcher.ts
var isTTY = !!process.stdout.isTTY;
var useColor2 = isTTY && !process.env.NO_COLOR;
var truecolor = useColor2 && /truecolor|24bit/i.test(process.env.COLORTERM ?? "");
var X_FROM = [255, 61, 46];
var X_TO = [255, 154, 61];
var CORAL = [255, 107, 84];
var WORD = [241, 234, 226];
var DESC = [140, 131, 123];
var OKGREEN = [111, 207, 155];
var FAINT = [92, 83, 75];
var tc = (rgb, s) => truecolor ? `\x1B[38;2;${rgb[0]};${rgb[1]};${rgb[2]}m${s}\x1B[0m` : useColor2 ? `\x1B[91m${s}\x1B[0m` : s;
var ansi = (code, s) => useColor2 ? `\x1B[${code}m${s}\x1B[0m` : s;
var dim = (s) => ansi("2", s);
var coral = (s) => tc(CORAL, s);
var desc = (s) => truecolor ? tc(DESC, s) : dim(s);
var X_ART = [
"\u2588\u2588\u2557 \u2588\u2588\u2557",
"\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D",
" \u255A\u2588\u2588\u2588\u2554\u255D ",
" \u2588\u2588\u2554\u2588\u2588\u2557 ",
"\u2588\u2588\u2554\u255D \u2588\u2588\u2557",
"\u255A\u2550\u255D \u255A\u2550\u255D"
];
function brandX() {
const n = X_ART.length - 1;
return X_ART.map((row, i) => {
const t = n === 0 ? 0 : i / n;
const rgb = [
Math.round(X_FROM[0] + (X_TO[0] - X_FROM[0]) * t),
Math.round(X_FROM[1] + (X_TO[1] - X_FROM[1]) * t),
Math.round(X_FROM[2] + (X_TO[2] - X_FROM[2]) * t)
];
return " " + tc(rgb, row);
}).join("\n");
}
function wordmark() {
return ` ${tc(WORD, "crossdeck")} ${coral("CLI")} ${desc(`\xB7 v${version()}`)}`;
}
var TAGLINE = "The platform that joins revenue, errors, and identity \u2014 by identity \u2014 now in your terminal.";
function label(text) {
return ` ${desc(text.toUpperCase())}`;
}
function cmd(name, description, pad) {
return ` ${coral(name.padEnd(pad))} ${desc(description)}`;
}
var CLI_VERSION = "0.0.0";
function setLauncherVersion(v) {
CLI_VERSION = v;
}
function version() {
return CLI_VERSION;
}
function renderLauncher() {
const creds = safeLoad();
const out = [];
out.push("");
out.push(brandX());
out.push("");
out.push(wordmark());
out.push(` ${desc(TAGLINE)}`);
out.push("");
if (!creds) {
out.push(` ${truecolor ? tc(FAINT, "\u25CB") : dim("\u25CB")} Not signed in.`);
out.push("");
out.push(label("Get started"));
out.push(cmd("crossdeck login", "Sign in \u2014 opens your browser", 24));
out.push(cmd("crossdeck login --key \u2026", "Non-interactive (CI): use a project secret key", 24));
out.push("");
out.push(` ${desc("Docs")} ${tc(WORD, "cross-deck.com/docs")}`);
out.push(` ${desc("Dashboard")} ${tc(WORD, "app.cross-deck.com")}`);
out.push("");
out.push(` ${desc("New here? Run 'crossdeck login' to connect this machine.")}`);
} else {
const who = creds.email ? `Signed in as ${creds.email}` : "Signed in";
out.push(` ${tc(OKGREEN, "\u2713")} ${who}`);
const active = getActiveProject();
if (active) {
out.push(` ${coral("\u25CF")} ${active}`);
} else {
out.push(` ${truecolor ? tc(FAINT, "\u25CB") : dim("\u25CB")} ${desc("No active project \u2014 run 'crossdeck use <id>'")}`);
}
out.push("");
out.push(label("Stand up the engine"));
out.push(cmd("crossdeck init", "Create a project + app, mint keys", 24));
out.push(cmd("crossdeck apps create", "Add an app to a project", 24));
out.push(cmd("crossdeck use", "Switch the active project", 24));
out.push("");
out.push(label("Read the facts"));
out.push(cmd("crossdeck revenue", "MRR & recognised cash", 24));
out.push(cmd("crossdeck analytics", "Traffic & acquisition", 24));
out.push(cmd("crossdeck errors", "An issue, stitched to who it hit", 24));
out.push("");
out.push(` ${desc("Docs")} ${tc(WORD, "cross-deck.com/docs")}`);
out.push(` ${desc("Run 'crossdeck help' for the full command tree.")}`);
}
out.push("");
process.stdout.write(out.join("\n") + "\n");
}
function safeLoad() {
try {
return credentialStore().load();
} catch {
return null;
}
}
// src/help.ts
var isTTY2 = !!process.stdout.isTTY;
var useColor3 = isTTY2 && !process.env.NO_COLOR;
var truecolor2 = useColor3 && /truecolor|24bit/i.test(process.env.COLORTERM ?? "");
var CORAL2 = [255, 107, 84];
var WORD2 = [241, 234, 226];
var DESC2 = [140, 131, 123];
var tc2 = (rgb, s) => truecolor2 ? `\x1B[38;2;${rgb[0]};${rgb[1]};${rgb[2]}m${s}\x1B[0m` : useColor3 ? `\x1B[91m${s}\x1B[0m` : s;
var ansi2 = (code, s) => useColor3 ? `\x1B[${code}m${s}\x1B[0m` : s;
var dim2 = (s) => ansi2("2", s);
var bold = (s) => ansi2("1", s);
var coral2 = (s) => tc2(CORAL2, s);
var desc2 = (s) => truecolor2 ? tc2(DESC2, s) : dim2(s);
var GROUPS = [
{
title: "Account",
note: "Sign in with your browser (OAuth). Grants this machine provisioning + read access.",
cmds: [
{ name: "login", desc: "Sign in \u2014 opens your browser (--read-only, --no-browser)" },
{ name: "whoami", desc: "Show the active session \u2014 API, scopes, portfolio size" },
{ name: "logout", desc: "Sign out \u2014 revokes this machine server-side" }
]
},
{
title: "Stand up the engine",
cmds: [
{ name: "init", desc: "Zero to installed: project + app, mint keys, print the SDK snippet" },
{ name: "projects create", desc: "Create a project (-n name, --business-model, --activate)" },
{ name: "projects list", desc: "List the projects you own" },
{ name: "apps create", desc: "Create an app + mint publishable keys (-P web|ios|android)" },
{ name: "apps list", desc: "List apps (all, or one project's with -p)" },
{ name: "use", desc: "Set (or show) the active project for later commands" }
]
},
{
title: "Read the facts",
note: "Read-only. Every number is self-describing \u2014 coverage and semantics travel with it.",
cmds: [
{ name: "revenue", desc: "Recognised cash for a project (GET /v1/revenue)" },
{ name: "analytics", desc: "Signup acquisition sources (GET /v1/acquisition)" },
{ name: "errors", desc: "One issue, stitched to who it hit (-i <fingerprint>)" }
]
},
{
title: "Source maps \xB7 CI",
note: "Key-based (cd_sk_\u2026), no login. What the Errors tab means by 'install the CLI'.",
cmds: [
{ name: "sourcemaps upload", desc: "Upload .map files so the dashboard resolves minified frames" },
{ name: "upload-sourcemaps", desc: "Permanent alias for `sourcemaps upload`" },
{ name: "doctor", desc: "Validate auth + API reachability without uploading" }
]
}
];
var CLI_VERSION2 = "0.0.0";
function setHelpVersion(v) {
CLI_VERSION2 = v;
}
function renderHelp() {
const pad = Math.max(
...GROUPS.flatMap((g) => g.cmds.map((c2) => c2.name.length))
);
const out = [];
out.push("");
out.push(` ${bold(tc2(WORD2, "crossdeck"))} ${coral2("CLI")} ${desc2(`\xB7 v${CLI_VERSION2}`)}`);
out.push(` ${desc2("Sign in, provision projects & apps, and read the facts \u2014 from your terminal.")}`);
out.push("");
out.push(` ${desc2("Usage:")} crossdeck ${coral2("<command>")} ${desc2("[options]")}`);
out.push(` crossdeck ${desc2("# the launcher")}`);
out.push(` crossdeck help ${coral2("<command>")} ${desc2("# flags for one command")}`);
for (const g of GROUPS) {
out.push("");
out.push(` ${desc2(g.title.toUpperCase())}`);
if (g.note) out.push(` ${dim2(g.note)}`);
for (const c2 of g.cmds) {
out.push(` ${coral2(c2.name.padEnd(pad))} ${desc2(c2.desc)}`);
}
}
out.push("");
out.push(` ${desc2("Docs")} ${tc2(WORD2, "cross-deck.com/docs/cli")} ${desc2("Global flags:")} --json, --base-url <url>`);
out.push("");
process.stdout.write(out.join("\n") + "\n");
}
// src/cli.ts
var VERSION = "1.2.0";
var VERSION = "1.3.0";
setLauncherVersion(VERSION);
setHelpVersion(VERSION);
var program = new Command();
program.name("crossdeck").description(
"Crossdeck CLI \u2014 sign in, provision projects & apps, and monitor errors, analytics, and revenue from your terminal."
).version(VERSION);
).version(VERSION).helpCommand(false);
program.command("login").description("Sign in to Crossdeck in your browser (OAuth). Grants this machine provisioning + read access.").option("--read-only", "Request read-only scope (no project/app/key creation).", false).option("--scope <scope>", "Override the exact space-separated OAuth scope to request.").option("--no-browser", "Print the sign-in URL instead of opening a browser (headless machines).").option("--base-url <url>", "Crossdeck API base URL. Defaults to https://api.cross-deck.com.").action(async (opts) => {

@@ -1427,2 +1665,21 @@ process.exit(

});
program.command("help").argument("[command]", "Show flags for one command instead of the whole tree.").description("Show the command tree, or one command's flags.").action((command) => {
if (!command) {
renderHelp();
process.exit(0);
}
const target = program.commands.find((cmd2) => cmd2.name() === command);
if (target) {
target.outputHelp();
process.exit(0);
}
process.stderr.write(`Unknown command: ${command}
`);
renderHelp();
process.exit(1);
});
if (process.argv.length <= 2) {
renderLauncher();
process.exit(0);
}
program.parseAsync(process.argv).catch((err) => {

@@ -1429,0 +1686,0 @@ console.error(err instanceof Error ? err.message : String(err));

+1
-1
{
"name": "@cross-deck/cli",
"version": "1.2.0",
"version": "1.3.0",
"description": "Crossdeck CLI — upload source maps so production stack traces resolve back to original file:line:function.",

@@ -5,0 +5,0 @@ "license": "MIT",

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display