UNPKG

@tanstack/db

Version:

A reactive client store for building super fast apps on sync

1 lines • 5.83 kB
{"version":3,"file":"debounceStrategy.cjs","sources":["../../../src/strategies/debounceStrategy.ts"],"sourcesContent":["import { createSerialPacer } from './serial-pacer'\nimport { runWithCommitCompletion } from './commit-completion'\nimport type { DebounceStrategy, DebounceStrategyOptions } from './types'\nimport type { Transaction } from '../transactions'\n\n/**\n * Creates a debounce strategy that delays transaction execution until after\n * a period of inactivity.\n *\n * Ideal for scenarios like search inputs or auto-save fields where you want\n * to wait for the user to stop typing before persisting changes.\n *\n * @param options - Configuration for the debounce behavior\n * @returns A debounce strategy instance\n *\n * @example\n * ```ts\n * const mutate = usePacedMutations({\n * onMutate: (value) => {\n * collection.update(id, draft => { draft.value = value })\n * },\n * mutationFn: async ({ transaction }) => {\n * await api.save(transaction.mutations)\n * },\n * strategy: debounceStrategy({ wait: 500 })\n * })\n * ```\n */\nexport function debounceStrategy(\n options: DebounceStrategyOptions,\n): DebounceStrategy {\n const leading = options.leading ?? false\n const trailing = options.trailing ?? true\n const serial = createSerialPacer(0)\n let canLead = true\n let leadingPending = false\n let leadingOwner: object | undefined\n let timeout: ReturnType<typeof setTimeout> | undefined\n const trailingRuns = new Map<\n object,\n { run: () => Promise<unknown>; isCanceled: () => boolean }\n >()\n\n return {\n _type: `debounce`,\n options,\n execute: <T extends object = Record<string, unknown>>(\n fn: () => Transaction<T>,\n onAdmit?: () => Transaction<T> | void,\n onCommit?: () => Promise<unknown> | undefined,\n ) => {\n const run = () => runWithCommitCompletion(fn, onCommit)\n const leadingCall = leading && canLead\n const admitted = leadingCall || trailing\n // Reserve the edge before optimistic mutation can reenter execute.\n const wasLeadAvailable = canLead\n canLead = false\n let owner: object = fn\n let transaction: Transaction<T> | undefined\n try {\n if (admitted) {\n const admittedOwner = onAdmit?.()\n if (admittedOwner) {\n transaction = admittedOwner\n owner = admittedOwner\n }\n }\n } catch (error) {\n // A nested admitted call may have installed its own quiet timer.\n if (timeout === undefined) canLead = wasLeadAvailable\n throw error\n }\n // A replacement transaction after rollback cannot inherit a canceled\n // leading callback's eligibility. It needs its own quiet-edge schedule.\n const joinsPendingLeading =\n leadingPending && !leadingCall && owner === leadingOwner\n if (timeout !== undefined) clearTimeout(timeout)\n // A new call renews the quiet period, including after an earlier timer\n // became eligible while persistence was held.\n if (trailing)\n for (const pendingOwner of trailingRuns.keys())\n serial.cancel(pendingOwner)\n if (trailing && admitted && !leadingCall && !joinsPendingLeading) {\n trailingRuns.set(owner, {\n run,\n isCanceled: () => transaction?.state === `failed`,\n })\n }\n timeout = setTimeout(() => {\n timeout = undefined\n canLead = true\n for (const [pendingOwner, pending] of trailingRuns) {\n if (pending.isCanceled()) {\n trailingRuns.delete(pendingOwner)\n continue\n }\n serial.schedule(() => {\n trailingRuns.delete(pendingOwner)\n return pending.run()\n }, pendingOwner)\n }\n }, options.wait)\n if (leadingCall) {\n // A same-manager reentrant trailing call joins this leading transaction.\n // A different manager's trailing transaction keeps the shared edge.\n trailingRuns.delete(owner)\n leadingPending = true\n leadingOwner = owner\n serial.schedule(() => {\n leadingPending = false\n leadingOwner = undefined\n return run()\n }, owner)\n }\n if (!admitted) return false\n return\n },\n cleanup: () => {\n // Admitted work retains its timer and persistence obligation.\n },\n }\n}\n"],"names":["createSerialPacer","runWithCommitCompletion"],"mappings":";;;;AA4BO,SAAS,iBACd,SACkB;AAClB,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,SAASA,YAAAA,kBAAkB,CAAC;AAClC,MAAI,UAAU;AACd,MAAI,iBAAiB;AACrB,MAAI;AACJ,MAAI;AACJ,QAAM,mCAAmB,IAAA;AAKzB,SAAO;AAAA,IACL,OAAO;AAAA,IACP;AAAA,IACA,SAAS,CACP,IACA,SACA,aACG;AACH,YAAM,MAAM,MAAMC,yCAAwB,IAAI,QAAQ;AACtD,YAAM,cAAc,WAAW;AAC/B,YAAM,WAAW,eAAe;AAEhC,YAAM,mBAAmB;AACzB,gBAAU;AACV,UAAI,QAAgB;AACpB,UAAI;AACJ,UAAI;AACF,YAAI,UAAU;AACZ,gBAAM,gBAAgB,UAAA;AACtB,cAAI,eAAe;AACjB,0BAAc;AACd,oBAAQ;AAAA,UACV;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AAEd,YAAI,YAAY,OAAW,WAAU;AACrC,cAAM;AAAA,MACR;AAGA,YAAM,sBACJ,kBAAkB,CAAC,eAAe,UAAU;AAC9C,UAAI,YAAY,OAAW,cAAa,OAAO;AAG/C,UAAI;AACF,mBAAW,gBAAgB,aAAa,KAAA;AACtC,iBAAO,OAAO,YAAY;AAC9B,UAAI,YAAY,YAAY,CAAC,eAAe,CAAC,qBAAqB;AAChE,qBAAa,IAAI,OAAO;AAAA,UACtB;AAAA,UACA,YAAY,MAAM,aAAa,UAAU;AAAA,QAAA,CAC1C;AAAA,MACH;AACA,gBAAU,WAAW,MAAM;AACzB,kBAAU;AACV,kBAAU;AACV,mBAAW,CAAC,cAAc,OAAO,KAAK,cAAc;AAClD,cAAI,QAAQ,cAAc;AACxB,yBAAa,OAAO,YAAY;AAChC;AAAA,UACF;AACA,iBAAO,SAAS,MAAM;AACpB,yBAAa,OAAO,YAAY;AAChC,mBAAO,QAAQ,IAAA;AAAA,UACjB,GAAG,YAAY;AAAA,QACjB;AAAA,MACF,GAAG,QAAQ,IAAI;AACf,UAAI,aAAa;AAGf,qBAAa,OAAO,KAAK;AACzB,yBAAiB;AACjB,uBAAe;AACf,eAAO,SAAS,MAAM;AACpB,2BAAiB;AACjB,yBAAe;AACf,iBAAO,IAAA;AAAA,QACT,GAAG,KAAK;AAAA,MACV;AACA,UAAI,CAAC,SAAU,QAAO;AACtB;AAAA,IACF;AAAA,IACA,SAAS,MAAM;AAAA,IAEf;AAAA,EAAA;AAEJ;;"}