azdo-cli 0.10.0-develop.373 → 0.10.0-develop.386

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.
Files changed (2) hide show
  1. package/dist/index.js +117 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3351,9 +3351,114 @@ function createDownloadAttachmentCommand() {
3351
3351
  return command;
3352
3352
  }
3353
3353
 
3354
+ // src/services/update-check.ts
3355
+ import fs from "fs";
3356
+ import path from "path";
3357
+ import os from "os";
3358
+ var THROTTLE_MS = 10 * 60 * 1e3;
3359
+ var FETCH_TIMEOUT_MS = 1500;
3360
+ var REGISTRY_URL = "https://registry.npmjs.org/azdo-cli/latest";
3361
+ function getCachePath() {
3362
+ return path.join(os.homedir(), ".azdo", "update-check.json");
3363
+ }
3364
+ function defaultReadCache() {
3365
+ try {
3366
+ return fs.readFileSync(getCachePath(), "utf-8");
3367
+ } catch {
3368
+ return null;
3369
+ }
3370
+ }
3371
+ function defaultWriteCache(data) {
3372
+ try {
3373
+ const cachePath = getCachePath();
3374
+ fs.mkdirSync(path.dirname(cachePath), { recursive: true });
3375
+ fs.writeFileSync(cachePath, data);
3376
+ } catch {
3377
+ }
3378
+ }
3379
+ function parseCache(raw) {
3380
+ if (!raw) return null;
3381
+ let parsed;
3382
+ try {
3383
+ parsed = JSON.parse(raw);
3384
+ } catch {
3385
+ return null;
3386
+ }
3387
+ if (typeof parsed !== "object" || parsed === null) return null;
3388
+ const { lastCheck, latestVersion } = parsed;
3389
+ if (typeof lastCheck !== "number" || !Number.isFinite(lastCheck)) return null;
3390
+ if (typeof latestVersion !== "string" || latestVersion.length === 0) return null;
3391
+ return { lastCheck, latestVersion };
3392
+ }
3393
+ async function defaultFetchLatest() {
3394
+ const controller = new AbortController();
3395
+ const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
3396
+ try {
3397
+ const res = await fetch(REGISTRY_URL, { signal: controller.signal });
3398
+ if (!res.ok) return null;
3399
+ const body = await res.json();
3400
+ if (typeof body !== "object" || body === null) return null;
3401
+ const v = body.version;
3402
+ return typeof v === "string" && v.length > 0 ? v : null;
3403
+ } catch {
3404
+ return null;
3405
+ } finally {
3406
+ clearTimeout(timer);
3407
+ }
3408
+ }
3409
+ function parseVersion(v) {
3410
+ if (typeof v !== "string") return null;
3411
+ const trimmed = v.trim().replace(/^v/, "");
3412
+ const match = /^(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$/.exec(trimmed);
3413
+ if (!match) return null;
3414
+ const release = [Number(match[1]), Number(match[2]), Number(match[3])];
3415
+ if (!release.every(Number.isFinite)) return null;
3416
+ return { release, prerelease: match[4] !== void 0 };
3417
+ }
3418
+ function isNewer(latest, current) {
3419
+ const a = parseVersion(latest);
3420
+ const b = parseVersion(current);
3421
+ if (!a || !b) return false;
3422
+ for (let i = 0; i < 3; i++) {
3423
+ if (a.release[i] > b.release[i]) return true;
3424
+ if (a.release[i] < b.release[i]) return false;
3425
+ }
3426
+ if (a.prerelease && !b.prerelease) return false;
3427
+ if (!a.prerelease && b.prerelease) return true;
3428
+ return false;
3429
+ }
3430
+ async function getUpdateNotice(opts) {
3431
+ try {
3432
+ const {
3433
+ enabled = true,
3434
+ now = Date.now,
3435
+ readCache = defaultReadCache,
3436
+ writeCache = defaultWriteCache,
3437
+ fetchLatest = defaultFetchLatest,
3438
+ isTTY = () => Boolean(process.stderr.isTTY),
3439
+ currentVersion = version
3440
+ } = opts ?? {};
3441
+ if (enabled === false) return null;
3442
+ if (!isTTY()) return null;
3443
+ const cache = parseCache(readCache());
3444
+ const lastCheck = cache?.lastCheck ?? 0;
3445
+ if (now() - lastCheck < THROTTLE_MS) return null;
3446
+ const latest = await fetchLatest();
3447
+ if (!latest) return null;
3448
+ writeCache(JSON.stringify({ lastCheck: now(), latestVersion: latest }));
3449
+ if (isNewer(latest, currentVersion)) {
3450
+ return `A new version of azdo-cli is available: ${currentVersion} \u2192 ${latest}. Run \`npm i -g azdo-cli\` to update.`;
3451
+ }
3452
+ return null;
3453
+ } catch {
3454
+ return null;
3455
+ }
3456
+ }
3457
+
3354
3458
  // src/index.ts
3355
3459
  var program = new Command15();
3356
3460
  program.name("azdo").description("Azure DevOps CLI tool").version(version, "-v, --version");
3461
+ program.option("--no-update-check", "Skip the check for a newer published version");
3357
3462
  program.addCommand(createGetItemCommand());
3358
3463
  program.addCommand(createAuthCommand());
3359
3464
  program.addCommand(createClearPatCommand());
@@ -3369,7 +3474,16 @@ program.addCommand(createPrCommand());
3369
3474
  program.addCommand(createCommentsCommand());
3370
3475
  program.addCommand(createDownloadAttachmentCommand());
3371
3476
  program.showHelpAfterError();
3372
- program.parse();
3373
- if (process.argv.length <= 2) {
3374
- program.help();
3477
+ program.hook("postAction", async () => {
3478
+ const notice = await getUpdateNotice({ enabled: program.opts().updateCheck });
3479
+ if (notice) {
3480
+ process.stderr.write(notice + "\n");
3481
+ }
3482
+ });
3483
+ async function main() {
3484
+ await program.parseAsync();
3485
+ if (process.argv.length <= 2) {
3486
+ program.help();
3487
+ }
3375
3488
  }
3489
+ void main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "azdo-cli",
3
- "version": "0.10.0-develop.373",
3
+ "version": "0.10.0-develop.386",
4
4
  "description": "Azure DevOps CLI tool",
5
5
  "type": "module",
6
6
  "bin": {