@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
package/src/frappeReact.spec.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
2
|
import { act, renderHook, waitFor } from "@testing-library/react";
|
|
3
|
+
import { useState } from "react";
|
|
3
4
|
|
|
4
5
|
const {
|
|
5
6
|
mockSubscribe,
|
|
@@ -28,7 +29,14 @@ vi.mock("./sync", () => ({
|
|
|
28
29
|
},
|
|
29
30
|
}));
|
|
30
31
|
|
|
31
|
-
vi.
|
|
32
|
+
const { mockRealtimeCtor } = vi.hoisted(() => ({ mockRealtimeCtor: vi.fn() }));
|
|
33
|
+
vi.mock("./realtime", () => ({
|
|
34
|
+
RealtimeModule: class {
|
|
35
|
+
constructor(config: unknown) {
|
|
36
|
+
mockRealtimeCtor(config);
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
}));
|
|
32
40
|
vi.mock("./core/http", () => ({ HttpClient: class {} }));
|
|
33
41
|
vi.mock("./db", () => ({ DbModule: class {} }));
|
|
34
42
|
const { mockCreateFrappeCollection, mockIsBrowser } = vi.hoisted(() => ({
|
|
@@ -41,6 +49,7 @@ vi.mock("./util", () => ({ isBrowser: mockIsBrowser }));
|
|
|
41
49
|
vi.mock("./fixtureDb", () => ({ FixtureDbModule: class {} }));
|
|
42
50
|
|
|
43
51
|
import { isBrowser } from "./util";
|
|
52
|
+
import { Order } from "./sync/types";
|
|
44
53
|
import type { UseFrappeCollectionConfig, UseFrappeInfiniteListConfig } from "./frappeReact";
|
|
45
54
|
import {
|
|
46
55
|
__getActiveSyncModule,
|
|
@@ -325,6 +334,561 @@ describe("useFrappeCollection", () => {
|
|
|
325
334
|
const active = __getActiveSyncModule();
|
|
326
335
|
expect(active).toBeDefined();
|
|
327
336
|
});
|
|
337
|
+
|
|
338
|
+
it("passes socketOptions through to the RealtimeModule", () => {
|
|
339
|
+
const socketOptions = { transports: ["polling", "websocket"] };
|
|
340
|
+
const config: UseFrappeCollectionConfig = {
|
|
341
|
+
baseURL: `https://socketopts-${testNum}.example.com`,
|
|
342
|
+
socketOptions,
|
|
343
|
+
};
|
|
344
|
+
renderHook(() => useFrappeCollection(config, "Task"));
|
|
345
|
+
expect(mockRealtimeCtor).toHaveBeenCalledWith(expect.objectContaining({ socketOptions }));
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// ---------------------------------------------------------------------------
|
|
350
|
+
// useFrappeCollection — shared collection cache (dedupe by configKey)
|
|
351
|
+
// ---------------------------------------------------------------------------
|
|
352
|
+
|
|
353
|
+
describe("useFrappeCollection shared cache", () => {
|
|
354
|
+
let testNum = 100;
|
|
355
|
+
/** > SHARED_COLLECTION_GC_MS in frappeReact.ts */
|
|
356
|
+
const GC_WAIT_MS = 1_500;
|
|
357
|
+
|
|
358
|
+
const makeCollection = () =>
|
|
359
|
+
({ id: `collection-${Math.random().toString(36).slice(2)}`, cleanup: vi.fn() }) as any;
|
|
360
|
+
|
|
361
|
+
beforeEach(() => {
|
|
362
|
+
testNum++;
|
|
363
|
+
vi.clearAllMocks();
|
|
364
|
+
vi.useFakeTimers();
|
|
365
|
+
mockIsBrowser.mockReturnValue(true);
|
|
366
|
+
mockCreateFrappeCollection.mockImplementation(() => makeCollection());
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
afterEach(() => {
|
|
370
|
+
vi.runOnlyPendingTimers();
|
|
371
|
+
vi.useRealTimers();
|
|
372
|
+
mockIsBrowser.mockReturnValue(true);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
const configFor = (label: string): UseFrappeCollectionConfig => ({
|
|
376
|
+
baseURL: `https://shared-${label}-${testNum}.example.com`,
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
it("shares one collection across consumers with the same config/doctype/options", () => {
|
|
380
|
+
const config = configFor("same");
|
|
381
|
+
const options = { filters: { name: "TODO-001" } };
|
|
382
|
+
const a = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
383
|
+
const b = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
384
|
+
|
|
385
|
+
expect(a.result.current).toBeDefined();
|
|
386
|
+
expect(b.result.current).toBe(a.result.current);
|
|
387
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(1);
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it("does not share across different filters", () => {
|
|
391
|
+
const config = configFor("difffilters");
|
|
392
|
+
const a = renderHook(() => useFrappeCollection(config, "Todo", { filters: { name: "A" } }));
|
|
393
|
+
const b = renderHook(() => useFrappeCollection(config, "Todo", { filters: { name: "B" } }));
|
|
394
|
+
|
|
395
|
+
expect(a.result.current).not.toBe(b.result.current);
|
|
396
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(2);
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
it("does not share across different orderBy/limit (part of the identity key)", () => {
|
|
400
|
+
const config = configFor("difforder");
|
|
401
|
+
const a = renderHook(() =>
|
|
402
|
+
useFrappeCollection(config, "Todo", { orderBy: { field: "modified", order: Order.Desc } }),
|
|
403
|
+
);
|
|
404
|
+
const b = renderHook(() => useFrappeCollection(config, "Todo", { limit: 5 }));
|
|
405
|
+
|
|
406
|
+
expect(a.result.current).not.toBe(b.result.current);
|
|
407
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(2);
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
it("keeps the shared collection alive while any consumer remains mounted", () => {
|
|
411
|
+
const config = configFor("partial");
|
|
412
|
+
const options = { filters: { name: "TODO-001" } };
|
|
413
|
+
const a = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
414
|
+
const b = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
415
|
+
const shared = a.result.current as any;
|
|
416
|
+
|
|
417
|
+
a.unmount();
|
|
418
|
+
act(() => {
|
|
419
|
+
vi.advanceTimersByTime(GC_WAIT_MS);
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
expect(shared.cleanup).not.toHaveBeenCalled();
|
|
423
|
+
// Remaining consumer still gets the same live instance
|
|
424
|
+
b.rerender();
|
|
425
|
+
expect(b.result.current).toBe(shared);
|
|
426
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(1);
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it("cleans up the shared collection after the last consumer unmounts", () => {
|
|
430
|
+
const config = configFor("lastout");
|
|
431
|
+
const options = { filters: { name: "TODO-001" } };
|
|
432
|
+
const a = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
433
|
+
const b = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
434
|
+
const shared = a.result.current as any;
|
|
435
|
+
|
|
436
|
+
a.unmount();
|
|
437
|
+
b.unmount();
|
|
438
|
+
expect(shared.cleanup).not.toHaveBeenCalled(); // grace period
|
|
439
|
+
act(() => {
|
|
440
|
+
vi.advanceTimersByTime(GC_WAIT_MS);
|
|
441
|
+
});
|
|
442
|
+
expect(shared.cleanup).toHaveBeenCalledTimes(1);
|
|
443
|
+
|
|
444
|
+
// A later consumer gets a fresh collection (no stale entry)
|
|
445
|
+
const c = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
446
|
+
expect(c.result.current).not.toBe(shared);
|
|
447
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(2);
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
it("reuses the same collection when remounting within the grace period", () => {
|
|
451
|
+
const config = configFor("remount");
|
|
452
|
+
const options = { filters: { name: "TODO-001" } };
|
|
453
|
+
const a = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
454
|
+
const shared = a.result.current as any;
|
|
455
|
+
|
|
456
|
+
a.unmount();
|
|
457
|
+
// Remount before the grace period elapses (e.g. StrictMode / quick nav)
|
|
458
|
+
const b = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
459
|
+
act(() => {
|
|
460
|
+
vi.advanceTimersByTime(GC_WAIT_MS);
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
expect(b.result.current).toBe(shared);
|
|
464
|
+
expect(shared.cleanup).not.toHaveBeenCalled();
|
|
465
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(1);
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
it("swaps cleanly when options change: new shared entry, old entry released", () => {
|
|
469
|
+
const config = configFor("swap");
|
|
470
|
+
const { result, rerender } = renderHook(
|
|
471
|
+
({ name }: { name: string }) => useFrappeCollection(config, "Todo", { filters: { name } }),
|
|
472
|
+
{ initialProps: { name: "TODO-001" } },
|
|
473
|
+
);
|
|
474
|
+
const first = result.current as any;
|
|
475
|
+
|
|
476
|
+
rerender({ name: "TODO-002" });
|
|
477
|
+
const second = result.current as any;
|
|
478
|
+
expect(second).not.toBe(first);
|
|
479
|
+
|
|
480
|
+
act(() => {
|
|
481
|
+
vi.advanceTimersByTime(GC_WAIT_MS);
|
|
482
|
+
});
|
|
483
|
+
expect(first.cleanup).toHaveBeenCalledTimes(1);
|
|
484
|
+
expect(second.cleanup).not.toHaveBeenCalled();
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
it("fans out onSyncError to every mounted consumer of the shared collection", () => {
|
|
488
|
+
const config = configFor("errfan");
|
|
489
|
+
const options = { filters: { name: "TODO-001" } };
|
|
490
|
+
const errorA = vi.fn();
|
|
491
|
+
const errorB = vi.fn();
|
|
492
|
+
renderHook(() => useFrappeCollection(config, "Todo", { ...options, onSyncError: errorA }));
|
|
493
|
+
renderHook(() => useFrappeCollection(config, "Todo", { ...options, onSyncError: errorB }));
|
|
494
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(1);
|
|
495
|
+
|
|
496
|
+
const passedOptions = mockCreateFrappeCollection.mock.calls[0][1];
|
|
497
|
+
const syncError = new Error("initial sync failed");
|
|
498
|
+
act(() => {
|
|
499
|
+
passedOptions.onSyncError(syncError);
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
expect(errorA).toHaveBeenCalledWith(syncError);
|
|
503
|
+
expect(errorB).toHaveBeenCalledWith(syncError);
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
it("HOLDS an errored entry while consumers are mounted: re-renders and late mounts share it (no refetch loop)", () => {
|
|
507
|
+
const config = configFor("errhold");
|
|
508
|
+
const options = { filters: { name: "TODO-001" } };
|
|
509
|
+
const a = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
510
|
+
const errored = a.result.current;
|
|
511
|
+
|
|
512
|
+
const passedOptions = mockCreateFrappeCollection.mock.calls[0][1];
|
|
513
|
+
act(() => {
|
|
514
|
+
passedOptions.onSyncError(new Error("initial sync failed"));
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
// The mounted consumer's next render (e.g. after storing the error in
|
|
518
|
+
// state) re-acquires the SAME errored entry — no fresh failing sync.
|
|
519
|
+
a.rerender();
|
|
520
|
+
expect(a.result.current).toBe(errored);
|
|
521
|
+
// A late consumer mounting while the error is held shares the errored
|
|
522
|
+
// entry and gets the error replayed on retain.
|
|
523
|
+
const lateError = vi.fn();
|
|
524
|
+
const late = renderHook(() =>
|
|
525
|
+
useFrappeCollection(config, "Todo", { ...options, onSyncError: lateError }),
|
|
526
|
+
);
|
|
527
|
+
expect(late.result.current).toBe(errored);
|
|
528
|
+
expect(lateError).toHaveBeenCalledTimes(1);
|
|
529
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(1);
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
it("REGRESSION: an error-state consumer does not loop failing fetches (bounded attempt count)", () => {
|
|
533
|
+
// Reproduces the retry storm: a consumer that stores the sync error in
|
|
534
|
+
// state re-renders on every failure. With eviction-on-error, each
|
|
535
|
+
// re-render acquired a fresh entry with a fresh failing sync — an
|
|
536
|
+
// unbounded fetch loop (froze storybook renderers, OOM'd vitest
|
|
537
|
+
// workers). The errored entry must be a stable fixpoint instead.
|
|
538
|
+
const config = configFor("errloop");
|
|
539
|
+
const options = { filters: { name: "TODO-001" } };
|
|
540
|
+
|
|
541
|
+
let failuresSeen = 0;
|
|
542
|
+
const consumer = renderHook(() => {
|
|
543
|
+
// Mimic the consumer pattern: setState-on-error → re-render.
|
|
544
|
+
const [, setError] = useState<unknown>(null);
|
|
545
|
+
return useFrappeCollection(config, "Todo", {
|
|
546
|
+
...options,
|
|
547
|
+
onSyncError: (error) => {
|
|
548
|
+
failuresSeen++;
|
|
549
|
+
setError(error);
|
|
550
|
+
},
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
// Fail every FRESH sync attempt the cache starts, like a down bench:
|
|
555
|
+
// each newly created collection errors exactly once. Under the old
|
|
556
|
+
// eviction-on-error semantics every round created a new collection, so
|
|
557
|
+
// this drove 25 attempts; the fix must hold it at one.
|
|
558
|
+
let failedAttempts = 0;
|
|
559
|
+
for (let round = 0; round < 25; round++) {
|
|
560
|
+
const calls = mockCreateFrappeCollection.mock.calls;
|
|
561
|
+
if (calls.length > failedAttempts) {
|
|
562
|
+
failedAttempts = calls.length;
|
|
563
|
+
const passedOptions = calls[calls.length - 1][1];
|
|
564
|
+
act(() => {
|
|
565
|
+
passedOptions.onSyncError(new Error(`sync failure ${round}`));
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
consumer.rerender();
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// ONE collection, ONE real failure surfaced — not 25 fresh attempts.
|
|
572
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(1);
|
|
573
|
+
expect(failuresSeen).toBe(1);
|
|
574
|
+
expect(consumer.result.current).toBeDefined();
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
it("REGRESSION: unmounting during an error state neither throws nor starts new syncs", () => {
|
|
578
|
+
const config = configFor("errunmount");
|
|
579
|
+
const options = { filters: { name: "TODO-001" } };
|
|
580
|
+
const a = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
581
|
+
|
|
582
|
+
const passedOptions = mockCreateFrappeCollection.mock.calls[0][1];
|
|
583
|
+
act(() => {
|
|
584
|
+
passedOptions.onSyncError(new Error("initial sync failed"));
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
expect(() => {
|
|
588
|
+
a.unmount();
|
|
589
|
+
act(() => {
|
|
590
|
+
vi.advanceTimersByTime(GC_WAIT_MS);
|
|
591
|
+
});
|
|
592
|
+
}).not.toThrow();
|
|
593
|
+
// Unmount must not have spawned another attempt.
|
|
594
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(1);
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
it("evicts the errored entry when the LAST consumer releases: the next mount is a fresh attempt (Retry contract)", () => {
|
|
598
|
+
const config = configFor("errretry");
|
|
599
|
+
const options = { filters: { name: "TODO-001" } };
|
|
600
|
+
const a = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
601
|
+
const errored = a.result.current;
|
|
602
|
+
|
|
603
|
+
const passedOptions = mockCreateFrappeCollection.mock.calls[0][1];
|
|
604
|
+
act(() => {
|
|
605
|
+
passedOptions.onSyncError(new Error("initial sync failed"));
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
// Retry-by-remount: the failing consumer unmounts…
|
|
609
|
+
a.unmount();
|
|
610
|
+
// …and the remount acquires a FRESH entry with a fresh sync attempt —
|
|
611
|
+
// immediately, not after a GC grace (a grace would replay the stale
|
|
612
|
+
// error back into the retry).
|
|
613
|
+
const retry = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
614
|
+
expect(retry.result.current).not.toBe(errored);
|
|
615
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(2);
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
it("an errored entry shared by two consumers survives one unmount and retries after both release", () => {
|
|
619
|
+
const config = configFor("errshared");
|
|
620
|
+
const options = { filters: { name: "TODO-001" } };
|
|
621
|
+
const a = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
622
|
+
const b = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
623
|
+
const errored = a.result.current;
|
|
624
|
+
|
|
625
|
+
const passedOptions = mockCreateFrappeCollection.mock.calls[0][1];
|
|
626
|
+
act(() => {
|
|
627
|
+
passedOptions.onSyncError(new Error("initial sync failed"));
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
// One consumer leaves: the other still holds the errored entry stably.
|
|
631
|
+
a.unmount();
|
|
632
|
+
b.rerender();
|
|
633
|
+
expect(b.result.current).toBe(errored);
|
|
634
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(1);
|
|
635
|
+
|
|
636
|
+
// Both released → next mount starts the one fresh attempt.
|
|
637
|
+
b.unmount();
|
|
638
|
+
const retry = renderHook(() => useFrappeCollection(config, "Todo", options));
|
|
639
|
+
expect(retry.result.current).not.toBe(errored);
|
|
640
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(2);
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
it("a released consumer's onSyncError no longer fires", () => {
|
|
644
|
+
const config = configFor("errrelease");
|
|
645
|
+
const options = { filters: { name: "TODO-001" } };
|
|
646
|
+
const errorA = vi.fn();
|
|
647
|
+
const errorB = vi.fn();
|
|
648
|
+
const a = renderHook(() =>
|
|
649
|
+
useFrappeCollection(config, "Todo", { ...options, onSyncError: errorA }),
|
|
650
|
+
);
|
|
651
|
+
renderHook(() => useFrappeCollection(config, "Todo", { ...options, onSyncError: errorB }));
|
|
652
|
+
|
|
653
|
+
a.unmount();
|
|
654
|
+
const passedOptions = mockCreateFrappeCollection.mock.calls[0][1];
|
|
655
|
+
act(() => {
|
|
656
|
+
passedOptions.onSyncError(new Error("late failure"));
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
expect(errorA).not.toHaveBeenCalled();
|
|
660
|
+
expect(errorB).toHaveBeenCalledTimes(1);
|
|
661
|
+
});
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
// ---------------------------------------------------------------------------
|
|
665
|
+
// useFrappeCollection — GC vs live-query subscribers
|
|
666
|
+
// ---------------------------------------------------------------------------
|
|
667
|
+
//
|
|
668
|
+
// Live queries subscribe to a collection outside the hook refcount
|
|
669
|
+
// (synchronously during render; detaching asynchronously through TanStack
|
|
670
|
+
// DB's own GC). Cleaning up a collection while a query is attached
|
|
671
|
+
// permanently errors the query ("Source collection … was manually cleaned up
|
|
672
|
+
// while live query … depends on it"), so the registry GC must defer while
|
|
673
|
+
// `collection.subscriberCount > 0` — bounded by a force window that reclaims
|
|
674
|
+
// collections pinned by leaked queries from never-committed renders.
|
|
675
|
+
|
|
676
|
+
describe("useFrappeCollection shared cache — GC vs live queries", () => {
|
|
677
|
+
let testNum = 200;
|
|
678
|
+
/** > SHARED_COLLECTION_GC_MS in frappeReact.ts */
|
|
679
|
+
const GC_WAIT_MS = 1_500;
|
|
680
|
+
/** > SHARED_COLLECTION_GC_FORCE_MS in frappeReact.ts (plus defer ticks) */
|
|
681
|
+
const FORCE_WAIT_MS = 40_000;
|
|
682
|
+
|
|
683
|
+
/** Mock collection mirroring the TanStack DB surface the registry relies
|
|
684
|
+
* on: `subscriberCount`, `status`, `on("status:change")`, and a cleanup()
|
|
685
|
+
* that transitions status and emits the event (as the real one does). */
|
|
686
|
+
const makeLiveCollection = () => {
|
|
687
|
+
const listeners = new Set<(event: { status?: string }) => void>();
|
|
688
|
+
const collection: any = {
|
|
689
|
+
id: `collection-${Math.random().toString(36).slice(2)}`,
|
|
690
|
+
status: "ready",
|
|
691
|
+
subscriberCount: 0,
|
|
692
|
+
on: vi.fn((event: string, cb: (event: { status?: string }) => void) => {
|
|
693
|
+
if (event === "status:change") listeners.add(cb);
|
|
694
|
+
return () => listeners.delete(cb);
|
|
695
|
+
}),
|
|
696
|
+
cleanup: vi.fn(() => {
|
|
697
|
+
collection.status = "cleaned-up";
|
|
698
|
+
for (const cb of [...listeners]) cb({ status: "cleaned-up" });
|
|
699
|
+
}),
|
|
700
|
+
};
|
|
701
|
+
return collection;
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
beforeEach(() => {
|
|
705
|
+
testNum++;
|
|
706
|
+
vi.clearAllMocks();
|
|
707
|
+
vi.useFakeTimers();
|
|
708
|
+
mockIsBrowser.mockReturnValue(true);
|
|
709
|
+
mockCreateFrappeCollection.mockImplementation(() => makeLiveCollection());
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
afterEach(() => {
|
|
713
|
+
vi.runOnlyPendingTimers();
|
|
714
|
+
vi.useRealTimers();
|
|
715
|
+
mockIsBrowser.mockReturnValue(true);
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
const configFor = (label: string): UseFrappeCollectionConfig => ({
|
|
719
|
+
baseURL: `https://gcrace-${label}-${testNum}.example.com`,
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
it("defers cleanup while a live query is still attached, then cleans up once it detaches", () => {
|
|
723
|
+
const config = configFor("defer");
|
|
724
|
+
const a = renderHook(() => useFrappeCollection(config, "Workspace"));
|
|
725
|
+
const shared = a.result.current as any;
|
|
726
|
+
|
|
727
|
+
// A live query attached to the collection (e.g. created during render or
|
|
728
|
+
// still detaching through TanStack's idle GC after unmount).
|
|
729
|
+
shared.subscriberCount = 1;
|
|
730
|
+
a.unmount();
|
|
731
|
+
|
|
732
|
+
act(() => {
|
|
733
|
+
vi.advanceTimersByTime(GC_WAIT_MS);
|
|
734
|
+
});
|
|
735
|
+
expect(shared.cleanup).not.toHaveBeenCalled();
|
|
736
|
+
act(() => {
|
|
737
|
+
vi.advanceTimersByTime(3 * GC_WAIT_MS);
|
|
738
|
+
});
|
|
739
|
+
expect(shared.cleanup).not.toHaveBeenCalled();
|
|
740
|
+
|
|
741
|
+
// Query detaches → the next deferred GC tick cleans up.
|
|
742
|
+
shared.subscriberCount = 0;
|
|
743
|
+
act(() => {
|
|
744
|
+
vi.advanceTimersByTime(GC_WAIT_MS);
|
|
745
|
+
});
|
|
746
|
+
expect(shared.cleanup).toHaveBeenCalledTimes(1);
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
it("a remount during a deferred GC window reuses the same still-live collection", () => {
|
|
750
|
+
const config = configFor("remountdefer");
|
|
751
|
+
const a = renderHook(() => useFrappeCollection(config, "Workspace"));
|
|
752
|
+
const shared = a.result.current as any;
|
|
753
|
+
shared.subscriberCount = 1;
|
|
754
|
+
a.unmount();
|
|
755
|
+
|
|
756
|
+
// Past the plain grace period — the entry survives on the deferral path.
|
|
757
|
+
act(() => {
|
|
758
|
+
vi.advanceTimersByTime(2 * GC_WAIT_MS);
|
|
759
|
+
});
|
|
760
|
+
const b = renderHook(() => useFrappeCollection(config, "Workspace"));
|
|
761
|
+
expect(b.result.current).toBe(shared);
|
|
762
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(1);
|
|
763
|
+
|
|
764
|
+
// Retained again: even the force window passing must not clean it up.
|
|
765
|
+
act(() => {
|
|
766
|
+
vi.advanceTimersByTime(FORCE_WAIT_MS);
|
|
767
|
+
});
|
|
768
|
+
expect(shared.cleanup).not.toHaveBeenCalled();
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
it("force-cleans after the max defer window when a leaked query pins the collection", () => {
|
|
772
|
+
const config = configFor("force");
|
|
773
|
+
const a = renderHook(() => useFrappeCollection(config, "Workspace"));
|
|
774
|
+
const shared = a.result.current as any;
|
|
775
|
+
// A query that never detaches (created by a render that never committed —
|
|
776
|
+
// TanStack DB never arms its GC because it never had a subscriber).
|
|
777
|
+
shared.subscriberCount = 1;
|
|
778
|
+
a.unmount();
|
|
779
|
+
|
|
780
|
+
act(() => {
|
|
781
|
+
vi.advanceTimersByTime(FORCE_WAIT_MS);
|
|
782
|
+
});
|
|
783
|
+
expect(shared.cleanup).toHaveBeenCalledTimes(1);
|
|
784
|
+
|
|
785
|
+
// A later consumer gets a fresh collection, not the force-cleaned husk.
|
|
786
|
+
const b = renderHook(() => useFrappeCollection(config, "Workspace"));
|
|
787
|
+
expect(b.result.current).not.toBe(shared);
|
|
788
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(2);
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
it("each idle period gets a fresh force window (deadline resets on retain)", () => {
|
|
792
|
+
const config = configFor("deadlinereset");
|
|
793
|
+
const a = renderHook(() => useFrappeCollection(config, "Workspace"));
|
|
794
|
+
const shared = a.result.current as any;
|
|
795
|
+
shared.subscriberCount = 1;
|
|
796
|
+
a.unmount();
|
|
797
|
+
|
|
798
|
+
// Burn most of the force window, then retain (remount) — resetting it.
|
|
799
|
+
act(() => {
|
|
800
|
+
vi.advanceTimersByTime(25_000);
|
|
801
|
+
});
|
|
802
|
+
const b = renderHook(() => useFrappeCollection(config, "Workspace"));
|
|
803
|
+
expect(b.result.current).toBe(shared);
|
|
804
|
+
b.unmount();
|
|
805
|
+
|
|
806
|
+
// A fresh full window applies after the release; 25s in, still deferred.
|
|
807
|
+
act(() => {
|
|
808
|
+
vi.advanceTimersByTime(25_000);
|
|
809
|
+
});
|
|
810
|
+
expect(shared.cleanup).not.toHaveBeenCalled();
|
|
811
|
+
act(() => {
|
|
812
|
+
vi.advanceTimersByTime(FORCE_WAIT_MS);
|
|
813
|
+
});
|
|
814
|
+
expect(shared.cleanup).toHaveBeenCalledTimes(1);
|
|
815
|
+
});
|
|
816
|
+
|
|
817
|
+
it("hands out a fresh collection when a cached entry's collection was cleaned up out-of-band", () => {
|
|
818
|
+
const config = configFor("stalerender");
|
|
819
|
+
const a = renderHook(() => useFrappeCollection(config, "Workspace"));
|
|
820
|
+
const stale = a.result.current as any;
|
|
821
|
+
|
|
822
|
+
// Out-of-band teardown the registry didn't drive (e.g. TanStack DB's own
|
|
823
|
+
// idle GC after every query detached, or a manual cleanup() call) — the
|
|
824
|
+
// status listener bumps the mounted consumer onto a fresh entry.
|
|
825
|
+
act(() => {
|
|
826
|
+
stale.cleanup();
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
expect(a.result.current).not.toBe(stale);
|
|
830
|
+
expect((a.result.current as any).status).not.toBe("cleaned-up");
|
|
831
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(2);
|
|
832
|
+
|
|
833
|
+
// New consumers share the fresh entry, not the husk.
|
|
834
|
+
const b = renderHook(() => useFrappeCollection(config, "Workspace"));
|
|
835
|
+
expect(b.result.current).toBe(a.result.current);
|
|
836
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(2);
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
it("REGRESSION: releasing an errored entry defers collection cleanup until live queries detach", () => {
|
|
840
|
+
// Unmount-during-error: the release evicts the entry immediately (Retry
|
|
841
|
+
// contract) but must NOT cleanup() while a live query is still attached
|
|
842
|
+
// — that would hard-error the query mid-detach ("Source collection …
|
|
843
|
+
// was manually cleaned up while live query … depends on it").
|
|
844
|
+
const config = configFor("erridle");
|
|
845
|
+
const a = renderHook(() => useFrappeCollection(config, "Workspace"));
|
|
846
|
+
const shared = a.result.current as any;
|
|
847
|
+
shared.subscriberCount = 1; // live query attached by the consumer's render
|
|
848
|
+
|
|
849
|
+
const passedOptions = mockCreateFrappeCollection.mock.calls[0][1];
|
|
850
|
+
act(() => {
|
|
851
|
+
passedOptions.onSyncError(new Error("initial sync failed"));
|
|
852
|
+
});
|
|
853
|
+
a.unmount();
|
|
854
|
+
|
|
855
|
+
// Evicted at once: a remount gets a fresh entry (fresh attempt) …
|
|
856
|
+
const retry = renderHook(() => useFrappeCollection(config, "Workspace"));
|
|
857
|
+
expect(retry.result.current).not.toBe(shared);
|
|
858
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(2);
|
|
859
|
+
|
|
860
|
+
// … while the old collection's cleanup waits for the query to detach.
|
|
861
|
+
act(() => {
|
|
862
|
+
vi.advanceTimersByTime(GC_WAIT_MS);
|
|
863
|
+
});
|
|
864
|
+
expect(shared.cleanup).not.toHaveBeenCalled();
|
|
865
|
+
shared.subscriberCount = 0;
|
|
866
|
+
act(() => {
|
|
867
|
+
vi.advanceTimersByTime(GC_WAIT_MS);
|
|
868
|
+
});
|
|
869
|
+
expect(shared.cleanup).toHaveBeenCalledTimes(1);
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
it("mount→unmount→mount within the grace window (StrictMode/HMR pattern) keeps one live instance", () => {
|
|
873
|
+
const config = configFor("strictish");
|
|
874
|
+
const a = renderHook(() => useFrappeCollection(config, "Workspace"));
|
|
875
|
+
const shared = a.result.current as any;
|
|
876
|
+
shared.subscriberCount = 1; // live query attached by the first mount
|
|
877
|
+
a.unmount();
|
|
878
|
+
|
|
879
|
+
// Remount well inside the grace window.
|
|
880
|
+
act(() => {
|
|
881
|
+
vi.advanceTimersByTime(200);
|
|
882
|
+
});
|
|
883
|
+
const b = renderHook(() => useFrappeCollection(config, "Workspace"));
|
|
884
|
+
expect(b.result.current).toBe(shared);
|
|
885
|
+
|
|
886
|
+
act(() => {
|
|
887
|
+
vi.advanceTimersByTime(FORCE_WAIT_MS);
|
|
888
|
+
});
|
|
889
|
+
expect(shared.cleanup).not.toHaveBeenCalled();
|
|
890
|
+
expect(mockCreateFrappeCollection).toHaveBeenCalledTimes(1);
|
|
891
|
+
});
|
|
328
892
|
});
|
|
329
893
|
|
|
330
894
|
// ---------------------------------------------------------------------------
|