@cortexkit/anthropic-auth-core
Advanced tools
+36
-14
| import { createHash, randomUUID } from 'node:crypto'; | ||
| import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'; | ||
| import { mkdir, readFile, rename, rm, stat, writeFile } from 'node:fs/promises'; | ||
| import { homedir } from 'node:os'; | ||
@@ -24,2 +24,3 @@ import { dirname, join } from 'node:path'; | ||
| const BACKGROUND_TICK_MS = 60_000; | ||
| const BACKGROUND_TICK_JITTER_MS = 60_000; | ||
| function getConfigDir() { | ||
@@ -166,16 +167,27 @@ if (process.env.OPENCODE_CONFIG_DIR?.trim()) { | ||
| const accountPath = options.path ?? getAccountStoragePath(); | ||
| const lockDir = `${accountPath}.${options.name}.lock`; | ||
| const ownerPath = join(lockDir, 'owner.json'); | ||
| const lockPath = `${accountPath}.${options.name}.lock`; | ||
| const legacyOwnerPath = join(lockPath, 'owner.json'); | ||
| const ownerId = randomUUID(); | ||
| const now = options.now ?? Date.now; | ||
| async function readOwner() { | ||
| try { | ||
| return JSON.parse(await readFile(lockPath, 'utf8')); | ||
| } | ||
| catch (error) { | ||
| const code = error.code; | ||
| if (code !== 'EISDIR') | ||
| throw error; | ||
| return JSON.parse(await readFile(legacyOwnerPath, 'utf8')); | ||
| } | ||
| } | ||
| async function tryAcquire() { | ||
| try { | ||
| await mkdir(lockDir, { mode: 0o700 }); | ||
| await writeFile(ownerPath, `${JSON.stringify({ ownerId, expiresAt: now() + options.ttlMs })}\n`, { encoding: 'utf8', mode: 0o600 }); | ||
| await writeFile(lockPath, `${JSON.stringify({ ownerId, expiresAt: now() + options.ttlMs })}\n`, { encoding: 'utf8', mode: 0o600, flag: 'wx' }); | ||
| return true; | ||
| } | ||
| catch (error) { | ||
| if (error.code !== 'EEXIST') | ||
| throw error; | ||
| return false; | ||
| const code = error.code; | ||
| if (code === 'EEXIST' || code === 'EISDIR') | ||
| return false; | ||
| throw error; | ||
| } | ||
@@ -185,3 +197,3 @@ } | ||
| try { | ||
| const owner = JSON.parse(await readFile(ownerPath, 'utf8')); | ||
| const owner = await readOwner(); | ||
| if (Number(owner?.expiresAt) > now()) | ||
@@ -191,5 +203,12 @@ return null; | ||
| catch { | ||
| // Broken owner metadata is treated as stale. | ||
| try { | ||
| const current = await stat(lockPath); | ||
| if (current.mtimeMs + options.ttlMs > Date.now()) | ||
| return null; | ||
| } | ||
| catch { | ||
| return null; | ||
| } | ||
| } | ||
| await rm(lockDir, { recursive: true, force: true }).catch(() => { }); | ||
| await rm(lockPath, { recursive: true, force: true }).catch(() => { }); | ||
| if (!(await tryAcquire())) | ||
@@ -201,3 +220,3 @@ return null; | ||
| try { | ||
| const owner = JSON.parse(await readFile(ownerPath, 'utf8')); | ||
| const owner = await readOwner(); | ||
| if (owner?.ownerId !== ownerId) | ||
@@ -209,3 +228,3 @@ return; | ||
| } | ||
| await rm(lockDir, { recursive: true, force: true }).catch(() => { }); | ||
| await rm(lockPath, { recursive: true, force: true }).catch(() => { }); | ||
| }, | ||
@@ -336,2 +355,5 @@ }; | ||
| } | ||
| function jitterMs(maxMs) { | ||
| return Math.floor(Math.random() * Math.max(0, maxMs)); | ||
| } | ||
| function refreshBeforeExpiryMs(storage) { | ||
@@ -541,3 +563,3 @@ const minutes = storage?.refresh?.refreshBeforeExpiryMinutes ?? | ||
| void run().catch(() => { }); | ||
| }, BACKGROUND_TICK_MS); | ||
| }, BACKGROUND_TICK_MS + jitterMs(BACKGROUND_TICK_JITTER_MS)); | ||
| if ('unref' in this.refreshTimer) | ||
@@ -544,0 +566,0 @@ this.refreshTimer.unref(); |
+1
-1
| { | ||
| "name": "@cortexkit/anthropic-auth-core", | ||
| "version": "1.2.1", | ||
| "version": "1.2.2", | ||
| "type": "module", | ||
@@ -5,0 +5,0 @@ "repository": { |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
152359
0.44%3764
0.59%