@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/index.cjs
CHANGED
|
@@ -205,8 +205,9 @@ async function dispatch(argv, deps) {
|
|
|
205
205
|
io.errline(`birdybeep ${path}: unknown option "${unknown}".`);
|
|
206
206
|
return EXIT.USAGE;
|
|
207
207
|
}
|
|
208
|
+
let code;
|
|
208
209
|
try {
|
|
209
|
-
|
|
210
|
+
code = await command.run({ args, flags, io });
|
|
210
211
|
} catch (err) {
|
|
211
212
|
if (err instanceof MissingInputError) {
|
|
212
213
|
io.errline(
|
|
@@ -217,6 +218,13 @@ async function dispatch(argv, deps) {
|
|
|
217
218
|
io.errline(`birdybeep ${path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
218
219
|
return EXIT.ERROR;
|
|
219
220
|
}
|
|
221
|
+
if (deps.notifyUpdate !== void 0) {
|
|
222
|
+
try {
|
|
223
|
+
await deps.notifyUpdate({ command: pathParts[0] ?? "", flags, io });
|
|
224
|
+
} catch {
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return code;
|
|
220
228
|
}
|
|
221
229
|
|
|
222
230
|
// src/commands/agent.ts
|
|
@@ -372,6 +380,12 @@ function resolveApiUrl() {
|
|
|
372
380
|
if (env !== void 0 && env.length > 0) return env;
|
|
373
381
|
return readCliConfig().apiUrl ?? DEFAULT_API_URL;
|
|
374
382
|
}
|
|
383
|
+
var DEFAULT_REGISTRY_URL = "https://registry.npmjs.org";
|
|
384
|
+
function resolveRegistryUrl() {
|
|
385
|
+
const env = process.env["npm_config_registry"];
|
|
386
|
+
if (env !== void 0 && env.length > 0) return env;
|
|
387
|
+
return DEFAULT_REGISTRY_URL;
|
|
388
|
+
}
|
|
375
389
|
|
|
376
390
|
// src/diagnostics.ts
|
|
377
391
|
var import_agent_core3 = require("@birdybeep/agent-core");
|
|
@@ -384,7 +398,7 @@ async function gatherIntegrations(adapters) {
|
|
|
384
398
|
}))
|
|
385
399
|
);
|
|
386
400
|
}
|
|
387
|
-
async function
|
|
401
|
+
async function isPaired(tokenOptions = {}) {
|
|
388
402
|
return await (0, import_agent_core3.getToken)(tokenOptions) !== null;
|
|
389
403
|
}
|
|
390
404
|
function localQueueDepth() {
|
|
@@ -421,13 +435,13 @@ function createDoctorCommand(deps = {}) {
|
|
|
421
435
|
run: async (ctx) => {
|
|
422
436
|
const checks = [];
|
|
423
437
|
const apiUrl = resolveApiUrl();
|
|
424
|
-
const
|
|
438
|
+
const paired = await isPaired(deps.tokenOptions ?? {});
|
|
425
439
|
checks.push(
|
|
426
|
-
|
|
440
|
+
paired ? { name: "Machine token", ok: true } : {
|
|
427
441
|
name: "Machine token",
|
|
428
442
|
ok: false,
|
|
429
443
|
detail: "No machine token found.",
|
|
430
|
-
remedy: "Run `birdybeep
|
|
444
|
+
remedy: "Run `birdybeep pair` to pair this machine."
|
|
431
445
|
}
|
|
432
446
|
);
|
|
433
447
|
for (const adapter of adapters) {
|
|
@@ -555,12 +569,49 @@ function createHookCommand(deps = {}) {
|
|
|
555
569
|
};
|
|
556
570
|
}
|
|
557
571
|
|
|
558
|
-
// src/commands/
|
|
559
|
-
var
|
|
572
|
+
// src/commands/logout.ts
|
|
573
|
+
var import_agent_core6 = require("@birdybeep/agent-core");
|
|
574
|
+
function createClearTokenCommand(spec, deps = {}) {
|
|
575
|
+
return {
|
|
576
|
+
name: spec.name,
|
|
577
|
+
summary: spec.summary,
|
|
578
|
+
usage: `birdybeep ${spec.name}`,
|
|
579
|
+
run: async (ctx) => {
|
|
580
|
+
await (0, import_agent_core6.clearToken)(deps.tokenOptions ?? {});
|
|
581
|
+
ctx.io.emit(spec.humanMessage, { [spec.jsonKey]: true });
|
|
582
|
+
return EXIT.OK;
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
function createLogoutCommand(deps = {}) {
|
|
587
|
+
return createClearTokenCommand(
|
|
588
|
+
{
|
|
589
|
+
name: "logout",
|
|
590
|
+
summary: "Remove the local machine token (same as `unpair`)",
|
|
591
|
+
humanMessage: "Logged out \u2014 the machine token was removed.",
|
|
592
|
+
jsonKey: "loggedOut"
|
|
593
|
+
},
|
|
594
|
+
deps
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
function createUnpairCommand(deps = {}) {
|
|
598
|
+
return createClearTokenCommand(
|
|
599
|
+
{
|
|
600
|
+
name: "unpair",
|
|
601
|
+
summary: "Unpair this machine \u2014 remove the local machine token (same as `logout`)",
|
|
602
|
+
humanMessage: "Unpaired \u2014 the machine token was removed.",
|
|
603
|
+
jsonKey: "unpaired"
|
|
604
|
+
},
|
|
605
|
+
deps
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// src/commands/pair.ts
|
|
610
|
+
var import_agent_core8 = require("@birdybeep/agent-core");
|
|
560
611
|
var import_uqr = require("uqr");
|
|
561
612
|
|
|
562
613
|
// src/pairing.ts
|
|
563
|
-
var
|
|
614
|
+
var import_agent_core7 = require("@birdybeep/agent-core");
|
|
564
615
|
function base(apiUrl) {
|
|
565
616
|
return apiUrl.replace(/\/$/, "");
|
|
566
617
|
}
|
|
@@ -576,7 +627,7 @@ async function pairStart(apiUrl, input, fetchImpl) {
|
|
|
576
627
|
body: JSON.stringify(body)
|
|
577
628
|
});
|
|
578
629
|
if (!res.ok) throw new Error(`pairing could not be started (HTTP ${res.status})`);
|
|
579
|
-
const parsed =
|
|
630
|
+
const parsed = import_agent_core7.pairStartResponseSchema.safeParse(await res.json());
|
|
580
631
|
if (!parsed.success) throw new Error("pairing start returned an unexpected response shape");
|
|
581
632
|
return parsed.data;
|
|
582
633
|
}
|
|
@@ -599,7 +650,7 @@ async function pairTokenPoll(apiUrl, deviceCode, fetchImpl, machineFingerprint)
|
|
|
599
650
|
body: JSON.stringify(body)
|
|
600
651
|
});
|
|
601
652
|
if (res.ok) {
|
|
602
|
-
const parsed =
|
|
653
|
+
const parsed = import_agent_core7.pairTokenResponseSchema.safeParse(await res.json());
|
|
603
654
|
if (!parsed.success) return { status: "pending" };
|
|
604
655
|
return {
|
|
605
656
|
status: "paired",
|
|
@@ -612,7 +663,7 @@ async function pairTokenPoll(apiUrl, deviceCode, fetchImpl, machineFingerprint)
|
|
|
612
663
|
errBody = await res.json();
|
|
613
664
|
} catch {
|
|
614
665
|
}
|
|
615
|
-
const env =
|
|
666
|
+
const env = import_agent_core7.errorEnvelopeSchema.safeParse(errBody);
|
|
616
667
|
const code = env.success ? env.data.error.code : void 0;
|
|
617
668
|
if (code === "validation_failed" || code === void 0 && res.status >= 400 && res.status < 500 && res.status !== 429) {
|
|
618
669
|
return { status: "pending" };
|
|
@@ -625,27 +676,27 @@ async function pairTokenPoll(apiUrl, deviceCode, fetchImpl, machineFingerprint)
|
|
|
625
676
|
}
|
|
626
677
|
|
|
627
678
|
// src/version.ts
|
|
628
|
-
var CLI_VERSION = "0.0
|
|
679
|
+
var CLI_VERSION = "0.2.0".length > 0 ? "0.2.0" : "0.0.0";
|
|
629
680
|
|
|
630
|
-
// src/commands/
|
|
681
|
+
// src/commands/pair.ts
|
|
631
682
|
var DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
632
683
|
var HEARTBEAT_MS = 15e3;
|
|
633
684
|
function renderQrMatrix(qrPayload) {
|
|
634
685
|
return (0, import_uqr.renderUnicodeCompact)(qrPayload, { border: 2 });
|
|
635
686
|
}
|
|
636
|
-
function
|
|
687
|
+
function createPairCommand(deps = {}) {
|
|
637
688
|
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
638
689
|
const sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
639
690
|
const clock = deps.now ?? (() => Date.now());
|
|
640
691
|
const renderQr = deps.renderQr ?? renderQrMatrix;
|
|
641
692
|
const intervalMs = deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
642
693
|
return {
|
|
643
|
-
name: "
|
|
694
|
+
name: "pair",
|
|
644
695
|
summary: "Pair this machine with your BirdyBeep account (QR or manual)",
|
|
645
|
-
usage: "birdybeep
|
|
696
|
+
usage: "birdybeep pair [--json]",
|
|
646
697
|
run: async (ctx) => {
|
|
647
698
|
const apiUrl = resolveApiUrl();
|
|
648
|
-
const identity = (0,
|
|
699
|
+
const identity = (0, import_agent_core8.getMachineIdentity)();
|
|
649
700
|
const start = await pairStart(
|
|
650
701
|
apiUrl,
|
|
651
702
|
{ machineLabel: identity.label, os: identity.os, cliVersion: CLI_VERSION },
|
|
@@ -706,11 +757,11 @@ function createLoginCommand(deps = {}) {
|
|
|
706
757
|
if (paired === void 0 || paired.status !== "paired") {
|
|
707
758
|
ctx.io.result({ paired: false, reason: "timeout" });
|
|
708
759
|
ctx.io.errline(
|
|
709
|
-
"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
|
|
760
|
+
"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."
|
|
710
761
|
);
|
|
711
762
|
return EXIT.ERROR;
|
|
712
763
|
}
|
|
713
|
-
await (0,
|
|
764
|
+
await (0, import_agent_core8.setToken)(paired.machineToken, deps.tokenOptions ?? {});
|
|
714
765
|
writeCliConfig({ apiUrl });
|
|
715
766
|
ctx.io.emit(`\u2713 Paired. Run \`birdybeep test\` to send a test Beep.`, {
|
|
716
767
|
paired: true,
|
|
@@ -721,21 +772,6 @@ function createLoginCommand(deps = {}) {
|
|
|
721
772
|
};
|
|
722
773
|
}
|
|
723
774
|
|
|
724
|
-
// src/commands/logout.ts
|
|
725
|
-
var import_agent_core8 = require("@birdybeep/agent-core");
|
|
726
|
-
function createLogoutCommand(deps = {}) {
|
|
727
|
-
return {
|
|
728
|
-
name: "logout",
|
|
729
|
-
summary: "Remove the local machine token",
|
|
730
|
-
usage: "birdybeep logout",
|
|
731
|
-
run: async (ctx) => {
|
|
732
|
-
await (0, import_agent_core8.clearToken)(deps.tokenOptions ?? {});
|
|
733
|
-
ctx.io.emit("Logged out \u2014 the machine token was removed.", { loggedOut: true });
|
|
734
|
-
return EXIT.OK;
|
|
735
|
-
}
|
|
736
|
-
};
|
|
737
|
-
}
|
|
738
|
-
|
|
739
775
|
// src/commands/queue.ts
|
|
740
776
|
var import_agent_core9 = require("@birdybeep/agent-core");
|
|
741
777
|
function createQueueCommand() {
|
|
@@ -792,7 +828,7 @@ function createReportStatusCommand(deps = {}) {
|
|
|
792
828
|
run: async (ctx) => {
|
|
793
829
|
const token = await (0, import_agent_core10.getToken)(deps.tokenOptions ?? {});
|
|
794
830
|
if (token === null) {
|
|
795
|
-
ctx.io.errline("
|
|
831
|
+
ctx.io.errline("No machine token \u2014 run `birdybeep pair` first.");
|
|
796
832
|
return EXIT.ERROR;
|
|
797
833
|
}
|
|
798
834
|
const items = await gatherItems(adapters);
|
|
@@ -837,7 +873,7 @@ function createReportStatusCommand(deps = {}) {
|
|
|
837
873
|
});
|
|
838
874
|
} else if (outcome === "terminal") {
|
|
839
875
|
ctx.io.errline(
|
|
840
|
-
`Report rejected (${errorCode ?? "auth"}) \u2014 your token may be revoked. Re-run \`birdybeep
|
|
876
|
+
`Report rejected (${errorCode ?? "auth"}) \u2014 your token may be revoked. Re-run \`birdybeep pair\`.`
|
|
841
877
|
);
|
|
842
878
|
} else {
|
|
843
879
|
for (const e of effective) {
|
|
@@ -868,14 +904,14 @@ function createStatusCommand(deps = {}) {
|
|
|
868
904
|
usage: "birdybeep status [--json]",
|
|
869
905
|
run: async (ctx) => {
|
|
870
906
|
const machine = machineIdentity();
|
|
871
|
-
const
|
|
907
|
+
const paired = await isPaired(deps.tokenOptions ?? {});
|
|
872
908
|
const integrations = await gatherIntegrations(adapters);
|
|
873
909
|
const depthBefore = localQueueDepth();
|
|
874
910
|
const drain = await makeSender(resolveApiUrl()).drainNow();
|
|
875
911
|
const depthAfter = localQueueDepth();
|
|
876
912
|
const report = {
|
|
877
913
|
machine,
|
|
878
|
-
|
|
914
|
+
paired,
|
|
879
915
|
integrations,
|
|
880
916
|
queue: { depthBefore, delivered: drain.delivered, depthAfter }
|
|
881
917
|
};
|
|
@@ -883,16 +919,14 @@ function createStatusCommand(deps = {}) {
|
|
|
883
919
|
ctx.io.result(report);
|
|
884
920
|
} else {
|
|
885
921
|
ctx.io.line(`Machine: ${machine.label} (${machine.os})`);
|
|
886
|
-
ctx.io.line(
|
|
887
|
-
loggedIn ? "Login: paired" : "Login: NOT logged in \u2014 run `birdybeep login`"
|
|
888
|
-
);
|
|
922
|
+
ctx.io.line(paired ? "Paired: yes" : "Paired: no \u2014 run `birdybeep pair`");
|
|
889
923
|
ctx.io.line("Integrations:");
|
|
890
924
|
for (const i of integrations) ctx.io.line(` ${i.displayName}: ${i.status}`);
|
|
891
925
|
ctx.io.line(
|
|
892
926
|
`Queue: ${depthBefore} queued \u2192 ${drain.delivered} delivered, ${depthAfter} remaining`
|
|
893
927
|
);
|
|
894
928
|
}
|
|
895
|
-
return
|
|
929
|
+
return paired ? EXIT.OK : EXIT.ERROR;
|
|
896
930
|
}
|
|
897
931
|
};
|
|
898
932
|
}
|
|
@@ -966,8 +1000,9 @@ function createTestCommand(deps = {}) {
|
|
|
966
1000
|
// src/commands.ts
|
|
967
1001
|
function buildCommands() {
|
|
968
1002
|
return [
|
|
969
|
-
|
|
1003
|
+
createPairCommand(),
|
|
970
1004
|
createLogoutCommand(),
|
|
1005
|
+
createUnpairCommand(),
|
|
971
1006
|
createStatusCommand(),
|
|
972
1007
|
createTestCommand(),
|
|
973
1008
|
createDoctorCommand(),
|
|
@@ -978,13 +1013,152 @@ function buildCommands() {
|
|
|
978
1013
|
];
|
|
979
1014
|
}
|
|
980
1015
|
|
|
1016
|
+
// src/update-check.ts
|
|
1017
|
+
var import_node_fs3 = require("fs");
|
|
1018
|
+
var import_node_path2 = require("path");
|
|
1019
|
+
var import_agent_core13 = require("@birdybeep/agent-core");
|
|
1020
|
+
var PACKAGE_NAME = "@birdybeep/cli";
|
|
1021
|
+
var PACKAGE_PATH = "@birdybeep%2Fcli";
|
|
1022
|
+
var UPDATE_CACHE_FILE = "update-check.json";
|
|
1023
|
+
var DEFAULT_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
1024
|
+
var DEFAULT_TIMEOUT_MS = 1500;
|
|
1025
|
+
var SKIP_COMMANDS = /* @__PURE__ */ new Set(["hook", "report-status"]);
|
|
1026
|
+
var SEMVER_RE = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
1027
|
+
function parseSemver(input) {
|
|
1028
|
+
const m = SEMVER_RE.exec(input.trim());
|
|
1029
|
+
if (m === null) return null;
|
|
1030
|
+
return {
|
|
1031
|
+
major: Number(m[1]),
|
|
1032
|
+
minor: Number(m[2]),
|
|
1033
|
+
patch: Number(m[3]),
|
|
1034
|
+
prerelease: m[4] !== void 0 ? m[4].split(".") : []
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
function comparePrerelease(a, b) {
|
|
1038
|
+
if (a.length === 0 && b.length === 0) return 0;
|
|
1039
|
+
if (a.length === 0) return 1;
|
|
1040
|
+
if (b.length === 0) return -1;
|
|
1041
|
+
const len = Math.min(a.length, b.length);
|
|
1042
|
+
for (let i = 0; i < len; i++) {
|
|
1043
|
+
const ai = a[i];
|
|
1044
|
+
const bi = b[i];
|
|
1045
|
+
const aNum = /^\d+$/.test(ai);
|
|
1046
|
+
const bNum = /^\d+$/.test(bi);
|
|
1047
|
+
if (aNum && bNum) {
|
|
1048
|
+
const d = Number(ai) - Number(bi);
|
|
1049
|
+
if (d !== 0) return d < 0 ? -1 : 1;
|
|
1050
|
+
} else if (aNum) {
|
|
1051
|
+
return -1;
|
|
1052
|
+
} else if (bNum) {
|
|
1053
|
+
return 1;
|
|
1054
|
+
} else if (ai !== bi) {
|
|
1055
|
+
return ai < bi ? -1 : 1;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
if (a.length === b.length) return 0;
|
|
1059
|
+
return a.length < b.length ? -1 : 1;
|
|
1060
|
+
}
|
|
1061
|
+
function compareSemver(a, b) {
|
|
1062
|
+
if (a.major !== b.major) return a.major < b.major ? -1 : 1;
|
|
1063
|
+
if (a.minor !== b.minor) return a.minor < b.minor ? -1 : 1;
|
|
1064
|
+
if (a.patch !== b.patch) return a.patch < b.patch ? -1 : 1;
|
|
1065
|
+
return comparePrerelease(a.prerelease, b.prerelease);
|
|
1066
|
+
}
|
|
1067
|
+
function isNewer(current, latest) {
|
|
1068
|
+
const cur = parseSemver(current);
|
|
1069
|
+
const lat = parseSemver(latest);
|
|
1070
|
+
return cur !== null && lat !== null && compareSemver(cur, lat) < 0;
|
|
1071
|
+
}
|
|
1072
|
+
function updateCachePath() {
|
|
1073
|
+
return (0, import_node_path2.join)((0, import_agent_core13.birdyBeepConfigDir)(), UPDATE_CACHE_FILE);
|
|
1074
|
+
}
|
|
1075
|
+
function readUpdateCache() {
|
|
1076
|
+
try {
|
|
1077
|
+
const parsed = JSON.parse((0, import_node_fs3.readFileSync)(updateCachePath(), "utf8"));
|
|
1078
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
1079
|
+
const { checkedAt, latest } = parsed;
|
|
1080
|
+
if (typeof checkedAt !== "number") return null;
|
|
1081
|
+
if (latest !== null && typeof latest !== "string") return null;
|
|
1082
|
+
return { checkedAt, latest };
|
|
1083
|
+
} catch {
|
|
1084
|
+
return null;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
function writeUpdateCache(cache) {
|
|
1088
|
+
(0, import_node_fs3.mkdirSync)((0, import_agent_core13.birdyBeepConfigDir)(), { recursive: true, mode: 448 });
|
|
1089
|
+
(0, import_node_fs3.writeFileSync)(updateCachePath(), `${JSON.stringify(cache)}
|
|
1090
|
+
`, { mode: 384 });
|
|
1091
|
+
}
|
|
1092
|
+
async function fetchLatestVersion(registryUrl, fetchImpl, timeoutMs) {
|
|
1093
|
+
const url = `${registryUrl.replace(/\/+$/, "")}/${PACKAGE_PATH}/latest`;
|
|
1094
|
+
const controller = new AbortController();
|
|
1095
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
1096
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
1097
|
+
try {
|
|
1098
|
+
const res = await fetchImpl(url, {
|
|
1099
|
+
headers: { accept: "application/json" },
|
|
1100
|
+
signal: controller.signal
|
|
1101
|
+
});
|
|
1102
|
+
if (!res.ok) throw new Error(`registry responded ${res.status}`);
|
|
1103
|
+
const body = await res.json();
|
|
1104
|
+
if (typeof body.version !== "string" || body.version.length === 0) {
|
|
1105
|
+
throw new Error("registry response had no version");
|
|
1106
|
+
}
|
|
1107
|
+
return body.version;
|
|
1108
|
+
} finally {
|
|
1109
|
+
clearTimeout(timer);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
function renderNotice(current, latest) {
|
|
1113
|
+
return `a new version of birdybeep is available: ${current} \u2192 ${latest}
|
|
1114
|
+
upgrade with: npm install -g ${PACKAGE_NAME}@latest`;
|
|
1115
|
+
}
|
|
1116
|
+
async function maybeNotifyUpdate(opts) {
|
|
1117
|
+
try {
|
|
1118
|
+
if (opts.command !== void 0 && SKIP_COMMANDS.has(opts.command)) return;
|
|
1119
|
+
if (opts.flags.json || opts.flags.nonInteractive) return;
|
|
1120
|
+
const env = opts.env ?? process.env;
|
|
1121
|
+
if (env["BIRDYBEEP_NO_UPDATE_NOTIFIER"] || env["NO_UPDATE_NOTIFIER"] || env["CI"]) return;
|
|
1122
|
+
const isTTY = opts.isTTY ?? Boolean(process.stderr.isTTY);
|
|
1123
|
+
if (!isTTY) return;
|
|
1124
|
+
const current = opts.currentVersion ?? CLI_VERSION;
|
|
1125
|
+
const now = opts.now ?? Date.now();
|
|
1126
|
+
const intervalMs = opts.intervalMs ?? DEFAULT_CHECK_INTERVAL_MS;
|
|
1127
|
+
const readCache = opts.readCache ?? readUpdateCache;
|
|
1128
|
+
const writeCache = opts.writeCache ?? writeUpdateCache;
|
|
1129
|
+
let cache = readCache();
|
|
1130
|
+
if (cache === null || now - cache.checkedAt >= intervalMs) {
|
|
1131
|
+
let latest = cache?.latest ?? null;
|
|
1132
|
+
try {
|
|
1133
|
+
latest = await fetchLatestVersion(
|
|
1134
|
+
opts.registryUrl ?? resolveRegistryUrl(),
|
|
1135
|
+
opts.fetchImpl ?? fetch,
|
|
1136
|
+
opts.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
1137
|
+
);
|
|
1138
|
+
} catch {
|
|
1139
|
+
}
|
|
1140
|
+
cache = { checkedAt: now, latest };
|
|
1141
|
+
try {
|
|
1142
|
+
writeCache(cache);
|
|
1143
|
+
} catch {
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
if (cache.latest !== null && isNewer(current, cache.latest)) {
|
|
1147
|
+
opts.io.errline(renderNotice(current, cache.latest));
|
|
1148
|
+
}
|
|
1149
|
+
} catch {
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
|
|
981
1153
|
// src/cli.ts
|
|
982
1154
|
function runCli(argv, deps = {}) {
|
|
1155
|
+
const notifyUpdate = deps.updateCheck === false ? void 0 : (ctx) => maybeNotifyUpdate({ ...ctx, ...deps.updateCheck ?? {} });
|
|
983
1156
|
return dispatch(argv, {
|
|
984
1157
|
version: CLI_VERSION,
|
|
985
1158
|
commands: deps.commands ?? buildCommands(),
|
|
986
1159
|
stdout: deps.stdout ?? process.stdout,
|
|
987
1160
|
stderr: deps.stderr ?? process.stderr,
|
|
1161
|
+
...notifyUpdate !== void 0 ? { notifyUpdate } : {},
|
|
988
1162
|
...deps.ensureConfig !== void 0 ? { ensureConfig: deps.ensureConfig } : {}
|
|
989
1163
|
});
|
|
990
1164
|
}
|