@birdybeep/cli 0.1.0 → 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 +155 -2
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-HGH5CDKD.js → chunk-OCS5IDYI.js} +156 -3
- package/dist/chunk-OCS5IDYI.js.map +1 -0
- package/dist/index.cjs +155 -2
- 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-HGH5CDKD.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");
|
|
@@ -662,7 +676,7 @@ async function pairTokenPoll(apiUrl, deviceCode, fetchImpl, machineFingerprint)
|
|
|
662
676
|
}
|
|
663
677
|
|
|
664
678
|
// src/version.ts
|
|
665
|
-
var CLI_VERSION = "0.
|
|
679
|
+
var CLI_VERSION = "0.2.0".length > 0 ? "0.2.0" : "0.0.0";
|
|
666
680
|
|
|
667
681
|
// src/commands/pair.ts
|
|
668
682
|
var DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
@@ -999,13 +1013,152 @@ function buildCommands() {
|
|
|
999
1013
|
];
|
|
1000
1014
|
}
|
|
1001
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
|
+
|
|
1002
1153
|
// src/cli.ts
|
|
1003
1154
|
function runCli(argv, deps = {}) {
|
|
1155
|
+
const notifyUpdate = deps.updateCheck === false ? void 0 : (ctx) => maybeNotifyUpdate({ ...ctx, ...deps.updateCheck ?? {} });
|
|
1004
1156
|
return dispatch(argv, {
|
|
1005
1157
|
version: CLI_VERSION,
|
|
1006
1158
|
commands: deps.commands ?? buildCommands(),
|
|
1007
1159
|
stdout: deps.stdout ?? process.stdout,
|
|
1008
1160
|
stderr: deps.stderr ?? process.stderr,
|
|
1161
|
+
...notifyUpdate !== void 0 ? { notifyUpdate } : {},
|
|
1009
1162
|
...deps.ensureConfig !== void 0 ? { ensureConfig: deps.ensureConfig } : {}
|
|
1010
1163
|
});
|
|
1011
1164
|
}
|