@basictech/react 0.8.0-beta.4 → 0.9.0-beta.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,"sources":["../src/config.ts","../src/sync/tokenRegistry.ts","../src/sync/syncProtocol.js","../package.json","../src/utils/network.ts","../src/context.tsx","../src/dev/BasicDevToolbar.tsx","../src/AuthContext.tsx","../src/sync/index.ts","../src/core/db/types.ts","../src/core/db/RemoteCollection.ts","../src/core/db/RemoteDB.ts","../src/core/auth/AuthManager.ts","../src/utils/storage.ts","../src/utils/normalizeClientId.ts","../src/utils/resolveDid.ts","../src/updater/versionUpdater.ts","../src/updater/updateMigrations.ts","../src/utils/schema.ts","../src/index.ts"],"sourcesContent":["export const log = (...args: any[]) => {\n try { \n if (localStorage.getItem('basic_debug') === 'true') {\n console.log('[basic]', ...args)\n }\n } catch (e) {\n // silently fail if localStorage is unavailable (SSR)\n }\n}\n","/**\n * Module-level registry for token getter functions, keyed by WebSocket URL.\n *\n * dexie-syncable serializes the `options` object into IndexedDB via\n * structured clone, which cannot handle functions. This registry keeps\n * the getToken function out of `options` so it survives serialization\n * while remaining accessible to the sync protocol on every (re)connect.\n */\n\ntype GetTokenFn = (options?: { forceRefresh?: boolean }) => Promise<string>\n\nconst registry = new Map<string, GetTokenFn>()\n\nexport function setTokenGetter(url: string, fn: GetTokenFn): void {\n registry.set(url, fn)\n}\n\nexport function getTokenGetter(url: string): GetTokenFn | undefined {\n return registry.get(url)\n}\n","\"use client\"\nimport { Dexie } from \"dexie\";\nimport { log } from \"../config\";\nimport { getTokenGetter } from \"./tokenRegistry\";\n\nfunction decodeJwtExp(token) {\n try {\n var parts = token.split(\".\");\n if (parts.length !== 3) return null;\n var payload = JSON.parse(atob(parts[1].replace(/-/g, \"+\").replace(/_/g, \"/\")));\n return typeof payload.exp === \"number\" ? payload.exp : null;\n } catch (_) {\n return null;\n }\n}\n\nexport const syncProtocol = function () {\n log(\"Initializing syncProtocol\");\n // Constants:\n var RECONNECT_DELAY = 5000; // Reconnect delay in case of errors such as network down.\n var TOKEN_REFRESH_BUFFER = 60; // Refresh token this many seconds before exp\n\n Dexie.Syncable.registerSyncProtocol(\"websocket\", {\n sync: function (\n context,\n url,\n options,\n baseRevision,\n syncedRevision,\n changes,\n partial,\n applyRemoteChanges,\n onChangesAccepted,\n onSuccess,\n onError,\n ) {\n // The following vars are needed because we must know which callback to ack when server sends it's ack to us.\n var requestId = 0;\n var acceptCallbacks = {};\n var refreshTimer = null;\n var pendingTokenUpdate = null;\n\n // Connect the WebSocket to given url:\n log(\"Connecting to\", url)\n var ws = new WebSocket(url);\n\n // sendChanges() method:\n function sendChanges(changes, baseRevision, partial, onChangesAccepted) {\n log(\"sendChanges\", changes.length, baseRevision);\n ++requestId;\n acceptCallbacks[requestId.toString()] = onChangesAccepted;\n\n // In this example, the server expects the following JSON format of the request:\n // {\n // type: \"changes\"\n // baseRevision: baseRevision,\n // changes: changes,\n // partial: partial,\n // requestId: id\n // }\n // To make the sample simplified, we assume the server has the exact same specification of how changes are structured.\n // In real world, you would have to pre-process the changes array to fit the server specification.\n // However, this example shows how to deal with the WebSocket to fullfill the API.\n\n ws.send(\n JSON.stringify({\n type: \"changes\",\n changes: changes,\n partial: partial,\n baseRevision: baseRevision,\n requestId: requestId,\n }),\n );\n }\n\n\n\n function clearRefreshTimer() {\n if (refreshTimer) {\n clearTimeout(refreshTimer);\n refreshTimer = null;\n }\n }\n\n function sendTokenUpdate(token) {\n if (ws.readyState !== WebSocket.OPEN) return false;\n pendingTokenUpdate = token;\n ws.send(JSON.stringify({ type: \"tokenUpdate\", authToken: token }));\n return true;\n }\n\n // Resolve the getToken function from the module-level registry.\n // It's stored there (not in options) because dexie-syncable serializes\n // options into IndexedDB, and functions can't survive structured clone.\n function resolveGetToken() {\n var fn = getTokenGetter(url);\n if (!fn) throw new Error(\"No token getter registered for \" + url);\n return fn;\n }\n\n // Schedule a proactive token refresh before the JWT expires.\n // Sends a tokenUpdate message on the existing WebSocket so the\n // server can accept the new token without dropping the connection.\n function scheduleTokenRefresh(tokenStr) {\n clearRefreshTimer();\n var exp = decodeJwtExp(tokenStr);\n if (!exp) return;\n var msUntilRefresh = (exp - TOKEN_REFRESH_BUFFER) * 1000 - Date.now();\n if (msUntilRefresh <= 0) return;\n log(\"Scheduling proactive token refresh in\", Math.round(msUntilRefresh / 1000), \"s\");\n refreshTimer = setTimeout(async function () {\n try {\n var newToken = await resolveGetToken()({ forceRefresh: true });\n if (sendTokenUpdate(newToken)) {\n log(\"Sending tokenUpdate on existing WebSocket\");\n }\n } catch (err) {\n log(\"Proactive token refresh failed (non-fatal):\", err);\n }\n }, msUntilRefresh);\n }\n\n // When WebSocket opens, get a fresh token and send our identity to the server.\n // This runs on every open, including reconnects after ERROR_WILL_RETRY,\n // so each attempt gets a fresh token via getToken().\n ws.onopen = async function (event) {\n try {\n var token = await resolveGetToken()();\n log(\"Opening socket - sending clientIdentity\", context.clientIdentity);\n ws.send(\n JSON.stringify({\n type: \"clientIdentity\",\n clientIdentity: context.clientIdentity || null,\n authToken: token,\n schema: options.schema\n }),\n );\n scheduleTokenRefresh(token);\n } catch (err) {\n log(\"Failed to get token for WebSocket:\", err);\n ws.close();\n onError(\"Authentication failed: \" + (err.message || err), RECONNECT_DELAY);\n }\n };\n\n // When the page becomes visible again (e.g. PWA/mobile browser resuming\n // from background), the scheduled setTimeout for token refresh may have\n // been frozen by the browser. Force-refresh the token and re-send it to\n // the server so the WebSocket connection stays authenticated.\n function handleVisibilityResume() {\n if (document.visibilityState === 'visible' && ws.readyState === WebSocket.OPEN) {\n log(\"Page became visible - refreshing token for WebSocket\");\n resolveGetToken()({ forceRefresh: true }).then(function(newToken) {\n sendTokenUpdate(newToken);\n }).catch(function(err) {\n log(\"Token refresh on visibility resume failed:\", err);\n });\n }\n }\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', handleVisibilityResume);\n }\n\n function cleanupVisibilityListener() {\n if (typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', handleVisibilityResume);\n }\n }\n\n // If network down or other error, tell the framework to reconnect again in some time:\n ws.onerror = function (event) {\n clearRefreshTimer();\n cleanupVisibilityListener();\n ws.close();\n log(\"ws.onerror\", event);\n onError(event?.message, RECONNECT_DELAY);\n };\n\n // If socket is closed (network disconnected), inform framework and make it reconnect\n ws.onclose = function (event) {\n clearRefreshTimer();\n cleanupVisibilityListener();\n onError(\"Socket closed: \" + event.reason, RECONNECT_DELAY);\n };\n\n // isFirstRound: Will need to call onSuccess() only when we are in sync the first time.\n // onSuccess() will unblock Dexie to be used by application code.\n // If for example app code writes: db.friends.where('shoeSize').above(40).toArray(callback), the execution of that query\n // will not run until we have called onSuccess(). This is because we want application code to get results that are as\n // accurate as possible. Specifically when connected the first time and the entire DB is being synced down to the browser,\n // it is important that queries starts running first when db is in sync.\n var isFirstRound = true;\n // When message arrive from the server, deal with the message accordingly:\n ws.onmessage = function (event) {\n try {\n // Assume we have a server that should send JSON messages of the following format:\n // {\n // type: \"clientIdentity\", \"changes\", \"ack\" or \"error\"\n // clientIdentity: unique value for our database client node to persist in the context. (Only applicable if type=\"clientIdentity\")\n // message: Error message (Only applicable if type=\"error\")\n // requestId: ID of change request that is acked by the server (Only applicable if type=\"ack\" or \"error\")\n // changes: changes from server (Only applicable if type=\"changes\")\n // lastRevision: last revision of changes sent (applicable if type=\"changes\")\n // partial: true if server has additionalChanges to send. False if these changes were the last known. (applicable if type=\"changes\")\n // }\n var requestFromServer = JSON.parse(event.data);\n log(\"requestFromServer\", requestFromServer, { isFirstRound });\n\n if (requestFromServer.type == \"clientIdentity\") {\n context.clientIdentity = requestFromServer.clientIdentity;\n context.save();\n\n sendChanges(changes, baseRevision, partial, onChangesAccepted);\n\n ws.send(\n JSON.stringify({\n type: \"subscribe\",\n syncedRevision: syncedRevision,\n }),\n );\n } else if (requestFromServer.type == \"changes\") {\n applyRemoteChanges(\n requestFromServer.changes,\n requestFromServer.currentRevision,\n requestFromServer.partial,\n );\n if (isFirstRound && !requestFromServer.partial) {\n // Since this is the first sync round and server sais we've got all changes - now is the time to call onsuccess()\n onSuccess({\n // Specify a react function that will react on additional client changes\n react: function (\n changes,\n baseRevision,\n partial,\n onChangesAccepted,\n ) {\n sendChanges(\n changes,\n baseRevision,\n partial,\n onChangesAccepted,\n );\n },\n disconnect: function () {\n clearRefreshTimer();\n cleanupVisibilityListener();\n ws.close();\n },\n });\n isFirstRound = false;\n }\n } else if (requestFromServer.type == \"tokenUpdateAck\") {\n if (requestFromServer.ok) {\n scheduleTokenRefresh(requestFromServer.authToken || pendingTokenUpdate);\n pendingTokenUpdate = null;\n } else {\n log(\"tokenUpdate rejected by server:\", requestFromServer.code || requestFromServer.message);\n pendingTokenUpdate = null;\n ws.close(4001, requestFromServer.code || \"token_update_failed\");\n onError(\n requestFromServer.message || \"Authentication refresh failed\",\n RECONNECT_DELAY,\n );\n }\n } else if (requestFromServer.type == \"ack\") {\n var requestId = requestFromServer.requestId;\n var acceptCallback = acceptCallbacks[requestId.toString()];\n acceptCallback(); // Tell framework that server has acknowledged the changes sent.\n delete acceptCallbacks[requestId.toString()];\n } else if (requestFromServer.type == \"error\") {\n ws.close();\n if (requestFromServer.code === \"TOKEN_EXPIRED\" || requestFromServer.code === \"UNAUTHORIZED\") {\n log(\"Auth error from server, will reconnect with fresh token:\", requestFromServer.message);\n onError(requestFromServer.message, RECONNECT_DELAY);\n } else {\n onError(requestFromServer.message, Infinity);\n }\n } else {\n log(\"unknown message\", requestFromServer);\n ws.close();\n onError(\"unknown message\", Infinity);\n }\n } catch (e) {\n ws.close();\n log(\"caught error\", e)\n onError(e, Infinity); // Something went crazy. Server sends invalid format or our code is buggy. Dont reconnect - it would continue failing.\n }\n };\n },\n });\n};\n","{\n \"name\": \"@basictech/react\",\n \"version\": \"0.8.0-beta.4\",\n \"description\": \"\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"private\": false,\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"prepublishOnly\": \"npm run build\",\n \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n },\n \"author\": \"\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"semver\": \"^7.7.2\",\n \"ajv\": \"^8.17.1\",\n \"dexie\": \"^4.2.1\",\n \"dexie-observable\": \"^4.0.1-beta.13\",\n \"dexie-react-hooks\": \"^4.2.0\",\n \"dexie-syncable\": \"^4.0.1-beta.13\",\n \"jwt-decode\": \"^4.0.0\",\n \"uuid\": \"^10.0.0\",\n \"@basictech/schema\": \"0.7.0-beta.0\"\n },\n \"devDependencies\": {\n \"@repo/typescript-config\": \"*\",\n \"tsup\": \"^8.0.0\",\n \"typescript\": \"^5.0.0\"\n },\n \"peerDependencies\": {\n \"react\": \"^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0\"\n }\n}\n","// Network utilities for Basic React package\nimport semver from 'semver'\nimport { log } from '../config'\nimport { version as pkgVersion } from '../../package.json'\n\nexport function isDevelopment(debug?: boolean): boolean {\n if (debug === true) return true\n if (typeof process !== 'undefined' && process.env.NODE_ENV === 'development') return true\n if (typeof window === 'undefined' || !window.location) return false\n const host = window.location.hostname\n return (\n host === 'localhost' ||\n host === '127.0.0.1' ||\n host.includes('localhost') ||\n host.includes('127.0.0.1') ||\n host.includes('.local')\n )\n}\n\nfunction normalizeVersion(v: string | null | undefined): string | null {\n if (v == null) return null\n const t = String(v).trim()\n return t.length ? t : null\n}\n\nfunction versionsMatch(a: string, b: string): boolean {\n const na = a.trim()\n const nb = b.trim()\n if (na === nb) return true\n const va = semver.valid(na)\n const vb = semver.valid(nb)\n if (va && vb) return semver.eq(va, vb)\n return false\n}\n\n/** Use npm `beta` dist-tag when the installed version is a semver prerelease whose first id is `beta`. */\nfunction usesBetaDistTag(version: string): boolean {\n const pre = semver.prerelease(version)\n const id = pre?.[0]\n return typeof id === 'string' && id.toLowerCase() === 'beta'\n}\n\ntype NpmInstallMeta = {\n 'dist-tags'?: { latest?: string; beta?: string }\n}\n\nexport async function checkForNewVersion(): Promise<{ \n hasNewVersion: boolean, \n latestVersion: string | null, \n currentVersion: string | null \n}> {\n try {\n const currentVersion = normalizeVersion(pkgVersion)\n if (!currentVersion) {\n return { hasNewVersion: false, latestVersion: null, currentVersion: null }\n }\n\n const response = await fetch('https://registry.npmjs.org/@basictech/react', {\n headers: { Accept: 'application/vnd.npm.install-v1+json' },\n })\n if (!response.ok) {\n throw new Error('Failed to fetch version from npm');\n }\n\n const data = (await response.json()) as NpmInstallMeta\n const distTags = data['dist-tags'] ?? {}\n const rawRegistry =\n usesBetaDistTag(currentVersion)\n ? distTags.beta ?? distTags.latest\n : distTags.latest\n const latestVersion = normalizeVersion(rawRegistry ?? null)\n if (!latestVersion) {\n throw new Error('Missing dist-tags from npm registry')\n }\n\n const same = versionsMatch(currentVersion, latestVersion)\n\n if (!same && isDevelopment()) {\n log('[basic] version check mismatch:', {\n currentVersion,\n registryVersion: latestVersion,\n channel: usesBetaDistTag(currentVersion) ? 'beta' : 'latest',\n })\n }\n\n if (!same) {\n console.warn('[basic] New version available:', latestVersion, `\\nrun \"npm install @basictech/react@${latestVersion}\" to update`);\n }\n if (usesBetaDistTag(currentVersion)) {\n log('thank you for being on basictech/react beta :)')\n }\n \n return {\n hasNewVersion: !same,\n latestVersion,\n currentVersion\n };\n } catch (error) {\n log('Error checking for new version:', error);\n return {\n hasNewVersion: false,\n latestVersion: null, \n currentVersion: null\n };\n }\n}\n\nexport function cleanOAuthParamsFromUrl(): void {\n if (window.location.search.includes('code') || window.location.search.includes('state')) {\n const url = new URL(window.location.href)\n url.searchParams.delete('code')\n url.searchParams.delete('state')\n window.history.replaceState({}, document.title, url.pathname + url.search)\n log('Cleaned OAuth parameters from URL')\n }\n}\n\nexport function getSyncStatus(statusCode: number): string {\n switch (statusCode) {\n case -1:\n return \"ERROR\";\n case 0:\n return \"OFFLINE\";\n case 1:\n return \"CONNECTING\";\n case 2:\n return \"ONLINE\";\n case 3:\n return \"SYNCING\";\n case 4:\n return \"ERROR_WILL_RETRY\";\n default:\n return \"UNKNOWN\";\n }\n}\n","import { createContext, useContext } from 'react'\nimport type { BasicDB } from './core/db'\nimport type {\n User,\n AuthResult,\n GetTokenOptions,\n AuthStatus,\n} from './core/auth/AuthManager'\nimport type { DBMode } from './core/db'\n\nexport enum DBStatus {\n LOADING = 'LOADING',\n OFFLINE = 'OFFLINE',\n CONNECTING = 'CONNECTING',\n ONLINE = 'ONLINE',\n SYNCING = 'SYNCING',\n ERROR = 'ERROR',\n /** Sync-layer error with automatic retry (maps from dexie-syncable status 4). */\n ERROR_WILL_RETRY = 'ERROR_WILL_RETRY',\n /**\n * Auth-driven status: set by the provider when `authStatus` transitions to\n * `reauth_required`, causing sync to disconnect. Unlike the other statuses\n * this is NOT mapped from a dexie-syncable status code — it is set\n * programmatically by `BasicProvider` to signal that the token is\n * definitively invalid and the user must re-authenticate before sync can\n * resume.\n */\n ERROR_TOKEN_EXPIRED = 'ERROR_TOKEN_EXPIRED',\n}\n\n/** Snapshot of local schema vs server (for dev toolbar and debugging). */\nexport type BasicSchemaDevInfo = {\n projectId: string | null\n localVersion: number | undefined\n status: string\n valid: boolean\n lastCheckedAt: number\n error?: string\n}\n\n/**\n * Context type for useBasic hook\n */\nexport type BasicContextType = {\n isReady: boolean\n isSignedIn: boolean\n authStatus: AuthStatus\n authErrorCode: string | null\n user: User | null\n did: string | null\n scope: string | null\n hasScope: (scope: string) => boolean\n missingScopes: () => string[]\n\n signIn: () => Promise<void>\n signInWithHandle: (handle: string) => Promise<void>\n signOut: () => Promise<void>\n signInWithCode: (code: string, state?: string) => Promise<AuthResult>\n\n getToken: (options?: GetTokenOptions) => Promise<string>\n getSignInUrl: (redirectUri?: string) => Promise<string>\n\n db: BasicDB\n dbStatus: DBStatus\n dbMode: DBMode\n\n /** Local schema vs server status; null if no schema on the provider. */\n devInfo: BasicSchemaDevInfo | null\n /** Re-run remote schema check (dev toolbar). */\n refreshSchemaStatus: () => Promise<void>\n\n isAuthReady: boolean\n signin: () => Promise<void>\n signout: () => Promise<void>\n signinWithCode: (code: string, state?: string) => Promise<AuthResult>\n getSignInLink: (redirectUri?: string) => Promise<string>\n}\n\nconst noDb: BasicDB = {\n collection: () => {\n throw new Error('no basicdb found - initialization failed. double check your schema.')\n },\n}\n\nexport const BasicContext = createContext<BasicContextType>({\n isReady: false,\n isSignedIn: false,\n authStatus: 'bootstrapping',\n authErrorCode: null,\n user: null,\n did: null,\n scope: null,\n hasScope: () => false,\n missingScopes: () => [],\n\n signIn: () => Promise.resolve(),\n signInWithHandle: () => Promise.resolve(),\n signOut: () => Promise.resolve(),\n signInWithCode: () => Promise.resolve({ success: false }),\n\n getToken: (_options?: GetTokenOptions) => Promise.reject(new Error('no token')),\n getSignInUrl: () => Promise.resolve(''),\n\n db: noDb,\n dbStatus: DBStatus.LOADING,\n dbMode: 'sync',\n\n devInfo: null,\n refreshSchemaStatus: async () => {},\n\n isAuthReady: false,\n signin: () => Promise.resolve(),\n signout: () => Promise.resolve(),\n signinWithCode: () => Promise.resolve({ success: false }),\n getSignInLink: () => Promise.resolve(''),\n})\n\nexport function useBasic() {\n return useContext(BasicContext)\n}\n\nexport { noDb }\n","'use client'\n\nimport React, { useCallback, useMemo, useState } from 'react'\nimport { useBasic, DBStatus } from '../context'\nimport type { BasicSchemaDevInfo } from '../context'\nimport { version as sdkVersion } from '../../package.json'\nimport { isDevelopment } from '../utils/network'\n\nconst INDEXED_DB_NAME = 'basicdb'\nconst PANEL_PAD_X = 12\n\ntype ChipTone = 'ok' | 'warn' | 'bad' | 'muted'\n\nfunction toneForAuth(isReady: boolean, isSignedIn: boolean): ChipTone {\n if (!isReady) return 'muted'\n if (isSignedIn) return 'ok'\n return 'warn'\n}\n\nfunction toneForDb(dbMode: string, dbStatus: DBStatus): ChipTone {\n if (dbMode === 'remote') return dbStatus === DBStatus.ONLINE ? 'ok' : 'warn'\n if (dbStatus === DBStatus.ONLINE || dbStatus === DBStatus.SYNCING) return 'ok'\n if (dbStatus === DBStatus.CONNECTING || dbStatus === DBStatus.LOADING) return 'warn'\n if (dbStatus === DBStatus.OFFLINE) return 'muted'\n return 'bad'\n}\n\nfunction toneForSchema(info: BasicSchemaDevInfo | null): ChipTone {\n if (!info) return 'muted'\n if (info.valid && info.status === 'current') return 'ok'\n if (info.status === 'unpublished') return 'warn'\n if (info.status === 'no_schema') return 'muted'\n return 'bad'\n}\n\nfunction dbStatusLabel(status: DBStatus): string {\n switch (status) {\n case DBStatus.LOADING:\n return 'Initializing'\n case DBStatus.OFFLINE:\n return 'Offline'\n case DBStatus.CONNECTING:\n return 'Connecting'\n case DBStatus.ONLINE:\n return 'Connected'\n case DBStatus.SYNCING:\n return 'Syncing'\n case DBStatus.ERROR:\n return 'Error'\n case DBStatus.ERROR_WILL_RETRY:\n return 'Retrying'\n case DBStatus.ERROR_TOKEN_EXPIRED:\n return 'Token refresh'\n default:\n return String(status)\n }\n}\n\nfunction chipColor(tone: ChipTone): string {\n switch (tone) {\n case 'ok':\n return '#22c55e'\n case 'warn':\n return '#eab308'\n case 'bad':\n return '#ef4444'\n default:\n return '#71717a'\n }\n}\n\n/** Full value for display in dev panel (wraps; no truncation). */\nfunction displayDid(did: string | null): string {\n return did || '—'\n}\n\nfunction displayUserLine(user: { sub?: string; email?: string; name?: string; picture?: string }): string {\n const parts: string[] = []\n if (user.sub) parts.push(`sub: ${user.sub}`)\n if (user.email) parts.push(`email: ${user.email}`)\n if (user.name) parts.push(`name: ${user.name}`)\n return parts.length ? parts.join(' · ') : '—'\n}\n\nfunction ClipboardIcon() {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n )\n}\n\nexport type BasicDevToolbarProps = {\n /** When false, toolbar does not render. Defaults to true when used standalone. */\n enabled?: boolean\n /** Same as BasicProvider `debug` — when true, toolbar shows even off localhost. */\n debug?: boolean\n}\n\ntype CopyableRowProps = {\n rowKey: string\n label: string\n copyText: string\n copiedKey: string | null\n onCopied: (key: string) => void\n children: React.ReactNode\n}\n\nfunction SectionHeader({ children }: { children: React.ReactNode }) {\n return (\n <div\n style={{\n fontSize: 10,\n fontWeight: 700,\n color: '#e4e4e7',\n letterSpacing: '0.07em',\n textTransform: 'uppercase',\n marginBottom: 8,\n }}\n >\n {children}\n </div>\n )\n}\n\n/** Full-bleed horizontal rule: only above a section (not under the header). */\nfunction SectionRule() {\n const bleed = PANEL_PAD_X\n return (\n <div\n role=\"separator\"\n style={{\n height: 1,\n background: 'rgba(255, 255, 255, 0.055)',\n marginLeft: -bleed,\n marginRight: -bleed,\n marginTop: 14,\n marginBottom: 10,\n width: `calc(100% + ${bleed * 2}px)`,\n }}\n />\n )\n}\n\nfunction CopyableRow({\n rowKey,\n label,\n copyText,\n copiedKey,\n onCopied,\n children,\n}: CopyableRowProps) {\n const [hover, setHover] = useState(false)\n const canCopy = copyText.length > 0\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n if (!canCopy) return\n void navigator.clipboard.writeText(copyText).then(() => onCopied(rowKey))\n },\n [canCopy, copyText, onCopied, rowKey],\n )\n\n return (\n <div\n role={canCopy ? 'button' : undefined}\n tabIndex={canCopy ? 0 : undefined}\n onClick={canCopy ? handleClick : undefined}\n onKeyDown={\n canCopy\n ? (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleClick(e as unknown as React.MouseEvent)\n }\n }\n : undefined\n }\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n display: 'flex',\n gap: 8,\n marginBottom: 6,\n alignItems: 'flex-start',\n borderRadius: 6,\n padding: '4px 6px',\n marginLeft: -6,\n marginRight: -6,\n cursor: canCopy ? 'pointer' : 'default',\n background: hover && canCopy ? 'rgba(255,255,255,0.06)' : 'transparent',\n transition: 'background 0.12s ease',\n }}\n >\n <span style={{ color: '#a1a1aa', minWidth: 88, flexShrink: 0, paddingTop: 2 }}>{label}</span>\n <span\n style={{\n flex: 1,\n minWidth: 0,\n wordBreak: 'break-all',\n paddingTop: 2,\n lineHeight: 1.35,\n }}\n >\n {children}\n </span>\n {canCopy && (\n <span\n style={{\n flexShrink: 0,\n color: copiedKey === rowKey ? '#22c55e' : '#71717a',\n opacity: hover || copiedKey === rowKey ? 1 : 0,\n transition: 'opacity 0.12s ease, color 0.12s ease',\n paddingTop: 2,\n display: 'flex',\n alignItems: 'flex-start',\n }}\n title=\"Copy value\"\n >\n {copiedKey === rowKey ? (\n <span style={{ fontSize: 10 }}>✓</span>\n ) : (\n <ClipboardIcon />\n )}\n </span>\n )}\n </div>\n )\n}\n\n/**\n * Floating dev-only toolbar: auth, DB/sync, and schema status. Requires `BasicProvider` with `debug` or localhost / NODE_ENV=development for visibility unless `enabled` is forced.\n */\nexport function BasicDevToolbar({ enabled = true, debug }: BasicDevToolbarProps) {\n const {\n isReady,\n isSignedIn,\n user,\n did,\n scope,\n missingScopes,\n dbMode,\n dbStatus,\n devInfo,\n refreshSchemaStatus,\n } = useBasic()\n\n const [open, setOpen] = useState(false)\n const [refreshing, setRefreshing] = useState(false)\n const [copied, setCopied] = useState(false)\n const [rowCopied, setRowCopied] = useState<string | null>(null)\n\n const show =\n enabled && typeof window !== 'undefined' && isDevelopment(debug)\n\n const authTone = toneForAuth(isReady, isSignedIn)\n const dbTone = toneForDb(dbMode, dbStatus)\n const schemaTone = toneForSchema(devInfo)\n\n const syncTone: ChipTone =\n dbMode === 'remote'\n ? 'muted'\n : dbTone === 'ok' || dbStatus === DBStatus.SYNCING\n ? 'ok'\n : dbTone === 'warn'\n ? 'warn'\n : dbTone === 'bad'\n ? 'bad'\n : 'muted'\n\n const handleRefreshSchema = useCallback(async () => {\n setRefreshing(true)\n try {\n await refreshSchemaStatus()\n } finally {\n setRefreshing(false)\n }\n }, [refreshSchemaStatus])\n\n const missingList = missingScopes()\n\n const debugPayload = useMemo(() => {\n return {\n sdkVersion,\n isReady,\n isSignedIn,\n did: did ?? null,\n user: user\n ? {\n sub: user.sub,\n email: user.email,\n name: user.name,\n picture: user.picture,\n }\n : null,\n scope,\n missingScopes: missingList,\n dbMode,\n dbStatus,\n indexedDbName: dbMode === 'sync' ? INDEXED_DB_NAME : null,\n schema: devInfo,\n }\n }, [isReady, isSignedIn, did, user, scope, dbMode, dbStatus, devInfo, missingList])\n\n const handleCopy = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(JSON.stringify(debugPayload, null, 2))\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n } catch {\n /* ignore */\n }\n }, [debugPayload])\n\n const onRowCopied = useCallback((key: string) => {\n setRowCopied(key)\n setTimeout(() => setRowCopied((k) => (k === key ? null : k)), 1500)\n }, [])\n\n if (!show) return null\n\n const shell: React.CSSProperties = {\n position: 'fixed',\n bottom: 12,\n left: '50%',\n transform: 'translateX(-50%)',\n zIndex: 99999,\n fontFamily:\n 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace',\n fontSize: 11,\n color: '#e4e4e7',\n pointerEvents: 'auto',\n }\n\n const bar: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '8px 12px',\n borderRadius: 999,\n background: 'rgba(24, 24, 27, 0.92)',\n border: '1px solid rgba(63, 63, 70, 0.9)',\n boxShadow: '0 8px 32px rgba(0,0,0,0.35)',\n cursor: 'pointer',\n userSelect: 'none',\n }\n\n /** Fixed box so flex line-height / strut cannot stretch dots when the pill width changes. */\n const dot = (tone: ChipTone) => (\n <span\n style={{\n display: 'block',\n boxSizing: 'border-box',\n width: 6,\n height: 6,\n minWidth: 6,\n minHeight: 6,\n maxWidth: 6,\n maxHeight: 6,\n borderRadius: '50%',\n background: chipColor(tone),\n flexShrink: 0,\n }}\n />\n )\n\n const dotSlot = (title: string, tone: ChipTone) => (\n <span\n title={title}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 6,\n height: 6,\n flexShrink: 0,\n lineHeight: 0,\n }}\n >\n {dot(tone)}\n </span>\n )\n\n const panel: React.CSSProperties = {\n marginBottom: 8,\n maxHeight: '50vh',\n overflow: 'auto',\n padding: PANEL_PAD_X,\n borderRadius: 10,\n background: 'rgba(24, 24, 27, 0.96)',\n border: '1px solid rgba(63, 63, 70, 0.9)',\n boxShadow: '0 8px 32px rgba(0,0,0,0.35)',\n minWidth: 300,\n maxWidth: 'min(560px, calc(100vw - 24px))',\n }\n\n const syncStatusText = dbStatusLabel(dbStatus)\n\n return (\n <div style={shell}>\n {open && (\n <div style={panel}>\n <div style={{ marginBottom: 12 }}>\n <div style={{ fontWeight: 600, fontSize: 12 }}>Basic SDK</div>\n <div style={{ color: '#71717a', fontSize: 10, marginTop: 2 }}>v{sdkVersion}</div>\n </div>\n\n <SectionHeader>Auth</SectionHeader>\n <CopyableRow\n rowKey=\"ready\"\n label=\"Ready\"\n copyText={String(isReady)}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {String(isReady)}\n </CopyableRow>\n <CopyableRow\n rowKey=\"signedIn\"\n label=\"Signed in\"\n copyText={String(isSignedIn)}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {String(isSignedIn)}\n </CopyableRow>\n <CopyableRow\n rowKey=\"did\"\n label=\"DID\"\n copyText={did || ''}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {displayDid(did)}\n </CopyableRow>\n <CopyableRow\n rowKey=\"user\"\n label=\"User\"\n copyText={user ? displayUserLine(user) : ''}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {user ? displayUserLine(user) : '—'}\n </CopyableRow>\n <CopyableRow\n rowKey=\"scopes\"\n label=\"Scopes\"\n copyText={scope || ''}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {scope || '—'}\n </CopyableRow>\n <CopyableRow\n rowKey=\"missingScopes\"\n label=\"Missing scopes\"\n copyText={missingList.length ? missingList.join(', ') : ''}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {missingList.length ? missingList.join(', ') : '—'}\n </CopyableRow>\n\n <SectionRule />\n <SectionHeader>Database</SectionHeader>\n <CopyableRow\n rowKey=\"dbMode\"\n label=\"Mode\"\n copyText={dbMode}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {dbMode}\n </CopyableRow>\n <CopyableRow\n rowKey=\"indexedDb\"\n label=\"IndexedDB\"\n copyText={dbMode === 'sync' ? INDEXED_DB_NAME : ''}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {dbMode === 'sync' ? INDEXED_DB_NAME : '—'}\n </CopyableRow>\n <CopyableRow\n rowKey=\"syncStatus\"\n label=\"Sync / status\"\n copyText={syncStatusText}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {syncStatusText}\n </CopyableRow>\n\n <SectionRule />\n <SectionHeader>Schema</SectionHeader>\n {devInfo ? (\n <>\n <CopyableRow\n rowKey=\"schemaProject\"\n label=\"Project\"\n copyText={devInfo.projectId ?? ''}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {devInfo.projectId ?? '—'}\n </CopyableRow>\n <CopyableRow\n rowKey=\"schemaLocalVer\"\n label=\"Local version\"\n copyText={\n devInfo.localVersion !== undefined && devInfo.localVersion !== null\n ? String(devInfo.localVersion)\n : ''\n }\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {devInfo.localVersion ?? '—'}\n </CopyableRow>\n <CopyableRow\n rowKey=\"schemaRemote\"\n label=\"Remote check\"\n copyText={devInfo.status}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {devInfo.status}\n </CopyableRow>\n <CopyableRow\n rowKey=\"schemaValid\"\n label=\"Valid\"\n copyText={String(devInfo.valid)}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {String(devInfo.valid)}\n </CopyableRow>\n <CopyableRow\n rowKey=\"schemaChecked\"\n label=\"Checked\"\n copyText={\n devInfo.lastCheckedAt\n ? new Date(devInfo.lastCheckedAt).toISOString()\n : ''\n }\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {devInfo.lastCheckedAt\n ? new Date(devInfo.lastCheckedAt).toLocaleString()\n : '—'}\n </CopyableRow>\n {devInfo.error ? (\n <CopyableRow\n rowKey=\"schemaError\"\n label=\"Error\"\n copyText={devInfo.error}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {devInfo.error}\n </CopyableRow>\n ) : null}\n </>\n ) : (\n <CopyableRow\n rowKey=\"schemaStatus\"\n label=\"Status\"\n copyText=\"No schema on provider\"\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n No schema on provider\n </CopyableRow>\n )}\n\n <div style={{ display: 'flex', gap: 8, marginTop: 12, flexWrap: 'wrap' }}>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n void handleRefreshSchema()\n }}\n disabled={refreshing}\n style={{\n padding: '6px 10px',\n borderRadius: 6,\n border: '1px solid #3f3f46',\n background: '#27272a',\n color: '#e4e4e7',\n cursor: refreshing ? 'wait' : 'pointer',\n fontSize: 11,\n fontFamily: 'inherit',\n }}\n >\n {refreshing ? 'Refreshing…' : 'Refresh schema'}\n </button>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n void handleCopy()\n }}\n style={{\n padding: '6px 10px',\n borderRadius: 6,\n border: '1px solid #3f3f46',\n background: '#27272a',\n color: '#e4e4e7',\n cursor: 'pointer',\n fontSize: 11,\n fontFamily: 'inherit',\n }}\n >\n {copied ? 'Copied' : 'Copy debug info'}\n </button>\n </div>\n </div>\n )}\n\n <button\n type=\"button\"\n aria-expanded={open}\n onClick={() => setOpen((o) => !o)}\n style={{\n ...bar,\n border: 'none',\n width: '100%',\n cursor: 'pointer',\n }}\n >\n <span style={{ fontWeight: 600, letterSpacing: 0.02 }}>Basic</span>\n <span\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: 6,\n marginLeft: 8,\n height: 6,\n flexShrink: 0,\n lineHeight: 0,\n }}\n >\n {dotSlot('Auth', authTone)}\n {dotSlot('DB', dbTone)}\n {dotSlot('Sync', syncTone)}\n {dotSlot('Schema', schemaTone)}\n </span>\n <span style={{ color: '#71717a', marginLeft: 4 }}>{open ? '▾' : '▴'}</span>\n </button>\n </div>\n )\n}\n","import React, {\n useCallback,\n useEffect,\n useRef,\n useState,\n Suspense,\n lazy,\n} from 'react'\n\nimport { BasicSync, initDexieExtensions } from './sync'\nimport { RemoteDB, DBMode, BasicDB } from './core/db'\nimport { AuthManager } from './core/auth/AuthManager'\nimport type {\n User,\n AuthResult,\n GetTokenOptions,\n PdsEndpoints,\n AuthStatus,\n} from './core/auth/AuthManager'\n\nimport { log } from './config'\nimport { version as currentVersion } from '../package.json'\nimport { createVersionUpdater } from './updater/versionUpdater'\nimport { getMigrations } from './updater/updateMigrations'\nimport { BasicStorage, LocalStorageAdapter } from './utils/storage'\nimport {\n isDevelopment,\n checkForNewVersion,\n getSyncStatus,\n} from './utils/network'\nimport { validateAndCheckSchema } from './utils/schema'\nimport {\n BasicContext,\n DBStatus,\n noDb,\n type BasicSchemaDevInfo,\n} from './context'\n\nconst BasicDevToolbar = lazy(() =>\n import('./dev/BasicDevToolbar').then((m) => ({ default: m.BasicDevToolbar })),\n)\n\nexport type { BasicStorage, LocalStorageAdapter } from './utils/storage'\nexport type { DBMode, BasicDB, Collection } from './core/db'\nexport type {\n Token,\n User,\n AuthResult,\n GetTokenOptions,\n PdsEndpoints,\n AuthStatus,\n} from './core/auth/AuthManager'\nexport type { BasicContextType, BasicSchemaDevInfo } from './context'\nexport { DBStatus, useBasic, BasicContext } from './context'\n\nexport type AuthConfig = {\n scopes?: string | string[]\n /** @deprecated Use pds_url instead */\n server_url?: string\n /** PDS URL for auth and data (default: https://pds.basic.id) */\n pds_url?: string\n /** Admin server URL for connect reporting (default: https://api.basic.tech) */\n admin_url?: string\n ws_url?: string\n}\n\nexport type BasicProviderProps = {\n children: React.ReactNode\n /**\n * @deprecated Project ID is now extracted from schema.project_id.\n * This prop is kept for backward compatibility but can be omitted.\n */\n project_id?: string\n /** The Basic schema object containing project_id and table definitions */\n schema?: any\n debug?: boolean\n storage?: BasicStorage\n auth?: AuthConfig\n /**\n * Database mode - determines which implementation is used\n * - 'sync': Uses Dexie + WebSocket for local-first sync (default)\n * - 'remote': Uses REST API calls directly to server\n */\n dbMode?: DBMode\n /** Show floating dev toolbar (localhost, NODE_ENV=development, or debug=true). */\n devToolbar?: boolean\n}\n\nconst DEFAULT_AUTH_CONFIG = {\n scopes: 'profile,email,app:admin',\n pds_url: 'https://pds.basic.id',\n admin_url: 'https://api.basic.tech',\n ws_url: 'wss://pds.basic.id/ws',\n} as const\n\ntype ErrorObject = {\n code: string\n title: string\n message: string\n}\n\ntype AuthSnapshot = {\n isSignedIn: boolean\n hasToken: boolean\n isAuthReady: boolean\n authStatus: AuthStatus\n authErrorCode: string | null\n user: User | null\n did: string | null\n tokenScope: string | null\n}\n\nfunction snapshotAuth(mgr: AuthManager): AuthSnapshot {\n return {\n isSignedIn: mgr.isSignedIn,\n hasToken: !!mgr.token,\n isAuthReady: mgr.isAuthReady,\n authStatus: mgr.authStatus,\n authErrorCode: mgr.authErrorCode,\n user: mgr.user,\n did: mgr.did,\n tokenScope: mgr.tokenScope,\n }\n}\n\nexport function BasicProvider({\n children,\n project_id: project_id_prop,\n schema,\n debug = false,\n storage,\n auth,\n dbMode = 'sync',\n devToolbar = false,\n}: BasicProviderProps) {\n const project_id = schema?.project_id || project_id_prop\n\n if (auth?.server_url && !auth?.pds_url) {\n log('Warning: auth.server_url is deprecated, use auth.pds_url instead')\n }\n const authConfig = {\n scopes: auth?.scopes || DEFAULT_AUTH_CONFIG.scopes,\n pds_url: auth?.pds_url || auth?.server_url || DEFAULT_AUTH_CONFIG.pds_url,\n admin_url: auth?.admin_url || DEFAULT_AUTH_CONFIG.admin_url,\n ws_url: auth?.ws_url || DEFAULT_AUTH_CONFIG.ws_url,\n }\n\n const scopesString = Array.isArray(authConfig.scopes)\n ? authConfig.scopes.join(' ')\n : authConfig.scopes\n\n const storageRef = useRef<BasicStorage>(storage || new LocalStorageAdapter())\n const storageAdapter = storageRef.current\n\n const schemaRef = useRef(schema)\n schemaRef.current = schema\n\n const [authState, setAuthState] = useState<AuthSnapshot>({\n isSignedIn: false,\n hasToken: false,\n isAuthReady: false,\n authStatus: 'bootstrapping',\n authErrorCode: null,\n user: null,\n did: null,\n tokenScope: null,\n })\n\n const authRef = useRef<AuthManager>(null!)\n if (!authRef.current) {\n authRef.current = new AuthManager(\n {\n projectId: project_id,\n scopes: scopesString,\n pdsUrl: authConfig.pds_url,\n adminUrl: authConfig.admin_url,\n debug,\n },\n storageAdapter,\n () => setAuthState(snapshotAuth(authRef.current)),\n )\n }\n\n const syncRef = useRef<BasicSync | null>(null)\n const remoteDbRef = useRef<RemoteDB | null>(null)\n const [shouldConnect, setShouldConnect] = useState(false)\n const [dbStatus, setDbStatus] = useState<DBStatus>(DBStatus.OFFLINE)\n const [isDbReady, setIsDbReady] = useState(false)\n const [error, setError] = useState<ErrorObject | null>(null)\n const [schemaDevInfo, setSchemaDevInfo] = useState<BasicSchemaDevInfo | null>(\n null,\n )\n\n const isDevMode = () => isDevelopment(debug)\n\n const refreshSchemaStatus = useCallback(async () => {\n const s = schemaRef.current\n if (!s) {\n setSchemaDevInfo(\n project_id\n ? {\n projectId: project_id,\n localVersion: undefined,\n status: 'no_schema',\n valid: false,\n lastCheckedAt: Date.now(),\n }\n : null,\n )\n return\n }\n const result = await validateAndCheckSchema(s)\n if (!result.isValid) {\n const errText =\n result.errors\n ?.map((e: { message?: string }) => e.message || '')\n .join('; ') || 'invalid'\n setSchemaDevInfo({\n projectId: s.project_id ?? null,\n localVersion: s.version,\n status: 'invalid',\n valid: false,\n lastCheckedAt: Date.now(),\n error: errText,\n })\n return\n }\n setSchemaDevInfo({\n projectId: s.project_id ?? null,\n localVersion: s.version,\n status: result.schemaStatus.status ?? 'unknown',\n valid: result.schemaStatus.valid,\n lastCheckedAt: Date.now(),\n })\n }, [project_id])\n\n useEffect(() => {\n const runVersionUpdater = async () => {\n try {\n const versionUpdater = createVersionUpdater(\n storageAdapter,\n currentVersion,\n getMigrations(),\n )\n const updateResult = await versionUpdater.checkAndUpdate()\n\n if (updateResult.updated) {\n log(\n `App updated from ${updateResult.fromVersion} to ${updateResult.toVersion}`,\n )\n } else {\n log(`App version ${updateResult.toVersion} is current`)\n }\n } catch (error) {\n log('Version update failed:', error)\n }\n }\n\n runVersionUpdater()\n authRef.current.initialize()\n\n return authRef.current.setupNetworkListeners()\n }, [])\n\n useEffect(() => {\n async function initSyncDb(options: { shouldConnect: boolean }) {\n if (!syncRef.current) {\n log('Initializing Basic Sync DB')\n\n await initDexieExtensions()\n\n syncRef.current = new BasicSync('basicdb', { schema: schema })\n\n syncRef.current.syncable.on('statusChanged', (status: number) => {\n const newStatus = getSyncStatus(status) as DBStatus\n setDbStatus(newStatus)\n\n if (newStatus === DBStatus.ERROR_WILL_RETRY) {\n log(\n 'Sync entered ERROR_WILL_RETRY - reconciling auth session before retry',\n )\n authRef.current\n .reconcileSession('sync retry', {\n forceRefresh: true,\n throttleMs: 0,\n })\n .catch(() => {})\n }\n })\n\n if (options.shouldConnect) {\n setShouldConnect(true)\n } else {\n log('Sync is disabled')\n }\n\n setIsDbReady(true)\n }\n }\n\n function initRemoteDb() {\n if (!remoteDbRef.current) {\n if (!project_id) {\n setError({\n code: 'missing_project_id',\n title: 'Project ID Required',\n message:\n 'Remote mode requires a project_id. Provide it via schema.project_id or the project_id prop.',\n })\n setIsDbReady(true)\n return\n }\n\n log('Initializing Basic Remote DB')\n remoteDbRef.current = new RemoteDB({\n serverUrl: authConfig.pds_url,\n projectId: project_id,\n getToken: (opts) => authRef.current.getToken(opts),\n schema: schema,\n debug: debug,\n onAuthError: (error) => {\n log('RemoteDB auth error:', error)\n if (error.errorType === 'forbidden') {\n log('403 Forbidden - user lacks required scope, not signing out')\n return\n }\n authRef.current\n .reconcileSession(`remote db ${error.errorType}`, {\n forceRefresh: error.errorType !== 'network',\n throttleMs: 0,\n })\n .catch((reconcileError) => {\n log('RemoteDB auth recovery failed:', reconcileError)\n })\n },\n })\n setDbStatus(DBStatus.ONLINE)\n setIsDbReady(true)\n }\n }\n\n async function checkSchema() {\n const result = await validateAndCheckSchema(schema)\n\n if (!result.isValid) {\n let errorMessage = ''\n if (result.errors) {\n result.errors.forEach((err: any, index: number) => {\n errorMessage += `${index + 1}: ${err.message} - at ${err.instancePath}\\n`\n })\n }\n setSchemaDevInfo({\n projectId: schema?.project_id ?? null,\n localVersion: schema?.version,\n status: 'invalid',\n valid: false,\n lastCheckedAt: Date.now(),\n error: errorMessage.trim() || undefined,\n })\n setError({\n code: 'schema_invalid',\n title: 'Basic Schema is invalid!',\n message: errorMessage,\n })\n setIsDbReady(true)\n return null\n }\n\n setSchemaDevInfo({\n projectId: schema?.project_id ?? null,\n localVersion: schema?.version,\n status: result.schemaStatus.status ?? 'unknown',\n valid: result.schemaStatus.valid,\n lastCheckedAt: Date.now(),\n })\n\n if (dbMode === 'remote') {\n initRemoteDb()\n } else {\n if (result.schemaStatus.valid) {\n await initSyncDb({ shouldConnect: true })\n } else {\n if (result.schemaStatus.status === 'unpublished') {\n log(\n 'Schema not published yet (version 0) - sync is disabled. Publish your schema to enable sync.',\n )\n } else {\n log('Schema is invalid!', result.schemaStatus)\n }\n await initSyncDb({ shouldConnect: false })\n }\n }\n\n checkForNewVersion()\n }\n\n if (schema) {\n checkSchema()\n } else {\n setSchemaDevInfo(\n project_id\n ? {\n projectId: project_id,\n localVersion: undefined,\n status: 'no_schema',\n valid: false,\n lastCheckedAt: Date.now(),\n }\n : null,\n )\n if (dbMode === 'remote' && project_id) {\n initRemoteDb()\n } else {\n setIsDbReady(true)\n }\n }\n }, [])\n\n useEffect(() => {\n if (\n authState.hasToken &&\n syncRef.current &&\n authState.isSignedIn &&\n authState.authStatus !== 'reauth_required' &&\n shouldConnect\n ) {\n log('connecting to db...')\n\n syncRef.current\n ?.connect({\n getToken: (opts?: GetTokenOptions) => authRef.current.getToken(opts),\n ws_url: authConfig.ws_url,\n })\n .catch((e: any) => {\n log('error connecting to db', e)\n })\n }\n }, [\n authState.authStatus,\n authState.isSignedIn,\n authState.hasToken,\n shouldConnect,\n ])\n\n useEffect(() => {\n if (authState.authStatus !== 'reauth_required' || !syncRef.current) {\n return\n }\n\n log('Auth requires reauthentication - disconnecting sync without deleting local DB')\n setDbStatus(DBStatus.ERROR_TOKEN_EXPIRED)\n syncRef.current\n .disconnect({ ws_url: authConfig.ws_url })\n .catch((disconnectError: unknown) => {\n log('Error disconnecting sync after auth invalidation:', disconnectError)\n })\n }, [authConfig.ws_url, authState.authStatus])\n\n // TODO: replace reload with proper sync DB teardown + re-init so\n // sign-out → sign-in works without a full page reload.\n const handleSignOut = async () => {\n await authRef.current.signOut()\n if (syncRef.current) {\n try {\n await syncRef.current.close()\n await syncRef.current.delete({ disableAutoOpen: false })\n syncRef.current = null\n } catch (error) {\n console.error('Error during database cleanup:', error)\n }\n }\n if (typeof window !== 'undefined') {\n window.location.reload()\n }\n }\n\n const handleSignIn = async () => {\n try {\n await authRef.current.signIn()\n } catch (error) {\n if (isDevMode()) {\n setError({\n code: 'signin_error',\n title: 'Sign-in Failed',\n message:\n (error as Error).message ||\n 'An error occurred during sign-in. Please try again.',\n })\n }\n throw error\n }\n }\n\n const handleSignInWithHandle = async (handle: string) => {\n try {\n await authRef.current.signInWithHandle(handle)\n } catch (error) {\n if (isDevMode()) {\n setError({\n code: 'signin_error',\n title: 'Sign-in Failed',\n message:\n (error as Error).message ||\n 'An error occurred during sign-in. Please try again.',\n })\n }\n throw error\n }\n }\n\n const getCurrentDb = (): BasicDB => {\n if (dbMode === 'remote') {\n return remoteDbRef.current || noDb\n }\n return syncRef.current || noDb\n }\n\n const contextValue = {\n isReady: authState.isAuthReady,\n isSignedIn: authState.isSignedIn,\n authStatus: authState.authStatus,\n authErrorCode: authState.authErrorCode,\n user: authState.user,\n did: authState.did,\n scope: authState.tokenScope,\n hasScope: (s: string) => authRef.current.hasScope(s),\n missingScopes: () => authRef.current.missingScopes(),\n\n signIn: handleSignIn,\n signInWithHandle: handleSignInWithHandle,\n signOut: handleSignOut,\n signInWithCode: (code: string, state?: string) =>\n authRef.current.signInWithCode(code, state),\n\n getToken: (opts?: GetTokenOptions) => authRef.current.getToken(opts),\n getSignInUrl: (redirectUri?: string) =>\n authRef.current.getSignInUrl(redirectUri),\n\n db: getCurrentDb(),\n dbStatus,\n dbMode,\n\n devInfo: schemaDevInfo,\n refreshSchemaStatus,\n\n isAuthReady: authState.isAuthReady,\n signin: handleSignIn,\n signout: handleSignOut,\n signinWithCode: (code: string, state?: string) =>\n authRef.current.signInWithCode(code, state),\n getSignInLink: (redirectUri?: string) =>\n authRef.current.getSignInUrl(redirectUri),\n }\n\n return (\n <BasicContext.Provider value={contextValue}>\n {error && isDevMode() && <ErrorDisplay error={error} />}\n {devToolbar && isDevMode() && (\n <Suspense fallback={null}>\n <BasicDevToolbar debug={debug} />\n </Suspense>\n )}\n {isDbReady && authState.isAuthReady && children}\n </BasicContext.Provider>\n )\n}\n\nfunction ErrorDisplay({ error }: { error: ErrorObject }) {\n return (\n <div\n style={{\n position: 'absolute',\n top: 20,\n left: 20,\n color: 'black',\n backgroundColor: '#f8d7da',\n border: '1px solid #f5c6cb',\n borderRadius: '4px',\n padding: '20px',\n maxWidth: '400px',\n margin: '20px auto',\n boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',\n fontFamily: 'monospace',\n }}\n >\n <h3 style={{ fontSize: '0.8rem', opacity: 0.8 }}>code: {error.code}</h3>\n <h1 style={{ fontSize: '1.2rem', lineHeight: 1.5 }}>{error.title}</h1>\n <p>{error.message}</p>\n </div>\n )\n}\n","\"use client\"\n\nimport { v7 as uuidv7 } from 'uuid';\nimport { Dexie } from 'dexie';\n\nimport { log } from '../config'\nimport { validateData } from '@basictech/schema'\nimport { setTokenGetter } from './tokenRegistry'\n\n// Track initialization state\nlet dexieExtensionsLoaded = false;\nlet initPromise: Promise<void> | null = null;\n\n/**\n * Initialize Dexie extensions (syncable and observable)\n * This must be called before creating a BasicSync instance\n * Safe to call multiple times - will only load once\n */\nexport async function initDexieExtensions(): Promise<void> {\n // Return early if already loaded or not in browser\n if (dexieExtensionsLoaded) return;\n if (typeof window === 'undefined') return;\n \n // If already initializing, wait for that promise\n if (initPromise) return initPromise;\n \n initPromise = (async () => {\n try {\n // Dynamic imports - only loaded in browser\n await import('dexie-syncable');\n await import('dexie-observable');\n \n // Import and register sync protocol\n const { syncProtocol } = await import('./syncProtocol');\n syncProtocol();\n \n dexieExtensionsLoaded = true;\n log('Dexie extensions loaded successfully');\n } catch (error) {\n console.error('Failed to load Dexie extensions:', error);\n throw error;\n }\n })();\n \n return initPromise;\n}\n\n/**\n * Check if Dexie extensions are loaded\n */\nexport function isDexieReady(): boolean {\n return dexieExtensionsLoaded;\n}\n\n\nexport class BasicSync extends Dexie {\n basic_schema: any\n\n constructor(name: string, options: any) {\n super(name, options);\n\n // --- INIT SCHEMA --- //\n this.basic_schema = options.schema\n this.version(1).stores(this._convertSchemaToDxSchema(this.basic_schema))\n this.version(2).stores({})\n\n // @ts-ignore - alias for toArray\n this.Collection.prototype.get = this.Collection.prototype.toArray\n }\n\n async connect({ getToken, ws_url }: { getToken: (opts?: { forceRefresh?: boolean }) => Promise<string>, ws_url?: string }) {\n const WS_URL = ws_url || 'wss://pds.basic.id/ws'\n\n log('Connecting to', WS_URL)\n\n // Store getToken in module-level registry (not in options) because\n // dexie-syncable serializes options into IndexedDB via structured clone,\n // which cannot handle functions.\n setTokenGetter(WS_URL, getToken)\n\n await this.updateSyncNodes();\n \n log('Starting connection...')\n return this.syncable.connect(\"websocket\", WS_URL, { schema: this.basic_schema });\n }\n\n async disconnect({ ws_url }: { ws_url?: string } = {}) {\n const WS_URL = ws_url || 'wss://pds.basic.id/ws'\n\n return this.syncable.disconnect(WS_URL) \n }\n\n private async updateSyncNodes() {\n try {\n const syncNodes = await this.table('_syncNodes').toArray();\n const localSyncNodes = syncNodes.filter(node => node.type === 'local');\n log('Local sync nodes:', localSyncNodes);\n\n if (localSyncNodes.length > 1) {\n\n \n const largestNodeId = Math.max(...localSyncNodes.map(node => node.id));\n // Check if the largest node is already the master\n const largestNode = localSyncNodes.find(node => node.id === largestNodeId);\n if (largestNode && largestNode.isMaster === 1) {\n log('Largest node is already the master. No changes needed.');\n return; // Exit the function early as no changes are needed\n }\n\n\n log('Largest node id:', largestNodeId);\n log('HEISENBUG: More than one local sync node found.')\n\n for (const node of localSyncNodes) {\n log(`Local sync node keys:`, node.id, node.isMaster);\n await this.table('_syncNodes').update(node.id, { isMaster: node.id === largestNodeId ? 1 : 0 });\n\n log(`HEISENBUG: Setting ${node.id} to ${node.id === largestNodeId ? 'master' : '0'}`);\n }\n\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n if (typeof window !== 'undefined') {\n window.location.reload();\n }\n }\n\n log('Sync nodes updated');\n } catch (error) {\n console.error('Error updating _syncNodes table:', error);\n }\n }\n\n handleStatusChange(fn: any) {\n this.syncable.on(\"statusChanged\", fn)\n }\n\n\n _convertSchemaToDxSchema(schema: any) {\n const stores = Object.entries(schema.tables).map(([key, table]: any) => {\n const indexedFields = Object.entries(table.fields)\n .filter(([, field]: any) => field.indexed)\n .map(([fieldKey]: any) => `,${fieldKey}`)\n .join('')\n return {\n [key]: 'id' + indexedFields\n }\n })\n\n return Object.assign({}, ...stores)\n }\n\n debugeroo() {\n return this.syncable\n }\n\n collection<T extends { id: string } = Record<string, any> & { id: string }>(name: string) {\n // Validate table exists in schema\n if (this.basic_schema?.tables && !this.basic_schema.tables[name]) {\n throw new Error(`Table \"${name}\" not found in schema`)\n }\n\n const table = this.table(name)\n\n return {\n /**\n * Returns the underlying Dexie table\n * @type {Dexie.Table}\n */\n ref: table,\n\n // --- WRITE ---- // \n\n /**\n * Add a new record - returns the full object with generated id\n */\n add: async (data: Omit<T, 'id'>): Promise<T> => {\n const valid = validateData(this.basic_schema, name, data)\n if (!valid.valid) {\n log('Invalid data', valid)\n throw new Error(valid.message || 'Data validation failed')\n }\n\n const id = uuidv7()\n const fullData = { id, ...data } as T\n \n await table.add(fullData)\n return fullData\n },\n\n /**\n * Put (upsert) a record - returns the full object\n */\n put: async (data: T): Promise<T> => {\n if (!data.id) {\n throw new Error('put() requires an id field')\n }\n\n const valid = validateData(this.basic_schema, name, data)\n if (!valid.valid) {\n log('Invalid data', valid)\n throw new Error(valid.message || 'Data validation failed')\n }\n\n await table.put(data)\n return data\n },\n\n /**\n * Update an existing record - returns updated object or null\n */\n update: async (id: string, data: Partial<Omit<T, 'id'>>): Promise<T | null> => {\n if (!id) {\n throw new Error('update() requires an id')\n }\n\n const valid = validateData(this.basic_schema, name, data, false)\n if (!valid.valid) {\n log('Invalid data', valid)\n throw new Error(valid.message || 'Data validation failed')\n }\n\n const updated = await table.update(id, data)\n if (updated === 0) {\n return null\n }\n\n // Fetch and return the updated record\n const record = await table.get(id)\n return (record as T) || null\n },\n\n /**\n * Delete a record - returns true if deleted, false if not found\n */\n delete: async (id: string): Promise<boolean> => {\n if (!id) {\n throw new Error('delete() requires an id')\n }\n\n // Check if record exists first\n const exists = await table.get(id)\n if (!exists) {\n return false\n }\n\n await table.delete(id)\n return true\n },\n\n // --- READ ---- // \n\n /**\n * Get a single record by id - returns null if not found\n */\n get: async (id: string): Promise<T | null> => {\n if (!id) {\n throw new Error('get() requires an id')\n }\n\n const record = await table.get(id)\n return (record as T) || null\n },\n\n /**\n * Get all records in the collection\n */\n getAll: async (): Promise<T[]> => {\n return table.toArray() as Promise<T[]>\n },\n\n // --- QUERY ---- // \n\n /**\n * Filter records using a predicate function\n */\n filter: async (fn: (item: T) => boolean): Promise<T[]> => {\n return table.filter(fn).toArray() as Promise<T[]>\n },\n\n /**\n * Get the raw Dexie table for advanced queries\n * @deprecated Use ref instead\n */\n query: () => table,\n }\n }\n}\n","/**\n * Core DB types for Basic SDK\n * These interfaces are implemented by both SyncDB (Dexie-based) and RemoteDB (REST-based)\n */\n\n/**\n * Collection interface for CRUD operations on a table\n * All write operations return the full object (not just the id)\n */\nexport interface Collection<T extends { id: string } = Record<string, any> & { id: string }> {\n /**\n * Add a new record to the collection\n * @param data - The data to add (without id, which will be generated)\n * @returns The created object with its generated id\n */\n add(data: Omit<T, 'id'>): Promise<T>\n\n /**\n * Put (upsert) a record - requires id\n * @param data - The full object including id\n * @returns The upserted object\n */\n put(data: T): Promise<T>\n\n /**\n * Update an existing record by id\n * @param id - The record id to update\n * @param data - Partial data to merge\n * @returns The updated object, or null if not found\n */\n update(id: string, data: Partial<Omit<T, 'id'>>): Promise<T | null>\n\n /**\n * Delete a record by id\n * @param id - The record id to delete\n * @returns true if deleted, false if not found\n */\n delete(id: string): Promise<boolean>\n\n /**\n * Get a single record by id\n * @param id - The record id to fetch\n * @returns The object or null if not found\n */\n get(id: string): Promise<T | null>\n\n /**\n * Get all records in the collection\n * @returns Array of all objects\n */\n getAll(): Promise<T[]>\n\n /**\n * Filter records using a predicate function\n * @param fn - Filter function that returns true for matches\n * @returns Array of matching objects\n */\n filter(fn: (item: T) => boolean): Promise<T[]>\n\n /**\n * Direct access to underlying storage (optional)\n * For sync mode: Dexie table reference\n * For remote mode: undefined\n */\n ref?: any\n}\n\n/**\n * BasicDB interface - factory for creating collections\n */\nexport interface BasicDB {\n /**\n * Get a collection by name\n * @param name - The table/collection name (must match schema)\n * @returns A Collection instance for CRUD operations\n */\n collection<T extends { id: string } = Record<string, any> & { id: string }>(name: string): Collection<T>\n}\n\n/**\n * Database mode - determines which implementation is used\n * - 'sync': Uses Dexie + WebSocket for local-first sync (default)\n * - 'remote': Uses REST API calls directly to server\n */\nexport type DBMode = 'sync' | 'remote'\n\n/**\n * Auth error information passed to onAuthError callback\n */\nexport interface AuthError {\n status: number\n message: string\n response?: any\n /** Classifies the error for UI display (e.g. \"session expired\" vs \"forbidden\") */\n errorType: 'expired' | 'forbidden' | 'revoked' | 'network' | 'unknown'\n /** True if this error occurred after a retry with a refreshed token */\n afterRetry: boolean\n}\n\n/**\n * Custom error class for Remote DB API errors\n * Includes HTTP status code for reliable error handling\n */\nexport class RemoteDBError extends Error {\n status: number\n response?: any\n\n constructor(message: string, status: number, response?: any) {\n super(message)\n this.name = 'RemoteDBError'\n this.status = status\n this.response = response\n }\n}\n\n/**\n * Options for getToken (e.g. force refresh after 401)\n */\nexport interface GetTokenOptions {\n /** When true, refresh the access token before returning (e.g. after server returned 401) */\n forceRefresh?: boolean\n}\n\n/**\n * Configuration for RemoteDB\n */\nexport interface RemoteDBConfig {\n serverUrl: string\n projectId: string\n getToken: (options?: GetTokenOptions) => Promise<string>\n schema?: any\n /** Enable debug logging (default: false) */\n debug?: boolean\n /**\n * Optional callback when authentication fails (401 error after retry)\n * Use this to show login UI or redirect to sign-in\n */\n onAuthError?: (error: AuthError) => void\n}\n\n","import { Collection, RemoteDBConfig, RemoteDBError } from './types'\nimport { validateData } from '@basictech/schema'\n\n/**\n * Error thrown when user is not authenticated\n */\nexport class NotAuthenticatedError extends Error {\n constructor(message: string = 'Not authenticated') {\n super(message)\n this.name = 'NotAuthenticatedError'\n }\n}\n\n/**\n * RemoteCollection - REST API based implementation of the Collection interface\n * All operations make HTTP calls to the Basic API server\n */\nexport class RemoteCollection<T extends { id: string } = Record<string, any> & { id: string }> implements Collection<T> {\n private tableName: string\n private config: RemoteDBConfig\n\n constructor(tableName: string, config: RemoteDBConfig) {\n this.tableName = tableName\n this.config = config\n }\n\n private log(...args: any[]) {\n if (this.config.debug) {\n console.log('[RemoteDB]', ...args)\n }\n }\n\n /**\n * Check if an error is a \"not authenticated\" error\n */\n private isNotAuthenticatedError(error: unknown): boolean {\n if (error instanceof Error) {\n const message = error.message.toLowerCase()\n return message.includes('no token') || \n message.includes('not authenticated') ||\n message.includes('please sign in')\n }\n return false\n }\n\n /**\n * Helper to make authenticated API requests\n * Automatically retries once on 401 (token expired) by refreshing the token\n */\n private async request<R>(\n method: string,\n path: string,\n body?: any,\n isRetry: boolean = false\n ): Promise<R> {\n // Try to get token - may throw if not authenticated\n const token = await this.config.getToken()\n const url = `${this.config.serverUrl}${path}`\n\n this.log(`${method} ${url}`, body ? JSON.stringify(body) : '')\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${token}`\n }\n if (body) {\n headers['Content-Type'] = 'application/json'\n }\n\n const response = await fetch(url, {\n method,\n headers,\n ...(body ? { body: JSON.stringify(body) } : {})\n })\n\n const responseData = await response.json().catch(() => ({}))\n\n if (!response.ok) {\n // Handle 401 Unauthorized - force refresh then retry once\n if (response.status === 401 && !isRetry) {\n this.log('Got 401, forcing token refresh and retrying...')\n await this.config.getToken({ forceRefresh: true })\n return this.request<R>(method, path, body, true)\n }\n\n if (this.config.debug) {\n console.error(`[RemoteDB] Error ${response.status}:`, responseData)\n }\n \n // Call onAuthError callback for auth/authz errors\n if (this.config.onAuthError) {\n if (response.status === 401) {\n this.config.onAuthError({\n status: response.status,\n message: 'Authentication failed',\n response: responseData,\n errorType: 'expired',\n afterRetry: isRetry,\n })\n } else if (response.status === 403) {\n this.config.onAuthError({\n status: response.status,\n message: responseData.message || 'Forbidden - insufficient permissions or missing scope',\n response: responseData,\n errorType: 'forbidden',\n afterRetry: isRetry,\n })\n }\n }\n\n const errorMessage = responseData.message || responseData.error || responseData.detail || \n (typeof responseData === 'string' ? responseData : `API request failed: ${response.status}`)\n throw new RemoteDBError(errorMessage, response.status, responseData)\n }\n\n this.log('Response:', responseData)\n return responseData\n }\n\n /**\n * Validate data against schema if available\n */\n private validateData(data: any, checkRequired: boolean = true): void {\n if (this.config.schema) {\n const result = validateData(this.config.schema, this.tableName, data, checkRequired)\n if (!result.valid) {\n throw new Error(result.message || 'Data validation failed')\n }\n }\n }\n\n /**\n * Get the base path for this collection\n */\n private get basePath(): string {\n return `/account/${this.config.projectId}/db/${this.tableName}`\n }\n\n /**\n * Add a new record to the collection\n * The server generates the ID\n * Requires authentication - throws NotAuthenticatedError if not signed in\n */\n async add(data: Omit<T, 'id'>): Promise<T> {\n this.validateData(data, true)\n\n try {\n const result = await this.request<{ data: T }>(\n 'POST',\n this.basePath,\n { value: data }\n )\n // Server returns the created record with the generated ID\n return result.data\n } catch (error) {\n if (this.isNotAuthenticatedError(error)) {\n throw new NotAuthenticatedError('Sign in required to add items')\n }\n throw error\n }\n }\n\n /**\n * Put (upsert) a record - requires id\n * Requires authentication - throws NotAuthenticatedError if not signed in\n */\n async put(data: T): Promise<T> {\n if (!data.id) {\n throw new Error('put() requires an id field')\n }\n\n // Extract id from data, send the rest in the body\n const { id, ...rest } = data\n this.validateData(rest, true)\n\n try {\n const result = await this.request<{ data: T }>(\n 'PUT',\n `${this.basePath}/${id}`,\n { value: rest }\n )\n return result.data || data\n } catch (error) {\n if (this.isNotAuthenticatedError(error)) {\n throw new NotAuthenticatedError('Sign in required to update items')\n }\n throw error\n }\n }\n\n /**\n * Update an existing record by id\n * Requires authentication - throws NotAuthenticatedError if not signed in\n */\n async update(id: string, data: Partial<Omit<T, 'id'>>): Promise<T | null> {\n if (!id) {\n throw new Error('update() requires an id')\n }\n\n this.validateData(data, false)\n\n try {\n const result = await this.request<{ data: T }>(\n 'PATCH',\n `${this.basePath}/${id}`,\n { value: data }\n )\n\n return result.data || null\n } catch (error) {\n // If record not found, return null instead of throwing\n if (error instanceof RemoteDBError && error.status === 404) {\n return null\n }\n if (this.isNotAuthenticatedError(error)) {\n throw new NotAuthenticatedError('Sign in required to update items')\n }\n throw error\n }\n }\n\n /**\n * Delete a record by id\n * Requires authentication - throws NotAuthenticatedError if not signed in\n */\n async delete(id: string): Promise<boolean> {\n if (!id) {\n throw new Error('delete() requires an id')\n }\n\n try {\n await this.request<any>(\n 'DELETE',\n `${this.basePath}/${id}`\n )\n return true\n } catch (error) {\n // If record not found, return false instead of throwing\n if (error instanceof RemoteDBError && error.status === 404) {\n return false\n }\n if (this.isNotAuthenticatedError(error)) {\n throw new NotAuthenticatedError('Sign in required to delete items')\n }\n throw error\n }\n }\n\n /**\n * Get a single record by id\n * Returns null if not authenticated (graceful degradation for read operations)\n */\n async get(id: string): Promise<T | null> {\n if (!id) {\n throw new Error('get() requires an id')\n }\n\n try {\n // Use the API's id query parameter for efficient single-record fetch\n const result = await this.request<{ data: T[] }>(\n 'GET',\n `${this.basePath}?id=${id}`\n )\n return result.data?.[0] || null\n } catch (error) {\n // For get(), return null on any error (not found, not authenticated, etc.)\n if (this.isNotAuthenticatedError(error)) {\n this.log('Not authenticated - returning null for get()')\n }\n return null\n }\n }\n\n /**\n * Get all records in the collection\n * Returns empty array if not authenticated (graceful degradation for read operations)\n */\n async getAll(): Promise<T[]> {\n try {\n const result = await this.request<{ data: T[] }>(\n 'GET',\n this.basePath\n )\n return result.data || []\n } catch (error) {\n // If not authenticated, return empty array gracefully\n if (this.isNotAuthenticatedError(error)) {\n this.log('Not authenticated - returning empty array for getAll()')\n return []\n }\n throw error\n }\n }\n\n /**\n * Filter records using a predicate function\n * Note: This fetches all records and filters client-side\n * Returns empty array if not authenticated (graceful degradation for read operations)\n */\n async filter(fn: (item: T) => boolean): Promise<T[]> {\n const all = await this.getAll()\n return all.filter(fn)\n }\n\n /**\n * ref is not available for remote collections\n */\n ref = undefined\n}\n","import { BasicDB, Collection, RemoteDBConfig } from './types'\nimport { RemoteCollection } from './RemoteCollection'\n\n/**\n * RemoteDB - REST API based implementation of BasicDB\n * Creates RemoteCollection instances for each table\n */\nexport class RemoteDB implements BasicDB {\n private config: RemoteDBConfig\n private collections: Map<string, RemoteCollection<any>> = new Map()\n\n constructor(config: RemoteDBConfig) {\n this.config = config\n }\n\n /**\n * Get a collection by name\n * Collections are cached for reuse\n */\n collection<T extends { id: string } = Record<string, any> & { id: string }>(\n name: string\n ): Collection<T> {\n // Return cached collection if exists\n if (this.collections.has(name)) {\n return this.collections.get(name) as RemoteCollection<T>\n }\n\n // Validate table exists in schema if schema is provided\n if (this.config.schema?.tables && !this.config.schema.tables[name]) {\n throw new Error(`Table \"${name}\" not found in schema`)\n }\n\n // Create and cache new collection\n const collection = new RemoteCollection<T>(name, this.config)\n this.collections.set(name, collection)\n\n return collection\n }\n}\n\n","import { jwtDecode } from 'jwt-decode'\nimport { BasicStorage, STORAGE_KEYS } from '../../utils/storage'\nimport { normalizeClientId } from '../../utils/normalizeClientId'\nimport { resolveHandle } from '../../utils/resolveDid'\nimport { cleanOAuthParamsFromUrl } from '../../utils/network'\nimport { log } from '../../config'\n\nconst DEFINITIVE_TOKEN_ERRORS = new Set([\n 'invalid_grant',\n 'invalid_client',\n 'unauthorized_client',\n])\nconst USER_RECOVERY_RETRY_COOLDOWN_MS = 30_000\nconst SESSION_RECONCILE_THROTTLE_MS = 5_000\n\nclass DefinitiveAuthError extends Error {\n readonly code: string\n\n constructor(code: string) {\n super(`Definitive auth failure: ${code}`)\n this.name = 'DefinitiveAuthError'\n this.code = code\n }\n}\n\n// --- PKCE helpers (RFC 7636) ---\n\nfunction generateCodeVerifier(): string {\n const array = new Uint8Array(32)\n crypto.getRandomValues(array)\n return base64UrlEncode(array)\n}\n\nasync function generateCodeChallenge(\n verifier: string,\n): Promise<{ challenge: string; method: 'S256' | 'plain' }> {\n if (typeof crypto === 'undefined' || !crypto.subtle) {\n log(\n 'crypto.subtle unavailable (non-secure context?) -- falling back to plain PKCE challenge',\n )\n return { challenge: verifier, method: 'plain' }\n }\n const encoder = new TextEncoder()\n const data = encoder.encode(verifier)\n const digest = await crypto.subtle.digest('SHA-256', data)\n return { challenge: base64UrlEncode(new Uint8Array(digest)), method: 'S256' }\n}\n\nfunction base64UrlEncode(buffer: Uint8Array): string {\n let str = ''\n for (let i = 0; i < buffer.length; i++) {\n str += String.fromCharCode(buffer[i]!)\n }\n return btoa(str).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\nexport type Token = {\n access_token: string\n token_type: string\n expires_in: number\n refresh_token: string\n}\n\nexport type User = {\n sub?: string\n name?: string\n email?: string\n picture?: string\n}\n\n/**\n * High-level auth lifecycle state.\n *\n * - `bootstrapping` — SDK is initializing; not yet determined if a session exists.\n * - `authenticated` — User has a valid access token and active session.\n * - `recovering` — A session likely exists (refresh token / cached user) but\n * the SDK hasn't confirmed it yet (e.g. offline, mid-refresh).\n * - `reauth_required` — The session is definitively invalid (revoked, expired\n * refresh token, etc.). The user must sign in again.\n * NOTE: `isSignedIn` remains `true` in this state so the UI\n * can display user info while prompting re-authentication.\n * Use `authStatus === 'reauth_required'` to distinguish\n * this from a healthy signed-in state.\n * - `signed_out` — No session. User is not authenticated.\n *\n * TODO: revisit naming and ergonomics — consider adding a `needsReauth` or\n * `shouldPromptSignIn` convenience getter so consumers don't need to inspect\n * the raw status to decide between \"sign in\" vs \"sign out\" UI.\n */\nexport type AuthStatus =\n | 'bootstrapping'\n | 'authenticated'\n | 'recovering'\n | 'reauth_required'\n | 'signed_out'\n\nexport type AuthResult = {\n success: boolean\n error?: string\n code?: string\n}\n\nexport type GetTokenOptions = {\n forceRefresh?: boolean\n}\n\nexport type PdsEndpoints = {\n pds_url: string\n authorization_endpoint: string\n token_endpoint: string\n userinfo_endpoint: string\n}\n\nexport type AuthManagerConfig = {\n projectId: string | undefined\n scopes: string\n pdsUrl: string\n adminUrl: string\n debug: boolean\n}\n\ntype JwtClaims = {\n sub?: string\n scope?: string\n typ?: string\n exp?: number\n}\n\ntype CurrentSessionInfo = {\n active: boolean\n reauth_required?: boolean\n session_id?: string | null\n client_id?: string\n scope?: string\n account_did?: string\n connection_status?: string\n last_seen_at?: string | null\n error?: string\n}\n\n/**\n * Framework-agnostic auth manager. Holds token state, handles OAuth flow,\n * token refresh (with mutex), and user info fetching.\n *\n * React integration: pass a state-setter as `notify` so the component\n * re-renders whenever auth state changes.\n */\nexport class AuthManager {\n // --- Public state (read by the UI layer) ---\n token: Token | null = null\n user: User | null = null\n isSignedIn: boolean = false\n isAuthReady: boolean = false\n authStatus: AuthStatus = 'bootstrapping'\n authErrorCode: string | null = null\n did: string | null = null\n /** Space-separated scopes granted in the current access token */\n tokenScope: string | null = null\n /** Space-separated scopes originally requested in the auth config */\n requestedScopes: string\n\n readonly config: AuthManagerConfig\n readonly storage: BasicStorage\n\n /** True only during a user-initiated OAuth code exchange (not session restore) */\n private freshSignIn: boolean = false\n\n // --- Private ---\n private notify: () => void\n private refreshPromise: Promise<Token | null> | null = null\n private codeExchangePromise: Promise<Token | null> | null = null\n private pendingRefresh: boolean = false\n private isOnline: boolean =\n typeof navigator !== 'undefined' ? navigator.onLine : true\n private channel: BroadcastChannel | null = null\n private nextUserRecoveryAt: number = 0\n private sessionCheckPromise: Promise<void> | null = null\n private lastSessionCheckAt: number = 0\n\n constructor(\n config: AuthManagerConfig,\n storage: BasicStorage,\n notify: () => void,\n ) {\n this.config = config\n this.storage = storage\n this.notify = notify\n this.requestedScopes = config.scopes\n this.initCrossTabSync()\n }\n\n private initCrossTabSync(): void {\n if (typeof BroadcastChannel === 'undefined') return\n\n try {\n this.channel = new BroadcastChannel('basic-auth')\n this.channel.onmessage = (event) => {\n if (event.data?.type === 'token_refreshed') {\n log('Received token refresh from another tab')\n void this.handleExternalTokenRefresh(event.data)\n }\n if (event.data?.type === 'signed_in') {\n log('Received sign-in from another tab, restoring session')\n void this.restoreStoredSession('cross-tab sign-in')\n }\n if (event.data?.type === 'signed_out') {\n log('Received sign-out from another tab')\n this.resetAuthState('signed_out')\n this.notify()\n // TODO: replace reload with proper cross-tab sync teardown so\n // other tabs can clean up without a full page reload.\n if (typeof window !== 'undefined') {\n window.location.reload()\n }\n }\n if (event.data?.type === 'session_invalidated') {\n log('Received session invalidation from another tab')\n void this.markReauthRequired(event.data.code || 'invalid_grant', {\n broadcast: false,\n })\n }\n }\n } catch {\n log('BroadcastChannel not available for cross-tab sync')\n }\n }\n\n private broadcastTokenRefresh(): void {\n this.channel?.postMessage({\n type: 'token_refreshed',\n accessToken: this.token?.access_token,\n did: this.did,\n tokenScope: this.tokenScope,\n })\n }\n\n private broadcastSignIn(): void {\n this.channel?.postMessage({ type: 'signed_in' })\n }\n\n private broadcastSignOut(): void {\n this.channel?.postMessage({ type: 'signed_out' })\n }\n\n private broadcastSessionInvalidated(code: string): void {\n this.channel?.postMessage({ type: 'session_invalidated', code })\n }\n\n // ------------------------------------------------------------------\n // Public API\n // ------------------------------------------------------------------\n\n /**\n * Bootstrap auth: handle OAuth callback (?code=), restore session\n * from refresh token, or load cached user for offline mode.\n */\n async initialize(): Promise<void> {\n this.updateAuthStatus('bootstrapping')\n await this.storage.set(\n STORAGE_KEYS.DEBUG,\n this.config.debug ? 'true' : 'false',\n )\n\n const storedServerUrl = await this.storage.get(STORAGE_KEYS.SERVER_URL)\n if (storedServerUrl && storedServerUrl !== this.config.pdsUrl) {\n log('PDS URL changed, clearing stored tokens')\n await this.clearStoredAuth()\n }\n await this.storage.set(STORAGE_KEYS.SERVER_URL, this.config.pdsUrl)\n\n try {\n const params = new URLSearchParams(window.location.search)\n\n if (params.has('code')) {\n const code = params.get('code')\n if (!code) {\n this.updateAuthStatus('signed_out')\n this.notify()\n return\n }\n\n const state = await this.storage.get(STORAGE_KEYS.AUTH_STATE)\n const urlState = params.get('state')\n if (!state || state !== urlState) {\n log('error: auth state does not match')\n this.updateAuthStatus('signed_out')\n this.notify()\n await this.storage.remove(STORAGE_KEYS.AUTH_STATE)\n cleanOAuthParamsFromUrl()\n return\n }\n\n await this.storage.remove(STORAGE_KEYS.AUTH_STATE)\n cleanOAuthParamsFromUrl()\n\n this.freshSignIn = true\n this.exchangeToken(code, false).catch((error) => {\n log('Error fetching token:', error)\n this.freshSignIn = false\n void this.restoreCachedUser({\n hasRecoverableSession: !this.isDefinitiveAuthFailure(error),\n })\n })\n } else {\n await this.restoreStoredSession('initialize')\n }\n } catch (e) {\n log('error getting token', e)\n this.updateAuthStatus('signed_out')\n this.notify()\n }\n }\n\n /**\n * Get a valid access token string. Refreshes proactively (5s buffer)\n * or on demand (forceRefresh). Mutex prevents concurrent refreshes.\n */\n async getToken(options?: GetTokenOptions): Promise<string> {\n log('getting token...')\n\n if (!this.token) {\n const refreshToken = await this.getRefreshToken()\n if (refreshToken) {\n log('No token in memory, attempting to refresh from storage')\n\n if (this.refreshPromise) {\n log('Token refresh already in progress, waiting...')\n try {\n const newToken = await this.refreshPromise\n if (newToken?.access_token) {\n return newToken.access_token\n }\n } catch (error) {\n log('In-flight refresh failed:', error)\n throw error\n }\n }\n\n try {\n const newToken = await this.exchangeToken(refreshToken, true)\n if (newToken?.access_token) {\n return newToken.access_token\n }\n } catch (error) {\n log('Failed to refresh token from storage:', error)\n if (this.isNetworkError(error)) {\n throw new Error(\n 'Network offline - authentication will be retried when online',\n )\n }\n if (!this.isDefinitiveAuthFailure(error)) {\n throw error\n }\n throw new Error('Authentication expired. Please sign in again.')\n }\n }\n log('no token found')\n throw new Error('no token found')\n }\n\n const decoded = jwtDecode<JwtClaims>(this.token.access_token)\n const expirationBuffer = 5\n const isExpired =\n decoded.exp && decoded.exp < Date.now() / 1000 + expirationBuffer\n const shouldRefresh = isExpired || options?.forceRefresh === true\n\n if (shouldRefresh) {\n log(\n options?.forceRefresh\n ? 'force refreshing token...'\n : 'token is expired - refreshing ...',\n )\n\n if (this.refreshPromise) {\n log('Token refresh already in progress, waiting...')\n try {\n const newToken = await this.refreshPromise\n if (!newToken?.access_token)\n throw new Error('Token refresh returned empty access token')\n return newToken.access_token\n } catch (error) {\n log('In-flight refresh failed:', error)\n if (this.isNetworkError(error)) {\n log('Network issue - using expired token until network is restored')\n return this.token.access_token\n }\n throw error\n }\n }\n\n const refreshToken = await this.getRefreshToken()\n if (refreshToken) {\n try {\n const newToken = await this.exchangeToken(refreshToken, true)\n if (!newToken?.access_token)\n throw new Error('Token refresh returned empty access token')\n return newToken.access_token\n } catch (error) {\n log('Failed to refresh expired token:', error)\n if (this.isNetworkError(error)) {\n log('Network issue - using expired token until network is restored')\n return this.token.access_token\n }\n if (!this.isDefinitiveAuthFailure(error)) {\n throw error\n }\n throw new Error('Authentication expired. Please sign in again.')\n }\n } else {\n throw new Error('no refresh token available')\n }\n }\n\n if (!this.token.access_token)\n throw new Error('Token exists but access_token is empty')\n return this.token.access_token\n }\n\n async getSignInUrl(\n redirectUri?: string,\n endpoints?: PdsEndpoints,\n ): Promise<string> {\n log('getting sign in link...')\n\n if (!this.config.projectId) {\n throw new Error('Project ID is required to generate sign-in link')\n }\n\n const pdsEndpoints = endpoints || this.defaultPdsEndpoints()\n await this.storage.set(\n STORAGE_KEYS.PDS_ENDPOINTS,\n JSON.stringify(pdsEndpoints),\n )\n\n const randomState = base64UrlEncode(\n crypto.getRandomValues(new Uint8Array(16)),\n )\n await this.storage.set(STORAGE_KEYS.AUTH_STATE, randomState)\n\n const redirectUrl = redirectUri || window.location.href\n if (\n !redirectUrl ||\n (!redirectUrl.startsWith('http://') &&\n !redirectUrl.startsWith('https://'))\n ) {\n throw new Error('Invalid redirect URI provided')\n }\n\n await this.storage.set(STORAGE_KEYS.REDIRECT_URI, redirectUrl)\n log('Stored redirect_uri for token exchange:', redirectUrl)\n\n // PKCE: generate code_verifier and code_challenge (RFC 7636)\n const codeVerifier = generateCodeVerifier()\n const { challenge: codeChallenge, method: challengeMethod } =\n await generateCodeChallenge(codeVerifier)\n await this.storage.set(STORAGE_KEYS.CODE_VERIFIER, codeVerifier)\n\n let baseUrl = pdsEndpoints.authorization_endpoint\n baseUrl += `?client_id=${encodeURIComponent(normalizeClientId(this.config.projectId, this.adminHostname))}`\n baseUrl += `&redirect_uri=${encodeURIComponent(redirectUrl)}`\n baseUrl += `&response_type=code`\n baseUrl += `&scope=${encodeURIComponent(this.config.scopes)}`\n baseUrl += `&state=${randomState}`\n baseUrl += `&code_challenge=${encodeURIComponent(codeChallenge)}`\n baseUrl += `&code_challenge_method=${challengeMethod}`\n\n log('Generated sign-in link successfully with scopes:', this.config.scopes)\n return baseUrl\n }\n\n async signIn(redirectUri?: string): Promise<void> {\n log('signing in...')\n\n if (!this.config.projectId) {\n log('Error: project_id is required for sign-in')\n throw new Error('Project ID is required for authentication')\n }\n\n const signInLink = await this.getSignInUrl(redirectUri)\n log('Generated sign-in link:', signInLink)\n\n try {\n new URL(signInLink)\n } catch {\n log('Error: Invalid sign-in link generated')\n throw new Error('Failed to generate valid sign-in URL')\n }\n\n window.location.href = signInLink\n }\n\n async signInWithHandle(handle: string): Promise<void> {\n log('signing in with handle:', handle)\n\n if (!this.config.projectId) {\n throw new Error('Project ID is required for authentication')\n }\n\n const resolved = await resolveHandle(handle)\n log('Resolved handle to PDS:', resolved.pdsUrl)\n\n const endpoints: PdsEndpoints = {\n pds_url: resolved.pdsUrl,\n authorization_endpoint: resolved.authorization_endpoint,\n token_endpoint: resolved.token_endpoint,\n userinfo_endpoint: resolved.userinfo_endpoint,\n }\n\n const signInLink = await this.getSignInUrl(undefined, endpoints)\n log('Generated federated sign-in link:', signInLink)\n\n try {\n new URL(signInLink)\n } catch {\n throw new Error('Failed to generate valid sign-in URL')\n }\n\n window.location.href = signInLink\n }\n\n async signInWithCode(code: string, state?: string): Promise<AuthResult> {\n try {\n log('signInWithCode called with code:', code)\n\n if (!code || typeof code !== 'string') {\n return { success: false, error: 'Invalid authorization code' }\n }\n\n if (state) {\n const storedState = await this.storage.get(STORAGE_KEYS.AUTH_STATE)\n if (storedState && storedState !== state) {\n log('State parameter mismatch:', {\n provided: state,\n stored: storedState,\n })\n return { success: false, error: 'State parameter mismatch' }\n }\n }\n\n await this.storage.remove(STORAGE_KEYS.AUTH_STATE)\n cleanOAuthParamsFromUrl()\n\n this.freshSignIn = true\n const token = await this.exchangeToken(code, false)\n if (token) {\n log('signInWithCode successful')\n return { success: true }\n } else {\n return { success: false, error: 'Failed to exchange code for token' }\n }\n } catch (error) {\n log('signInWithCode error:', error)\n this.freshSignIn = false\n return {\n success: false,\n error: (error as Error).message || 'Authentication failed',\n }\n }\n }\n\n /**\n * Clear auth state and storage. Does NOT handle sync/DB cleanup —\n * the UI layer (BasicProvider) wraps this to add sync teardown.\n */\n async signOut(): Promise<void> {\n log('signing out!')\n this.resetAuthState('signed_out')\n\n await this.storage.remove(STORAGE_KEYS.AUTH_STATE)\n await this.storage.remove(STORAGE_KEYS.LAST_CONNECT_REPORT)\n await this.clearStoredAuth()\n\n this.broadcastSignOut()\n this.notify()\n }\n\n async reconcileSession(\n reason: string = 'manual',\n options?: { forceRefresh?: boolean; throttleMs?: number },\n ): Promise<void> {\n if (this.authStatus === 'signed_out' || this.authStatus === 'reauth_required') {\n return\n }\n\n if (!this.isOnline) {\n this.updateAuthStatus('recovering', this.authErrorCode)\n this.notify()\n return\n }\n\n const throttleMs = options?.throttleMs ?? SESSION_RECONCILE_THROTTLE_MS\n const forceRefresh = options?.forceRefresh === true\n const now = Date.now()\n\n if (this.sessionCheckPromise) {\n return this.sessionCheckPromise\n }\n\n if (!forceRefresh && now - this.lastSessionCheckAt < throttleMs) {\n return\n }\n\n this.lastSessionCheckAt = now\n\n let sessionCheck: Promise<void> | null = null\n sessionCheck = (async () => {\n try {\n const accessToken = await this.getToken(\n forceRefresh ? { forceRefresh: true } : undefined,\n )\n const currentSession = await this.fetchCurrentSession(accessToken)\n if (currentSession?.active) {\n this.updateAuthStatus('authenticated')\n this.notify()\n if (!this.user) {\n await this.recoverMissingUserProfile(reason, accessToken)\n }\n }\n } catch (error) {\n log(`Session reconciliation failed on ${reason}:`, error)\n if (this.isDefinitiveAuthFailure(error)) {\n return\n }\n if (this.isNetworkError(error)) {\n this.updateAuthStatus('recovering', this.authErrorCode)\n this.notify()\n }\n } finally {\n if (this.sessionCheckPromise === sessionCheck) {\n this.sessionCheckPromise = null\n }\n }\n })()\n\n this.sessionCheckPromise = sessionCheck\n return sessionCheck\n }\n\n hasScope(scope: string): boolean {\n if (!this.tokenScope) return false\n return this.tokenScope\n .split(/[\\s,]+/)\n .filter(Boolean)\n .includes(scope)\n }\n\n /**\n * Returns scopes that were requested but not granted in the current token.\n * Useful after login or when a 403 is returned.\n */\n missingScopes(): string[] {\n const requested = this.requestedScopes.split(/[\\s,]+/).filter(Boolean)\n if (!this.tokenScope) return requested\n const granted = new Set(this.tokenScope.split(/[\\s,]+/).filter(Boolean))\n return requested.filter((s) => !granted.has(s))\n }\n\n /**\n * Register online/offline and visibility handlers that retry pending\n * refreshes and proactively refresh tokens when the app resumes from\n * background (critical for PWAs and mobile browsers where timers are\n * frozen while backgrounded).\n * Returns a cleanup function for useEffect teardown.\n */\n setupNetworkListeners(): () => void {\n const handleOnline = async () => {\n log('Network came back online')\n this.isOnline = true\n if (this.pendingRefresh) {\n log('Retrying pending token refresh')\n this.pendingRefresh = false\n const refreshToken = await this.getRefreshToken()\n if (refreshToken) {\n this.exchangeToken(refreshToken, true).catch((error) => {\n log('Retry refresh failed:', error)\n })\n }\n }\n if (this.isSignedIn) {\n this.reconcileSession('online event', {\n forceRefresh: true,\n throttleMs: 0,\n }).catch((error) => {\n log('Session reconciliation on online failed:', error)\n })\n } else if (this.user) {\n await this.restoreStoredSession('online restore')\n }\n }\n\n const handleOffline = () => {\n log('Network went offline')\n this.isOnline = false\n }\n\n const handleVisibilityChange = () => {\n if (document.visibilityState === 'visible' && this.isSignedIn) {\n log('App became visible - reconciling auth session')\n this.reconcileSession('visibility resume', {\n forceRefresh: true,\n }).catch((err) => {\n log('Session reconciliation on visibility resume failed:', err)\n })\n }\n }\n\n window.addEventListener('online', handleOnline)\n window.addEventListener('offline', handleOffline)\n\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', handleVisibilityChange)\n }\n\n return () => {\n window.removeEventListener('online', handleOnline)\n window.removeEventListener('offline', handleOffline)\n if (typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', handleVisibilityChange)\n }\n }\n }\n\n // ------------------------------------------------------------------\n // Private\n // ------------------------------------------------------------------\n\n private get adminHostname(): string {\n try {\n return new URL(this.config.adminUrl).hostname\n } catch {\n return 'api.basic.tech'\n }\n }\n\n private defaultPdsEndpoints(): PdsEndpoints {\n return {\n pds_url: this.config.pdsUrl,\n authorization_endpoint: `${this.config.pdsUrl}/auth/authorize`,\n token_endpoint: `${this.config.pdsUrl}/auth/token`,\n userinfo_endpoint: `${this.config.pdsUrl}/auth/userinfo`,\n }\n }\n\n private async getActivePdsEndpoints(): Promise<PdsEndpoints> {\n const stored = await this.storage.get(STORAGE_KEYS.PDS_ENDPOINTS)\n if (stored) {\n try {\n return JSON.parse(stored) as PdsEndpoints\n } catch {\n /* fall through */\n }\n }\n return this.defaultPdsEndpoints()\n }\n\n private async reportConnection(accessToken: string): Promise<void> {\n if (!this.config.projectId || !this.config.adminUrl) return\n const lastReport = await this.storage.get(STORAGE_KEYS.LAST_CONNECT_REPORT)\n if (lastReport) {\n const elapsed = Date.now() - parseInt(lastReport, 10)\n if (elapsed < 24 * 60 * 60 * 1000) return\n }\n try {\n await fetch(\n `${this.config.adminUrl}/project/${this.config.projectId}/user/connect`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token: accessToken }),\n },\n )\n await this.storage.set(\n STORAGE_KEYS.LAST_CONNECT_REPORT,\n Date.now().toString(),\n )\n log('Reported connection to admin server')\n } catch (err) {\n log('Failed to report connection (non-blocking):', err)\n }\n }\n\n /**\n * After a new token is stored, decode JWT claims and fetch user info.\n */\n private async processNewToken(): Promise<void> {\n if (!this.token) {\n this.updateAuthStatus('signed_out')\n this.notify()\n return\n }\n\n try {\n const decoded = jwtDecode<JwtClaims>(this.token.access_token)\n this.applyTokenClaims(decoded)\n this.updateAuthStatus('authenticated')\n this.notify()\n this.broadcastSessionUpdate()\n await this.fetchUser(this.token.access_token)\n } catch (error) {\n log('Error processing token:', error)\n this.updateAuthStatus('recovering')\n this.notify()\n }\n }\n\n private async restoreCachedUser(options?: {\n hasRecoverableSession: boolean\n }): Promise<void> {\n const cached = await this.storage.get(STORAGE_KEYS.USER_INFO)\n if (cached && options?.hasRecoverableSession) {\n try {\n this.user = JSON.parse(cached)\n log('Restored cached user info for recoverable session')\n } catch {\n /* corrupted cache, ignore */\n }\n } else {\n this.user = null\n }\n this.updateAuthStatus(\n options?.hasRecoverableSession ? 'recovering' : 'signed_out',\n )\n this.notify()\n }\n\n private async fetchUser(accessToken: string): Promise<void> {\n log('fetching user')\n try {\n const endpoints = await this.getActivePdsEndpoints()\n const response = await fetch(endpoints.userinfo_endpoint, {\n method: 'GET',\n headers: { Authorization: `Bearer ${accessToken}` },\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch user info: ${response.status}`)\n }\n\n const user = await response.json()\n\n if (user.error) {\n log('error fetching user', user.error)\n throw new Error(`User info error: ${user.error}`)\n }\n\n if (this.token?.refresh_token) {\n await this.storage.set(\n STORAGE_KEYS.REFRESH_TOKEN,\n this.token.refresh_token,\n )\n }\n\n await this.storage.set(STORAGE_KEYS.USER_INFO, JSON.stringify(user))\n log('Cached user info in storage')\n\n this.user = user\n if (this.authStatus !== 'reauth_required') {\n this.updateAuthStatus('authenticated')\n }\n this.nextUserRecoveryAt = 0\n this.notify()\n } catch (error) {\n log('Failed to fetch user info:', error)\n await this.handleUserFetchFailure()\n }\n }\n\n /**\n * Exchange an auth code or refresh token for an access token.\n * Handles mutex (one in-flight refresh), token validation, and\n * triggers processNewToken on success.\n */\n private async exchangeToken(\n codeOrRefreshToken: string,\n isRefreshToken: boolean,\n ): Promise<Token | null> {\n if (!codeOrRefreshToken || codeOrRefreshToken.trim() === '') {\n const errorMsg = isRefreshToken\n ? 'Refresh token is empty or undefined'\n : 'Authorization code is empty or undefined'\n log('Error:', errorMsg)\n throw new Error(errorMsg)\n }\n\n if (isRefreshToken && this.refreshPromise) {\n log('Reusing in-flight refresh token request')\n return this.refreshPromise\n }\n\n if (!isRefreshToken && this.codeExchangePromise) {\n log('Reusing in-flight code exchange request')\n return this.codeExchangePromise\n }\n\n const tokenPromise = (async (): Promise<Token | null> => {\n try {\n if (!this.isOnline) {\n log('Network is offline, marking refresh as pending')\n this.pendingRefresh = true\n throw new Error(\n 'Network offline - refresh will be retried when online',\n )\n }\n\n const endpoints = await this.getActivePdsEndpoints()\n let requestBody: any\n\n if (isRefreshToken) {\n requestBody = {\n grant_type: 'refresh_token',\n refresh_token: codeOrRefreshToken,\n }\n if (this.config.projectId) {\n requestBody.client_id = normalizeClientId(\n this.config.projectId,\n this.adminHostname,\n )\n }\n } else {\n requestBody = {\n grant_type: 'authorization_code',\n code: codeOrRefreshToken,\n }\n\n const storedRedirectUri = await this.storage.get(\n STORAGE_KEYS.REDIRECT_URI,\n )\n if (storedRedirectUri) {\n requestBody.redirect_uri = storedRedirectUri\n log('Including redirect_uri in token exchange:', storedRedirectUri)\n } else {\n log('Warning: No redirect_uri found in storage for token exchange')\n }\n\n // PKCE: include code_verifier from the authorization request\n const codeVerifier = await this.storage.get(\n STORAGE_KEYS.CODE_VERIFIER,\n )\n if (codeVerifier) {\n requestBody.code_verifier = codeVerifier\n }\n\n if (this.config.projectId) {\n requestBody.client_id = normalizeClientId(\n this.config.projectId,\n this.adminHostname,\n )\n }\n }\n\n log('Token exchange request body:', {\n ...requestBody,\n ...(isRefreshToken\n ? { refresh_token: '[REDACTED]' }\n : { code: '[REDACTED]' }),\n ...(requestBody.code_verifier ? { code_verifier: '[REDACTED]' } : {}),\n })\n\n const token = await fetch(endpoints.token_endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestBody),\n })\n .then((response) => response.json())\n .catch((error) => {\n log('Network error fetching token:', error)\n if (!this.isOnline) {\n this.pendingRefresh = true\n throw new Error(\n 'Network offline - refresh will be retried when online',\n )\n }\n throw new Error('Network error during token refresh')\n })\n\n if (token.access_token) {\n try {\n const decoded = jwtDecode<{ typ?: string }>(token.access_token)\n if (decoded.typ === 'refresh') {\n log('Error: received refresh token as access token')\n throw new Error(\n 'Invalid token: received refresh token instead of access token',\n )\n }\n } catch (decodeError) {\n if ((decodeError as Error).message.includes('Invalid token')) {\n throw decodeError\n }\n log(\n 'Warning: could not decode access token for type check:',\n decodeError,\n )\n }\n }\n\n if (token.error) {\n log('error fetching token', token.error)\n\n if (\n typeof token.error === 'string' &&\n (token.error.includes('network') || token.error.includes('timeout'))\n ) {\n this.pendingRefresh = true\n throw new Error(\n 'Network issue - refresh will be retried when online',\n )\n }\n\n // Only clear stored auth on definitive OAuth rejection.\n // Transient server errors (500, 503, etc.) should NOT wipe\n // the refresh token — the user can retry later.\n if (this.isDefinitiveTokenErrorCode(token.error)) {\n await this.markReauthRequired(token.error)\n throw new DefinitiveAuthError(token.error)\n }\n throw new Error(`Token refresh failed: ${token.error}`)\n } else {\n if (!token.access_token) {\n throw new Error('Token response missing access token')\n }\n this.token = token\n this.pendingRefresh = false\n\n if (token.refresh_token) {\n await this.storage.set(\n STORAGE_KEYS.REFRESH_TOKEN,\n token.refresh_token,\n )\n log('Updated refresh token in storage')\n }\n\n if (!isRefreshToken) {\n await this.storage.remove(STORAGE_KEYS.REDIRECT_URI)\n await this.storage.remove(STORAGE_KEYS.CODE_VERIFIER)\n log(\n 'Cleaned up redirect_uri and code_verifier from storage after successful exchange',\n )\n }\n\n this.reportConnection(token.access_token).catch(() => {})\n\n await this.processNewToken()\n }\n\n return token\n } catch (error) {\n log('Token refresh error:', error)\n if (this.isDefinitiveAuthFailure(error)) {\n log('Preserving cleared auth state after definitive token rejection')\n } else if (this.isNetworkError(error)) {\n log('Recoverable network auth failure - preserving session state')\n } else {\n log('Recoverable auth failure - preserving session state')\n }\n\n throw error\n }\n })()\n\n if (isRefreshToken) {\n this.refreshPromise = tokenPromise\n tokenPromise.finally(() => {\n if (this.refreshPromise === tokenPromise) {\n this.refreshPromise = null\n log('Cleared refresh promise reference')\n }\n })\n } else {\n this.codeExchangePromise = tokenPromise\n tokenPromise.finally(() => {\n if (this.codeExchangePromise === tokenPromise) {\n this.codeExchangePromise = null\n log('Cleared code exchange promise reference')\n }\n })\n }\n\n return tokenPromise\n }\n\n private resetAuthState(status: AuthStatus = 'signed_out'): void {\n this.user = status === 'reauth_required' ? this.user : null\n this.token = null\n if (status !== 'reauth_required') {\n this.did = null\n }\n this.tokenScope = null\n this.nextUserRecoveryAt = 0\n this.updateAuthStatus(status)\n }\n\n private async clearStoredAuth(): Promise<void> {\n await this.storage.remove(STORAGE_KEYS.REFRESH_TOKEN)\n await this.storage.remove(STORAGE_KEYS.USER_INFO)\n await this.storage.remove(STORAGE_KEYS.REDIRECT_URI)\n await this.storage.remove(STORAGE_KEYS.CODE_VERIFIER)\n await this.storage.remove(STORAGE_KEYS.SERVER_URL)\n await this.storage.remove(STORAGE_KEYS.PDS_ENDPOINTS)\n }\n\n private isNetworkError(error: unknown): boolean {\n if (error instanceof TypeError) return true\n if (error instanceof Error) {\n return (\n error.message.includes('offline') || error.message.includes('Network')\n )\n }\n return false\n }\n\n private async getRefreshToken(): Promise<string | null> {\n const storedRefreshToken = await this.storage.get(\n STORAGE_KEYS.REFRESH_TOKEN,\n )\n if (storedRefreshToken) {\n log('Using refresh token from storage')\n if (this.token && this.token.refresh_token !== storedRefreshToken) {\n this.token = { ...this.token, refresh_token: storedRefreshToken }\n }\n return storedRefreshToken\n }\n\n const memoryRefreshToken = this.token?.refresh_token ?? null\n if (memoryRefreshToken) {\n log('Using refresh token from memory fallback')\n } else {\n log('No refresh token available in storage or memory')\n }\n return memoryRefreshToken\n }\n\n private async syncRefreshTokenFromStorage(): Promise<void> {\n const storedRefreshToken = await this.storage.get(\n STORAGE_KEYS.REFRESH_TOKEN,\n )\n if (\n storedRefreshToken &&\n this.token &&\n this.token.refresh_token !== storedRefreshToken\n ) {\n this.token = { ...this.token, refresh_token: storedRefreshToken }\n log('Synced refresh token from shared storage into memory')\n }\n }\n\n private applyTokenClaims(decoded: JwtClaims): void {\n this.did = decoded.sub || null\n this.tokenScope = decoded.scope || null\n }\n\n private broadcastSessionUpdate(): void {\n if (this.freshSignIn) {\n this.freshSignIn = false\n this.broadcastSignIn()\n } else {\n this.broadcastTokenRefresh()\n }\n }\n\n private async handleUserFetchFailure(): Promise<void> {\n if (this.isCompatibleUser(this.user)) {\n log('Preserving existing user after userinfo failure')\n } else if (this.user) {\n log('Discarding stale in-memory user after userinfo failure')\n this.user = null\n }\n\n if (!this.user) {\n const cached = await this.storage.get(STORAGE_KEYS.USER_INFO)\n if (cached) {\n try {\n const parsed = JSON.parse(cached) as User\n if (this.isCompatibleUser(parsed)) {\n this.user = parsed\n log('Recovered cached user after userinfo failure')\n } else {\n log('Cached user did not match the active session')\n }\n } catch (error) {\n log('Failed to parse cached user after userinfo failure:', error)\n }\n }\n }\n\n if (!this.user) {\n log('No compatible cached user available after userinfo failure')\n this.nextUserRecoveryAt = Date.now() + USER_RECOVERY_RETRY_COOLDOWN_MS\n } else {\n this.nextUserRecoveryAt = 0\n }\n\n if (this.authStatus === 'bootstrapping') {\n this.updateAuthStatus(this.token ? 'authenticated' : 'recovering')\n }\n this.notify()\n }\n\n private isCompatibleUser(user: User | null): boolean {\n if (!user) return false\n if (!this.did) return true\n return user.sub === this.did\n }\n\n private async recoverMissingUserProfile(\n reason: string,\n accessToken?: string,\n ): Promise<void> {\n if (!this.isSignedIn || this.user) return\n const now = Date.now()\n if (this.nextUserRecoveryAt > now) {\n log(\n `Skipping user profile recovery on ${reason} until ${new Date(this.nextUserRecoveryAt).toISOString()}`,\n )\n return\n }\n log(`Attempting user profile recovery on ${reason}`)\n const token = accessToken ?? (await this.getToken())\n if (this.user) return\n await this.fetchUser(token)\n }\n\n private isDefinitiveTokenErrorCode(code: unknown): code is string {\n return typeof code === 'string' && DEFINITIVE_TOKEN_ERRORS.has(code)\n }\n\n private isDefinitiveAuthFailure(error: unknown): boolean {\n return error instanceof DefinitiveAuthError\n }\n\n /**\n * Centralised auth status setter. Derives `isSignedIn` and `isAuthReady`\n * from the status so they stay consistent.\n *\n * `isSignedIn` is intentionally `true` during `reauth_required` so the\n * UI layer can still display user info while prompting re-authentication.\n * Consumers should check `authStatus` (or a future convenience getter)\n * when they need to distinguish \"healthy session\" from \"needs re-auth\".\n */\n private updateAuthStatus(\n status: AuthStatus,\n errorCode: string | null = null,\n ): void {\n this.authStatus = status\n this.authErrorCode = errorCode\n this.isSignedIn =\n status === 'authenticated' ||\n status === 'recovering' ||\n status === 'reauth_required'\n this.isAuthReady = status !== 'bootstrapping'\n }\n\n private async clearStoredSessionTokens(): Promise<void> {\n await this.storage.remove(STORAGE_KEYS.REFRESH_TOKEN)\n await this.storage.remove(STORAGE_KEYS.REDIRECT_URI)\n await this.storage.remove(STORAGE_KEYS.CODE_VERIFIER)\n }\n\n private async restoreStoredSession(reason: string): Promise<void> {\n const refreshToken = await this.getRefreshToken()\n if (!refreshToken) {\n log(`No stored refresh token available during ${reason}`)\n await this.restoreCachedUser({ hasRecoverableSession: false })\n return\n }\n\n log(`Restoring stored session during ${reason}`)\n await this.restoreCachedUser({ hasRecoverableSession: true })\n\n if (!this.isOnline) {\n return\n }\n\n this.exchangeToken(refreshToken, true).catch(async (error) => {\n log(`Stored session refresh failed during ${reason}:`, error)\n if (this.isDefinitiveAuthFailure(error)) {\n return\n }\n await this.restoreCachedUser({ hasRecoverableSession: true })\n })\n }\n\n private async handleExternalTokenRefresh(data: {\n accessToken?: string\n did?: string\n tokenScope?: string\n }): Promise<void> {\n await this.syncRefreshTokenFromStorage()\n const refreshToken = await this.getRefreshToken()\n if (data.accessToken && refreshToken) {\n try {\n const decoded = jwtDecode<JwtClaims>(data.accessToken)\n const expiresIn =\n decoded.exp != null\n ? Math.max(0, decoded.exp - Math.floor(Date.now() / 1000))\n : 0\n this.token = {\n access_token: data.accessToken,\n token_type: 'Bearer',\n expires_in: expiresIn,\n refresh_token: refreshToken,\n }\n this.applyTokenClaims(decoded)\n } catch (error) {\n log('Failed to decode token refreshed by another tab:', error)\n this.token = {\n access_token: data.accessToken,\n token_type: 'Bearer',\n expires_in: 0,\n refresh_token: refreshToken,\n }\n }\n if (this.authStatus !== 'reauth_required') {\n this.updateAuthStatus('authenticated')\n }\n } else if (refreshToken) {\n await this.restoreCachedUser({ hasRecoverableSession: true })\n }\n\n if (data.did) this.did = data.did\n if (data.tokenScope) this.tokenScope = data.tokenScope\n this.notify()\n }\n\n private async fetchCurrentSession(\n accessToken: string,\n ): Promise<CurrentSessionInfo | null> {\n const endpoints = await this.getActivePdsEndpoints()\n const response = await fetch(`${endpoints.pds_url}/auth/session`, {\n method: 'GET',\n headers: { Authorization: `Bearer ${accessToken}` },\n })\n const data = (await response.json().catch(() => ({}))) as CurrentSessionInfo\n\n if (response.status === 401 && data.reauth_required) {\n await this.markReauthRequired(data.error || 'invalid_session')\n throw new DefinitiveAuthError(data.error || 'invalid_session')\n }\n\n if (!response.ok) {\n throw new Error(`Failed to reconcile session: ${response.status}`)\n }\n\n return data\n }\n\n private async markReauthRequired(\n code: string,\n options?: { broadcast?: boolean },\n ): Promise<void> {\n log('Marking auth session as requiring reauthentication:', code)\n await this.clearStoredSessionTokens()\n if (!this.user) {\n const cached = await this.storage.get(STORAGE_KEYS.USER_INFO)\n if (cached) {\n try {\n this.user = JSON.parse(cached)\n } catch {\n /* ignore corrupted cache */\n }\n }\n }\n this.token = null\n this.tokenScope = null\n this.nextUserRecoveryAt = 0\n this.updateAuthStatus('reauth_required', code)\n if (options?.broadcast !== false) {\n this.broadcastSessionInvalidated(code)\n }\n this.notify()\n }\n}\n","// Storage utilities for Basic React package\nexport interface BasicStorage {\n get(key: string): Promise<string | null>\n set(key: string, value: string): Promise<void>\n remove(key: string): Promise<void>\n}\n\nexport class LocalStorageAdapter implements BasicStorage {\n async get(key: string): Promise<string | null> {\n return localStorage.getItem(key)\n }\n \n async set(key: string, value: string): Promise<void> {\n localStorage.setItem(key, value)\n }\n \n async remove(key: string): Promise<void> {\n localStorage.removeItem(key)\n }\n}\n\nexport const STORAGE_KEYS = {\n REFRESH_TOKEN: 'basic_refresh_token',\n USER_INFO: 'basic_user_info',\n AUTH_STATE: 'basic_auth_state',\n REDIRECT_URI: 'basic_redirect_uri',\n SERVER_URL: 'basic_server_url',\n PDS_ENDPOINTS: 'basic_pds_endpoints',\n LAST_CONNECT_REPORT: 'basic_last_connect_report',\n DEBUG: 'basic_debug',\n CODE_VERIFIER: 'basic_code_verifier'\n} as const\n\nexport function getCookie(name: string): string {\n let cookieValue = '';\n if (document.cookie && document.cookie !== '') {\n const cookies = document.cookie.split(';');\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i]?.trim();\n if (cookie && cookie.substring(0, name.length + 1) === (name + '=')) {\n cookieValue = decodeURIComponent(cookie.substring(name.length + 1));\n break;\n }\n }\n }\n return cookieValue;\n}\n\nexport function setCookie(name: string, value: string, options?: { secure?: boolean, sameSite?: string, httpOnly?: boolean }): void {\n const opts = {\n secure: true,\n sameSite: 'Strict',\n httpOnly: false,\n ...options\n };\n \n let cookieString = `${name}=${value}`;\n if (opts.secure) cookieString += '; Secure';\n if (opts.sameSite) cookieString += `; SameSite=${opts.sameSite}`;\n if (opts.httpOnly) cookieString += '; HttpOnly';\n \n document.cookie = cookieString;\n}\n\nexport function clearCookie(name: string): void {\n document.cookie = `${name}=; Secure; SameSite=Strict`;\n}\n","const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\n/**\n * Normalize a project_id / client_id to the canonical did:web format\n * before sending it to the PDS.\n *\n * - did:web:... -> passthrough (already canonical)\n * - bare UUID -> did:web:{adminHostname}:projects:{hex}\n * - \"self\" -> passthrough\n */\nexport function normalizeClientId(projectId: string, adminHostname: string = 'api.basic.tech'): string {\n if (!projectId) return projectId\n if (projectId === 'self') return projectId\n if (projectId.startsWith('did:')) return projectId\n\n if (UUID_RE.test(projectId)) {\n const hex = projectId.replace(/-/g, '').toLowerCase()\n return `did:web:${adminHostname}:projects:${hex}`\n }\n\n return projectId\n}\n","export type ResolvedDid = {\n did: string\n handle?: string\n didDocument: Record<string, unknown>\n pdsUrl: string\n authorization_endpoint: string\n token_endpoint: string\n userinfo_endpoint: string\n}\n\n/**\n * Convert a did:web DID to the HTTPS URL where its DID document lives.\n *\n * did:web:pds.basic.id:did:abc123 -> https://pds.basic.id/did/abc123/did.json\n * did:web:example.com -> https://example.com/.well-known/did.json\n */\nexport function resolveDidWebUrl(did: string): string | null {\n if (!did.startsWith('did:web:')) return null\n\n const rest = did.slice(8) // strip 'did:web:'\n if (!rest) return null\n const parts = rest.split(':')\n\n // Decode the hostname (first part, may contain %3A for port)\n const hostname = parts[0]!.replace(/%3A/gi, ':')\n\n if (parts.length === 1) {\n return `https://${hostname}/.well-known/did.json`\n }\n\n const pathParts = parts.slice(1).map(p => decodeURIComponent(p))\n return `https://${hostname}/${pathParts.join('/')}/did.json`\n}\n\n/**\n * Given a DID document, extract PDS URL and discover OAuth endpoints.\n */\nasync function resolveFromDocument(did: string, didDocument: Record<string, unknown>): Promise<ResolvedDid> {\n const services = didDocument.service as Array<{ id: string; type: string; serviceEndpoint: string }> | undefined\n const pdsService = services?.find(\n (s) => s.id === '#basic_pds' || s.id === `${did}#basic_pds`\n )\n if (!pdsService) {\n throw new Error(`DID document has no #basic_pds service entry`)\n }\n const pdsUrl = pdsService.serviceEndpoint.replace(/\\/+$/, '')\n\n const oauthRes = await fetch(`${pdsUrl}/auth/.well-known/openid-configuration`)\n if (!oauthRes.ok) {\n throw new Error(`Failed to fetch OpenID configuration from ${pdsUrl}: ${oauthRes.status}`)\n }\n const oauth = await oauthRes.json()\n\n return {\n did,\n didDocument,\n pdsUrl,\n authorization_endpoint: oauth.authorization_endpoint,\n token_endpoint: oauth.token_endpoint,\n userinfo_endpoint: oauth.userinfo_endpoint,\n }\n}\n\n/**\n * Fetch a DID document by DID, extract the PDS URL, and discover OAuth endpoints.\n */\nexport async function resolveDid(did: string): Promise<ResolvedDid> {\n const url = resolveDidWebUrl(did)\n if (!url) {\n throw new Error(`Unsupported DID method: ${did}`)\n }\n\n const didRes = await fetch(url)\n if (!didRes.ok) {\n throw new Error(`Failed to fetch DID document at ${url}: ${didRes.status}`)\n }\n const didDocument = await didRes.json()\n\n return resolveFromDocument(did, didDocument)\n}\n\n/**\n * Resolve a handle (e.g. \"alice.basic.id\") to a DID and discover PDS + OAuth endpoints.\n *\n * Fetches https://{handle}/.well-known/did.json per the did:web spec.\n */\nexport async function resolveHandle(handle: string): Promise<ResolvedDid> {\n const res = await fetch(`https://${handle}/.well-known/did.json`)\n if (!res.ok) {\n throw new Error(`Handle resolution failed for ${handle}: ${res.status}`)\n }\n const didDocument = await res.json()\n const did = didDocument.id as string\n if (!did) {\n throw new Error(`Handle response has no 'id' field`)\n }\n\n const resolved = await resolveFromDocument(did, didDocument)\n resolved.handle = handle\n return resolved\n}\n","import { BasicStorage } from '../utils/storage'\nimport { log } from '../config'\n\nexport interface VersionInfo {\n version: string\n lastUpdated: number\n}\n\nexport interface Migration {\n fromVersion: string\n toVersion: string\n migrate: (storage: BasicStorage) => Promise<void>\n}\n\nexport class VersionUpdater {\n private storage: BasicStorage\n private currentVersion: string\n private migrations: Migration[]\n private versionKey = 'basic_app_version'\n\n constructor(storage: BasicStorage, currentVersion: string, migrations: Migration[] = []) {\n this.storage = storage\n this.currentVersion = currentVersion\n this.migrations = migrations.sort((a, b) => this.compareVersions(a.fromVersion, b.fromVersion))\n }\n\n /**\n * Check current stored version and run migrations if needed\n * Only compares major.minor versions, ignoring beta/prerelease parts\n * Example: \"0.7.0-beta.1\" and \"0.7.0\" are treated as the same version\n */\n async checkAndUpdate(): Promise<{ updated: boolean; fromVersion?: string; toVersion: string }> {\n const storedVersion = await this.getStoredVersion()\n \n if (!storedVersion) {\n // First time setup\n await this.setStoredVersion(this.currentVersion)\n return { updated: false, toVersion: this.currentVersion }\n }\n\n if (storedVersion === this.currentVersion) {\n return { updated: false, toVersion: this.currentVersion }\n }\n\n // Need to run migrations\n const migrationsToRun = this.getMigrationsToRun(storedVersion, this.currentVersion)\n \n if (migrationsToRun.length === 0) {\n // No migrations needed, just update version\n await this.setStoredVersion(this.currentVersion)\n return { updated: true, fromVersion: storedVersion, toVersion: this.currentVersion }\n }\n\n // Run migrations\n for (const migration of migrationsToRun) {\n try {\n log(`Running migration from ${migration.fromVersion} to ${migration.toVersion}`)\n await migration.migrate(this.storage)\n } catch (error) {\n console.error(`Migration failed from ${migration.fromVersion} to ${migration.toVersion}:`, error)\n throw new Error(`Migration failed: ${error}`)\n }\n }\n\n // Update to current version\n await this.setStoredVersion(this.currentVersion)\n return { updated: true, fromVersion: storedVersion, toVersion: this.currentVersion }\n }\n\n private async getStoredVersion(): Promise<string | null> {\n try {\n const versionData = await this.storage.get(this.versionKey)\n if (!versionData) return null\n \n const versionInfo: VersionInfo = JSON.parse(versionData)\n return versionInfo.version\n } catch (error) {\n console.warn('Failed to get stored version:', error)\n return null\n }\n }\n\n private async setStoredVersion(version: string): Promise<void> {\n const versionInfo: VersionInfo = {\n version,\n lastUpdated: Date.now()\n }\n await this.storage.set(this.versionKey, JSON.stringify(versionInfo))\n }\n\n private getMigrationsToRun(fromVersion: string, toVersion: string): Migration[] {\n return this.migrations.filter(migration => {\n const storedLessThanMigrationTo = this.compareVersions(fromVersion, migration.toVersion) < 0\n const currentGreaterThanOrEqualMigrationTo = this.compareVersions(toVersion, migration.toVersion) >= 0\n const shouldRun = storedLessThanMigrationTo && currentGreaterThanOrEqualMigrationTo\n log(`Migration ${migration.fromVersion} → ${migration.toVersion}: shouldRun=${shouldRun}`)\n return shouldRun\n })\n }\n\n /**\n * Simple semantic version comparison (major.minor only, ignoring beta/prerelease)\n * Returns: -1 if a < b, 0 if a === b, 1 if a > b\n */\n private compareVersions(a: string, b: string): number {\n // Extract major.minor from version strings, ignoring beta/prerelease parts\n const aMajorMinor = this.extractMajorMinor(a)\n const bMajorMinor = this.extractMajorMinor(b)\n \n // Compare major version first\n if (aMajorMinor.major !== bMajorMinor.major) {\n return aMajorMinor.major - bMajorMinor.major\n }\n \n // Then compare minor version\n return aMajorMinor.minor - bMajorMinor.minor\n }\n\n /**\n * Extract major.minor from version string, ignoring beta/prerelease\n * Examples: \"0.7.0-beta.1\" -> {major: 0, minor: 7}\n * \"1.2.3\" -> {major: 1, minor: 2}\n */\n private extractMajorMinor(version: string): { major: number, minor: number } {\n // Remove beta/prerelease parts and split by dots\n const cleanVersion = version.split('-')[0]?.split('+')[0] || version\n const parts = cleanVersion.split('.').map(Number)\n \n return {\n major: parts[0] || 0,\n minor: parts[1] || 0\n }\n }\n\n /**\n * Add a migration to the updater\n */\n addMigration(migration: Migration): void {\n this.migrations.push(migration)\n this.migrations.sort((a, b) => this.compareVersions(a.fromVersion, b.fromVersion))\n }\n}\n\n/**\n * Create a simple version updater instance\n */\nexport function createVersionUpdater(\n storage: BasicStorage, \n currentVersion: string, \n migrations: Migration[] = []\n): VersionUpdater {\n return new VersionUpdater(storage, currentVersion, migrations)\n}\n","import { BasicStorage } from '../utils/storage'\nimport { Migration } from './versionUpdater'\nimport { log } from '../config'\n\nexport const addMigrationTimestamp: Migration = {\n fromVersion: '0.6.0',\n toVersion: '0.7.0',\n async migrate(storage: BasicStorage) {\n log('Running migration 0.6.0 → 0.7.0')\n storage.set('test_migration', 'true')\n }\n}\n\n\n/**\n * Get all available migrations\n */\nexport function getMigrations(): Migration[] {\n return [\n addMigrationTimestamp\n ]\n}\n","// Schema utilities for Basic React package\nimport { validateSchema, compareSchemas } from '@basictech/schema'\nimport { log } from '../config'\n\nexport async function getSchemaStatus(schema: any): Promise<{\n valid: boolean,\n status: string,\n latest: any\n}> {\n const projectId = schema.project_id\n const valid = validateSchema(schema)\n\n if (!valid.valid) {\n console.warn('BasicDB Error: your local schema is invalid. Please fix errors and try again - sync is disabled')\n return { \n valid: false, \n status: 'invalid',\n latest: null\n }\n }\n\n const latestSchema = await fetch(`https://api.basic.tech/project/${projectId}/schema`)\n .then(res => res.json())\n .then(data => data.data[0].schema)\n .catch(err => {\n return { \n valid: false, \n status: 'error',\n latest: null\n }\n })\n\n if (!latestSchema.version) {\n return { \n valid: false, \n status: 'error',\n latest: null\n }\n }\n\n if (latestSchema.version > schema.version) {\n // error_code: schema_behind\n console.warn('BasicDB Error: your local schema version is behind the latest. Found version:', schema.version, 'but expected', latestSchema.version, \" - sync is disabled\")\n return { \n valid: false, \n status: 'behind', \n latest: latestSchema\n }\n } else if (latestSchema.version < schema.version) {\n // error_code: schema_ahead\n console.warn('BasicDB Error: your local schema version is ahead of the latest. Found version:', schema.version, 'but expected', latestSchema.version, \" - sync is disabled\")\n return { \n valid: false, \n status: 'ahead', \n latest: latestSchema\n }\n } else if (latestSchema.version === schema.version) {\n const changes = compareSchemas(schema, latestSchema)\n if (changes.valid) {\n return { \n valid: true,\n status: 'current',\n latest: latestSchema\n }\n } else {\n // error_code: schema_conflict\n console.warn('BasicDB Error: your local schema is conflicting with the latest. Your version:', schema.version, 'does not match origin version', latestSchema.version, \" - sync is disabled\")\n return { \n valid: false, \n status: 'conflict',\n latest: latestSchema\n }\n }\n } else { \n return { \n valid: false, \n status: 'error',\n latest: null\n }\n }\n}\n\nexport async function validateAndCheckSchema(schema: any): Promise<{\n isValid: boolean,\n schemaStatus: { valid: boolean, status?: string, latest?: any },\n errors?: any[]\n}> {\n const valid = validateSchema(schema)\n if (!valid.valid) {\n log('Basic Schema is invalid!', valid.errors)\n console.group('Schema Errors')\n let errorMessage = ''\n valid.errors.forEach((error, index) => {\n log(`${index + 1}:`, error.message, ` - at ${error.instancePath}`)\n errorMessage += `${index + 1}: ${error.message} - at ${error.instancePath}\\n`\n })\n console.groupEnd()\n \n return {\n isValid: false,\n schemaStatus: { valid: false },\n errors: valid.errors\n }\n }\n\n let schemaStatus: { valid: boolean, status?: string, latest?: any } = { valid: false }\n if (schema.version !== 0) {\n schemaStatus = await getSchemaStatus(schema)\n log('schemaStatus', schemaStatus)\n } else {\n schemaStatus = { valid: false, status: 'unpublished' }\n log(\"schema not published - at version 0\")\n }\n\n return {\n isValid: true,\n schemaStatus\n }\n}\n","import { useBasic, BasicProvider } from \"./AuthContext\";\nimport { useLiveQuery as useQuery } from \"dexie-react-hooks\";\n\nexport { useBasic, BasicProvider, useQuery }\nexport { BasicDevToolbar } from \"./dev/BasicDevToolbar\"\nexport type { BasicDevToolbarProps } from \"./dev/BasicDevToolbar\"\n\nexport type { \n AuthConfig, \n BasicStorage, \n LocalStorageAdapter, \n BasicProviderProps,\n BasicContextType,\n BasicSchemaDevInfo,\n AuthResult\n} from \"./AuthContext\"\nexport { DBStatus } from \"./AuthContext\"\n\n// Core DB exports\nexport type { \n DBMode, \n BasicDB, \n Collection, \n RemoteDBConfig,\n GetTokenOptions,\n AuthError\n} from \"./core/db\"\n\nexport { RemoteDB, RemoteCollection, RemoteDBError, NotAuthenticatedError } from \"./core/db\"\n\n// Storage utilities\nexport { STORAGE_KEYS } from \"./utils/storage\"\n\n// DID resolution\nexport { resolveDid, resolveHandle, resolveDidWebUrl } from \"./utils/resolveDid\"\nexport type { ResolvedDid } from \"./utils/resolveDid\""],"mappings":"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","names":["changes","baseRevision","partial","onChangesAccepted","requestId","version","DBStatus","useCallback","useState","Dexie","syncProtocol","Dexie","validateData","version","jsx","jsxs","BasicDevToolbar","useState","useCallback","error"]}
1
+ {"version":3,"sources":["../src/react/context.ts","../src/config.ts","../package.json","../src/utils/network.ts","../src/react/hooks.ts","../src/dev/BasicDevToolbar.tsx","../src/react/BasicProvider.tsx","../src/core/auth/AuthManager.ts","../src/utils/storage.ts","../src/utils/normalizeClientId.ts","../src/utils/resolveDid.ts","../src/core/http/RestClient.ts","../src/core/sync/SyncEngine.ts","../src/core/sync/protocol.ts","../src/core/sync/SyncConnection.ts","../src/core/sync/SyncStore.ts","../src/core/db.ts","../src/utils/schema.ts","../src/updater/versionUpdater.ts","../src/updater/updateMigrations.ts","../src/core/BasicClient.ts","../src/index.ts"],"sourcesContent":["import { createContext } from 'react'\nimport type { BasicClient } from '../core/BasicClient'\n\nexport const BasicClientContext = createContext<BasicClient | null>(null)\n","export const log = (...args: any[]) => {\n try { \n if (localStorage.getItem('basic_debug') === 'true') {\n console.log('[basic]', ...args)\n }\n } catch (e) {\n // silently fail if localStorage is unavailable (SSR)\n }\n}\n","{\n \"name\": \"@basictech/react\",\n \"version\": \"0.9.0-beta.0\",\n \"description\": \"\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n }\n }\n },\n \"files\": [\n \"dist\",\n \"readme.md\",\n \"changelog.md\"\n ],\n \"sideEffects\": false,\n \"private\": false,\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"prepublishOnly\": \"npm run build\",\n \"test\": \"vitest run\"\n },\n \"author\": \"\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"semver\": \"^7.7.2\",\n \"dexie\": \"^4.2.1\",\n \"dexie-react-hooks\": \"^4.2.0\",\n \"jwt-decode\": \"^4.0.0\",\n \"@basictech/schema\": \"^0.7.0\"\n },\n \"devDependencies\": {\n \"@repo/typescript-config\": \"*\",\n \"@types/react\": \"^19.0.0\",\n \"@types/ws\": \"^8.5.0\",\n \"fake-indexeddb\": \"^6.0.0\",\n \"tsup\": \"^8.0.0\",\n \"typescript\": \"^5.0.0\",\n \"vitest\": \"^3.0.0\",\n \"ws\": \"^8.18.0\"\n },\n \"peerDependencies\": {\n \"react\": \"^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0\"\n }\n}\n","// Network utilities for Basic React package\nimport semver from 'semver'\nimport { log } from '../config'\nimport { version as pkgVersion } from '../../package.json'\n\nexport function isDevelopment(debug?: boolean): boolean {\n if (debug === true) return true\n if (typeof process !== 'undefined' && process.env.NODE_ENV === 'development') return true\n if (typeof window === 'undefined' || !window.location) return false\n const host = window.location.hostname\n return (\n host === 'localhost' ||\n host === '127.0.0.1' ||\n host.includes('localhost') ||\n host.includes('127.0.0.1') ||\n host.includes('.local')\n )\n}\n\nfunction normalizeVersion(v: string | null | undefined): string | null {\n if (v == null) return null\n const t = String(v).trim()\n return t.length ? t : null\n}\n\nfunction versionsMatch(a: string, b: string): boolean {\n const na = a.trim()\n const nb = b.trim()\n if (na === nb) return true\n const va = semver.valid(na)\n const vb = semver.valid(nb)\n if (va && vb) return semver.eq(va, vb)\n return false\n}\n\n/** Use npm `beta` dist-tag when the installed version is a semver prerelease whose first id is `beta`. */\nfunction usesBetaDistTag(version: string): boolean {\n const pre = semver.prerelease(version)\n const id = pre?.[0]\n return typeof id === 'string' && id.toLowerCase() === 'beta'\n}\n\ntype NpmInstallMeta = {\n 'dist-tags'?: { latest?: string; beta?: string }\n}\n\nexport async function checkForNewVersion(): Promise<{ \n hasNewVersion: boolean, \n latestVersion: string | null, \n currentVersion: string | null \n}> {\n try {\n const currentVersion = normalizeVersion(pkgVersion)\n if (!currentVersion) {\n return { hasNewVersion: false, latestVersion: null, currentVersion: null }\n }\n\n const response = await fetch('https://registry.npmjs.org/@basictech/react', {\n headers: { Accept: 'application/vnd.npm.install-v1+json' },\n })\n if (!response.ok) {\n throw new Error('Failed to fetch version from npm');\n }\n\n const data = (await response.json()) as NpmInstallMeta\n const distTags = data['dist-tags'] ?? {}\n const rawRegistry =\n usesBetaDistTag(currentVersion)\n ? distTags.beta ?? distTags.latest\n : distTags.latest\n const latestVersion = normalizeVersion(rawRegistry ?? null)\n if (!latestVersion) {\n throw new Error('Missing dist-tags from npm registry')\n }\n\n const same = versionsMatch(currentVersion, latestVersion)\n\n if (!same && isDevelopment()) {\n log('[basic] version check mismatch:', {\n currentVersion,\n registryVersion: latestVersion,\n channel: usesBetaDistTag(currentVersion) ? 'beta' : 'latest',\n })\n }\n\n if (!same) {\n console.warn('[basic] New version available:', latestVersion, `\\nrun \"npm install @basictech/react@${latestVersion}\" to update`);\n }\n if (usesBetaDistTag(currentVersion)) {\n log('thank you for being on basictech/react beta :)')\n }\n \n return {\n hasNewVersion: !same,\n latestVersion,\n currentVersion\n };\n } catch (error) {\n log('Error checking for new version:', error);\n return {\n hasNewVersion: false,\n latestVersion: null, \n currentVersion: null\n };\n }\n}\n\nexport function cleanOAuthParamsFromUrl(): void {\n if (window.location.search.includes('code') || window.location.search.includes('state')) {\n const url = new URL(window.location.href)\n url.searchParams.delete('code')\n url.searchParams.delete('state')\n window.history.replaceState({}, document.title, url.pathname + url.search)\n log('Cleaned OAuth parameters from URL')\n }\n}\n\nexport function getSyncStatus(statusCode: number): string {\n switch (statusCode) {\n case -1:\n return \"ERROR\";\n case 0:\n return \"OFFLINE\";\n case 1:\n return \"CONNECTING\";\n case 2:\n return \"ONLINE\";\n case 3:\n return \"SYNCING\";\n case 4:\n return \"ERROR_WILL_RETRY\";\n default:\n return \"UNKNOWN\";\n }\n}\n","import { useContext, useEffect, useMemo, useState, useSyncExternalStore } from 'react'\nimport { useLiveQuery } from 'dexie-react-hooks'\nimport { BasicClientContext } from './context'\nimport type { BasicClient, BasicClientSnapshot, ShareMountHandle } from '../core/BasicClient'\nimport type { BasicDb } from '../core/db'\nimport type { AuthResult, AuthStatus, GetTokenOptions, User } from '../core/auth/AuthManager'\nimport type { SyncStatus } from '../core/sync/SyncEngine'\nimport type { RejectedRow } from '../core/sync/SyncStore'\nimport type { Share } from '../core/sync/protocol'\n\n/**\n * Reactive live queries against the local database (sync mode).\n * Re-export of dexie-react-hooks' `useLiveQuery` — any read through\n * `db.table(...)` (or its `ref` Dexie table) is observable.\n *\n * ```tsx\n * const todos = useQuery(() => db.table('todos').getAll())\n * ```\n */\nexport const useQuery = useLiveQuery\n\n/** The BasicClient instance from the nearest provider. */\nexport function useBasicClient(): BasicClient {\n const client = useContext(BasicClientContext)\n if (!client) {\n throw new Error('useBasic must be used within a <BasicProvider>')\n }\n return client\n}\n\nfunction useClientSnapshot(client: BasicClient): BasicClientSnapshot {\n return useSyncExternalStore(client.subscribe, client.getSnapshot, client.getSnapshot)\n}\n\nexport interface UseAuthResult {\n /** Auth bootstrap finished (a session may or may not exist). */\n isReady: boolean\n isSignedIn: boolean\n status: AuthStatus\n errorCode: string | null\n user: User | null\n did: string | null\n /** Space-separated scopes granted in the current access token. */\n scope: string | null\n hasScope: (scope: string) => boolean\n missingScopes: () => string[]\n signIn: (redirectUri?: string) => Promise<void>\n signInWithHandle: (handle: string) => Promise<void>\n signInWithCode: (code: string, state?: string) => Promise<AuthResult>\n signOut: () => Promise<void>\n getToken: (options?: GetTokenOptions) => Promise<string>\n getSignInUrl: (redirectUri?: string) => Promise<string>\n}\n\n/** Auth state + actions. */\nexport function useAuth(): UseAuthResult {\n const client = useBasicClient()\n const snapshot = useClientSnapshot(client)\n\n return useMemo(\n () => ({\n isReady: snapshot.isReady,\n isSignedIn: snapshot.isSignedIn,\n status: snapshot.authStatus,\n errorCode: snapshot.authErrorCode,\n user: snapshot.user,\n did: snapshot.did,\n scope: snapshot.scope,\n hasScope: (s: string) => client.auth.hasScope(s),\n missingScopes: () => client.auth.missingScopes(),\n signIn: (redirectUri?: string) => client.auth.signIn(redirectUri),\n signInWithHandle: (handle: string) => client.auth.signInWithHandle(handle),\n signInWithCode: (code: string, state?: string) => client.auth.signInWithCode(code, state),\n signOut: () => client.signOut(),\n getToken: (options?: GetTokenOptions) => client.auth.getToken(options),\n getSignInUrl: (redirectUri?: string) => client.auth.getSignInUrl(redirectUri),\n }),\n [client, snapshot],\n )\n}\n\n/** The database handle (own channel). Offline-first in sync mode. */\nexport function useDb(): BasicDb {\n const client = useBasicClient()\n return client.db\n}\n\nexport interface UseSyncStatusResult {\n /** Engine status: idle | connecting | online | offline | auth_required | revoked | stopped */\n status: SyncStatus\n /** True when the schema is valid + published and sync can run. */\n enabled: boolean\n /** Locally queued ops not yet confirmed by the server. */\n pendingCount: number\n /** Terminally rejected ops (poison-op rule — never re-pushed). */\n listRejected: () => Promise<RejectedRow[]>\n clearRejected: () => Promise<void>\n}\n\n/** Sync engine state: connection status, pending queue depth, rejected ops. */\nexport function useSyncStatus(): UseSyncStatusResult {\n const client = useBasicClient()\n const snapshot = useClientSnapshot(client)\n\n return useMemo(\n () => ({\n status: snapshot.syncStatus,\n enabled: snapshot.syncEnabled,\n pendingCount: snapshot.pendingCount,\n listRejected: () => client.listRejected(),\n clearRejected: () => client.clearRejected(),\n }),\n [client, snapshot],\n )\n}\n\nexport interface UseSharesResult {\n /** Shares this user granted to others (for this app). */\n granted: Share[]\n /** Shares others granted to this user (mountable). */\n received: Share[]\n isLoading: boolean\n error: Error | null\n refresh: () => Promise<void>\n}\n\n/** List shares granted by / received by the signed-in user for this app. */\nexport function useShares(): UseSharesResult {\n const client = useBasicClient()\n const snapshot = useClientSnapshot(client)\n const [state, setState] = useState<{\n granted: Share[]\n received: Share[]\n isLoading: boolean\n error: Error | null\n }>({ granted: [], received: [], isLoading: false, error: null })\n\n const isSignedIn = snapshot.isSignedIn && snapshot.authStatus === 'authenticated'\n\n const refresh = useMemo(\n () => async () => {\n setState((s) => ({ ...s, isLoading: true, error: null }))\n try {\n const { granted, received } = await client.listShares()\n setState({ granted, received, isLoading: false, error: null })\n } catch (err) {\n setState((s) => ({\n ...s,\n isLoading: false,\n error: err instanceof Error ? err : new Error(String(err)),\n }))\n }\n },\n [client],\n )\n\n useEffect(() => {\n if (isSignedIn) void refresh()\n }, [isSignedIn, refresh])\n\n return { ...state, refresh }\n}\n\nexport interface UseShareResult {\n /** Table API over the mounted share's keyspace; null until mounted. */\n db: BasicDb | null\n status: 'mounting' | 'mounted' | 'error' | 'revoked'\n error: Error | null\n}\n\n/**\n * Mount a share (data another user granted to you) and get a db handle for\n * it. The mount lives in its own local keyspace with its own cursor and\n * pending queue — never merged with your own data.\n */\nexport function useShare(shareId: string | null | undefined): UseShareResult {\n const client = useBasicClient()\n const snapshot = useClientSnapshot(client)\n const [handle, setHandle] = useState<ShareMountHandle | null>(null)\n const [error, setError] = useState<Error | null>(null)\n const [revoked, setRevoked] = useState(false)\n\n const canMount =\n !!shareId && snapshot.isSignedIn && snapshot.authStatus !== 'reauth_required'\n\n useEffect(() => {\n if (!canMount || !shareId) return\n let cancelled = false\n setError(null)\n setRevoked(false)\n\n client\n .mountShare(shareId)\n .then((h) => {\n if (!cancelled) setHandle(h)\n })\n .catch((err) => {\n if (!cancelled) setError(err instanceof Error ? err : new Error(String(err)))\n })\n\n const offSubError = client.engine?.on('suberror', ({ sub, code }) => {\n if (sub === `share:${shareId}` && (code === 'SHARE_REVOKED' || code === 'CONNECTION_REVOKED')) {\n setRevoked(true)\n setHandle(null)\n }\n })\n\n return () => {\n cancelled = true\n offSubError?.()\n setHandle(null)\n void client.unmountShare(shareId).catch(() => {})\n }\n }, [client, shareId, canMount])\n\n return {\n db: handle?.db ?? null,\n status: revoked ? 'revoked' : error ? 'error' : handle ? 'mounted' : 'mounting',\n error,\n }\n}\n\nexport interface UseBasicResult extends UseAuthResult {\n db: BasicDb\n sync: UseSyncStatusResult\n /** Local schema vs server status; null if no schema on the provider. */\n devInfo: BasicClientSnapshot['devInfo']\n refreshSchemaStatus: () => Promise<void>\n client: BasicClient\n}\n\n/** Umbrella hook: auth + db + sync status. */\nexport function useBasic(): UseBasicResult {\n const client = useBasicClient()\n const snapshot = useClientSnapshot(client)\n const auth = useAuth()\n const sync = useSyncStatus()\n\n return useMemo(\n () => ({\n ...auth,\n db: client.db,\n sync,\n devInfo: snapshot.devInfo,\n refreshSchemaStatus: () => client.refreshSchemaStatus(),\n client,\n }),\n [client, snapshot, auth, sync],\n )\n}\n","'use client'\n\nimport React, { useCallback, useMemo, useState } from 'react'\nimport { useBasic } from '../react/hooks'\nimport type { BasicSchemaDevInfo } from '../core/BasicClient'\nimport type { SyncStatus } from '../core/sync/SyncEngine'\nimport { version as sdkVersion } from '../../package.json'\nimport { isDevelopment } from '../utils/network'\n\nconst PANEL_PAD_X = 12\n\ntype ChipTone = 'ok' | 'warn' | 'bad' | 'muted'\n\nfunction toneForAuth(isReady: boolean, isSignedIn: boolean): ChipTone {\n if (!isReady) return 'muted'\n if (isSignedIn) return 'ok'\n return 'warn'\n}\n\nfunction toneForSync(mode: string, status: SyncStatus): ChipTone {\n if (mode === 'rest') return 'muted'\n if (status === 'online') return 'ok'\n if (status === 'connecting') return 'warn'\n if (status === 'offline' || status === 'idle' || status === 'stopped') return 'muted'\n return 'bad'\n}\n\nfunction toneForSchema(info: BasicSchemaDevInfo | null): ChipTone {\n if (!info) return 'muted'\n if (info.valid && info.status === 'current') return 'ok'\n if (info.status === 'unpublished') return 'warn'\n if (info.status === 'no_schema') return 'muted'\n return 'bad'\n}\n\nfunction syncStatusLabel(status: SyncStatus): string {\n switch (status) {\n case 'idle':\n return 'Idle'\n case 'connecting':\n return 'Connecting'\n case 'online':\n return 'Connected'\n case 'offline':\n return 'Offline'\n case 'auth_required':\n return 'Reauth required'\n case 'revoked':\n return 'Connection revoked'\n case 'stopped':\n return 'Stopped'\n default:\n return String(status)\n }\n}\n\nfunction chipColor(tone: ChipTone): string {\n switch (tone) {\n case 'ok':\n return '#22c55e'\n case 'warn':\n return '#eab308'\n case 'bad':\n return '#ef4444'\n default:\n return '#71717a'\n }\n}\n\n/** Full value for display in dev panel (wraps; no truncation). */\nfunction displayDid(did: string | null): string {\n return did || '—'\n}\n\nfunction displayUserLine(user: { sub?: string; email?: string; name?: string; picture?: string }): string {\n const parts: string[] = []\n if (user.sub) parts.push(`sub: ${user.sub}`)\n if (user.email) parts.push(`email: ${user.email}`)\n if (user.name) parts.push(`name: ${user.name}`)\n return parts.length ? parts.join(' · ') : '—'\n}\n\nfunction ClipboardIcon() {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n )\n}\n\nexport type BasicDevToolbarProps = {\n /** When false, toolbar does not render. Defaults to true when used standalone. */\n enabled?: boolean\n /** Same as BasicProvider `debug` — when true, toolbar shows even off localhost. */\n debug?: boolean\n}\n\ntype CopyableRowProps = {\n rowKey: string\n label: string\n copyText: string\n copiedKey: string | null\n onCopied: (key: string) => void\n children: React.ReactNode\n}\n\nfunction SectionHeader({ children }: { children: React.ReactNode }) {\n return (\n <div\n style={{\n fontSize: 10,\n fontWeight: 700,\n color: '#e4e4e7',\n letterSpacing: '0.07em',\n textTransform: 'uppercase',\n marginBottom: 8,\n }}\n >\n {children}\n </div>\n )\n}\n\n/** Full-bleed horizontal rule: only above a section (not under the header). */\nfunction SectionRule() {\n const bleed = PANEL_PAD_X\n return (\n <div\n role=\"separator\"\n style={{\n height: 1,\n background: 'rgba(255, 255, 255, 0.055)',\n marginLeft: -bleed,\n marginRight: -bleed,\n marginTop: 14,\n marginBottom: 10,\n width: `calc(100% + ${bleed * 2}px)`,\n }}\n />\n )\n}\n\nfunction CopyableRow({\n rowKey,\n label,\n copyText,\n copiedKey,\n onCopied,\n children,\n}: CopyableRowProps) {\n const [hover, setHover] = useState(false)\n const canCopy = copyText.length > 0\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n if (!canCopy) return\n void navigator.clipboard.writeText(copyText).then(() => onCopied(rowKey))\n },\n [canCopy, copyText, onCopied, rowKey],\n )\n\n return (\n <div\n role={canCopy ? 'button' : undefined}\n tabIndex={canCopy ? 0 : undefined}\n onClick={canCopy ? handleClick : undefined}\n onKeyDown={\n canCopy\n ? (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleClick(e as unknown as React.MouseEvent)\n }\n }\n : undefined\n }\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n display: 'flex',\n gap: 8,\n marginBottom: 6,\n alignItems: 'flex-start',\n borderRadius: 6,\n padding: '4px 6px',\n marginLeft: -6,\n marginRight: -6,\n cursor: canCopy ? 'pointer' : 'default',\n background: hover && canCopy ? 'rgba(255,255,255,0.06)' : 'transparent',\n transition: 'background 0.12s ease',\n }}\n >\n <span style={{ color: '#a1a1aa', minWidth: 88, flexShrink: 0, paddingTop: 2 }}>{label}</span>\n <span\n style={{\n flex: 1,\n minWidth: 0,\n wordBreak: 'break-all',\n paddingTop: 2,\n lineHeight: 1.35,\n }}\n >\n {children}\n </span>\n {canCopy && (\n <span\n style={{\n flexShrink: 0,\n color: copiedKey === rowKey ? '#22c55e' : '#71717a',\n opacity: hover || copiedKey === rowKey ? 1 : 0,\n transition: 'opacity 0.12s ease, color 0.12s ease',\n paddingTop: 2,\n display: 'flex',\n alignItems: 'flex-start',\n }}\n title=\"Copy value\"\n >\n {copiedKey === rowKey ? (\n <span style={{ fontSize: 10 }}>✓</span>\n ) : (\n <ClipboardIcon />\n )}\n </span>\n )}\n </div>\n )\n}\n\n/**\n * Floating dev-only toolbar: auth, DB/sync, and schema status. Requires `BasicProvider` with `debug` or localhost / NODE_ENV=development for visibility unless `enabled` is forced.\n */\nexport function BasicDevToolbar({ enabled = true, debug }: BasicDevToolbarProps) {\n const {\n isReady,\n isSignedIn,\n user,\n did,\n scope,\n missingScopes,\n sync,\n devInfo,\n refreshSchemaStatus,\n client,\n } = useBasic()\n\n const dbMode = client.mode\n const syncStatus = sync.status\n const indexedDbName =\n dbMode === 'sync' && client.projectId ? `basic-sync:${client.projectId}` : null\n\n const [open, setOpen] = useState(false)\n const [refreshing, setRefreshing] = useState(false)\n const [copied, setCopied] = useState(false)\n const [rowCopied, setRowCopied] = useState<string | null>(null)\n\n const show =\n enabled && typeof window !== 'undefined' && isDevelopment(debug)\n\n const authTone = toneForAuth(isReady, isSignedIn)\n const dbTone = toneForSync(dbMode, syncStatus)\n const schemaTone = toneForSchema(devInfo)\n const syncTone: ChipTone = dbTone\n\n const handleRefreshSchema = useCallback(async () => {\n setRefreshing(true)\n try {\n await refreshSchemaStatus()\n } finally {\n setRefreshing(false)\n }\n }, [refreshSchemaStatus])\n\n const missingList = missingScopes()\n\n const debugPayload = useMemo(() => {\n return {\n sdkVersion,\n isReady,\n isSignedIn,\n did: did ?? null,\n user: user\n ? {\n sub: user.sub,\n email: user.email,\n name: user.name,\n picture: user.picture,\n }\n : null,\n scope,\n missingScopes: missingList,\n dbMode,\n syncStatus,\n pendingOps: sync.pendingCount,\n indexedDbName,\n schema: devInfo,\n }\n }, [isReady, isSignedIn, did, user, scope, dbMode, syncStatus, sync.pendingCount, indexedDbName, devInfo, missingList])\n\n const handleCopy = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(JSON.stringify(debugPayload, null, 2))\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n } catch {\n /* ignore */\n }\n }, [debugPayload])\n\n const onRowCopied = useCallback((key: string) => {\n setRowCopied(key)\n setTimeout(() => setRowCopied((k) => (k === key ? null : k)), 1500)\n }, [])\n\n if (!show) return null\n\n const shell: React.CSSProperties = {\n position: 'fixed',\n bottom: 12,\n left: '50%',\n transform: 'translateX(-50%)',\n zIndex: 99999,\n fontFamily:\n 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace',\n fontSize: 11,\n color: '#e4e4e7',\n pointerEvents: 'auto',\n }\n\n const bar: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '8px 12px',\n borderRadius: 999,\n background: 'rgba(24, 24, 27, 0.92)',\n border: '1px solid rgba(63, 63, 70, 0.9)',\n boxShadow: '0 8px 32px rgba(0,0,0,0.35)',\n cursor: 'pointer',\n userSelect: 'none',\n }\n\n /** Fixed box so flex line-height / strut cannot stretch dots when the pill width changes. */\n const dot = (tone: ChipTone) => (\n <span\n style={{\n display: 'block',\n boxSizing: 'border-box',\n width: 6,\n height: 6,\n minWidth: 6,\n minHeight: 6,\n maxWidth: 6,\n maxHeight: 6,\n borderRadius: '50%',\n background: chipColor(tone),\n flexShrink: 0,\n }}\n />\n )\n\n const dotSlot = (title: string, tone: ChipTone) => (\n <span\n title={title}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 6,\n height: 6,\n flexShrink: 0,\n lineHeight: 0,\n }}\n >\n {dot(tone)}\n </span>\n )\n\n const panel: React.CSSProperties = {\n marginBottom: 8,\n maxHeight: '50vh',\n overflow: 'auto',\n padding: PANEL_PAD_X,\n borderRadius: 10,\n background: 'rgba(24, 24, 27, 0.96)',\n border: '1px solid rgba(63, 63, 70, 0.9)',\n boxShadow: '0 8px 32px rgba(0,0,0,0.35)',\n minWidth: 300,\n maxWidth: 'min(560px, calc(100vw - 24px))',\n }\n\n const syncStatusText =\n dbMode === 'rest'\n ? 'REST mode'\n : `${syncStatusLabel(syncStatus)}${sync.pendingCount > 0 ? ` (${sync.pendingCount} pending)` : ''}`\n\n return (\n <div style={shell}>\n {open && (\n <div style={panel}>\n <div style={{ marginBottom: 12 }}>\n <div style={{ fontWeight: 600, fontSize: 12 }}>Basic SDK</div>\n <div style={{ color: '#71717a', fontSize: 10, marginTop: 2 }}>v{sdkVersion}</div>\n </div>\n\n <SectionHeader>Auth</SectionHeader>\n <CopyableRow\n rowKey=\"ready\"\n label=\"Ready\"\n copyText={String(isReady)}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {String(isReady)}\n </CopyableRow>\n <CopyableRow\n rowKey=\"signedIn\"\n label=\"Signed in\"\n copyText={String(isSignedIn)}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {String(isSignedIn)}\n </CopyableRow>\n <CopyableRow\n rowKey=\"did\"\n label=\"DID\"\n copyText={did || ''}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {displayDid(did)}\n </CopyableRow>\n <CopyableRow\n rowKey=\"user\"\n label=\"User\"\n copyText={user ? displayUserLine(user) : ''}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {user ? displayUserLine(user) : '—'}\n </CopyableRow>\n <CopyableRow\n rowKey=\"scopes\"\n label=\"Scopes\"\n copyText={scope || ''}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {scope || '—'}\n </CopyableRow>\n <CopyableRow\n rowKey=\"missingScopes\"\n label=\"Missing scopes\"\n copyText={missingList.length ? missingList.join(', ') : ''}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {missingList.length ? missingList.join(', ') : '—'}\n </CopyableRow>\n\n <SectionRule />\n <SectionHeader>Database</SectionHeader>\n <CopyableRow\n rowKey=\"dbMode\"\n label=\"Mode\"\n copyText={dbMode}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {dbMode}\n </CopyableRow>\n <CopyableRow\n rowKey=\"indexedDb\"\n label=\"IndexedDB\"\n copyText={indexedDbName ?? ''}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {indexedDbName ?? '—'}\n </CopyableRow>\n <CopyableRow\n rowKey=\"syncStatus\"\n label=\"Sync / status\"\n copyText={syncStatusText}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {syncStatusText}\n </CopyableRow>\n\n <SectionRule />\n <SectionHeader>Schema</SectionHeader>\n {devInfo ? (\n <>\n <CopyableRow\n rowKey=\"schemaProject\"\n label=\"Project\"\n copyText={devInfo.projectId ?? ''}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {devInfo.projectId ?? '—'}\n </CopyableRow>\n <CopyableRow\n rowKey=\"schemaLocalVer\"\n label=\"Local version\"\n copyText={\n devInfo.localVersion !== undefined && devInfo.localVersion !== null\n ? String(devInfo.localVersion)\n : ''\n }\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {devInfo.localVersion ?? '—'}\n </CopyableRow>\n <CopyableRow\n rowKey=\"schemaRemote\"\n label=\"Remote check\"\n copyText={devInfo.status}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {devInfo.status}\n </CopyableRow>\n <CopyableRow\n rowKey=\"schemaValid\"\n label=\"Valid\"\n copyText={String(devInfo.valid)}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {String(devInfo.valid)}\n </CopyableRow>\n <CopyableRow\n rowKey=\"schemaChecked\"\n label=\"Checked\"\n copyText={\n devInfo.lastCheckedAt\n ? new Date(devInfo.lastCheckedAt).toISOString()\n : ''\n }\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {devInfo.lastCheckedAt\n ? new Date(devInfo.lastCheckedAt).toLocaleString()\n : '—'}\n </CopyableRow>\n {devInfo.error ? (\n <CopyableRow\n rowKey=\"schemaError\"\n label=\"Error\"\n copyText={devInfo.error}\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n {devInfo.error}\n </CopyableRow>\n ) : null}\n </>\n ) : (\n <CopyableRow\n rowKey=\"schemaStatus\"\n label=\"Status\"\n copyText=\"No schema on provider\"\n copiedKey={rowCopied}\n onCopied={onRowCopied}\n >\n No schema on provider\n </CopyableRow>\n )}\n\n <div style={{ display: 'flex', gap: 8, marginTop: 12, flexWrap: 'wrap' }}>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n void handleRefreshSchema()\n }}\n disabled={refreshing}\n style={{\n padding: '6px 10px',\n borderRadius: 6,\n border: '1px solid #3f3f46',\n background: '#27272a',\n color: '#e4e4e7',\n cursor: refreshing ? 'wait' : 'pointer',\n fontSize: 11,\n fontFamily: 'inherit',\n }}\n >\n {refreshing ? 'Refreshing…' : 'Refresh schema'}\n </button>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n void handleCopy()\n }}\n style={{\n padding: '6px 10px',\n borderRadius: 6,\n border: '1px solid #3f3f46',\n background: '#27272a',\n color: '#e4e4e7',\n cursor: 'pointer',\n fontSize: 11,\n fontFamily: 'inherit',\n }}\n >\n {copied ? 'Copied' : 'Copy debug info'}\n </button>\n </div>\n </div>\n )}\n\n <button\n type=\"button\"\n aria-expanded={open}\n onClick={() => setOpen((o) => !o)}\n style={{\n ...bar,\n border: 'none',\n width: '100%',\n cursor: 'pointer',\n }}\n >\n <span style={{ fontWeight: 600, letterSpacing: 0.02 }}>Basic</span>\n <span\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: 6,\n marginLeft: 8,\n height: 6,\n flexShrink: 0,\n lineHeight: 0,\n }}\n >\n {dotSlot('Auth', authTone)}\n {dotSlot('DB', dbTone)}\n {dotSlot('Sync', syncTone)}\n {dotSlot('Schema', schemaTone)}\n </span>\n <span style={{ color: '#71717a', marginLeft: 4 }}>{open ? '▾' : '▴'}</span>\n </button>\n </div>\n )\n}\n","import React, { Suspense, lazy, useEffect, useRef, useSyncExternalStore } from 'react'\nimport { BasicClientContext } from './context'\nimport { BasicClient, type BasicAuthConfig, type BasicMode } from '../core/BasicClient'\nimport type { BasicStorage } from '../utils/storage'\nimport { isDevelopment, checkForNewVersion } from '../utils/network'\n\nconst BasicDevToolbar = lazy(() =>\n import('../dev/BasicDevToolbar').then((m) => ({ default: m.BasicDevToolbar })),\n)\n\nexport interface BasicProviderProps {\n children: React.ReactNode\n /** The Basic schema object containing project_id and table definitions. */\n schema?: Record<string, unknown>\n /** Project id override; normally taken from `schema.project_id`. */\n project_id?: string\n auth?: BasicAuthConfig\n storage?: BasicStorage\n debug?: boolean\n /**\n * - 'sync' (default): offline-first local replica synced over Sync/2\n * - 'rest': direct REST calls, no local persistence\n */\n mode?: BasicMode\n /** Show the floating dev toolbar (localhost / NODE_ENV=development / debug). */\n devToolbar?: boolean\n /**\n * Render children before auth/db are ready (default false: children render\n * once the client finished bootstrapping, like previous versions).\n */\n renderWhileLoading?: boolean\n}\n\nexport function BasicProvider({\n children,\n schema,\n project_id,\n auth,\n storage,\n debug = false,\n mode = 'sync',\n devToolbar = false,\n renderWhileLoading = false,\n}: BasicProviderProps) {\n const clientRef = useRef<BasicClient | null>(null)\n if (!clientRef.current) {\n clientRef.current = new BasicClient({\n schema: schema as BasicClient['config']['schema'],\n project_id,\n auth,\n storage,\n debug,\n mode,\n })\n }\n const client = clientRef.current\n\n useEffect(() => {\n void client.start()\n void checkForNewVersion()\n return () => client.stop()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const snapshot = useSyncExternalStore(client.subscribe, client.getSnapshot, client.getSnapshot)\n const showDevTools = devToolbar && isDevelopment(debug)\n const ready = snapshot.isReady\n\n return (\n <BasicClientContext.Provider value={client}>\n {showDevTools && (\n <Suspense fallback={null}>\n <BasicDevToolbar debug={debug} />\n </Suspense>\n )}\n {(ready || renderWhileLoading) && children}\n </BasicClientContext.Provider>\n )\n}\n","import { jwtDecode } from 'jwt-decode'\nimport { BasicStorage, STORAGE_KEYS } from '../../utils/storage'\nimport { normalizeClientId } from '../../utils/normalizeClientId'\nimport { resolveHandle } from '../../utils/resolveDid'\nimport { cleanOAuthParamsFromUrl } from '../../utils/network'\nimport { log } from '../../config'\n\nconst DEFINITIVE_TOKEN_ERRORS = new Set([\n 'invalid_grant',\n 'invalid_client',\n 'unauthorized_client',\n])\nconst USER_RECOVERY_RETRY_COOLDOWN_MS = 30_000\nconst SESSION_RECONCILE_THROTTLE_MS = 5_000\n\nclass DefinitiveAuthError extends Error {\n readonly code: string\n\n constructor(code: string) {\n super(`Definitive auth failure: ${code}`)\n this.name = 'DefinitiveAuthError'\n this.code = code\n }\n}\n\n// --- PKCE helpers (RFC 7636) ---\n\nfunction generateCodeVerifier(): string {\n const array = new Uint8Array(32)\n crypto.getRandomValues(array)\n return base64UrlEncode(array)\n}\n\nasync function generateCodeChallenge(\n verifier: string,\n): Promise<{ challenge: string; method: 'S256' | 'plain' }> {\n if (typeof crypto === 'undefined' || !crypto.subtle) {\n log(\n 'crypto.subtle unavailable (non-secure context?) -- falling back to plain PKCE challenge',\n )\n return { challenge: verifier, method: 'plain' }\n }\n const encoder = new TextEncoder()\n const data = encoder.encode(verifier)\n const digest = await crypto.subtle.digest('SHA-256', data)\n return { challenge: base64UrlEncode(new Uint8Array(digest)), method: 'S256' }\n}\n\nfunction base64UrlEncode(buffer: Uint8Array): string {\n let str = ''\n for (let i = 0; i < buffer.length; i++) {\n str += String.fromCharCode(buffer[i]!)\n }\n return btoa(str).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\nexport type Token = {\n access_token: string\n token_type: string\n expires_in: number\n refresh_token: string\n}\n\nexport type User = {\n sub?: string\n name?: string\n email?: string\n picture?: string\n}\n\n/**\n * High-level auth lifecycle state.\n *\n * - `bootstrapping` — SDK is initializing; not yet determined if a session exists.\n * - `authenticated` — User has a valid access token and active session.\n * - `recovering` — A session likely exists (refresh token / cached user) but\n * the SDK hasn't confirmed it yet (e.g. offline, mid-refresh).\n * - `reauth_required` — The session is definitively invalid (revoked, expired\n * refresh token, etc.). The user must sign in again.\n * NOTE: `isSignedIn` remains `true` in this state so the UI\n * can display user info while prompting re-authentication.\n * Use `authStatus === 'reauth_required'` to distinguish\n * this from a healthy signed-in state.\n * - `signed_out` — No session. User is not authenticated.\n *\n * TODO: revisit naming and ergonomics — consider adding a `needsReauth` or\n * `shouldPromptSignIn` convenience getter so consumers don't need to inspect\n * the raw status to decide between \"sign in\" vs \"sign out\" UI.\n */\nexport type AuthStatus =\n | 'bootstrapping'\n | 'authenticated'\n | 'recovering'\n | 'reauth_required'\n | 'signed_out'\n\nexport type AuthResult = {\n success: boolean\n error?: string\n code?: string\n}\n\nexport type GetTokenOptions = {\n forceRefresh?: boolean\n}\n\nexport type PdsEndpoints = {\n pds_url: string\n authorization_endpoint: string\n token_endpoint: string\n userinfo_endpoint: string\n}\n\nexport type AuthManagerConfig = {\n projectId: string | undefined\n scopes: string\n pdsUrl: string\n adminUrl: string\n debug: boolean\n}\n\ntype JwtClaims = {\n sub?: string\n scope?: string\n typ?: string\n exp?: number\n}\n\ntype CurrentSessionInfo = {\n active: boolean\n reauth_required?: boolean\n session_id?: string | null\n client_id?: string\n scope?: string\n account_did?: string\n connection_status?: string\n last_seen_at?: string | null\n error?: string\n}\n\n/**\n * Framework-agnostic auth manager. Holds token state, handles OAuth flow,\n * token refresh (with mutex), and user info fetching.\n *\n * React integration: pass a state-setter as `notify` so the component\n * re-renders whenever auth state changes.\n */\nexport class AuthManager {\n // --- Public state (read by the UI layer) ---\n token: Token | null = null\n user: User | null = null\n isSignedIn: boolean = false\n isAuthReady: boolean = false\n authStatus: AuthStatus = 'bootstrapping'\n authErrorCode: string | null = null\n did: string | null = null\n /** Space-separated scopes granted in the current access token */\n tokenScope: string | null = null\n /** Space-separated scopes originally requested in the auth config */\n requestedScopes: string\n\n readonly config: AuthManagerConfig\n readonly storage: BasicStorage\n\n /** True only during a user-initiated OAuth code exchange (not session restore) */\n private freshSignIn: boolean = false\n\n // --- Private ---\n private notify: () => void\n private refreshPromise: Promise<Token | null> | null = null\n private codeExchangePromise: Promise<Token | null> | null = null\n private pendingRefresh: boolean = false\n private isOnline: boolean =\n typeof navigator !== 'undefined' ? navigator.onLine : true\n private channel: BroadcastChannel | null = null\n private nextUserRecoveryAt: number = 0\n private sessionCheckPromise: Promise<void> | null = null\n private lastSessionCheckAt: number = 0\n\n constructor(\n config: AuthManagerConfig,\n storage: BasicStorage,\n notify: () => void,\n ) {\n this.config = config\n this.storage = storage\n this.notify = notify\n this.requestedScopes = config.scopes\n this.initCrossTabSync()\n }\n\n private initCrossTabSync(): void {\n if (typeof BroadcastChannel === 'undefined') return\n\n try {\n this.channel = new BroadcastChannel('basic-auth')\n this.channel.onmessage = (event) => {\n if (event.data?.type === 'token_refreshed') {\n log('Received token refresh from another tab')\n void this.handleExternalTokenRefresh(event.data)\n }\n if (event.data?.type === 'signed_in') {\n log('Received sign-in from another tab, restoring session')\n void this.restoreStoredSession('cross-tab sign-in')\n }\n if (event.data?.type === 'signed_out') {\n log('Received sign-out from another tab')\n this.resetAuthState('signed_out')\n this.notify()\n }\n if (event.data?.type === 'session_invalidated') {\n log('Received session invalidation from another tab')\n void this.markReauthRequired(event.data.code || 'invalid_grant', {\n broadcast: false,\n })\n }\n }\n } catch {\n log('BroadcastChannel not available for cross-tab sync')\n }\n }\n\n private broadcastTokenRefresh(): void {\n this.channel?.postMessage({\n type: 'token_refreshed',\n accessToken: this.token?.access_token,\n did: this.did,\n tokenScope: this.tokenScope,\n })\n }\n\n private broadcastSignIn(): void {\n this.channel?.postMessage({ type: 'signed_in' })\n }\n\n private broadcastSignOut(): void {\n this.channel?.postMessage({ type: 'signed_out' })\n }\n\n private broadcastSessionInvalidated(code: string): void {\n this.channel?.postMessage({ type: 'session_invalidated', code })\n }\n\n // ------------------------------------------------------------------\n // Public API\n // ------------------------------------------------------------------\n\n /**\n * Bootstrap auth: handle OAuth callback (?code=), restore session\n * from refresh token, or load cached user for offline mode.\n */\n async initialize(): Promise<void> {\n this.updateAuthStatus('bootstrapping')\n await this.storage.set(\n STORAGE_KEYS.DEBUG,\n this.config.debug ? 'true' : 'false',\n )\n\n const storedServerUrl = await this.storage.get(STORAGE_KEYS.SERVER_URL)\n if (storedServerUrl && storedServerUrl !== this.config.pdsUrl) {\n log('PDS URL changed, clearing stored tokens')\n await this.clearStoredAuth()\n }\n await this.storage.set(STORAGE_KEYS.SERVER_URL, this.config.pdsUrl)\n\n try {\n const params = new URLSearchParams(window.location.search)\n\n if (params.has('code')) {\n const code = params.get('code')\n if (!code) {\n this.updateAuthStatus('signed_out')\n this.notify()\n return\n }\n\n const state = await this.storage.get(STORAGE_KEYS.AUTH_STATE)\n const urlState = params.get('state')\n if (!state || state !== urlState) {\n log('error: auth state does not match')\n this.updateAuthStatus('signed_out')\n this.notify()\n await this.storage.remove(STORAGE_KEYS.AUTH_STATE)\n cleanOAuthParamsFromUrl()\n return\n }\n\n await this.storage.remove(STORAGE_KEYS.AUTH_STATE)\n cleanOAuthParamsFromUrl()\n\n this.freshSignIn = true\n this.exchangeToken(code, false).catch((error) => {\n log('Error fetching token:', error)\n this.freshSignIn = false\n void this.restoreCachedUser({\n hasRecoverableSession: !this.isDefinitiveAuthFailure(error),\n })\n })\n } else {\n await this.restoreStoredSession('initialize')\n }\n } catch (e) {\n log('error getting token', e)\n this.updateAuthStatus('signed_out')\n this.notify()\n }\n }\n\n /**\n * Get a valid access token string. Refreshes proactively (5s buffer)\n * or on demand (forceRefresh). Mutex prevents concurrent refreshes.\n */\n async getToken(options?: GetTokenOptions): Promise<string> {\n log('getting token...')\n\n if (!this.token) {\n const refreshToken = await this.getRefreshToken()\n if (refreshToken) {\n log('No token in memory, attempting to refresh from storage')\n\n if (this.refreshPromise) {\n log('Token refresh already in progress, waiting...')\n try {\n const newToken = await this.refreshPromise\n if (newToken?.access_token) {\n return newToken.access_token\n }\n } catch (error) {\n log('In-flight refresh failed:', error)\n throw error\n }\n }\n\n try {\n const newToken = await this.exchangeToken(refreshToken, true)\n if (newToken?.access_token) {\n return newToken.access_token\n }\n } catch (error) {\n log('Failed to refresh token from storage:', error)\n if (this.isNetworkError(error)) {\n throw new Error(\n 'Network offline - authentication will be retried when online',\n )\n }\n if (!this.isDefinitiveAuthFailure(error)) {\n throw error\n }\n throw new Error('Authentication expired. Please sign in again.')\n }\n }\n log('no token found')\n throw new Error('no token found')\n }\n\n const decoded = jwtDecode<JwtClaims>(this.token.access_token)\n const expirationBuffer = 5\n const isExpired =\n decoded.exp && decoded.exp < Date.now() / 1000 + expirationBuffer\n const shouldRefresh = isExpired || options?.forceRefresh === true\n\n if (shouldRefresh) {\n log(\n options?.forceRefresh\n ? 'force refreshing token...'\n : 'token is expired - refreshing ...',\n )\n\n if (this.refreshPromise) {\n log('Token refresh already in progress, waiting...')\n try {\n const newToken = await this.refreshPromise\n if (!newToken?.access_token)\n throw new Error('Token refresh returned empty access token')\n return newToken.access_token\n } catch (error) {\n log('In-flight refresh failed:', error)\n if (this.isNetworkError(error)) {\n log('Network issue - using expired token until network is restored')\n return this.token.access_token\n }\n throw error\n }\n }\n\n const refreshToken = await this.getRefreshToken()\n if (refreshToken) {\n try {\n const newToken = await this.exchangeToken(refreshToken, true)\n if (!newToken?.access_token)\n throw new Error('Token refresh returned empty access token')\n return newToken.access_token\n } catch (error) {\n log('Failed to refresh expired token:', error)\n if (this.isNetworkError(error)) {\n log('Network issue - using expired token until network is restored')\n return this.token.access_token\n }\n if (!this.isDefinitiveAuthFailure(error)) {\n throw error\n }\n throw new Error('Authentication expired. Please sign in again.')\n }\n } else {\n throw new Error('no refresh token available')\n }\n }\n\n if (!this.token.access_token)\n throw new Error('Token exists but access_token is empty')\n return this.token.access_token\n }\n\n async getSignInUrl(\n redirectUri?: string,\n endpoints?: PdsEndpoints,\n ): Promise<string> {\n log('getting sign in link...')\n\n if (!this.config.projectId) {\n throw new Error('Project ID is required to generate sign-in link')\n }\n\n const pdsEndpoints = endpoints || this.defaultPdsEndpoints()\n await this.storage.set(\n STORAGE_KEYS.PDS_ENDPOINTS,\n JSON.stringify(pdsEndpoints),\n )\n\n const randomState = base64UrlEncode(\n crypto.getRandomValues(new Uint8Array(16)),\n )\n await this.storage.set(STORAGE_KEYS.AUTH_STATE, randomState)\n\n const redirectUrl = redirectUri || window.location.href\n if (\n !redirectUrl ||\n (!redirectUrl.startsWith('http://') &&\n !redirectUrl.startsWith('https://'))\n ) {\n throw new Error('Invalid redirect URI provided')\n }\n\n await this.storage.set(STORAGE_KEYS.REDIRECT_URI, redirectUrl)\n log('Stored redirect_uri for token exchange:', redirectUrl)\n\n // PKCE: generate code_verifier and code_challenge (RFC 7636)\n const codeVerifier = generateCodeVerifier()\n const { challenge: codeChallenge, method: challengeMethod } =\n await generateCodeChallenge(codeVerifier)\n await this.storage.set(STORAGE_KEYS.CODE_VERIFIER, codeVerifier)\n\n let baseUrl = pdsEndpoints.authorization_endpoint\n baseUrl += `?client_id=${encodeURIComponent(normalizeClientId(this.config.projectId, this.adminHostname))}`\n baseUrl += `&redirect_uri=${encodeURIComponent(redirectUrl)}`\n baseUrl += `&response_type=code`\n baseUrl += `&scope=${encodeURIComponent(this.config.scopes)}`\n baseUrl += `&state=${randomState}`\n baseUrl += `&code_challenge=${encodeURIComponent(codeChallenge)}`\n baseUrl += `&code_challenge_method=${challengeMethod}`\n\n log('Generated sign-in link successfully with scopes:', this.config.scopes)\n return baseUrl\n }\n\n async signIn(redirectUri?: string): Promise<void> {\n log('signing in...')\n\n if (!this.config.projectId) {\n log('Error: project_id is required for sign-in')\n throw new Error('Project ID is required for authentication')\n }\n\n const signInLink = await this.getSignInUrl(redirectUri)\n log('Generated sign-in link:', signInLink)\n\n try {\n new URL(signInLink)\n } catch {\n log('Error: Invalid sign-in link generated')\n throw new Error('Failed to generate valid sign-in URL')\n }\n\n window.location.href = signInLink\n }\n\n async signInWithHandle(handle: string): Promise<void> {\n log('signing in with handle:', handle)\n\n if (!this.config.projectId) {\n throw new Error('Project ID is required for authentication')\n }\n\n const resolved = await resolveHandle(handle)\n log('Resolved handle to PDS:', resolved.pdsUrl)\n\n const endpoints: PdsEndpoints = {\n pds_url: resolved.pdsUrl,\n authorization_endpoint: resolved.authorization_endpoint,\n token_endpoint: resolved.token_endpoint,\n userinfo_endpoint: resolved.userinfo_endpoint,\n }\n\n const signInLink = await this.getSignInUrl(undefined, endpoints)\n log('Generated federated sign-in link:', signInLink)\n\n try {\n new URL(signInLink)\n } catch {\n throw new Error('Failed to generate valid sign-in URL')\n }\n\n window.location.href = signInLink\n }\n\n async signInWithCode(code: string, state?: string): Promise<AuthResult> {\n try {\n log('signInWithCode called with code:', code)\n\n if (!code || typeof code !== 'string') {\n return { success: false, error: 'Invalid authorization code' }\n }\n\n if (state) {\n const storedState = await this.storage.get(STORAGE_KEYS.AUTH_STATE)\n if (storedState && storedState !== state) {\n log('State parameter mismatch:', {\n provided: state,\n stored: storedState,\n })\n return { success: false, error: 'State parameter mismatch' }\n }\n }\n\n await this.storage.remove(STORAGE_KEYS.AUTH_STATE)\n cleanOAuthParamsFromUrl()\n\n this.freshSignIn = true\n const token = await this.exchangeToken(code, false)\n if (token) {\n log('signInWithCode successful')\n return { success: true }\n } else {\n return { success: false, error: 'Failed to exchange code for token' }\n }\n } catch (error) {\n log('signInWithCode error:', error)\n this.freshSignIn = false\n return {\n success: false,\n error: (error as Error).message || 'Authentication failed',\n }\n }\n }\n\n /**\n * Sign out: revoke the session server-side (`POST /auth/logout`, best\n * effort), then clear auth state and storage. Does NOT handle sync/DB\n * cleanup — the client layer wraps this to add sync teardown.\n */\n async signOut(): Promise<void> {\n log('signing out!')\n\n await this.revokeSessionOnServer()\n\n this.resetAuthState('signed_out')\n\n await this.storage.remove(STORAGE_KEYS.AUTH_STATE)\n await this.storage.remove(STORAGE_KEYS.LAST_CONNECT_REPORT)\n await this.clearStoredAuth()\n\n this.broadcastSignOut()\n this.notify()\n }\n\n /**\n * Best-effort server-side revocation of the current device/session and\n * its refresh chain (Step 2 auth: logout is finally server-side).\n * Never blocks or fails the local sign-out.\n */\n private async revokeSessionOnServer(): Promise<void> {\n try {\n let accessToken: string | null = null\n try {\n accessToken = await this.getToken()\n } catch {\n accessToken = this.token?.access_token ?? null\n }\n if (!accessToken) return\n const endpoints = await this.getActivePdsEndpoints()\n await fetch(`${endpoints.pds_url}/auth/logout`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${accessToken}` },\n })\n log('Server-side logout succeeded')\n } catch (error) {\n log('Server-side logout failed (non-blocking):', error)\n }\n }\n\n async reconcileSession(\n reason: string = 'manual',\n options?: { forceRefresh?: boolean; throttleMs?: number },\n ): Promise<void> {\n if (this.authStatus === 'signed_out' || this.authStatus === 'reauth_required') {\n return\n }\n\n if (!this.isOnline) {\n this.updateAuthStatus('recovering', this.authErrorCode)\n this.notify()\n return\n }\n\n const throttleMs = options?.throttleMs ?? SESSION_RECONCILE_THROTTLE_MS\n const forceRefresh = options?.forceRefresh === true\n const now = Date.now()\n\n if (this.sessionCheckPromise) {\n return this.sessionCheckPromise\n }\n\n if (!forceRefresh && now - this.lastSessionCheckAt < throttleMs) {\n return\n }\n\n this.lastSessionCheckAt = now\n\n let sessionCheck: Promise<void> | null = null\n sessionCheck = (async () => {\n try {\n const accessToken = await this.getToken(\n forceRefresh ? { forceRefresh: true } : undefined,\n )\n const currentSession = await this.fetchCurrentSession(accessToken)\n if (currentSession?.active) {\n this.updateAuthStatus('authenticated')\n this.notify()\n if (!this.user) {\n await this.recoverMissingUserProfile(reason, accessToken)\n }\n }\n } catch (error) {\n log(`Session reconciliation failed on ${reason}:`, error)\n if (this.isDefinitiveAuthFailure(error)) {\n return\n }\n if (this.isNetworkError(error)) {\n this.updateAuthStatus('recovering', this.authErrorCode)\n this.notify()\n }\n } finally {\n if (this.sessionCheckPromise === sessionCheck) {\n this.sessionCheckPromise = null\n }\n }\n })()\n\n this.sessionCheckPromise = sessionCheck\n return sessionCheck\n }\n\n hasScope(scope: string): boolean {\n if (!this.tokenScope) return false\n return this.tokenScope\n .split(/[\\s,]+/)\n .filter(Boolean)\n .includes(scope)\n }\n\n /**\n * Returns scopes that were requested but not granted in the current token.\n * Useful after login or when a 403 is returned.\n */\n missingScopes(): string[] {\n const requested = this.requestedScopes.split(/[\\s,]+/).filter(Boolean)\n if (!this.tokenScope) return requested\n const granted = new Set(this.tokenScope.split(/[\\s,]+/).filter(Boolean))\n return requested.filter((s) => !granted.has(s))\n }\n\n /**\n * Register online/offline and visibility handlers that retry pending\n * refreshes and proactively refresh tokens when the app resumes from\n * background (critical for PWAs and mobile browsers where timers are\n * frozen while backgrounded).\n * Returns a cleanup function for useEffect teardown.\n */\n setupNetworkListeners(): () => void {\n const handleOnline = async () => {\n log('Network came back online')\n this.isOnline = true\n if (this.pendingRefresh) {\n log('Retrying pending token refresh')\n this.pendingRefresh = false\n const refreshToken = await this.getRefreshToken()\n if (refreshToken) {\n this.exchangeToken(refreshToken, true).catch((error) => {\n log('Retry refresh failed:', error)\n })\n }\n }\n if (this.isSignedIn) {\n this.reconcileSession('online event', {\n forceRefresh: true,\n throttleMs: 0,\n }).catch((error) => {\n log('Session reconciliation on online failed:', error)\n })\n } else if (this.user) {\n await this.restoreStoredSession('online restore')\n }\n }\n\n const handleOffline = () => {\n log('Network went offline')\n this.isOnline = false\n }\n\n const handleVisibilityChange = () => {\n if (document.visibilityState === 'visible' && this.isSignedIn) {\n log('App became visible - reconciling auth session')\n this.reconcileSession('visibility resume', {\n forceRefresh: true,\n }).catch((err) => {\n log('Session reconciliation on visibility resume failed:', err)\n })\n }\n }\n\n window.addEventListener('online', handleOnline)\n window.addEventListener('offline', handleOffline)\n\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', handleVisibilityChange)\n }\n\n return () => {\n window.removeEventListener('online', handleOnline)\n window.removeEventListener('offline', handleOffline)\n if (typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', handleVisibilityChange)\n }\n }\n }\n\n // ------------------------------------------------------------------\n // Private\n // ------------------------------------------------------------------\n\n private get adminHostname(): string {\n try {\n return new URL(this.config.adminUrl).hostname\n } catch {\n return 'api.basic.tech'\n }\n }\n\n private defaultPdsEndpoints(): PdsEndpoints {\n return {\n pds_url: this.config.pdsUrl,\n authorization_endpoint: `${this.config.pdsUrl}/auth/authorize`,\n token_endpoint: `${this.config.pdsUrl}/auth/token`,\n userinfo_endpoint: `${this.config.pdsUrl}/auth/userinfo`,\n }\n }\n\n private async getActivePdsEndpoints(): Promise<PdsEndpoints> {\n const stored = await this.storage.get(STORAGE_KEYS.PDS_ENDPOINTS)\n if (stored) {\n try {\n return JSON.parse(stored) as PdsEndpoints\n } catch {\n /* fall through */\n }\n }\n return this.defaultPdsEndpoints()\n }\n\n private async reportConnection(accessToken: string): Promise<void> {\n if (!this.config.projectId || !this.config.adminUrl) return\n const lastReport = await this.storage.get(STORAGE_KEYS.LAST_CONNECT_REPORT)\n if (lastReport) {\n const elapsed = Date.now() - parseInt(lastReport, 10)\n if (elapsed < 24 * 60 * 60 * 1000) return\n }\n try {\n await fetch(\n `${this.config.adminUrl}/project/${this.config.projectId}/user/connect`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token: accessToken }),\n },\n )\n await this.storage.set(\n STORAGE_KEYS.LAST_CONNECT_REPORT,\n Date.now().toString(),\n )\n log('Reported connection to admin server')\n } catch (err) {\n log('Failed to report connection (non-blocking):', err)\n }\n }\n\n /**\n * After a new token is stored, decode JWT claims and fetch user info.\n */\n private async processNewToken(): Promise<void> {\n if (!this.token) {\n this.updateAuthStatus('signed_out')\n this.notify()\n return\n }\n\n try {\n const decoded = jwtDecode<JwtClaims>(this.token.access_token)\n this.applyTokenClaims(decoded)\n this.updateAuthStatus('authenticated')\n this.notify()\n this.broadcastSessionUpdate()\n await this.fetchUser(this.token.access_token)\n } catch (error) {\n log('Error processing token:', error)\n this.updateAuthStatus('recovering')\n this.notify()\n }\n }\n\n private async restoreCachedUser(options?: {\n hasRecoverableSession: boolean\n }): Promise<void> {\n const cached = await this.storage.get(STORAGE_KEYS.USER_INFO)\n if (cached && options?.hasRecoverableSession) {\n try {\n this.user = JSON.parse(cached)\n log('Restored cached user info for recoverable session')\n } catch {\n /* corrupted cache, ignore */\n }\n } else {\n this.user = null\n }\n this.updateAuthStatus(\n options?.hasRecoverableSession ? 'recovering' : 'signed_out',\n )\n this.notify()\n }\n\n private async fetchUser(accessToken: string): Promise<void> {\n log('fetching user')\n try {\n const endpoints = await this.getActivePdsEndpoints()\n const response = await fetch(endpoints.userinfo_endpoint, {\n method: 'GET',\n headers: { Authorization: `Bearer ${accessToken}` },\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch user info: ${response.status}`)\n }\n\n const user = await response.json()\n\n if (user.error) {\n log('error fetching user', user.error)\n throw new Error(`User info error: ${user.error}`)\n }\n\n if (this.token?.refresh_token) {\n await this.storage.set(\n STORAGE_KEYS.REFRESH_TOKEN,\n this.token.refresh_token,\n )\n }\n\n await this.storage.set(STORAGE_KEYS.USER_INFO, JSON.stringify(user))\n log('Cached user info in storage')\n\n this.user = user\n if (this.authStatus !== 'reauth_required') {\n this.updateAuthStatus('authenticated')\n }\n this.nextUserRecoveryAt = 0\n this.notify()\n } catch (error) {\n log('Failed to fetch user info:', error)\n await this.handleUserFetchFailure()\n }\n }\n\n /**\n * Exchange an auth code or refresh token for an access token.\n * Handles mutex (one in-flight refresh), token validation, and\n * triggers processNewToken on success.\n */\n private async exchangeToken(\n codeOrRefreshToken: string,\n isRefreshToken: boolean,\n ): Promise<Token | null> {\n if (!codeOrRefreshToken || codeOrRefreshToken.trim() === '') {\n const errorMsg = isRefreshToken\n ? 'Refresh token is empty or undefined'\n : 'Authorization code is empty or undefined'\n log('Error:', errorMsg)\n throw new Error(errorMsg)\n }\n\n if (isRefreshToken && this.refreshPromise) {\n log('Reusing in-flight refresh token request')\n return this.refreshPromise\n }\n\n if (!isRefreshToken && this.codeExchangePromise) {\n log('Reusing in-flight code exchange request')\n return this.codeExchangePromise\n }\n\n const tokenPromise = (async (): Promise<Token | null> => {\n try {\n if (!this.isOnline) {\n log('Network is offline, marking refresh as pending')\n this.pendingRefresh = true\n throw new Error(\n 'Network offline - refresh will be retried when online',\n )\n }\n\n const endpoints = await this.getActivePdsEndpoints()\n let requestBody: any\n\n if (isRefreshToken) {\n requestBody = {\n grant_type: 'refresh_token',\n refresh_token: codeOrRefreshToken,\n }\n if (this.config.projectId) {\n requestBody.client_id = normalizeClientId(\n this.config.projectId,\n this.adminHostname,\n )\n }\n } else {\n requestBody = {\n grant_type: 'authorization_code',\n code: codeOrRefreshToken,\n }\n\n const storedRedirectUri = await this.storage.get(\n STORAGE_KEYS.REDIRECT_URI,\n )\n if (storedRedirectUri) {\n requestBody.redirect_uri = storedRedirectUri\n log('Including redirect_uri in token exchange:', storedRedirectUri)\n } else {\n log('Warning: No redirect_uri found in storage for token exchange')\n }\n\n // PKCE: include code_verifier from the authorization request\n const codeVerifier = await this.storage.get(\n STORAGE_KEYS.CODE_VERIFIER,\n )\n if (codeVerifier) {\n requestBody.code_verifier = codeVerifier\n }\n\n if (this.config.projectId) {\n requestBody.client_id = normalizeClientId(\n this.config.projectId,\n this.adminHostname,\n )\n }\n }\n\n log('Token exchange request body:', {\n ...requestBody,\n ...(isRefreshToken\n ? { refresh_token: '[REDACTED]' }\n : { code: '[REDACTED]' }),\n ...(requestBody.code_verifier ? { code_verifier: '[REDACTED]' } : {}),\n })\n\n const response = await fetch(endpoints.token_endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestBody),\n }).catch((error) => {\n log('Network error fetching token:', error)\n if (!this.isOnline) {\n this.pendingRefresh = true\n throw new Error(\n 'Network offline - refresh will be retried when online',\n )\n }\n throw new Error('Network error during token refresh')\n })\n\n // Rate limited (Step 2 auth adds @fastify/rate-limit on /auth/token).\n // Transient by definition: keep the refresh token, retry later.\n if (response.status === 429) {\n log('Token endpoint rate limited (429) - will retry later')\n this.pendingRefresh = true\n throw new Error(\n 'Token endpoint rate limited - refresh will be retried',\n )\n }\n\n const token = await response.json().catch(() => {\n throw new Error(\n `Token endpoint returned invalid JSON (status ${response.status})`,\n )\n })\n\n if (token.access_token) {\n try {\n const decoded = jwtDecode<{ typ?: string }>(token.access_token)\n if (decoded.typ === 'refresh') {\n log('Error: received refresh token as access token')\n throw new Error(\n 'Invalid token: received refresh token instead of access token',\n )\n }\n } catch (decodeError) {\n if ((decodeError as Error).message.includes('Invalid token')) {\n throw decodeError\n }\n log(\n 'Warning: could not decode access token for type check:',\n decodeError,\n )\n }\n }\n\n if (token.error) {\n log('error fetching token', token.error)\n\n if (\n typeof token.error === 'string' &&\n (token.error.includes('network') || token.error.includes('timeout'))\n ) {\n this.pendingRefresh = true\n throw new Error(\n 'Network issue - refresh will be retried when online',\n )\n }\n\n // Only clear stored auth on definitive OAuth rejection.\n // Transient server errors (500, 503, etc.) should NOT wipe\n // the refresh token — the user can retry later.\n if (this.isDefinitiveTokenErrorCode(token.error)) {\n await this.markReauthRequired(token.error)\n throw new DefinitiveAuthError(token.error)\n }\n throw new Error(`Token refresh failed: ${token.error}`)\n } else {\n if (!token.access_token) {\n throw new Error('Token response missing access token')\n }\n this.token = token\n this.pendingRefresh = false\n\n if (token.refresh_token) {\n await this.storage.set(\n STORAGE_KEYS.REFRESH_TOKEN,\n token.refresh_token,\n )\n log('Updated refresh token in storage')\n }\n\n if (!isRefreshToken) {\n await this.storage.remove(STORAGE_KEYS.REDIRECT_URI)\n await this.storage.remove(STORAGE_KEYS.CODE_VERIFIER)\n log(\n 'Cleaned up redirect_uri and code_verifier from storage after successful exchange',\n )\n }\n\n this.reportConnection(token.access_token).catch(() => {})\n\n await this.processNewToken()\n }\n\n return token\n } catch (error) {\n log('Token refresh error:', error)\n if (this.isDefinitiveAuthFailure(error)) {\n log('Preserving cleared auth state after definitive token rejection')\n } else if (this.isNetworkError(error)) {\n log('Recoverable network auth failure - preserving session state')\n } else {\n log('Recoverable auth failure - preserving session state')\n }\n\n throw error\n }\n })()\n\n if (isRefreshToken) {\n this.refreshPromise = tokenPromise\n tokenPromise.finally(() => {\n if (this.refreshPromise === tokenPromise) {\n this.refreshPromise = null\n log('Cleared refresh promise reference')\n }\n })\n } else {\n this.codeExchangePromise = tokenPromise\n tokenPromise.finally(() => {\n if (this.codeExchangePromise === tokenPromise) {\n this.codeExchangePromise = null\n log('Cleared code exchange promise reference')\n }\n })\n }\n\n return tokenPromise\n }\n\n private resetAuthState(status: AuthStatus = 'signed_out'): void {\n this.user = status === 'reauth_required' ? this.user : null\n this.token = null\n if (status !== 'reauth_required') {\n this.did = null\n }\n this.tokenScope = null\n this.nextUserRecoveryAt = 0\n this.updateAuthStatus(status)\n }\n\n private async clearStoredAuth(): Promise<void> {\n await this.storage.remove(STORAGE_KEYS.REFRESH_TOKEN)\n await this.storage.remove(STORAGE_KEYS.USER_INFO)\n await this.storage.remove(STORAGE_KEYS.REDIRECT_URI)\n await this.storage.remove(STORAGE_KEYS.CODE_VERIFIER)\n await this.storage.remove(STORAGE_KEYS.SERVER_URL)\n await this.storage.remove(STORAGE_KEYS.PDS_ENDPOINTS)\n }\n\n private isNetworkError(error: unknown): boolean {\n if (error instanceof TypeError) return true\n if (error instanceof Error) {\n return (\n error.message.includes('offline') ||\n error.message.includes('Network') ||\n // 429 on the token endpoint: transient, keep the session alive\n error.message.includes('rate limited')\n )\n }\n return false\n }\n\n private async getRefreshToken(): Promise<string | null> {\n const storedRefreshToken = await this.storage.get(\n STORAGE_KEYS.REFRESH_TOKEN,\n )\n if (storedRefreshToken) {\n log('Using refresh token from storage')\n if (this.token && this.token.refresh_token !== storedRefreshToken) {\n this.token = { ...this.token, refresh_token: storedRefreshToken }\n }\n return storedRefreshToken\n }\n\n const memoryRefreshToken = this.token?.refresh_token ?? null\n if (memoryRefreshToken) {\n log('Using refresh token from memory fallback')\n } else {\n log('No refresh token available in storage or memory')\n }\n return memoryRefreshToken\n }\n\n private async syncRefreshTokenFromStorage(): Promise<void> {\n const storedRefreshToken = await this.storage.get(\n STORAGE_KEYS.REFRESH_TOKEN,\n )\n if (\n storedRefreshToken &&\n this.token &&\n this.token.refresh_token !== storedRefreshToken\n ) {\n this.token = { ...this.token, refresh_token: storedRefreshToken }\n log('Synced refresh token from shared storage into memory')\n }\n }\n\n private applyTokenClaims(decoded: JwtClaims): void {\n this.did = decoded.sub || null\n this.tokenScope = decoded.scope || null\n }\n\n private broadcastSessionUpdate(): void {\n if (this.freshSignIn) {\n this.freshSignIn = false\n this.broadcastSignIn()\n } else {\n this.broadcastTokenRefresh()\n }\n }\n\n private async handleUserFetchFailure(): Promise<void> {\n if (this.isCompatibleUser(this.user)) {\n log('Preserving existing user after userinfo failure')\n } else if (this.user) {\n log('Discarding stale in-memory user after userinfo failure')\n this.user = null\n }\n\n if (!this.user) {\n const cached = await this.storage.get(STORAGE_KEYS.USER_INFO)\n if (cached) {\n try {\n const parsed = JSON.parse(cached) as User\n if (this.isCompatibleUser(parsed)) {\n this.user = parsed\n log('Recovered cached user after userinfo failure')\n } else {\n log('Cached user did not match the active session')\n }\n } catch (error) {\n log('Failed to parse cached user after userinfo failure:', error)\n }\n }\n }\n\n if (!this.user) {\n log('No compatible cached user available after userinfo failure')\n this.nextUserRecoveryAt = Date.now() + USER_RECOVERY_RETRY_COOLDOWN_MS\n } else {\n this.nextUserRecoveryAt = 0\n }\n\n if (this.authStatus === 'bootstrapping') {\n this.updateAuthStatus(this.token ? 'authenticated' : 'recovering')\n }\n this.notify()\n }\n\n private isCompatibleUser(user: User | null): boolean {\n if (!user) return false\n if (!this.did) return true\n return user.sub === this.did\n }\n\n private async recoverMissingUserProfile(\n reason: string,\n accessToken?: string,\n ): Promise<void> {\n if (!this.isSignedIn || this.user) return\n const now = Date.now()\n if (this.nextUserRecoveryAt > now) {\n log(\n `Skipping user profile recovery on ${reason} until ${new Date(this.nextUserRecoveryAt).toISOString()}`,\n )\n return\n }\n log(`Attempting user profile recovery on ${reason}`)\n const token = accessToken ?? (await this.getToken())\n if (this.user) return\n await this.fetchUser(token)\n }\n\n private isDefinitiveTokenErrorCode(code: unknown): code is string {\n return typeof code === 'string' && DEFINITIVE_TOKEN_ERRORS.has(code)\n }\n\n private isDefinitiveAuthFailure(error: unknown): boolean {\n return error instanceof DefinitiveAuthError\n }\n\n /**\n * Centralised auth status setter. Derives `isSignedIn` and `isAuthReady`\n * from the status so they stay consistent.\n *\n * `isSignedIn` is intentionally `true` during `reauth_required` so the\n * UI layer can still display user info while prompting re-authentication.\n * Consumers should check `authStatus` (or a future convenience getter)\n * when they need to distinguish \"healthy session\" from \"needs re-auth\".\n */\n private updateAuthStatus(\n status: AuthStatus,\n errorCode: string | null = null,\n ): void {\n this.authStatus = status\n this.authErrorCode = errorCode\n this.isSignedIn =\n status === 'authenticated' ||\n status === 'recovering' ||\n status === 'reauth_required'\n this.isAuthReady = status !== 'bootstrapping'\n }\n\n private async clearStoredSessionTokens(): Promise<void> {\n await this.storage.remove(STORAGE_KEYS.REFRESH_TOKEN)\n await this.storage.remove(STORAGE_KEYS.REDIRECT_URI)\n await this.storage.remove(STORAGE_KEYS.CODE_VERIFIER)\n }\n\n private async restoreStoredSession(reason: string): Promise<void> {\n const refreshToken = await this.getRefreshToken()\n if (!refreshToken) {\n log(`No stored refresh token available during ${reason}`)\n await this.restoreCachedUser({ hasRecoverableSession: false })\n return\n }\n\n log(`Restoring stored session during ${reason}`)\n await this.restoreCachedUser({ hasRecoverableSession: true })\n\n if (!this.isOnline) {\n return\n }\n\n this.exchangeToken(refreshToken, true).catch(async (error) => {\n log(`Stored session refresh failed during ${reason}:`, error)\n if (this.isDefinitiveAuthFailure(error)) {\n return\n }\n await this.restoreCachedUser({ hasRecoverableSession: true })\n })\n }\n\n private async handleExternalTokenRefresh(data: {\n accessToken?: string\n did?: string\n tokenScope?: string\n }): Promise<void> {\n await this.syncRefreshTokenFromStorage()\n const refreshToken = await this.getRefreshToken()\n if (data.accessToken && refreshToken) {\n try {\n const decoded = jwtDecode<JwtClaims>(data.accessToken)\n const expiresIn =\n decoded.exp != null\n ? Math.max(0, decoded.exp - Math.floor(Date.now() / 1000))\n : 0\n this.token = {\n access_token: data.accessToken,\n token_type: 'Bearer',\n expires_in: expiresIn,\n refresh_token: refreshToken,\n }\n this.applyTokenClaims(decoded)\n } catch (error) {\n log('Failed to decode token refreshed by another tab:', error)\n this.token = {\n access_token: data.accessToken,\n token_type: 'Bearer',\n expires_in: 0,\n refresh_token: refreshToken,\n }\n }\n if (this.authStatus !== 'reauth_required') {\n this.updateAuthStatus('authenticated')\n }\n } else if (refreshToken) {\n await this.restoreCachedUser({ hasRecoverableSession: true })\n }\n\n if (data.did) this.did = data.did\n if (data.tokenScope) this.tokenScope = data.tokenScope\n this.notify()\n }\n\n private async fetchCurrentSession(\n accessToken: string,\n ): Promise<CurrentSessionInfo | null> {\n const endpoints = await this.getActivePdsEndpoints()\n const response = await fetch(`${endpoints.pds_url}/auth/session`, {\n method: 'GET',\n headers: { Authorization: `Bearer ${accessToken}` },\n })\n const data = (await response.json().catch(() => ({}))) as CurrentSessionInfo\n\n if (response.status === 401 && data.reauth_required) {\n await this.markReauthRequired(data.error || 'invalid_session')\n throw new DefinitiveAuthError(data.error || 'invalid_session')\n }\n\n if (!response.ok) {\n throw new Error(`Failed to reconcile session: ${response.status}`)\n }\n\n return data\n }\n\n private async markReauthRequired(\n code: string,\n options?: { broadcast?: boolean },\n ): Promise<void> {\n log('Marking auth session as requiring reauthentication:', code)\n await this.clearStoredSessionTokens()\n if (!this.user) {\n const cached = await this.storage.get(STORAGE_KEYS.USER_INFO)\n if (cached) {\n try {\n this.user = JSON.parse(cached)\n } catch {\n /* ignore corrupted cache */\n }\n }\n }\n this.token = null\n this.tokenScope = null\n this.nextUserRecoveryAt = 0\n this.updateAuthStatus('reauth_required', code)\n if (options?.broadcast !== false) {\n this.broadcastSessionInvalidated(code)\n }\n this.notify()\n }\n}\n","// Storage utilities for Basic React package\nexport interface BasicStorage {\n get(key: string): Promise<string | null>\n set(key: string, value: string): Promise<void>\n remove(key: string): Promise<void>\n}\n\nexport class LocalStorageAdapter implements BasicStorage {\n async get(key: string): Promise<string | null> {\n return localStorage.getItem(key)\n }\n \n async set(key: string, value: string): Promise<void> {\n localStorage.setItem(key, value)\n }\n \n async remove(key: string): Promise<void> {\n localStorage.removeItem(key)\n }\n}\n\nexport const STORAGE_KEYS = {\n REFRESH_TOKEN: 'basic_refresh_token',\n USER_INFO: 'basic_user_info',\n AUTH_STATE: 'basic_auth_state',\n REDIRECT_URI: 'basic_redirect_uri',\n SERVER_URL: 'basic_server_url',\n PDS_ENDPOINTS: 'basic_pds_endpoints',\n LAST_CONNECT_REPORT: 'basic_last_connect_report',\n DEBUG: 'basic_debug',\n CODE_VERIFIER: 'basic_code_verifier'\n} as const\n\nexport function getCookie(name: string): string {\n let cookieValue = '';\n if (document.cookie && document.cookie !== '') {\n const cookies = document.cookie.split(';');\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i]?.trim();\n if (cookie && cookie.substring(0, name.length + 1) === (name + '=')) {\n cookieValue = decodeURIComponent(cookie.substring(name.length + 1));\n break;\n }\n }\n }\n return cookieValue;\n}\n\nexport function setCookie(name: string, value: string, options?: { secure?: boolean, sameSite?: string, httpOnly?: boolean }): void {\n const opts = {\n secure: true,\n sameSite: 'Strict',\n httpOnly: false,\n ...options\n };\n \n let cookieString = `${name}=${value}`;\n if (opts.secure) cookieString += '; Secure';\n if (opts.sameSite) cookieString += `; SameSite=${opts.sameSite}`;\n if (opts.httpOnly) cookieString += '; HttpOnly';\n \n document.cookie = cookieString;\n}\n\nexport function clearCookie(name: string): void {\n document.cookie = `${name}=; Secure; SameSite=Strict`;\n}\n","const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\n/**\n * Normalize a project_id / client_id to the canonical did:web format\n * before sending it to the PDS.\n *\n * - did:web:... -> passthrough (already canonical)\n * - bare UUID -> did:web:{adminHostname}:projects:{hex}\n * - \"self\" -> passthrough\n */\nexport function normalizeClientId(projectId: string, adminHostname: string = 'api.basic.tech'): string {\n if (!projectId) return projectId\n if (projectId === 'self') return projectId\n if (projectId.startsWith('did:')) return projectId\n\n if (UUID_RE.test(projectId)) {\n const hex = projectId.replace(/-/g, '').toLowerCase()\n return `did:web:${adminHostname}:projects:${hex}`\n }\n\n return projectId\n}\n","export type ResolvedDid = {\n did: string\n handle?: string\n didDocument: Record<string, unknown>\n pdsUrl: string\n authorization_endpoint: string\n token_endpoint: string\n userinfo_endpoint: string\n}\n\n/**\n * Convert a did:web DID to the HTTPS URL where its DID document lives.\n *\n * did:web:pds.basic.id:did:abc123 -> https://pds.basic.id/did/abc123/did.json\n * did:web:example.com -> https://example.com/.well-known/did.json\n */\nexport function resolveDidWebUrl(did: string): string | null {\n if (!did.startsWith('did:web:')) return null\n\n const rest = did.slice(8) // strip 'did:web:'\n if (!rest) return null\n const parts = rest.split(':')\n\n // Decode the hostname (first part, may contain %3A for port)\n const hostname = parts[0]!.replace(/%3A/gi, ':')\n\n if (parts.length === 1) {\n return `https://${hostname}/.well-known/did.json`\n }\n\n const pathParts = parts.slice(1).map(p => decodeURIComponent(p))\n return `https://${hostname}/${pathParts.join('/')}/did.json`\n}\n\n/**\n * Given a DID document, extract PDS URL and discover OAuth endpoints.\n */\nasync function resolveFromDocument(did: string, didDocument: Record<string, unknown>): Promise<ResolvedDid> {\n const services = didDocument.service as Array<{ id: string; type: string; serviceEndpoint: string }> | undefined\n const pdsService = services?.find(\n (s) => s.id === '#basic_pds' || s.id === `${did}#basic_pds`\n )\n if (!pdsService) {\n throw new Error(`DID document has no #basic_pds service entry`)\n }\n const pdsUrl = pdsService.serviceEndpoint.replace(/\\/+$/, '')\n\n const oauthRes = await fetch(`${pdsUrl}/auth/.well-known/openid-configuration`)\n if (!oauthRes.ok) {\n throw new Error(`Failed to fetch OpenID configuration from ${pdsUrl}: ${oauthRes.status}`)\n }\n const oauth = await oauthRes.json()\n\n return {\n did,\n didDocument,\n pdsUrl,\n authorization_endpoint: oauth.authorization_endpoint,\n token_endpoint: oauth.token_endpoint,\n userinfo_endpoint: oauth.userinfo_endpoint,\n }\n}\n\n/**\n * Fetch a DID document by DID, extract the PDS URL, and discover OAuth endpoints.\n */\nexport async function resolveDid(did: string): Promise<ResolvedDid> {\n const url = resolveDidWebUrl(did)\n if (!url) {\n throw new Error(`Unsupported DID method: ${did}`)\n }\n\n const didRes = await fetch(url)\n if (!didRes.ok) {\n throw new Error(`Failed to fetch DID document at ${url}: ${didRes.status}`)\n }\n const didDocument = await didRes.json()\n\n return resolveFromDocument(did, didDocument)\n}\n\n/**\n * Resolve a handle (e.g. \"alice.basic.id\") to a DID and discover PDS + OAuth endpoints.\n *\n * Fetches https://{handle}/.well-known/did.json per the did:web spec.\n */\nexport async function resolveHandle(handle: string): Promise<ResolvedDid> {\n const res = await fetch(`https://${handle}/.well-known/did.json`)\n if (!res.ok) {\n throw new Error(`Handle resolution failed for ${handle}: ${res.status}`)\n }\n const didDocument = await res.json()\n const did = didDocument.id as string\n if (!did) {\n throw new Error(`Handle response has no 'id' field`)\n }\n\n const resolved = await resolveFromDocument(did, didDocument)\n resolved.handle = handle\n return resolved\n}\n","/**\n * RestClient — the REST v2 surface under `/account/:project_id/db/...`.\n *\n * Used by the sync engine for bootstrap (`snapshot`) and pull sync\n * (`changes`), by the shares API, and by the REST-mode table API (CRUD on\n * materialized state). All writes go through the same server-side sync\n * engine as WebSocket pushes — one write path.\n */\nimport type { ChangesPage, Share, Snapshot } from '../sync/protocol'\n\nexport interface GetTokenOptions {\n forceRefresh?: boolean\n}\n\nexport class RestError extends Error {\n readonly status: number\n readonly code?: string\n readonly response?: unknown\n\n constructor(message: string, status: number, code?: string, response?: unknown) {\n super(message)\n this.name = 'RestError'\n this.status = status\n this.code = code\n this.response = response\n }\n}\n\nexport class NotAuthenticatedError extends Error {\n constructor(message: string = 'Not authenticated') {\n super(message)\n this.name = 'NotAuthenticatedError'\n }\n}\n\nexport interface RestClientOptions {\n /** PDS base URL, e.g. `https://pds.basic.id` */\n baseUrl: string\n /** Project id (UUID or DID) — used in `/account/:project_id/...` paths. */\n projectId: string\n getToken: (options?: GetTokenOptions) => Promise<string>\n log?: (...args: unknown[]) => void\n}\n\n/** A record as returned by REST reads: flattened `{ id, ...fields }`. */\nexport type RestRecord = { id: string } & Record<string, unknown>\n\nexport class RestClient {\n private readonly opts: RestClientOptions\n\n constructor(opts: RestClientOptions) {\n this.opts = { ...opts, baseUrl: opts.baseUrl.replace(/\\/$/, '') }\n }\n\n get projectId(): string {\n return this.opts.projectId\n }\n\n // -------------------------------------------------------------------\n // Sync surface\n // -------------------------------------------------------------------\n\n /** `GET /account/:project_id/db` — tables, enforced schema version, channel head. */\n async getDbInfo(): Promise<{\n tables: string[]\n schema_version: string | number | null\n channel: { id: string; head_seq: number; compacted_to_seq: number }\n }> {\n const res = await this.request<{ data: never }>('GET', `${this.dbPath}`)\n return res.data\n }\n\n /** Bootstrap snapshot (SPEC §5). `share` bootstraps a mount; `table` filters. */\n async getSnapshot(options?: { share?: string; table?: string }): Promise<Snapshot> {\n const query = new URLSearchParams()\n if (options?.share) query.set('share', options.share)\n if (options?.table) query.set('table', options.table)\n const qs = query.toString()\n const res = await this.request<{ data: Snapshot }>(\n 'GET',\n `${this.dbPath}/snapshot${qs ? `?${qs}` : ''}`,\n )\n return res.data\n }\n\n /** Pull ordered ops after a cursor — the non-WebSocket sync path. */\n async getChanges(options: {\n cursor: number\n limit?: number\n share?: string\n table?: string\n }): Promise<ChangesPage> {\n const query = new URLSearchParams({ cursor: String(options.cursor) })\n if (options.limit) query.set('limit', String(options.limit))\n if (options.share) query.set('share', options.share)\n if (options.table) query.set('table', options.table)\n const res = await this.request<{ data: ChangesPage }>(\n 'GET',\n `${this.dbPath}/changes?${query.toString()}`,\n )\n return res.data\n }\n\n // -------------------------------------------------------------------\n // Shares (multiplayer v1)\n // -------------------------------------------------------------------\n\n /**\n * Shares granted by and received by the caller. App tokens see only\n * shares involving their own app (the ones they can mount).\n */\n async listShares(): Promise<{ granted: Share[]; received: Share[] }> {\n const res = await this.request<{ data: { granted: Share[]; received: Share[] } }>(\n 'GET',\n '/account/shares',\n )\n return res.data\n }\n\n // -------------------------------------------------------------------\n // CRUD on materialized state (REST-mode table API)\n // -------------------------------------------------------------------\n\n async list(table: string, query?: Record<string, string>): Promise<RestRecord[]> {\n const qs = query ? `?${new URLSearchParams(query).toString()}` : ''\n const res = await this.request<{ data: RestRecord[] }>(\n 'GET',\n `${this.dbPath}/${encodeURIComponent(table)}${qs}`,\n )\n return res.data ?? []\n }\n\n async getRecord(table: string, id: string): Promise<RestRecord | null> {\n try {\n const res = await this.request<{ data: RestRecord }>(\n 'GET',\n `${this.dbPath}/${encodeURIComponent(table)}/${encodeURIComponent(id)}`,\n )\n return res.data ?? null\n } catch (err) {\n if (err instanceof RestError && err.status === 404) return null\n throw err\n }\n }\n\n /** `POST` — server mints the record id. */\n async createRecord(table: string, value: Record<string, unknown>): Promise<RestRecord> {\n const res = await this.request<{ data: RestRecord }>(\n 'POST',\n `${this.dbPath}/${encodeURIComponent(table)}`,\n { value },\n )\n return res.data\n }\n\n /** `PUT` — full replace. REST semantics: 404 for missing records. */\n async putRecord(\n table: string,\n id: string,\n value: Record<string, unknown>,\n ): Promise<RestRecord | null> {\n try {\n const res = await this.request<{ data: RestRecord }>(\n 'PUT',\n `${this.dbPath}/${encodeURIComponent(table)}/${encodeURIComponent(id)}`,\n { value },\n )\n return res.data ?? null\n } catch (err) {\n if (err instanceof RestError && err.status === 404) return null\n throw err\n }\n }\n\n /** `PATCH` — partial merge. 404 → null. */\n async patchRecord(\n table: string,\n id: string,\n value: Record<string, unknown>,\n ): Promise<RestRecord | null> {\n try {\n const res = await this.request<{ data: RestRecord }>(\n 'PATCH',\n `${this.dbPath}/${encodeURIComponent(table)}/${encodeURIComponent(id)}`,\n { value },\n )\n return res.data ?? null\n } catch (err) {\n if (err instanceof RestError && err.status === 404) return null\n throw err\n }\n }\n\n /** `DELETE`. Returns false when the record did not exist. */\n async deleteRecord(table: string, id: string): Promise<boolean> {\n try {\n await this.request(\n 'DELETE',\n `${this.dbPath}/${encodeURIComponent(table)}/${encodeURIComponent(id)}`,\n )\n return true\n } catch (err) {\n if (err instanceof RestError && err.status === 404) return false\n throw err\n }\n }\n\n // -------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------\n\n private get dbPath(): string {\n return `/account/${encodeURIComponent(this.opts.projectId)}/db`\n }\n\n /** Authenticated request; retries once with a force-refreshed token on 401. */\n private async request<R>(\n method: string,\n path: string,\n body?: unknown,\n isRetry: boolean = false,\n ): Promise<R> {\n let token: string\n try {\n token = await this.opts.getToken(isRetry ? { forceRefresh: true } : undefined)\n } catch (err) {\n throw new NotAuthenticatedError(\n err instanceof Error ? err.message : 'could not get access token',\n )\n }\n\n const url = `${this.opts.baseUrl}${path}`\n this.opts.log?.('[rest]', method, url)\n\n const headers: Record<string, string> = { Authorization: `Bearer ${token}` }\n if (body !== undefined) headers['Content-Type'] = 'application/json'\n\n const response = await fetch(url, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n })\n\n const responseData = (await response.json().catch(() => ({}))) as Record<string, unknown>\n\n if (!response.ok) {\n if (response.status === 401 && !isRetry) {\n this.opts.log?.('[rest] 401 — refreshing token and retrying once')\n return this.request<R>(method, path, body, true)\n }\n const code = typeof responseData.error === 'string' ? responseData.error : undefined\n const message =\n (typeof responseData.message === 'string' && responseData.message) ||\n code ||\n `request failed: ${response.status}`\n throw new RestError(message, response.status, code, responseData)\n }\n\n return responseData as R\n }\n}\n","/**\n * SyncEngine — the six client responsibilities (SYNC_V2.md §15) per\n * subscription, over one multiplexed connection:\n *\n * 1. Store — local materialized records (SyncStore `_server` + views)\n * 2. Pending — locally created ops not yet confirmed (persisted)\n * 3. Cursor — last seq seen, persisted\n * 4. Ordered apply — incoming ops applied in seq order\n * 5. Dedupe/confirm — own ops confirmed by op_id echo; skips re-applies\n * 6. Rebase — app-visible view = serverState + pending, recomputed on change\n *\n * Plus the §9 error contract: terminal op errors are poison (rejected store,\n * never re-pushed); SNAPSHOT_REQUIRED/RESET_REQUIRED re-bootstraps keeping\n * pending ops; SHARE_REVOKED drops the mount; retryables back off.\n *\n * Subscriptions: `own` (the token's app channel) plus one per mounted share.\n * Each has its own SyncStore keyspace — mounted data is never merged with\n * own-channel data (§12.3).\n */\nimport { validateData } from '@basictech/schema'\nimport { SyncConnection, type ConnectionStatus } from './SyncConnection'\nimport { SyncStore, type PendingRow, type RejectedRow } from './SyncStore'\nimport {\n DEFAULT_LIMITS,\n isRebootstrapError,\n isTerminalOpError,\n mintOpId,\n type ErrorMsg,\n type LoggedOp,\n type OpEnvelope,\n type OpType,\n type OpsMsg,\n type PushedMsg,\n type ServerMsg,\n type Snapshot,\n type SubscribedMsg,\n type SyncLimits,\n type WelcomeMsg,\n} from './protocol'\n\nexport type SyncStatus =\n | 'idle'\n | 'connecting'\n | 'online'\n | 'offline'\n | 'auth_required'\n | 'revoked'\n | 'stopped'\n\nexport const OWN_SUB = 'own'\n\nexport function shareSubKey(shareId: string): string {\n return `share:${shareId}`\n}\n\ninterface PendingEntry {\n op: OpEnvelope\n sent: boolean\n ackedSeq?: number\n}\n\ntype SubStatus = 'initializing' | 'live' | 'revoked' | 'error'\n\nclass BoundedSet {\n private set = new Set<string>()\n private order: string[] = []\n constructor(private readonly cap: number = 2048) {}\n has(value: string): boolean {\n return this.set.has(value)\n }\n add(value: string): void {\n if (this.set.has(value)) return\n this.set.add(value)\n this.order.push(value)\n if (this.order.length > this.cap) {\n const evicted = this.order.shift()\n if (evicted !== undefined) this.set.delete(evicted)\n }\n }\n clear(): void {\n this.set.clear()\n this.order = []\n }\n}\n\nexport interface SubscriptionState {\n key: string\n shareId: string | null\n store: SyncStore\n cursor: number\n pending: PendingEntry[]\n /** Bound on the current socket (subscribed ack received). */\n active: boolean\n bootstrapped: boolean\n status: SubStatus\n revokedCode?: string\n appliedOpIds: BoundedSet\n /** Serializes ops/pushed/bootstrap handling per subscription. */\n chain: Promise<void>\n schemaVersion: string | number | null\n}\n\nexport interface SyncEngineEvents {\n status: SyncStatus\n /** Records changed in a subscription's view (local write or server ops). */\n change: { sub: string; tables: string[] }\n rejected: { sub: string; rejection: RejectedRow }\n /** Sub-level protocol errors (share revoked, re-bootstrapping, ...). */\n suberror: { sub: string; code: string; message?: string }\n /** Connection-level revocation — the app connection is gone. */\n revoked: { code: string; message?: string }\n}\n\nexport interface EngineSchema {\n project_id?: string\n version?: number\n tables: Record<\n string,\n { fields: Record<string, { type: string; required?: boolean; indexed?: boolean }> }\n >\n}\n\nexport interface SyncEngineOptions {\n projectId: string\n schema: EngineSchema\n /** e.g. `wss://pds.basic.id/sync/` */\n wsUrl: string\n getToken: (options?: { forceRefresh?: boolean }) => Promise<string>\n /** Bootstrap fetch (REST snapshot). Injected so the engine stays transport-thin. */\n fetchSnapshot: (options?: { share?: string }) => Promise<Snapshot>\n /** Prefix for IndexedDB database names. Default `basic-sync`. */\n dbNamePrefix?: string\n /**\n * App name included in `subscribe` messages. Production derives the channel\n * from the token and ignores this; the sync-playground conformance server\n * requires it. Leave unset against production.\n */\n appName?: string\n WebSocketImpl?: typeof WebSocket\n heartbeatMs?: number\n /** Validate writes locally before queueing (mirrors server). Default true. */\n validateWrites?: boolean\n log?: (...args: unknown[]) => void\n}\n\nconst RETRY_FLUSH_DELAY_MS = 1_200\n\nexport class SyncEngine {\n readonly projectId: string\n readonly schema: EngineSchema\n\n private readonly opts: SyncEngineOptions\n private readonly connection: SyncConnection\n private readonly subs = new Map<string, SubscriptionState>()\n private limits: SyncLimits = { ...DEFAULT_LIMITS }\n private actor: string | null = null\n\n private started = false\n private revokedInfo: { code: string; message?: string } | null = null\n private connectionStatus: ConnectionStatus = 'idle'\n private _status: SyncStatus = 'idle'\n\n private listeners = new Map<keyof SyncEngineEvents, Set<(data: never) => void>>()\n private timers = new Set<ReturnType<typeof setTimeout>>()\n\n constructor(opts: SyncEngineOptions) {\n this.opts = opts\n this.projectId = opts.projectId\n this.schema = opts.schema\n this.connection = new SyncConnection({\n wsUrl: opts.wsUrl,\n getToken: opts.getToken,\n WebSocketImpl: opts.WebSocketImpl,\n heartbeatMs: opts.heartbeatMs,\n onWelcome: (msg) => this.handleWelcome(msg),\n onMessage: (msg) => this.handleMessage(msg),\n onStatus: (status) => this.handleConnectionStatus(status),\n log: opts.log,\n })\n }\n\n // -------------------------------------------------------------------\n // Events\n // -------------------------------------------------------------------\n\n on<E extends keyof SyncEngineEvents>(\n event: E,\n fn: (data: SyncEngineEvents[E]) => void,\n ): () => void {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set())\n const set = this.listeners.get(event)! as Set<(data: SyncEngineEvents[E]) => void>\n set.add(fn)\n return () => set.delete(fn)\n }\n\n private emit<E extends keyof SyncEngineEvents>(event: E, data: SyncEngineEvents[E]): void {\n const set = this.listeners.get(event) as Set<(data: SyncEngineEvents[E]) => void> | undefined\n if (!set) return\n for (const fn of set) {\n try {\n fn(data)\n } catch (err) {\n this.log('listener error:', err)\n }\n }\n }\n\n // -------------------------------------------------------------------\n // Public state\n // -------------------------------------------------------------------\n\n get status(): SyncStatus {\n return this._status\n }\n\n get syncLimits(): SyncLimits {\n return { ...this.limits }\n }\n\n get serverActor(): string | null {\n return this.actor\n }\n\n getSubscription(key: string): SubscriptionState | undefined {\n return this.subs.get(key)\n }\n\n get own(): SubscriptionState | undefined {\n return this.subs.get(OWN_SUB)\n }\n\n get pendingCount(): number {\n let n = 0\n for (const sub of this.subs.values()) n += sub.pending.length\n return n\n }\n\n async listRejected(subKey: string = OWN_SUB): Promise<RejectedRow[]> {\n const sub = this.subs.get(subKey)\n if (!sub) return []\n return sub.store.listRejected()\n }\n\n async clearRejected(subKey: string = OWN_SUB): Promise<void> {\n await this.subs.get(subKey)?.store.clearRejected()\n }\n\n // -------------------------------------------------------------------\n // Lifecycle\n // -------------------------------------------------------------------\n\n /** Open the own-channel keyspace and connect. Idempotent. */\n async start(): Promise<void> {\n if (this.started) {\n // a fresh start after auth recovery clears the revoked latch\n if (this.connectionStatus === 'auth_failed' || this._status === 'auth_required') {\n this.connection.start()\n }\n return\n }\n this.started = true\n this.revokedInfo = null\n\n if (!this.subs.has(OWN_SUB)) {\n const sub = await this.openSub(OWN_SUB, null)\n this.subs.set(OWN_SUB, sub)\n }\n this.connection.start()\n this.recomputeStatus()\n }\n\n /** Close the socket and stores; local data is kept. */\n stop(): void {\n this.started = false\n this.connection.stop()\n for (const t of this.timers) clearTimeout(t)\n this.timers.clear()\n for (const sub of this.subs.values()) {\n sub.active = false\n sub.store.close()\n }\n this.subs.clear()\n this.recomputeStatus()\n }\n\n /**\n * Stop and delete every local database for this project (sign-out).\n * Best-effort discovery of mount keyspaces from previous sessions.\n */\n async destroyLocal(): Promise<void> {\n const open = [...this.subs.values()]\n this.stop()\n for (const sub of open) {\n try {\n await sub.store.destroy()\n } catch (err) {\n this.log('failed deleting local db:', err)\n }\n }\n // stale mount keyspaces from previous sessions\n try {\n const idb = (globalThis as { indexedDB?: IDBFactory }).indexedDB\n if (idb && typeof idb.databases === 'function') {\n const prefix = `${this.dbPrefix}:${this.projectId}`\n const dbs = await idb.databases()\n for (const info of dbs) {\n if (info.name && info.name.startsWith(prefix)) {\n await new Promise<void>((resolve) => {\n const req = idb.deleteDatabase(info.name!)\n req.onsuccess = req.onerror = req.onblocked = () => resolve()\n })\n }\n }\n }\n } catch {\n /* best effort */\n }\n }\n\n // -------------------------------------------------------------------\n // Shares (mounts)\n // -------------------------------------------------------------------\n\n /**\n * Mount a share: separate keyspace `(project, share)` with its own cursor\n * and pending queue. Bootstraps + subscribes when the socket is online.\n */\n async mountShare(shareId: string): Promise<SubscriptionState> {\n const key = shareSubKey(shareId)\n const existing = this.subs.get(key)\n if (existing) return existing\n\n const sub = await this.openSub(key, shareId)\n this.subs.set(key, sub)\n if (this.connection.isOnline) {\n this.enqueue(sub, () => this.activateSub(sub))\n }\n return sub\n }\n\n /** Unsubscribe a mount. Local cache is kept unless `purge` is set. */\n async unmountShare(shareId: string, options?: { purge?: boolean }): Promise<void> {\n const key = shareSubKey(shareId)\n const sub = this.subs.get(key)\n if (!sub) return\n if (sub.active) {\n this.connection.send({ type: 'unsubscribe', sub: key })\n }\n this.subs.delete(key)\n if (options?.purge) {\n await sub.store.destroy()\n } else {\n sub.store.close()\n }\n }\n\n // -------------------------------------------------------------------\n // Writes (responsibility 2 + 6: pending queue + optimistic rebase)\n // -------------------------------------------------------------------\n\n /**\n * Queue a local op, apply it optimistically, and push when online.\n * Returns the resulting view record (null when deleted).\n * Throws on local validation failure (fail fast — the server would\n * terminally reject it anyway).\n */\n async apply(\n subKey: string,\n partial: { type: OpType; table: string; record_id: string; data?: Record<string, unknown> },\n ): Promise<Record<string, unknown> | null> {\n const sub = this.subs.get(subKey)\n if (!sub) throw new Error(`unknown subscription '${subKey}' — is the engine started?`)\n if (!sub.store.hasTable(partial.table)) {\n throw new Error(`table \"${partial.table}\" not found in schema`)\n }\n\n if (this.opts.validateWrites !== false && partial.type !== 'delete') {\n // mirror the server: put validates required fields, patch does not\n const result = validateData(\n this.schema as Parameters<typeof validateData>[0],\n partial.table,\n partial.data ?? {},\n partial.type === 'put',\n )\n if (!result.valid) {\n throw new Error(result.message || 'data validation failed')\n }\n }\n\n const op: OpEnvelope = {\n op_id: mintOpId(),\n type: partial.type,\n table: partial.table,\n record_id: partial.record_id,\n ...(partial.type !== 'delete' ? { data: partial.data ?? {} } : {}),\n base_seq: Math.max(sub.cursor, 0),\n }\n\n const bytes = JSON.stringify(op).length\n if (bytes > this.limits.max_op_bytes) {\n throw new Error(\n `op exceeds max_op_bytes (${bytes} > ${this.limits.max_op_bytes}) — PAYLOAD_TOO_LARGE`,\n )\n }\n\n let view: Record<string, unknown> | null = null\n await this.enqueue(sub, async () => {\n view = await sub.store.addPending(op)\n sub.pending.push({ op, sent: false })\n })\n this.emit('change', { sub: sub.key, tables: [op.table] })\n this.flush(sub)\n return view\n }\n\n // -------------------------------------------------------------------\n // Connection handling\n // -------------------------------------------------------------------\n\n private handleConnectionStatus(status: ConnectionStatus): void {\n this.connectionStatus = status\n if (status === 'offline' || status === 'connecting' || status === 'auth_failed') {\n for (const sub of this.subs.values()) {\n sub.active = false\n // re-push everything after reconnect; idempotent by op_id\n for (const p of sub.pending) {\n p.sent = false\n p.ackedSeq = undefined\n }\n }\n }\n this.recomputeStatus()\n }\n\n private handleWelcome(msg: WelcomeMsg): void {\n this.actor = msg.actor\n if (msg.limits) this.limits = { ...this.limits, ...msg.limits }\n for (const sub of this.subs.values()) {\n if (sub.status === 'revoked') continue\n this.enqueue(sub, () => this.activateSub(sub))\n }\n }\n\n private handleMessage(msg: ServerMsg): void {\n switch (msg.type) {\n case 'subscribed':\n this.handleSubscribed(msg)\n return\n case 'ops': {\n const sub = this.subs.get(msg.sub)\n if (sub) this.enqueue(sub, () => this.processOps(sub, msg))\n return\n }\n case 'pushed': {\n const sub = this.subs.get(msg.sub)\n if (sub) this.enqueue(sub, () => this.processPushed(sub, msg))\n return\n }\n case 'error':\n this.handleError(msg)\n return\n case 'pong':\n case 'token_ok':\n case 'unsubscribed':\n case 'welcome':\n return\n default:\n // forward compatibility: ignore unknown message types\n return\n }\n }\n\n private handleSubscribed(msg: SubscribedMsg): void {\n const sub = this.subs.get(msg.sub)\n if (!sub) return\n sub.active = true\n sub.status = 'live'\n sub.schemaVersion = msg.schema_version\n this.log(`subscribed '${sub.key}' channel=${msg.channel} cursor=${msg.cursor} head=${msg.head}`)\n this.flush(sub)\n }\n\n private handleError(msg: ErrorMsg): void {\n const subKey = msg.sub\n this.log(`server error${subKey ? ` (sub ${subKey})` : ''}: ${msg.code} — ${msg.message ?? ''}`)\n\n if (subKey) {\n const sub = this.subs.get(subKey)\n if (!sub) return\n this.emit('suberror', { sub: subKey, code: msg.code, message: msg.message })\n\n if (isRebootstrapError(msg.code)) {\n // §5 recovery: discard state, snapshot again, resubscribe — pending\n // survives and is re-pushed (idempotent by op_id)\n sub.active = false\n sub.bootstrapped = false\n for (const p of sub.pending) {\n p.sent = false\n p.ackedSeq = undefined\n }\n this.enqueue(sub, async () => {\n await this.activateSub(sub)\n })\n return\n }\n if (msg.code === 'SHARE_REVOKED' || msg.code === 'CONNECTION_REVOKED') {\n sub.active = false\n sub.status = 'revoked'\n sub.revokedCode = msg.code\n this.subs.delete(subKey)\n // a revoked mount's cache is purged per the guest-side contract\n void sub.store.destroy().catch(() => {})\n return\n }\n return\n }\n\n // connection-level\n switch (msg.code) {\n case 'CONNECTION_REVOKED':\n this.revokedInfo = { code: msg.code, message: msg.message }\n this.started = false\n this.connection.stop()\n this.recomputeStatus()\n this.emit('revoked', { code: msg.code, message: msg.message })\n return\n case 'UNSUPPORTED_VERSION':\n this.started = false\n this.connection.stop()\n this.recomputeStatus()\n return\n case 'TOO_MANY_OPS':\n case 'RATE_LIMITED': {\n for (const sub of this.subs.values()) {\n for (const p of sub.pending) {\n if (p.ackedSeq === undefined) p.sent = false\n }\n }\n this.timer(() => {\n for (const sub of this.subs.values()) this.flush(sub)\n }, RETRY_FLUSH_DELAY_MS)\n return\n }\n case 'UNAUTHORIZED':\n case 'TOKEN_EXPIRED':\n // SyncConnection already handles refresh-and-retry\n return\n case 'SNAPSHOT_REQUIRED':\n case 'RESET_REQUIRED':\n // defensive: shouldn't occur without a sub in multiplexed mode\n for (const sub of this.subs.values()) {\n sub.active = false\n sub.bootstrapped = false\n this.enqueue(sub, () => this.activateSub(sub))\n }\n return\n default:\n return\n }\n }\n\n // -------------------------------------------------------------------\n // Subscription state machine (serialized per sub via `chain`)\n // -------------------------------------------------------------------\n\n private async openSub(key: string, shareId: string | null): Promise<SubscriptionState> {\n const name = shareId\n ? `${this.dbPrefix}:${this.projectId}:share:${shareId}`\n : `${this.dbPrefix}:${this.projectId}`\n const store = new SyncStore(name, this.schema)\n const [cursor, pendingRows] = await Promise.all([store.getCursor(), store.loadPending()])\n return {\n key,\n shareId,\n store,\n cursor: cursor ?? -1, // -1 = never bootstrapped\n pending: pendingRows.map((row: PendingRow) => ({ op: row.op, sent: false })),\n active: false,\n bootstrapped: cursor !== null,\n status: 'initializing',\n appliedOpIds: new BoundedSet(),\n chain: Promise.resolve(),\n schemaVersion: null,\n }\n }\n\n /** Bootstrap if needed, then bind the stream on the current socket. */\n private async activateSub(sub: SubscriptionState): Promise<void> {\n if (!this.connection.isOnline) return\n if (!sub.bootstrapped || sub.cursor < 0) {\n try {\n await this.bootstrapSub(sub)\n } catch (err) {\n this.log(`bootstrap failed for '${sub.key}':`, err)\n sub.status = 'error'\n // retry on next welcome / explicit flush; snapshot failures are\n // usually transient (offline) or auth (handled by connection)\n return\n }\n }\n this.connection.send({\n type: 'subscribe',\n sub: sub.key,\n cursor: sub.cursor,\n ...(sub.shareId\n ? { share: sub.shareId }\n : this.opts.appName\n ? { app: this.opts.appName }\n : {}),\n } as Parameters<SyncConnection['send']>[0])\n }\n\n /** Cold start = snapshot + tail; never log replay (§5). Pending survives. */\n private async bootstrapSub(sub: SubscriptionState): Promise<void> {\n const snapshot = await this.opts.fetchSnapshot(\n sub.shareId ? { share: sub.shareId } : undefined,\n )\n await sub.store.replaceFromSnapshot({\n channel: snapshot.channel,\n records: snapshot.records ?? {},\n cursor: snapshot.cursor ?? 0,\n })\n sub.cursor = snapshot.cursor ?? 0\n sub.bootstrapped = true\n sub.appliedOpIds.clear() // snapshot state subsumes history\n this.log(`bootstrapped '${sub.key}' cursor=${sub.cursor}`)\n this.emit('change', { sub: sub.key, tables: sub.store.tables })\n }\n\n /**\n * Responsibilities 3+4+5: ordered apply, cursor advance, dedupe/confirm.\n * Runs inside the sub's serial chain.\n */\n private async processOps(sub: SubscriptionState, msg: OpsMsg): Promise<void> {\n const applyOps: LoggedOp[] = []\n const confirmedOpIds: string[] = []\n\n for (const op of msg.ops) {\n if (typeof op.seq !== 'number' || op.seq <= sub.cursor) continue // already seen\n sub.cursor = op.seq\n if (sub.appliedOpIds.has(op.op_id)) continue\n const idx = sub.pending.findIndex((p) => p.op.op_id === op.op_id)\n if (idx >= 0) {\n // own op echoed back — confirmation (may arrive before `pushed`)\n sub.pending.splice(idx, 1)\n confirmedOpIds.push(op.op_id)\n }\n if (!sub.store.hasTable(op.table)) {\n // forward compatibility: unknown tables/op shapes advance the cursor only\n sub.appliedOpIds.add(op.op_id)\n continue\n }\n applyOps.push(op)\n sub.appliedOpIds.add(op.op_id)\n }\n\n // empty `ops` may still advance the cursor (filtered tail) — must adopt it\n if (typeof msg.cursor === 'number' && msg.cursor > sub.cursor) {\n sub.cursor = msg.cursor\n }\n\n if (applyOps.length > 0 || confirmedOpIds.length > 0) {\n await sub.store.commitIncoming({ applyOps, confirmedOpIds, cursor: sub.cursor })\n const tables = [...new Set(applyOps.map((op) => op.table))]\n this.emit('change', { sub: sub.key, tables })\n } else {\n await sub.store.setCursor(sub.cursor)\n }\n }\n\n /**\n * Push verdicts (§6.5, §8, §9). Success acks are recorded but the op stays\n * pending until its echo arrives in seq order — this preserves strict\n * ordered apply even when `pushed` races ahead of intermediate remote ops.\n * Terminal errors apply the poison-op rule; retryables back off.\n */\n private async processPushed(sub: SubscriptionState, msg: PushedMsg): Promise<void> {\n let needsRetry = false\n const changedTables = new Set<string>()\n\n for (const result of msg.results) {\n const idx = sub.pending.findIndex((p) => p.op.op_id === result.op_id)\n\n if ('seq' in result && typeof result.seq === 'number') {\n if (idx >= 0) {\n if (result.seq <= sub.cursor) {\n // The op is already part of confirmed history — either its echo\n // was applied or a re-bootstrap snapshot subsumed it (idempotent\n // re-push returned the original seq). The echo will never arrive,\n // so confirm now: drop from pending and rebase the record.\n const [entry] = sub.pending.splice(idx, 1)\n await sub.store.commitIncoming({\n applyOps: [],\n confirmedOpIds: [entry!.op.op_id],\n cursor: sub.cursor,\n })\n changedTables.add(entry!.op.table)\n } else {\n sub.pending[idx]!.ackedSeq = result.seq\n await sub.store.markAcked(result.op_id, result.seq)\n }\n }\n continue\n }\n\n if ('error' in result) {\n if (isTerminalOpError(result.error, result.terminal)) {\n // poison-op rule: out of pending forever, into rejected, surfaced\n if (idx >= 0) sub.pending.splice(idx, 1)\n const rejection = await sub.store.rejectPending(\n result.op_id,\n result.error,\n result.message,\n )\n if (rejection) {\n changedTables.add(rejection.op.table)\n this.emit('rejected', { sub: sub.key, rejection })\n this.log(\n `op rejected (${result.error}): ${rejection.op.type} ${rejection.op.table}/${rejection.op.record_id}`,\n )\n }\n } else if (idx >= 0) {\n sub.pending[idx]!.sent = false\n needsRetry = true\n }\n }\n }\n\n if (changedTables.size > 0) {\n this.emit('change', { sub: sub.key, tables: [...changedTables] })\n }\n if (needsRetry) {\n this.timer(() => this.flush(sub), RETRY_FLUSH_DELAY_MS)\n }\n }\n\n /** Push unsent pending ops, chunked to `limits.max_ops_per_push`. */\n private flush(sub: SubscriptionState): void {\n if (!this.connection.isOnline || !sub.active) return\n const unsent = sub.pending.filter((p) => !p.sent && p.ackedSeq === undefined)\n if (unsent.length === 0) return\n const chunkSize = Math.max(1, this.limits.max_ops_per_push)\n for (let i = 0; i < unsent.length; i += chunkSize) {\n const chunk = unsent.slice(i, i + chunkSize)\n for (const p of chunk) p.sent = true\n const ok = this.connection.send({\n type: 'push',\n sub: sub.key,\n ops: chunk.map((p) => p.op),\n })\n if (!ok) {\n for (const p of chunk) p.sent = false\n return\n }\n }\n this.log(`pushed ${unsent.length} op(s) on '${sub.key}'`)\n }\n\n // -------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------\n\n private get dbPrefix(): string {\n return this.opts.dbNamePrefix ?? 'basic-sync'\n }\n\n private enqueue(sub: SubscriptionState, task: () => Promise<void>): Promise<void> {\n sub.chain = sub.chain.then(task).catch((err) => {\n this.log(`task failed on '${sub.key}':`, err)\n })\n return sub.chain\n }\n\n private timer(fn: () => void, ms: number): void {\n const t = setTimeout(() => {\n this.timers.delete(t)\n fn()\n }, ms)\n this.timers.add(t)\n }\n\n private recomputeStatus(): void {\n let status: SyncStatus\n if (this.revokedInfo) status = 'revoked'\n else if (this.connectionStatus === 'auth_failed') status = 'auth_required'\n else if (!this.started) status = this.connectionStatus === 'stopped' ? 'stopped' : 'idle'\n else if (this.connectionStatus === 'online') status = 'online'\n else if (this.connectionStatus === 'connecting') status = 'connecting'\n else if (this.connectionStatus === 'idle') status = 'connecting'\n else status = 'offline'\n\n if (status !== this._status) {\n this._status = status\n this.emit('status', status)\n }\n }\n\n private log(...args: unknown[]): void {\n this.opts.log?.('[sync-engine]', ...args)\n }\n}\n","/**\n * Sync/2 wire protocol types — the client side of basic-server's\n * `docs/SYNC_V2.md` contract (protocol version 1).\n *\n * WebSocket endpoint: `wss://<pds>/sync/`\n * HTTP bootstrap: `GET /account/:project_id/db/snapshot`\n * HTTP pull: `GET /account/:project_id/db/changes`\n */\n\nexport const PROTOCOL_VERSION = 1\n\n// ---------------------------------------------------------------------------\n// Ops\n// ---------------------------------------------------------------------------\n\nexport type OpType = 'put' | 'patch' | 'delete'\n\n/** An op as pushed by the client. `op_id` is the client-minted idempotency key. */\nexport interface OpEnvelope {\n op_id: string\n type: OpType\n table: string\n record_id: string\n data?: Record<string, unknown> | null\n /** What the writer had seen when creating the op. Recorded, never enforced (v1). */\n base_seq?: number | null\n}\n\n/** An op as delivered by the server (`ops` message / `changes` endpoint). */\nexport interface LoggedOp extends OpEnvelope {\n seq: number\n /** Server-stamped writer identity — never sent by the client. */\n actor: string\n server_ts: string | number\n}\n\n// ---------------------------------------------------------------------------\n// Error taxonomy (SYNC_V2.md §9)\n// ---------------------------------------------------------------------------\n\nexport type SyncErrorCode =\n // terminal op-level: the input will never succeed; re-pushing is a bug\n | 'SCHEMA_VALIDATION_FAILED'\n | 'UNKNOWN_TABLE'\n | 'RECORD_NOT_FOUND'\n | 'PERMISSION_DENIED'\n | 'PAYLOAD_TOO_LARGE'\n | 'CHANNEL_FULL'\n // retryable\n | 'TOO_MANY_OPS'\n | 'RATE_LIMITED'\n | 'TRY_AGAIN'\n // recovery (re-bootstrap from snapshot, keep pending ops)\n | 'SNAPSHOT_REQUIRED'\n | 'RESET_REQUIRED'\n // auth / lifecycle\n | 'UNAUTHORIZED'\n | 'TOKEN_EXPIRED'\n | 'SHARE_REVOKED'\n | 'CONNECTION_REVOKED'\n | 'UNSUPPORTED_VERSION'\n | 'BAD_MESSAGE'\n\nconst TERMINAL_OP_ERRORS: ReadonlySet<string> = new Set([\n 'SCHEMA_VALIDATION_FAILED',\n 'UNKNOWN_TABLE',\n 'RECORD_NOT_FOUND',\n 'PERMISSION_DENIED',\n 'PAYLOAD_TOO_LARGE',\n 'CHANNEL_FULL',\n 'BAD_MESSAGE',\n])\n\n/** Terminal = poison-op rule applies: park in rejected store, never re-push. */\nexport function isTerminalOpError(code: string | undefined, terminalFlag?: boolean): boolean {\n if (terminalFlag !== undefined) return terminalFlag\n return code !== undefined && TERMINAL_OP_ERRORS.has(code)\n}\n\n/** Errors that mean \"discard channel state, re-bootstrap from snapshot, resubscribe\". */\nexport function isRebootstrapError(code: string): boolean {\n return code === 'SNAPSHOT_REQUIRED' || code === 'RESET_REQUIRED'\n}\n\n/** Errors that mean the subscription is gone and must not be retried. */\nexport function isRevocationError(code: string): boolean {\n return code === 'SHARE_REVOKED' || code === 'CONNECTION_REVOKED'\n}\n\n/** Errors that mean the token was rejected; reauth then reconnect. */\nexport function isAuthError(code: string): boolean {\n return code === 'UNAUTHORIZED' || code === 'TOKEN_EXPIRED'\n}\n\n// ---------------------------------------------------------------------------\n// Limits (advertised in `welcome.limits`; authoritative)\n// ---------------------------------------------------------------------------\n\nexport interface SyncLimits {\n max_ops_per_push: number\n max_op_bytes: number\n replay_limit: number\n}\n\nexport const DEFAULT_LIMITS: SyncLimits = {\n max_ops_per_push: 500,\n max_op_bytes: 64 * 1024,\n replay_limit: 1000,\n}\n\n// ---------------------------------------------------------------------------\n// Client → server messages\n// ---------------------------------------------------------------------------\n\n/**\n * First message on the socket. Sending only `{version, token}` opens a\n * multiplexed session (auth-only welcome); streams are then bound with\n * explicit `subscribe` messages. (The legacy single-subscription handshake\n * with `cursor`/`share` on the hello is not used by this client.)\n */\nexport interface HelloMsg {\n type: 'hello'\n version: number\n token: string\n}\n\nexport interface SubscribeFilter {\n table: string\n record_ids?: string[]\n}\n\nexport interface SubscribeMsg {\n type: 'subscribe'\n sub: string\n /** Last seq seen. Required — a null/absent cursor gets SNAPSHOT_REQUIRED. */\n cursor: number\n /** Mount a share instead of the token's own channel. */\n share?: string\n /** Narrow an own-channel subscription (partial sync). */\n filter?: SubscribeFilter\n}\n\nexport interface UnsubscribeMsg {\n type: 'unsubscribe'\n sub: string\n}\n\nexport interface PushMsg {\n type: 'push'\n sub: string\n ops: OpEnvelope[]\n}\n\nexport interface PingMsg {\n type: 'ping'\n cursor?: number\n}\n\n/** Refresh auth on a live socket without reconnecting. */\nexport interface TokenMsg {\n type: 'token'\n token: string\n}\n\nexport type ClientMsg =\n | HelloMsg\n | SubscribeMsg\n | UnsubscribeMsg\n | PushMsg\n | PingMsg\n | TokenMsg\n\n// ---------------------------------------------------------------------------\n// Server → client messages\n// ---------------------------------------------------------------------------\n\n/** Multiplexed handshake: auth-only welcome (`channel`/`cursor` absent). */\nexport interface WelcomeMsg {\n type: 'welcome'\n actor: string\n limits: SyncLimits\n channel?: string\n cursor?: number\n head?: number\n schema_version?: string | number | null\n}\n\nexport interface SubscribedMsg {\n type: 'subscribed'\n sub: string\n channel: string\n cursor: number\n head: number\n schema_version: string | number | null\n}\n\nexport interface UnsubscribedMsg {\n type: 'unsubscribed'\n sub: string\n}\n\nexport interface OpsMsg {\n type: 'ops'\n sub: string\n /** May be empty — a filtered tail still advances `cursor`; always adopt it. */\n ops: LoggedOp[]\n cursor: number\n}\n\nexport type PushResult =\n | { op_id: string; seq: number }\n | { op_id: string; error: SyncErrorCode; terminal?: boolean; message?: string }\n\nexport interface PushedMsg {\n type: 'pushed'\n sub: string\n results: PushResult[]\n /** Channel head after commit. Absent when nothing was committed. */\n cursor?: number\n}\n\nexport interface PongMsg {\n type: 'pong'\n head: number\n heads?: Record<string, number>\n}\n\nexport interface TokenOkMsg {\n type: 'token_ok'\n}\n\nexport interface ErrorMsg {\n type: 'error'\n code: SyncErrorCode\n message?: string\n terminal?: boolean\n /** Present when the error concerns one subscription on a multiplexed socket. */\n sub?: string\n}\n\nexport type ServerMsg =\n | WelcomeMsg\n | SubscribedMsg\n | UnsubscribedMsg\n | OpsMsg\n | PushedMsg\n | PongMsg\n | TokenOkMsg\n | ErrorMsg\n\n// ---------------------------------------------------------------------------\n// HTTP shapes\n// ---------------------------------------------------------------------------\n\n/** `GET /account/:project_id/db/snapshot` → `{ data: Snapshot }` */\nexport interface Snapshot {\n channel: string\n /** table → record_id → field values (tombstones excluded, no `id` field). */\n records: Record<string, Record<string, Record<string, unknown>>>\n /** Head seq the snapshot is consistent with. */\n cursor: number\n}\n\n/** `GET /account/:project_id/db/changes` → `{ data: ChangesPage }` */\nexport interface ChangesPage {\n ops: LoggedOp[]\n cursor: number\n more: boolean\n}\n\nexport type SharePermission = 'read' | 'write'\n\nexport interface ShareSelector {\n table: string\n record_ids?: string[] | null\n}\n\n/** A share row as returned by `GET /account/shares`. */\nexport interface Share {\n id: string\n account_id: string\n channel_id: string\n grantee: string\n selector: ShareSelector\n permission: SharePermission\n created_at: string\n expires_at: string | null\n revoked_at: string | null\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Client-minted op id (idempotency key). */\nexport function mintOpId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID()\n }\n // non-secure-context fallback\n return 'op-' + Math.random().toString(36).slice(2) + Date.now().toString(36)\n}\n\n/** JSON-safe deep clone (op payloads are JSON by construction). */\nexport function cloneData<T>(value: T): T {\n return value === undefined ? value : JSON.parse(JSON.stringify(value))\n}\n\n/**\n * Apply one op to a record's field data. Returns the new data, or `undefined`\n * when the record does not exist (deleted / never created).\n *\n * - `put`: create or replace the whole record\n * - `patch`: shallow-merge top-level fields; no effect on a missing record\n * - `delete`: tombstone (idempotent)\n */\nexport function applyOpToData(\n existing: Record<string, unknown> | undefined,\n op: OpEnvelope,\n): Record<string, unknown> | undefined {\n switch (op.type) {\n case 'put':\n return cloneData(op.data ?? {}) as Record<string, unknown>\n case 'patch':\n if (existing === undefined) return undefined\n return { ...existing, ...(cloneData(op.data ?? {}) as Record<string, unknown>) }\n case 'delete':\n return undefined\n }\n}\n","/**\n * SyncConnection — one multiplexed WebSocket to `wss://<pds>/sync/`\n * (SYNC_V2.md §6.9: one socket, many streams).\n *\n * Owns the transport only: hello handshake, heartbeat ping, exponential\n * backoff reconnect, and token refresh on auth rejection. Everything above\n * the socket (subscriptions, cursors, pending queues) belongs to SyncEngine,\n * which receives every parsed server message via `onMessage`.\n */\nimport {\n PROTOCOL_VERSION,\n isAuthError,\n type ClientMsg,\n type ServerMsg,\n type WelcomeMsg,\n} from './protocol'\n\nexport type ConnectionStatus =\n | 'idle'\n | 'connecting'\n | 'online'\n | 'offline'\n | 'auth_failed'\n | 'stopped'\n\nexport interface SyncConnectionOptions {\n /** e.g. `wss://pds.basic.id/sync/` */\n wsUrl: string\n getToken: (options?: { forceRefresh?: boolean }) => Promise<string>\n /** Pass the `ws` constructor in Node; defaults to global WebSocket. */\n WebSocketImpl?: typeof WebSocket\n /** Heartbeat interval (default 30s per spec). */\n heartbeatMs?: number\n onWelcome: (msg: WelcomeMsg) => void\n onMessage: (msg: ServerMsg) => void\n onStatus: (status: ConnectionStatus) => void\n log?: (...args: unknown[]) => void\n}\n\nconst INITIAL_RECONNECT_DELAY_MS = 500\nconst MAX_RECONNECT_DELAY_MS = 30_000\n\nexport class SyncConnection {\n private readonly opts: SyncConnectionOptions\n private readonly WS: typeof WebSocket\n private readonly heartbeatMs: number\n\n private ws: WebSocket | null = null\n private _status: ConnectionStatus = 'idle'\n private stopped = true\n private reconnectDelay = INITIAL_RECONNECT_DELAY_MS\n private timers = new Set<ReturnType<typeof setTimeout>>()\n private heartbeatTimer: ReturnType<typeof setTimeout> | null = null\n /** One forced-refresh reconnect attempt per auth rejection. */\n private authRetryUsed = false\n private removeOnlineListener: (() => void) | null = null\n\n constructor(opts: SyncConnectionOptions) {\n this.opts = opts\n this.WS = opts.WebSocketImpl ?? (globalThis.WebSocket as typeof WebSocket)\n this.heartbeatMs = opts.heartbeatMs ?? 30_000\n }\n\n get status(): ConnectionStatus {\n return this._status\n }\n\n get isOnline(): boolean {\n return this._status === 'online' && this.ws?.readyState === 1\n }\n\n start(): void {\n if (!this.stopped && this.ws) return\n this.stopped = false\n this.authRetryUsed = false\n this.listenForNetwork()\n this.open()\n }\n\n stop(): void {\n this.stopped = true\n this.clearTimers()\n this.removeOnlineListener?.()\n this.removeOnlineListener = null\n if (this.ws) {\n try {\n this.ws.close()\n } catch {\n /* ignore */\n }\n this.ws = null\n }\n this.setStatus('stopped')\n }\n\n /** Send a message; returns false when the socket is not open. */\n send(msg: ClientMsg): boolean {\n if (this.ws?.readyState === 1) {\n this.ws.send(JSON.stringify(msg))\n return true\n }\n return false\n }\n\n /** Refresh auth on the live socket (no reconnect). */\n async sendToken(): Promise<void> {\n if (!this.isOnline) return\n try {\n const token = await this.opts.getToken()\n this.send({ type: 'token', token })\n } catch {\n /* token unavailable; auth errors will surface through the socket */\n }\n }\n\n /**\n * The server rejected our token (`UNAUTHORIZED` / `TOKEN_EXPIRED` + close).\n * Retry once with a force-refreshed token; give up (status `auth_failed`)\n * when the refresh itself fails or a fresh token is rejected again.\n */\n handleAuthRejection(): void {\n if (this.stopped) return\n if (this.authRetryUsed) {\n this.log('fresh token rejected — giving up until reauth')\n this.stopped = true\n this.clearTimers()\n this.setStatus('auth_failed')\n return\n }\n this.authRetryUsed = true\n this.log('token rejected — force refreshing and reconnecting')\n void (async () => {\n try {\n await this.opts.getToken({ forceRefresh: true })\n this.scheduleReconnect(0)\n } catch (err) {\n this.log('token refresh failed after auth rejection:', err)\n this.stopped = true\n this.setStatus('auth_failed')\n }\n })()\n }\n\n // -------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------\n\n private open(): void {\n if (this.stopped) return\n if (this.ws && (this.ws.readyState === 0 || this.ws.readyState === 1)) return\n if (!this.WS) {\n this.log('no WebSocket implementation available')\n this.setStatus('offline')\n return\n }\n this.setStatus('connecting')\n\n const ws = new this.WS(this.opts.wsUrl)\n this.ws = ws\n\n ws.onopen = () => {\n void (async () => {\n try {\n const token = await this.opts.getToken()\n if (this.ws !== ws || ws.readyState !== 1) return\n const hello = { type: 'hello', version: PROTOCOL_VERSION, token } satisfies ClientMsg\n ws.send(JSON.stringify(hello))\n } catch (err) {\n this.log('could not get token for hello:', err)\n try {\n ws.close()\n } catch {\n /* ignore */\n }\n }\n })()\n }\n\n ws.onmessage = (event: MessageEvent) => {\n let msg: ServerMsg\n try {\n const text =\n typeof event.data === 'string' ? event.data : new TextDecoder().decode(event.data)\n msg = JSON.parse(text)\n } catch {\n return\n }\n this.handleMessage(msg)\n }\n\n ws.onclose = () => {\n if (this.ws !== ws) return\n this.ws = null\n this.stopHeartbeat()\n if (this.stopped) return\n this.setStatus('offline')\n this.scheduleReconnect()\n }\n\n ws.onerror = () => {\n /* onclose follows */\n }\n }\n\n private handleMessage(msg: ServerMsg): void {\n if (msg.type === 'welcome') {\n this.reconnectDelay = INITIAL_RECONNECT_DELAY_MS\n this.authRetryUsed = false\n this.setStatus('online')\n this.startHeartbeat()\n this.opts.onWelcome(msg)\n return\n }\n if (msg.type === 'error' && !('sub' in msg && msg.sub) && isAuthError(msg.code)) {\n // connection-level auth rejection; the server closes the socket\n this.handleAuthRejection()\n this.opts.onMessage(msg)\n return\n }\n this.opts.onMessage(msg)\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat()\n const tick = () => {\n if (this.stopped) return\n this.send({ type: 'ping' })\n this.heartbeatTimer = setTimeout(tick, this.heartbeatMs)\n this.timers.add(this.heartbeatTimer)\n }\n this.heartbeatTimer = setTimeout(tick, this.heartbeatMs)\n this.timers.add(this.heartbeatTimer)\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearTimeout(this.heartbeatTimer)\n this.timers.delete(this.heartbeatTimer)\n this.heartbeatTimer = null\n }\n }\n\n private scheduleReconnect(delayOverride?: number): void {\n if (this.stopped) return\n const delay = delayOverride ?? this.reconnectDelay\n this.reconnectDelay = Math.min(this.reconnectDelay * 2, MAX_RECONNECT_DELAY_MS)\n this.log(`reconnecting in ${delay}ms`)\n const timer = setTimeout(() => {\n this.timers.delete(timer)\n this.open()\n }, delay)\n this.timers.add(timer)\n }\n\n private listenForNetwork(): void {\n if (this.removeOnlineListener || typeof window === 'undefined') return\n const handleOnline = () => {\n if (this.stopped) return\n this.log('network online — reconnecting immediately')\n this.reconnectDelay = INITIAL_RECONNECT_DELAY_MS\n this.open()\n }\n window.addEventListener('online', handleOnline)\n this.removeOnlineListener = () => window.removeEventListener('online', handleOnline)\n }\n\n private clearTimers(): void {\n for (const t of this.timers) clearTimeout(t)\n this.timers.clear()\n this.heartbeatTimer = null\n }\n\n private setStatus(status: ConnectionStatus): void {\n if (this._status === status) return\n this._status = status\n this.opts.onStatus(status)\n }\n\n private log(...args: unknown[]): void {\n this.opts.log?.('[sync-connection]', ...args)\n }\n}\n","/**\n * SyncStore — persistent local state for one sync keyspace (an own channel or\n * a mounted share), backed by plain Dexie/IndexedDB.\n *\n * Layout (one Dexie database per keyspace):\n * - one **view** store per app table: `{ id, ...fields }` — what the app\n * reads (server state + pending ops rebased). `useQuery`/liveQuery reads\n * these stores directly.\n * - `_server`: confirmed records only, keyed `[table+record_id]`.\n * - `_pending`: queued local ops (survive restarts), insertion-ordered.\n * - `_rejected`: terminally rejected ops (poison-op rule — never re-pushed).\n * - `_meta`: cursor, channel id, limits, schema version.\n *\n * The app-visible view is always `serverState + pending applied in order`\n * (client responsibility #6). Rebasing is done per affected record inside\n * the same transaction as the change that triggered it.\n */\nimport Dexie, { type Table } from 'dexie'\nimport {\n applyOpToData,\n cloneData,\n type LoggedOp,\n type OpEnvelope,\n type SyncErrorCode,\n} from './protocol'\n\nexport interface ServerRow {\n table: string\n record_id: string\n data: Record<string, unknown>\n}\n\nexport interface PendingRow {\n /** Auto-increment — preserves creation order across restarts. */\n idx?: number\n op_id: string\n op: OpEnvelope\n /** Set when the server acked the op (`pushed` seq) but the echo hasn't arrived yet. */\n acked_seq?: number\n}\n\nexport interface RejectedRow {\n idx?: number\n op_id: string\n op: OpEnvelope\n error: SyncErrorCode | string\n message?: string\n rejected_at: number\n}\n\ninterface MetaRow {\n key: string\n value: unknown\n}\n\nconst META_CURSOR = 'cursor'\nconst META_CHANNEL = 'channel'\n\nexport interface SyncStoreSchema {\n version?: number\n tables: Record<string, { fields: Record<string, { indexed?: boolean }> }>\n}\n\nexport class SyncStore {\n readonly db: Dexie\n readonly name: string\n private readonly tableNames: string[]\n\n constructor(name: string, schema: SyncStoreSchema) {\n this.name = name\n this.tableNames = Object.keys(schema.tables)\n this.db = new Dexie(name)\n\n const stores: Record<string, string> = {\n _server: '[table+record_id], table',\n _pending: '++idx, op_id',\n _rejected: '++idx, op_id',\n _meta: 'key',\n }\n for (const [tableName, table] of Object.entries(schema.tables)) {\n const indexed = Object.entries(table.fields)\n .filter(([, f]) => f.indexed)\n .map(([fieldName]) => `,${fieldName}`)\n .join('')\n stores[tableName] = 'id' + indexed\n }\n // Dexie versions must be monotonic; app schema versions are (enforced by\n // @basictech/schema validateUpdateSchema), so reuse them.\n this.db.version(Math.max(schema.version ?? 1, 1)).stores(stores)\n }\n\n /** The Dexie view table for an app table (what liveQuery reads). */\n view(table: string): Table<Record<string, unknown>, string> {\n return this.db.table(table)\n }\n\n hasTable(table: string): boolean {\n return this.tableNames.includes(table)\n }\n\n get tables(): string[] {\n return [...this.tableNames]\n }\n\n private get server(): Table<ServerRow, [string, string]> {\n return this.db.table('_server')\n }\n private get pending(): Table<PendingRow, number> {\n return this.db.table('_pending')\n }\n private get rejected(): Table<RejectedRow, number> {\n return this.db.table('_rejected')\n }\n private get meta(): Table<MetaRow, string> {\n return this.db.table('_meta')\n }\n\n private get allStores(): string[] {\n return ['_server', '_pending', '_rejected', '_meta', ...this.tableNames]\n }\n\n // -------------------------------------------------------------------\n // Meta\n // -------------------------------------------------------------------\n\n async getCursor(): Promise<number | null> {\n const row = await this.meta.get(META_CURSOR)\n return typeof row?.value === 'number' ? row.value : null\n }\n\n async getChannel(): Promise<string | null> {\n const row = await this.meta.get(META_CHANNEL)\n return typeof row?.value === 'string' ? row.value : null\n }\n\n // -------------------------------------------------------------------\n // Pending / rejected\n // -------------------------------------------------------------------\n\n /** All pending ops in creation order (used to warm the in-memory queue). */\n async loadPending(): Promise<PendingRow[]> {\n return this.pending.orderBy('idx').toArray()\n }\n\n async listRejected(): Promise<RejectedRow[]> {\n return this.rejected.orderBy('idx').toArray()\n }\n\n async clearRejected(): Promise<void> {\n await this.rejected.clear()\n }\n\n /** Record a server ack for a pending op (echo not yet seen). */\n async markAcked(opId: string, seq: number): Promise<void> {\n await this.pending.where('op_id').equals(opId).modify({ acked_seq: seq })\n }\n\n // -------------------------------------------------------------------\n // Writes\n // -------------------------------------------------------------------\n\n /**\n * Enqueue a local op and apply it optimistically to the view.\n * Returns the resulting view record (null when the op deletes it).\n */\n async addPending(op: OpEnvelope): Promise<Record<string, unknown> | null> {\n return this.db.transaction('rw', this.allStores, async () => {\n await this.pending.add({ op_id: op.op_id, op: cloneData(op) })\n return this.recomputeViewRecord(op.table, op.record_id)\n })\n }\n\n /**\n * Commit a batch of incoming server ops (already filtered/deduped by the\n * engine): update `_server`, drop confirmed pending ops, advance the\n * cursor, and rebase every affected view record — in one transaction.\n */\n async commitIncoming(params: {\n applyOps: LoggedOp[]\n confirmedOpIds: string[]\n cursor: number\n }): Promise<void> {\n const { applyOps, confirmedOpIds, cursor } = params\n await this.db.transaction('rw', this.allStores, async () => {\n const affected = new Set<string>()\n for (const op of applyOps) affected.add(`${op.table}\\u0000${op.record_id}`)\n\n for (const op of applyOps) {\n await this.applyToServer(op)\n }\n if (confirmedOpIds.length > 0) {\n // confirmed ops outside applyOps (already subsumed by a snapshot or\n // an earlier echo) still need their records rebased once the pending\n // row is gone — collect them before deleting\n const confirmedRows = await this.pending.where('op_id').anyOf(confirmedOpIds).toArray()\n for (const row of confirmedRows) affected.add(`${row.op.table}\\u0000${row.op.record_id}`)\n await this.pending.where('op_id').anyOf(confirmedOpIds).delete()\n }\n await this.meta.put({ key: META_CURSOR, value: cursor })\n\n for (const key of affected) {\n const [table, recordId] = key.split('\\u0000') as [string, string]\n await this.recomputeViewRecord(table, recordId)\n }\n })\n }\n\n /** Persist a cursor advance with no ops (empty `ops` message / pushed cursor). */\n async setCursor(cursor: number): Promise<void> {\n await this.meta.put({ key: META_CURSOR, value: cursor })\n }\n\n /**\n * Terminal rejection: remove from pending, park in the rejected store,\n * roll the view record back to server state + remaining pending ops.\n */\n async rejectPending(\n opId: string,\n error: SyncErrorCode | string,\n message?: string,\n ): Promise<RejectedRow | null> {\n return this.db.transaction('rw', this.allStores, async () => {\n const row = await this.pending.where('op_id').equals(opId).first()\n if (!row) return null\n await this.pending.where('op_id').equals(opId).delete()\n const rejectedRow: RejectedRow = {\n op_id: opId,\n op: row.op,\n error,\n message,\n rejected_at: Date.now(),\n }\n await this.rejected.add(rejectedRow)\n await this.recomputeViewRecord(row.op.table, row.op.record_id)\n return rejectedRow\n })\n }\n\n // -------------------------------------------------------------------\n // Bootstrap\n // -------------------------------------------------------------------\n\n /**\n * Replace all server state from a snapshot (cold start or\n * SNAPSHOT_REQUIRED/RESET_REQUIRED recovery). Pending ops survive and are\n * re-applied on top of the fresh state.\n */\n async replaceFromSnapshot(params: {\n channel: string\n records: Record<string, Record<string, Record<string, unknown>>>\n cursor: number\n }): Promise<void> {\n const { channel, records, cursor } = params\n await this.db.transaction('rw', this.allStores, async () => {\n await this.server.clear()\n for (const tableName of this.tableNames) {\n await this.view(tableName).clear()\n }\n\n for (const [tableName, tableRecords] of Object.entries(records)) {\n if (!this.hasTable(tableName)) continue\n const serverRows: ServerRow[] = []\n const viewRows: Record<string, unknown>[] = []\n for (const [recordId, data] of Object.entries(tableRecords)) {\n serverRows.push({ table: tableName, record_id: recordId, data: data ?? {} })\n viewRows.push({ id: recordId, ...(data ?? {}) })\n }\n await this.server.bulkPut(serverRows)\n await this.view(tableName).bulkPut(viewRows)\n }\n\n // rebase pending ops on top of the fresh snapshot\n const pendingRows = await this.pending.orderBy('idx').toArray()\n const affected = new Set<string>()\n for (const row of pendingRows) affected.add(`${row.op.table}\\u0000${row.op.record_id}`)\n for (const key of affected) {\n const [table, recordId] = key.split('\\u0000') as [string, string]\n if (this.hasTable(table)) await this.recomputeViewRecord(table, recordId)\n }\n\n await this.meta.put({ key: META_CURSOR, value: cursor })\n await this.meta.put({ key: META_CHANNEL, value: channel })\n })\n }\n\n // -------------------------------------------------------------------\n // Reads\n // -------------------------------------------------------------------\n\n async getViewRecord(table: string, id: string): Promise<Record<string, unknown> | null> {\n const record = await this.view(table).get(id)\n return record ?? null\n }\n\n async getViewRecords(table: string): Promise<Record<string, unknown>[]> {\n return this.view(table).toArray()\n }\n\n // -------------------------------------------------------------------\n // Lifecycle\n // -------------------------------------------------------------------\n\n close(): void {\n this.db.close()\n }\n\n /** Delete the underlying IndexedDB database (sign-out / revoked mount). */\n async destroy(): Promise<void> {\n this.db.close()\n await Dexie.delete(this.name)\n }\n\n // -------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------\n\n private async applyToServer(op: LoggedOp): Promise<void> {\n if (!this.hasTable(op.table)) return\n const existing = await this.server.get([op.table, op.record_id])\n const next = applyOpToData(existing?.data, op)\n if (next === undefined) {\n await this.server.delete([op.table, op.record_id])\n } else {\n await this.server.put({ table: op.table, record_id: op.record_id, data: next })\n }\n }\n\n /**\n * Rebase one record: view = server data + pending ops for that record in\n * creation order. Must run inside a transaction covering all stores.\n */\n private async recomputeViewRecord(\n table: string,\n recordId: string,\n ): Promise<Record<string, unknown> | null> {\n if (!this.hasTable(table)) return null\n const serverRow = await this.server.get([table, recordId])\n let data: Record<string, unknown> | undefined = serverRow\n ? cloneData(serverRow.data)\n : undefined\n\n const pendingRows = await this.pending.orderBy('idx').toArray()\n for (const row of pendingRows) {\n if (row.op.table === table && row.op.record_id === recordId) {\n data = applyOpToData(data, row.op)\n }\n }\n\n if (data === undefined) {\n await this.view(table).delete(recordId)\n return null\n }\n const viewRecord = { id: recordId, ...data }\n await this.view(table).put(viewRecord)\n return viewRecord\n }\n}\n","/**\n * The table API — the app-facing database surface, shaped around Sync/2 ops.\n *\n * Two implementations of the same interface:\n * - `SyncDb` — offline-first over a SyncEngine subscription (own channel or\n * a mounted share). Writes queue ops and apply optimistically; reads hit\n * the local Dexie view stores (which `useQuery`/liveQuery observe).\n * - `RestDb` — direct REST calls, no local persistence (for server-ish\n * contexts or apps that don't want a local replica).\n */\nimport type { Table } from 'dexie'\nimport { SyncEngine, OWN_SUB } from './sync/SyncEngine'\nimport { mintOpId } from './sync/protocol'\nimport { RestClient, type RestRecord } from './http/RestClient'\n\nexport type BasicRecord = { id: string } & Record<string, unknown>\n\nexport interface BasicTable<T extends BasicRecord = BasicRecord> {\n /** Create a record. Sync mode mints the id locally; REST mode server-side. */\n create(data: Omit<T, 'id'>): Promise<T>\n /** Create or replace the whole record (Sync/2 `put` op). */\n put(id: string, data: Omit<T, 'id'>): Promise<T>\n /** Shallow-merge top-level fields (`patch` op). Returns null when missing. */\n patch(id: string, data: Partial<Omit<T, 'id'>>): Promise<T | null>\n /** Delete (tombstone). Idempotent. */\n delete(id: string): Promise<void>\n get(id: string): Promise<T | null>\n getAll(): Promise<T[]>\n find(predicate: (record: T) => boolean): Promise<T[]>\n /** Sync mode: the Dexie view table (for liveQuery / advanced queries). */\n ref?: Table<T, string>\n}\n\nexport interface BasicDb {\n readonly kind: 'sync' | 'rest'\n table<T extends BasicRecord = BasicRecord>(name: string): BasicTable<T>\n}\n\nfunction mintRecordId(): string {\n return mintOpId()\n}\n\n// ---------------------------------------------------------------------------\n// Sync mode\n// ---------------------------------------------------------------------------\n\nclass SyncTable<T extends BasicRecord> implements BasicTable<T> {\n constructor(\n private readonly engine: SyncEngine,\n private readonly subKey: string,\n private readonly name: string,\n ) {}\n\n private get store() {\n const sub = this.engine.getSubscription(this.subKey)\n if (!sub) {\n throw new Error(\n `subscription '${this.subKey}' is not open — sign in and wait for the db to be ready`,\n )\n }\n return sub.store\n }\n\n get ref(): Table<T, string> {\n return this.store.view(this.name) as unknown as Table<T, string>\n }\n\n async create(data: Omit<T, 'id'>): Promise<T> {\n const id = mintRecordId()\n const view = await this.engine.apply(this.subKey, {\n type: 'put',\n table: this.name,\n record_id: id,\n data: data as Record<string, unknown>,\n })\n return (view ?? { id, ...data }) as T\n }\n\n async put(id: string, data: Omit<T, 'id'>): Promise<T> {\n if (!id) throw new Error('put() requires an id')\n const view = await this.engine.apply(this.subKey, {\n type: 'put',\n table: this.name,\n record_id: id,\n data: data as Record<string, unknown>,\n })\n return (view ?? { id, ...data }) as T\n }\n\n async patch(id: string, data: Partial<Omit<T, 'id'>>): Promise<T | null> {\n if (!id) throw new Error('patch() requires an id')\n // a patch on a missing record is a terminal server rejection — fail fast\n const existing = await this.store.getViewRecord(this.name, id)\n if (!existing) return null\n const view = await this.engine.apply(this.subKey, {\n type: 'patch',\n table: this.name,\n record_id: id,\n data: data as Record<string, unknown>,\n })\n return view as T | null\n }\n\n async delete(id: string): Promise<void> {\n if (!id) throw new Error('delete() requires an id')\n await this.engine.apply(this.subKey, {\n type: 'delete',\n table: this.name,\n record_id: id,\n })\n }\n\n async get(id: string): Promise<T | null> {\n return (await this.store.getViewRecord(this.name, id)) as T | null\n }\n\n async getAll(): Promise<T[]> {\n return (await this.store.getViewRecords(this.name)) as T[]\n }\n\n async find(predicate: (record: T) => boolean): Promise<T[]> {\n const all = await this.getAll()\n return all.filter(predicate)\n }\n}\n\nexport class SyncDb implements BasicDb {\n readonly kind = 'sync' as const\n private readonly tables = new Map<string, SyncTable<BasicRecord>>()\n\n constructor(\n private readonly engine: SyncEngine,\n private readonly subKey: string = OWN_SUB,\n ) {}\n\n table<T extends BasicRecord = BasicRecord>(name: string): BasicTable<T> {\n if (!this.engine.schema.tables[name]) {\n throw new Error(`table \"${name}\" not found in schema`)\n }\n if (!this.tables.has(name)) {\n this.tables.set(name, new SyncTable(this.engine, this.subKey, name))\n }\n return this.tables.get(name) as unknown as BasicTable<T>\n }\n}\n\n// ---------------------------------------------------------------------------\n// REST mode\n// ---------------------------------------------------------------------------\n\nclass RestTable<T extends BasicRecord> implements BasicTable<T> {\n constructor(\n private readonly rest: RestClient,\n private readonly name: string,\n ) {}\n\n async create(data: Omit<T, 'id'>): Promise<T> {\n const record = await this.rest.createRecord(this.name, data as Record<string, unknown>)\n return record as T\n }\n\n async put(id: string, data: Omit<T, 'id'>): Promise<T> {\n if (!id) throw new Error('put() requires an id')\n const record = await this.rest.putRecord(this.name, id, data as Record<string, unknown>)\n if (!record) throw new Error(`record ${this.name}/${id} not found (REST put is replace-only)`)\n return record as T\n }\n\n async patch(id: string, data: Partial<Omit<T, 'id'>>): Promise<T | null> {\n if (!id) throw new Error('patch() requires an id')\n const record = await this.rest.patchRecord(this.name, id, data as Record<string, unknown>)\n return record as T | null\n }\n\n async delete(id: string): Promise<void> {\n if (!id) throw new Error('delete() requires an id')\n await this.rest.deleteRecord(this.name, id)\n }\n\n async get(id: string): Promise<T | null> {\n const record: RestRecord | null = await this.rest.getRecord(this.name, id)\n return record as T | null\n }\n\n async getAll(): Promise<T[]> {\n return (await this.rest.list(this.name)) as T[]\n }\n\n async find(predicate: (record: T) => boolean): Promise<T[]> {\n const all = await this.getAll()\n return all.filter(predicate)\n }\n}\n\nexport class RestDb implements BasicDb {\n readonly kind = 'rest' as const\n private readonly tables = new Map<string, RestTable<BasicRecord>>()\n\n constructor(\n private readonly rest: RestClient,\n private readonly schema?: { tables?: Record<string, unknown> },\n ) {}\n\n table<T extends BasicRecord = BasicRecord>(name: string): BasicTable<T> {\n if (this.schema?.tables && !this.schema.tables[name]) {\n throw new Error(`table \"${name}\" not found in schema`)\n }\n if (!this.tables.has(name)) {\n this.tables.set(name, new RestTable(this.rest, name))\n }\n return this.tables.get(name) as unknown as BasicTable<T>\n }\n}\n","// Schema utilities for Basic React package\nimport { validateSchema, compareSchemas } from '@basictech/schema'\nimport { log } from '../config'\n\nexport async function getSchemaStatus(schema: any): Promise<{\n valid: boolean,\n status: string,\n latest: any\n}> {\n const projectId = schema.project_id\n const valid = validateSchema(schema)\n\n if (!valid.valid) {\n console.warn('BasicDB Error: your local schema is invalid. Please fix errors and try again - sync is disabled')\n return { \n valid: false, \n status: 'invalid',\n latest: null\n }\n }\n\n const latestSchema = await fetch(`https://api.basic.tech/project/${projectId}/schema`)\n .then(res => res.json())\n .then(data => data.data[0].schema)\n .catch(err => {\n return { \n valid: false, \n status: 'error',\n latest: null\n }\n })\n\n if (!latestSchema.version) {\n return { \n valid: false, \n status: 'error',\n latest: null\n }\n }\n\n if (latestSchema.version > schema.version) {\n // error_code: schema_behind\n console.warn('BasicDB Error: your local schema version is behind the latest. Found version:', schema.version, 'but expected', latestSchema.version, \" - sync is disabled\")\n return { \n valid: false, \n status: 'behind', \n latest: latestSchema\n }\n } else if (latestSchema.version < schema.version) {\n // error_code: schema_ahead\n console.warn('BasicDB Error: your local schema version is ahead of the latest. Found version:', schema.version, 'but expected', latestSchema.version, \" - sync is disabled\")\n return { \n valid: false, \n status: 'ahead', \n latest: latestSchema\n }\n } else if (latestSchema.version === schema.version) {\n const changes = compareSchemas(schema, latestSchema)\n if (changes.valid) {\n return { \n valid: true,\n status: 'current',\n latest: latestSchema\n }\n } else {\n // error_code: schema_conflict\n console.warn('BasicDB Error: your local schema is conflicting with the latest. Your version:', schema.version, 'does not match origin version', latestSchema.version, \" - sync is disabled\")\n return { \n valid: false, \n status: 'conflict',\n latest: latestSchema\n }\n }\n } else { \n return { \n valid: false, \n status: 'error',\n latest: null\n }\n }\n}\n\nexport async function validateAndCheckSchema(schema: any): Promise<{\n isValid: boolean,\n schemaStatus: { valid: boolean, status?: string, latest?: any },\n errors?: any[]\n}> {\n const valid = validateSchema(schema)\n if (!valid.valid) {\n log('Basic Schema is invalid!', valid.errors)\n console.group('Schema Errors')\n let errorMessage = ''\n valid.errors.forEach((error, index) => {\n log(`${index + 1}:`, error.message, ` - at ${error.instancePath}`)\n errorMessage += `${index + 1}: ${error.message} - at ${error.instancePath}\\n`\n })\n console.groupEnd()\n \n return {\n isValid: false,\n schemaStatus: { valid: false },\n errors: valid.errors\n }\n }\n\n let schemaStatus: { valid: boolean, status?: string, latest?: any } = { valid: false }\n if (schema.version !== 0) {\n schemaStatus = await getSchemaStatus(schema)\n log('schemaStatus', schemaStatus)\n } else {\n schemaStatus = { valid: false, status: 'unpublished' }\n log(\"schema not published - at version 0\")\n }\n\n return {\n isValid: true,\n schemaStatus\n }\n}\n","import { BasicStorage } from '../utils/storage'\nimport { log } from '../config'\n\nexport interface VersionInfo {\n version: string\n lastUpdated: number\n}\n\nexport interface Migration {\n fromVersion: string\n toVersion: string\n migrate: (storage: BasicStorage) => Promise<void>\n}\n\nexport class VersionUpdater {\n private storage: BasicStorage\n private currentVersion: string\n private migrations: Migration[]\n private versionKey = 'basic_app_version'\n\n constructor(storage: BasicStorage, currentVersion: string, migrations: Migration[] = []) {\n this.storage = storage\n this.currentVersion = currentVersion\n this.migrations = migrations.sort((a, b) => this.compareVersions(a.fromVersion, b.fromVersion))\n }\n\n /**\n * Check current stored version and run migrations if needed\n * Only compares major.minor versions, ignoring beta/prerelease parts\n * Example: \"0.7.0-beta.1\" and \"0.7.0\" are treated as the same version\n */\n async checkAndUpdate(): Promise<{ updated: boolean; fromVersion?: string; toVersion: string }> {\n const storedVersion = await this.getStoredVersion()\n \n if (!storedVersion) {\n // First time setup\n await this.setStoredVersion(this.currentVersion)\n return { updated: false, toVersion: this.currentVersion }\n }\n\n if (storedVersion === this.currentVersion) {\n return { updated: false, toVersion: this.currentVersion }\n }\n\n // Need to run migrations\n const migrationsToRun = this.getMigrationsToRun(storedVersion, this.currentVersion)\n \n if (migrationsToRun.length === 0) {\n // No migrations needed, just update version\n await this.setStoredVersion(this.currentVersion)\n return { updated: true, fromVersion: storedVersion, toVersion: this.currentVersion }\n }\n\n // Run migrations\n for (const migration of migrationsToRun) {\n try {\n log(`Running migration from ${migration.fromVersion} to ${migration.toVersion}`)\n await migration.migrate(this.storage)\n } catch (error) {\n console.error(`Migration failed from ${migration.fromVersion} to ${migration.toVersion}:`, error)\n throw new Error(`Migration failed: ${error}`)\n }\n }\n\n // Update to current version\n await this.setStoredVersion(this.currentVersion)\n return { updated: true, fromVersion: storedVersion, toVersion: this.currentVersion }\n }\n\n private async getStoredVersion(): Promise<string | null> {\n try {\n const versionData = await this.storage.get(this.versionKey)\n if (!versionData) return null\n \n const versionInfo: VersionInfo = JSON.parse(versionData)\n return versionInfo.version\n } catch (error) {\n console.warn('Failed to get stored version:', error)\n return null\n }\n }\n\n private async setStoredVersion(version: string): Promise<void> {\n const versionInfo: VersionInfo = {\n version,\n lastUpdated: Date.now()\n }\n await this.storage.set(this.versionKey, JSON.stringify(versionInfo))\n }\n\n private getMigrationsToRun(fromVersion: string, toVersion: string): Migration[] {\n return this.migrations.filter(migration => {\n const storedLessThanMigrationTo = this.compareVersions(fromVersion, migration.toVersion) < 0\n const currentGreaterThanOrEqualMigrationTo = this.compareVersions(toVersion, migration.toVersion) >= 0\n const shouldRun = storedLessThanMigrationTo && currentGreaterThanOrEqualMigrationTo\n log(`Migration ${migration.fromVersion} → ${migration.toVersion}: shouldRun=${shouldRun}`)\n return shouldRun\n })\n }\n\n /**\n * Simple semantic version comparison (major.minor only, ignoring beta/prerelease)\n * Returns: -1 if a < b, 0 if a === b, 1 if a > b\n */\n private compareVersions(a: string, b: string): number {\n // Extract major.minor from version strings, ignoring beta/prerelease parts\n const aMajorMinor = this.extractMajorMinor(a)\n const bMajorMinor = this.extractMajorMinor(b)\n \n // Compare major version first\n if (aMajorMinor.major !== bMajorMinor.major) {\n return aMajorMinor.major - bMajorMinor.major\n }\n \n // Then compare minor version\n return aMajorMinor.minor - bMajorMinor.minor\n }\n\n /**\n * Extract major.minor from version string, ignoring beta/prerelease\n * Examples: \"0.7.0-beta.1\" -> {major: 0, minor: 7}\n * \"1.2.3\" -> {major: 1, minor: 2}\n */\n private extractMajorMinor(version: string): { major: number, minor: number } {\n // Remove beta/prerelease parts and split by dots\n const cleanVersion = version.split('-')[0]?.split('+')[0] || version\n const parts = cleanVersion.split('.').map(Number)\n \n return {\n major: parts[0] || 0,\n minor: parts[1] || 0\n }\n }\n\n /**\n * Add a migration to the updater\n */\n addMigration(migration: Migration): void {\n this.migrations.push(migration)\n this.migrations.sort((a, b) => this.compareVersions(a.fromVersion, b.fromVersion))\n }\n}\n\n/**\n * Create a simple version updater instance\n */\nexport function createVersionUpdater(\n storage: BasicStorage, \n currentVersion: string, \n migrations: Migration[] = []\n): VersionUpdater {\n return new VersionUpdater(storage, currentVersion, migrations)\n}\n","import { BasicStorage } from '../utils/storage'\nimport { Migration } from './versionUpdater'\nimport { log } from '../config'\n\nexport const addMigrationTimestamp: Migration = {\n fromVersion: '0.6.0',\n toVersion: '0.7.0',\n async migrate(storage: BasicStorage) {\n log('Running migration 0.6.0 → 0.7.0')\n storage.set('test_migration', 'true')\n }\n}\n\n/**\n * 0.9.0 replaced the dexie-syncable sync client with the Sync/2 engine.\n * The legacy `basicdb` IndexedDB database is unused; delete it. Data loss is\n * safe: the server is the source of truth and 0.9 bootstraps fresh replicas\n * into `basic-sync:<project_id>` databases.\n */\nexport const dropLegacySyncDb: Migration = {\n fromVersion: '0.8.0',\n toVersion: '0.9.0',\n async migrate() {\n log('Running migration 0.8.0 → 0.9.0: deleting legacy basicdb')\n try {\n const idb = (globalThis as { indexedDB?: IDBFactory }).indexedDB\n if (!idb) return\n await new Promise<void>((resolve) => {\n const req = idb.deleteDatabase('basicdb')\n req.onsuccess = req.onerror = req.onblocked = () => resolve()\n })\n } catch {\n /* best effort */\n }\n }\n}\n\n/**\n * Get all available migrations\n */\nexport function getMigrations(): Migration[] {\n return [\n addMigrationTimestamp,\n dropLegacySyncDb\n ]\n}\n","/**\n * BasicClient — the framework-agnostic SDK core. Owns:\n * - AuthManager (OAuth/PKCE, tokens, cross-tab session)\n * - SyncEngine (Sync/2 client: local store, pending queue, WS connection)\n * - RestClient (REST v2: snapshot/changes bootstrap, shares, CRUD)\n *\n * and orchestrates them: sync connects when a healthy session exists, stops\n * on reauth_required, and tears down local data on sign-out (no page reload).\n * The React layer (`BasicProvider` + hooks) is a thin subscriber.\n */\nimport { AuthManager } from './auth/AuthManager'\nimport type { AuthStatus, GetTokenOptions, User } from './auth/AuthManager'\nimport { RestClient } from './http/RestClient'\nimport { SyncEngine, OWN_SUB, shareSubKey, type SyncStatus } from './sync/SyncEngine'\nimport type { RejectedRow } from './sync/SyncStore'\nimport type { Share } from './sync/protocol'\nimport { SyncDb, RestDb, type BasicDb } from './db'\nimport { BasicStorage, LocalStorageAdapter } from '../utils/storage'\nimport { validateAndCheckSchema } from '../utils/schema'\nimport { createVersionUpdater } from '../updater/versionUpdater'\nimport { getMigrations } from '../updater/updateMigrations'\nimport { log as debugLog } from '../config'\nimport { version as sdkVersion } from '../../package.json'\n\nexport type BasicMode = 'sync' | 'rest'\n\nexport interface BasicAuthConfig {\n scopes?: string | string[]\n /** PDS URL for auth, data, and sync (default https://pds.basic.id) */\n pds_url?: string\n /** Admin server URL for connect reporting + schema status (default https://api.basic.tech) */\n admin_url?: string\n /** Sync WebSocket URL. Default: pds_url with ws(s) scheme + `/sync/`. */\n sync_url?: string\n}\n\nexport interface BasicClientConfig {\n /** The Basic schema document (`{ project_id, version, tables }`). */\n schema?: Record<string, unknown> & {\n project_id?: string\n version?: number\n tables?: Record<string, unknown>\n }\n /** Project id override; normally taken from `schema.project_id`. */\n project_id?: string\n auth?: BasicAuthConfig\n storage?: BasicStorage\n debug?: boolean\n /** 'sync' (offline-first local replica, default) or 'rest' (direct API). */\n mode?: BasicMode\n /** Node/testing: pass the `ws` constructor. */\n WebSocketImpl?: typeof WebSocket\n}\n\n/** Local schema vs server status (dev toolbar and debugging). */\nexport interface BasicSchemaDevInfo {\n projectId: string | null\n localVersion: number | undefined\n status: string\n valid: boolean\n lastCheckedAt: number\n error?: string\n}\n\nexport interface BasicClientSnapshot {\n /** Auth bootstrap finished and (in sync mode) the local db is decided. */\n isReady: boolean\n isSignedIn: boolean\n authStatus: AuthStatus\n authErrorCode: string | null\n user: User | null\n did: string | null\n /** Space-separated scopes granted in the current access token. */\n scope: string | null\n syncStatus: SyncStatus\n pendingCount: number\n /** True when the schema allows sync (valid + published + matching server). */\n syncEnabled: boolean\n devInfo: BasicSchemaDevInfo | null\n mode: BasicMode\n}\n\nexport interface ShareMountHandle {\n shareId: string\n db: BasicDb\n}\n\nconst DEFAULTS = {\n scopes: 'profile,email,app:admin',\n pds_url: 'https://pds.basic.id',\n admin_url: 'https://api.basic.tech',\n} as const\n\nfunction deriveSyncUrl(pdsUrl: string): string {\n return pdsUrl.replace(/^http/, 'ws').replace(/\\/$/, '') + '/sync/'\n}\n\nexport class BasicClient {\n readonly auth: AuthManager\n readonly rest: RestClient\n readonly engine: SyncEngine | null\n readonly mode: BasicMode\n readonly config: BasicClientConfig\n readonly projectId: string | undefined\n\n private readonly syncDb: SyncDb | null\n private readonly restDb: RestDb\n private readonly debug: boolean\n\n private devInfo: BasicSchemaDevInfo | null = null\n private syncEnabled = false\n private schemaChecked = false\n private started = false\n private cleanupFns: Array<() => void> = []\n private mounts = new Map<string, ShareMountHandle>()\n\n private listeners = new Set<() => void>()\n private snapshot: BasicClientSnapshot\n\n constructor(config: BasicClientConfig) {\n this.config = config\n this.debug = config.debug ?? false\n this.mode = config.mode ?? 'sync'\n this.projectId = (config.schema?.project_id as string | undefined) || config.project_id\n\n const authConfig = {\n scopes: Array.isArray(config.auth?.scopes)\n ? config.auth!.scopes.join(' ')\n : config.auth?.scopes || DEFAULTS.scopes,\n pds_url: config.auth?.pds_url || DEFAULTS.pds_url,\n admin_url: config.auth?.admin_url || DEFAULTS.admin_url,\n }\n const syncUrl = config.auth?.sync_url || deriveSyncUrl(authConfig.pds_url)\n const storage = config.storage || new LocalStorageAdapter()\n\n this.auth = new AuthManager(\n {\n projectId: this.projectId,\n scopes: authConfig.scopes,\n pdsUrl: authConfig.pds_url,\n adminUrl: authConfig.admin_url,\n debug: this.debug,\n },\n storage,\n () => this.handleAuthChange(),\n )\n\n this.rest = new RestClient({\n baseUrl: authConfig.pds_url,\n projectId: this.projectId ?? '',\n getToken: (opts?: GetTokenOptions) => this.auth.getToken(opts),\n log: this.debug ? debugLog : undefined,\n })\n\n if (this.mode === 'sync' && this.projectId && this.config.schema?.tables) {\n this.engine = new SyncEngine({\n projectId: this.projectId,\n schema: this.config.schema as SyncEngine['schema'],\n wsUrl: syncUrl,\n getToken: (opts) => this.auth.getToken(opts),\n fetchSnapshot: (opts) => this.rest.getSnapshot(opts),\n WebSocketImpl: config.WebSocketImpl,\n log: debugLog,\n })\n this.syncDb = new SyncDb(this.engine, OWN_SUB)\n this.wireEngineEvents(this.engine)\n } else {\n this.engine = null\n this.syncDb = null\n }\n\n this.restDb = new RestDb(this.rest, this.config.schema as { tables?: Record<string, unknown> })\n this.snapshot = this.buildSnapshot()\n }\n\n // -------------------------------------------------------------------\n // Public surface\n // -------------------------------------------------------------------\n\n /** The database handle: offline-first in sync mode, direct API in rest mode. */\n get db(): BasicDb {\n if (this.mode === 'sync' && this.syncDb) return this.syncDb\n return this.restDb\n }\n\n /** Bootstrap: version migrations, schema check, auth initialization. */\n async start(): Promise<void> {\n if (this.started) return\n this.started = true\n\n try {\n const updater = createVersionUpdater(this.auth.storage, sdkVersion, getMigrations())\n const result = await updater.checkAndUpdate()\n if (result.updated) debugLog(`SDK storage migrated ${result.fromVersion} → ${result.toVersion}`)\n } catch (err) {\n debugLog('version updater failed:', err)\n }\n\n // schema gate + auth bootstrap run concurrently\n void this.checkSchema().then(() => this.maybeStartSync())\n await this.auth.initialize()\n const teardownNetwork = this.auth.setupNetworkListeners()\n this.cleanupFns.push(teardownNetwork)\n }\n\n /** Sign out: server-side revoke, local auth clear, sync teardown + purge. */\n async signOut(): Promise<void> {\n await this.auth.signOut()\n await this.teardownLocalData()\n }\n\n /** Stop connections and listeners; local data is kept. */\n stop(): void {\n this.started = false\n this.engine?.stop()\n for (const fn of this.cleanupFns) {\n try {\n fn()\n } catch {\n /* ignore */\n }\n }\n this.cleanupFns = []\n }\n\n /** Re-run the remote schema status check (dev toolbar). */\n async refreshSchemaStatus(): Promise<void> {\n this.schemaChecked = false\n await this.checkSchema()\n this.maybeStartSync()\n }\n\n async listRejected(): Promise<RejectedRow[]> {\n return this.engine?.listRejected() ?? []\n }\n\n async clearRejected(): Promise<void> {\n await this.engine?.clearRejected()\n this.publish()\n }\n\n // ---------------- shares ----------------\n\n /** Shares granted by / received by this user for this app. */\n async listShares(): Promise<{ granted: Share[]; received: Share[] }> {\n return this.rest.listShares()\n }\n\n /** Mount a share: separate local keyspace + subscription. */\n async mountShare(shareId: string): Promise<ShareMountHandle> {\n if (!this.engine) throw new Error('shares require sync mode')\n const existing = this.mounts.get(shareId)\n if (existing) return existing\n await this.engine.mountShare(shareId)\n const handle: ShareMountHandle = {\n shareId,\n db: new SyncDb(this.engine, shareSubKey(shareId)),\n }\n this.mounts.set(shareId, handle)\n this.publish()\n return handle\n }\n\n async unmountShare(shareId: string, options?: { purge?: boolean }): Promise<void> {\n if (!this.engine) return\n await this.engine.unmountShare(shareId, options)\n this.mounts.delete(shareId)\n this.publish()\n }\n\n getMountedShare(shareId: string): ShareMountHandle | undefined {\n return this.mounts.get(shareId)\n }\n\n // ---------------- React subscription surface ----------------\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n getSnapshot = (): BasicClientSnapshot => {\n return this.snapshot\n }\n\n // -------------------------------------------------------------------\n // Orchestration\n // -------------------------------------------------------------------\n\n private handleAuthChange(): void {\n const status = this.auth.authStatus\n if (status === 'reauth_required') {\n // token definitively invalid: stop syncing, keep local data\n this.engine?.stop()\n } else if (status === 'signed_out') {\n void this.teardownLocalData()\n } else {\n this.maybeStartSync()\n }\n this.publish()\n }\n\n private maybeStartSync(): void {\n if (!this.engine || !this.started) return\n if (!this.syncEnabled) return\n if (\n this.auth.isSignedIn &&\n this.auth.token &&\n this.auth.authStatus !== 'reauth_required'\n ) {\n void this.engine.start().catch((err) => debugLog('sync start failed:', err))\n }\n }\n\n private async teardownLocalData(): Promise<void> {\n this.mounts.clear()\n if (this.engine) {\n try {\n await this.engine.destroyLocal()\n } catch (err) {\n debugLog('local data teardown failed:', err)\n }\n }\n this.publish()\n }\n\n private wireEngineEvents(engine: SyncEngine): void {\n engine.on('status', () => this.publish())\n engine.on('change', () => this.publish())\n engine.on('rejected', ({ rejection }) => {\n debugLog('op rejected:', rejection.error, rejection.op)\n this.publish()\n })\n engine.on('revoked', ({ code, message }) => {\n // the app connection was revoked (user disconnected the app on\n // basic.id). Probe the session so auth state reflects reality.\n debugLog('connection revoked:', code, message)\n void this.auth\n .reconcileSession('connection revoked', { forceRefresh: true, throttleMs: 0 })\n .catch(() => {})\n this.publish()\n })\n }\n\n private async checkSchema(): Promise<void> {\n if (this.schemaChecked) return\n const schema = this.config.schema\n if (!schema) {\n this.devInfo = this.projectId\n ? {\n projectId: this.projectId,\n localVersion: undefined,\n status: 'no_schema',\n valid: false,\n lastCheckedAt: Date.now(),\n }\n : null\n this.syncEnabled = false\n this.publish()\n return\n }\n\n try {\n const result = await validateAndCheckSchema(schema)\n if (!result.isValid) {\n const errText =\n result.errors\n ?.map((e: { message?: string }) => e.message || '')\n .join('; ') || 'invalid'\n this.devInfo = {\n projectId: (schema.project_id as string) ?? null,\n localVersion: schema.version as number | undefined,\n status: 'invalid',\n valid: false,\n lastCheckedAt: Date.now(),\n error: errText,\n }\n this.syncEnabled = false\n } else {\n const status = result.schemaStatus.status ?? 'unknown'\n this.devInfo = {\n projectId: (schema.project_id as string) ?? null,\n localVersion: schema.version as number | undefined,\n status,\n valid: result.schemaStatus.valid,\n lastCheckedAt: Date.now(),\n }\n // Offline-first: only a *definitive* server verdict (behind / ahead /\n // conflict / unpublished) disables sync. A failed registry check\n // (offline, registry down) must not brick the app — the server\n // validates every op anyway.\n const locallyPublishable =\n typeof schema.version === 'number' && (schema.version as number) > 0\n const remoteCheckInconclusive = status === 'error' || status === 'unknown'\n this.syncEnabled =\n result.schemaStatus.valid || (remoteCheckInconclusive && locallyPublishable)\n if (!result.schemaStatus.valid) {\n if (status === 'unpublished') {\n debugLog('Schema not published (version 0) — sync is disabled until you publish.')\n } else if (remoteCheckInconclusive && locallyPublishable) {\n debugLog('Schema registry check failed — proceeding with the local schema (offline-first).')\n }\n }\n }\n } catch (err) {\n debugLog('schema check failed:', err)\n // network failure checking the registry must not brick offline usage:\n // a locally valid, published schema still allows sync\n this.syncEnabled = !!schema.version && (schema.version as number) > 0\n this.devInfo = {\n projectId: (schema.project_id as string) ?? null,\n localVersion: schema.version as number | undefined,\n status: 'unknown',\n valid: this.syncEnabled,\n lastCheckedAt: Date.now(),\n }\n }\n this.schemaChecked = true\n this.publish()\n }\n\n private buildSnapshot(): BasicClientSnapshot {\n return {\n isReady: this.auth.isAuthReady,\n isSignedIn: this.auth.isSignedIn,\n authStatus: this.auth.authStatus,\n authErrorCode: this.auth.authErrorCode,\n user: this.auth.user,\n did: this.auth.did,\n scope: this.auth.tokenScope,\n syncStatus: this.engine?.status ?? 'idle',\n pendingCount: this.engine?.pendingCount ?? 0,\n syncEnabled: this.syncEnabled,\n devInfo: this.devInfo,\n mode: this.mode,\n }\n }\n\n private publish(): void {\n this.snapshot = this.buildSnapshot()\n for (const listener of this.listeners) {\n try {\n listener()\n } catch {\n /* ignore */\n }\n }\n }\n}\n\nexport function createBasicClient(config: BasicClientConfig): BasicClient {\n return new BasicClient(config)\n}\n","// @basictech/react — Basic SDK for React, built on the Sync/2 protocol.\n\n// ---------------------------------------------------------------------------\n// React layer\n// ---------------------------------------------------------------------------\nexport { BasicProvider } from './react/BasicProvider'\nexport type { BasicProviderProps } from './react/BasicProvider'\nexport {\n useBasic,\n useAuth,\n useDb,\n useQuery,\n useSyncStatus,\n useShares,\n useShare,\n useBasicClient,\n} from './react/hooks'\nexport type {\n UseBasicResult,\n UseAuthResult,\n UseSyncStatusResult,\n UseSharesResult,\n UseShareResult,\n} from './react/hooks'\n\n// ---------------------------------------------------------------------------\n// Client core (framework-agnostic)\n// ---------------------------------------------------------------------------\nexport { BasicClient, createBasicClient } from './core/BasicClient'\nexport type {\n BasicClientConfig,\n BasicClientSnapshot,\n BasicAuthConfig,\n BasicMode,\n BasicSchemaDevInfo,\n ShareMountHandle,\n} from './core/BasicClient'\n\n// Database (table API)\nexport { SyncDb, RestDb } from './core/db'\nexport type { BasicDb, BasicTable, BasicRecord } from './core/db'\n\n// Auth\nexport { AuthManager } from './core/auth/AuthManager'\nexport type {\n Token,\n User,\n AuthResult,\n AuthStatus,\n GetTokenOptions,\n PdsEndpoints,\n} from './core/auth/AuthManager'\n\n// REST\nexport { RestClient, RestError, NotAuthenticatedError } from './core/http/RestClient'\nexport type { RestClientOptions, RestRecord } from './core/http/RestClient'\n\n// ---------------------------------------------------------------------------\n// Sync/2 protocol + engine (for advanced use and other runtimes)\n// ---------------------------------------------------------------------------\nexport { SyncEngine, SyncConnection, SyncStore, OWN_SUB, shareSubKey } from './core/sync'\nexport type {\n SyncStatus,\n SyncEngineOptions,\n SyncEngineEvents,\n SubscriptionState,\n ConnectionStatus,\n SyncStoreSchema,\n PendingRow,\n RejectedRow,\n} from './core/sync'\nexport {\n PROTOCOL_VERSION,\n DEFAULT_LIMITS,\n isTerminalOpError,\n isRebootstrapError,\n isRevocationError,\n isAuthError,\n mintOpId,\n applyOpToData,\n} from './core/sync/protocol'\nexport type {\n OpType,\n OpEnvelope,\n LoggedOp,\n SyncErrorCode,\n SyncLimits,\n Snapshot,\n ChangesPage,\n Share,\n ShareSelector,\n SharePermission,\n PushResult,\n} from './core/sync/protocol'\n\n// ---------------------------------------------------------------------------\n// Utilities\n// ---------------------------------------------------------------------------\nexport { STORAGE_KEYS, LocalStorageAdapter } from './utils/storage'\nexport type { BasicStorage } from './utils/storage'\nexport { resolveDid, resolveHandle, resolveDidWebUrl } from './utils/resolveDid'\nexport type { ResolvedDid } from './utils/resolveDid'\n\n// Dev tools\nexport { BasicDevToolbar } from './dev/BasicDevToolbar'\nexport type { BasicDevToolbarProps } from './dev/BasicDevToolbar'\n"],"mappings":"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","names":["version","useMemo","useState","useEffect","useSyncExternalStore","version","jsx","jsxs","BasicDevToolbar","useEffect","useSyncExternalStore"]}