@pixelume/sdk 0.3.0 → 0.5.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"AuthModule.js","sourceRoot":"","sources":["../../../src/modules/auth/AuthModule.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n parseEmptyResponse,\n parseOAuthTokenResponse,\n parsePlayerEnvelope,\n} from '../../contracts/index.js';\nimport {\n PixelumeAuthError,\n PixelumeConfigError,\n PixelumeHttpError,\n isPixelumeError,\n type PixelumeError,\n} from '../../core/errors.js';\nimport type {\n PixelumeBrowserAdapter,\n PixelumeRequestOptions,\n PixelumeSessionStorage,\n} from '../../core/types.js';\nimport type { ResolvedConfig } from '../../core/config.js';\nimport type { HttpClient } from '../../http/HttpClient.js';\n\nconst AUTHORIZATION_REQUEST_TTL_MS = 10 * 60_000;\nconst TOKEN_EXPIRY_SKEW_MS = 5_000;\nconst CALLBACK_PARAMETERS = ['code', 'state', 'error', 'error_description'] as const;\n\nexport interface PixelumePlayer {\n readonly id: string;\n readonly displayName: string;\n readonly avatarUrl: string | null;\n}\n\nexport type PixelumeAnonymousReason = 'visitor' | 'cancelled' | 'expired' | 'logged_out' | 'error';\n\nexport type PixelumeAuthState =\n | { readonly status: 'uninitialized'; readonly player: null }\n | { readonly status: 'redirecting'; readonly player: null }\n | { readonly status: 'exchanging'; readonly player: null }\n | {\n readonly status: 'anonymous';\n readonly player: null;\n readonly reason: PixelumeAnonymousReason;\n readonly error: PixelumeError | null;\n }\n | { readonly status: 'authenticated'; readonly player: PixelumePlayer };\n\nexport type PixelumeAuthListener = (state: PixelumeAuthState, previous: PixelumeAuthState) => void;\n\nexport interface PixelumeLoginOptions {\n /** OAuth scope. The current API accepts only `profile`. */\n readonly scope?: 'profile';\n}\n\nexport interface PixelumeAuthApi {\n /** Current synchronous authentication state. */\n readonly state: PixelumeAuthState;\n /** Starts a top-level redirect to the API authorization endpoint. */\n login(options?: PixelumeLoginOptions): Promise<void>;\n /** Returns the current player, revalidating the memory-only access token with the API. */\n getPlayer(options?: PixelumeRequestOptions): Promise<PixelumePlayer | null>;\n /** Revokes this game's access token and clears local authentication state. */\n logout(options?: PixelumeRequestOptions): Promise<void>;\n /** Subscribes to state changes. The returned function removes the listener. */\n subscribe(listener: PixelumeAuthListener): () => void;\n}\n\ninterface PendingAuthorization {\n readonly version: 1;\n readonly state: string;\n readonly verifier: string;\n readonly redirectUri: string;\n readonly createdAt: number;\n}\n\ninterface AccessToken {\n readonly value: string;\n readonly expiresAt: number;\n}\n\nexport class AuthModule implements PixelumeAuthApi {\n readonly #http: HttpClient;\n readonly #config: ResolvedConfig;\n readonly #listeners = new Set<PixelumeAuthListener>();\n #state: PixelumeAuthState = Object.freeze({ status: 'uninitialized', player: null });\n #token: AccessToken | null = null;\n #initializePromise: Promise<PixelumeAuthState> | null = null;\n #loginPromise: Promise<void> | null = null;\n #playerPromise: Promise<PixelumePlayer | null> | null = null;\n #logoutPromise: Promise<void> | null = null;\n\n constructor(http: HttpClient, config: ResolvedConfig) {\n this.#http = http;\n this.#config = config;\n }\n\n get state(): PixelumeAuthState {\n return this.#state;\n }\n\n initialize(): Promise<PixelumeAuthState> {\n this.#initializePromise ??= this.#doInitialize();\n return this.#initializePromise;\n }\n\n subscribe(listener: PixelumeAuthListener): () => void {\n this.#listeners.add(listener);\n return () => this.#listeners.delete(listener);\n }\n\n login(options: PixelumeLoginOptions = {}): Promise<void> {\n const scope: unknown = options.scope;\n if (scope !== undefined && scope !== 'profile') {\n return Promise.reject(\n new PixelumeConfigError('Pixelume Auth supports only the \"profile\" scope'),\n );\n }\n this.#loginPromise ??= this.#doLogin().finally(() => {\n this.#loginPromise = null;\n });\n return this.#loginPromise;\n }\n\n getPlayer(options: PixelumeRequestOptions = {}): Promise<PixelumePlayer | null> {\n if (this.#token === null) return Promise.resolve(null);\n if (this.#token.expiresAt <= Date.now() + TOKEN_EXPIRY_SKEW_MS) {\n this.#token = null;\n this.#setState(anonymous('expired'));\n return Promise.resolve(null);\n }\n this.#playerPromise ??= this.#fetchPlayer(options).finally(() => {\n this.#playerPromise = null;\n });\n return this.#playerPromise;\n }\n\n logout(options: PixelumeRequestOptions = {}): Promise<void> {\n this.#logoutPromise ??= this.#doLogout(options).finally(() => {\n this.#logoutPromise = null;\n });\n return this.#logoutPromise;\n }\n\n async #doInitialize(): Promise<PixelumeAuthState> {\n try {\n const browser = this.#browser();\n const callback = this.#readCallback(browser.currentUrl());\n if (callback !== null) {\n await this.#handleCallback(browser, callback);\n } else if (this.#config.restoreSession && this.#readSessionHint(browser.sessionStorage)) {\n this.#removeSessionHint(browser.sessionStorage);\n await this.login();\n } else {\n this.#setState(anonymous('visitor'));\n }\n } catch (error) {\n const failure = isPixelumeError(error)\n ? error\n : new PixelumeAuthError('browser_unavailable', { cause: error });\n this.#setState(anonymous('error', failure));\n }\n return this.#state;\n }\n\n async #doLogin(): Promise<void> {\n const clientId = this.#requireClientId();\n const redirectUri = this.#requireRedirectUri();\n const browser = this.#browser();\n let pending = this.#readPending(browser.sessionStorage);\n if (pending === null || pending.redirectUri !== redirectUri || this.#isExpired(pending)) {\n pending = {\n version: 1,\n state: randomBase64Url(browser.crypto),\n verifier: randomBase64Url(browser.crypto),\n redirectUri,\n createdAt: Date.now(),\n };\n this.#writePending(browser.sessionStorage, pending);\n }\n const challenge = await sha256Base64Url(browser.crypto, pending.verifier);\n const authorization = new URL('/v1/oauth/authorize', this.#config.apiUrl);\n authorization.search = new URLSearchParams({\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: 'code',\n state: pending.state,\n code_challenge: challenge,\n code_challenge_method: 'S256',\n scope: 'profile',\n }).toString();\n this.#setState(Object.freeze({ status: 'redirecting', player: null }));\n try {\n browser.navigate(authorization.toString());\n } catch (cause) {\n this.#removePending(browser.sessionStorage);\n throw new PixelumeAuthError('browser_unavailable', { cause });\n }\n }\n\n async #handleCallback(\n browser: PixelumeBrowserAdapter,\n callback: {\n readonly url: URL;\n readonly code: string | null;\n readonly error: string | null;\n readonly invalid: boolean;\n },\n ): Promise<void> {\n const pending = this.#readPending(browser.sessionStorage);\n this.#removePending(browser.sessionStorage);\n this.#cleanCallback(browser, callback.url);\n\n if (callback.invalid) throw new PixelumeAuthError('invalid_callback');\n if (pending === null || this.#isExpired(pending)) {\n this.#removeSessionHint(browser.sessionStorage);\n throw new PixelumeAuthError(pending === null ? 'invalid_callback' : 'authorization_expired');\n }\n if (\n pending.redirectUri !== this.#config.redirectUri ||\n (callback.code !== null && !/^[A-Za-z0-9_-]{43,128}$/u.test(callback.code))\n ) {\n throw new PixelumeAuthError('invalid_callback');\n }\n const returnedState = singleParameter(callback.url, 'state');\n if (returnedState === null || returnedState !== pending.state) {\n this.#removeSessionHint(browser.sessionStorage);\n throw new PixelumeAuthError('state_mismatch');\n }\n if (callback.error !== null) {\n this.#removeSessionHint(browser.sessionStorage);\n if (callback.error === 'access_denied') {\n this.#setState(anonymous('cancelled'));\n return;\n }\n throw new PixelumeAuthError('invalid_callback');\n }\n if (callback.code === null) throw new PixelumeAuthError('invalid_callback');\n\n this.#setState(Object.freeze({ status: 'exchanging', player: null }));\n const response = await this.#http.request({\n method: 'POST',\n path: '/v1/oauth/token',\n credentials: 'omit',\n form: {\n grant_type: 'authorization_code',\n code: callback.code,\n client_id: this.#requireClientId(),\n redirect_uri: pending.redirectUri,\n code_verifier: pending.verifier,\n },\n parse: parseOAuthTokenResponse,\n });\n this.#token = {\n value: response.data.access_token,\n expiresAt: Date.now() + response.data.expires_in * 1_000,\n };\n const player = await this.getPlayer();\n if (player !== null) this.#writeSessionHint(browser.sessionStorage);\n }\n\n async #fetchPlayer(options: PixelumeRequestOptions): Promise<PixelumePlayer | null> {\n const token = this.#token;\n if (token === null) return null;\n try {\n const response = await this.#http.request({\n method: 'GET',\n path: '/v1/oauth/userinfo',\n credentials: 'omit',\n headers: { authorization: `Bearer ${token.value}` },\n signal: options.signal,\n timeoutMs: options.timeoutMs,\n parse: parsePlayerEnvelope,\n });\n const player = Object.freeze({ ...response.data.player });\n this.#setState(Object.freeze({ status: 'authenticated', player }));\n return player;\n } catch (error) {\n if (error instanceof PixelumeHttpError && error.status === 401) {\n this.#token = null;\n this.#setState(anonymous('expired'));\n return null;\n }\n throw error;\n }\n }\n\n async #doLogout(options: PixelumeRequestOptions): Promise<void> {\n const token = this.#token;\n this.#token = null;\n const browser = this.#optionalBrowser();\n if (browser) {\n this.#removePending(browser.sessionStorage);\n this.#removeSessionHint(browser.sessionStorage);\n }\n this.#setState(anonymous('logged_out'));\n if (token === null) return;\n await this.#http.request({\n method: 'POST',\n path: '/v1/oauth/revoke',\n credentials: 'omit',\n form: { token: token.value, token_type_hint: 'access_token' },\n signal: options.signal,\n timeoutMs: options.timeoutMs,\n parse: parseEmptyResponse,\n });\n }\n\n #readCallback(value: string): {\n readonly url: URL;\n readonly code: string | null;\n readonly error: string | null;\n readonly invalid: boolean;\n } | null {\n const redirectUri = this.#config.redirectUri;\n if (redirectUri === null) return null;\n const current = new URL(value);\n const expected = new URL(redirectUri);\n if (current.origin !== expected.origin || current.pathname !== expected.pathname) return null;\n const hasCallbackParameter = CALLBACK_PARAMETERS.some((key) => current.searchParams.has(key));\n if (!hasCallbackParameter) return null;\n const code = singleParameter(current, 'code');\n const error = singleParameter(current, 'error');\n return {\n url: current,\n code,\n error,\n invalid: !sameCallbackBase(current, expected) || (code === null) === (error === null),\n };\n }\n\n #cleanCallback(browser: PixelumeBrowserAdapter, url: URL): void {\n const clean = new URL(url.toString());\n for (const key of CALLBACK_PARAMETERS) clean.searchParams.delete(key);\n browser.replaceUrl(`${clean.pathname}${clean.search}${clean.hash}`);\n }\n\n #browser(): PixelumeBrowserAdapter {\n const browser = this.#optionalBrowser();\n if (!browser) throw new PixelumeAuthError('browser_unavailable');\n if (\n typeof browser.crypto.getRandomValues !== 'function' ||\n typeof browser.crypto.subtle.digest !== 'function'\n ) {\n throw new PixelumeAuthError('crypto_unavailable');\n }\n return browser;\n }\n\n #optionalBrowser(): PixelumeBrowserAdapter | null {\n if (this.#config.browser) return this.#config.browser;\n try {\n if (\n typeof globalThis.location === 'undefined' ||\n typeof globalThis.history === 'undefined' ||\n typeof globalThis.sessionStorage === 'undefined' ||\n typeof globalThis.crypto === 'undefined'\n ) {\n return null;\n }\n return {\n currentUrl: () => globalThis.location.href,\n navigate: (url) => {\n globalThis.location.assign(url);\n },\n replaceUrl: (url) => {\n globalThis.history.replaceState(globalThis.history.state, '', url);\n },\n sessionStorage: globalThis.sessionStorage,\n crypto: globalThis.crypto,\n };\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #requireClientId(): string {\n if (this.#config.clientId === null) {\n throw new PixelumeConfigError('Pixelume Auth requires clientId or gameId');\n }\n return this.#config.clientId;\n }\n\n #requireRedirectUri(): string {\n if (this.#config.redirectUri === null) {\n throw new PixelumeAuthError('browser_unavailable');\n }\n return this.#config.redirectUri;\n }\n\n #pendingKey(): string {\n return `pixelume.oauth.pending.${this.#config.clientId ?? 'unconfigured'}`;\n }\n\n #hintKey(): string {\n return `pixelume.oauth.session.${this.#config.clientId ?? 'unconfigured'}`;\n }\n\n #readPending(storage: PixelumeSessionStorage): PendingAuthorization | null {\n try {\n const raw = storage.getItem(this.#pendingKey());\n if (raw === null) return null;\n const value: unknown = JSON.parse(raw);\n if (!isPendingAuthorization(value)) {\n storage.removeItem(this.#pendingKey());\n return null;\n }\n return value;\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #writePending(storage: PixelumeSessionStorage, pending: PendingAuthorization): void {\n try {\n storage.setItem(this.#pendingKey(), JSON.stringify(pending));\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #removePending(storage: PixelumeSessionStorage): void {\n try {\n storage.removeItem(this.#pendingKey());\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #readSessionHint(storage: PixelumeSessionStorage): boolean {\n try {\n return storage.getItem(this.#hintKey()) === '1';\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #writeSessionHint(storage: PixelumeSessionStorage): void {\n try {\n storage.setItem(this.#hintKey(), '1');\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #removeSessionHint(storage: PixelumeSessionStorage): void {\n try {\n storage.removeItem(this.#hintKey());\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #isExpired(pending: PendingAuthorization): boolean {\n const now = Date.now();\n return (\n pending.createdAt > now + 60_000 || pending.createdAt + AUTHORIZATION_REQUEST_TTL_MS < now\n );\n }\n\n #setState(state: PixelumeAuthState): void {\n const previous = this.#state;\n if (sameState(previous, state)) return;\n this.#state = state;\n for (const listener of [...this.#listeners]) listener(state, previous);\n }\n}\n\nfunction anonymous(\n reason: PixelumeAnonymousReason,\n error: PixelumeError | null = null,\n): PixelumeAuthState {\n return Object.freeze({ status: 'anonymous', player: null, reason, error });\n}\n\nfunction isPendingAuthorization(value: unknown): value is PendingAuthorization {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const pending = value as Record<string, unknown>;\n return (\n pending.version === 1 &&\n typeof pending.state === 'string' &&\n /^[A-Za-z0-9_-]{43}$/u.test(pending.state) &&\n typeof pending.verifier === 'string' &&\n /^[A-Za-z0-9_-]{43}$/u.test(pending.verifier) &&\n typeof pending.redirectUri === 'string' &&\n typeof pending.createdAt === 'number' &&\n Number.isFinite(pending.createdAt)\n );\n}\n\nfunction sameCallbackBase(current: URL, expected: URL): boolean {\n if (current.origin !== expected.origin || current.pathname !== expected.pathname) return false;\n const currentBase = new URL(current.toString());\n for (const key of CALLBACK_PARAMETERS) currentBase.searchParams.delete(key);\n currentBase.hash = '';\n const expectedBase = new URL(expected.toString());\n expectedBase.hash = '';\n return currentBase.toString() === expectedBase.toString();\n}\n\nfunction singleParameter(url: URL, name: string): string | null {\n const values = url.searchParams.getAll(name);\n if (values.length !== 1 || values[0] === '') return null;\n return values[0] ?? null;\n}\n\nfunction randomBase64Url(crypto: Crypto): string {\n const bytes = crypto.getRandomValues(new Uint8Array(32));\n return bytesToBase64Url(bytes);\n}\n\nasync function sha256Base64Url(crypto: Crypto, value: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(value));\n return bytesToBase64Url(new Uint8Array(digest));\n}\n\nfunction bytesToBase64Url(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary).replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/u, '');\n}\n\nfunction sameState(left: PixelumeAuthState, right: PixelumeAuthState): boolean {\n if (left.status !== right.status) return false;\n if (left.status === 'authenticated' && right.status === 'authenticated') {\n return left.player === right.player;\n }\n if (left.status === 'anonymous' && right.status === 'anonymous') {\n return left.reason === right.reason && left.error === right.error;\n }\n return true;\n}\n"]}
1
+ {"version":3,"file":"AuthModule.js","sourceRoot":"","sources":["../../../src/modules/auth/AuthModule.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n parseEmptyResponse,\n parseOAuthTokenResponse,\n parsePlayerEnvelope,\n} from '../../contracts/index.js';\nimport {\n PixelumeAuthError,\n PixelumeConfigError,\n isPixelumeError,\n type PixelumeError,\n} from '../../core/errors.js';\nimport type {\n PixelumeBrowserAdapter,\n PixelumeRequestOptions,\n PixelumeSessionStorage,\n} from '../../core/types.js';\nimport type { ResolvedConfig } from '../../core/config.js';\nimport type { HttpClient } from '../../http/HttpClient.js';\nimport {\n SessionManager,\n browserResumeSource,\n type PixelumeSessionListener,\n type PixelumeSessionState,\n} from './SessionManager.js';\n\nconst AUTHORIZATION_REQUEST_TTL_MS = 10 * 60_000;\nconst CALLBACK_PARAMETERS = ['code', 'state', 'error', 'error_description'] as const;\n/** `prompt=none` answers meaning \"the central session cannot authorize without a screen\". */\nconst SESSION_ENDED_ERRORS = new Set([\n 'login_required',\n 'consent_required',\n 'interaction_required',\n]);\n\nexport interface PixelumePlayer {\n readonly id: string;\n readonly displayName: string;\n readonly avatarUrl: string | null;\n}\n\n/**\n * Why there is no signed-in player:\n * - `visitor`: no login to restore in this tab/browser (or restoration is off). Not proof that the\n * central session ended.\n * - `cancelled`: the player cancelled the login in the portal.\n * - `expired`: a session that was running ended (renewal refused).\n * - `logged_out`: `auth.logout()`.\n * - `session_ended`: a cross-session restoration attempt found no valid central session\n * (`login_required`); the hint was removed and no further automatic attempt is made.\n * - `offline`: a cross-session restoration could not run or finish for lack of connectivity. The\n * hint is kept; the next start (or `login()`) tries again. Local progress is untouched.\n * - `error`: anything else; see `error`.\n */\nexport type PixelumeAnonymousReason =\n 'visitor' | 'cancelled' | 'expired' | 'logged_out' | 'session_ended' | 'offline' | 'error';\n\n/**\n * `restoring: true` marks the silent cross-session attempt (`restoreAcrossSessions`): the page is\n * leaving for a brief round trip without UI, or completing it. Interactive logins omit it.\n */\nexport type PixelumeAuthState =\n | { readonly status: 'uninitialized'; readonly player: null }\n | { readonly status: 'redirecting'; readonly player: null; readonly restoring?: true }\n | { readonly status: 'exchanging'; readonly player: null; readonly restoring?: true }\n | {\n readonly status: 'anonymous';\n readonly player: null;\n readonly reason: PixelumeAnonymousReason;\n readonly error: PixelumeError | null;\n }\n | { readonly status: 'authenticated'; readonly player: PixelumePlayer };\n\nexport type PixelumeAuthListener = (state: PixelumeAuthState, previous: PixelumeAuthState) => void;\n\n/**\n * OAuth scope requested at login. `profile` identifies the player; `profile saves` also allows\n * Cloud Saves and requires `saves` to be enabled for the game in the Pixelume Game Registry.\n */\nexport type PixelumeScopeRequest = 'profile' | 'profile saves';\n\nexport interface PixelumeLoginOptions {\n /** Defaults to the client `scope` option (`profile` unless configured). */\n readonly scope?: PixelumeScopeRequest;\n}\n\nexport interface PixelumeAuthApi {\n /** Current synchronous authentication state. */\n readonly state: PixelumeAuthState;\n /** Starts a top-level redirect to the API authorization endpoint. */\n login(options?: PixelumeLoginOptions): Promise<void>;\n /** Returns the current player, revalidating the memory-only access token with the API. */\n getPlayer(options?: PixelumeRequestOptions): Promise<PixelumePlayer | null>;\n /**\n * Revokes this game's authorization (refresh token family and access tokens) and clears local\n * authentication state. The central Pixelume session in the portal is not affected.\n */\n logout(options?: PixelumeRequestOptions): Promise<void>;\n /** Subscribes to state changes. The returned function removes the listener. */\n subscribe(listener: PixelumeAuthListener): () => void;\n /**\n * Token lifecycle of the signed-in player (scopes, expiry, renewal in flight, last transient\n * renewal error). Never exposes tokens.\n */\n readonly session: PixelumeSessionState;\n /** Subscribes to `session` changes. The returned function removes the listener. */\n subscribeSession(listener: PixelumeSessionListener): () => void;\n /**\n * Renews the access token now. Renewal is automatic; call this only to renew ahead of a\n * critical operation. Rejects with the transient error (the session is kept and retried) or\n * with `PixelumeAuthError` when there is no session or it ended.\n */\n refresh(options?: PixelumeRequestOptions): Promise<void>;\n}\n\ninterface PendingAuthorization {\n readonly version: 1;\n readonly state: string;\n readonly verifier: string;\n readonly redirectUri: string;\n readonly createdAt: number;\n /** Present on silent (`prompt=none`) attempts only. */\n readonly silent?: true;\n /** Scope of a silent attempt, to adjust the hint after `invalid_scope`. */\n readonly scope?: PixelumeScopeRequest;\n /** Same-origin path, query and hash of the page that started a silent attempt. */\n readonly returnTo?: string;\n}\n\n/** Non-secret cross-session hint kept in persistent storage. Never contains tokens or identity. */\ninterface PersistentHint {\n readonly version: 1;\n readonly scope: PixelumeScopeRequest;\n /** Time of the last successful authorization on this browser. */\n readonly at: number;\n}\n\nexport class AuthModule implements PixelumeAuthApi {\n readonly #http: HttpClient;\n readonly #config: ResolvedConfig;\n readonly #listeners = new Set<PixelumeAuthListener>();\n #state: PixelumeAuthState = Object.freeze({ status: 'uninitialized', player: null });\n readonly #session: SessionManager;\n #initializePromise: Promise<PixelumeAuthState> | null = null;\n #loginPromise: Promise<void> | null = null;\n #playerPromise: Promise<PixelumePlayer | null> | null = null;\n #logoutPromise: Promise<void> | null = null;\n /** True while a callback of a silent attempt is being completed. */\n #completingRestore = false;\n readonly #resume: ((onResume: () => void) => () => void) | null;\n #stopRestoreWatch: (() => void) | null = null;\n\n constructor(http: HttpClient, config: ResolvedConfig) {\n this.#http = http;\n this.#config = config;\n const browser = config.browser;\n this.#resume =\n browser !== undefined && typeof browser.subscribeResume === 'function'\n ? (onResume) => browser.subscribeResume?.(onResume) ?? (() => undefined)\n : browserResumeSource();\n this.#session = new SessionManager({\n http,\n clientId: () => this.#requireClientId(),\n resume: this.#resume,\n onEnded: (error) => {\n this.#setState(anonymous('expired', error));\n },\n });\n }\n\n get state(): PixelumeAuthState {\n return this.#state;\n }\n\n get session(): PixelumeSessionState {\n return this.#session.state;\n }\n\n /** @internal Shared with feature modules that call Bearer-protected routes. */\n get sessionManager(): SessionManager {\n return this.#session;\n }\n\n subscribeSession(listener: PixelumeSessionListener): () => void {\n return this.#session.subscribe(listener);\n }\n\n refresh(options: PixelumeRequestOptions = {}): Promise<void> {\n return this.#session.refresh(options);\n }\n\n /** @internal Releases timers/listeners and drops credentials from memory (no revocation). */\n dispose(): void {\n this.#stopRestoreWatch?.();\n this.#stopRestoreWatch = null;\n this.#session.dispose();\n this.#listeners.clear();\n }\n\n initialize(): Promise<PixelumeAuthState> {\n this.#initializePromise ??= this.#doInitialize();\n return this.#initializePromise;\n }\n\n subscribe(listener: PixelumeAuthListener): () => void {\n this.#listeners.add(listener);\n return () => this.#listeners.delete(listener);\n }\n\n login(options: PixelumeLoginOptions = {}): Promise<void> {\n const scope: unknown = options.scope ?? this.#config.scope;\n if (scope !== 'profile' && scope !== 'profile saves') {\n return Promise.reject(\n new PixelumeConfigError('Pixelume Auth scope must be \"profile\" or \"profile saves\"'),\n );\n }\n this.#loginPromise ??= this.#doLogin(scope, false).finally(() => {\n this.#loginPromise = null;\n });\n return this.#loginPromise;\n }\n\n getPlayer(options: PixelumeRequestOptions = {}): Promise<PixelumePlayer | null> {\n if (!this.#session.active) return Promise.resolve(null);\n this.#playerPromise ??= this.#fetchPlayer(options).finally(() => {\n this.#playerPromise = null;\n });\n return this.#playerPromise;\n }\n\n logout(options: PixelumeRequestOptions = {}): Promise<void> {\n this.#logoutPromise ??= this.#doLogout(options).finally(() => {\n this.#logoutPromise = null;\n });\n return this.#logoutPromise;\n }\n\n async #doInitialize(): Promise<PixelumeAuthState> {\n try {\n const browser = this.#browser();\n const callback = this.#readCallback(browser.currentUrl());\n if (callback !== null) {\n await this.#handleCallback(browser, callback);\n } else {\n const persistent = this.#persistentStorage(browser);\n if (this.#config.crossSessionRestore !== null && persistent !== null) {\n await this.#restoreAcrossSessions(browser, persistent, this.#config.crossSessionRestore);\n } else {\n // The feature was turned off: do not leave a stale hint behind.\n if (persistent !== null) this.#removePersistentHint(persistent);\n await this.#restoreSameTab(browser);\n }\n }\n } catch (error) {\n const failure = isPixelumeError(error)\n ? error\n : new PixelumeAuthError('browser_unavailable', { cause: error });\n const offline =\n this.#completingRestore && (failure.kind === 'network' || failure.kind === 'timeout');\n this.#setState(anonymous(offline ? 'offline' : 'error', failure));\n } finally {\n this.#completingRestore = false;\n }\n return this.#state;\n }\n\n /** Behaviour without `restoreAcrossSessions` (unchanged since 0.2): same-tab reload only. */\n async #restoreSameTab(browser: PixelumeBrowserAdapter): Promise<void> {\n const scope = this.#config.restoreSession\n ? this.#readSessionHint(browser.sessionStorage)\n : null;\n if (scope === null) {\n this.#setState(anonymous('visitor'));\n return;\n }\n this.#removeSessionHint(browser.sessionStorage);\n await this.login({ scope });\n }\n\n /**\n * At most one silent (`prompt=none`) attempt per start, driven by the tab hint (reload) or the\n * persistent hint (new tab, reopened browser). A per-tab marker stops a second attempt while a\n * previous one did not come back (navigation error, back button), so it can never loop.\n */\n async #restoreAcrossSessions(\n browser: PixelumeBrowserAdapter,\n persistent: PixelumeSessionStorage,\n options: { readonly maxAgeMs: number },\n ): Promise<void> {\n const tabScope = this.#config.restoreSession\n ? this.#readSessionHint(browser.sessionStorage)\n : null;\n const hint = this.#readPersistentHint(persistent, options.maxAgeMs);\n const remembered = tabScope ?? hint?.scope ?? null;\n if (remembered === null) {\n this.#setState(anonymous('visitor'));\n return;\n }\n if (this.#recentRestoreAttempt(browser.sessionStorage)) {\n this.#setState(anonymous('visitor'));\n return;\n }\n if (!isOnline(browser)) {\n this.#setState(anonymous('offline'));\n return;\n }\n // Never ask silently for more than both the game and the previous grant allow.\n const scope: PixelumeScopeRequest =\n remembered === 'profile saves' && this.#config.scope === 'profile saves'\n ? 'profile saves'\n : 'profile';\n this.#removeSessionHint(browser.sessionStorage);\n await this.#doLogin(scope, true);\n }\n\n async #doLogin(scope: PixelumeScopeRequest, silent: boolean): Promise<void> {\n const clientId = this.#requireClientId();\n const redirectUri = this.#requireRedirectUri();\n const browser = this.#browser();\n let pending = this.#readPending(browser.sessionStorage);\n if (\n silent ||\n pending === null ||\n pending.redirectUri !== redirectUri ||\n pending.silent === true ||\n this.#isExpired(pending)\n ) {\n const returnTo = silent ? sameOriginPath(browser.currentUrl(), redirectUri) : null;\n pending = {\n version: 1,\n state: randomBase64Url(browser.crypto),\n verifier: randomBase64Url(browser.crypto),\n redirectUri,\n createdAt: Date.now(),\n ...(silent ? { silent: true as const, scope } : {}),\n ...(returnTo === null ? {} : { returnTo }),\n };\n this.#writePending(browser.sessionStorage, pending);\n }\n const challenge = await sha256Base64Url(browser.crypto, pending.verifier);\n const authorization = new URL('/v1/oauth/authorize', this.#config.apiUrl);\n authorization.search = new URLSearchParams({\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: 'code',\n state: pending.state,\n code_challenge: challenge,\n code_challenge_method: 'S256',\n scope,\n ...(silent ? { prompt: 'none' } : {}),\n }).toString();\n if (silent) this.#writeRestoreAttempt(browser.sessionStorage);\n this.#setState(\n Object.freeze(\n silent\n ? { status: 'redirecting', player: null, restoring: true as const }\n : { status: 'redirecting', player: null },\n ),\n );\n try {\n browser.navigate(authorization.toString());\n } catch (cause) {\n this.#removePending(browser.sessionStorage);\n throw new PixelumeAuthError('browser_unavailable', { cause });\n }\n if (silent) this.#watchInterruptedRestore();\n }\n\n /**\n * If the page comes back without leaving (back/forward cache, navigation error then \"back\"),\n * the silent attempt is over: become a visitor instead of staying in `redirecting`. The per-tab\n * marker stays, so the next start does not try again right away.\n */\n #watchInterruptedRestore(): void {\n this.#stopRestoreWatch?.();\n if (this.#resume === null) return;\n const stop = this.#resume(() => {\n const current = this.#state;\n if (current.status === 'redirecting' && current.restoring === true) {\n this.#setState(anonymous('visitor'));\n }\n stop();\n if (this.#stopRestoreWatch === stop) this.#stopRestoreWatch = null;\n });\n this.#stopRestoreWatch = stop;\n }\n\n async #handleCallback(\n browser: PixelumeBrowserAdapter,\n callback: {\n readonly url: URL;\n readonly code: string | null;\n readonly error: string | null;\n readonly invalid: boolean;\n },\n ): Promise<void> {\n const pending = this.#readPending(browser.sessionStorage);\n this.#removePending(browser.sessionStorage);\n this.#removeRestoreAttempt(browser.sessionStorage);\n const silent = pending?.silent === true && !this.#isExpired(pending);\n this.#cleanCallback(browser, callback.url, silent ? (pending.returnTo ?? null) : null);\n this.#completingRestore = silent;\n\n if (callback.invalid) throw new PixelumeAuthError('invalid_callback');\n if (pending === null || this.#isExpired(pending)) {\n this.#removeSessionHint(browser.sessionStorage);\n throw new PixelumeAuthError(pending === null ? 'invalid_callback' : 'authorization_expired');\n }\n if (\n pending.redirectUri !== this.#config.redirectUri ||\n (callback.code !== null && !/^[A-Za-z0-9_-]{43,128}$/u.test(callback.code))\n ) {\n throw new PixelumeAuthError('invalid_callback');\n }\n const returnedState = singleParameter(callback.url, 'state');\n if (returnedState === null || returnedState !== pending.state) {\n this.#removeSessionHint(browser.sessionStorage);\n throw new PixelumeAuthError('state_mismatch');\n }\n if (callback.error !== null) {\n this.#removeSessionHint(browser.sessionStorage);\n const persistent = this.#persistentStorage(browser);\n if (silent) {\n this.#completingRestore = false;\n if (SESSION_ENDED_ERRORS.has(callback.error)) {\n if (persistent !== null) this.#removePersistentHint(persistent);\n this.#setState(anonymous('session_ended'));\n return;\n }\n if (callback.error === 'invalid_scope' && pending.scope === 'profile saves') {\n // The game no longer allows `saves`: the next start tries `profile` only.\n if (persistent !== null) this.#downgradePersistentHint(persistent);\n } else if (persistent !== null) {\n this.#removePersistentHint(persistent);\n }\n throw new PixelumeAuthError('restore_rejected');\n }\n if (persistent !== null) this.#removePersistentHint(persistent);\n if (callback.error === 'access_denied') {\n this.#setState(anonymous('cancelled'));\n return;\n }\n throw new PixelumeAuthError('invalid_callback');\n }\n if (callback.code === null) throw new PixelumeAuthError('invalid_callback');\n\n this.#setState(\n Object.freeze(\n silent\n ? { status: 'exchanging', player: null, restoring: true as const }\n : { status: 'exchanging', player: null },\n ),\n );\n const response = await this.#http.request({\n method: 'POST',\n path: '/v1/oauth/token',\n credentials: 'omit',\n form: {\n grant_type: 'authorization_code',\n code: callback.code,\n client_id: this.#requireClientId(),\n redirect_uri: pending.redirectUri,\n code_verifier: pending.verifier,\n },\n parse: parseOAuthTokenResponse,\n });\n this.#session.start(response.data);\n const player = await this.getPlayer();\n if (player !== null) {\n const scope = response.data.scopes.includes('saves') ? 'profile saves' : 'profile';\n this.#writeSessionHint(browser.sessionStorage, scope);\n const persistent = this.#persistentStorage(browser);\n if (this.#config.crossSessionRestore !== null && persistent !== null) {\n this.#writePersistentHint(persistent, scope);\n }\n }\n }\n\n async #fetchPlayer(options: PixelumeRequestOptions): Promise<PixelumePlayer | null> {\n try {\n const response = await this.#session.authorizedRequest({\n method: 'GET',\n path: '/v1/oauth/userinfo',\n signal: options.signal,\n timeoutMs: options.timeoutMs,\n parse: parsePlayerEnvelope,\n });\n const player = Object.freeze({ ...response.data.player });\n const current = this.#state;\n // Keep the same object when nothing changed, so renewals do not look like a new login.\n if (current.status === 'authenticated' && samePlayer(current.player, player)) {\n return current.player;\n }\n this.#setState(Object.freeze({ status: 'authenticated', player }));\n return player;\n } catch (error) {\n // The session ended (expired/revoked); the state already reflects it.\n if (error instanceof PixelumeAuthError) return null;\n throw error;\n }\n }\n\n async #doLogout(options: PixelumeRequestOptions): Promise<void> {\n const token = this.#session.reset();\n const browser = this.#optionalBrowser();\n if (browser) {\n this.#removePending(browser.sessionStorage);\n this.#removeSessionHint(browser.sessionStorage);\n const persistent = this.#persistentStorage(browser);\n if (persistent !== null) this.#removePersistentHint(persistent);\n }\n this.#setState(anonymous('logged_out'));\n if (token === null) return;\n // Revoking any token of the family revokes all of it; the refresh token is the preferred hint.\n await this.#http.request({\n method: 'POST',\n path: '/v1/oauth/revoke',\n credentials: 'omit',\n form: {\n token: token.refreshToken ?? token.accessToken,\n token_type_hint: token.refreshToken === null ? 'access_token' : 'refresh_token',\n client_id: this.#requireClientId(),\n },\n signal: options.signal,\n timeoutMs: options.timeoutMs,\n parse: parseEmptyResponse,\n });\n }\n\n #readCallback(value: string): {\n readonly url: URL;\n readonly code: string | null;\n readonly error: string | null;\n readonly invalid: boolean;\n } | null {\n const redirectUri = this.#config.redirectUri;\n if (redirectUri === null) return null;\n const current = new URL(value);\n const expected = new URL(redirectUri);\n if (current.origin !== expected.origin || current.pathname !== expected.pathname) return null;\n const hasCallbackParameter = CALLBACK_PARAMETERS.some((key) => current.searchParams.has(key));\n if (!hasCallbackParameter) return null;\n const code = singleParameter(current, 'code');\n const error = singleParameter(current, 'error');\n return {\n url: current,\n code,\n error,\n invalid: !sameCallbackBase(current, expected) || (code === null) === (error === null),\n };\n }\n\n /** Removes the callback fields; a silent attempt returns to the page that started it. */\n #cleanCallback(browser: PixelumeBrowserAdapter, url: URL, returnTo: string | null): void {\n if (returnTo !== null && isSafeReturnPath(returnTo)) {\n browser.replaceUrl(returnTo);\n return;\n }\n const clean = new URL(url.toString());\n for (const key of CALLBACK_PARAMETERS) clean.searchParams.delete(key);\n browser.replaceUrl(`${clean.pathname}${clean.search}${clean.hash}`);\n }\n\n #browser(): PixelumeBrowserAdapter {\n const browser = this.#optionalBrowser();\n if (!browser) throw new PixelumeAuthError('browser_unavailable');\n if (\n typeof browser.crypto.getRandomValues !== 'function' ||\n typeof browser.crypto.subtle.digest !== 'function'\n ) {\n throw new PixelumeAuthError('crypto_unavailable');\n }\n return browser;\n }\n\n #optionalBrowser(): PixelumeBrowserAdapter | null {\n if (this.#config.browser) return this.#config.browser;\n try {\n if (\n typeof globalThis.location === 'undefined' ||\n typeof globalThis.history === 'undefined' ||\n typeof globalThis.sessionStorage === 'undefined' ||\n typeof globalThis.crypto === 'undefined'\n ) {\n return null;\n }\n return {\n currentUrl: () => globalThis.location.href,\n navigate: (url) => {\n globalThis.location.assign(url);\n },\n replaceUrl: (url) => {\n globalThis.history.replaceState(globalThis.history.state, '', url);\n },\n sessionStorage: globalThis.sessionStorage,\n get persistentStorage() {\n try {\n return typeof globalThis.localStorage === 'undefined' ? null : globalThis.localStorage;\n } catch {\n // Blocked storage (privacy settings, sandboxed frames).\n return null;\n }\n },\n crypto: globalThis.crypto,\n };\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #requireClientId(): string {\n if (this.#config.clientId === null) {\n throw new PixelumeConfigError('Pixelume Auth requires clientId or gameId');\n }\n return this.#config.clientId;\n }\n\n #requireRedirectUri(): string {\n if (this.#config.redirectUri === null) {\n throw new PixelumeAuthError('browser_unavailable');\n }\n return this.#config.redirectUri;\n }\n\n #pendingKey(): string {\n return `pixelume.oauth.pending.${this.#config.clientId ?? 'unconfigured'}`;\n }\n\n #hintKey(): string {\n return `pixelume.oauth.session.${this.#config.clientId ?? 'unconfigured'}`;\n }\n\n #persistentHintKey(): string {\n return `pixelume.oauth.restore.${this.#config.clientId ?? 'unconfigured'}`;\n }\n\n #restoreAttemptKey(): string {\n return `pixelume.oauth.restore-attempt.${this.#config.clientId ?? 'unconfigured'}`;\n }\n\n #persistentStorage(browser: PixelumeBrowserAdapter): PixelumeSessionStorage | null {\n try {\n return browser.persistentStorage ?? null;\n } catch {\n return null;\n }\n }\n\n /**\n * Persistent-hint helpers never throw: an unavailable `localStorage` only disables\n * cross-session restoration, it must not break the login itself.\n */\n #readPersistentHint(storage: PixelumeSessionStorage, maxAgeMs: number): PersistentHint | null {\n try {\n const raw = storage.getItem(this.#persistentHintKey());\n if (raw === null) return null;\n const value: unknown = JSON.parse(raw);\n const now = Date.now();\n if (!isPersistentHint(value) || value.at > now + 60_000 || value.at + maxAgeMs < now) {\n storage.removeItem(this.#persistentHintKey());\n return null;\n }\n return value;\n } catch {\n this.#removePersistentHint(storage);\n return null;\n }\n }\n\n #writePersistentHint(storage: PixelumeSessionStorage, scope: PixelumeScopeRequest): void {\n const hint: PersistentHint = { version: 1, scope, at: Date.now() };\n try {\n storage.setItem(this.#persistentHintKey(), JSON.stringify(hint));\n } catch {\n // Quota or blocked storage: the next new tab simply starts as a visitor.\n }\n }\n\n #downgradePersistentHint(storage: PixelumeSessionStorage): void {\n try {\n const raw = storage.getItem(this.#persistentHintKey());\n const value: unknown = raw === null ? null : JSON.parse(raw);\n if (!isPersistentHint(value)) return;\n storage.setItem(\n this.#persistentHintKey(),\n JSON.stringify({ ...value, scope: 'profile' } satisfies PersistentHint),\n );\n } catch {\n this.#removePersistentHint(storage);\n }\n }\n\n #removePersistentHint(storage: PixelumeSessionStorage): void {\n try {\n storage.removeItem(this.#persistentHintKey());\n } catch {\n // Nothing else to do.\n }\n }\n\n #recentRestoreAttempt(storage: PixelumeSessionStorage): boolean {\n const raw = storage.getItem(this.#restoreAttemptKey());\n if (raw === null) return false;\n const at = Number(raw);\n const now = Date.now();\n if (!Number.isFinite(at) || at > now + 60_000 || at + AUTHORIZATION_REQUEST_TTL_MS < now) {\n storage.removeItem(this.#restoreAttemptKey());\n return false;\n }\n return true;\n }\n\n #writeRestoreAttempt(storage: PixelumeSessionStorage): void {\n try {\n storage.setItem(this.#restoreAttemptKey(), String(Date.now()));\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #removeRestoreAttempt(storage: PixelumeSessionStorage): void {\n try {\n storage.removeItem(this.#restoreAttemptKey());\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #readPending(storage: PixelumeSessionStorage): PendingAuthorization | null {\n try {\n const raw = storage.getItem(this.#pendingKey());\n if (raw === null) return null;\n const value: unknown = JSON.parse(raw);\n if (!isPendingAuthorization(value)) {\n storage.removeItem(this.#pendingKey());\n return null;\n }\n return value;\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #writePending(storage: PixelumeSessionStorage, pending: PendingAuthorization): void {\n try {\n storage.setItem(this.#pendingKey(), JSON.stringify(pending));\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #removePending(storage: PixelumeSessionStorage): void {\n try {\n storage.removeItem(this.#pendingKey());\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n /** The hint is non-secret: only \"a session existed\" and the scope that was granted. */\n #readSessionHint(storage: PixelumeSessionStorage): PixelumeScopeRequest | null {\n try {\n const value = storage.getItem(this.#hintKey());\n if (value === '1' || value === 'profile') return 'profile';\n if (value === 'profile saves') return 'profile saves';\n return null;\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #writeSessionHint(storage: PixelumeSessionStorage, scope: PixelumeScopeRequest): void {\n try {\n storage.setItem(this.#hintKey(), scope);\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #removeSessionHint(storage: PixelumeSessionStorage): void {\n try {\n storage.removeItem(this.#hintKey());\n } catch (cause) {\n throw new PixelumeAuthError('storage_unavailable', { cause });\n }\n }\n\n #isExpired(pending: PendingAuthorization): boolean {\n const now = Date.now();\n return (\n pending.createdAt > now + 60_000 || pending.createdAt + AUTHORIZATION_REQUEST_TTL_MS < now\n );\n }\n\n #setState(state: PixelumeAuthState): void {\n const previous = this.#state;\n if (sameState(previous, state)) return;\n this.#state = state;\n for (const listener of [...this.#listeners]) listener(state, previous);\n }\n}\n\nfunction anonymous(\n reason: PixelumeAnonymousReason,\n error: PixelumeError | null = null,\n): PixelumeAuthState {\n return Object.freeze({ status: 'anonymous', player: null, reason, error });\n}\n\nfunction samePlayer(left: PixelumePlayer, right: PixelumePlayer): boolean {\n return (\n left.id === right.id &&\n left.displayName === right.displayName &&\n left.avatarUrl === right.avatarUrl\n );\n}\n\nfunction isPersistentHint(value: unknown): value is PersistentHint {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const hint = value as Record<string, unknown>;\n return (\n hint.version === 1 &&\n (hint.scope === 'profile' || hint.scope === 'profile saves') &&\n typeof hint.at === 'number' &&\n Number.isFinite(hint.at)\n );\n}\n\nfunction isOnline(browser: PixelumeBrowserAdapter): boolean {\n try {\n if (typeof browser.isOnline === 'function') return browser.isOnline();\n const navigator = Reflect.get(globalThis, 'navigator') as { onLine?: unknown } | undefined;\n return navigator?.onLine !== false;\n } catch {\n return true;\n }\n}\n\n/** Path, query and hash of `current` when it is on the redirect URI's origin; null otherwise. */\nfunction sameOriginPath(current: string, redirectUri: string): string | null {\n try {\n const url = new URL(current);\n if (url.origin !== new URL(redirectUri).origin) return null;\n for (const key of CALLBACK_PARAMETERS) url.searchParams.delete(key);\n const path = `${url.pathname}${url.search}${url.hash}`;\n return isSafeReturnPath(path) ? path : null;\n } catch {\n return null;\n }\n}\n\nfunction isSafeReturnPath(value: string): boolean {\n return (\n value.startsWith('/') &&\n !value.startsWith('//') &&\n !value.includes('\\\\') &&\n value.length <= 2048\n );\n}\n\nfunction isPendingAuthorization(value: unknown): value is PendingAuthorization {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const pending = value as Record<string, unknown>;\n return (\n (pending.silent === undefined || pending.silent === true) &&\n (pending.scope === undefined ||\n pending.scope === 'profile' ||\n pending.scope === 'profile saves') &&\n (pending.returnTo === undefined ||\n (typeof pending.returnTo === 'string' && isSafeReturnPath(pending.returnTo))) &&\n pending.version === 1 &&\n typeof pending.state === 'string' &&\n /^[A-Za-z0-9_-]{43}$/u.test(pending.state) &&\n typeof pending.verifier === 'string' &&\n /^[A-Za-z0-9_-]{43}$/u.test(pending.verifier) &&\n typeof pending.redirectUri === 'string' &&\n typeof pending.createdAt === 'number' &&\n Number.isFinite(pending.createdAt)\n );\n}\n\nfunction sameCallbackBase(current: URL, expected: URL): boolean {\n if (current.origin !== expected.origin || current.pathname !== expected.pathname) return false;\n const currentBase = new URL(current.toString());\n for (const key of CALLBACK_PARAMETERS) currentBase.searchParams.delete(key);\n currentBase.hash = '';\n const expectedBase = new URL(expected.toString());\n expectedBase.hash = '';\n return currentBase.toString() === expectedBase.toString();\n}\n\nfunction singleParameter(url: URL, name: string): string | null {\n const values = url.searchParams.getAll(name);\n if (values.length !== 1 || values[0] === '') return null;\n return values[0] ?? null;\n}\n\nfunction randomBase64Url(crypto: Crypto): string {\n const bytes = crypto.getRandomValues(new Uint8Array(32));\n return bytesToBase64Url(bytes);\n}\n\nasync function sha256Base64Url(crypto: Crypto, value: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(value));\n return bytesToBase64Url(new Uint8Array(digest));\n}\n\nfunction bytesToBase64Url(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary).replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/u, '');\n}\n\nfunction sameState(left: PixelumeAuthState, right: PixelumeAuthState): boolean {\n if (left.status !== right.status) return false;\n if (left.status === 'authenticated' && right.status === 'authenticated') {\n return left.player === right.player;\n }\n if (left.status === 'anonymous' && right.status === 'anonymous') {\n return left.reason === right.reason && left.error === right.error;\n }\n if (\n (left.status === 'redirecting' && right.status === 'redirecting') ||\n (left.status === 'exchanging' && right.status === 'exchanging')\n ) {\n return left.restoring === right.restoring;\n }\n return true;\n}\n"]}
@@ -0,0 +1,91 @@
1
+ import { type OAuthTokenResponseWire } from '../../contracts/index.js';
2
+ import { PixelumeAuthError, type PixelumeError } from '../../core/errors.js';
3
+ import type { PixelumeRequestOptions } from '../../core/types.js';
4
+ import type { HttpClient } from '../../http/HttpClient.js';
5
+ import type { HttpRequest, HttpResponse } from '../../http/types.js';
6
+ /**
7
+ * Renew this long before the access token expires (API guide: `expires_in − 60 s`). For very short
8
+ * tokens (the API allows down to 60 s) the lead is capped at half the lifetime.
9
+ */
10
+ export declare const REFRESH_LEAD_MS = 60000;
11
+ /** Never schedule a renewal sooner than this, even for very short access tokens. */
12
+ export declare const MIN_REFRESH_DELAY_MS = 10000;
13
+ /** OAuth scopes the API can grant. `profile` is always present. */
14
+ export type PixelumeScope = 'profile' | 'saves';
15
+ /** Snapshot of the token lifecycle of the signed-in player. Never contains tokens. */
16
+ export interface PixelumeSessionState {
17
+ /** `true` while the SDK holds credentials for a player. */
18
+ readonly active: boolean;
19
+ /** Scopes granted to the current access token (empty when inactive). */
20
+ readonly scopes: readonly PixelumeScope[];
21
+ /**
22
+ * Whether the API issued a refresh token. When `false` (legacy authorization) the session ends
23
+ * when the access token expires and the player must sign in again.
24
+ */
25
+ readonly renewable: boolean;
26
+ /** Approximate expiry of the current access token (local clock, ms since epoch), or `null`. */
27
+ readonly accessTokenExpiresAt: number | null;
28
+ /** A renewal request is in flight. */
29
+ readonly renewing: boolean;
30
+ /**
31
+ * Last transient renewal failure (network, timeout, 5xx or rate limit). The session is still
32
+ * recoverable and the SDK will retry; cleared after a successful renewal.
33
+ */
34
+ readonly error: PixelumeError | null;
35
+ }
36
+ export type PixelumeSessionListener = (state: PixelumeSessionState, previous: PixelumeSessionState) => void;
37
+ /** Registers a callback for "the page may have been suspended" signals. Returns an unsubscribe. */
38
+ export type ResumeSource = (onResume: () => void) => () => void;
39
+ /** Timer/clock seam; tests drive it with fake timers. */
40
+ interface Clock {
41
+ now(): number;
42
+ monotonic(): number;
43
+ }
44
+ export interface SessionManagerOptions {
45
+ readonly http: HttpClient;
46
+ readonly clientId: () => string;
47
+ readonly resume: ResumeSource | null;
48
+ /** Called once when the session ends for good (not on logout/reset). */
49
+ readonly onEnded: (error: PixelumeAuthError) => void;
50
+ }
51
+ /**
52
+ * Owns the player's OAuth credentials for one client instance: memory-only storage, proactive
53
+ * and on-demand renewal with refresh-token rotation, single-flight coordination, one retry after
54
+ * `401`, and timers/listeners that are released on reset or dispose.
55
+ *
56
+ * Tokens never leave this class except as the `Authorization` header and the token/revoke form
57
+ * bodies sent to the API.
58
+ */
59
+ export declare class SessionManager {
60
+ #private;
61
+ constructor(options: SessionManagerOptions, clock?: Clock);
62
+ get state(): PixelumeSessionState;
63
+ get active(): boolean;
64
+ subscribe(listener: PixelumeSessionListener): () => void;
65
+ /** Installs the credentials returned by the authorization-code exchange. */
66
+ start(token: OAuthTokenResponseWire): void;
67
+ /**
68
+ * Discards credentials without contacting the API (logout does the revocation) and returns
69
+ * them so the caller can revoke. Cancels timers, in-flight renewals and listeners.
70
+ */
71
+ reset(): {
72
+ readonly accessToken: string;
73
+ readonly refreshToken: string | null;
74
+ } | null;
75
+ /** Releases timers and listeners for good. Credentials are dropped from memory. */
76
+ dispose(): void;
77
+ /**
78
+ * Renews now (single-flight). Resolves after a successful rotation; rejects with the transient
79
+ * error (session kept) or with `PixelumeAuthError` when the session ended.
80
+ */
81
+ refresh(options?: PixelumeRequestOptions): Promise<void>;
82
+ /**
83
+ * Sends a Bearer request with a fresh access token. On `401` it renews once (shared with any
84
+ * concurrent caller) and repeats the very same request once. A `401` is returned by the API
85
+ * before the operation runs, so the repetition never applies a write twice.
86
+ */
87
+ authorizedRequest<T>(request: Omit<HttpRequest<T>, 'headers' | 'credentials'>): Promise<HttpResponse<T>>;
88
+ }
89
+ /** Default resume signals in a browser: tab visible again, back/forward cache restore, online. */
90
+ export declare function browserResumeSource(): ResumeSource | null;
91
+ export {};