@multiplatform.one/frappe 6.1.0 → 6.3.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/README.md +38 -12
- package/dist/cjs/auth.cjs +1 -1
- package/dist/cjs/auth.native.js.map +1 -1
- package/dist/cjs/call.cjs +1 -1
- package/dist/cjs/call.native.js.map +1 -1
- package/dist/cjs/collection.cjs +18 -4
- package/dist/cjs/collection.native.js +18 -4
- package/dist/cjs/collection.native.js.map +1 -1
- package/dist/cjs/core/http.cjs +92 -9
- package/dist/cjs/core/http.native.js +96 -7
- package/dist/cjs/core/http.native.js.map +1 -1
- package/dist/cjs/db.cjs +7 -7
- package/dist/cjs/db.native.js +4 -4
- package/dist/cjs/db.native.js.map +1 -1
- package/dist/cjs/doctype.cjs +97 -39
- package/dist/cjs/doctype.native.js +116 -46
- package/dist/cjs/doctype.native.js.map +1 -1
- package/dist/cjs/file.cjs +1 -1
- package/dist/cjs/file.native.js.map +1 -1
- package/dist/cjs/fixtureDb.cjs +3 -2
- package/dist/cjs/fixtureDb.native.js +2 -1
- package/dist/cjs/fixtureDb.native.js.map +1 -1
- package/dist/cjs/frappeApp.cjs +15 -14
- package/dist/cjs/frappeApp.native.js +16 -14
- package/dist/cjs/frappeApp.native.js.map +1 -1
- package/dist/cjs/frappeReact.cjs +198 -18
- package/dist/cjs/frappeReact.native.js +241 -18
- package/dist/cjs/frappeReact.native.js.map +1 -1
- package/dist/cjs/index.cjs +9 -4
- package/dist/cjs/index.native.js +9 -4
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/pacer.cjs +2 -2
- package/dist/cjs/pacer.native.js +2 -2
- package/dist/cjs/pacer.native.js.map +1 -1
- package/dist/cjs/realtime.cjs +186 -46
- package/dist/cjs/realtime.native.js +268 -48
- package/dist/cjs/realtime.native.js.map +1 -1
- package/dist/cjs/sync/backfill.cjs +32 -27
- package/dist/cjs/sync/backfill.native.js +49 -43
- package/dist/cjs/sync/backfill.native.js.map +1 -1
- package/dist/cjs/sync/index.cjs +90 -24
- package/dist/cjs/sync/index.native.js +112 -10
- package/dist/cjs/sync/index.native.js.map +1 -1
- package/dist/cjs/sync/merge.cjs +0 -3
- package/dist/cjs/sync/merge.native.js +0 -3
- package/dist/cjs/sync/merge.native.js.map +1 -1
- package/dist/cjs/sync/mutationEngine.cjs +25 -19
- package/dist/cjs/sync/mutationEngine.native.js +16 -13
- package/dist/cjs/sync/mutationEngine.native.js.map +1 -1
- package/dist/cjs/sync/mutationJournal.cjs +9 -4
- package/dist/cjs/sync/mutationJournal.native.js +7 -4
- package/dist/cjs/sync/mutationJournal.native.js.map +1 -1
- package/dist/cjs/sync/normalizedCache.cjs +7 -3
- package/dist/cjs/sync/normalizedCache.native.js +7 -2
- package/dist/cjs/sync/normalizedCache.native.js.map +1 -1
- package/dist/cjs/sync/persistence.cjs +63 -31
- package/dist/cjs/sync/persistence.native.js +120 -63
- package/dist/cjs/sync/persistence.native.js.map +1 -1
- package/dist/cjs/sync/realtime.cjs +124 -13
- package/dist/cjs/sync/realtime.native.js +163 -20
- package/dist/cjs/sync/realtime.native.js.map +1 -1
- package/dist/cjs/sync/rehydration.cjs +16 -10
- package/dist/cjs/sync/rehydration.native.js +16 -14
- package/dist/cjs/sync/rehydration.native.js.map +1 -1
- package/dist/cjs/sync/storage.cjs +3 -3
- package/dist/cjs/sync/storage.native.js +1 -1
- package/dist/cjs/sync/storage.native.js.map +1 -1
- package/dist/cjs/sync/subscriptionManager.cjs +255 -65
- package/dist/cjs/sync/subscriptionManager.native.js +330 -93
- package/dist/cjs/sync/subscriptionManager.native.js.map +1 -1
- package/dist/cjs/sync/types.cjs +2 -0
- package/dist/cjs/sync/types.native.js +2 -0
- package/dist/cjs/sync/types.native.js.map +1 -1
- package/dist/cjs/sync/virtualPageManager.cjs +9 -9
- package/dist/cjs/sync/virtualPageManager.native.js +5 -9
- package/dist/cjs/sync/virtualPageManager.native.js.map +1 -1
- package/dist/cjs/useLiveQuery.cjs +52 -0
- package/dist/cjs/useLiveQuery.native.js +59 -0
- package/dist/cjs/useLiveQuery.native.js.map +1 -0
- package/dist/cjs/util.cjs +11 -2
- package/dist/cjs/util.native.js +16 -2
- package/dist/cjs/util.native.js.map +1 -1
- package/dist/esm/auth.mjs +1 -1
- package/dist/esm/auth.mjs.map +1 -1
- package/dist/esm/auth.native.js.map +1 -1
- package/dist/esm/call.mjs +1 -1
- package/dist/esm/call.mjs.map +1 -1
- package/dist/esm/call.native.js.map +1 -1
- package/dist/esm/collection.mjs +18 -4
- package/dist/esm/collection.mjs.map +1 -1
- package/dist/esm/collection.native.js +18 -4
- package/dist/esm/collection.native.js.map +1 -1
- package/dist/esm/core/http.mjs +93 -10
- package/dist/esm/core/http.mjs.map +1 -1
- package/dist/esm/core/http.native.js +97 -8
- package/dist/esm/core/http.native.js.map +1 -1
- package/dist/esm/db.mjs +7 -7
- package/dist/esm/db.mjs.map +1 -1
- package/dist/esm/db.native.js +4 -4
- package/dist/esm/db.native.js.map +1 -1
- package/dist/esm/doctype.mjs +96 -39
- package/dist/esm/doctype.mjs.map +1 -1
- package/dist/esm/doctype.native.js +115 -46
- package/dist/esm/doctype.native.js.map +1 -1
- package/dist/esm/file.mjs +1 -1
- package/dist/esm/file.mjs.map +1 -1
- package/dist/esm/file.native.js.map +1 -1
- package/dist/esm/fixtureDb.mjs +3 -2
- package/dist/esm/fixtureDb.mjs.map +1 -1
- package/dist/esm/fixtureDb.native.js +2 -1
- package/dist/esm/fixtureDb.native.js.map +1 -1
- package/dist/esm/frappeApp.mjs +15 -14
- package/dist/esm/frappeApp.mjs.map +1 -1
- package/dist/esm/frappeApp.native.js +16 -14
- package/dist/esm/frappeApp.native.js.map +1 -1
- package/dist/esm/frappeReact.mjs +197 -19
- package/dist/esm/frappeReact.mjs.map +1 -1
- package/dist/esm/frappeReact.native.js +240 -19
- package/dist/esm/frappeReact.native.js.map +1 -1
- package/dist/esm/index.mjs +5 -4
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +5 -4
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/pacer.mjs +1 -1
- package/dist/esm/pacer.native.js +1 -1
- package/dist/esm/realtime.mjs +187 -47
- package/dist/esm/realtime.mjs.map +1 -1
- package/dist/esm/realtime.native.js +269 -49
- package/dist/esm/realtime.native.js.map +1 -1
- package/dist/esm/sync/backfill.mjs +32 -27
- package/dist/esm/sync/backfill.mjs.map +1 -1
- package/dist/esm/sync/backfill.native.js +49 -43
- package/dist/esm/sync/backfill.native.js.map +1 -1
- package/dist/esm/sync/index.mjs +90 -24
- package/dist/esm/sync/index.mjs.map +1 -1
- package/dist/esm/sync/index.native.js +112 -10
- package/dist/esm/sync/index.native.js.map +1 -1
- package/dist/esm/sync/merge.mjs +1 -1
- package/dist/esm/sync/merge.mjs.map +1 -1
- package/dist/esm/sync/merge.native.js +1 -1
- package/dist/esm/sync/merge.native.js.map +1 -1
- package/dist/esm/sync/mutationEngine.mjs +25 -19
- package/dist/esm/sync/mutationEngine.mjs.map +1 -1
- package/dist/esm/sync/mutationEngine.native.js +16 -13
- package/dist/esm/sync/mutationEngine.native.js.map +1 -1
- package/dist/esm/sync/mutationJournal.mjs +9 -4
- package/dist/esm/sync/mutationJournal.mjs.map +1 -1
- package/dist/esm/sync/mutationJournal.native.js +7 -4
- package/dist/esm/sync/mutationJournal.native.js.map +1 -1
- package/dist/esm/sync/normalizedCache.mjs +7 -3
- package/dist/esm/sync/normalizedCache.mjs.map +1 -1
- package/dist/esm/sync/normalizedCache.native.js +7 -2
- package/dist/esm/sync/normalizedCache.native.js.map +1 -1
- package/dist/esm/sync/persistence.mjs +64 -32
- package/dist/esm/sync/persistence.mjs.map +1 -1
- package/dist/esm/sync/persistence.native.js +121 -64
- package/dist/esm/sync/persistence.native.js.map +1 -1
- package/dist/esm/sync/realtime.mjs +124 -13
- package/dist/esm/sync/realtime.mjs.map +1 -1
- package/dist/esm/sync/realtime.native.js +163 -20
- package/dist/esm/sync/realtime.native.js.map +1 -1
- package/dist/esm/sync/rehydration.mjs +16 -10
- package/dist/esm/sync/rehydration.mjs.map +1 -1
- package/dist/esm/sync/rehydration.native.js +16 -14
- package/dist/esm/sync/rehydration.native.js.map +1 -1
- package/dist/esm/sync/storage.mjs +3 -3
- package/dist/esm/sync/storage.mjs.map +1 -1
- package/dist/esm/sync/storage.native.js +1 -1
- package/dist/esm/sync/storage.native.js.map +1 -1
- package/dist/esm/sync/subscriptionManager.mjs +255 -65
- package/dist/esm/sync/subscriptionManager.mjs.map +1 -1
- package/dist/esm/sync/subscriptionManager.native.js +330 -93
- package/dist/esm/sync/subscriptionManager.native.js.map +1 -1
- package/dist/esm/sync/types.mjs +2 -0
- package/dist/esm/sync/types.mjs.map +1 -1
- package/dist/esm/sync/types.native.js +2 -0
- package/dist/esm/sync/types.native.js.map +1 -1
- package/dist/esm/sync/virtualPageManager.mjs +9 -9
- package/dist/esm/sync/virtualPageManager.mjs.map +1 -1
- package/dist/esm/sync/virtualPageManager.native.js +5 -9
- package/dist/esm/sync/virtualPageManager.native.js.map +1 -1
- package/dist/esm/useLiveQuery.mjs +26 -0
- package/dist/esm/useLiveQuery.mjs.map +1 -0
- package/dist/esm/useLiveQuery.native.js +30 -0
- package/dist/esm/useLiveQuery.native.js.map +1 -0
- package/dist/esm/util.mjs +10 -2
- package/dist/esm/util.mjs.map +1 -1
- package/dist/esm/util.native.js +15 -2
- package/dist/esm/util.native.js.map +1 -1
- package/dist/jsx/auth.mjs +1 -1
- package/dist/jsx/auth.mjs.map +1 -1
- package/dist/jsx/auth.native.js.map +1 -1
- package/dist/jsx/call.mjs +1 -1
- package/dist/jsx/call.mjs.map +1 -1
- package/dist/jsx/call.native.js.map +1 -1
- package/dist/jsx/collection.mjs +18 -4
- package/dist/jsx/collection.mjs.map +1 -1
- package/dist/jsx/collection.native.js +18 -4
- package/dist/jsx/collection.native.js.map +1 -1
- package/dist/jsx/core/http.mjs +93 -10
- package/dist/jsx/core/http.mjs.map +1 -1
- package/dist/jsx/core/http.native.js +96 -7
- package/dist/jsx/core/http.native.js.map +1 -1
- package/dist/jsx/db.mjs +7 -7
- package/dist/jsx/db.mjs.map +1 -1
- package/dist/jsx/db.native.js +4 -4
- package/dist/jsx/db.native.js.map +1 -1
- package/dist/jsx/doctype.mjs +96 -39
- package/dist/jsx/doctype.mjs.map +1 -1
- package/dist/jsx/doctype.native.js +116 -46
- package/dist/jsx/doctype.native.js.map +1 -1
- package/dist/jsx/file.mjs +1 -1
- package/dist/jsx/file.mjs.map +1 -1
- package/dist/jsx/file.native.js.map +1 -1
- package/dist/jsx/fixtureDb.mjs +3 -2
- package/dist/jsx/fixtureDb.mjs.map +1 -1
- package/dist/jsx/fixtureDb.native.js +2 -1
- package/dist/jsx/fixtureDb.native.js.map +1 -1
- package/dist/jsx/frappeApp.mjs +15 -14
- package/dist/jsx/frappeApp.mjs.map +1 -1
- package/dist/jsx/frappeApp.native.js +16 -14
- package/dist/jsx/frappeApp.native.js.map +1 -1
- package/dist/jsx/frappeReact.mjs +197 -19
- package/dist/jsx/frappeReact.mjs.map +1 -1
- package/dist/jsx/frappeReact.native.js +241 -18
- package/dist/jsx/frappeReact.native.js.map +1 -1
- package/dist/jsx/index.js +5 -4
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +5 -4
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +9 -4
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/pacer.mjs +1 -1
- package/dist/jsx/pacer.native.js +2 -2
- package/dist/jsx/pacer.native.js.map +1 -1
- package/dist/jsx/realtime.mjs +187 -47
- package/dist/jsx/realtime.mjs.map +1 -1
- package/dist/jsx/realtime.native.js +268 -48
- package/dist/jsx/realtime.native.js.map +1 -1
- package/dist/jsx/sync/backfill.mjs +32 -27
- package/dist/jsx/sync/backfill.mjs.map +1 -1
- package/dist/jsx/sync/backfill.native.js +49 -43
- package/dist/jsx/sync/backfill.native.js.map +1 -1
- package/dist/jsx/sync/index.mjs +90 -24
- package/dist/jsx/sync/index.mjs.map +1 -1
- package/dist/jsx/sync/index.native.js +112 -10
- package/dist/jsx/sync/index.native.js.map +1 -1
- package/dist/jsx/sync/merge.mjs +1 -1
- package/dist/jsx/sync/merge.mjs.map +1 -1
- package/dist/jsx/sync/merge.native.js +0 -3
- package/dist/jsx/sync/merge.native.js.map +1 -1
- package/dist/jsx/sync/mutationEngine.mjs +25 -19
- package/dist/jsx/sync/mutationEngine.mjs.map +1 -1
- package/dist/jsx/sync/mutationEngine.native.js +16 -13
- package/dist/jsx/sync/mutationEngine.native.js.map +1 -1
- package/dist/jsx/sync/mutationJournal.mjs +9 -4
- package/dist/jsx/sync/mutationJournal.mjs.map +1 -1
- package/dist/jsx/sync/mutationJournal.native.js +7 -4
- package/dist/jsx/sync/mutationJournal.native.js.map +1 -1
- package/dist/jsx/sync/normalizedCache.mjs +7 -3
- package/dist/jsx/sync/normalizedCache.mjs.map +1 -1
- package/dist/jsx/sync/normalizedCache.native.js +7 -2
- package/dist/jsx/sync/normalizedCache.native.js.map +1 -1
- package/dist/jsx/sync/persistence.mjs +64 -32
- package/dist/jsx/sync/persistence.mjs.map +1 -1
- package/dist/jsx/sync/persistence.native.js +120 -63
- package/dist/jsx/sync/persistence.native.js.map +1 -1
- package/dist/jsx/sync/realtime.mjs +124 -13
- package/dist/jsx/sync/realtime.mjs.map +1 -1
- package/dist/jsx/sync/realtime.native.js +163 -20
- package/dist/jsx/sync/realtime.native.js.map +1 -1
- package/dist/jsx/sync/rehydration.mjs +16 -10
- package/dist/jsx/sync/rehydration.mjs.map +1 -1
- package/dist/jsx/sync/rehydration.native.js +16 -14
- package/dist/jsx/sync/rehydration.native.js.map +1 -1
- package/dist/jsx/sync/storage.mjs +3 -3
- package/dist/jsx/sync/storage.mjs.map +1 -1
- package/dist/jsx/sync/storage.native.js +1 -1
- package/dist/jsx/sync/storage.native.js.map +1 -1
- package/dist/jsx/sync/subscriptionManager.mjs +255 -65
- package/dist/jsx/sync/subscriptionManager.mjs.map +1 -1
- package/dist/jsx/sync/subscriptionManager.native.js +330 -93
- package/dist/jsx/sync/subscriptionManager.native.js.map +1 -1
- package/dist/jsx/sync/types.mjs +2 -0
- package/dist/jsx/sync/types.mjs.map +1 -1
- package/dist/jsx/sync/types.native.js +2 -0
- package/dist/jsx/sync/types.native.js.map +1 -1
- package/dist/jsx/sync/virtualPageManager.mjs +9 -9
- package/dist/jsx/sync/virtualPageManager.mjs.map +1 -1
- package/dist/jsx/sync/virtualPageManager.native.js +5 -9
- package/dist/jsx/sync/virtualPageManager.native.js.map +1 -1
- package/dist/jsx/useLiveQuery.mjs +26 -0
- package/dist/jsx/useLiveQuery.mjs.map +1 -0
- package/dist/jsx/useLiveQuery.native.js +59 -0
- package/dist/jsx/useLiveQuery.native.js.map +1 -0
- package/dist/jsx/util.mjs +10 -2
- package/dist/jsx/util.mjs.map +1 -1
- package/dist/jsx/util.native.js +16 -2
- package/dist/jsx/util.native.js.map +1 -1
- package/package.json +20 -17
- package/src/auth.ts +5 -1
- package/src/call.ts +5 -1
- package/src/collection.spec.ts +55 -0
- package/src/collection.ts +33 -4
- package/src/core/http.spec.ts +66 -0
- package/src/core/http.ts +115 -9
- package/src/core/httpNative.spec.ts +234 -0
- package/src/core/types.ts +2 -0
- package/src/db.spec.ts +91 -51
- package/src/db.ts +27 -8
- package/src/doctype.spec.ts +247 -39
- package/src/doctype.ts +203 -53
- package/src/file.ts +5 -1
- package/src/fixtureDb.ts +13 -2
- package/src/frappeApp.ts +18 -19
- package/src/frappeReact.spec.ts +565 -1
- package/src/frappeReact.ts +445 -37
- package/src/frappeReactLiveQueryGc.spec.ts +320 -0
- package/src/frappeReactNative.spec.ts +65 -0
- package/src/index.ts +10 -9
- package/src/pacer.ts +1 -1
- package/src/realtime.spec.ts +464 -20
- package/src/realtime.ts +284 -46
- package/src/sync/backfill.spec.ts +43 -0
- package/src/sync/backfill.ts +59 -39
- package/src/sync/debug.spec.ts +36 -0
- package/src/sync/filterValidation.spec.ts +197 -0
- package/src/sync/index.ts +98 -7
- package/src/sync/merge.ts +3 -3
- package/src/sync/mutationEngine.spec.ts +36 -4
- package/src/sync/mutationEngine.ts +30 -11
- package/src/sync/mutationJournal.ts +18 -4
- package/src/sync/normalizedCache.spec.ts +102 -0
- package/src/sync/normalizedCache.ts +19 -3
- package/src/sync/offlineRestore.spec.ts +423 -0
- package/src/sync/persistence.spec.ts +39 -7
- package/src/sync/persistence.ts +90 -18
- package/src/sync/persistenceGjs.spec.ts +143 -0
- package/src/sync/persistenceNative.spec.ts +139 -0
- package/src/sync/realtime.spec.ts +18 -1
- package/src/sync/realtime.ts +161 -13
- package/src/sync/rehydration.ts +23 -5
- package/src/sync/storage.ts +5 -4
- package/src/sync/subscriptionManager.spec.ts +94 -0
- package/src/sync/subscriptionManager.ts +304 -82
- package/src/sync/syncModule.spec.ts +137 -0
- package/src/sync/types.ts +39 -0
- package/src/sync/virtualPageManager.ts +8 -4
- package/src/useLiveQuery.ts +58 -0
- package/src/util.spec.ts +35 -4
- package/src/util.ts +34 -7
- package/types/auth.d.ts +13 -0
- package/types/auth.d.ts.map +1 -0
- package/types/call.d.ts +10 -0
- package/types/call.d.ts.map +1 -0
- package/types/collection.d.ts +127 -0
- package/types/collection.d.ts.map +1 -0
- package/types/common/types.d.ts +35 -0
- package/types/common/types.d.ts.map +1 -0
- package/types/core/http.d.ts +86 -0
- package/types/core/http.d.ts.map +1 -0
- package/types/core/types.d.ts +74 -0
- package/types/core/types.d.ts.map +1 -0
- package/types/core/wire.d.ts +405 -0
- package/types/core/wire.d.ts.map +1 -0
- package/types/db.d.ts +244 -0
- package/types/db.d.ts.map +1 -0
- package/types/devtools/FrappeDevtoolsPanel.d.ts +7 -0
- package/types/devtools/FrappeDevtoolsPanel.d.ts.map +1 -0
- package/types/devtools/index.d.ts +4 -0
- package/types/devtools/index.d.ts.map +1 -0
- package/types/devtools/plugin.d.ts +9 -0
- package/types/devtools/plugin.d.ts.map +1 -0
- package/types/devtools/theme.d.ts +15 -0
- package/types/devtools/theme.d.ts.map +1 -0
- package/types/doctype.d.ts +256 -0
- package/types/doctype.d.ts.map +1 -0
- package/types/file.d.ts +15 -0
- package/types/file.d.ts.map +1 -0
- package/types/fixtureDb.d.ts +76 -0
- package/types/fixtureDb.d.ts.map +1 -0
- package/types/fixtures.d.ts +55 -0
- package/types/fixtures.d.ts.map +1 -0
- package/types/frappeApp.d.ts +45 -0
- package/types/frappeApp.d.ts.map +1 -0
- package/types/frappeReact.d.ts +270 -0
- package/types/frappeReact.d.ts.map +1 -0
- package/types/index.d.ts +44 -0
- package/types/index.d.ts.map +1 -0
- package/types/optimistic.d.ts +38 -0
- package/types/optimistic.d.ts.map +1 -0
- package/types/pacer.d.ts +193 -0
- package/types/pacer.d.ts.map +1 -0
- package/types/plugin/index.d.ts +11 -0
- package/types/plugin/index.d.ts.map +1 -0
- package/types/realtime.d.ts +121 -0
- package/types/realtime.d.ts.map +1 -0
- package/types/sync/backfill.d.ts +60 -0
- package/types/sync/backfill.d.ts.map +1 -0
- package/types/sync/filters.d.ts +101 -0
- package/types/sync/filters.d.ts.map +1 -0
- package/types/sync/index.d.ts +181 -0
- package/types/sync/index.d.ts.map +1 -0
- package/types/sync/merge.d.ts +59 -0
- package/types/sync/merge.d.ts.map +1 -0
- package/types/sync/mutationEngine.d.ts +117 -0
- package/types/sync/mutationEngine.d.ts.map +1 -0
- package/types/sync/mutationJournal.d.ts +60 -0
- package/types/sync/mutationJournal.d.ts.map +1 -0
- package/types/sync/normalizedCache.d.ts +59 -0
- package/types/sync/normalizedCache.d.ts.map +1 -0
- package/types/sync/persistence.d.ts +185 -0
- package/types/sync/persistence.d.ts.map +1 -0
- package/types/sync/realtime.d.ts +121 -0
- package/types/sync/realtime.d.ts.map +1 -0
- package/types/sync/rehydration.d.ts +109 -0
- package/types/sync/rehydration.d.ts.map +1 -0
- package/types/sync/storage.d.ts +65 -0
- package/types/sync/storage.d.ts.map +1 -0
- package/types/sync/subscriptionManager.d.ts +161 -0
- package/types/sync/subscriptionManager.d.ts.map +1 -0
- package/types/sync/types.d.ts +435 -0
- package/types/sync/types.d.ts.map +1 -0
- package/types/sync/virtualPageManager.d.ts +190 -0
- package/types/sync/virtualPageManager.d.ts.map +1 -0
- package/types/useLiveQuery.d.ts +16 -0
- package/types/useLiveQuery.d.ts.map +1 -0
- package/types/util.d.ts +24 -0
- package/types/util.d.ts.map +1 -0
- package/dist/cjs/auth.spec.cjs +0 -322
- package/dist/cjs/auth.spec.native.js +0 -329
- package/dist/cjs/auth.spec.native.js.map +0 -1
- package/dist/cjs/call.spec.cjs +0 -427
- package/dist/cjs/call.spec.native.js +0 -430
- package/dist/cjs/call.spec.native.js.map +0 -1
- package/dist/cjs/collection.spec.cjs +0 -186
- package/dist/cjs/collection.spec.native.js +0 -216
- package/dist/cjs/collection.spec.native.js.map +0 -1
- package/dist/cjs/common/types.spec.cjs +0 -266
- package/dist/cjs/common/types.spec.native.js +0 -271
- package/dist/cjs/common/types.spec.native.js.map +0 -1
- package/dist/cjs/core/http.spec.cjs +0 -1259
- package/dist/cjs/core/http.spec.native.js +0 -1401
- package/dist/cjs/core/http.spec.native.js.map +0 -1
- package/dist/cjs/core/wire.spec.cjs +0 -478
- package/dist/cjs/core/wire.spec.native.js +0 -482
- package/dist/cjs/core/wire.spec.native.js.map +0 -1
- package/dist/cjs/db.spec.cjs +0 -862
- package/dist/cjs/db.spec.native.js +0 -865
- package/dist/cjs/db.spec.native.js.map +0 -1
- package/dist/cjs/doctype.spec.cjs +0 -460
- package/dist/cjs/doctype.spec.native.js +0 -538
- package/dist/cjs/doctype.spec.native.js.map +0 -1
- package/dist/cjs/file.spec.cjs +0 -315
- package/dist/cjs/file.spec.native.js +0 -342
- package/dist/cjs/file.spec.native.js.map +0 -1
- package/dist/cjs/frappeApp.spec.cjs +0 -306
- package/dist/cjs/frappeApp.spec.native.js +0 -308
- package/dist/cjs/frappeApp.spec.native.js.map +0 -1
- package/dist/cjs/frappeReact.spec.cjs +0 -531
- package/dist/cjs/frappeReact.spec.native.js +0 -670
- package/dist/cjs/frappeReact.spec.native.js.map +0 -1
- package/dist/cjs/optimistic.spec.cjs +0 -11
- package/dist/cjs/optimistic.spec.native.js +0 -19
- package/dist/cjs/optimistic.spec.native.js.map +0 -1
- package/dist/cjs/pacer.spec.cjs +0 -470
- package/dist/cjs/pacer.spec.native.js +0 -537
- package/dist/cjs/pacer.spec.native.js.map +0 -1
- package/dist/cjs/realtime.spec.cjs +0 -326
- package/dist/cjs/realtime.spec.native.js +0 -392
- package/dist/cjs/realtime.spec.native.js.map +0 -1
- package/dist/cjs/sync/backfill.spec.cjs +0 -586
- package/dist/cjs/sync/backfill.spec.native.js +0 -712
- package/dist/cjs/sync/backfill.spec.native.js.map +0 -1
- package/dist/cjs/sync/debug.spec.cjs +0 -125
- package/dist/cjs/sync/debug.spec.native.js +0 -133
- package/dist/cjs/sync/debug.spec.native.js.map +0 -1
- package/dist/cjs/sync/filters.spec.cjs +0 -168
- package/dist/cjs/sync/filters.spec.native.js +0 -173
- package/dist/cjs/sync/filters.spec.native.js.map +0 -1
- package/dist/cjs/sync/merge.spec.cjs +0 -908
- package/dist/cjs/sync/merge.spec.native.js +0 -937
- package/dist/cjs/sync/merge.spec.native.js.map +0 -1
- package/dist/cjs/sync/multiOrderBy.spec.cjs +0 -165
- package/dist/cjs/sync/multiOrderBy.spec.native.js +0 -229
- package/dist/cjs/sync/multiOrderBy.spec.native.js.map +0 -1
- package/dist/cjs/sync/mutationEngine.spec.cjs +0 -1158
- package/dist/cjs/sync/mutationEngine.spec.native.js +0 -1173
- package/dist/cjs/sync/mutationEngine.spec.native.js.map +0 -1
- package/dist/cjs/sync/mutationJournal.spec.cjs +0 -330
- package/dist/cjs/sync/mutationJournal.spec.native.js +0 -333
- package/dist/cjs/sync/mutationJournal.spec.native.js.map +0 -1
- package/dist/cjs/sync/mutations.spec.cjs +0 -327
- package/dist/cjs/sync/mutations.spec.native.js +0 -330
- package/dist/cjs/sync/mutations.spec.native.js.map +0 -1
- package/dist/cjs/sync/normalizedCache.spec.cjs +0 -302
- package/dist/cjs/sync/normalizedCache.spec.native.js +0 -311
- package/dist/cjs/sync/normalizedCache.spec.native.js.map +0 -1
- package/dist/cjs/sync/persistence.spec.cjs +0 -562
- package/dist/cjs/sync/persistence.spec.native.js +0 -572
- package/dist/cjs/sync/persistence.spec.native.js.map +0 -1
- package/dist/cjs/sync/realtime.spec.cjs +0 -499
- package/dist/cjs/sync/realtime.spec.native.js +0 -512
- package/dist/cjs/sync/realtime.spec.native.js.map +0 -1
- package/dist/cjs/sync/rehydration.spec.cjs +0 -731
- package/dist/cjs/sync/rehydration.spec.native.js +0 -736
- package/dist/cjs/sync/rehydration.spec.native.js.map +0 -1
- package/dist/cjs/sync/storage.spec.cjs +0 -446
- package/dist/cjs/sync/storage.spec.native.js +0 -470
- package/dist/cjs/sync/storage.spec.native.js.map +0 -1
- package/dist/cjs/sync/subscriptionManager.spec.cjs +0 -1102
- package/dist/cjs/sync/subscriptionManager.spec.native.js +0 -1136
- package/dist/cjs/sync/subscriptionManager.spec.native.js.map +0 -1
- package/dist/cjs/sync/subscriptions.spec.cjs +0 -937
- package/dist/cjs/sync/subscriptions.spec.native.js +0 -969
- package/dist/cjs/sync/subscriptions.spec.native.js.map +0 -1
- package/dist/cjs/sync/syncModule.spec.cjs +0 -206
- package/dist/cjs/sync/syncModule.spec.native.js +0 -222
- package/dist/cjs/sync/syncModule.spec.native.js.map +0 -1
- package/dist/cjs/sync/types.spec.cjs +0 -246
- package/dist/cjs/sync/types.spec.native.js +0 -256
- package/dist/cjs/sync/types.spec.native.js.map +0 -1
- package/dist/cjs/sync/virtualPageManager.spec.cjs +0 -801
- package/dist/cjs/sync/virtualPageManager.spec.native.js +0 -873
- package/dist/cjs/sync/virtualPageManager.spec.native.js.map +0 -1
- package/dist/cjs/util.spec.cjs +0 -43
- package/dist/cjs/util.spec.native.js +0 -48
- package/dist/cjs/util.spec.native.js.map +0 -1
- package/dist/esm/auth.spec.mjs +0 -323
- package/dist/esm/auth.spec.mjs.map +0 -1
- package/dist/esm/auth.spec.native.js +0 -327
- package/dist/esm/auth.spec.native.js.map +0 -1
- package/dist/esm/call.spec.mjs +0 -428
- package/dist/esm/call.spec.mjs.map +0 -1
- package/dist/esm/call.spec.native.js +0 -428
- package/dist/esm/call.spec.native.js.map +0 -1
- package/dist/esm/collection.spec.mjs +0 -187
- package/dist/esm/collection.spec.mjs.map +0 -1
- package/dist/esm/collection.spec.native.js +0 -214
- package/dist/esm/collection.spec.native.js.map +0 -1
- package/dist/esm/common/types.spec.mjs +0 -267
- package/dist/esm/common/types.spec.mjs.map +0 -1
- package/dist/esm/common/types.spec.native.js +0 -269
- package/dist/esm/common/types.spec.native.js.map +0 -1
- package/dist/esm/core/http.spec.mjs +0 -1260
- package/dist/esm/core/http.spec.mjs.map +0 -1
- package/dist/esm/core/http.spec.native.js +0 -1399
- package/dist/esm/core/http.spec.native.js.map +0 -1
- package/dist/esm/core/wire.spec.mjs +0 -479
- package/dist/esm/core/wire.spec.mjs.map +0 -1
- package/dist/esm/core/wire.spec.native.js +0 -480
- package/dist/esm/core/wire.spec.native.js.map +0 -1
- package/dist/esm/db.spec.mjs +0 -863
- package/dist/esm/db.spec.mjs.map +0 -1
- package/dist/esm/db.spec.native.js +0 -863
- package/dist/esm/db.spec.native.js.map +0 -1
- package/dist/esm/doctype.spec.mjs +0 -461
- package/dist/esm/doctype.spec.mjs.map +0 -1
- package/dist/esm/doctype.spec.native.js +0 -536
- package/dist/esm/doctype.spec.native.js.map +0 -1
- package/dist/esm/file.spec.mjs +0 -316
- package/dist/esm/file.spec.mjs.map +0 -1
- package/dist/esm/file.spec.native.js +0 -340
- package/dist/esm/file.spec.native.js.map +0 -1
- package/dist/esm/frappeApp.spec.mjs +0 -307
- package/dist/esm/frappeApp.spec.mjs.map +0 -1
- package/dist/esm/frappeApp.spec.native.js +0 -306
- package/dist/esm/frappeApp.spec.native.js.map +0 -1
- package/dist/esm/frappeReact.spec.mjs +0 -532
- package/dist/esm/frappeReact.spec.mjs.map +0 -1
- package/dist/esm/frappeReact.spec.native.js +0 -668
- package/dist/esm/frappeReact.spec.native.js.map +0 -1
- package/dist/esm/optimistic.spec.mjs +0 -12
- package/dist/esm/optimistic.spec.mjs.map +0 -1
- package/dist/esm/optimistic.spec.native.js +0 -17
- package/dist/esm/optimistic.spec.native.js.map +0 -1
- package/dist/esm/pacer.spec.mjs +0 -447
- package/dist/esm/pacer.spec.mjs.map +0 -1
- package/dist/esm/pacer.spec.native.js +0 -511
- package/dist/esm/pacer.spec.native.js.map +0 -1
- package/dist/esm/realtime.spec.mjs +0 -327
- package/dist/esm/realtime.spec.mjs.map +0 -1
- package/dist/esm/realtime.spec.native.js +0 -390
- package/dist/esm/realtime.spec.native.js.map +0 -1
- package/dist/esm/sync/backfill.spec.mjs +0 -563
- package/dist/esm/sync/backfill.spec.mjs.map +0 -1
- package/dist/esm/sync/backfill.spec.native.js +0 -686
- package/dist/esm/sync/backfill.spec.native.js.map +0 -1
- package/dist/esm/sync/debug.spec.mjs +0 -102
- package/dist/esm/sync/debug.spec.mjs.map +0 -1
- package/dist/esm/sync/debug.spec.native.js +0 -107
- package/dist/esm/sync/debug.spec.native.js.map +0 -1
- package/dist/esm/sync/filters.spec.mjs +0 -169
- package/dist/esm/sync/filters.spec.mjs.map +0 -1
- package/dist/esm/sync/filters.spec.native.js +0 -171
- package/dist/esm/sync/filters.spec.native.js.map +0 -1
- package/dist/esm/sync/merge.spec.mjs +0 -909
- package/dist/esm/sync/merge.spec.mjs.map +0 -1
- package/dist/esm/sync/merge.spec.native.js +0 -935
- package/dist/esm/sync/merge.spec.native.js.map +0 -1
- package/dist/esm/sync/multiOrderBy.spec.mjs +0 -166
- package/dist/esm/sync/multiOrderBy.spec.mjs.map +0 -1
- package/dist/esm/sync/multiOrderBy.spec.native.js +0 -227
- package/dist/esm/sync/multiOrderBy.spec.native.js.map +0 -1
- package/dist/esm/sync/mutationEngine.spec.mjs +0 -1159
- package/dist/esm/sync/mutationEngine.spec.mjs.map +0 -1
- package/dist/esm/sync/mutationEngine.spec.native.js +0 -1171
- package/dist/esm/sync/mutationEngine.spec.native.js.map +0 -1
- package/dist/esm/sync/mutationJournal.spec.mjs +0 -331
- package/dist/esm/sync/mutationJournal.spec.mjs.map +0 -1
- package/dist/esm/sync/mutationJournal.spec.native.js +0 -331
- package/dist/esm/sync/mutationJournal.spec.native.js.map +0 -1
- package/dist/esm/sync/mutations.spec.mjs +0 -328
- package/dist/esm/sync/mutations.spec.mjs.map +0 -1
- package/dist/esm/sync/mutations.spec.native.js +0 -328
- package/dist/esm/sync/mutations.spec.native.js.map +0 -1
- package/dist/esm/sync/normalizedCache.spec.mjs +0 -303
- package/dist/esm/sync/normalizedCache.spec.mjs.map +0 -1
- package/dist/esm/sync/normalizedCache.spec.native.js +0 -309
- package/dist/esm/sync/normalizedCache.spec.native.js.map +0 -1
- package/dist/esm/sync/persistence.spec.mjs +0 -563
- package/dist/esm/sync/persistence.spec.mjs.map +0 -1
- package/dist/esm/sync/persistence.spec.native.js +0 -570
- package/dist/esm/sync/persistence.spec.native.js.map +0 -1
- package/dist/esm/sync/realtime.spec.mjs +0 -500
- package/dist/esm/sync/realtime.spec.mjs.map +0 -1
- package/dist/esm/sync/realtime.spec.native.js +0 -510
- package/dist/esm/sync/realtime.spec.native.js.map +0 -1
- package/dist/esm/sync/rehydration.spec.mjs +0 -732
- package/dist/esm/sync/rehydration.spec.mjs.map +0 -1
- package/dist/esm/sync/rehydration.spec.native.js +0 -734
- package/dist/esm/sync/rehydration.spec.native.js.map +0 -1
- package/dist/esm/sync/storage.spec.mjs +0 -423
- package/dist/esm/sync/storage.spec.mjs.map +0 -1
- package/dist/esm/sync/storage.spec.native.js +0 -444
- package/dist/esm/sync/storage.spec.native.js.map +0 -1
- package/dist/esm/sync/subscriptionManager.spec.mjs +0 -1079
- package/dist/esm/sync/subscriptionManager.spec.mjs.map +0 -1
- package/dist/esm/sync/subscriptionManager.spec.native.js +0 -1110
- package/dist/esm/sync/subscriptionManager.spec.native.js.map +0 -1
- package/dist/esm/sync/subscriptions.spec.mjs +0 -914
- package/dist/esm/sync/subscriptions.spec.mjs.map +0 -1
- package/dist/esm/sync/subscriptions.spec.native.js +0 -943
- package/dist/esm/sync/subscriptions.spec.native.js.map +0 -1
- package/dist/esm/sync/syncModule.spec.mjs +0 -207
- package/dist/esm/sync/syncModule.spec.mjs.map +0 -1
- package/dist/esm/sync/syncModule.spec.native.js +0 -220
- package/dist/esm/sync/syncModule.spec.native.js.map +0 -1
- package/dist/esm/sync/types.spec.mjs +0 -247
- package/dist/esm/sync/types.spec.mjs.map +0 -1
- package/dist/esm/sync/types.spec.native.js +0 -254
- package/dist/esm/sync/types.spec.native.js.map +0 -1
- package/dist/esm/sync/virtualPageManager.spec.mjs +0 -802
- package/dist/esm/sync/virtualPageManager.spec.mjs.map +0 -1
- package/dist/esm/sync/virtualPageManager.spec.native.js +0 -871
- package/dist/esm/sync/virtualPageManager.spec.native.js.map +0 -1
- package/dist/esm/util.spec.mjs +0 -20
- package/dist/esm/util.spec.mjs.map +0 -1
- package/dist/esm/util.spec.native.js +0 -22
- package/dist/esm/util.spec.native.js.map +0 -1
- package/dist/jsx/auth.spec.mjs +0 -323
- package/dist/jsx/auth.spec.mjs.map +0 -1
- package/dist/jsx/auth.spec.native.js +0 -329
- package/dist/jsx/auth.spec.native.js.map +0 -1
- package/dist/jsx/call.spec.mjs +0 -428
- package/dist/jsx/call.spec.mjs.map +0 -1
- package/dist/jsx/call.spec.native.js +0 -430
- package/dist/jsx/call.spec.native.js.map +0 -1
- package/dist/jsx/collection.spec.mjs +0 -187
- package/dist/jsx/collection.spec.mjs.map +0 -1
- package/dist/jsx/collection.spec.native.js +0 -216
- package/dist/jsx/collection.spec.native.js.map +0 -1
- package/dist/jsx/common/types.spec.mjs +0 -267
- package/dist/jsx/common/types.spec.mjs.map +0 -1
- package/dist/jsx/common/types.spec.native.js +0 -271
- package/dist/jsx/common/types.spec.native.js.map +0 -1
- package/dist/jsx/core/http.spec.mjs +0 -1260
- package/dist/jsx/core/http.spec.mjs.map +0 -1
- package/dist/jsx/core/http.spec.native.js +0 -1401
- package/dist/jsx/core/http.spec.native.js.map +0 -1
- package/dist/jsx/core/wire.spec.mjs +0 -479
- package/dist/jsx/core/wire.spec.mjs.map +0 -1
- package/dist/jsx/core/wire.spec.native.js +0 -482
- package/dist/jsx/core/wire.spec.native.js.map +0 -1
- package/dist/jsx/db.spec.mjs +0 -863
- package/dist/jsx/db.spec.mjs.map +0 -1
- package/dist/jsx/db.spec.native.js +0 -865
- package/dist/jsx/db.spec.native.js.map +0 -1
- package/dist/jsx/doctype.spec.mjs +0 -461
- package/dist/jsx/doctype.spec.mjs.map +0 -1
- package/dist/jsx/doctype.spec.native.js +0 -538
- package/dist/jsx/doctype.spec.native.js.map +0 -1
- package/dist/jsx/file.spec.mjs +0 -316
- package/dist/jsx/file.spec.mjs.map +0 -1
- package/dist/jsx/file.spec.native.js +0 -342
- package/dist/jsx/file.spec.native.js.map +0 -1
- package/dist/jsx/frappeApp.spec.mjs +0 -307
- package/dist/jsx/frappeApp.spec.mjs.map +0 -1
- package/dist/jsx/frappeApp.spec.native.js +0 -308
- package/dist/jsx/frappeApp.spec.native.js.map +0 -1
- package/dist/jsx/frappeReact.spec.mjs +0 -532
- package/dist/jsx/frappeReact.spec.mjs.map +0 -1
- package/dist/jsx/frappeReact.spec.native.js +0 -670
- package/dist/jsx/frappeReact.spec.native.js.map +0 -1
- package/dist/jsx/optimistic.spec.mjs +0 -12
- package/dist/jsx/optimistic.spec.mjs.map +0 -1
- package/dist/jsx/optimistic.spec.native.js +0 -19
- package/dist/jsx/optimistic.spec.native.js.map +0 -1
- package/dist/jsx/pacer.spec.mjs +0 -447
- package/dist/jsx/pacer.spec.mjs.map +0 -1
- package/dist/jsx/pacer.spec.native.js +0 -537
- package/dist/jsx/pacer.spec.native.js.map +0 -1
- package/dist/jsx/realtime.spec.mjs +0 -327
- package/dist/jsx/realtime.spec.mjs.map +0 -1
- package/dist/jsx/realtime.spec.native.js +0 -392
- package/dist/jsx/realtime.spec.native.js.map +0 -1
- package/dist/jsx/sync/backfill.spec.mjs +0 -563
- package/dist/jsx/sync/backfill.spec.mjs.map +0 -1
- package/dist/jsx/sync/backfill.spec.native.js +0 -712
- package/dist/jsx/sync/backfill.spec.native.js.map +0 -1
- package/dist/jsx/sync/debug.spec.mjs +0 -102
- package/dist/jsx/sync/debug.spec.mjs.map +0 -1
- package/dist/jsx/sync/debug.spec.native.js +0 -133
- package/dist/jsx/sync/debug.spec.native.js.map +0 -1
- package/dist/jsx/sync/filters.spec.mjs +0 -169
- package/dist/jsx/sync/filters.spec.mjs.map +0 -1
- package/dist/jsx/sync/filters.spec.native.js +0 -173
- package/dist/jsx/sync/filters.spec.native.js.map +0 -1
- package/dist/jsx/sync/merge.spec.mjs +0 -909
- package/dist/jsx/sync/merge.spec.mjs.map +0 -1
- package/dist/jsx/sync/merge.spec.native.js +0 -937
- package/dist/jsx/sync/merge.spec.native.js.map +0 -1
- package/dist/jsx/sync/multiOrderBy.spec.mjs +0 -166
- package/dist/jsx/sync/multiOrderBy.spec.mjs.map +0 -1
- package/dist/jsx/sync/multiOrderBy.spec.native.js +0 -229
- package/dist/jsx/sync/multiOrderBy.spec.native.js.map +0 -1
- package/dist/jsx/sync/mutationEngine.spec.mjs +0 -1159
- package/dist/jsx/sync/mutationEngine.spec.mjs.map +0 -1
- package/dist/jsx/sync/mutationEngine.spec.native.js +0 -1173
- package/dist/jsx/sync/mutationEngine.spec.native.js.map +0 -1
- package/dist/jsx/sync/mutationJournal.spec.mjs +0 -331
- package/dist/jsx/sync/mutationJournal.spec.mjs.map +0 -1
- package/dist/jsx/sync/mutationJournal.spec.native.js +0 -333
- package/dist/jsx/sync/mutationJournal.spec.native.js.map +0 -1
- package/dist/jsx/sync/mutations.spec.mjs +0 -328
- package/dist/jsx/sync/mutations.spec.mjs.map +0 -1
- package/dist/jsx/sync/mutations.spec.native.js +0 -330
- package/dist/jsx/sync/mutations.spec.native.js.map +0 -1
- package/dist/jsx/sync/normalizedCache.spec.mjs +0 -303
- package/dist/jsx/sync/normalizedCache.spec.mjs.map +0 -1
- package/dist/jsx/sync/normalizedCache.spec.native.js +0 -311
- package/dist/jsx/sync/normalizedCache.spec.native.js.map +0 -1
- package/dist/jsx/sync/persistence.spec.mjs +0 -563
- package/dist/jsx/sync/persistence.spec.mjs.map +0 -1
- package/dist/jsx/sync/persistence.spec.native.js +0 -572
- package/dist/jsx/sync/persistence.spec.native.js.map +0 -1
- package/dist/jsx/sync/realtime.spec.mjs +0 -500
- package/dist/jsx/sync/realtime.spec.mjs.map +0 -1
- package/dist/jsx/sync/realtime.spec.native.js +0 -512
- package/dist/jsx/sync/realtime.spec.native.js.map +0 -1
- package/dist/jsx/sync/rehydration.spec.mjs +0 -732
- package/dist/jsx/sync/rehydration.spec.mjs.map +0 -1
- package/dist/jsx/sync/rehydration.spec.native.js +0 -736
- package/dist/jsx/sync/rehydration.spec.native.js.map +0 -1
- package/dist/jsx/sync/storage.spec.mjs +0 -423
- package/dist/jsx/sync/storage.spec.mjs.map +0 -1
- package/dist/jsx/sync/storage.spec.native.js +0 -470
- package/dist/jsx/sync/storage.spec.native.js.map +0 -1
- package/dist/jsx/sync/subscriptionManager.spec.mjs +0 -1079
- package/dist/jsx/sync/subscriptionManager.spec.mjs.map +0 -1
- package/dist/jsx/sync/subscriptionManager.spec.native.js +0 -1136
- package/dist/jsx/sync/subscriptionManager.spec.native.js.map +0 -1
- package/dist/jsx/sync/subscriptions.spec.mjs +0 -914
- package/dist/jsx/sync/subscriptions.spec.mjs.map +0 -1
- package/dist/jsx/sync/subscriptions.spec.native.js +0 -969
- package/dist/jsx/sync/subscriptions.spec.native.js.map +0 -1
- package/dist/jsx/sync/syncModule.spec.mjs +0 -207
- package/dist/jsx/sync/syncModule.spec.mjs.map +0 -1
- package/dist/jsx/sync/syncModule.spec.native.js +0 -222
- package/dist/jsx/sync/syncModule.spec.native.js.map +0 -1
- package/dist/jsx/sync/types.spec.mjs +0 -247
- package/dist/jsx/sync/types.spec.mjs.map +0 -1
- package/dist/jsx/sync/types.spec.native.js +0 -256
- package/dist/jsx/sync/types.spec.native.js.map +0 -1
- package/dist/jsx/sync/virtualPageManager.spec.mjs +0 -802
- package/dist/jsx/sync/virtualPageManager.spec.mjs.map +0 -1
- package/dist/jsx/sync/virtualPageManager.spec.native.js +0 -873
- package/dist/jsx/sync/virtualPageManager.spec.native.js.map +0 -1
- package/dist/jsx/util.spec.mjs +0 -20
- package/dist/jsx/util.spec.mjs.map +0 -1
- package/dist/jsx/util.spec.native.js +0 -48
- package/dist/jsx/util.spec.native.js.map +0 -1
|
@@ -14,6 +14,22 @@ import type {
|
|
|
14
14
|
} from "./types";
|
|
15
15
|
import { VirtualPageManager } from "./virtualPageManager";
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Result of `SubscriptionManager.subscribe`.
|
|
19
|
+
*/
|
|
20
|
+
export interface SubscribeResult<Data extends FrappeDocData> {
|
|
21
|
+
subscriptionId: string;
|
|
22
|
+
rows: FrappeDoc<Data>[];
|
|
23
|
+
checkpoint?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Present only when a restored (persisted) subscription was re-adopted:
|
|
26
|
+
* the returned `rows` came from the cache and this promise tracks the
|
|
27
|
+
* background network refresh. Never rejects — a failed refresh marks the
|
|
28
|
+
* subscription `stale` and resolves `{ ok: false }`.
|
|
29
|
+
*/
|
|
30
|
+
refresh?: Promise<{ ok: boolean; error?: unknown }>;
|
|
31
|
+
}
|
|
32
|
+
|
|
17
33
|
export class SubscriptionManager {
|
|
18
34
|
private subscriptions = new Map<string, Subscription>();
|
|
19
35
|
private virtualPageManager: VirtualPageManager;
|
|
@@ -22,21 +38,35 @@ export class SubscriptionManager {
|
|
|
22
38
|
private queryKeyToSubId = new Map<string, string>();
|
|
23
39
|
/** Reference counts per subscriptionId for shared subscription lifecycle */
|
|
24
40
|
private subRefCounts = new Map<string, number>();
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Subscriptions restored from a persisted snapshot (or detached on
|
|
43
|
+
* unsubscribe while persistence is on) that no live query has re-adopted
|
|
44
|
+
* yet. They serve cache-first renders on re-subscribe, are excluded from
|
|
45
|
+
* backfill fan-out, and are GC'd after `restoredSubscriptionTTL`.
|
|
46
|
+
*/
|
|
47
|
+
private restoredByQueryKey = new Map<string, string>();
|
|
48
|
+
/** Restore/detach timestamps per restored subscriptionId (for TTL GC). */
|
|
49
|
+
private restoredAt = new Map<string, number>();
|
|
50
|
+
private readonly db: DbModule;
|
|
51
|
+
private readonly normalizedCache: NormalizedCache;
|
|
52
|
+
private readonly options: SyncOptions;
|
|
53
|
+
|
|
54
|
+
constructor(db: DbModule, normalizedCache: NormalizedCache, options: SyncOptions = {}) {
|
|
55
|
+
this.db = db;
|
|
56
|
+
this.normalizedCache = normalizedCache;
|
|
57
|
+
this.options = options;
|
|
31
58
|
this.virtualPageManager = new VirtualPageManager(this.normalizedCache, this.db, {
|
|
32
59
|
batchSize: this.options.batchSize,
|
|
33
60
|
});
|
|
34
61
|
this.backfillManager = new BackfillManager(this.db, this.normalizedCache, {
|
|
35
62
|
pageSize: this.options.pageSize,
|
|
63
|
+
maxPages: this.options.backfillMaxPages,
|
|
36
64
|
});
|
|
37
65
|
}
|
|
38
66
|
|
|
39
|
-
async subscribe<Data extends FrappeDocData>(
|
|
67
|
+
async subscribe<Data extends FrappeDocData>(
|
|
68
|
+
query: SubscriptionQuery,
|
|
69
|
+
): Promise<SubscribeResult<Data>> {
|
|
40
70
|
// Dedup: if an identical query is already active, reuse it
|
|
41
71
|
const queryKey = JSON.stringify(query);
|
|
42
72
|
const existingId = this.queryKeyToSubId.get(queryKey);
|
|
@@ -47,7 +77,68 @@ export class SubscriptionManager {
|
|
|
47
77
|
return { subscriptionId: existingId, rows, checkpoint };
|
|
48
78
|
}
|
|
49
79
|
|
|
80
|
+
// Cache-first: re-adopt a matching subscription restored from a persisted
|
|
81
|
+
// snapshot — serve its cached membership immediately and refresh from the
|
|
82
|
+
// network in the background.
|
|
83
|
+
const adopted = this.adoptRestoredSubscription<Data>(queryKey, query);
|
|
84
|
+
if (adopted) return adopted;
|
|
85
|
+
|
|
50
86
|
const subscriptionId = cryptoRandomId();
|
|
87
|
+
const { rows, cursor, checkpoint } = await this.fetchInitialRows<Data>(query);
|
|
88
|
+
// Materialize the in-memory subscription record with initial membership
|
|
89
|
+
const subscription: Subscription = {
|
|
90
|
+
id: subscriptionId,
|
|
91
|
+
query,
|
|
92
|
+
checkpoint, // For CDC backfill
|
|
93
|
+
cursor, // For stable pagination
|
|
94
|
+
docIds: rows.map((row) => row.name),
|
|
95
|
+
tombstones: new Map<string, number>(),
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// Track page boundaries for optimistic placement
|
|
99
|
+
if (rows.length > 0) {
|
|
100
|
+
subscription.boundaries = {
|
|
101
|
+
firstItem: rows[0] as unknown as FrappeDoc<Data>,
|
|
102
|
+
lastItem: rows[rows.length - 1] as unknown as FrappeDoc<Data>,
|
|
103
|
+
offset: query.limitStart || 0,
|
|
104
|
+
pageSize: query.limit || 20,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Initialize metadata for tracking items outside current page
|
|
109
|
+
subscription.metadata = {
|
|
110
|
+
itemsBeforePage: 0,
|
|
111
|
+
itemsAfterPage: 0,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Activate it
|
|
115
|
+
this.subscriptions.set(subscriptionId, subscription);
|
|
116
|
+
this.queryKeyToSubId.set(queryKey, subscriptionId);
|
|
117
|
+
this.subRefCounts.set(subscriptionId, 1);
|
|
118
|
+
|
|
119
|
+
// Register with VirtualPageManager for progressive pagination if requested
|
|
120
|
+
if (query.progressive) {
|
|
121
|
+
this.virtualPageManager.registerSubscription(
|
|
122
|
+
subscriptionId,
|
|
123
|
+
subscription,
|
|
124
|
+
subscription.docIds,
|
|
125
|
+
cursor,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Provide the caller with the seeded rows and computed checkpoint
|
|
130
|
+
return { subscriptionId: subscriptionId, rows, checkpoint };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Performs the initial subscription fetch (single doc via getDoc, lists via
|
|
135
|
+
* getDocList), seeds the normalized cache, and computes the CDC checkpoint
|
|
136
|
+
* as the max `modified` across returned rows. Shared by fresh subscribes
|
|
137
|
+
* and adopted-subscription refreshes so both have identical semantics.
|
|
138
|
+
*/
|
|
139
|
+
private async fetchInitialRows<Data extends FrappeDocData>(
|
|
140
|
+
query: SubscriptionQuery,
|
|
141
|
+
): Promise<{ rows: FrappeDoc<Data>[]; cursor?: string; checkpoint?: string }> {
|
|
51
142
|
// Only restrict fields when the caller explicitly specifies them.
|
|
52
143
|
// When fields is undefined/empty, pass undefined so all fields are returned.
|
|
53
144
|
const queryFields = query.fields?.length
|
|
@@ -101,55 +192,143 @@ export class SubscriptionManager {
|
|
|
101
192
|
if (!row.modified) continue;
|
|
102
193
|
if (!checkpoint || row.modified > checkpoint) checkpoint = row.modified;
|
|
103
194
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
id: subscriptionId,
|
|
107
|
-
query,
|
|
108
|
-
checkpoint, // For CDC backfill
|
|
109
|
-
cursor, // For stable pagination
|
|
110
|
-
docIds: rows.map((row) => row.name),
|
|
111
|
-
tombstones: new Map<string, number>(),
|
|
112
|
-
};
|
|
195
|
+
return { rows, cursor, checkpoint };
|
|
196
|
+
}
|
|
113
197
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
198
|
+
/**
|
|
199
|
+
* Re-adopts a subscription restored from a persisted snapshot when an
|
|
200
|
+
* identical query subscribes: the cached membership renders immediately and
|
|
201
|
+
* a background refresh re-seeds from the network. Progressive queries are
|
|
202
|
+
* excluded — their VirtualPageManager state is not persisted, so they take
|
|
203
|
+
* the fresh-subscribe path.
|
|
204
|
+
*/
|
|
205
|
+
private adoptRestoredSubscription<Data extends FrappeDocData>(
|
|
206
|
+
queryKey: string,
|
|
207
|
+
query: SubscriptionQuery,
|
|
208
|
+
): SubscribeResult<Data> | undefined {
|
|
209
|
+
if (query.progressive) return undefined;
|
|
210
|
+
const restoredId = this.restoredByQueryKey.get(queryKey);
|
|
211
|
+
if (!restoredId) return undefined;
|
|
212
|
+
const subscription = this.subscriptions.get(restoredId);
|
|
213
|
+
this.restoredByQueryKey.delete(queryKey);
|
|
214
|
+
this.restoredAt.delete(restoredId);
|
|
215
|
+
if (!subscription) return undefined;
|
|
216
|
+
|
|
217
|
+
// Activate under the live dedup/refcount lifecycle
|
|
218
|
+
this.queryKeyToSubId.set(queryKey, restoredId);
|
|
219
|
+
this.subRefCounts.set(restoredId, 1);
|
|
220
|
+
|
|
221
|
+
const refresh = this.refreshAdoptedSubscription<Data>(subscription);
|
|
222
|
+
const rows = this.getDocsForSubscription<Data>(restoredId);
|
|
223
|
+
return { subscriptionId: restoredId, rows, checkpoint: subscription.checkpoint, refresh };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Network refresh for an adopted subscription with fresh-subscribe
|
|
228
|
+
* semantics: an authoritative page fetch replaces membership and recomputes
|
|
229
|
+
* the checkpoint (identical to what a brand-new subscribe would produce).
|
|
230
|
+
* On failure (offline) the cached membership and the restored CDC
|
|
231
|
+
* checkpoint are kept and the subscription is marked stale — the next
|
|
232
|
+
* backfill trigger drains changes from that checkpoint. Never rejects.
|
|
233
|
+
*/
|
|
234
|
+
private async refreshAdoptedSubscription<Data extends FrappeDocData>(
|
|
235
|
+
subscription: Subscription,
|
|
236
|
+
): Promise<{ ok: boolean; error?: unknown }> {
|
|
237
|
+
try {
|
|
238
|
+
const { rows, cursor, checkpoint } = await this.fetchInitialRows<Data>(subscription.query);
|
|
239
|
+
subscription.checkpoint = checkpoint;
|
|
240
|
+
subscription.cursor = cursor;
|
|
241
|
+
subscription.docIds = rows.map((row) => row.name);
|
|
242
|
+
if (rows.length > 0) {
|
|
243
|
+
subscription.boundaries = {
|
|
244
|
+
firstItem: rows[0] as unknown as FrappeDoc<FrappeDocData>,
|
|
245
|
+
lastItem: rows[rows.length - 1] as unknown as FrappeDoc<FrappeDocData>,
|
|
246
|
+
offset: subscription.query.limitStart || 0,
|
|
247
|
+
pageSize: subscription.query.limit || 20,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
subscription.metadata = { itemsBeforePage: 0, itemsAfterPage: 0 };
|
|
251
|
+
subscription.stale = false;
|
|
252
|
+
return { ok: true };
|
|
253
|
+
} catch (error) {
|
|
254
|
+
subscription.stale = true;
|
|
255
|
+
return { ok: false, error };
|
|
122
256
|
}
|
|
257
|
+
}
|
|
123
258
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
259
|
+
/**
|
|
260
|
+
* Registers a subscription restored from a persisted snapshot. Restored
|
|
261
|
+
* subscriptions are dormant: they hold the persisted query, CDC checkpoint,
|
|
262
|
+
* and membership for cache-first re-adoption, but are skipped by backfill
|
|
263
|
+
* fan-out until adopted. Duplicate snapshot entries for the same query
|
|
264
|
+
* (accumulated by pre-GC versions) collapse last-wins.
|
|
265
|
+
*/
|
|
266
|
+
restoreSubscription(
|
|
267
|
+
snapshotSub: Pick<Subscription, "id" | "query"> &
|
|
268
|
+
Partial<Pick<Subscription, "checkpoint" | "cursor" | "docIds">>,
|
|
269
|
+
) {
|
|
270
|
+
if (!snapshotSub?.id || !snapshotSub.query?.doctype) return;
|
|
271
|
+
if (this.subscriptions.has(snapshotSub.id)) return;
|
|
272
|
+
const queryKey = JSON.stringify(snapshotSub.query);
|
|
273
|
+
// An active subscription already serves this query — the restored copy
|
|
274
|
+
// would never be adopted, so drop it.
|
|
275
|
+
const activeId = this.queryKeyToSubId.get(queryKey);
|
|
276
|
+
if (activeId && this.subscriptions.has(activeId)) return;
|
|
277
|
+
// Last-wins: later snapshot entries are from more recent sessions
|
|
278
|
+
const previousId = this.restoredByQueryKey.get(queryKey);
|
|
279
|
+
if (previousId) {
|
|
280
|
+
this.subscriptions.delete(previousId);
|
|
281
|
+
this.restoredAt.delete(previousId);
|
|
282
|
+
}
|
|
283
|
+
const subscription: Subscription = {
|
|
284
|
+
id: snapshotSub.id,
|
|
285
|
+
query: snapshotSub.query,
|
|
286
|
+
checkpoint: snapshotSub.checkpoint,
|
|
287
|
+
cursor: snapshotSub.cursor,
|
|
288
|
+
docIds: Array.isArray(snapshotSub.docIds) ? snapshotSub.docIds : [],
|
|
289
|
+
tombstones: new Map<string, number>(),
|
|
290
|
+
metadata: { itemsBeforePage: 0, itemsAfterPage: 0 },
|
|
128
291
|
};
|
|
292
|
+
this.subscriptions.set(subscription.id, subscription);
|
|
293
|
+
this.restoredByQueryKey.set(queryKey, subscription.id);
|
|
294
|
+
this.restoredAt.set(subscription.id, Date.now());
|
|
295
|
+
}
|
|
129
296
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
this.
|
|
133
|
-
|
|
297
|
+
/** True when the subscription came from a snapshot and is not yet adopted. */
|
|
298
|
+
isRestoredSubscription(subscriptionId: string): boolean {
|
|
299
|
+
return this.restoredAt.has(subscriptionId);
|
|
300
|
+
}
|
|
134
301
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
302
|
+
/**
|
|
303
|
+
* Drops restored subscriptions that no query re-adopted within
|
|
304
|
+
* `restoredSubscriptionTTL` (default 30 minutes). Called before every
|
|
305
|
+
* persistence snapshot so expired entries also leave the snapshot.
|
|
306
|
+
*/
|
|
307
|
+
gcRestoredSubscriptions(now = Date.now()) {
|
|
308
|
+
const ttl = this.options.restoredSubscriptionTTL ?? 30 * 60 * 1000;
|
|
309
|
+
for (const [subscriptionId, restoredAtMs] of this.restoredAt) {
|
|
310
|
+
if (now - restoredAtMs <= ttl) continue;
|
|
311
|
+
this.restoredAt.delete(subscriptionId);
|
|
312
|
+
this.subscriptions.delete(subscriptionId);
|
|
313
|
+
for (const [key, id] of this.restoredByQueryKey) {
|
|
314
|
+
if (id === subscriptionId) {
|
|
315
|
+
this.restoredByQueryKey.delete(key);
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
143
319
|
}
|
|
144
|
-
|
|
145
|
-
// Provide the caller with the seeded rows and computed checkpoint
|
|
146
|
-
return { subscriptionId: subscriptionId, rows, checkpoint };
|
|
147
320
|
}
|
|
148
321
|
|
|
149
322
|
/**
|
|
150
323
|
* Removes a subscription by id. Cached docs remain until evicted by
|
|
151
324
|
* realtime/backfill or explicit resets. This keeps other subs fast if they
|
|
152
325
|
* share the same doctypes.
|
|
326
|
+
*
|
|
327
|
+
* With persistence enabled (`persistKey`), the released subscription is
|
|
328
|
+
* detached into the restored pool instead of deleted: its query,
|
|
329
|
+
* checkpoint, and membership stay in the snapshot so a remount (or a
|
|
330
|
+
* cold offline reload) can re-adopt it cache-first. Detached subscriptions
|
|
331
|
+
* are excluded from backfill and GC'd after `restoredSubscriptionTTL`.
|
|
153
332
|
*/
|
|
154
333
|
unsubscribe(subscriptionId: string) {
|
|
155
334
|
const refCount = (this.subRefCounts.get(subscriptionId) || 1) - 1;
|
|
@@ -159,12 +338,26 @@ export class SubscriptionManager {
|
|
|
159
338
|
}
|
|
160
339
|
// Last consumer released — clean up
|
|
161
340
|
this.subRefCounts.delete(subscriptionId);
|
|
341
|
+
let queryKey: string | undefined;
|
|
162
342
|
for (const [key, id] of this.queryKeyToSubId) {
|
|
163
343
|
if (id === subscriptionId) {
|
|
344
|
+
queryKey = key;
|
|
164
345
|
this.queryKeyToSubId.delete(key);
|
|
165
346
|
break;
|
|
166
347
|
}
|
|
167
348
|
}
|
|
349
|
+
const subscription = this.subscriptions.get(subscriptionId);
|
|
350
|
+
if (
|
|
351
|
+
this.options.persistKey &&
|
|
352
|
+
subscription &&
|
|
353
|
+
queryKey &&
|
|
354
|
+
!subscription.query.progressive &&
|
|
355
|
+
!this.restoredByQueryKey.has(queryKey)
|
|
356
|
+
) {
|
|
357
|
+
this.restoredByQueryKey.set(queryKey, subscriptionId);
|
|
358
|
+
this.restoredAt.set(subscriptionId, Date.now());
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
168
361
|
this.subscriptions.delete(subscriptionId);
|
|
169
362
|
}
|
|
170
363
|
|
|
@@ -250,8 +443,13 @@ export class SubscriptionManager {
|
|
|
250
443
|
*/
|
|
251
444
|
async backfill<Data extends FrappeDocData>(args: BackfillArgs) {
|
|
252
445
|
if (args.scope === BackfillScope.All) {
|
|
253
|
-
for (const subscription of this.subscriptions.values())
|
|
446
|
+
for (const subscription of this.subscriptions.values()) {
|
|
447
|
+
// Restored-but-unadopted subscriptions have no consumers; catching
|
|
448
|
+
// them up would spend a CDC request per trigger for nothing (their
|
|
449
|
+
// adoption refresh re-seeds from the network anyway).
|
|
450
|
+
if (this.restoredAt.has(subscription.id)) continue;
|
|
254
451
|
await this.backfillSub(subscription, args.pageSize);
|
|
452
|
+
}
|
|
255
453
|
return;
|
|
256
454
|
}
|
|
257
455
|
if (args.scope === BackfillScope.Subscriptions) {
|
|
@@ -263,9 +461,11 @@ export class SubscriptionManager {
|
|
|
263
461
|
}
|
|
264
462
|
if (args.scope === BackfillScope.Doctypes) {
|
|
265
463
|
const set = new Set(args.doctypes || []);
|
|
266
|
-
for (const subscription of this.subscriptions.values())
|
|
464
|
+
for (const subscription of this.subscriptions.values()) {
|
|
465
|
+
if (this.restoredAt.has(subscription.id)) continue;
|
|
267
466
|
if (set.has(subscription.query.doctype))
|
|
268
467
|
await this.backfillSub(subscription, args.pageSize);
|
|
468
|
+
}
|
|
269
469
|
return;
|
|
270
470
|
}
|
|
271
471
|
if (args.scope === BackfillScope.Docs) {
|
|
@@ -280,7 +480,9 @@ export class SubscriptionManager {
|
|
|
280
480
|
* Backfills one subscription using CDC checkpoint and updates membership.
|
|
281
481
|
*
|
|
282
482
|
* Algorithm
|
|
283
|
-
* - Query backfill using checkpoint for CDC (Change Data Capture)
|
|
483
|
+
* - Query backfill using checkpoint for CDC (Change Data Capture),
|
|
484
|
+
* draining follow-up pages while the server reports has_more (bounded)
|
|
485
|
+
* so reconnect catch-up is complete rather than one page deep
|
|
284
486
|
* - Upsert each row to cache
|
|
285
487
|
* - For each row: test client-side filters; add/remove membership accordingly
|
|
286
488
|
* - Track tombstones for deleted documents
|
|
@@ -291,42 +493,55 @@ export class SubscriptionManager {
|
|
|
291
493
|
subscription: Subscription,
|
|
292
494
|
pageSize = this.options.pageSize ?? 200,
|
|
293
495
|
) {
|
|
294
|
-
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
496
|
+
const maxPages = this.options.backfillMaxPages ?? 20;
|
|
497
|
+
const rows: FrappeDoc<Data>[] = [];
|
|
498
|
+
const deleted: { doctype?: string; name: string }[] = [];
|
|
499
|
+
for (let page = 0; page < maxPages; page++) {
|
|
500
|
+
// Request changes since the last known checkpoint using CDC backfill API
|
|
501
|
+
const response = await this.db.backfill<Data>({
|
|
502
|
+
doctype: subscription.query.doctype,
|
|
503
|
+
fields: subscription.query.fields,
|
|
504
|
+
filters: subscription.query.filters,
|
|
505
|
+
modifiedAfter: subscription.checkpoint, // CDC checkpoint
|
|
506
|
+
limit: pageSize,
|
|
507
|
+
});
|
|
508
|
+
if (Array.isArray(response.deleted)) {
|
|
509
|
+
deleted.push(...(response.deleted as { doctype?: string; name: string }[]));
|
|
510
|
+
}
|
|
511
|
+
rows.push(...response.rows);
|
|
512
|
+
// Advance the checkpoint to the server-provided cursor for next cycle
|
|
513
|
+
if (response.checkpoint) subscription.checkpoint = response.checkpoint;
|
|
514
|
+
// Keep draining only while the server reports truncation AND handed us
|
|
515
|
+
// a cursor to resume from (guards against servers without has_more and
|
|
516
|
+
// against spinning on a fixed cursor).
|
|
517
|
+
const madeProgress = response.rows.length > 0 || (response.deleted?.length ?? 0) > 0;
|
|
518
|
+
if (!response.has_more || !response.checkpoint || !madeProgress) break;
|
|
519
|
+
}
|
|
302
520
|
// Apply authoritative deletes first if backend returns tombstones.
|
|
303
521
|
// The backfill endpoint returns {name: string} objects (no doctype),
|
|
304
522
|
// so we fall back to the subscription's doctype when not provided.
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
// Track in tombstones map for this subscription with timestamp
|
|
314
|
-
if (deletedDoctype === subscription.query.doctype && subscription.tombstones) {
|
|
315
|
-
subscription.tombstones.set(deleted.name, Date.now());
|
|
316
|
-
}
|
|
317
|
-
// Evict from cache and any list memberships for this doctype
|
|
318
|
-
this.normalizedCache.remove({
|
|
319
|
-
doctype: deletedDoctype,
|
|
320
|
-
name: deleted.name,
|
|
321
|
-
});
|
|
322
|
-
if (deletedDoctype === subscription.query.doctype)
|
|
323
|
-
subscription.docIds = subscription.docIds.filter(
|
|
324
|
-
(currentName) => currentName !== deleted.name,
|
|
325
|
-
);
|
|
523
|
+
for (const deletedRef of deleted) {
|
|
524
|
+
if (!deletedRef?.name) continue;
|
|
525
|
+
const deletedDoctype = deletedRef.doctype || subscription.query.doctype;
|
|
526
|
+
|
|
527
|
+
// Track in tombstones map for this subscription with timestamp
|
|
528
|
+
if (deletedDoctype === subscription.query.doctype && subscription.tombstones) {
|
|
529
|
+
subscription.tombstones.set(deletedRef.name, Date.now());
|
|
326
530
|
}
|
|
531
|
+
// Evict from cache and any list memberships for this doctype
|
|
532
|
+
this.normalizedCache.remove({
|
|
533
|
+
doctype: deletedDoctype,
|
|
534
|
+
name: deletedRef.name,
|
|
535
|
+
});
|
|
536
|
+
if (deletedDoctype === subscription.query.doctype)
|
|
537
|
+
subscription.docIds = subscription.docIds.filter(
|
|
538
|
+
(currentName) => currentName !== deletedRef.name,
|
|
539
|
+
);
|
|
327
540
|
}
|
|
328
|
-
// Upsert each changed/inserted row, then reconcile membership using client filters
|
|
329
|
-
|
|
541
|
+
// Upsert each changed/inserted row, then reconcile membership using client filters.
|
|
542
|
+
// A doc deleted then recreated within the drained window is evicted above
|
|
543
|
+
// and re-added here, matching the server's delete-before-row ordering.
|
|
544
|
+
for (const row of rows) {
|
|
330
545
|
if (!row.doctype) row.doctype = subscription.query.doctype;
|
|
331
546
|
this.normalizedCache.upsert(row);
|
|
332
547
|
const name = row.name;
|
|
@@ -336,11 +551,9 @@ export class SubscriptionManager {
|
|
|
336
551
|
if (!match)
|
|
337
552
|
subscription.docIds = subscription.docIds.filter((currentName) => currentName !== name);
|
|
338
553
|
}
|
|
339
|
-
// Advance the checkpoint to the server-provided checkpoint for next cycle
|
|
340
|
-
if (response.checkpoint) subscription.checkpoint = response.checkpoint;
|
|
341
554
|
// If no filters, the rows represent the full page; maintain membership directly
|
|
342
|
-
if (
|
|
343
|
-
subscription.docIds =
|
|
555
|
+
if (rows.length && !subscription.query.filters)
|
|
556
|
+
subscription.docIds = rows.map((row) => row.name);
|
|
344
557
|
|
|
345
558
|
// Update page boundaries after backfill
|
|
346
559
|
if (subscription.docIds.length > 0) {
|
|
@@ -369,10 +582,13 @@ export class SubscriptionManager {
|
|
|
369
582
|
// Cleanup expired tombstones to prevent memory leaks
|
|
370
583
|
this.cleanupTombstones(subscription.id);
|
|
371
584
|
|
|
585
|
+
// A completed drain means the membership is authoritative again
|
|
586
|
+
subscription.stale = false;
|
|
587
|
+
|
|
372
588
|
if (this.options.onBackfill)
|
|
373
589
|
this.options.onBackfill({
|
|
374
590
|
doctype: subscription.query.doctype,
|
|
375
|
-
fetched:
|
|
591
|
+
fetched: rows.length,
|
|
376
592
|
checkpoint: subscription.checkpoint,
|
|
377
593
|
});
|
|
378
594
|
}
|
|
@@ -405,6 +621,10 @@ export class SubscriptionManager {
|
|
|
405
621
|
updateSubscriptionMembership<Data extends FrappeDocData>(doc: FrappeDoc<Data>): Subscription[] {
|
|
406
622
|
const subscriptionsNeedingRehydration: Subscription[] = [];
|
|
407
623
|
for (const subscription of this.subscriptions.values()) {
|
|
624
|
+
// Dormant restored subscriptions have no renderers and are re-seeded on
|
|
625
|
+
// adoption — skip them so realtime hints don't trigger rehydration
|
|
626
|
+
// fetches (or VPM updates) on their behalf.
|
|
627
|
+
if (this.restoredAt.has(subscription.id)) continue;
|
|
408
628
|
if (subscription.query.doctype !== doc.doctype) continue;
|
|
409
629
|
const match = matchesFilters(doc, subscription.query.filters);
|
|
410
630
|
const isExisting = subscription.docIds.includes(doc.name);
|
|
@@ -529,6 +749,8 @@ export class SubscriptionManager {
|
|
|
529
749
|
this.subscriptions.clear();
|
|
530
750
|
this.queryKeyToSubId.clear();
|
|
531
751
|
this.subRefCounts.clear();
|
|
752
|
+
this.restoredByQueryKey.clear();
|
|
753
|
+
this.restoredAt.clear();
|
|
532
754
|
}
|
|
533
755
|
|
|
534
756
|
/**
|
|
@@ -4,6 +4,7 @@ import { BackfillScope } from "./types";
|
|
|
4
4
|
import type { SubscriptionQuery } from "./types";
|
|
5
5
|
|
|
6
6
|
vi.mock("@multiplatform.one/platform", () => ({
|
|
7
|
+
isNative: false,
|
|
7
8
|
onAppFocus: vi.fn(() => vi.fn()),
|
|
8
9
|
onOnline: vi.fn(() => vi.fn()),
|
|
9
10
|
onVisibilityChange: vi.fn(() => vi.fn()),
|
|
@@ -47,6 +48,8 @@ describe("SyncModule", () => {
|
|
|
47
48
|
isHealthy: vi.fn(() => false),
|
|
48
49
|
connect: vi.fn(),
|
|
49
50
|
disconnect: vi.fn(),
|
|
51
|
+
subscribeList: vi.fn().mockResolvedValue(undefined),
|
|
52
|
+
unsubscribeList: vi.fn(),
|
|
50
53
|
};
|
|
51
54
|
});
|
|
52
55
|
|
|
@@ -177,6 +180,140 @@ describe("SyncModule", () => {
|
|
|
177
180
|
});
|
|
178
181
|
});
|
|
179
182
|
|
|
183
|
+
describe("realtime events bridge to store listeners", () => {
|
|
184
|
+
let eventHandlers: Record<string, (payload?: unknown) => Promise<void> | void>;
|
|
185
|
+
|
|
186
|
+
beforeEach(() => {
|
|
187
|
+
eventHandlers = {};
|
|
188
|
+
mockRealtime.on = vi.fn().mockImplementation((event: string, handler: any) => {
|
|
189
|
+
eventHandlers[event] = handler;
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("notifies store listeners after a remote doc_update reconciles", async () => {
|
|
194
|
+
sync = createSync();
|
|
195
|
+
await sync.subscribe({ doctype: "TestDoc", fields: ["title"] });
|
|
196
|
+
|
|
197
|
+
const listener = vi.fn();
|
|
198
|
+
sync.subscribeStore(listener);
|
|
199
|
+
|
|
200
|
+
mockDb.getDoc.mockResolvedValueOnce({
|
|
201
|
+
name: "doc1",
|
|
202
|
+
doctype: "TestDoc",
|
|
203
|
+
title: "Doc 1 edited",
|
|
204
|
+
modified: "2024-01-01T11:00:00",
|
|
205
|
+
});
|
|
206
|
+
await eventHandlers.doc_update?.({ doctype: "TestDoc", name: "doc1" });
|
|
207
|
+
|
|
208
|
+
expect(listener).toHaveBeenCalled();
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it("notifies store listeners after a remote list_update reconciles", async () => {
|
|
212
|
+
sync = createSync();
|
|
213
|
+
await sync.subscribe({ doctype: "TestDoc", fields: ["title"] });
|
|
214
|
+
|
|
215
|
+
const listener = vi.fn();
|
|
216
|
+
sync.subscribeStore(listener);
|
|
217
|
+
|
|
218
|
+
await eventHandlers.list_update?.({ doctype: "TestDoc", name: "doc2" });
|
|
219
|
+
|
|
220
|
+
expect(listener).toHaveBeenCalled();
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("notifies store listeners after doc_deleted evicts the row", async () => {
|
|
224
|
+
sync = createSync();
|
|
225
|
+
const { subscriptionId } = await sync.subscribe({ doctype: "TestDoc", fields: ["title"] });
|
|
226
|
+
expect(sync.getDocsForSubscription(subscriptionId).map((d) => d.name)).toContain("doc1");
|
|
227
|
+
|
|
228
|
+
const listener = vi.fn();
|
|
229
|
+
sync.subscribeStore(listener);
|
|
230
|
+
|
|
231
|
+
await eventHandlers.doc_deleted?.({ doctype: "TestDoc", name: "doc1" });
|
|
232
|
+
|
|
233
|
+
expect(listener).toHaveBeenCalled();
|
|
234
|
+
expect(sync.getDocsForSubscription(subscriptionId).map((d) => d.name)).not.toContain("doc1");
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it("flips getConnectionState and notifies listeners on connect/disconnect", async () => {
|
|
238
|
+
sync = createSync();
|
|
239
|
+
expect(sync.getConnectionState()).toEqual({ connected: false, everConnected: false });
|
|
240
|
+
|
|
241
|
+
const listener = vi.fn();
|
|
242
|
+
sync.subscribeStore(listener);
|
|
243
|
+
|
|
244
|
+
await eventHandlers.connected?.();
|
|
245
|
+
expect(sync.getConnectionState()).toEqual({ connected: true, everConnected: true });
|
|
246
|
+
expect(listener).toHaveBeenCalled();
|
|
247
|
+
|
|
248
|
+
listener.mockClear();
|
|
249
|
+
await eventHandlers.disconnect?.();
|
|
250
|
+
expect(sync.getConnectionState()).toEqual({ connected: false, everConnected: true });
|
|
251
|
+
expect(listener).toHaveBeenCalled();
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it("forwards realtime events to subscribeRealtimeEvents listeners and unsubscribes", async () => {
|
|
255
|
+
sync = createSync();
|
|
256
|
+
const events: { type: string; payload?: unknown }[] = [];
|
|
257
|
+
const unsubscribe = sync.subscribeRealtimeEvents((event) =>
|
|
258
|
+
events.push(event as { type: string; payload?: unknown }),
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
await eventHandlers.list_update?.({ doctype: "TestDoc", name: "doc2" });
|
|
262
|
+
expect(events.some((e) => e.type === "list_update")).toBe(true);
|
|
263
|
+
|
|
264
|
+
unsubscribe();
|
|
265
|
+
events.length = 0;
|
|
266
|
+
await eventHandlers.list_update?.({ doctype: "TestDoc", name: "doc2" });
|
|
267
|
+
expect(events).toHaveLength(0);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it("chains a consumer-provided onRealtimeEvent option alongside listeners", async () => {
|
|
271
|
+
const onRealtimeEvent = vi.fn();
|
|
272
|
+
sync = createSync({ onRealtimeEvent });
|
|
273
|
+
|
|
274
|
+
await eventHandlers.doc_update?.({ doctype: "TestDoc", name: "doc1" });
|
|
275
|
+
|
|
276
|
+
expect(onRealtimeEvent).toHaveBeenCalledWith(expect.objectContaining({ type: "doc_update" }));
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it("watchDoctype/unwatchDoctype join and leave the doctype room", () => {
|
|
280
|
+
sync = createSync();
|
|
281
|
+
sync.watchDoctype("TestDoc");
|
|
282
|
+
expect(mockRealtime.subscribeList).toHaveBeenCalledWith("TestDoc");
|
|
283
|
+
|
|
284
|
+
sync.unwatchDoctype("TestDoc");
|
|
285
|
+
expect(mockRealtime.unsubscribeList).toHaveBeenCalledWith("TestDoc");
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it("notifies store listeners after debounced rehydration runs (remote create)", async () => {
|
|
289
|
+
sync = createSync();
|
|
290
|
+
await sync.subscribe({
|
|
291
|
+
doctype: "TestDoc",
|
|
292
|
+
fields: ["title"],
|
|
293
|
+
filters: { status: "Open" },
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
const listener = vi.fn();
|
|
297
|
+
sync.subscribeStore(listener);
|
|
298
|
+
|
|
299
|
+
// A brand-new doc matching the filters triggers RemoteCreate rehydration
|
|
300
|
+
mockDb.getDoc.mockResolvedValueOnce({
|
|
301
|
+
name: "doc3",
|
|
302
|
+
doctype: "TestDoc",
|
|
303
|
+
status: "Open",
|
|
304
|
+
title: "Doc 3",
|
|
305
|
+
modified: "2024-01-01T12:00:00",
|
|
306
|
+
});
|
|
307
|
+
await eventHandlers.doc_update?.({ doctype: "TestDoc", name: "doc3" });
|
|
308
|
+
listener.mockClear();
|
|
309
|
+
|
|
310
|
+
// RemoteCreate rehydration is debounced (~500ms) then refreshes the page
|
|
311
|
+
await vi.advanceTimersByTimeAsync(1000);
|
|
312
|
+
|
|
313
|
+
expect(listener).toHaveBeenCalled();
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
|
|
180
317
|
describe("getPage and getNextBatch emit", () => {
|
|
181
318
|
it("getPage notifies store listeners", async () => {
|
|
182
319
|
sync = createSync();
|