@binaryandthread/cli 0.2.1 → 0.3.0
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/bin.js +45 -80
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-AP5ARNWU.js → chunk-RDJJLYXB.js} +17 -2
- package/dist/chunk-RDJJLYXB.js.map +1 -0
- package/dist/{interactive-4XWSUOOK.js → interactive-DJXIUVBM.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-AP5ARNWU.js.map +0 -1
- /package/dist/{interactive-4XWSUOOK.js.map → interactive-DJXIUVBM.js.map} +0 -0
package/dist/bin.js
CHANGED
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
versionLine,
|
|
54
54
|
warn,
|
|
55
55
|
working
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-RDJJLYXB.js";
|
|
57
57
|
import {
|
|
58
58
|
__require
|
|
59
59
|
} from "./chunk-7OCVIDC7.js";
|
|
@@ -82,7 +82,7 @@ function makeLogger(debug, write = (s) => process.stderr.write(s)) {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
// src/version.ts
|
|
85
|
-
var VERSION = "0.
|
|
85
|
+
var VERSION = "0.3.0";
|
|
86
86
|
|
|
87
87
|
// src/eggs.ts
|
|
88
88
|
function teapot() {
|
|
@@ -222,7 +222,7 @@ function isMainModule(argv1, moduleUrl, realpath = realpathSync) {
|
|
|
222
222
|
import * as fs from "fs";
|
|
223
223
|
import * as path from "path";
|
|
224
224
|
var CACHE_FILE = "update-check.json";
|
|
225
|
-
var CHECK_INTERVAL_MS =
|
|
225
|
+
var CHECK_INTERVAL_MS = 6 * 60 * 60 * 1e3;
|
|
226
226
|
var REGISTRY_LATEST = "https://registry.npmjs.org/@binaryandthread/cli/latest";
|
|
227
227
|
var FETCH_TIMEOUT_MS = 2e3;
|
|
228
228
|
function parseSemver(v) {
|
|
@@ -478,7 +478,7 @@ function registerBrowse(program, makeClient2, loadConfig2) {
|
|
|
478
478
|
program.command("browse").alias("ls").description("list what's in stock on a branch.").option("--branch <branch>", "main (live) or next (terminal-only drops)").option("--pick", "opt into the arrow-key picker (default is the numbered table \u2014 use bt stage <n>)").option("--plain", "force the static table (the default; kept for back-compat)").action(async (opts) => {
|
|
479
479
|
const { json, brand } = resolveOutput(program);
|
|
480
480
|
if (opts.pick && !json && brand.color && process.stdout.isTTY && process.stdin.isTTY) {
|
|
481
|
-
const { runInteractiveBrowse } = await import("./interactive-
|
|
481
|
+
const { runInteractiveBrowse } = await import("./interactive-DJXIUVBM.js");
|
|
482
482
|
const handled = await runInteractiveBrowse(makeClient2(), loadConfig2(), { branch: opts.branch, brand });
|
|
483
483
|
if (handled) return;
|
|
484
484
|
}
|
|
@@ -820,8 +820,13 @@ async function runCheckout(client, config, args, deps) {
|
|
|
820
820
|
// fail-closed, no order placed → non-zero (matches the shown exit 1)
|
|
821
821
|
};
|
|
822
822
|
}
|
|
823
|
+
const email = (config.email ?? "").trim();
|
|
824
|
+
const mint = await client.mintCheckout(cartId, email || void 0, "cli");
|
|
825
|
+
const { checkout_url, session_id } = mint;
|
|
826
|
+
const save = email ? { email } : {};
|
|
827
|
+
const currency = mint.currency ?? cart.currency_code ?? region.currency_code;
|
|
823
828
|
const itemCount = cart.items.reduce((n, li) => n + (li.quantity ?? 1), 0);
|
|
824
|
-
const totalLine = fmtPrice(shippedCart?.total ?? cart.total,
|
|
829
|
+
const totalLine = fmtPrice(mint.total ?? shippedCart?.total ?? cart.total, currency);
|
|
825
830
|
const taxIncl = isCartTaxInclusive(cart);
|
|
826
831
|
const reviewLines = [header(style, "bt checkout \u2014 staged for commit")];
|
|
827
832
|
for (const li of cart.items) {
|
|
@@ -831,6 +836,11 @@ async function runCheckout(client, config, args, deps) {
|
|
|
831
836
|
` ${(li.title ?? li.product_title ?? "item").toString()}${colourTag} \xB7 qty ${li.quantity}` + (li.total != null ? ` ${cyan(style, fmtPrice(li.total, cart.currency_code ?? region.currency_code))}` : "")
|
|
832
837
|
);
|
|
833
838
|
}
|
|
839
|
+
if (mint.discount && mint.discount.amount > 0) {
|
|
840
|
+
reviewLines.push(
|
|
841
|
+
dim(style, ` dev channel \u2212${fmtPrice(mint.discount.amount, currency)} (${mint.discount.pct}% \u2014 for shopping the terminal)`)
|
|
842
|
+
);
|
|
843
|
+
}
|
|
834
844
|
reviewLines.push(` total ${cyan(style, totalLine)}${taxSuffix(taxIncl)}`);
|
|
835
845
|
const print = deps.print ?? ((line) => process.stdout.write(line + "\n"));
|
|
836
846
|
for (const line of reviewLines) {
|
|
@@ -849,9 +859,6 @@ async function runCheckout(client, config, args, deps) {
|
|
|
849
859
|
}
|
|
850
860
|
const allowed = supportedCountries(region);
|
|
851
861
|
const shipsTo = (allowed[0] ?? "").toUpperCase();
|
|
852
|
-
const email = (config.email ?? "").trim();
|
|
853
|
-
const { checkout_url, session_id } = await client.mintCheckout(cartId, email || void 0, "cli");
|
|
854
|
-
const save = email ? { email } : {};
|
|
855
862
|
const opened = await deps.open(checkout_url);
|
|
856
863
|
for (const line of opened.lines) {
|
|
857
864
|
print(line);
|
|
@@ -884,6 +891,9 @@ async function runCheckout(client, config, args, deps) {
|
|
|
884
891
|
lines.push(ok("deploy successful."));
|
|
885
892
|
lines.push(` committed to wardrobe@main`);
|
|
886
893
|
lines.push(` order #${displayId}`);
|
|
894
|
+
if (mint.discount && mint.discount.amount > 0) {
|
|
895
|
+
lines.push(dim(style, ` dev channel \u2212${fmtPrice(mint.discount.amount, currency)} (${mint.discount.pct}% \u2014 the terminal's cut for you)`));
|
|
896
|
+
}
|
|
887
897
|
lines.push(` total ${cyan(style, totalLine)}${taxIncl ? " (incl. VAT)" : ""}`);
|
|
888
898
|
if (shipsTo) {
|
|
889
899
|
lines.push(` ships to ${shipsTo} \xB7 ~3\u20136 working days`);
|
|
@@ -901,10 +911,11 @@ async function runCheckout(client, config, args, deps) {
|
|
|
901
911
|
status: "placed",
|
|
902
912
|
order_id: outcome.order_id,
|
|
903
913
|
display_id: displayId,
|
|
904
|
-
// A2 — the SHIPPING-INCLUSIVE total the buyer consented to (same
|
|
905
|
-
// so a --json / bt buy consumer has the real amount, not just a status.
|
|
906
|
-
total: shippedCart?.total ?? cart.total ?? null,
|
|
907
|
-
currency: cart.currency_code ?? region.currency_code ?? null
|
|
914
|
+
// A2 — the SHIPPING-INCLUSIVE, dev-channel-discounted total the buyer consented to (same
|
|
915
|
+
// figure as the review), so a --json / bt buy consumer has the real amount, not just a status.
|
|
916
|
+
total: mint.total ?? shippedCart?.total ?? cart.total ?? null,
|
|
917
|
+
currency: mint.currency ?? cart.currency_code ?? region.currency_code ?? null,
|
|
918
|
+
discount: mint.discount ?? null
|
|
908
919
|
} : void 0
|
|
909
920
|
};
|
|
910
921
|
}
|
|
@@ -1348,52 +1359,31 @@ function registerUnstage(program, makeClient2, loadConfig2) {
|
|
|
1348
1359
|
}
|
|
1349
1360
|
|
|
1350
1361
|
// src/commands/whoami.ts
|
|
1351
|
-
var
|
|
1352
|
-
contributor: { at: 5, name: "maintainer", pct: 10 },
|
|
1353
|
-
maintainer: { at: 20, name: "core", pct: 15 },
|
|
1354
|
-
core: { at: 0, name: "core", pct: 20 }
|
|
1355
|
-
};
|
|
1362
|
+
var DEV_CHANNEL_PCT = 10;
|
|
1356
1363
|
var GRAPH_CAP = 20;
|
|
1357
1364
|
var CARD_WIDTH = 58;
|
|
1358
1365
|
function profileCard(p, style, handle) {
|
|
1359
|
-
const tier = p.bt_tier ?? "contributor";
|
|
1360
1366
|
const commits = p.bt_commit_count ?? 0;
|
|
1361
|
-
const next = NEXT_TIER[tier];
|
|
1362
|
-
const isMax = tier === "core" || !next;
|
|
1363
|
-
const toNext = next && !isMax ? Math.max(0, next.at - commits) : 0;
|
|
1364
|
-
const standing = p.standing_pct ?? NEXT_TIER[tier]?.pct ?? null;
|
|
1365
1367
|
const inner = [];
|
|
1366
|
-
inner.push(`${handle ? `${handle} \xB7 ` : ""}${cyan(style,
|
|
1368
|
+
inner.push(`${handle ? `${handle} \xB7 ` : ""}${cyan(style, "terminal")}`);
|
|
1367
1369
|
inner.push(rule(CARD_WIDTH - 1));
|
|
1368
|
-
if (isMax) {
|
|
1369
|
-
inner.push(`tier ${tier.padEnd(13)}max standing \u2014 ${standing ?? 20}%`);
|
|
1370
|
-
} else {
|
|
1371
|
-
inner.push(`tier ${tier.padEnd(13)}${toNext} more commit${toNext === 1 ? "" : "s"} to ${next.name}`);
|
|
1372
|
-
}
|
|
1373
1370
|
if (commits === 0) {
|
|
1374
|
-
inner.push(`
|
|
1371
|
+
inner.push(`orders ${String(commits).padEnd(13)}your repo's empty \u2014 everyone starts at 0`);
|
|
1375
1372
|
} else {
|
|
1376
|
-
inner.push(`
|
|
1377
|
-
}
|
|
1378
|
-
if (standing != null) {
|
|
1379
|
-
inner.push(`standing ${cyan(style, `${standing}%`.padEnd(13))}applied at every commit`);
|
|
1373
|
+
inner.push(`orders ${String(commits).padEnd(13)}committed`);
|
|
1380
1374
|
}
|
|
1375
|
+
inner.push(`discount ${cyan(style, `${DEV_CHANNEL_PCT}%`.padEnd(13))}off every order \u2014 for shopping the terminal`);
|
|
1381
1376
|
const bar = contributionBar(style, commits, GRAPH_CAP);
|
|
1382
1377
|
const graphLabel = commits === 0 ? "no commits yet" : `${commits} contribution${commits === 1 ? "" : "s"}`;
|
|
1383
1378
|
inner.push(`graph ${bar} ${graphLabel}`);
|
|
1384
|
-
if (p.bt_badges && p.bt_badges.length > 0) {
|
|
1385
|
-
inner.push(`badges ${p.bt_badges.join(" \xB7 ")}`);
|
|
1386
|
-
}
|
|
1387
1379
|
if (p.bt_connected_at) {
|
|
1388
|
-
inner.push(`since
|
|
1380
|
+
inner.push(`since connected ${p.bt_connected_at.slice(0, 10)}`);
|
|
1389
1381
|
}
|
|
1390
1382
|
inner.push(rule(CARD_WIDTH - 1));
|
|
1391
|
-
if (
|
|
1392
|
-
inner.push(`in ${green(style, "AUTHORS")}. earned, not bought.`);
|
|
1393
|
-
} else if (commits === 0) {
|
|
1383
|
+
if (commits === 0) {
|
|
1394
1384
|
inner.push("your first commit makes this worth screenshotting \u2192 bt browse");
|
|
1395
1385
|
} else {
|
|
1396
|
-
inner.push(
|
|
1386
|
+
inner.push(`in ${green(style, "AUTHORS")}. earned, not bought.`);
|
|
1397
1387
|
}
|
|
1398
1388
|
return box(inner, { width: CARD_WIDTH, title: "bt whoami", style });
|
|
1399
1389
|
}
|
|
@@ -1414,10 +1404,8 @@ async function runWhoami(client, config, args, token) {
|
|
|
1414
1404
|
lines: profileCard(me, style, handle),
|
|
1415
1405
|
json: {
|
|
1416
1406
|
authenticated: true,
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
badges: me.bt_badges,
|
|
1420
|
-
standing_pct: me.standing_pct ?? null,
|
|
1407
|
+
orders: me.bt_commit_count ?? 0,
|
|
1408
|
+
discount_pct: DEV_CHANNEL_PCT,
|
|
1421
1409
|
connected_at: me.bt_connected_at,
|
|
1422
1410
|
token_expires_at: expiresAt,
|
|
1423
1411
|
token_expired: expired
|
|
@@ -1430,11 +1418,10 @@ async function runWhoami(client, config, args, token) {
|
|
|
1430
1418
|
return {
|
|
1431
1419
|
lines: [
|
|
1432
1420
|
empty("you're browsing as a guest \u2014 not connected yet."),
|
|
1433
|
-
" connect \u2192 bt login (the
|
|
1421
|
+
" connect \u2192 bt login (order history + a persistent cart; the terminal's 10% applies either way)"
|
|
1434
1422
|
],
|
|
1435
1423
|
json: args.json ? {
|
|
1436
1424
|
authenticated: false,
|
|
1437
|
-
tier: null,
|
|
1438
1425
|
connected: false,
|
|
1439
1426
|
token_expires_at: expiresAt,
|
|
1440
1427
|
token_expired: expired
|
|
@@ -1445,7 +1432,7 @@ async function runWhoami(client, config, args, token) {
|
|
|
1445
1432
|
}
|
|
1446
1433
|
}
|
|
1447
1434
|
function registerWhoami(program, makeClient2, loadConfig2) {
|
|
1448
|
-
program.command("whoami").description("your
|
|
1435
|
+
program.command("whoami").description("your profile + order history.").action(async () => {
|
|
1449
1436
|
const { json, brand } = resolveOutput(program);
|
|
1450
1437
|
const res = await runWhoami(makeClient2(), loadConfig2(), { json, brand }, getToken());
|
|
1451
1438
|
printResult(res, json);
|
|
@@ -1505,31 +1492,6 @@ function registerDrops(program, makeClient2, loadConfig2) {
|
|
|
1505
1492
|
});
|
|
1506
1493
|
}
|
|
1507
1494
|
|
|
1508
|
-
// src/commands/connect.ts
|
|
1509
|
-
async function runConnect(args) {
|
|
1510
|
-
const lines = [
|
|
1511
|
-
"connect your wardrobe \u2014 become a contributor.",
|
|
1512
|
-
" connecting authenticates you and unlocks:",
|
|
1513
|
-
" \xB7 10% standing (applied at every commit)",
|
|
1514
|
-
" \xB7 access to next (drops before the web sees them)",
|
|
1515
|
-
" \xB7 your wardrobe repo + the contributor badge",
|
|
1516
|
-
"",
|
|
1517
|
-
" connect now \u2192 bt login",
|
|
1518
|
-
" (we email you a token to paste; it lives in your OS keychain, never in plaintext config.)"
|
|
1519
|
-
];
|
|
1520
|
-
return {
|
|
1521
|
-
lines,
|
|
1522
|
-
json: args.json ? { connected: false, login_command: "bt login" } : void 0
|
|
1523
|
-
};
|
|
1524
|
-
}
|
|
1525
|
-
function registerConnect(program) {
|
|
1526
|
-
program.command("connect").description("the contributor on-ramp \u2014 what connecting unlocks. run bt login to connect.").action(async () => {
|
|
1527
|
-
const { json } = resolveOutput(program);
|
|
1528
|
-
const res = await runConnect({ json });
|
|
1529
|
-
printResult(res, json);
|
|
1530
|
-
});
|
|
1531
|
-
}
|
|
1532
|
-
|
|
1533
1495
|
// src/commands/login.ts
|
|
1534
1496
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1535
1497
|
async function runLogin(client, prompts, keychain, config, args) {
|
|
@@ -1557,7 +1519,7 @@ async function runLogin(client, prompts, keychain, config, args) {
|
|
|
1557
1519
|
}
|
|
1558
1520
|
keychain.setToken(jsonResult.jwt);
|
|
1559
1521
|
return {
|
|
1560
|
-
lines: [ok("authenticated. welcome
|
|
1522
|
+
lines: [ok("authenticated. welcome back.")],
|
|
1561
1523
|
save: { email: jsonEmail },
|
|
1562
1524
|
json: { connected: true, customer_id: jsonResult.customer.id }
|
|
1563
1525
|
};
|
|
@@ -1608,9 +1570,9 @@ async function runLogin(client, prompts, keychain, config, args) {
|
|
|
1608
1570
|
keychain.setToken(result.jwt);
|
|
1609
1571
|
return {
|
|
1610
1572
|
lines: [
|
|
1611
|
-
ok("authenticated. welcome
|
|
1573
|
+
ok("authenticated. welcome back."),
|
|
1612
1574
|
` ${GLYPH.arrow} your token is in your OS keychain (never plaintext).`,
|
|
1613
|
-
` ${GLYPH.arrow}
|
|
1575
|
+
` ${GLYPH.arrow} your profile \u2192 bt whoami \xB7 order history \u2192 bt log`
|
|
1614
1576
|
],
|
|
1615
1577
|
save: { email },
|
|
1616
1578
|
json: args.json ? { connected: true, customer_id: result.customer.id } : void 0
|
|
@@ -1725,20 +1687,24 @@ function runInit(args) {
|
|
|
1725
1687
|
const lines = [
|
|
1726
1688
|
header(style, "bt \u2014 binary & thread, the terminal store"),
|
|
1727
1689
|
" buy heavyweight pieces from your terminal. zero setup \u2014 you're already pointed at the live store.",
|
|
1690
|
+
" shopping here is 10% off the web \u2014 always, applied at checkout. no code, no login.",
|
|
1728
1691
|
"",
|
|
1729
1692
|
" the happy path:",
|
|
1730
1693
|
" bt browse # the catalog, numbered",
|
|
1731
1694
|
" bt stage <n|slug> --size L # add to your cart (a browse number, or a slug)",
|
|
1732
|
-
" bt checkout # pay in your browser \u2014 cards never touch the terminal",
|
|
1695
|
+
" bt checkout # pay in your browser \u2014 cards never touch the terminal (10% applied)",
|
|
1696
|
+
"",
|
|
1697
|
+
" ships worldwide \u2014 set your country so prices show your currency:",
|
|
1698
|
+
" bt region <cc> # e.g. se / us / de \xB7 see all \u2192 bt region --list",
|
|
1733
1699
|
"",
|
|
1734
1700
|
" optional:",
|
|
1735
|
-
" bt login #
|
|
1701
|
+
" bt login # order history + a persistent cart",
|
|
1736
1702
|
" bt whoami # your profile",
|
|
1737
1703
|
` docs \u2192 ${DOCS_URL}`
|
|
1738
1704
|
];
|
|
1739
1705
|
return {
|
|
1740
1706
|
lines,
|
|
1741
|
-
json: args.json ? { happy_path: HAPPY_PATH, docs: DOCS_URL, zero_setup: true } : void 0
|
|
1707
|
+
json: args.json ? { happy_path: HAPPY_PATH, docs: DOCS_URL, zero_setup: true, dev_channel_discount_pct: 10 } : void 0
|
|
1742
1708
|
};
|
|
1743
1709
|
}
|
|
1744
1710
|
function registerInit(program) {
|
|
@@ -2066,7 +2032,6 @@ function registerCommands(program) {
|
|
|
2066
2032
|
registerStatus(program, makeClient, effectiveConfig);
|
|
2067
2033
|
registerWhoami(program, makeClient, effectiveConfig);
|
|
2068
2034
|
registerDrops(program, makeClient, effectiveConfig);
|
|
2069
|
-
registerConnect(program);
|
|
2070
2035
|
registerUnstage(program, makeClient, effectiveConfig);
|
|
2071
2036
|
const prompts = makePrompts();
|
|
2072
2037
|
registerLogin(
|