@binaryandthread/cli 0.1.3 → 0.1.4
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 +95 -77
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-IM3HF7NN.js → chunk-AAN4VWP3.js} +2 -2
- package/dist/{chunk-IM3HF7NN.js.map → chunk-AAN4VWP3.js.map} +1 -1
- package/dist/{chunk-7FH7BZ3I.js → chunk-V7YRJ67J.js} +201 -34
- package/dist/chunk-V7YRJ67J.js.map +1 -0
- package/dist/{interactive-DZ67P6UX.js → interactive-GY4AK7D2.js} +2 -2
- package/dist/{prompts-GTC5VYM6.js → prompts-DDVV5RE6.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-7FH7BZ3I.js.map +0 -1
- /package/dist/{interactive-DZ67P6UX.js.map → interactive-GY4AK7D2.js.map} +0 -0
- /package/dist/{prompts-GTC5VYM6.js.map → prompts-DDVV5RE6.js.map} +0 -0
package/dist/bin.js
CHANGED
|
@@ -7,10 +7,11 @@ import {
|
|
|
7
7
|
} from "./chunk-OVG37IIX.js";
|
|
8
8
|
import {
|
|
9
9
|
makePrompts
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-AAN4VWP3.js";
|
|
11
11
|
import {
|
|
12
12
|
BT_DEFAULT_PUBLISHABLE_KEY,
|
|
13
13
|
BT_DEFAULT_STORE_URL,
|
|
14
|
+
EXIT,
|
|
14
15
|
GLYPH,
|
|
15
16
|
RecoverableCartError,
|
|
16
17
|
StoreApiError,
|
|
@@ -27,6 +28,7 @@ import {
|
|
|
27
28
|
firstPrice,
|
|
28
29
|
fmtPrice,
|
|
29
30
|
formatCartLine,
|
|
31
|
+
formatFatal,
|
|
30
32
|
green,
|
|
31
33
|
header,
|
|
32
34
|
lineColour,
|
|
@@ -44,7 +46,7 @@ import {
|
|
|
44
46
|
versionLine,
|
|
45
47
|
warn,
|
|
46
48
|
working
|
|
47
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-V7YRJ67J.js";
|
|
48
50
|
import {
|
|
49
51
|
__require
|
|
50
52
|
} from "./chunk-7OCVIDC7.js";
|
|
@@ -73,7 +75,7 @@ function makeLogger(debug, write = (s) => process.stderr.write(s)) {
|
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
// src/version.ts
|
|
76
|
-
var VERSION = "0.1.
|
|
78
|
+
var VERSION = "0.1.4";
|
|
77
79
|
|
|
78
80
|
// src/eggs.ts
|
|
79
81
|
function teapot() {
|
|
@@ -102,6 +104,21 @@ function rmWardrobe() {
|
|
|
102
104
|
function force() {
|
|
103
105
|
return "--force-pushing to prod, are we. there's no --force here \u2014\n a commit to your wardrobe is already that decisive.";
|
|
104
106
|
}
|
|
107
|
+
function gitClone() {
|
|
108
|
+
return "no clone for a fit \u2014 each one's committed by hand. browse the originals \u2192 bt browse";
|
|
109
|
+
}
|
|
110
|
+
function gitStash() {
|
|
111
|
+
return "that's bt unstage here. your cart holds; nothing's lost.";
|
|
112
|
+
}
|
|
113
|
+
function gitPush() {
|
|
114
|
+
return "no remote for your wardrobe. the only push that ships \u2192 bt commit";
|
|
115
|
+
}
|
|
116
|
+
function gitPull() {
|
|
117
|
+
return "nothing to pull \u2014 the freshest designs land as drops \u2192 bt drops";
|
|
118
|
+
}
|
|
119
|
+
function gitReflog() {
|
|
120
|
+
return "nothing's ever truly lost here. your history \u2192 bt log";
|
|
121
|
+
}
|
|
105
122
|
var FORTUNES = [
|
|
106
123
|
'// "there are only two hard things in computer science: cache invalidation and naming things." \u2014 phil karlton',
|
|
107
124
|
'// "premature optimization is the root of all evil." \u2014 donald knuth',
|
|
@@ -180,50 +197,6 @@ function manPage(version) {
|
|
|
180
197
|
];
|
|
181
198
|
}
|
|
182
199
|
|
|
183
|
-
// src/errors.ts
|
|
184
|
-
var EXIT = {
|
|
185
|
-
OK: 0,
|
|
186
|
-
GENERIC: 1,
|
|
187
|
-
DATAERR: 65,
|
|
188
|
-
// EX_DATAERR — bad request / unprocessable / stale cart (400/409/422)
|
|
189
|
-
UNAVAILABLE: 69,
|
|
190
|
-
// EX_UNAVAILABLE — not found (404)
|
|
191
|
-
TEMPFAIL: 75,
|
|
192
|
-
// EX_TEMPFAIL — temporary: 5xx, network/exhausted, rate-limited (429)
|
|
193
|
-
NOPERM: 77
|
|
194
|
-
// EX_NOPERM — auth required / forbidden (401/403)
|
|
195
|
-
};
|
|
196
|
-
function messageOf(e) {
|
|
197
|
-
if (e instanceof Error && e.message) {
|
|
198
|
-
return e.message;
|
|
199
|
-
}
|
|
200
|
-
const s = String(e ?? "").trim();
|
|
201
|
-
return s || "unexpected error";
|
|
202
|
-
}
|
|
203
|
-
function classifyError(e) {
|
|
204
|
-
const message = String(redact(messageOf(e)));
|
|
205
|
-
if (e instanceof RecoverableCartError) {
|
|
206
|
-
return { code: EXIT.DATAERR, type: "stale_cart", status: e.status, message };
|
|
207
|
-
}
|
|
208
|
-
if (e instanceof StoreApiError) {
|
|
209
|
-
const s = e.status;
|
|
210
|
-
if (s === 401 || s === 403) return { code: EXIT.NOPERM, type: "auth", status: s, message };
|
|
211
|
-
if (s === 404) return { code: EXIT.UNAVAILABLE, type: "not_found", status: s, message };
|
|
212
|
-
if (s === 429) return { code: EXIT.TEMPFAIL, type: "rate_limited", status: s, message };
|
|
213
|
-
if (s === 0 || s === 408 || s >= 500) return { code: EXIT.TEMPFAIL, type: "upstream", status: s, message };
|
|
214
|
-
if (s >= 400) return { code: EXIT.DATAERR, type: "client_error", status: s, message };
|
|
215
|
-
}
|
|
216
|
-
return { code: EXIT.GENERIC, type: "error", message };
|
|
217
|
-
}
|
|
218
|
-
function formatFatal(e, json) {
|
|
219
|
-
const info = classifyError(e);
|
|
220
|
-
if (json) {
|
|
221
|
-
const envelope = { error: { code: info.code, type: info.type, message: info.message } };
|
|
222
|
-
return { out: JSON.stringify(envelope, null, 2), err: null, code: info.code };
|
|
223
|
-
}
|
|
224
|
-
return { out: null, err: `\u2717 ${info.message}`, code: info.code };
|
|
225
|
-
}
|
|
226
|
-
|
|
227
200
|
// src/is-main.ts
|
|
228
201
|
import { realpathSync } from "fs";
|
|
229
202
|
import { fileURLToPath } from "url";
|
|
@@ -312,19 +285,20 @@ function deleteToken(deps = {}) {
|
|
|
312
285
|
}
|
|
313
286
|
|
|
314
287
|
// src/commands/browse.ts
|
|
315
|
-
function productRow(p, stage, style) {
|
|
288
|
+
function productRow(p, index, stage, style) {
|
|
316
289
|
const { amount, currency } = firstPrice(p);
|
|
317
290
|
const { title, handle } = displayName(p);
|
|
318
291
|
const colours = colourMarker(productColours(p));
|
|
292
|
+
const ref = dim(style, `[${index + 1}]`.padEnd(4));
|
|
319
293
|
const parts = [
|
|
320
294
|
title.padEnd(22),
|
|
321
295
|
cyan(style, fmtPrice(amount, currency).padEnd(11)),
|
|
322
|
-
dim(style, handle.padEnd(
|
|
296
|
+
dim(style, handle.padEnd(30)),
|
|
323
297
|
stageMarker(stage)
|
|
324
298
|
];
|
|
325
|
-
const row = parts.join(" ")
|
|
299
|
+
const row = `${ref} ${parts.join(" ")}`.trimEnd();
|
|
326
300
|
return colours ? `${row}
|
|
327
|
-
|
|
301
|
+
${dim(style, colours)}` : row;
|
|
328
302
|
}
|
|
329
303
|
async function runBrowse(client, config, args) {
|
|
330
304
|
const style = brandOf(args);
|
|
@@ -344,9 +318,9 @@ async function runBrowse(client, config, args) {
|
|
|
344
318
|
lines.push(" peek at next \u2192 bt browse --branch=next");
|
|
345
319
|
} else {
|
|
346
320
|
lines.push(header(style, "bt browse \u2014 in stock"));
|
|
347
|
-
|
|
348
|
-
lines.push(productRow(p, stage, style));
|
|
349
|
-
}
|
|
321
|
+
rows.forEach(({ p, stage }, i) => {
|
|
322
|
+
lines.push(productRow(p, i, stage, style));
|
|
323
|
+
});
|
|
350
324
|
for (const d of drops) {
|
|
351
325
|
const dt = (d.title ?? d.handle ?? d.id).toString();
|
|
352
326
|
lines.push(
|
|
@@ -361,7 +335,7 @@ async function runBrowse(client, config, args) {
|
|
|
361
335
|
if (drops.length > 0) {
|
|
362
336
|
lines.push(" on next, before the web \u2192 bt drops");
|
|
363
337
|
}
|
|
364
|
-
lines.push(" view one \u2192 bt view <
|
|
338
|
+
lines.push(" view one \u2192 bt view <n|slug> \xB7 stage one \u2192 bt stage <n|slug> --size L");
|
|
365
339
|
}
|
|
366
340
|
return {
|
|
367
341
|
lines,
|
|
@@ -377,10 +351,10 @@ async function runBrowse(client, config, args) {
|
|
|
377
351
|
};
|
|
378
352
|
}
|
|
379
353
|
function registerBrowse(program, makeClient2, loadConfig2) {
|
|
380
|
-
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("--plain", "force the static table (
|
|
354
|
+
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) => {
|
|
381
355
|
const { json, brand } = resolveOutput(program);
|
|
382
|
-
if (
|
|
383
|
-
const { runInteractiveBrowse } = await import("./interactive-
|
|
356
|
+
if (opts.pick && !json && brand.color && process.stdout.isTTY && process.stdin.isTTY) {
|
|
357
|
+
const { runInteractiveBrowse } = await import("./interactive-GY4AK7D2.js");
|
|
384
358
|
const handled = await runInteractiveBrowse(makeClient2(), loadConfig2(), { branch: opts.branch, brand });
|
|
385
359
|
if (handled) return;
|
|
386
360
|
}
|
|
@@ -497,6 +471,18 @@ function registerCart(program, makeClient2, loadConfig2) {
|
|
|
497
471
|
function supportedCountries(region) {
|
|
498
472
|
return (region.countries ?? []).map((c) => (c.iso_2 ?? "").toLowerCase()).filter((c) => c.length > 0);
|
|
499
473
|
}
|
|
474
|
+
var HEARTBEAT_EVERY_TICKS = 6;
|
|
475
|
+
function heartbeatLine(attempt, opts = {}) {
|
|
476
|
+
const everyTicks = opts.everyTicks ?? HEARTBEAT_EVERY_TICKS;
|
|
477
|
+
if (attempt <= 1 || (attempt - 1) % everyTicks !== 0) {
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
const intervalMs = opts.intervalMs ?? 5e3;
|
|
481
|
+
const elapsedS = Math.round((attempt - 1) * intervalMs / 1e3);
|
|
482
|
+
return working(
|
|
483
|
+
`still waiting for the browser hand-off, ${elapsedS}s in. ctrl-c is safe; resume with bt checkout --resume`
|
|
484
|
+
);
|
|
485
|
+
}
|
|
500
486
|
async function runCheckout(client, config, args, deps) {
|
|
501
487
|
const cartId = config.cart_id;
|
|
502
488
|
if (!cartId) {
|
|
@@ -562,7 +548,9 @@ async function runCheckout(client, config, args, deps) {
|
|
|
562
548
|
what: "couldn't attach a shipping method to your cart.",
|
|
563
549
|
fix: "this region may not have shipping configured yet \u2014 try again shortly, or re-stage."
|
|
564
550
|
})
|
|
565
|
-
]
|
|
551
|
+
],
|
|
552
|
+
exitCode: EXIT.GENERIC
|
|
553
|
+
// fail-closed, no order placed → non-zero (matches the shown exit 1)
|
|
566
554
|
};
|
|
567
555
|
}
|
|
568
556
|
const itemCount = cart.items.reduce((n, li) => n + (li.quantity ?? 1), 0);
|
|
@@ -616,7 +604,9 @@ async function runCheckout(client, config, args, deps) {
|
|
|
616
604
|
link: checkout_url
|
|
617
605
|
})
|
|
618
606
|
],
|
|
619
|
-
save
|
|
607
|
+
save,
|
|
608
|
+
exitCode: EXIT.TEMPFAIL
|
|
609
|
+
// lost the connection mid-poll → not confirmed → non-zero (75)
|
|
620
610
|
};
|
|
621
611
|
}
|
|
622
612
|
const lines = [];
|
|
@@ -648,7 +638,7 @@ async function runCheckout(client, config, args, deps) {
|
|
|
648
638
|
warn("your stage expired before checkout completed. nothing was charged.")
|
|
649
639
|
);
|
|
650
640
|
lines.push(" re-stage \u2192 bt stage <slug> then bt checkout");
|
|
651
|
-
return { lines, save, json: args.json ? { status: "expired" } : void 0 };
|
|
641
|
+
return { lines, save, json: args.json ? { status: "expired" } : void 0, exitCode: EXIT.TEMPFAIL };
|
|
652
642
|
}
|
|
653
643
|
lines.push("");
|
|
654
644
|
lines.push(
|
|
@@ -660,7 +650,13 @@ async function runCheckout(client, config, args, deps) {
|
|
|
660
650
|
link: checkout_url
|
|
661
651
|
})
|
|
662
652
|
);
|
|
663
|
-
return {
|
|
653
|
+
return {
|
|
654
|
+
lines,
|
|
655
|
+
save,
|
|
656
|
+
json: args.json ? { status: "timeout", checkout_url } : void 0,
|
|
657
|
+
exitCode: EXIT.TEMPFAIL
|
|
658
|
+
// handoff timed out → not placed → non-zero (matches the shown exit 75)
|
|
659
|
+
};
|
|
664
660
|
}
|
|
665
661
|
async function resolveDisplayId(client, orderId, email) {
|
|
666
662
|
if (!orderId) {
|
|
@@ -687,11 +683,13 @@ function maskEmail(email) {
|
|
|
687
683
|
function registerCheckout(program, makeClient2, loadConfig2) {
|
|
688
684
|
const action = async (opts) => {
|
|
689
685
|
const { json, brand } = resolveOutput(program);
|
|
690
|
-
const { makePrompts: makePrompts2 } = await import("./prompts-
|
|
686
|
+
const { makePrompts: makePrompts2 } = await import("./prompts-DDVV5RE6.js");
|
|
691
687
|
const { openCheckout } = await import("./browser-EO5EQUXQ.js");
|
|
692
688
|
const { pollUntilPlaced } = await import("./poll-O3VUD5WV.js");
|
|
693
689
|
const { saveConfig: saveConfig2 } = await import("./config-FXGCWC6Y.js");
|
|
694
690
|
const client = makeClient2();
|
|
691
|
+
const print = json ? () => {
|
|
692
|
+
} : (line) => process.stdout.write(line + "\n");
|
|
695
693
|
const res = await runCheckout(
|
|
696
694
|
client,
|
|
697
695
|
loadConfig2(),
|
|
@@ -699,11 +697,16 @@ function registerCheckout(program, makeClient2, loadConfig2) {
|
|
|
699
697
|
{
|
|
700
698
|
prompts: makePrompts2(),
|
|
701
699
|
open: (url) => openCheckout(url),
|
|
702
|
-
|
|
700
|
+
// Heartbeat the browser-hop wait so the terminal never looks hung (a dim, calm line every
|
|
701
|
+
// ~30s). Suppressed under --json (print is a no-op there).
|
|
702
|
+
poll: (sessionId) => pollUntilPlaced(client, sessionId, {
|
|
703
|
+
onTick: (attempt) => {
|
|
704
|
+
const line = heartbeatLine(attempt);
|
|
705
|
+
if (line) print(dim(brand, line));
|
|
706
|
+
}
|
|
707
|
+
}),
|
|
703
708
|
saveConfig: saveConfig2,
|
|
704
|
-
|
|
705
|
-
print: json ? () => {
|
|
706
|
-
} : (line) => process.stdout.write(line + "\n")
|
|
709
|
+
print
|
|
707
710
|
}
|
|
708
711
|
);
|
|
709
712
|
if (res.save && Object.keys(res.save).length > 0) {
|
|
@@ -1424,8 +1427,8 @@ function runInit(args) {
|
|
|
1424
1427
|
" buy heavyweight pieces from your terminal. zero setup \u2014 you're already pointed at the live store.",
|
|
1425
1428
|
"",
|
|
1426
1429
|
" the happy path:",
|
|
1427
|
-
" bt browse # the catalog
|
|
1428
|
-
" bt stage <
|
|
1430
|
+
" bt browse # the catalog, numbered",
|
|
1431
|
+
" bt stage <n|slug> --size L # add to your cart (a browse number, or a slug)",
|
|
1429
1432
|
" bt checkout # pay in your browser \u2014 cards never touch the terminal",
|
|
1430
1433
|
"",
|
|
1431
1434
|
" optional:",
|
|
@@ -1467,24 +1470,34 @@ async function runBuy(client, config, args, deps) {
|
|
|
1467
1470
|
return {
|
|
1468
1471
|
lines: [...staged.lines, "", ...checked.lines],
|
|
1469
1472
|
save: { ...staged.save ?? {}, ...checked.save ?? {} },
|
|
1470
|
-
json: args.json ? { cart_id: cartId, checkout: checked.json ?? null } : void 0
|
|
1473
|
+
json: args.json ? { cart_id: cartId, checkout: checked.json ?? null } : void 0,
|
|
1474
|
+
// forward the checkout outcome's exit code — bt buy runs the SAME money-path poll as bt
|
|
1475
|
+
// checkout, so a timed-out/failed composed checkout must not report success (d10).
|
|
1476
|
+
exitCode: checked.exitCode
|
|
1471
1477
|
};
|
|
1472
1478
|
}
|
|
1473
1479
|
function registerBuy(program, makeClient2, loadConfig2) {
|
|
1474
|
-
program.command("buy").argument("<handle>", "the
|
|
1480
|
+
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").description("stage + checkout in one \u2014 reserve, then open browser checkout. cards never touch the terminal.").action(async (handle, opts) => {
|
|
1475
1481
|
const { json, brand } = resolveOutput(program);
|
|
1476
|
-
const { makePrompts: makePrompts2 } = await import("./prompts-
|
|
1482
|
+
const { makePrompts: makePrompts2 } = await import("./prompts-DDVV5RE6.js");
|
|
1477
1483
|
const { openCheckout } = await import("./browser-EO5EQUXQ.js");
|
|
1478
1484
|
const { pollUntilPlaced } = await import("./poll-O3VUD5WV.js");
|
|
1479
1485
|
const { saveConfig: saveConfig2 } = await import("./config-FXGCWC6Y.js");
|
|
1480
1486
|
const client = makeClient2();
|
|
1487
|
+
const print = json ? () => {
|
|
1488
|
+
} : (line) => process.stdout.write(line + "\n");
|
|
1481
1489
|
const res = await runBuy(client, loadConfig2(), { handle, size: opts.size, colour: opts.colour, json, brand }, {
|
|
1482
1490
|
prompts: makePrompts2(),
|
|
1483
1491
|
open: (url) => openCheckout(url),
|
|
1484
|
-
|
|
1492
|
+
// Same heartbeat as bt checkout — bt buy's browser-hop wait is the identical 20-min poll.
|
|
1493
|
+
poll: (sessionId) => pollUntilPlaced(client, sessionId, {
|
|
1494
|
+
onTick: (attempt) => {
|
|
1495
|
+
const line = heartbeatLine(attempt);
|
|
1496
|
+
if (line) print(dim(brand, line));
|
|
1497
|
+
}
|
|
1498
|
+
}),
|
|
1485
1499
|
saveConfig: saveConfig2,
|
|
1486
|
-
print
|
|
1487
|
-
} : (line) => process.stdout.write(line + "\n")
|
|
1500
|
+
print
|
|
1488
1501
|
});
|
|
1489
1502
|
if (res.save && Object.keys(res.save).length > 0) {
|
|
1490
1503
|
saveConfig2(res.save);
|
|
@@ -1630,7 +1643,7 @@ function registerReport(program, makeClient2) {
|
|
|
1630
1643
|
const gOpts = program.opts();
|
|
1631
1644
|
const json = Boolean(gOpts.json);
|
|
1632
1645
|
const debug = process.argv.includes("--debug") || process.argv.includes("--verbose");
|
|
1633
|
-
const { makePrompts: makePrompts2 } = await import("./prompts-
|
|
1646
|
+
const { makePrompts: makePrompts2 } = await import("./prompts-DDVV5RE6.js");
|
|
1634
1647
|
const snapshot = gatherDoctorSnapshot({ color: gOpts.color });
|
|
1635
1648
|
const res = await runReport(
|
|
1636
1649
|
makeClient2(),
|
|
@@ -1657,7 +1670,7 @@ function buildProgram() {
|
|
|
1657
1670
|
const program = new Command();
|
|
1658
1671
|
program.name("bt").description(
|
|
1659
1672
|
"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)"
|
|
1660
|
-
).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)");
|
|
1673
|
+
).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)").showSuggestionAfterError();
|
|
1661
1674
|
program.addHelpText("beforeAll", "\n bt \u2014 the binary & thread terminal store. new here? \u2192 bt init\n");
|
|
1662
1675
|
program.command("brew").argument("[what]", "what to brew").description("we make clothing, not coffee.").action(() => {
|
|
1663
1676
|
process.stdout.write(teapot() + "\n");
|
|
@@ -1731,6 +1744,11 @@ function registerEggs(program) {
|
|
|
1731
1744
|
program.command("ship", { hidden: true }).argument("[what]").action(() => print(shipIt()));
|
|
1732
1745
|
program.command("rm", { hidden: true }).allowUnknownOption().argument("[args...]").action(() => print(rmWardrobe()));
|
|
1733
1746
|
program.command("force", { hidden: true }).allowUnknownOption().argument("[args...]").action(() => print(force()));
|
|
1747
|
+
program.command("clone", { hidden: true }).allowUnknownOption().argument("[args...]").action(() => print(gitClone()));
|
|
1748
|
+
program.command("stash", { hidden: true }).allowUnknownOption().argument("[args...]").action(() => print(gitStash()));
|
|
1749
|
+
program.command("push", { hidden: true }).allowUnknownOption().argument("[args...]").action(() => print(gitPush()));
|
|
1750
|
+
program.command("pull", { hidden: true }).allowUnknownOption().argument("[args...]").action(() => print(gitPull()));
|
|
1751
|
+
program.command("reflog", { hidden: true }).allowUnknownOption().argument("[args...]").action(() => print(gitReflog()));
|
|
1734
1752
|
program.command("blame", { hidden: true }).argument("[slug]", "a design slug to blame").description("who's responsible for all this \u2014 provenance + lore.").action((slug) => print(blame(slug)));
|
|
1735
1753
|
program.command("fortune").description("a coding fortune. real aphorisms only.").action(() => {
|
|
1736
1754
|
const seed = Math.floor(Date.now() / 1e3) % FORTUNES.length;
|