Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
2.4 kB · 70 lines
TypeScript
at main
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071import type { SecureStorage, SecureStorageData } from './types.js'
/** * Creates a fallback storage that tries to use the primary storage first, * and if that fails, falls back to the secondary storage */export function createFallbackStorage( primary: SecureStorage, secondary: SecureStorage,): SecureStorage { return { name: `${primary.name}-with-${secondary.name}-fallback`, read(): SecureStorageData { const result = primary.read() if (result !== null && result !== undefined) { return result } return secondary.read() || {} }, async readAsync(): Promise<SecureStorageData | null> { const result = await primary.readAsync() if (result !== null && result !== undefined) { return result } return (await secondary.readAsync()) || {} }, update(data: SecureStorageData): { success: boolean; warning?: string } { // Capture state before update const primaryDataBefore = primary.read()
const result = primary.update(data)
if (result.success) { // Delete secondary when migrating to primary for the first time // This preserves credentials when sharing .claude between host and containers // See: https://github.com/anthropics/claude-code/issues/1414 if (primaryDataBefore === null) { secondary.delete() } return result }
const fallbackResult = secondary.update(data)
if (fallbackResult.success) { // Primary write failed but primary may still hold an *older* valid // entry. read() prefers primary whenever it returns non-null, so that // stale entry would shadow the fresh data we just wrote to secondary — // e.g. a refresh token the server has already rotated away, causing a // /login loop (#30337). Best-effort delete; if this also fails the // user's keychain is in a bad state we can't fix from here. if (primaryDataBefore !== null) { primary.delete() } return { success: true, warning: fallbackResult.warning, } }
return { success: false } }, delete(): boolean { const primarySuccess = primary.delete() const secondarySuccess = secondary.delete()
return primarySuccess || secondarySuccess }, }}