From 69101a9348bf06f2ac51daa12ea2b9d02b1c0c2f Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Tue, 4 Aug 2026 21:24:36 +0300 Subject: [PATCH] take named options in makeSessionHooks Co-Authored-By: Claude Fable 5 --- .../session/__tests__/session-core-test.ts | 60 +++++++++---------- src/state/session/create-account.ts | 8 +-- src/state/session/session-core.ts | 42 +++++++------ 3 files changed, 58 insertions(+), 52 deletions(-) diff --git a/src/state/session/__tests__/session-core-test.ts b/src/state/session/__tests__/session-core-test.ts index bb1896d389..9dbc646c9f 100644 --- a/src/state/session/__tests__/session-core-test.ts +++ b/src/state/session/__tests__/session-core-test.ts @@ -425,11 +425,11 @@ describe('makeSessionHooks arm-latch + event mapping', () => { >() /* the hook only passes this through by identity; a stub bundle suffices */ const bundle = {} as SessionBundle - const hooks = makeSessionHooks( + const hooks = makeSessionHooks({ onSessionChange, - () => bundle, - () => DID, - ) + getBundle: () => bundle, + getDid: () => DID, + }) return {onSessionChange, bundle, hooks} } @@ -528,11 +528,11 @@ describe('session-hook payload threading (pre-commit ordering)', () => { refreshedAccountAtHookTime = deriveRefreshedAccount(event, sessionData) }, ) - const hooks = makeSessionHooks( + const hooks = makeSessionHooks({ onSessionChange, - () => ({}) as SessionBundle, - () => DID, - ) + getBundle: () => ({}) as SessionBundle, + getDid: () => DID, + }) session = new PasswordSession(sessionAccountToSessionData(makeAccount()), { ...hooks, fetch: asFetch(fetchMock), @@ -573,11 +573,11 @@ describe('session-hook payload threading (pre-commit ordering)', () => { refreshedAccountAtHookTime = deriveRefreshedAccount(event, sessionData) }, ) - const hooks = makeSessionHooks( + const hooks = makeSessionHooks({ onSessionChange, - () => ({}) as SessionBundle, - () => DID, - ) + getBundle: () => ({}) as SessionBundle, + getDid: () => DID, + }) const session = new PasswordSession( sessionAccountToSessionData(makeAccount()), {...hooks, fetch: asFetch(fetchMock)}, @@ -606,11 +606,11 @@ describe('session-hook payload threading (pre-commit ordering)', () => { */ describe('disposeBundle kill-switch', () => { it('the injected fetch throws after disposeBundle', () => { - const hooks = makeSessionHooks( - jest.fn(), - () => ({}) as SessionBundle, - () => DID, - ) + const hooks = makeSessionHooks({ + onSessionChange: jest.fn(), + getBundle: () => ({}) as SessionBundle, + getDid: () => DID, + }) /* the injected fetch is the kill-switch wrapper makeSessionHooks bakes in */ const injectedFetch = hooks.fetch! @@ -734,11 +734,11 @@ describe('PasswordSession.refresh through armed hooks', () => { (bundle: SessionBundle, did: string, event: AtpSessionEvent) => void >() const bundle = {} as SessionBundle - const hooks = makeSessionHooks( + const hooks = makeSessionHooks({ onSessionChange, - () => bundle, - () => DID, - ) + getBundle: () => bundle, + getDid: () => DID, + }) /* * makeSessionHooks bakes in networkAwareFetch (the real global fetch); * override it with the mock while keeping the arm-latched callbacks (they @@ -957,11 +957,11 @@ describe('a session destroyed or rejected during preparation', () => { }) it('finishPreparation disposes and rethrows without running the snapshot', async () => { - const hooks = makeSessionHooks( - jest.fn(), - () => bundle, - () => DID, - ) + const hooks = makeSessionHooks({ + onSessionChange: jest.fn(), + getBundle: () => bundle, + getDid: () => DID, + }) const session = new PasswordSession( sessionAccountToSessionData(makeAccount()), {...hooks, fetch: asFetch(makeMockFetch())}, @@ -997,11 +997,11 @@ describe('a throwing onSessionChange does not brick the session', () => { throw new Error('reducer side effect exploded') }) let bundle!: SessionBundle - const hooks = makeSessionHooks( + const hooks = makeSessionHooks({ onSessionChange, - () => bundle, - () => DID, - ) + getBundle: () => bundle, + getDid: () => DID, + }) const session = new PasswordSession( sessionAccountToSessionData(makeAccount()), {...hooks, fetch: asFetch(fetchMock)}, diff --git a/src/state/session/create-account.ts b/src/state/session/create-account.ts index 989ca1d36c..fd67681482 100644 --- a/src/state/session/create-account.ts +++ b/src/state/session/create-account.ts @@ -58,11 +58,11 @@ export async function createSessionBundleAndCreateAccount( ): Promise<{account: SessionAccount; bundle: SessionBundle}> { let bundle!: SessionBundle let accountDid = '' - const hooks = makeSessionHooks( + const hooks = makeSessionHooks({ onSessionChange, - () => bundle, - () => accountDid, - ) + getBundle: () => bundle, + getDid: () => accountDid, + }) const session = await PasswordSession.createAccount( { diff --git a/src/state/session/session-core.ts b/src/state/session/session-core.ts index 3ecd200e1d..5e3a9e8a8f 100644 --- a/src/state/session/session-core.ts +++ b/src/state/session/session-core.ts @@ -114,13 +114,19 @@ export type OnSessionChange = ( /** * Hooks stay inert during initial session preparation. `kill()` disarms them * and disables the injected fetch so a disposed session cannot refresh or - * dispatch. The bundle getters are deferred because hooks are created first. + * dispatch. */ -export function makeSessionHooks( - onSessionChange: OnSessionChange, - getBundle: () => SessionBundle, - getDid: () => string, -) { +export function makeSessionHooks({ + onSessionChange, + getBundle, + getDid, +}: { + onSessionChange: OnSessionChange + /** Deferred: hooks are created before the bundle exists. */ + getBundle: () => SessionBundle + /** Deferred: hooks are created before the bundle exists. */ + getDid: () => string +}) { let armed = false let killed = false const dispatch = (event: AtpSessionEvent, sessionData?: SessionData) => { @@ -247,11 +253,11 @@ export async function createSessionBundleAndResume( ): Promise<{account: SessionAccount; bundle: SessionBundle}> { const gates = features.refresh({strategy: 'prefer-low-latency'}) let bundle!: SessionBundle - const hooks = makeSessionHooks( + const hooks = makeSessionHooks({ onSessionChange, - () => bundle, - () => storedAccount.did, - ) + getBundle: () => bundle, + getDid: () => storedAccount.did, + }) let session: PasswordSession const sessionData = sessionAccountToSessionData(storedAccount) @@ -326,11 +332,11 @@ export async function createSessionBundleAndLogin( ): Promise<{account: SessionAccount; bundle: SessionBundle}> { let bundle!: SessionBundle let accountDid = '' - const hooks = makeSessionHooks( + const hooks = makeSessionHooks({ onSessionChange, - () => bundle, - () => accountDid, - ) + getBundle: () => bundle, + getDid: () => accountDid, + }) const session = await PasswordSession.login({ ...hooks, @@ -376,11 +382,11 @@ export function createSessionBundleFromStoredAccount( ) => boolean = () => true, ): {account: SessionAccount; bundle: SessionBundle} | undefined { let bundle!: SessionBundle - const hooks = makeSessionHooks( + const hooks = makeSessionHooks({ onSessionChange, - () => bundle, - () => storedAccount.did, - ) + getBundle: () => bundle, + getDid: () => storedAccount.did, + }) const session = new PasswordSession( sessionAccountToSessionData(storedAccount), hooks,