@binaryandthread/cli 0.4.11 → 0.4.13
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/README.md +2 -2
- package/dist/bin.js +71 -13
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-T7MFWTB7.js → chunk-IUN3OOYY.js} +6 -2
- package/dist/chunk-IUN3OOYY.js.map +1 -0
- package/dist/{chunk-UTSTDWKZ.js → chunk-ZRHSCMBQ.js} +91 -41
- package/dist/chunk-ZRHSCMBQ.js.map +1 -0
- package/dist/{config-L4X7G563.js → config-PWI2G2O5.js} +2 -2
- package/dist/{interactive-UM5FCZDG.js → interactive-JONAXMTQ.js} +6 -4
- package/dist/interactive-JONAXMTQ.js.map +1 -0
- package/man/bt.1 +1 -1
- package/package.json +1 -1
- package/dist/chunk-T7MFWTB7.js.map +0 -1
- package/dist/chunk-UTSTDWKZ.js.map +0 -1
- package/dist/interactive-UM5FCZDG.js.map +0 -1
- /package/dist/{config-L4X7G563.js.map → config-PWI2G2O5.js.map} +0 -0
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ Listing them would defeat the point.
|
|
|
58
58
|
| `bt browse` | the catalog as a numbered table (`bt stage <n>`); `--pick` opts into the ↑/↓ picker; `--json` for scripts |
|
|
59
59
|
| `bt search <q>` | filter the catalog |
|
|
60
60
|
| `bt view <n\|slug>` | one piece, specs + mockup (`--colour black` renders the black row; `--fit oversize` shows the other fit of a two-fit design) |
|
|
61
|
-
| `bt stage <n\|slug>` | add to your cart (`--size`, `--colour`, `--fit regular\|oversize`; a design sold in both fits needs `--fit`, or `bt config set defaultFit
|
|
61
|
+
| `bt stage <n\|slug>` | add to your cart (`--size`, `--colour`, `--fit regular\|oversize`; `--size` is required unless `bt config set defaultSize M`; a design sold in both fits needs `--fit`, or `bt config set defaultFit …`; one design per command, a two-word colour is `--colour coal` or quoted) |
|
|
62
62
|
| `bt blame <n\|slug>` | the design's lore + sources (git blame, for motifs) |
|
|
63
63
|
| `bt cart` / `bt unstage <ref>` | show / remove a line |
|
|
64
64
|
| `bt checkout` | mint a checkout, hand off to the browser to pay, then poll |
|
|
@@ -111,7 +111,7 @@ skips the interactive confirm so it never hangs in CI. Field shapes (stable, saf
|
|
|
111
111
|
| --- | --- |
|
|
112
112
|
| `bt browse` / `bt search` | `[{ id, handle, title, price, price_from, currency, colours[], fits[], channel_stage }]` (`price` is the cheapest fit when `price_from`) |
|
|
113
113
|
| `bt view <handle>` | `{ id, handle, title, fits[], fit, colours[], unavailable_colours[], specs, variants: [{ id, fit, colour, size, price, currency }] }` |
|
|
114
|
-
| `bt cart` | `{ cart_id, items: [{ id, title, colour, qty, total }], total, total_excludes_shipping }` |
|
|
114
|
+
| `bt cart` | `{ cart_id, items: [{ id, title, colour, qty, total }], total, total_excludes_shipping }`; a cart that became an order answers `{ cart_id: null, items: [], completed: true }` and clears the saved id |
|
|
115
115
|
| `bt checkout` | `{ status: "placed"\|"timeout"\|"expired", order_id?, display_id?, total?, currency?, checkout_url? }` |
|
|
116
116
|
| `bt region` | `{ region, currency, matched, home }` · `--list` → `{ regions: [{ currency, countries[] }] }` |
|
|
117
117
|
| `bt whoami` | `{ authenticated, tier, commits, standing_pct, token_expires_at, token_expired }` |
|
package/dist/bin.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
forgetConfig,
|
|
6
6
|
loadConfig,
|
|
7
7
|
saveConfig
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-IUN3OOYY.js";
|
|
9
9
|
import {
|
|
10
10
|
makePrompts
|
|
11
11
|
} from "./chunk-AAN4VWP3.js";
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
labelVariantTitle,
|
|
39
39
|
lineColour,
|
|
40
40
|
ok,
|
|
41
|
+
oneDesignPerCommand,
|
|
41
42
|
orderStage,
|
|
42
43
|
priceLine,
|
|
43
44
|
printResult,
|
|
@@ -58,7 +59,7 @@ import {
|
|
|
58
59
|
versionLine,
|
|
59
60
|
warn,
|
|
60
61
|
working
|
|
61
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-ZRHSCMBQ.js";
|
|
62
63
|
import {
|
|
63
64
|
__require
|
|
64
65
|
} from "./chunk-7OCVIDC7.js";
|
|
@@ -107,7 +108,7 @@ function makeLogger(debug, write = (s) => process.stderr.write(s)) {
|
|
|
107
108
|
}
|
|
108
109
|
|
|
109
110
|
// src/version.ts
|
|
110
|
-
var VERSION = "0.4.
|
|
111
|
+
var VERSION = "0.4.13";
|
|
111
112
|
|
|
112
113
|
// src/eggs.ts
|
|
113
114
|
function teapot() {
|
|
@@ -195,7 +196,7 @@ function manPage(version) {
|
|
|
195
196
|
" init first-run welcome + the happy path",
|
|
196
197
|
" browse list what's in stock",
|
|
197
198
|
" view render one piece (image or ASCII) + specs",
|
|
198
|
-
" stage reserve stock (like git add)",
|
|
199
|
+
" stage reserve stock (like git add); --size required unless bt config set defaultSize",
|
|
199
200
|
" commit turn your staged items into an order",
|
|
200
201
|
" buy stage + commit in one",
|
|
201
202
|
" log your order history as a git log (--graph, --oneline)",
|
|
@@ -527,7 +528,7 @@ function registerBrowse(program, makeClient2, loadConfig2) {
|
|
|
527
528
|
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) => {
|
|
528
529
|
const { json, brand } = resolveOutput(program);
|
|
529
530
|
if (opts.pick && !json && brand.color && process.stdout.isTTY && process.stdin.isTTY) {
|
|
530
|
-
const { runInteractiveBrowse } = await import("./interactive-
|
|
531
|
+
const { runInteractiveBrowse } = await import("./interactive-JONAXMTQ.js");
|
|
531
532
|
const handled = await runInteractiveBrowse(makeClient2(), loadConfig2(), { branch: opts.branch, brand });
|
|
532
533
|
if (handled) return;
|
|
533
534
|
}
|
|
@@ -730,6 +731,7 @@ function registerSearch(program, makeClient2, loadConfig2) {
|
|
|
730
731
|
|
|
731
732
|
// src/commands/cart.ts
|
|
732
733
|
var EMPTY_STATE = "no commits yet. your wardrobe is a fresh repo.";
|
|
734
|
+
var COMMITTED_LINE = "that cart was committed as an order, so it is no longer yours to edit.";
|
|
733
735
|
async function runCart(client, config, args) {
|
|
734
736
|
if (!config.cart_id) {
|
|
735
737
|
return {
|
|
@@ -740,6 +742,14 @@ async function runCart(client, config, args) {
|
|
|
740
742
|
const style = brandOf(args);
|
|
741
743
|
try {
|
|
742
744
|
const cart = await client.getCart(config.cart_id);
|
|
745
|
+
if (cart.completed_at) {
|
|
746
|
+
return {
|
|
747
|
+
lines: [warn(COMMITTED_LINE), empty(EMPTY_STATE), " start one \u2192 bt browse"],
|
|
748
|
+
// the id is dead: clear it, so the next bt stage starts a fresh cart without a detour
|
|
749
|
+
save: { cart_id: null },
|
|
750
|
+
json: args.json ? { cart_id: null, items: [], completed: true } : void 0
|
|
751
|
+
};
|
|
752
|
+
}
|
|
743
753
|
const lines = [];
|
|
744
754
|
if (!cart.items || cart.items.length === 0) {
|
|
745
755
|
lines.push(empty(EMPTY_STATE));
|
|
@@ -795,6 +805,10 @@ function registerCart(program, makeClient2, loadConfig2) {
|
|
|
795
805
|
program.command("cart").description("show your current cart \u2014 the authoritative server state.").action(async () => {
|
|
796
806
|
const { json, brand } = resolveOutput(program);
|
|
797
807
|
const res = await runCart(makeClient2(), loadConfig2(), { json, brand });
|
|
808
|
+
if (res.save) {
|
|
809
|
+
const { saveConfig: saveConfig2 } = await import("./config-PWI2G2O5.js");
|
|
810
|
+
saveConfig2(res.save);
|
|
811
|
+
}
|
|
798
812
|
printResult(res, json);
|
|
799
813
|
});
|
|
800
814
|
}
|
|
@@ -815,6 +829,14 @@ function heartbeatLine(attempt, opts = {}) {
|
|
|
815
829
|
`still waiting for the browser hand-off, ${elapsedS}s in. ctrl-c is safe; resume with bt checkout --resume`
|
|
816
830
|
);
|
|
817
831
|
}
|
|
832
|
+
function committedResult(args) {
|
|
833
|
+
return {
|
|
834
|
+
lines: [warn(COMMITTED_LINE), " see the order \u2192 bt log"],
|
|
835
|
+
save: { cart_id: null },
|
|
836
|
+
json: args.json ? { status: "completed", cart_id: null } : void 0,
|
|
837
|
+
exitCode: 0
|
|
838
|
+
};
|
|
839
|
+
}
|
|
818
840
|
async function runCheckout(client, config, args, deps) {
|
|
819
841
|
const cartId = config.cart_id;
|
|
820
842
|
if (!cartId) {
|
|
@@ -847,6 +869,9 @@ async function runCheckout(client, config, args, deps) {
|
|
|
847
869
|
}
|
|
848
870
|
throw e;
|
|
849
871
|
}
|
|
872
|
+
if (cart.completed_at) {
|
|
873
|
+
return committedResult(args);
|
|
874
|
+
}
|
|
850
875
|
if (!cart.items || cart.items.length === 0) {
|
|
851
876
|
return {
|
|
852
877
|
lines: [
|
|
@@ -886,7 +911,15 @@ async function runCheckout(client, config, args, deps) {
|
|
|
886
911
|
};
|
|
887
912
|
}
|
|
888
913
|
const email = (config.email ?? "").trim();
|
|
889
|
-
|
|
914
|
+
let mint;
|
|
915
|
+
try {
|
|
916
|
+
mint = await client.mintCheckout(cartId, email || void 0, "cli");
|
|
917
|
+
} catch (e) {
|
|
918
|
+
if (e instanceof StoreApiError && e.status === 409) {
|
|
919
|
+
return committedResult(args);
|
|
920
|
+
}
|
|
921
|
+
throw e;
|
|
922
|
+
}
|
|
890
923
|
const { checkout_url, session_id } = mint;
|
|
891
924
|
const save = email ? { email } : {};
|
|
892
925
|
const currency = mint.currency ?? cart.currency_code ?? region.currency_code;
|
|
@@ -965,7 +998,7 @@ async function runCheckout(client, config, args, deps) {
|
|
|
965
998
|
}
|
|
966
999
|
const lines = [];
|
|
967
1000
|
if (outcome.status === "placed") {
|
|
968
|
-
const displayId = await resolveDisplayId(client, outcome.order_id, email);
|
|
1001
|
+
const displayId = outcome.summary?.display_id ?? await resolveDisplayId(client, outcome.order_id, email);
|
|
969
1002
|
lines.push("");
|
|
970
1003
|
lines.push(ok("deploy successful."));
|
|
971
1004
|
lines.push(` committed to wardrobe@main`);
|
|
@@ -976,7 +1009,7 @@ async function runCheckout(client, config, args, deps) {
|
|
|
976
1009
|
if (settled?.discount_total) {
|
|
977
1010
|
const codes = settled.discount_codes.length ? ` (${settled.discount_codes.join(", ")})` : "";
|
|
978
1011
|
lines.push(dim(style, ` discount${codes} \u2212${fmtPrice(settled.discount_total, finalCurrency)}`));
|
|
979
|
-
} else if (mint.discount && mint.discount.amount > 0) {
|
|
1012
|
+
} else if (!settled && mint.discount && mint.discount.amount > 0) {
|
|
980
1013
|
lines.push(dim(style, ` dev channel \u2212${fmtPrice(mint.discount.amount, currency)} (${mint.discount.pct}% \u2014 the terminal's cut for you)`));
|
|
981
1014
|
}
|
|
982
1015
|
lines.push(` total ${cyan(style, fmtPrice(finalTotal, finalCurrency))}${taxIncl ? " (incl. VAT)" : ""}`);
|
|
@@ -991,7 +1024,9 @@ async function runCheckout(client, config, args, deps) {
|
|
|
991
1024
|
}
|
|
992
1025
|
return {
|
|
993
1026
|
lines,
|
|
994
|
-
|
|
1027
|
+
// TB252 (plan-check 2): the cart is an order now, so its id leaves the config. Left behind, it made
|
|
1028
|
+
// `bt cart` list the paid items as still staged.
|
|
1029
|
+
save: { ...save, cart_id: null },
|
|
995
1030
|
json: args.json ? {
|
|
996
1031
|
status: "placed",
|
|
997
1032
|
order_id: outcome.order_id,
|
|
@@ -1036,6 +1071,9 @@ async function resolveDisplayId(client, orderId, email) {
|
|
|
1036
1071
|
if (!orderId) {
|
|
1037
1072
|
return "\u2014";
|
|
1038
1073
|
}
|
|
1074
|
+
if (!email) {
|
|
1075
|
+
return orderId;
|
|
1076
|
+
}
|
|
1039
1077
|
try {
|
|
1040
1078
|
const looked = await client.getOrder(orderId, email);
|
|
1041
1079
|
const display = looked?.order?.display_id ?? looked?.display_id;
|
|
@@ -1060,7 +1098,7 @@ function registerCheckout(program, makeClient2, loadConfig2) {
|
|
|
1060
1098
|
const { makePrompts: makePrompts2 } = await import("./prompts-DDVV5RE6.js");
|
|
1061
1099
|
const { openCheckout } = await import("./browser-WCNC4AWS.js");
|
|
1062
1100
|
const { pollUntilPlaced } = await import("./poll-II3TVJLK.js");
|
|
1063
|
-
const { saveConfig: saveConfig2 } = await import("./config-
|
|
1101
|
+
const { saveConfig: saveConfig2 } = await import("./config-PWI2G2O5.js");
|
|
1064
1102
|
const client = makeClient2();
|
|
1065
1103
|
const print = json ? () => {
|
|
1066
1104
|
} : (line) => process.stdout.write(line + "\n");
|
|
@@ -1314,6 +1352,13 @@ async function runStatus(client, config, args) {
|
|
|
1314
1352
|
const style = brandOf(args);
|
|
1315
1353
|
try {
|
|
1316
1354
|
const cart = await client.getCart(config.cart_id);
|
|
1355
|
+
if (cart.completed_at) {
|
|
1356
|
+
return {
|
|
1357
|
+
lines: ["on branch main", warn(COMMITTED_LINE), empty(FRESH_REPO), " nothing staged. clean tree \u2192 bt browse"],
|
|
1358
|
+
save: { cart_id: null },
|
|
1359
|
+
json: args.json ? { branch: "main", staged: [], clean: true, completed: true } : void 0
|
|
1360
|
+
};
|
|
1361
|
+
}
|
|
1317
1362
|
const items = cart.items ?? [];
|
|
1318
1363
|
const lines = ["on branch main"];
|
|
1319
1364
|
if (items.length === 0) {
|
|
@@ -1352,6 +1397,10 @@ function registerStatus(program, makeClient2, loadConfig2) {
|
|
|
1352
1397
|
program.command("status").description("working-tree state: what's staged, what's in flight.").action(async () => {
|
|
1353
1398
|
const { json, brand } = resolveOutput(program);
|
|
1354
1399
|
const res = await runStatus(makeClient2(), loadConfig2(), { json, brand });
|
|
1400
|
+
if (res.save) {
|
|
1401
|
+
const { saveConfig: saveConfig2 } = await import("./config-PWI2G2O5.js");
|
|
1402
|
+
saveConfig2(res.save);
|
|
1403
|
+
}
|
|
1355
1404
|
printResult(res, json);
|
|
1356
1405
|
});
|
|
1357
1406
|
}
|
|
@@ -1811,6 +1860,7 @@ async function runBuy(client, config, args, deps) {
|
|
|
1811
1860
|
if (!cartId) {
|
|
1812
1861
|
return staged;
|
|
1813
1862
|
}
|
|
1863
|
+
deps.saveConfig(staged.save);
|
|
1814
1864
|
const checked = await runCheckout(
|
|
1815
1865
|
client,
|
|
1816
1866
|
{ ...config, cart_id: cartId },
|
|
@@ -1827,12 +1877,16 @@ async function runBuy(client, config, args, deps) {
|
|
|
1827
1877
|
};
|
|
1828
1878
|
}
|
|
1829
1879
|
function registerBuy(program, makeClient2, loadConfig2) {
|
|
1830
|
-
program.command("buy").argument("<handle>", "the design: a slug, a bt browse number (3), or a fuzzy hint (termnl)").option("--size <size>", "garment size").option("--colour <colour>", "colour, e.g. white / black").option("--fit <fit>", "regular or oversize (required when a design comes in both)").description("stage + checkout in one \u2014 reserve, then open browser checkout. cards never touch the terminal.").action(async (handle, opts) => {
|
|
1880
|
+
program.command("buy").argument("<handle>", "the design: a slug, a bt browse number (3), or a fuzzy hint (termnl)").option("--size <size>", "garment size (required unless bt config set defaultSize)").option("--colour <colour>", "colour, e.g. white / black").option("--fit <fit>", "regular or oversize (required when a design comes in both)").description("stage + checkout in one \u2014 reserve, then open browser checkout. cards never touch the terminal.").allowExcessArguments().action(async (handle, opts, cmd) => {
|
|
1831
1881
|
const { json, brand } = resolveOutput(program);
|
|
1882
|
+
if (cmd.args.length > 1) {
|
|
1883
|
+
printResult(oneDesignPerCommand(), json);
|
|
1884
|
+
return;
|
|
1885
|
+
}
|
|
1832
1886
|
const { makePrompts: makePrompts2 } = await import("./prompts-DDVV5RE6.js");
|
|
1833
1887
|
const { openCheckout } = await import("./browser-WCNC4AWS.js");
|
|
1834
1888
|
const { pollUntilPlaced } = await import("./poll-II3TVJLK.js");
|
|
1835
|
-
const { saveConfig: saveConfig2 } = await import("./config-
|
|
1889
|
+
const { saveConfig: saveConfig2 } = await import("./config-PWI2G2O5.js");
|
|
1836
1890
|
const client = makeClient2();
|
|
1837
1891
|
const print = json ? () => {
|
|
1838
1892
|
} : (line) => process.stdout.write(line + "\n");
|
|
@@ -1892,7 +1946,7 @@ function runConfig(args, deps) {
|
|
|
1892
1946
|
function registerConfig(program) {
|
|
1893
1947
|
program.command("config").argument("[sub]", "get | set", "get").argument("[key]", "config key").argument("[value]", "value (for set)").description("view or set local prefs (email, region, defaults). the auth token is never stored here.").action(async (sub, key, value) => {
|
|
1894
1948
|
const { json } = resolveOutput(program);
|
|
1895
|
-
const { loadConfig: loadConfig2, saveConfig: saveConfig2 } = await import("./config-
|
|
1949
|
+
const { loadConfig: loadConfig2, saveConfig: saveConfig2 } = await import("./config-PWI2G2O5.js");
|
|
1896
1950
|
const res = runConfig({ sub, key, value, json }, { load: loadConfig2, save: saveConfig2 });
|
|
1897
1951
|
printResult(res, json);
|
|
1898
1952
|
});
|
|
@@ -2059,6 +2113,10 @@ function buildProgram() {
|
|
|
2059
2113
|
"the binary & thread terminal store. techno-minimalist clothing & lifestyle, bought with the ceremony of a deploy.\nprimary invocation: npx @binaryandthread/cli (a bare `bt` may collide with another binary)"
|
|
2060
2114
|
).version(versionLine(VERSION), "-v, --version", "print the version").option("--json", "machine-readable output", false).option("--no-color", "disable ANSI colour + inline images (also honours NO_COLOR)").option("--debug, --verbose", "trace requests to stderr (redacted) \u2014 for bug reports (d15)").option("--region <cc>", "ship-to country for this command (ISO-2, overrides your saved region)").showSuggestionAfterError();
|
|
2061
2115
|
program.addHelpText("beforeAll", "\n bt \u2014 the binary & thread terminal store. new here? \u2192 bt init\n");
|
|
2116
|
+
program.addHelpText(
|
|
2117
|
+
"after",
|
|
2118
|
+
"\nexamples:\n bt browse\n bt stage konami-code --size M --colour coal\n bt buy konami-code --size M --colour coal\n bt stage --help (every command has its own)\n"
|
|
2119
|
+
);
|
|
2062
2120
|
program.command("brew").alias("teapot").argument("[what]", "what to brew").description("we make clothing, not coffee.").action(() => {
|
|
2063
2121
|
process.stdout.write(teapot() + "\n");
|
|
2064
2122
|
});
|