ccclub 0.2.78 → 0.2.79

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 +45 -18
  2. package/package.json +2 -1
package/dist/index.js CHANGED
@@ -206,9 +206,9 @@ function isHookInstalled() {
206
206
 
207
207
  // src/commands/sync.ts
208
208
  import { readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
209
- import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync } from "fs";
210
- import { join as join4 } from "path";
211
- import { homedir as homedir4 } from "os";
209
+ import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
210
+ import { join as join5 } from "path";
211
+ import { homedir as homedir5 } from "os";
212
212
  import chalk2 from "chalk";
213
213
  import ora from "ora";
214
214
 
@@ -394,11 +394,30 @@ function formatFetchError(err) {
394
394
  // src/usage-limits.ts
395
395
  import { execSync as execSync2, exec } from "child_process";
396
396
  import { promisify } from "util";
397
- import { userInfo as userInfo2 } from "os";
397
+ import { userInfo as userInfo2, homedir as homedir4 } from "os";
398
+ import { join as join4 } from "path";
399
+ import { readFileSync as readFileSync2, writeFileSync } from "fs";
398
400
  var execAsync = promisify(exec);
399
401
  var debug = (...args) => {
400
402
  if (process.env.CCCLUB_DEBUG) console.error("[usage-debug]", ...args);
401
403
  };
404
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
405
+ var CACHE_PATH = join4(homedir4(), CCCLUB_CONFIG_DIR, "usage-cache.json");
406
+ function readCache(allowStale = false) {
407
+ try {
408
+ const raw = readFileSync2(CACHE_PATH, "utf-8");
409
+ const { snapshot, fetchedAt } = JSON.parse(raw);
410
+ if (allowStale || Date.now() - fetchedAt < CACHE_TTL_MS) return snapshot;
411
+ } catch {
412
+ }
413
+ return null;
414
+ }
415
+ function writeCache(snapshot) {
416
+ try {
417
+ writeFileSync(CACHE_PATH, JSON.stringify({ snapshot, fetchedAt: Date.now() }));
418
+ } catch {
419
+ }
420
+ }
402
421
  function parseUtilization(value) {
403
422
  if (typeof value === "number") return Math.round(value * 100) / 100;
404
423
  if (typeof value === "string") {
@@ -408,6 +427,11 @@ function parseUtilization(value) {
408
427
  return 0;
409
428
  }
410
429
  async function fetchUsageLimits() {
430
+ const cached = readCache();
431
+ if (cached) {
432
+ debug("returning cached snapshot:", cached.fiveHour, cached.sevenDay);
433
+ return cached;
434
+ }
411
435
  try {
412
436
  const username = process.env.USER || process.env.USERNAME || userInfo2().username;
413
437
  debug("username:", username);
@@ -428,7 +452,7 @@ async function fetchUsageLimits() {
428
452
  debug("returning null: token expired at", expiresAt);
429
453
  return null;
430
454
  }
431
- const curlCmd = `curl -sf --max-time 8 --noproxy '*' "https://api.anthropic.com/api/oauth/usage" -H "Authorization: Bearer ${accessToken}" -H "anthropic-beta: oauth-2025-04-20" -H "User-Agent: claude-code/2.1.5"`;
455
+ const curlCmd = `curl -sf --max-time 8 "https://api.anthropic.com/api/oauth/usage" -H "Authorization: Bearer ${accessToken}" -H "anthropic-beta: oauth-2025-04-20" -H "User-Agent: claude-code/2.1.5"`;
432
456
  debug("running curl...");
433
457
  const { stdout: stdout5 } = await execAsync(curlCmd, { timeout: 9e3 });
434
458
  debug("curl stdout length:", stdout5.length, "first 100:", stdout5.slice(0, 100));
@@ -449,23 +473,26 @@ async function fetchUsageLimits() {
449
473
  snapshotAt: (/* @__PURE__ */ new Date()).toISOString()
450
474
  };
451
475
  debug("returning snapshot:", result.fiveHour, result.sevenDay);
476
+ writeCache(result);
452
477
  return result;
453
478
  } catch (err) {
454
479
  debug("caught error:", err instanceof Error ? err.message : String(err));
455
- return null;
480
+ const stale = readCache(true);
481
+ if (stale) debug("returning stale cache as fallback:", stale.fiveHour, stale.sevenDay);
482
+ return stale;
456
483
  }
457
484
  }
458
485
 
459
486
  // src/commands/sync.ts
460
487
  var SYNC_FORMAT_VERSION = "6";
461
488
  function getSyncVersionPath() {
462
- return join4(homedir4(), CCCLUB_CONFIG_DIR, "sync-version");
489
+ return join5(homedir5(), CCCLUB_CONFIG_DIR, "sync-version");
463
490
  }
464
491
  function needsFullSync() {
465
492
  const path = getSyncVersionPath();
466
493
  if (!existsSync3(path)) return true;
467
494
  try {
468
- const stored = readFileSync2(path, "utf-8").trim();
495
+ const stored = readFileSync3(path, "utf-8").trim();
469
496
  return stored !== SYNC_FORMAT_VERSION;
470
497
  } catch {
471
498
  return true;
@@ -477,13 +504,13 @@ async function syncCommand(options) {
477
504
  if (options.silent && !options.full) {
478
505
  if (existsSync3(timePath)) {
479
506
  try {
480
- const ts = parseInt(readFileSync2(timePath, "utf-8").trim(), 10);
507
+ const ts = parseInt(readFileSync3(timePath, "utf-8").trim(), 10);
481
508
  if (Date.now() - ts < THROTTLE_MS) return;
482
509
  } catch {
483
510
  }
484
511
  }
485
512
  try {
486
- writeFileSync(timePath, String(Date.now()));
513
+ writeFileSync2(timePath, String(Date.now()));
487
514
  } catch {
488
515
  }
489
516
  }
@@ -492,7 +519,7 @@ async function syncCommand(options) {
492
519
  } catch {
493
520
  if (options.silent) {
494
521
  try {
495
- writeFileSync(timePath, "0");
522
+ writeFileSync2(timePath, "0");
496
523
  } catch {
497
524
  }
498
525
  }
@@ -780,17 +807,17 @@ import Table from "cli-table3";
780
807
  import ora4 from "ora";
781
808
 
782
809
  // src/update-check.ts
783
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync4 } from "fs";
784
- import { join as join5 } from "path";
785
- import { homedir as homedir5 } from "os";
810
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync4 } from "fs";
811
+ import { join as join6 } from "path";
812
+ import { homedir as homedir6 } from "os";
786
813
  var CHECK_INTERVAL_MS = 12 * 60 * 60 * 1e3;
787
- var CHECK_FILE = join5(homedir5(), CCCLUB_CONFIG_DIR, "last-update-check");
814
+ var CHECK_FILE = join6(homedir6(), CCCLUB_CONFIG_DIR, "last-update-check");
788
815
  var pendingCheck = null;
789
816
  function startUpdateCheck(currentVersion) {
790
817
  if (process.argv.includes("--silent") || process.argv.includes("-s")) return;
791
818
  try {
792
819
  if (existsSync4(CHECK_FILE)) {
793
- const ts = parseInt(readFileSync3(CHECK_FILE, "utf-8").trim(), 10);
820
+ const ts = parseInt(readFileSync4(CHECK_FILE, "utf-8").trim(), 10);
794
821
  if (Date.now() - ts < CHECK_INTERVAL_MS) return;
795
822
  }
796
823
  } catch {
@@ -806,7 +833,7 @@ function startUpdateCheck(currentVersion) {
806
833
  return { latest: data.version, current: currentVersion };
807
834
  }
808
835
  try {
809
- writeFileSync2(CHECK_FILE, String(Date.now()));
836
+ writeFileSync3(CHECK_FILE, String(Date.now()));
810
837
  } catch {
811
838
  }
812
839
  return null;
@@ -1360,7 +1387,7 @@ async function hookCommand() {
1360
1387
  }
1361
1388
 
1362
1389
  // src/index.ts
1363
- var VERSION = "0.2.78";
1390
+ var VERSION = "0.2.79";
1364
1391
  startUpdateCheck(VERSION);
1365
1392
  var program = new Command();
1366
1393
  program.name("ccclub").description("Claude Code leaderboard among friends").version(VERSION, "-v, -V, --version");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccclub",
3
- "version": "0.2.78",
3
+ "version": "0.2.79",
4
4
  "type": "module",
5
5
  "description": "Claude Code leaderboard among friends",
6
6
  "bin": {
@@ -12,6 +12,7 @@
12
12
  ],
13
13
  "scripts": {
14
14
  "build": "tsup src/index.ts --format esm --dts --clean",
15
+ "prepublishOnly": "npm run build",
15
16
  "postinstall": "node scripts/postinstall.cjs",
16
17
  "dev": "tsx src/index.ts",
17
18
  "test": "vitest run"