lowdata 0.1.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.
- package/LICENSE +21 -0
- package/README.md +267 -0
- package/dist/client-BvdWSYIM.d.ts +187 -0
- package/dist/client-CqO3Y1J5.d.cts +187 -0
- package/dist/forms.cjs +1090 -0
- package/dist/forms.cjs.map +1 -0
- package/dist/forms.d.cts +29 -0
- package/dist/forms.d.ts +29 -0
- package/dist/forms.js +1088 -0
- package/dist/forms.js.map +1 -0
- package/dist/index.cjs +1109 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +1099 -0
- package/dist/index.js.map +1 -0
- package/dist/media.cjs +278 -0
- package/dist/media.cjs.map +1 -0
- package/dist/media.d.cts +35 -0
- package/dist/media.d.ts +35 -0
- package/dist/media.js +274 -0
- package/dist/media.js.map +1 -0
- package/dist/network.cjs +923 -0
- package/dist/network.cjs.map +1 -0
- package/dist/network.d.cts +46 -0
- package/dist/network.d.ts +46 -0
- package/dist/network.js +912 -0
- package/dist/network.js.map +1 -0
- package/dist/progressiveImage-BWNdewbi.d.cts +23 -0
- package/dist/progressiveImage-BhY_K8Dj.d.ts +23 -0
- package/dist/react.cjs +1195 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +33 -0
- package/dist/react.d.ts +33 -0
- package/dist/react.js +1190 -0
- package/dist/react.js.map +1 -0
- package/dist/retry-C3zL9T5Z.d.cts +22 -0
- package/dist/retry-D6DfKGOi.d.ts +22 -0
- package/dist/types--FRrBa-i.d.cts +39 -0
- package/dist/types--FRrBa-i.d.ts +39 -0
- package/dist/types-Bn1BAcch.d.ts +33 -0
- package/dist/types-CZDYS-fB.d.cts +33 -0
- package/package.json +97 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/events.ts","../src/core/id.ts","../src/core/connection.ts","../src/core/idb.ts","../src/network/errors.ts","../src/network/queue.ts","../src/core/backoff.ts","../src/core/abortAny.ts","../src/core/types.ts","../src/network/retry.ts","../src/core/lock.ts","../src/network/sync.ts","../src/network/client.ts","../src/network/types.ts","../src/forms/storage.ts","../src/forms/offlineForm.ts"],"names":["_a","STORE"],"mappings":"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","file":"forms.js","sourcesContent":["/** Tiny typed pub-sub. No Node `EventEmitter` dependency, works in any JS runtime. */\nexport class Emitter<T> {\n private listeners = new Set<(value: T) => void>();\n\n subscribe(listener: (value: T) => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n emit(value: T): void {\n for (const listener of this.listeners) {\n listener(value);\n }\n }\n\n clear(): void {\n this.listeners.clear();\n }\n\n get size(): number {\n return this.listeners.size;\n }\n}\n","/** Generate a reasonably unique id. Prefers `crypto.randomUUID`, falls back everywhere else. */\nexport function createId(): string {\n const g = globalThis as { crypto?: Crypto };\n if (g.crypto && typeof g.crypto.randomUUID === 'function') {\n return g.crypto.randomUUID();\n }\n return `ld_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n}\n","import { Emitter } from './events.js';\nimport type {\n ConnectionInfo,\n ConnectionListener,\n ConnectionQuality,\n Unsubscribe,\n} from './types.js';\n\n/**\n * The Network Information API (`navigator.connection`) is Chromium-only and not part of the\n * standard DOM lib types, hence this local shape instead of a global augmentation.\n */\ninterface NetworkInformationLike {\n effectiveType?: '4g' | '3g' | '2g' | 'slow-2g';\n downlink?: number;\n rtt?: number;\n saveData?: boolean;\n addEventListener?: (type: 'change', listener: () => void) => void;\n removeEventListener?: (type: 'change', listener: () => void) => void;\n}\n\ntype NavigatorWithConnection = Navigator & { connection?: NetworkInformationLike };\n\nexport interface ConnectionMonitorOptions {\n /**\n * Opt-in latency probe URL used to detect 'slow' connections on browsers without the Network\n * Information API (Safari, Firefox). Never probed automatically on a timer — only once on\n * startup and once per reconnect — because every probe costs a little data.\n */\n pingUrl?: string;\n /** Round-trip time above which the ping probe classifies the connection as 'slow'. Default 600ms. */\n slowRttThresholdMs?: number;\n /** downlink (Mbps) below which the Network Information API classifies as 'slow'. Default 0.5. */\n slowDownlinkMbps?: number;\n /** Timeout for the ping probe itself, in ms. Default 5000. */\n pingTimeoutMs?: number;\n}\n\nconst DEFAULT_SLOW_RTT_MS = 600;\nconst DEFAULT_SLOW_DOWNLINK_MBPS = 0.5;\nconst DEFAULT_PING_TIMEOUT_MS = 5000;\n\nfunction hasNavigator(): boolean {\n return typeof navigator !== 'undefined';\n}\n\n/**\n * Tracks connection quality (online / slow / offline) using the best signal available:\n * `navigator.onLine` + online/offline events as the universal baseline, `navigator.connection`\n * where present, and an optional opt-in ping probe as a cross-browser fallback for 'slow'.\n */\nexport class ConnectionMonitor {\n private emitter = new Emitter<ConnectionInfo>();\n private current: ConnectionInfo;\n private probedRttMs: number | undefined;\n private readonly options: Required<\n Pick<ConnectionMonitorOptions, 'slowRttThresholdMs' | 'slowDownlinkMbps' | 'pingTimeoutMs'>\n > &\n Pick<ConnectionMonitorOptions, 'pingUrl'>;\n private disposed = false;\n private onlineHandler?: () => void;\n private offlineHandler?: () => void;\n private connectionChangeHandler?: () => void;\n\n constructor(options: ConnectionMonitorOptions = {}) {\n this.options = {\n pingUrl: options.pingUrl,\n slowRttThresholdMs: options.slowRttThresholdMs ?? DEFAULT_SLOW_RTT_MS,\n slowDownlinkMbps: options.slowDownlinkMbps ?? DEFAULT_SLOW_DOWNLINK_MBPS,\n pingTimeoutMs: options.pingTimeoutMs ?? DEFAULT_PING_TIMEOUT_MS,\n };\n this.current = this.computeInfo();\n\n if (hasNavigator() && typeof window !== 'undefined') {\n this.onlineHandler = () => {\n this.refresh();\n void this.probeNow();\n };\n this.offlineHandler = () => this.refresh();\n window.addEventListener('online', this.onlineHandler);\n window.addEventListener('offline', this.offlineHandler);\n\n const conn = (navigator as NavigatorWithConnection).connection;\n if (conn?.addEventListener) {\n this.connectionChangeHandler = () => this.refresh();\n conn.addEventListener('change', this.connectionChangeHandler);\n }\n }\n\n if (this.options.pingUrl) {\n void this.probeNow();\n }\n }\n\n getStatus(): ConnectionInfo {\n return this.current;\n }\n\n subscribe(listener: ConnectionListener): Unsubscribe {\n return this.emitter.subscribe(listener);\n }\n\n /** Manually re-run the opt-in ping probe (no-op if no `pingUrl` was configured). */\n async probeNow(): Promise<ConnectionInfo> {\n if (!this.options.pingUrl || !hasNavigator() || navigator.onLine === false) {\n return this.current;\n }\n const start = Date.now();\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.options.pingTimeoutMs);\n try {\n await fetch(this.options.pingUrl, {\n method: 'HEAD',\n cache: 'no-store',\n signal: controller.signal,\n });\n this.probedRttMs = Date.now() - start;\n } catch {\n // A failed probe tells us nothing reliable about latency; leave prior measurement as-is.\n } finally {\n clearTimeout(timer);\n }\n return this.refresh();\n }\n\n destroy(): void {\n if (this.disposed) return;\n this.disposed = true;\n if (typeof window !== 'undefined') {\n if (this.onlineHandler) window.removeEventListener('online', this.onlineHandler);\n if (this.offlineHandler) window.removeEventListener('offline', this.offlineHandler);\n }\n if (hasNavigator() && this.connectionChangeHandler) {\n const conn = (navigator as NavigatorWithConnection).connection;\n conn?.removeEventListener?.('change', this.connectionChangeHandler);\n }\n this.emitter.clear();\n }\n\n private refresh(): ConnectionInfo {\n this.current = this.computeInfo();\n this.emitter.emit(this.current);\n return this.current;\n }\n\n private computeInfo(): ConnectionInfo {\n if (!hasNavigator()) {\n // Server/SSR context: assume the best case rather than block anything.\n return { quality: 'online', online: true };\n }\n\n const online = navigator.onLine !== false;\n if (!online) {\n return { quality: 'offline', online: false };\n }\n\n const conn = (navigator as NavigatorWithConnection).connection;\n if (conn) {\n const info: ConnectionInfo = {\n quality: 'online',\n online: true,\n effectiveType: conn.effectiveType,\n downlinkMbps: conn.downlink,\n rttMs: conn.rtt,\n saveData: conn.saveData,\n };\n const isSlow =\n conn.saveData === true ||\n conn.effectiveType === '2g' ||\n conn.effectiveType === 'slow-2g' ||\n (typeof conn.downlink === 'number' && conn.downlink < this.options.slowDownlinkMbps) ||\n (typeof conn.rtt === 'number' && conn.rtt > this.options.slowRttThresholdMs);\n return { ...info, quality: isSlow ? 'slow' : 'online' };\n }\n\n // No Network Information API: fall back to the opt-in ping probe measurement, if any.\n const quality: ConnectionQuality =\n typeof this.probedRttMs === 'number' && this.probedRttMs > this.options.slowRttThresholdMs\n ? 'slow'\n : 'online';\n return {\n quality,\n online: true,\n rttMs: this.probedRttMs,\n };\n }\n}\n\nlet sharedMonitor: ConnectionMonitor | undefined;\n\nfunction getSharedMonitor(): ConnectionMonitor {\n if (!sharedMonitor) sharedMonitor = new ConnectionMonitor();\n return sharedMonitor;\n}\n\n/** Convenience one-shot read of connection quality, without owning a `LowdataClient`. */\nexport function getConnectionQuality(): ConnectionInfo {\n return getSharedMonitor().getStatus();\n}\n\n/** Convenience subscription to connection changes, without owning a `LowdataClient`. */\nexport function onConnectionChange(listener: ConnectionListener): Unsubscribe {\n return getSharedMonitor().subscribe(listener);\n}\n","/**\n * Minimal promise-based IndexedDB wrapper. Deliberately small and hand-rolled (no `idb`\n * dependency) — lowdata only needs put/get/getAll/delete/clear against a handful of stores.\n */\n\nexport interface IdbIndexSpec {\n name: string;\n keyPath: string;\n unique?: boolean;\n}\n\nexport interface IdbStoreSpec {\n name: string;\n keyPath: string;\n indexes?: IdbIndexSpec[];\n}\n\nexport function isIndexedDbAvailable(): boolean {\n try {\n return typeof indexedDB !== 'undefined' && indexedDB !== null;\n } catch {\n return false;\n }\n}\n\nexport function openDatabase(\n name: string,\n version: number,\n stores: IdbStoreSpec[],\n): Promise<IDBDatabase> {\n if (!isIndexedDbAvailable()) {\n return Promise.reject(new Error('lowdata: IndexedDB is not available in this environment'));\n }\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(name, version);\n\n request.onupgradeneeded = () => {\n const db = request.result;\n for (const store of stores) {\n if (db.objectStoreNames.contains(store.name)) continue;\n const objectStore = db.createObjectStore(store.name, { keyPath: store.keyPath });\n for (const index of store.indexes ?? []) {\n objectStore.createIndex(index.name, index.keyPath, { unique: index.unique ?? false });\n }\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () =>\n reject(request.error ?? new Error('lowdata: failed to open IndexedDB database'));\n request.onblocked = () =>\n reject(new Error('lowdata: IndexedDB open blocked by another connection'));\n });\n}\n\nfunction wrapRequest<T>(request: IDBRequest<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error ?? new Error('lowdata: IndexedDB request failed'));\n });\n}\n\nfunction wrapTransaction(tx: IDBTransaction): Promise<void> {\n return new Promise((resolve, reject) => {\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error ?? new Error('lowdata: IndexedDB transaction failed'));\n tx.onabort = () => reject(tx.error ?? new Error('lowdata: IndexedDB transaction aborted'));\n });\n}\n\nexport async function idbPut<T>(db: IDBDatabase, storeName: string, value: T): Promise<void> {\n const tx = db.transaction(storeName, 'readwrite');\n tx.objectStore(storeName).put(value);\n await wrapTransaction(tx);\n}\n\nexport async function idbGet<T>(\n db: IDBDatabase,\n storeName: string,\n key: IDBValidKey,\n): Promise<T | undefined> {\n const tx = db.transaction(storeName, 'readonly');\n return wrapRequest<T>(tx.objectStore(storeName).get(key) as IDBRequest<T>);\n}\n\nexport async function idbDelete(\n db: IDBDatabase,\n storeName: string,\n key: IDBValidKey,\n): Promise<void> {\n const tx = db.transaction(storeName, 'readwrite');\n tx.objectStore(storeName).delete(key);\n await wrapTransaction(tx);\n}\n\nexport async function idbGetAll<T>(\n db: IDBDatabase,\n storeName: string,\n options?: { indexName?: string; query?: IDBValidKey | IDBKeyRange },\n): Promise<T[]> {\n const tx = db.transaction(storeName, 'readonly');\n const source = options?.indexName\n ? tx.objectStore(storeName).index(options.indexName)\n : tx.objectStore(storeName);\n return wrapRequest<T[]>(source.getAll(options?.query) as IDBRequest<T[]>);\n}\n\nexport async function idbClear(db: IDBDatabase, storeName: string): Promise<void> {\n const tx = db.transaction(storeName, 'readwrite');\n tx.objectStore(storeName).clear();\n await wrapTransaction(tx);\n}\n\nexport async function idbCount(db: IDBDatabase, storeName: string): Promise<number> {\n const tx = db.transaction(storeName, 'readonly');\n return wrapRequest<number>(tx.objectStore(storeName).count());\n}\n\n/** lowdata's shared database schema, opened once per store namespace (see `getSharedDb`). */\nexport const LOWDATA_DB_NAME = 'lowdata';\nexport const LOWDATA_DB_VERSION = 1;\n\nexport const LOWDATA_STORES: IdbStoreSpec[] = [\n {\n name: 'queue',\n keyPath: 'id',\n indexes: [\n { name: 'status', keyPath: 'status' },\n { name: 'priority', keyPath: 'priority' },\n { name: 'nextAttemptAt', keyPath: 'nextAttemptAt' },\n ],\n },\n { name: 'meta', keyPath: 'key' },\n {\n name: 'formDrafts',\n keyPath: 'submissionId',\n indexes: [{ name: 'formId', keyPath: 'formId' }],\n },\n];\n\nlet sharedDbPromise: Promise<IDBDatabase> | undefined;\n\n/** Lazily opens (and memoizes) the single shared lowdata database connection. */\nexport function getSharedDb(): Promise<IDBDatabase> {\n if (!sharedDbPromise) {\n sharedDbPromise = openDatabase(LOWDATA_DB_NAME, LOWDATA_DB_VERSION, LOWDATA_STORES).catch(\n (err) => {\n sharedDbPromise = undefined;\n throw err;\n },\n );\n }\n return sharedDbPromise;\n}\n\n/**\n * Test-only escape hatch to force a fresh connection between test cases. Closes the underlying\n * `IDBDatabase` connection (not just the cached promise) so a subsequent `indexedDB.deleteDatabase`\n * in test teardown completes instead of hanging in a \"blocked\" state waiting for this connection\n * to close.\n */\nexport async function _resetSharedDbForTests(): Promise<void> {\n const previous = sharedDbPromise;\n sharedDbPromise = undefined;\n if (!previous) return;\n try {\n const db = await previous;\n db.close();\n } catch {\n // Previous open attempt failed — nothing to close.\n }\n}\n\n/** Runs an operation against IndexedDB, or an in-memory fallback once IndexedDB has proven unavailable. */\nexport interface DbFallbackAccessor {\n run<T>(fn: (db: IDBDatabase) => Promise<T>, fallback: () => T): Promise<T>;\n isPersistent(): boolean;\n}\n\n/**\n * Shared \"try IndexedDB, permanently fall back to an in-memory implementation on first failure\"\n * policy, used by both the request queue and form draft storage. The fallback exists so importing\n * lowdata never throws in an environment without IndexedDB (SSR, locked-down browsers) — not to\n * promise durability there. Once a `getDb()` call has failed, every subsequent `run()` goes\n * straight to `fallback()` without retrying — an environment without IndexedDB isn't expected to\n * gain it mid-session.\n */\nexport function createDbFallbackAccessor(getDb: () => Promise<IDBDatabase>): DbFallbackAccessor {\n let dbAvailable = true;\n return {\n async run<T>(fn: (db: IDBDatabase) => Promise<T>, fallback: () => T): Promise<T> {\n if (!dbAvailable) return fallback();\n try {\n const db = await getDb();\n return await fn(db);\n } catch {\n dbAvailable = false;\n return fallback();\n }\n },\n isPersistent: () => dbAvailable,\n };\n}\n","import type { LowdataRequestError as LowdataRequestErrorShape } from '../core/types.js';\n\nexport class LowdataRequestError extends Error implements LowdataRequestErrorShape {\n status?: number;\n isNetworkError: boolean;\n isTimeout: boolean;\n attempt: number;\n retryAfterMs?: number;\n\n constructor(\n message: string,\n init: {\n status?: number;\n isNetworkError?: boolean;\n isTimeout?: boolean;\n attempt: number;\n retryAfterMs?: number;\n cause?: unknown;\n },\n ) {\n super(message, init.cause !== undefined ? { cause: init.cause } : undefined);\n this.name = 'LowdataRequestError';\n this.status = init.status;\n this.isNetworkError = init.isNetworkError ?? false;\n this.isTimeout = init.isTimeout ?? false;\n this.attempt = init.attempt;\n this.retryAfterMs = init.retryAfterMs;\n }\n}\n","import {\n createDbFallbackAccessor,\n idbClear,\n idbDelete,\n idbGet,\n idbGetAll,\n idbPut,\n} from '../core/idb.js';\nimport type { QueueItem, QueueItemStatus } from './types.js';\n\nconst STORE = 'queue';\n\nconst PRIORITY_ORDER: Record<QueueItem['priority'], number> = { high: 0, normal: 1, low: 2 };\n\nexport interface QueueListFilter {\n status?: QueueItemStatus;\n}\n\n/**\n * Persistent (IndexedDB-backed) request queue with an automatic in-memory fallback for\n * environments without IndexedDB (SSR, very old/locked-down browsers). The fallback is\n * non-persistent — it exists so importing lowdata never throws, not to promise durability there.\n */\nexport class RequestQueue {\n private memory = new Map<string, QueueItem>();\n private accessor;\n\n constructor(getDb: () => Promise<IDBDatabase>) {\n this.accessor = createDbFallbackAccessor(getDb);\n }\n\n isPersistent(): boolean {\n return this.accessor.isPersistent();\n }\n\n async add(item: QueueItem): Promise<QueueItem> {\n return this.accessor.run(\n async (db) => {\n await idbPut<QueueItem>(db, STORE, item);\n return item;\n },\n () => {\n this.memory.set(item.id, item);\n return item;\n },\n );\n }\n\n async update(item: QueueItem): Promise<void> {\n await this.accessor.run(\n async (db) => {\n await idbPut<QueueItem>(db, STORE, item);\n },\n () => {\n this.memory.set(item.id, item);\n },\n );\n }\n\n async get(id: string): Promise<QueueItem | undefined> {\n return this.accessor.run(\n (db) => idbGet<QueueItem>(db, STORE, id),\n () => this.memory.get(id),\n );\n }\n\n async remove(id: string): Promise<void> {\n await this.accessor.run(\n (db) => idbDelete(db, STORE, id),\n () => {\n this.memory.delete(id);\n },\n );\n }\n\n /** Filtering by status queries the `status` index rather than scanning the whole store. */\n async list(filter?: QueueListFilter): Promise<QueueItem[]> {\n if (filter?.status) {\n const status = filter.status;\n return this.accessor.run(\n (db) => idbGetAll<QueueItem>(db, STORE, { indexName: 'status', query: status }),\n () => Array.from(this.memory.values()).filter((item) => item.status === status),\n );\n }\n return this.accessor.run(\n (db) => idbGetAll<QueueItem>(db, STORE),\n () => Array.from(this.memory.values()),\n );\n }\n\n async clear(): Promise<void> {\n await this.accessor.run(\n (db) => idbClear(db, STORE),\n () => {\n this.memory.clear();\n },\n );\n }\n\n /** Items ready to send now: `pending` and due, sorted by priority then insertion order. */\n async selectEligible(now: number): Promise<QueueItem[]> {\n const pending = await this.list({ status: 'pending' });\n return pending\n .filter((item) => item.nextAttemptAt <= now)\n .sort((a, b) => {\n const byPriority = PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority];\n return byPriority !== 0 ? byPriority : a.createdAt - b.createdAt;\n });\n }\n\n /** Revive items stuck in `sending` longer than `staleAfterMs` (recovers from a crash mid-send). */\n async sweepStale(staleAfterMs: number, now: number): Promise<QueueItem[]> {\n const sending = await this.list({ status: 'sending' });\n const revived: QueueItem[] = [];\n for (const item of sending) {\n if (now - item.updatedAt > staleAfterMs) {\n const next: QueueItem = { ...item, status: 'pending', updatedAt: now };\n await this.update(next);\n revived.push(next);\n }\n }\n return revived;\n }\n}\n","import type { RetryBackoffConfig } from './types.js';\n\n/**\n * Exponential backoff with jitter.\n *\n * `attempt` is 0-indexed (0 = delay before the first retry, after the initial try failed).\n * Jitter strategies:\n * - 'full': Random(0, exp) — spreads retries the most, best for avoiding a\n * thundering herd when many clients reconnect at once.\n * - 'equal': exp/2 + Random(0, exp/2) — keeps delays closer to the exponential curve while\n * still avoiding perfect synchronization.\n * - 'none': exp — deterministic, useful mainly for tests.\n */\nexport function computeBackoffDelay(attempt: number, config: RetryBackoffConfig): number {\n const safeAttempt = Math.max(0, attempt);\n const exp = Math.min(config.maxDelayMs, config.baseDelayMs * 2 ** safeAttempt);\n\n switch (config.jitter) {\n case 'none':\n return exp;\n case 'equal':\n return exp / 2 + Math.random() * (exp / 2);\n case 'full':\n default:\n return Math.random() * exp;\n }\n}\n","/**\n * Combine multiple AbortSignals into one that aborts as soon as any input signal aborts.\n *\n * Hand-written because the build target (es2019) predates `AbortSignal.any()`, and this keeps\n * lowdata dependency-free rather than reaching for a polyfill.\n */\nexport function combineSignals(signals: Array<AbortSignal | undefined>): {\n signal: AbortSignal;\n dispose: () => void;\n} {\n const controller = new AbortController();\n const active = signals.filter((s): s is AbortSignal => Boolean(s));\n\n const onAbort = (source: AbortSignal) => () => {\n if (!controller.signal.aborted) {\n controller.abort(source.reason);\n }\n };\n\n const cleanups: Array<() => void> = [];\n for (const s of active) {\n if (s.aborted) {\n controller.abort(s.reason);\n break;\n }\n const handler = onAbort(s);\n s.addEventListener('abort', handler, { once: true });\n cleanups.push(() => s.removeEventListener('abort', handler));\n }\n\n return {\n signal: controller.signal,\n dispose: () => {\n for (const cleanup of cleanups) cleanup();\n },\n };\n}\n","/** Coarse connection quality bucket used throughout lowdata. */\nexport type ConnectionQuality = 'online' | 'slow' | 'offline';\n\n/** Snapshot of what lowdata currently knows about the network. */\nexport interface ConnectionInfo {\n quality: ConnectionQuality;\n online: boolean;\n /** Populated only where the Network Information API is available (Chromium browsers). */\n effectiveType?: '4g' | '3g' | '2g' | 'slow-2g';\n downlinkMbps?: number;\n rttMs?: number;\n saveData?: boolean;\n}\n\nexport type ConnectionListener = (info: ConnectionInfo) => void;\n/** Call to stop listening. */\nexport type Unsubscribe = () => void;\n\nexport type RequestPriority = 'high' | 'normal' | 'low';\n\nexport type JitterStrategy = 'full' | 'equal' | 'none';\n\nexport interface RetryBackoffConfig {\n /** Maximum number of retry attempts after the initial try. Default: 8. */\n maxRetries: number;\n /** Base delay in ms used by the exponential backoff formula. Default: 500. */\n baseDelayMs: number;\n /** Upper bound for any single computed delay, in ms. Default: 30_000. */\n maxDelayMs: number;\n /** Jitter strategy applied on top of the exponential delay. Default: 'full'. */\n jitter: JitterStrategy;\n /** Decide whether a failed attempt should be retried. Defaults to `defaultRetryOn`. */\n retryOn?: (error: LowdataRequestError, attempt: number) => boolean;\n}\n\n/** Error thrown/recorded for a failed request attempt, carrying retry-relevant metadata. */\nexport interface LowdataRequestError extends Error {\n status?: number;\n isNetworkError: boolean;\n isTimeout: boolean;\n attempt: number;\n retryAfterMs?: number;\n}\n\nexport const DEFAULT_RETRY_CONFIG: RetryBackoffConfig = {\n maxRetries: 8,\n baseDelayMs: 500,\n maxDelayMs: 30_000,\n jitter: 'full',\n};\n","import { computeBackoffDelay } from '../core/backoff.js';\nimport { combineSignals } from '../core/abortAny.js';\nimport { DEFAULT_RETRY_CONFIG, type RetryBackoffConfig } from '../core/types.js';\nimport { LowdataRequestError } from './errors.js';\n\nconst RETRYABLE_STATUS = new Set([429, 502, 503, 504]);\n\nexport function isRetryableStatus(status: number): boolean {\n return RETRYABLE_STATUS.has(status);\n}\n\n/** Default retry policy: retry network errors, timeouts, and 429/502/503/504; fail fast otherwise. */\nexport function defaultRetryOn(error: LowdataRequestError): boolean {\n if (error.isNetworkError || error.isTimeout) return true;\n return typeof error.status === 'number' && RETRYABLE_STATUS.has(error.status);\n}\n\nexport function parseRetryAfterMs(response: Response): number | undefined {\n const header = response.headers.get('Retry-After');\n if (!header) return undefined;\n const seconds = Number(header);\n if (!Number.isNaN(seconds)) return seconds * 1000;\n const dateMs = Date.parse(header);\n if (!Number.isNaN(dateMs)) return Math.max(0, dateMs - Date.now());\n return undefined;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason ?? new Error('lowdata: aborted'));\n return;\n }\n const timer = setTimeout(resolve, ms);\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer);\n reject(signal.reason ?? new Error('lowdata: aborted'));\n },\n { once: true },\n );\n });\n}\n\nexport interface AttemptWithRetryOptions {\n url: string;\n init?: RequestInit;\n retryConfig?: Partial<RetryBackoffConfig>;\n timeoutMs?: number;\n signal?: AbortSignal;\n /** Called after each failed attempt; returning `false` stops retrying immediately (e.g. connection dropped). */\n shouldContinue?: () => boolean;\n}\n\nexport const DEFAULT_TIMEOUT_MS = 15_000;\n\n/**\n * Perform a fetch with automatic retry + exponential backoff + jitter. Resolves with the\n * `Response` as soon as it's non-retryable (2xx..4xx outside the retryable set) — callers still\n * check `response.ok` themselves, matching native `fetch` semantics. Throws `LowdataRequestError`\n * only once retries are exhausted or `shouldContinue()` returns false.\n */\nexport async function attemptWithRetry(options: AttemptWithRetryOptions): Promise<Response> {\n const config: RetryBackoffConfig = { ...DEFAULT_RETRY_CONFIG, ...options.retryConfig };\n const retryOn = config.retryOn ?? defaultRetryOn;\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n let lastError: LowdataRequestError | undefined;\n\n for (let attempt = 0; attempt <= config.maxRetries; attempt++) {\n const timeoutController = new AbortController();\n const timer = setTimeout(() => timeoutController.abort(), timeoutMs);\n const combined = combineSignals([options.signal, timeoutController.signal]);\n\n try {\n const response = await fetch(options.url, { ...options.init, signal: combined.signal });\n clearTimeout(timer);\n combined.dispose();\n\n if (response.ok || !RETRYABLE_STATUS.has(response.status)) {\n return response;\n }\n\n lastError = new LowdataRequestError(`Request failed with status ${response.status}`, {\n status: response.status,\n attempt,\n retryAfterMs: parseRetryAfterMs(response),\n });\n } catch (cause) {\n clearTimeout(timer);\n combined.dispose();\n\n if (options.signal?.aborted) {\n // Caller explicitly cancelled — never retry, never fall back to queueing.\n throw cause;\n }\n\n const isTimeout = timeoutController.signal.aborted;\n lastError = new LowdataRequestError(\n isTimeout ? 'Request timed out' : 'Network request failed',\n { isNetworkError: !isTimeout, isTimeout, attempt, cause },\n );\n }\n\n const isLastAttempt = attempt === config.maxRetries;\n const continueRetrying = options.shouldContinue ? options.shouldContinue() : true;\n if (isLastAttempt || !continueRetrying || !retryOn(lastError, attempt)) {\n throw lastError;\n }\n\n const delay = lastError.retryAfterMs ?? computeBackoffDelay(attempt, config);\n await sleep(Math.min(delay, config.maxDelayMs), options.signal);\n }\n\n // Unreachable: the loop always returns or throws, but keeps TypeScript's control-flow happy.\n throw lastError ?? new LowdataRequestError('Request failed', { attempt: config.maxRetries });\n}\n","import { idbDelete, idbGet, idbPut } from './idb.js';\n\n/** How long an IndexedDB-fallback lock record is honored before it's considered stale/abandoned. */\nexport const LOCK_STALE_AFTER_MS = 15_000;\n\nexport interface SyncLockHandle {\n release: () => Promise<void>;\n /** Extend a fallback lock's stale-after window during a long-running critical section. No-op for Web Locks. */\n renew: () => Promise<void>;\n}\n\ninterface WebLockLike {\n name: string;\n}\ninterface LockManagerLike {\n request(\n name: string,\n options: { ifAvailable?: boolean },\n callback: (lock: WebLockLike | null) => Promise<void> | void,\n ): Promise<unknown>;\n}\n\nfunction getLockManager(): LockManagerLike | undefined {\n if (typeof navigator === 'undefined') return undefined;\n return (navigator as Navigator & { locks?: LockManagerLike }).locks;\n}\n\n/**\n * Acquire a named exclusive lock via the Web Locks API, non-blocking (`ifAvailable: true`):\n * resolves to `undefined` immediately if another tab already holds it rather than queueing.\n */\nfunction acquireWebLock(locks: LockManagerLike, name: string): Promise<SyncLockHandle | undefined> {\n return new Promise((resolveOuter) => {\n locks\n .request(name, { ifAvailable: true }, (lock) => {\n if (!lock) {\n resolveOuter(undefined);\n return;\n }\n return new Promise<void>((resolveInner) => {\n resolveOuter({\n release: async () => resolveInner(),\n renew: async () => {\n /* held exclusively for the lifetime of the callback; nothing to renew */\n },\n });\n });\n })\n .catch(() => resolveOuter(undefined));\n });\n}\n\ninterface SyncLockRecord {\n key: string;\n ownerId: string;\n expiresAt: number;\n}\n\nasync function acquireIdbLock(\n db: IDBDatabase,\n name: string,\n ownerId: string,\n): Promise<SyncLockHandle | undefined> {\n const key = `syncLock:${name}`;\n const now = Date.now();\n const existing = await idbGet<SyncLockRecord>(db, 'meta', key);\n if (existing && existing.expiresAt > now && existing.ownerId !== ownerId) {\n return undefined;\n }\n await idbPut<SyncLockRecord>(db, 'meta', { key, ownerId, expiresAt: now + LOCK_STALE_AFTER_MS });\n return {\n release: async () => {\n const current = await idbGet<SyncLockRecord>(db, 'meta', key);\n if (current?.ownerId === ownerId) {\n await idbDelete(db, 'meta', key);\n }\n },\n renew: async () => {\n await idbPut<SyncLockRecord>(db, 'meta', {\n key,\n ownerId,\n expiresAt: Date.now() + LOCK_STALE_AFTER_MS,\n });\n },\n };\n}\n\n/**\n * Acquire a cross-tab exclusive lock, preferring the Web Locks API where available (correct by\n * construction, no staleness window) and falling back to an IndexedDB record (stale after\n * `LOCK_STALE_AFTER_MS`) elsewhere. Returns `undefined` if the lock could not be acquired.\n */\nexport async function acquireSyncLock(\n db: IDBDatabase | undefined,\n name: string,\n ownerId: string,\n): Promise<SyncLockHandle | undefined> {\n const locks = getLockManager();\n if (locks) {\n return acquireWebLock(locks, name);\n }\n if (!db) return undefined;\n return acquireIdbLock(db, name, ownerId);\n}\n","import { computeBackoffDelay } from '../core/backoff.js';\nimport { createId } from '../core/id.js';\nimport { acquireSyncLock } from '../core/lock.js';\nimport { DEFAULT_RETRY_CONFIG, type RetryBackoffConfig } from '../core/types.js';\nimport type { ConnectionMonitor } from '../core/connection.js';\nimport { LowdataRequestError } from './errors.js';\nimport {\n DEFAULT_TIMEOUT_MS,\n defaultRetryOn,\n isRetryableStatus,\n parseRetryAfterMs,\n} from './retry.js';\nimport type { RequestQueue } from './queue.js';\nimport type { QueueItem, SyncEvent } from './types.js';\n\n/** Items stuck in `sending` longer than this are assumed crashed and revived to `pending`. */\nconst STALE_SENDING_MS = 60_000;\n/** Safety poll interval — covers reconnects the `online` event misses (e.g. laptop sleep/wake). */\nconst SAFETY_POLL_MS = 30_000;\nconst SYNC_LOCK_NAME = 'lowdata-sync';\n\n/** Sentinel abort reason distinguishing an explicit `queue.cancel()` from a timeout/network drop. */\nconst CANCELLED = Symbol('lowdata-cancelled');\n\nexport interface SyncManagerOptions {\n queue: RequestQueue;\n connection: ConnectionMonitor;\n getDb: () => Promise<IDBDatabase>;\n retryConfig?: Partial<RetryBackoffConfig>;\n /** How many queued items to send concurrently. Default 1 — deliberately conservative on 2G. */\n syncConcurrency?: number;\n onEvent?: (event: SyncEvent) => void;\n}\n\n/**\n * Drives the offline queue: drains eligible items when the connection is up, retries failed\n * ones with backoff across drain cycles (so retries survive reloads), and prevents two open tabs\n * from double-sending the same item via a cross-tab lock.\n */\nexport class SyncManager {\n private readonly ownerId = createId();\n private readonly retryConfig: RetryBackoffConfig;\n private readonly syncConcurrency: number;\n private inFlight = new Map<string, AbortController>();\n private draining = false;\n private disposed = false;\n private unsubscribeConnection: () => void;\n private safetyTimer?: ReturnType<typeof setInterval>;\n\n constructor(private opts: SyncManagerOptions) {\n this.retryConfig = { ...DEFAULT_RETRY_CONFIG, ...opts.retryConfig };\n this.syncConcurrency = Math.max(1, opts.syncConcurrency ?? 1);\n\n this.unsubscribeConnection = this.opts.connection.subscribe((info) => {\n if (info.quality !== 'offline') void this.drain();\n });\n\n if (typeof document !== 'undefined' && typeof setInterval !== 'undefined') {\n this.safetyTimer = setInterval(() => {\n if (document.visibilityState === 'visible') void this.drain();\n }, SAFETY_POLL_MS);\n }\n }\n\n /** Call after enqueueing a new item so a high-priority item is picked up without waiting for the next trigger. */\n notifyEnqueued(): void {\n if (this.opts.connection.getStatus().quality !== 'offline') void this.drain();\n }\n\n cancel(id: string): void {\n this.inFlight.get(id)?.abort(CANCELLED);\n this.inFlight.delete(id);\n }\n\n /**\n * Never throws/rejects — `drain()` is always invoked fire-and-forget (`void this.drain()`) from\n * event listeners, so any failure here (e.g. the shared IndexedDB connection was closed\n * mid-drain) is swallowed rather than surfacing as an unhandled rejection; the next reconnect\n * or safety poll simply tries again.\n */\n async drain(): Promise<void> {\n if (this.draining || this.disposed) return;\n if (this.opts.connection.getStatus().quality === 'offline') return;\n\n // Set synchronously, before any `await`, so two drain() calls issued in the same tick (e.g.\n // two client.fetch() calls both calling notifyEnqueued()) can't both pass the guard above\n // before either sets it — otherwise both could go on to acquire the lock and, on the\n // IndexedDB fallback lock (a non-atomic get-then-put, unlike the atomic Web Locks API), both\n // could believe they hold it and send the same item twice.\n this.draining = true;\n try {\n const db = await this.opts.getDb().catch(() => undefined);\n const lock = await acquireSyncLock(db, SYNC_LOCK_NAME, this.ownerId);\n if (!lock) return; // another tab is already draining, or no lock could be acquired this cycle\n\n let succeeded = 0;\n let failed = 0;\n try {\n await this.opts.queue.sweepStale(STALE_SENDING_MS, Date.now());\n\n const initialEligible = await this.opts.queue.selectEligible(Date.now());\n if (initialEligible.length === 0) return;\n this.opts.onEvent?.({ type: 'sync-start', pending: initialEligible.length });\n\n while (!this.disposed && this.opts.connection.getStatus().quality !== 'offline') {\n const eligible = await this.opts.queue.selectEligible(Date.now());\n if (eligible.length === 0) break;\n\n const batch = eligible.slice(0, this.syncConcurrency);\n const results = await Promise.all(batch.map((item) => this.sendItem(item)));\n succeeded += results.filter(Boolean).length;\n failed += results.filter((ok) => !ok).length;\n }\n\n this.opts.onEvent?.({ type: 'sync-complete', succeeded, failed });\n } finally {\n await lock.release().catch(() => {});\n }\n } catch {\n // swallow — see doc comment above\n } finally {\n this.draining = false;\n }\n }\n\n destroy(): void {\n this.disposed = true;\n this.unsubscribeConnection();\n if (this.safetyTimer) clearInterval(this.safetyTimer);\n for (const controller of this.inFlight.values()) controller.abort(CANCELLED);\n this.inFlight.clear();\n }\n\n private async sendItem(item: QueueItem): Promise<boolean> {\n const controller = new AbortController();\n this.inFlight.set(item.id, controller);\n const timeoutMs = item.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n const sendingItem: QueueItem = { ...item, status: 'sending', updatedAt: Date.now() };\n await this.opts.queue.update(sendingItem);\n this.opts.onEvent?.({ type: 'item-start', item: sendingItem });\n\n const retryConfig: RetryBackoffConfig = { ...this.retryConfig, ...item.retry };\n const retryOn = retryConfig.retryOn ?? defaultRetryOn;\n\n let requestError: LowdataRequestError | undefined;\n try {\n const response = await fetch(item.url, {\n method: item.method,\n headers: item.headers,\n body: item.body ?? undefined,\n signal: controller.signal,\n });\n if (response.ok || !isRetryableStatus(response.status)) {\n const doneItem: QueueItem = { ...sendingItem, status: 'done', updatedAt: Date.now() };\n // Terminal and successful — nothing more to do with it, so purge rather than let a\n // long-lived app's queue store grow forever. The event still carries the final item for\n // any subscriber that wants to build its own history.\n await this.opts.queue.remove(doneItem.id);\n this.opts.onEvent?.({ type: 'item-success', item: doneItem });\n return true;\n }\n requestError = new LowdataRequestError(`Request failed with status ${response.status}`, {\n status: response.status,\n attempt: item.attempts,\n retryAfterMs: parseRetryAfterMs(response),\n });\n } catch (cause) {\n if (controller.signal.reason === CANCELLED) {\n const cancelledItem: QueueItem = {\n ...sendingItem,\n status: 'cancelled',\n updatedAt: Date.now(),\n };\n await this.opts.queue.update(cancelledItem);\n this.opts.onEvent?.({ type: 'item-failed', item: cancelledItem, willRetry: false });\n return false;\n }\n const isTimeout = controller.signal.aborted && controller.signal.reason !== CANCELLED;\n requestError = new LowdataRequestError(\n isTimeout ? 'Request timed out' : 'Network request failed',\n { isNetworkError: !isTimeout, isTimeout, attempt: item.attempts, cause },\n );\n } finally {\n clearTimeout(timer);\n this.inFlight.delete(item.id);\n }\n\n const attempts = item.attempts + 1;\n const willRetry = attempts <= retryConfig.maxRetries && retryOn(requestError, item.attempts);\n // Capped the same way the live-retry path (retry.ts) caps it, so a server's Retry-After is\n // honored consistently regardless of whether the request started live or queued from the start.\n const rawDelay = requestError.retryAfterMs ?? computeBackoffDelay(item.attempts, retryConfig);\n const nextAttemptAt = willRetry\n ? Date.now() + Math.min(rawDelay, retryConfig.maxDelayMs)\n : sendingItem.nextAttemptAt;\n const resultItem: QueueItem = {\n ...sendingItem,\n attempts,\n status: willRetry ? 'pending' : 'failed',\n nextAttemptAt,\n lastError: requestError.message,\n updatedAt: Date.now(),\n };\n await this.opts.queue.update(resultItem);\n this.opts.onEvent?.({ type: 'item-failed', item: resultItem, willRetry });\n return false;\n }\n}\n","import { ConnectionMonitor } from '../core/connection.js';\nimport { Emitter } from '../core/events.js';\nimport { createId } from '../core/id.js';\nimport { getSharedDb } from '../core/idb.js';\nimport type { ConnectionInfo, ConnectionListener, Unsubscribe } from '../core/types.js';\nimport { LowdataRequestError } from './errors.js';\nimport { RequestQueue, type QueueListFilter } from './queue.js';\nimport { attemptWithRetry } from './retry.js';\nimport { SyncManager } from './sync.js';\nimport type {\n EnqueueOptions,\n HttpMethod,\n LowdataClientConfig,\n QueueItem,\n QueuedResult,\n SyncEvent,\n} from './types.js';\n\nconst DEFAULT_MAX_QUEUE_ITEM_BYTES = 5 * 1024 * 1024; // 5 MB\nconst MUTATING_METHODS = new Set<HttpMethod>(['POST', 'PUT', 'PATCH', 'DELETE']);\n\nfunction defaultShouldQueueOffline({ method }: { url: string; method: HttpMethod }): boolean {\n return MUTATING_METHODS.has(method);\n}\n\nfunction normalizeHeaders(headers?: HeadersInit): Record<string, string> | undefined {\n if (!headers) return undefined;\n if (headers instanceof Headers) {\n const out: Record<string, string> = {};\n headers.forEach((value, key) => {\n out[key] = value;\n });\n return out;\n }\n if (Array.isArray(headers)) return Object.fromEntries(headers);\n return { ...headers };\n}\n\n/** Only string/Blob bodies can be durably queued; other BodyInit shapes fail loudly, not silently. */\nfunction normalizeQueueableBody(body: string | Blob | null | undefined): string | Blob | null {\n if (body == null) return null;\n if (typeof body === 'string' || body instanceof Blob) return body;\n throw new TypeError(\n 'lowdata: only string or Blob request bodies can be queued for offline delivery. ' +\n 'Serialize your payload (e.g. JSON.stringify) or pass a Blob/File before queuing.',\n );\n}\n\nfunction bodySizeBytes(body: string | Blob | null): number {\n if (body === null) return 0;\n return typeof body === 'string' ? new Blob([body]).size : body.size;\n}\n\nexport class LowdataClient {\n readonly connection: {\n getStatus: () => ConnectionInfo;\n subscribe: (listener: ConnectionListener) => Unsubscribe;\n };\n readonly queue: {\n add: (\n item: Omit<\n QueueItem,\n 'id' | 'createdAt' | 'updatedAt' | 'attempts' | 'status' | 'nextAttemptAt'\n >,\n ) => Promise<QueueItem>;\n cancel: (id: string) => Promise<void>;\n list: (filter?: QueueListFilter) => Promise<QueueItem[]>;\n clear: () => Promise<void>;\n };\n\n private monitor: ConnectionMonitor;\n private requestQueue: RequestQueue;\n private syncManager: SyncManager;\n private syncEmitter = new Emitter<SyncEvent>();\n private destroyed = false;\n\n constructor(private config: LowdataClientConfig = {}) {\n this.monitor = new ConnectionMonitor(config.connection);\n this.requestQueue = new RequestQueue(() => getSharedDb());\n this.syncManager = new SyncManager({\n queue: this.requestQueue,\n connection: this.monitor,\n getDb: () => getSharedDb(),\n retryConfig: config.retry,\n syncConcurrency: config.syncConcurrency,\n onEvent: (event) => this.syncEmitter.emit(event),\n });\n\n this.connection = {\n getStatus: () => this.monitor.getStatus(),\n subscribe: (listener) => this.monitor.subscribe(listener),\n };\n this.queue = {\n add: (item) => this.enqueue(item),\n cancel: (id) => this.cancelQueued(id),\n list: (filter) => this.requestQueue.list(filter),\n clear: () => this.requestQueue.clear(),\n };\n }\n\n onSync(listener: (event: SyncEvent) => void): Unsubscribe {\n return this.syncEmitter.subscribe(listener);\n }\n\n /**\n * Drop-in `fetch()` wrapper: retries transient failures with backoff, and — for mutating\n * requests that still can't get through — falls back to the persistent offline queue instead\n * of losing the request. Returns a `QueuedResult` (check with `isQueued()`) when queued.\n */\n async fetch(\n url: string,\n init: RequestInit & EnqueueOptions = {},\n ): Promise<Response | QueuedResult> {\n if (this.destroyed) throw new Error('lowdata: this client has been destroyed');\n\n const fullUrl = this.resolveUrl(url);\n const method = (init.method ?? 'GET').toUpperCase() as HttpMethod;\n const shouldQueueOffline = this.config.shouldQueueOffline ?? defaultShouldQueueOffline;\n const canQueue = shouldQueueOffline({ url: fullUrl, method });\n const isOffline = this.monitor.getStatus().quality === 'offline';\n\n if ((init.forceQueue || isOffline) && canQueue) {\n return this.enqueueFromInit(fullUrl, method, init);\n }\n if (init.forceQueue || isOffline) {\n // Not queueable (e.g. a GET) and we're offline — surface a clear network error instead of\n // silently attempting (and failing) a doomed fetch.\n throw new LowdataRequestError('Offline and this request is not configured to be queued', {\n isNetworkError: true,\n attempt: 0,\n });\n }\n\n try {\n return await attemptWithRetry({\n url: fullUrl,\n init: {\n ...init,\n headers: { ...this.config.defaultHeaders, ...normalizeHeaders(init.headers) },\n },\n retryConfig: { ...this.config.retry, ...init.retry },\n timeoutMs: init.timeoutMs,\n signal: init.signal ?? undefined,\n shouldContinue: () => this.monitor.getStatus().quality !== 'offline',\n });\n } catch (err) {\n if (init.signal?.aborted) throw err; // explicit cancellation — never silently queue\n if (canQueue) {\n return this.enqueueFromInit(fullUrl, method, init);\n }\n throw err;\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.syncManager.destroy();\n this.monitor.destroy();\n this.syncEmitter.clear();\n }\n\n private resolveUrl(url: string): string {\n if (!this.config.baseUrl || /^[a-z][a-z0-9+.-]*:\\/\\//i.test(url)) return url;\n return `${this.config.baseUrl.replace(/\\/$/, '')}/${url.replace(/^\\//, '')}`;\n }\n\n private maxQueueItemBytes(): number {\n return this.config.maxQueueItemSizeBytes ?? DEFAULT_MAX_QUEUE_ITEM_BYTES;\n }\n\n private assertWithinSizeBudget(body: string | Blob | null): void {\n const size = bodySizeBytes(body);\n const max = this.maxQueueItemBytes();\n if (size > max) {\n throw new RangeError(\n `lowdata: request body (${size} bytes) exceeds maxQueueItemSizeBytes (${max} bytes).`,\n );\n }\n }\n\n /**\n * Shared by `enqueueFromInit` (the `fetch()` fallback path) and `enqueue` (the direct\n * `queue.add()` path) — the only difference between the two call sites is where the fields come\n * from, not how a queue item gets constructed, persisted, and announced to the sync manager.\n */\n private async persistNewQueueItem(\n fields: Omit<\n QueueItem,\n 'id' | 'createdAt' | 'updatedAt' | 'attempts' | 'status' | 'nextAttemptAt'\n >,\n ): Promise<QueueItem> {\n const body = normalizeQueueableBody(fields.body);\n this.assertWithinSizeBudget(body);\n\n const now = Date.now();\n const item: QueueItem = {\n ...fields,\n body,\n id: createId(),\n createdAt: now,\n updatedAt: now,\n attempts: 0,\n status: 'pending',\n nextAttemptAt: now,\n };\n const saved = await this.requestQueue.add(item);\n this.syncManager.notifyEnqueued();\n return saved;\n }\n\n private async enqueueFromInit(\n url: string,\n method: HttpMethod,\n init: RequestInit & EnqueueOptions,\n ): Promise<QueuedResult> {\n const saved = await this.persistNewQueueItem({\n url,\n method,\n headers: { ...this.config.defaultHeaders, ...normalizeHeaders(init.headers) },\n body: init.body as string | Blob | null | undefined,\n priority: init.priority ?? 'normal',\n meta: init.meta,\n timeoutMs: init.timeoutMs,\n retry: init.retry,\n idempotencyKey: init.idempotencyKey,\n });\n return { queued: true, id: saved.id, item: saved };\n }\n\n private async enqueue(\n partial: Omit<\n QueueItem,\n 'id' | 'createdAt' | 'updatedAt' | 'attempts' | 'status' | 'nextAttemptAt'\n >,\n ): Promise<QueueItem> {\n return this.persistNewQueueItem(partial);\n }\n\n private async cancelQueued(id: string): Promise<void> {\n this.syncManager.cancel(id);\n const item = await this.requestQueue.get(id);\n if (item && item.status !== 'done' && item.status !== 'cancelled') {\n await this.requestQueue.update({ ...item, status: 'cancelled', updatedAt: Date.now() });\n }\n }\n}\n\nexport function createLowdataClient(config?: LowdataClientConfig): LowdataClient {\n return new LowdataClient(config);\n}\n","import type { ConnectionMonitorOptions } from '../core/connection.js';\nimport type { RequestPriority, RetryBackoffConfig } from '../core/types.js';\n\nexport type QueueItemStatus = 'pending' | 'sending' | 'failed' | 'done' | 'cancelled';\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\nexport interface QueueItem {\n id: string;\n url: string;\n method: HttpMethod;\n headers?: Record<string, string>;\n body?: string | Blob | null;\n priority: RequestPriority;\n createdAt: number;\n updatedAt: number;\n attempts: number;\n status: QueueItemStatus;\n nextAttemptAt: number;\n lastError?: string;\n meta?: Record<string, unknown>;\n timeoutMs?: number;\n retry?: Partial<RetryBackoffConfig>;\n idempotencyKey?: string;\n}\n\nexport interface EnqueueOptions {\n priority?: RequestPriority;\n meta?: Record<string, unknown>;\n timeoutMs?: number;\n retry?: Partial<RetryBackoffConfig>;\n idempotencyKey?: string;\n /** Skip the live attempt and go straight to the persistent queue, even if currently online. */\n forceQueue?: boolean;\n}\n\n/** Result returned by `client.fetch()` when a request could not be sent live and was queued instead. */\nexport interface QueuedResult {\n queued: true;\n id: string;\n item: QueueItem;\n}\n\nexport function isQueued(result: Response | QueuedResult): result is QueuedResult {\n return typeof result === 'object' && result !== null && (result as QueuedResult).queued === true;\n}\n\nexport type SyncEvent =\n | { type: 'sync-start'; pending: number }\n | { type: 'item-start'; item: QueueItem }\n | { type: 'item-success'; item: QueueItem }\n | { type: 'item-failed'; item: QueueItem; willRetry: boolean }\n | { type: 'sync-complete'; succeeded: number; failed: number };\n\nexport interface LowdataClientConfig {\n /** Prefixed onto every relative URL passed to `fetch()`/`queue.add()`. */\n baseUrl?: string;\n defaultHeaders?: Record<string, string>;\n retry?: Partial<RetryBackoffConfig>;\n connection?: ConnectionMonitorOptions;\n /** How many queued items to send concurrently during a sync drain. Default 1 (conservative). */\n syncConcurrency?: number;\n /** Reject `queue.add()` for payloads larger than this. Default 5 MB. */\n maxQueueItemSizeBytes?: number;\n /**\n * Decide whether a failed/offline request should be queued for later instead of surfaced as an\n * error. Default: only mutating methods (POST/PUT/PATCH/DELETE) are queued; GET/HEAD are not,\n * since queuing a read rarely makes sense.\n */\n shouldQueueOffline?: (input: { url: string; method: HttpMethod }) => boolean;\n}\n","import { createDbFallbackAccessor, getSharedDb, idbDelete, idbGet, idbPut } from '../core/idb.js';\nimport type { FormRecord } from './types.js';\n\nconst STORE = 'formDrafts';\n\nfunction draftKey(formId: string): string {\n return `draft:${formId}`;\n}\n\nconst memory = new Map<string, FormRecord<unknown>>();\nconst accessor = createDbFallbackAccessor(getSharedDb);\n\n/** Autosave-before-send: the recoverable \"currently being typed\" draft for a form, one per formId. */\nexport async function saveDraft<T>(formId: string, values: T): Promise<FormRecord<T>> {\n const key = draftKey(formId);\n const now = Date.now();\n const existing = await getSubmission<T>(key);\n const record: FormRecord<T> = {\n submissionId: key,\n formId,\n kind: 'draft',\n values,\n status: 'saved',\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n };\n await saveSubmission(record);\n return record;\n}\n\nexport async function loadDraft<T>(formId: string): Promise<FormRecord<T> | undefined> {\n return getSubmission<T>(draftKey(formId));\n}\n\nexport async function discardDraft(formId: string): Promise<void> {\n const key = draftKey(formId);\n await accessor.run(\n (db) => idbDelete(db, STORE, key),\n () => {\n memory.delete(key);\n },\n );\n}\n\nexport async function saveSubmission<T>(record: FormRecord<T>): Promise<void> {\n await accessor.run(\n (db) => idbPut<FormRecord<T>>(db, STORE, record),\n () => {\n memory.set(record.submissionId, record as FormRecord<unknown>);\n },\n );\n}\n\nexport async function getSubmission<T>(submissionId: string): Promise<FormRecord<T> | undefined> {\n return accessor.run(\n (db) => idbGet<FormRecord<T>>(db, STORE, submissionId),\n () => memory.get(submissionId) as FormRecord<T> | undefined,\n );\n}\n","import { Emitter } from '../core/events.js';\nimport { createId } from '../core/id.js';\nimport type { Unsubscribe } from '../core/types.js';\nimport { createLowdataClient, type LowdataClient } from '../network/client.js';\nimport { isQueued } from '../network/types.js';\nimport { discardDraft, getSubmission, loadDraft, saveDraft, saveSubmission } from './storage.js';\nimport type { FormRecord, FormStatus, FormSubmissionDetail, OfflineFormConfig } from './types.js';\n\nexport interface OfflineForm<T = Record<string, unknown>> {\n /** Persist values locally without submitting — the safety net against reload wiping input. */\n save(values: T): Promise<void>;\n /** Save, then attempt delivery now (live) or queue it for automatic sync when back online. */\n submit(values: T): Promise<{ status: FormStatus }>;\n /** Re-attempt the last submission (only meaningful after `status` is `'failed'`). */\n retry(): Promise<void>;\n getStatus(): FormStatus;\n subscribe(callback: (status: FormStatus, detail?: FormSubmissionDetail) => void): Unsubscribe;\n /** Clear the saved draft/submission record and reset to `'idle'`. */\n discard(): Promise<void>;\n /**\n * Stop listening for this form's sync events. `submit()` subscribes to the client's `onSync`\n * stream lazily on first use and never unsubscribes on its own — call `destroy()` when the form\n * is no longer needed (e.g. on unmount, or before creating a replacement instance for the same\n * id) to avoid leaking that subscription on a long-lived shared/default client.\n */\n destroy(): void;\n}\n\nlet defaultClient: LowdataClient | undefined;\nfunction getDefaultClient(): LowdataClient {\n if (!defaultClient) defaultClient = createLowdataClient();\n return defaultClient;\n}\n\nexport function createOfflineForm<T = Record<string, unknown>>(\n config: OfflineFormConfig<T>,\n): OfflineForm<T> {\n const client = config.client ?? getDefaultClient();\n const emitter = new Emitter<{ status: FormStatus; detail?: FormSubmissionDetail }>();\n\n let status: FormStatus = 'idle';\n let lastValues: T | undefined;\n let activeSubmissionId: string | undefined;\n let unsubscribeSync: Unsubscribe | undefined;\n\n // Recover any draft left over from a previous session (e.g. the page reloaded mid-type).\n void loadDraft<T>(config.id).then((draft) => {\n if (draft && status === 'idle') {\n lastValues = draft.values;\n setStatus('saved');\n }\n });\n\n function setStatus(next: FormStatus, detail?: FormSubmissionDetail): void {\n status = next;\n config.onStatusChange?.(next, detail);\n emitter.emit({ status: next, detail });\n }\n\n async function patchSubmission(\n submissionId: string,\n patch: Partial<FormRecord<T>>,\n ): Promise<void> {\n const existing = await getSubmission<T>(submissionId);\n if (!existing) return;\n await saveSubmission<T>({ ...existing, ...patch, updatedAt: Date.now() });\n }\n\n async function onSubmissionSettled(\n submissionId: string,\n next: 'success' | 'failed',\n error?: string,\n ): Promise<void> {\n await patchSubmission(submissionId, { status: next, lastError: error });\n // Guard against a stale/superseded submission (e.g. submit() was called again before this one\n // settled) discarding the draft for whatever the CURRENT submission holds — only the active\n // submission's success should clear the recoverable draft.\n const isActive = submissionId === activeSubmissionId;\n if (next === 'success' && isActive) {\n await discardDraft(config.id);\n }\n if (isActive) {\n setStatus(next, { submissionId, error });\n }\n }\n\n function ensureSyncSubscription(): void {\n if (unsubscribeSync) return;\n unsubscribeSync = client.onSync((event) => {\n if (event.type === 'sync-start' || event.type === 'sync-complete') return;\n const submissionId = event.item.meta?.['submissionId'];\n if (typeof submissionId !== 'string' || submissionId !== activeSubmissionId) return;\n\n if (event.type === 'item-start') {\n void patchSubmission(submissionId, { status: 'syncing' });\n setStatus('syncing', { submissionId });\n } else if (event.type === 'item-success') {\n void onSubmissionSettled(submissionId, 'success');\n } else if (event.type === 'item-failed') {\n if (event.willRetry) {\n void patchSubmission(submissionId, {\n status: 'pending',\n lastError: event.item.lastError,\n });\n setStatus('pending', { submissionId, error: event.item.lastError });\n } else {\n void onSubmissionSettled(submissionId, 'failed', event.item.lastError);\n }\n }\n });\n }\n\n async function save(values: T): Promise<void> {\n lastValues = values;\n await saveDraft(config.id, values);\n setStatus('saved');\n }\n\n async function submit(values: T): Promise<{ status: FormStatus }> {\n await save(values);\n\n const submissionId = createId();\n activeSubmissionId = submissionId;\n const payload = config.transform ? config.transform(values) : JSON.stringify(values);\n const body = typeof payload === 'string' ? payload : JSON.stringify(payload);\n\n await saveSubmission<T>({\n submissionId,\n formId: config.id,\n kind: 'submission',\n values,\n status: 'pending',\n createdAt: Date.now(),\n updatedAt: Date.now(),\n });\n setStatus('pending', { submissionId });\n ensureSyncSubscription();\n\n const result = await client.fetch(config.endpoint, {\n method: config.method ?? 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n meta: { formId: config.id, submissionId },\n idempotencyKey: submissionId,\n });\n\n if (isQueued(result)) {\n await patchSubmission(submissionId, { status: 'pending', queueId: result.id });\n setStatus('pending', { submissionId });\n } else if (result.ok) {\n await onSubmissionSettled(submissionId, 'success');\n } else {\n await onSubmissionSettled(\n submissionId,\n 'failed',\n `Request failed with status ${result.status}`,\n );\n }\n\n return { status };\n }\n\n async function retry(): Promise<void> {\n if (!lastValues) return;\n await submit(lastValues);\n }\n\n function destroy(): void {\n unsubscribeSync?.();\n unsubscribeSync = undefined;\n }\n\n async function discard(): Promise<void> {\n await discardDraft(config.id);\n lastValues = undefined;\n activeSubmissionId = undefined;\n destroy();\n setStatus('idle');\n }\n\n return {\n save,\n submit,\n retry,\n getStatus: () => status,\n subscribe: (callback) => emitter.subscribe(({ status: s, detail }) => callback(s, detail)),\n discard,\n destroy,\n };\n}\n"]}
|