@birdybeep/cli 0.0.3 → 0.2.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.cjs +217 -43
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-6VRCYDN5.js → chunk-OCS5IDYI.js} +211 -37
- package/dist/chunk-OCS5IDYI.js.map +1 -0
- package/dist/index.cjs +217 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +1 -1
- package/package.json +5 -5
- package/dist/chunk-6VRCYDN5.js.map +0 -1
package/dist/bin.cjs
CHANGED
|
@@ -169,8 +169,9 @@ async function dispatch(argv, deps) {
|
|
|
169
169
|
io.errline(`birdybeep ${path}: unknown option "${unknown}".`);
|
|
170
170
|
return EXIT.USAGE;
|
|
171
171
|
}
|
|
172
|
+
let code;
|
|
172
173
|
try {
|
|
173
|
-
|
|
174
|
+
code = await command.run({ args, flags, io });
|
|
174
175
|
} catch (err) {
|
|
175
176
|
if (err instanceof MissingInputError) {
|
|
176
177
|
io.errline(
|
|
@@ -181,6 +182,13 @@ async function dispatch(argv, deps) {
|
|
|
181
182
|
io.errline(`birdybeep ${path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
182
183
|
return EXIT.ERROR;
|
|
183
184
|
}
|
|
185
|
+
if (deps.notifyUpdate !== void 0) {
|
|
186
|
+
try {
|
|
187
|
+
await deps.notifyUpdate({ command: pathParts[0] ?? "", flags, io });
|
|
188
|
+
} catch {
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return code;
|
|
184
192
|
}
|
|
185
193
|
|
|
186
194
|
// src/commands/agent.ts
|
|
@@ -336,6 +344,12 @@ function resolveApiUrl() {
|
|
|
336
344
|
if (env !== void 0 && env.length > 0) return env;
|
|
337
345
|
return readCliConfig().apiUrl ?? DEFAULT_API_URL;
|
|
338
346
|
}
|
|
347
|
+
var DEFAULT_REGISTRY_URL = "https://registry.npmjs.org";
|
|
348
|
+
function resolveRegistryUrl() {
|
|
349
|
+
const env = process.env["npm_config_registry"];
|
|
350
|
+
if (env !== void 0 && env.length > 0) return env;
|
|
351
|
+
return DEFAULT_REGISTRY_URL;
|
|
352
|
+
}
|
|
339
353
|
|
|
340
354
|
// src/diagnostics.ts
|
|
341
355
|
var import_agent_core3 = require("@birdybeep/agent-core");
|
|
@@ -348,7 +362,7 @@ async function gatherIntegrations(adapters) {
|
|
|
348
362
|
}))
|
|
349
363
|
);
|
|
350
364
|
}
|
|
351
|
-
async function
|
|
365
|
+
async function isPaired(tokenOptions = {}) {
|
|
352
366
|
return await (0, import_agent_core3.getToken)(tokenOptions) !== null;
|
|
353
367
|
}
|
|
354
368
|
function localQueueDepth() {
|
|
@@ -385,13 +399,13 @@ function createDoctorCommand(deps = {}) {
|
|
|
385
399
|
run: async (ctx) => {
|
|
386
400
|
const checks = [];
|
|
387
401
|
const apiUrl = resolveApiUrl();
|
|
388
|
-
const
|
|
402
|
+
const paired = await isPaired(deps.tokenOptions ?? {});
|
|
389
403
|
checks.push(
|
|
390
|
-
|
|
404
|
+
paired ? { name: "Machine token", ok: true } : {
|
|
391
405
|
name: "Machine token",
|
|
392
406
|
ok: false,
|
|
393
407
|
detail: "No machine token found.",
|
|
394
|
-
remedy: "Run `birdybeep
|
|
408
|
+
remedy: "Run `birdybeep pair` to pair this machine."
|
|
395
409
|
}
|
|
396
410
|
);
|
|
397
411
|
for (const adapter of adapters) {
|
|
@@ -519,12 +533,49 @@ function createHookCommand(deps = {}) {
|
|
|
519
533
|
};
|
|
520
534
|
}
|
|
521
535
|
|
|
522
|
-
// src/commands/
|
|
523
|
-
var
|
|
536
|
+
// src/commands/logout.ts
|
|
537
|
+
var import_agent_core6 = require("@birdybeep/agent-core");
|
|
538
|
+
function createClearTokenCommand(spec, deps = {}) {
|
|
539
|
+
return {
|
|
540
|
+
name: spec.name,
|
|
541
|
+
summary: spec.summary,
|
|
542
|
+
usage: `birdybeep ${spec.name}`,
|
|
543
|
+
run: async (ctx) => {
|
|
544
|
+
await (0, import_agent_core6.clearToken)(deps.tokenOptions ?? {});
|
|
545
|
+
ctx.io.emit(spec.humanMessage, { [spec.jsonKey]: true });
|
|
546
|
+
return EXIT.OK;
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
function createLogoutCommand(deps = {}) {
|
|
551
|
+
return createClearTokenCommand(
|
|
552
|
+
{
|
|
553
|
+
name: "logout",
|
|
554
|
+
summary: "Remove the local machine token (same as `unpair`)",
|
|
555
|
+
humanMessage: "Logged out \u2014 the machine token was removed.",
|
|
556
|
+
jsonKey: "loggedOut"
|
|
557
|
+
},
|
|
558
|
+
deps
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
function createUnpairCommand(deps = {}) {
|
|
562
|
+
return createClearTokenCommand(
|
|
563
|
+
{
|
|
564
|
+
name: "unpair",
|
|
565
|
+
summary: "Unpair this machine \u2014 remove the local machine token (same as `logout`)",
|
|
566
|
+
humanMessage: "Unpaired \u2014 the machine token was removed.",
|
|
567
|
+
jsonKey: "unpaired"
|
|
568
|
+
},
|
|
569
|
+
deps
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// src/commands/pair.ts
|
|
574
|
+
var import_agent_core8 = require("@birdybeep/agent-core");
|
|
524
575
|
var import_uqr = require("uqr");
|
|
525
576
|
|
|
526
577
|
// src/pairing.ts
|
|
527
|
-
var
|
|
578
|
+
var import_agent_core7 = require("@birdybeep/agent-core");
|
|
528
579
|
function base(apiUrl) {
|
|
529
580
|
return apiUrl.replace(/\/$/, "");
|
|
530
581
|
}
|
|
@@ -540,7 +591,7 @@ async function pairStart(apiUrl, input, fetchImpl) {
|
|
|
540
591
|
body: JSON.stringify(body)
|
|
541
592
|
});
|
|
542
593
|
if (!res.ok) throw new Error(`pairing could not be started (HTTP ${res.status})`);
|
|
543
|
-
const parsed =
|
|
594
|
+
const parsed = import_agent_core7.pairStartResponseSchema.safeParse(await res.json());
|
|
544
595
|
if (!parsed.success) throw new Error("pairing start returned an unexpected response shape");
|
|
545
596
|
return parsed.data;
|
|
546
597
|
}
|
|
@@ -563,7 +614,7 @@ async function pairTokenPoll(apiUrl, deviceCode, fetchImpl, machineFingerprint)
|
|
|
563
614
|
body: JSON.stringify(body)
|
|
564
615
|
});
|
|
565
616
|
if (res.ok) {
|
|
566
|
-
const parsed =
|
|
617
|
+
const parsed = import_agent_core7.pairTokenResponseSchema.safeParse(await res.json());
|
|
567
618
|
if (!parsed.success) return { status: "pending" };
|
|
568
619
|
return {
|
|
569
620
|
status: "paired",
|
|
@@ -576,7 +627,7 @@ async function pairTokenPoll(apiUrl, deviceCode, fetchImpl, machineFingerprint)
|
|
|
576
627
|
errBody = await res.json();
|
|
577
628
|
} catch {
|
|
578
629
|
}
|
|
579
|
-
const env =
|
|
630
|
+
const env = import_agent_core7.errorEnvelopeSchema.safeParse(errBody);
|
|
580
631
|
const code = env.success ? env.data.error.code : void 0;
|
|
581
632
|
if (code === "validation_failed" || code === void 0 && res.status >= 400 && res.status < 500 && res.status !== 429) {
|
|
582
633
|
return { status: "pending" };
|
|
@@ -589,27 +640,27 @@ async function pairTokenPoll(apiUrl, deviceCode, fetchImpl, machineFingerprint)
|
|
|
589
640
|
}
|
|
590
641
|
|
|
591
642
|
// src/version.ts
|
|
592
|
-
var CLI_VERSION = "0.0
|
|
643
|
+
var CLI_VERSION = "0.2.0".length > 0 ? "0.2.0" : "0.0.0";
|
|
593
644
|
|
|
594
|
-
// src/commands/
|
|
645
|
+
// src/commands/pair.ts
|
|
595
646
|
var DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
596
647
|
var HEARTBEAT_MS = 15e3;
|
|
597
648
|
function renderQrMatrix(qrPayload) {
|
|
598
649
|
return (0, import_uqr.renderUnicodeCompact)(qrPayload, { border: 2 });
|
|
599
650
|
}
|
|
600
|
-
function
|
|
651
|
+
function createPairCommand(deps = {}) {
|
|
601
652
|
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
602
653
|
const sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
603
654
|
const clock = deps.now ?? (() => Date.now());
|
|
604
655
|
const renderQr = deps.renderQr ?? renderQrMatrix;
|
|
605
656
|
const intervalMs = deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
606
657
|
return {
|
|
607
|
-
name: "
|
|
658
|
+
name: "pair",
|
|
608
659
|
summary: "Pair this machine with your BirdyBeep account (QR or manual)",
|
|
609
|
-
usage: "birdybeep
|
|
660
|
+
usage: "birdybeep pair [--json]",
|
|
610
661
|
run: async (ctx) => {
|
|
611
662
|
const apiUrl = resolveApiUrl();
|
|
612
|
-
const identity = (0,
|
|
663
|
+
const identity = (0, import_agent_core8.getMachineIdentity)();
|
|
613
664
|
const start = await pairStart(
|
|
614
665
|
apiUrl,
|
|
615
666
|
{ machineLabel: identity.label, os: identity.os, cliVersion: CLI_VERSION },
|
|
@@ -670,11 +721,11 @@ function createLoginCommand(deps = {}) {
|
|
|
670
721
|
if (paired === void 0 || paired.status !== "paired") {
|
|
671
722
|
ctx.io.result({ paired: false, reason: "timeout" });
|
|
672
723
|
ctx.io.errline(
|
|
673
|
-
"Pairing timed out before you approved it. In the BirdyBeep app, tap \u201Cpair a machine\u201D, scan the QR (or enter the code), then run `birdybeep
|
|
724
|
+
"Pairing timed out before you approved it. In the BirdyBeep app, tap \u201Cpair a machine\u201D, scan the QR (or enter the code), then run `birdybeep pair` again."
|
|
674
725
|
);
|
|
675
726
|
return EXIT.ERROR;
|
|
676
727
|
}
|
|
677
|
-
await (0,
|
|
728
|
+
await (0, import_agent_core8.setToken)(paired.machineToken, deps.tokenOptions ?? {});
|
|
678
729
|
writeCliConfig({ apiUrl });
|
|
679
730
|
ctx.io.emit(`\u2713 Paired. Run \`birdybeep test\` to send a test Beep.`, {
|
|
680
731
|
paired: true,
|
|
@@ -685,21 +736,6 @@ function createLoginCommand(deps = {}) {
|
|
|
685
736
|
};
|
|
686
737
|
}
|
|
687
738
|
|
|
688
|
-
// src/commands/logout.ts
|
|
689
|
-
var import_agent_core8 = require("@birdybeep/agent-core");
|
|
690
|
-
function createLogoutCommand(deps = {}) {
|
|
691
|
-
return {
|
|
692
|
-
name: "logout",
|
|
693
|
-
summary: "Remove the local machine token",
|
|
694
|
-
usage: "birdybeep logout",
|
|
695
|
-
run: async (ctx) => {
|
|
696
|
-
await (0, import_agent_core8.clearToken)(deps.tokenOptions ?? {});
|
|
697
|
-
ctx.io.emit("Logged out \u2014 the machine token was removed.", { loggedOut: true });
|
|
698
|
-
return EXIT.OK;
|
|
699
|
-
}
|
|
700
|
-
};
|
|
701
|
-
}
|
|
702
|
-
|
|
703
739
|
// src/commands/queue.ts
|
|
704
740
|
var import_agent_core9 = require("@birdybeep/agent-core");
|
|
705
741
|
function createQueueCommand() {
|
|
@@ -756,7 +792,7 @@ function createReportStatusCommand(deps = {}) {
|
|
|
756
792
|
run: async (ctx) => {
|
|
757
793
|
const token = await (0, import_agent_core10.getToken)(deps.tokenOptions ?? {});
|
|
758
794
|
if (token === null) {
|
|
759
|
-
ctx.io.errline("
|
|
795
|
+
ctx.io.errline("No machine token \u2014 run `birdybeep pair` first.");
|
|
760
796
|
return EXIT.ERROR;
|
|
761
797
|
}
|
|
762
798
|
const items = await gatherItems(adapters);
|
|
@@ -801,7 +837,7 @@ function createReportStatusCommand(deps = {}) {
|
|
|
801
837
|
});
|
|
802
838
|
} else if (outcome === "terminal") {
|
|
803
839
|
ctx.io.errline(
|
|
804
|
-
`Report rejected (${errorCode ?? "auth"}) \u2014 your token may be revoked. Re-run \`birdybeep
|
|
840
|
+
`Report rejected (${errorCode ?? "auth"}) \u2014 your token may be revoked. Re-run \`birdybeep pair\`.`
|
|
805
841
|
);
|
|
806
842
|
} else {
|
|
807
843
|
for (const e of effective) {
|
|
@@ -832,14 +868,14 @@ function createStatusCommand(deps = {}) {
|
|
|
832
868
|
usage: "birdybeep status [--json]",
|
|
833
869
|
run: async (ctx) => {
|
|
834
870
|
const machine = machineIdentity();
|
|
835
|
-
const
|
|
871
|
+
const paired = await isPaired(deps.tokenOptions ?? {});
|
|
836
872
|
const integrations = await gatherIntegrations(adapters);
|
|
837
873
|
const depthBefore = localQueueDepth();
|
|
838
874
|
const drain = await makeSender(resolveApiUrl()).drainNow();
|
|
839
875
|
const depthAfter = localQueueDepth();
|
|
840
876
|
const report = {
|
|
841
877
|
machine,
|
|
842
|
-
|
|
878
|
+
paired,
|
|
843
879
|
integrations,
|
|
844
880
|
queue: { depthBefore, delivered: drain.delivered, depthAfter }
|
|
845
881
|
};
|
|
@@ -847,16 +883,14 @@ function createStatusCommand(deps = {}) {
|
|
|
847
883
|
ctx.io.result(report);
|
|
848
884
|
} else {
|
|
849
885
|
ctx.io.line(`Machine: ${machine.label} (${machine.os})`);
|
|
850
|
-
ctx.io.line(
|
|
851
|
-
loggedIn ? "Login: paired" : "Login: NOT logged in \u2014 run `birdybeep login`"
|
|
852
|
-
);
|
|
886
|
+
ctx.io.line(paired ? "Paired: yes" : "Paired: no \u2014 run `birdybeep pair`");
|
|
853
887
|
ctx.io.line("Integrations:");
|
|
854
888
|
for (const i of integrations) ctx.io.line(` ${i.displayName}: ${i.status}`);
|
|
855
889
|
ctx.io.line(
|
|
856
890
|
`Queue: ${depthBefore} queued \u2192 ${drain.delivered} delivered, ${depthAfter} remaining`
|
|
857
891
|
);
|
|
858
892
|
}
|
|
859
|
-
return
|
|
893
|
+
return paired ? EXIT.OK : EXIT.ERROR;
|
|
860
894
|
}
|
|
861
895
|
};
|
|
862
896
|
}
|
|
@@ -930,8 +964,9 @@ function createTestCommand(deps = {}) {
|
|
|
930
964
|
// src/commands.ts
|
|
931
965
|
function buildCommands() {
|
|
932
966
|
return [
|
|
933
|
-
|
|
967
|
+
createPairCommand(),
|
|
934
968
|
createLogoutCommand(),
|
|
969
|
+
createUnpairCommand(),
|
|
935
970
|
createStatusCommand(),
|
|
936
971
|
createTestCommand(),
|
|
937
972
|
createDoctorCommand(),
|
|
@@ -942,13 +977,152 @@ function buildCommands() {
|
|
|
942
977
|
];
|
|
943
978
|
}
|
|
944
979
|
|
|
980
|
+
// src/update-check.ts
|
|
981
|
+
var import_node_fs3 = require("fs");
|
|
982
|
+
var import_node_path2 = require("path");
|
|
983
|
+
var import_agent_core13 = require("@birdybeep/agent-core");
|
|
984
|
+
var PACKAGE_NAME = "@birdybeep/cli";
|
|
985
|
+
var PACKAGE_PATH = "@birdybeep%2Fcli";
|
|
986
|
+
var UPDATE_CACHE_FILE = "update-check.json";
|
|
987
|
+
var DEFAULT_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
988
|
+
var DEFAULT_TIMEOUT_MS = 1500;
|
|
989
|
+
var SKIP_COMMANDS = /* @__PURE__ */ new Set(["hook", "report-status"]);
|
|
990
|
+
var SEMVER_RE = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
991
|
+
function parseSemver(input) {
|
|
992
|
+
const m = SEMVER_RE.exec(input.trim());
|
|
993
|
+
if (m === null) return null;
|
|
994
|
+
return {
|
|
995
|
+
major: Number(m[1]),
|
|
996
|
+
minor: Number(m[2]),
|
|
997
|
+
patch: Number(m[3]),
|
|
998
|
+
prerelease: m[4] !== void 0 ? m[4].split(".") : []
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
1001
|
+
function comparePrerelease(a, b) {
|
|
1002
|
+
if (a.length === 0 && b.length === 0) return 0;
|
|
1003
|
+
if (a.length === 0) return 1;
|
|
1004
|
+
if (b.length === 0) return -1;
|
|
1005
|
+
const len = Math.min(a.length, b.length);
|
|
1006
|
+
for (let i = 0; i < len; i++) {
|
|
1007
|
+
const ai = a[i];
|
|
1008
|
+
const bi = b[i];
|
|
1009
|
+
const aNum = /^\d+$/.test(ai);
|
|
1010
|
+
const bNum = /^\d+$/.test(bi);
|
|
1011
|
+
if (aNum && bNum) {
|
|
1012
|
+
const d = Number(ai) - Number(bi);
|
|
1013
|
+
if (d !== 0) return d < 0 ? -1 : 1;
|
|
1014
|
+
} else if (aNum) {
|
|
1015
|
+
return -1;
|
|
1016
|
+
} else if (bNum) {
|
|
1017
|
+
return 1;
|
|
1018
|
+
} else if (ai !== bi) {
|
|
1019
|
+
return ai < bi ? -1 : 1;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
if (a.length === b.length) return 0;
|
|
1023
|
+
return a.length < b.length ? -1 : 1;
|
|
1024
|
+
}
|
|
1025
|
+
function compareSemver(a, b) {
|
|
1026
|
+
if (a.major !== b.major) return a.major < b.major ? -1 : 1;
|
|
1027
|
+
if (a.minor !== b.minor) return a.minor < b.minor ? -1 : 1;
|
|
1028
|
+
if (a.patch !== b.patch) return a.patch < b.patch ? -1 : 1;
|
|
1029
|
+
return comparePrerelease(a.prerelease, b.prerelease);
|
|
1030
|
+
}
|
|
1031
|
+
function isNewer(current, latest) {
|
|
1032
|
+
const cur = parseSemver(current);
|
|
1033
|
+
const lat = parseSemver(latest);
|
|
1034
|
+
return cur !== null && lat !== null && compareSemver(cur, lat) < 0;
|
|
1035
|
+
}
|
|
1036
|
+
function updateCachePath() {
|
|
1037
|
+
return (0, import_node_path2.join)((0, import_agent_core13.birdyBeepConfigDir)(), UPDATE_CACHE_FILE);
|
|
1038
|
+
}
|
|
1039
|
+
function readUpdateCache() {
|
|
1040
|
+
try {
|
|
1041
|
+
const parsed = JSON.parse((0, import_node_fs3.readFileSync)(updateCachePath(), "utf8"));
|
|
1042
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
1043
|
+
const { checkedAt, latest } = parsed;
|
|
1044
|
+
if (typeof checkedAt !== "number") return null;
|
|
1045
|
+
if (latest !== null && typeof latest !== "string") return null;
|
|
1046
|
+
return { checkedAt, latest };
|
|
1047
|
+
} catch {
|
|
1048
|
+
return null;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
function writeUpdateCache(cache) {
|
|
1052
|
+
(0, import_node_fs3.mkdirSync)((0, import_agent_core13.birdyBeepConfigDir)(), { recursive: true, mode: 448 });
|
|
1053
|
+
(0, import_node_fs3.writeFileSync)(updateCachePath(), `${JSON.stringify(cache)}
|
|
1054
|
+
`, { mode: 384 });
|
|
1055
|
+
}
|
|
1056
|
+
async function fetchLatestVersion(registryUrl, fetchImpl, timeoutMs) {
|
|
1057
|
+
const url = `${registryUrl.replace(/\/+$/, "")}/${PACKAGE_PATH}/latest`;
|
|
1058
|
+
const controller = new AbortController();
|
|
1059
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
1060
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
1061
|
+
try {
|
|
1062
|
+
const res = await fetchImpl(url, {
|
|
1063
|
+
headers: { accept: "application/json" },
|
|
1064
|
+
signal: controller.signal
|
|
1065
|
+
});
|
|
1066
|
+
if (!res.ok) throw new Error(`registry responded ${res.status}`);
|
|
1067
|
+
const body = await res.json();
|
|
1068
|
+
if (typeof body.version !== "string" || body.version.length === 0) {
|
|
1069
|
+
throw new Error("registry response had no version");
|
|
1070
|
+
}
|
|
1071
|
+
return body.version;
|
|
1072
|
+
} finally {
|
|
1073
|
+
clearTimeout(timer);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
function renderNotice(current, latest) {
|
|
1077
|
+
return `a new version of birdybeep is available: ${current} \u2192 ${latest}
|
|
1078
|
+
upgrade with: npm install -g ${PACKAGE_NAME}@latest`;
|
|
1079
|
+
}
|
|
1080
|
+
async function maybeNotifyUpdate(opts) {
|
|
1081
|
+
try {
|
|
1082
|
+
if (opts.command !== void 0 && SKIP_COMMANDS.has(opts.command)) return;
|
|
1083
|
+
if (opts.flags.json || opts.flags.nonInteractive) return;
|
|
1084
|
+
const env = opts.env ?? process.env;
|
|
1085
|
+
if (env["BIRDYBEEP_NO_UPDATE_NOTIFIER"] || env["NO_UPDATE_NOTIFIER"] || env["CI"]) return;
|
|
1086
|
+
const isTTY = opts.isTTY ?? Boolean(process.stderr.isTTY);
|
|
1087
|
+
if (!isTTY) return;
|
|
1088
|
+
const current = opts.currentVersion ?? CLI_VERSION;
|
|
1089
|
+
const now = opts.now ?? Date.now();
|
|
1090
|
+
const intervalMs = opts.intervalMs ?? DEFAULT_CHECK_INTERVAL_MS;
|
|
1091
|
+
const readCache = opts.readCache ?? readUpdateCache;
|
|
1092
|
+
const writeCache = opts.writeCache ?? writeUpdateCache;
|
|
1093
|
+
let cache = readCache();
|
|
1094
|
+
if (cache === null || now - cache.checkedAt >= intervalMs) {
|
|
1095
|
+
let latest = cache?.latest ?? null;
|
|
1096
|
+
try {
|
|
1097
|
+
latest = await fetchLatestVersion(
|
|
1098
|
+
opts.registryUrl ?? resolveRegistryUrl(),
|
|
1099
|
+
opts.fetchImpl ?? fetch,
|
|
1100
|
+
opts.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
1101
|
+
);
|
|
1102
|
+
} catch {
|
|
1103
|
+
}
|
|
1104
|
+
cache = { checkedAt: now, latest };
|
|
1105
|
+
try {
|
|
1106
|
+
writeCache(cache);
|
|
1107
|
+
} catch {
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
if (cache.latest !== null && isNewer(current, cache.latest)) {
|
|
1111
|
+
opts.io.errline(renderNotice(current, cache.latest));
|
|
1112
|
+
}
|
|
1113
|
+
} catch {
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
|
|
945
1117
|
// src/cli.ts
|
|
946
1118
|
function runCli(argv, deps = {}) {
|
|
1119
|
+
const notifyUpdate = deps.updateCheck === false ? void 0 : (ctx) => maybeNotifyUpdate({ ...ctx, ...deps.updateCheck ?? {} });
|
|
947
1120
|
return dispatch(argv, {
|
|
948
1121
|
version: CLI_VERSION,
|
|
949
1122
|
commands: deps.commands ?? buildCommands(),
|
|
950
1123
|
stdout: deps.stdout ?? process.stdout,
|
|
951
1124
|
stderr: deps.stderr ?? process.stderr,
|
|
1125
|
+
...notifyUpdate !== void 0 ? { notifyUpdate } : {},
|
|
952
1126
|
...deps.ensureConfig !== void 0 ? { ensureConfig: deps.ensureConfig } : {}
|
|
953
1127
|
});
|
|
954
1128
|
}
|