The refactor routed the browser's RemoteOAuthStorage through `oauth-persist.ts`, which value-imported the Node-only `store-io.js` (`atomically` -> `stubborn-fs` -> `node:process.getuid`, plus `node:fs/promises`). That dragged Node built-ins into the browser bundle and the web app crashed to a blank page at runtime — a regression from v2/main, where browser OAuth storage used a Zustand JSON adapter with no Node imports. Unit/integration tests run in node/happy-dom and `smoke:web` only checks the served HTML, so none of them execute the app in a real browser and the break slipped through. Fix, following the existing `store-id.ts` precedent: - Split the pure JSON (de)serializers into Node-free `core/storage/store-serialize.ts`; `store-io.ts` re-exports them so existing importers are unaffected. - Move the Node-only `createFileOAuthPersistBackend` into `core/auth/node/oauth-persist-file.ts`; update `storage-node.ts` and the storage adapters test to import from there. - `oauth-persist.ts` now imports only the Node-free serializers, so the browser bundle no longer pulls in `node:fs`/`atomically`. Tests: - oauth-persist-browser-safe.test.ts: source-level guard that `oauth-persist.ts` never imports store-io/node:/atomically. - Direct unit tests for the isomorphic remote + session backends (restoring oauth-persist.ts coverage after the file backend moved out). - store.test.ts: OAuthMemoryStore unit coverage incl. replace() fallbacks. - storage.test.ts: clearAllOAuthClientState null-snapshot (no file) path. Verified end-to-end in a real browser (Playwright): DCR OAuth flow completes, tokens persist via the remote store, and after a full page reload the server reconnects with no re-authentication. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
16 lines
586 B
TypeScript
16 lines
586 B
TypeScript
/**
|
|
* Pure, Node-free JSON (de)serialization for store files. Split from
|
|
* `store-io.ts` (which imports `node:fs`/`node:path`/`atomically`) so
|
|
* isomorphic code — e.g. the browser OAuth persistence flow in
|
|
* `core/auth/oauth-persist.ts` — can (de)serialize store blobs without
|
|
* pulling Node deps into the browser bundle. `store-io.ts` re-exports these
|
|
* so existing importers are unaffected.
|
|
*/
|
|
|
|
export function serializeStore(data: unknown): string {
|
|
return JSON.stringify(data, null, 2);
|
|
}
|
|
|
|
export function parseStore(raw: string): unknown {
|
|
return JSON.parse(raw);
|
|
}
|