@dittolive/ditto 4.4.5 → 4.5.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/DittoReactNative.podspec +27 -0
- package/README.md +68 -51
- package/node/ditto.cjs.js +1639 -851
- package/node/ditto.darwin-arm64.node +0 -0
- package/node/ditto.darwin-x64.node +0 -0
- package/node/ditto.linux-arm.node +0 -0
- package/node/ditto.linux-x64.node +0 -0
- package/node/ditto.win32-x64.node +0 -0
- package/node/transports.darwin-arm64.node +0 -0
- package/node/transports.darwin-x64.node +0 -0
- package/package.json +34 -38
- package/react-native/android/CMakeLists.txt +37 -0
- package/react-native/android/build.gradle +203 -0
- package/react-native/android/cpp-adapter.cpp +254 -0
- package/react-native/android/gradle.properties +5 -0
- package/react-native/android/src/main/AndroidManifest.xml +4 -0
- package/react-native/android/src/main/java/com/dittolive/rnsdk/DittoRNSDKModule.java +85 -0
- package/react-native/android/src/main/java/com/dittolive/rnsdk/DittoRNSDKPackage.java +28 -0
- package/react-native/boost/boost/assert.hpp +85 -0
- package/react-native/boost/boost/config/abi/borland_prefix.hpp +27 -0
- package/react-native/boost/boost/config/abi/borland_suffix.hpp +12 -0
- package/react-native/boost/boost/config/abi/msvc_prefix.hpp +22 -0
- package/react-native/boost/boost/config/abi/msvc_suffix.hpp +8 -0
- package/react-native/boost/boost/config/abi_prefix.hpp +25 -0
- package/react-native/boost/boost/config/abi_suffix.hpp +25 -0
- package/react-native/boost/boost/config/assert_cxx03.hpp +211 -0
- package/react-native/boost/boost/config/assert_cxx11.hpp +209 -0
- package/react-native/boost/boost/config/assert_cxx14.hpp +47 -0
- package/react-native/boost/boost/config/assert_cxx17.hpp +62 -0
- package/react-native/boost/boost/config/assert_cxx20.hpp +59 -0
- package/react-native/boost/boost/config/assert_cxx98.hpp +23 -0
- package/react-native/boost/boost/config/auto_link.hpp +525 -0
- package/react-native/boost/boost/config/compiler/borland.hpp +339 -0
- package/react-native/boost/boost/config/compiler/clang.hpp +366 -0
- package/react-native/boost/boost/config/compiler/clang_version.hpp +83 -0
- package/react-native/boost/boost/config/compiler/codegear.hpp +385 -0
- package/react-native/boost/boost/config/compiler/comeau.hpp +59 -0
- package/react-native/boost/boost/config/compiler/common_edg.hpp +183 -0
- package/react-native/boost/boost/config/compiler/compaq_cxx.hpp +19 -0
- package/react-native/boost/boost/config/compiler/cray.hpp +446 -0
- package/react-native/boost/boost/config/compiler/diab.hpp +26 -0
- package/react-native/boost/boost/config/compiler/digitalmars.hpp +143 -0
- package/react-native/boost/boost/config/compiler/gcc.hpp +383 -0
- package/react-native/boost/boost/config/compiler/gcc_xml.hpp +114 -0
- package/react-native/boost/boost/config/compiler/greenhills.hpp +28 -0
- package/react-native/boost/boost/config/compiler/hp_acc.hpp +149 -0
- package/react-native/boost/boost/config/compiler/intel.hpp +577 -0
- package/react-native/boost/boost/config/compiler/kai.hpp +33 -0
- package/react-native/boost/boost/config/compiler/metrowerks.hpp +198 -0
- package/react-native/boost/boost/config/compiler/mpw.hpp +140 -0
- package/react-native/boost/boost/config/compiler/nvcc.hpp +61 -0
- package/react-native/boost/boost/config/compiler/pathscale.hpp +138 -0
- package/react-native/boost/boost/config/compiler/pgi.hpp +23 -0
- package/react-native/boost/boost/config/compiler/sgi_mipspro.hpp +29 -0
- package/react-native/boost/boost/config/compiler/sunpro_cc.hpp +222 -0
- package/react-native/boost/boost/config/compiler/vacpp.hpp +186 -0
- package/react-native/boost/boost/config/compiler/visualc.hpp +391 -0
- package/react-native/boost/boost/config/compiler/xlcpp.hpp +299 -0
- package/react-native/boost/boost/config/compiler/xlcpp_zos.hpp +173 -0
- package/react-native/boost/boost/config/detail/cxx_composite.hpp +203 -0
- package/react-native/boost/boost/config/detail/posix_features.hpp +95 -0
- package/react-native/boost/boost/config/detail/select_compiler_config.hpp +157 -0
- package/react-native/boost/boost/config/detail/select_platform_config.hpp +147 -0
- package/react-native/boost/boost/config/detail/select_stdlib_config.hpp +121 -0
- package/react-native/boost/boost/config/detail/suffix.hpp +1294 -0
- package/react-native/boost/boost/config/header_deprecated.hpp +26 -0
- package/react-native/boost/boost/config/helper_macros.hpp +37 -0
- package/react-native/boost/boost/config/no_tr1/cmath.hpp +28 -0
- package/react-native/boost/boost/config/no_tr1/complex.hpp +28 -0
- package/react-native/boost/boost/config/no_tr1/functional.hpp +28 -0
- package/react-native/boost/boost/config/no_tr1/memory.hpp +28 -0
- package/react-native/boost/boost/config/no_tr1/utility.hpp +28 -0
- package/react-native/boost/boost/config/platform/aix.hpp +33 -0
- package/react-native/boost/boost/config/platform/amigaos.hpp +15 -0
- package/react-native/boost/boost/config/platform/beos.hpp +26 -0
- package/react-native/boost/boost/config/platform/bsd.hpp +83 -0
- package/react-native/boost/boost/config/platform/cloudabi.hpp +18 -0
- package/react-native/boost/boost/config/platform/cray.hpp +18 -0
- package/react-native/boost/boost/config/platform/cygwin.hpp +71 -0
- package/react-native/boost/boost/config/platform/haiku.hpp +31 -0
- package/react-native/boost/boost/config/platform/hpux.hpp +87 -0
- package/react-native/boost/boost/config/platform/irix.hpp +31 -0
- package/react-native/boost/boost/config/platform/linux.hpp +106 -0
- package/react-native/boost/boost/config/platform/macos.hpp +87 -0
- package/react-native/boost/boost/config/platform/qnxnto.hpp +31 -0
- package/react-native/boost/boost/config/platform/solaris.hpp +31 -0
- package/react-native/boost/boost/config/platform/symbian.hpp +97 -0
- package/react-native/boost/boost/config/platform/vms.hpp +25 -0
- package/react-native/boost/boost/config/platform/vxworks.hpp +422 -0
- package/react-native/boost/boost/config/platform/wasm.hpp +23 -0
- package/react-native/boost/boost/config/platform/win32.hpp +90 -0
- package/react-native/boost/boost/config/platform/zos.hpp +32 -0
- package/react-native/boost/boost/config/pragma_message.hpp +31 -0
- package/react-native/boost/boost/config/requires_threads.hpp +92 -0
- package/react-native/boost/boost/config/stdlib/dinkumware.hpp +324 -0
- package/react-native/boost/boost/config/stdlib/libcomo.hpp +93 -0
- package/react-native/boost/boost/config/stdlib/libcpp.hpp +180 -0
- package/react-native/boost/boost/config/stdlib/libstdcpp3.hpp +482 -0
- package/react-native/boost/boost/config/stdlib/modena.hpp +79 -0
- package/react-native/boost/boost/config/stdlib/msl.hpp +98 -0
- package/react-native/boost/boost/config/stdlib/roguewave.hpp +208 -0
- package/react-native/boost/boost/config/stdlib/sgi.hpp +168 -0
- package/react-native/boost/boost/config/stdlib/stlport.hpp +258 -0
- package/react-native/boost/boost/config/stdlib/vacpp.hpp +74 -0
- package/react-native/boost/boost/config/stdlib/xlcpp_zos.hpp +61 -0
- package/react-native/boost/boost/config/user.hpp +133 -0
- package/react-native/boost/boost/config/warning_disable.hpp +47 -0
- package/react-native/boost/boost/config/workaround.hpp +305 -0
- package/react-native/boost/boost/config.hpp +67 -0
- package/react-native/boost/boost/cstdint.hpp +556 -0
- package/react-native/boost/boost/intrusive_ptr.hpp +18 -0
- package/react-native/boost/boost/smart_ptr/detail/atomic_count.hpp +103 -0
- package/react-native/boost/boost/smart_ptr/detail/atomic_count_gcc.hpp +79 -0
- package/react-native/boost/boost/smart_ptr/detail/atomic_count_gcc_atomic.hpp +63 -0
- package/react-native/boost/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp +88 -0
- package/react-native/boost/boost/smart_ptr/detail/atomic_count_nt.hpp +66 -0
- package/react-native/boost/boost/smart_ptr/detail/atomic_count_pt.hpp +104 -0
- package/react-native/boost/boost/smart_ptr/detail/atomic_count_spin.hpp +69 -0
- package/react-native/boost/boost/smart_ptr/detail/atomic_count_std_atomic.hpp +67 -0
- package/react-native/boost/boost/smart_ptr/detail/atomic_count_sync.hpp +72 -0
- package/react-native/boost/boost/smart_ptr/detail/atomic_count_win32.hpp +70 -0
- package/react-native/boost/boost/smart_ptr/detail/local_counted_base.hpp +148 -0
- package/react-native/boost/boost/smart_ptr/detail/local_sp_deleter.hpp +91 -0
- package/react-native/boost/boost/smart_ptr/detail/operator_bool.hpp +64 -0
- package/react-native/boost/boost/smart_ptr/detail/requires_cxx11.hpp +23 -0
- package/react-native/boost/boost/smart_ptr/detail/shared_count.hpp +707 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_convertible.hpp +92 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base.hpp +92 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp +163 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_aix.hpp +152 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp +185 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp +148 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp +170 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +200 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp +194 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp +179 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp +186 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_nt.hpp +119 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_pt.hpp +147 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp +174 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_spin.hpp +141 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp +147 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_sync.hpp +165 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp +163 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_base_w32.hpp +140 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_counted_impl.hpp +309 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_disable_deprecated.hpp +40 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_forward.hpp +52 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_has_gcc_intrinsics.hpp +27 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_has_sync_intrinsics.hpp +69 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_interlocked.hpp +173 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_noexcept.hpp +48 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_nullptr_t.hpp +45 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_obsolete.hpp +32 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_thread_pause.hpp +51 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_thread_sleep.hpp +104 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_thread_yield.hpp +100 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_typeinfo_.hpp +58 -0
- package/react-native/boost/boost/smart_ptr/detail/sp_win32_sleep.hpp +49 -0
- package/react-native/boost/boost/smart_ptr/intrusive_ptr.hpp +409 -0
- package/react-native/boost/boost/smart_ptr/intrusive_ref_counter.hpp +188 -0
- package/react-native/cpp/include/Attachment.h +16 -0
- package/react-native/cpp/include/Authentication.h +23 -0
- package/react-native/cpp/include/Collection.h +13 -0
- package/react-native/cpp/include/DQL.h +21 -0
- package/react-native/cpp/include/Document.h +17 -0
- package/react-native/cpp/include/Identity.h +17 -0
- package/react-native/cpp/include/Lifecycle.h +16 -0
- package/react-native/cpp/include/LiveQuery.h +17 -0
- package/react-native/cpp/include/Logger.h +22 -0
- package/react-native/cpp/include/Misc.h +26 -0
- package/react-native/cpp/include/Presence.h +14 -0
- package/react-native/cpp/include/RetainableState.h +24 -0
- package/react-native/cpp/include/SmallPeerInfo.h +17 -0
- package/react-native/cpp/include/Transports.h +25 -0
- package/react-native/cpp/include/TypedArray.hpp +167 -0
- package/react-native/cpp/include/Utils.h +61 -0
- package/react-native/cpp/include/main.h +10 -0
- package/react-native/cpp/src/Attachment.cpp +86 -0
- package/react-native/cpp/src/Authentication.cpp +224 -0
- package/react-native/cpp/src/Collection.cpp +54 -0
- package/react-native/cpp/src/DQL.cpp +254 -0
- package/react-native/cpp/src/Document.cpp +146 -0
- package/react-native/cpp/src/Identity.cpp +123 -0
- package/react-native/cpp/src/Lifecycle.cpp +75 -0
- package/react-native/cpp/src/LiveQuery.cpp +64 -0
- package/react-native/cpp/src/Logger.cpp +200 -0
- package/react-native/cpp/src/Misc.cpp +271 -0
- package/react-native/cpp/src/Presence.cpp +77 -0
- package/react-native/cpp/src/RetainableState.cpp +15 -0
- package/react-native/cpp/src/SmallPeerInfo.cpp +108 -0
- package/react-native/cpp/src/Transports.cpp +270 -0
- package/react-native/cpp/src/TypedArray.cpp +303 -0
- package/react-native/cpp/src/Utils.cpp +138 -0
- package/react-native/cpp/src/main.cpp +149 -0
- package/react-native/dittoffi/dittoffi.h +4698 -0
- package/react-native/dittoffi/ifaddrs.cpp +385 -0
- package/react-native/dittoffi/ifaddrs.h +206 -0
- package/react-native/ios/DittoRNSDK.h +7 -0
- package/react-native/ios/DittoRNSDK.mm +107 -0
- package/react-native/ios/YeetJSIUtils.h +60 -0
- package/react-native/ios/YeetJSIUtils.mm +196 -0
- package/react-native/lib/commonjs/ditto.rn.js +93 -0
- package/react-native/lib/commonjs/ditto.rn.js.map +1 -0
- package/react-native/lib/commonjs/index.js +14 -0
- package/react-native/lib/commonjs/index.js.map +1 -0
- package/react-native/lib/module/ditto.rn.js +83 -0
- package/react-native/lib/module/ditto.rn.js.map +1 -0
- package/react-native/lib/module/index.js +13 -0
- package/react-native/lib/module/index.js.map +1 -0
- package/react-native/lib/typescript/ditto.rn.d.ts +15 -0
- package/react-native/lib/typescript/ditto.rn.d.ts.map +1 -0
- package/react-native/lib/typescript/index.d.ts +1 -0
- package/react-native/lib/typescript/index.d.ts.map +1 -0
- package/react-native/scripts/ruby/include_local_boost.rb +78 -0
- package/react-native/src/ditto.rn.ts +91 -0
- package/react-native/src/environment/environment.fallback.ts +4 -0
- package/react-native/src/index.ts +26 -0
- package/react-native/src/sources/@cbor-redux.ts +2 -0
- package/react-native/src/sources/@ditto.core.ts +1 -0
- package/react-native/src/sources/@environment.ts +2 -0
- package/react-native/src/sources/attachment-fetch-event.ts +54 -0
- package/react-native/src/sources/attachment-fetcher-manager.ts +129 -0
- package/react-native/src/sources/attachment-fetcher.ts +124 -0
- package/react-native/src/sources/attachment-token.ts +48 -0
- package/react-native/src/sources/attachment.ts +59 -0
- package/react-native/src/sources/augment.ts +89 -0
- package/react-native/src/sources/authenticator.ts +314 -0
- package/react-native/src/sources/base-pending-cursor-operation.ts +237 -0
- package/react-native/src/sources/base-pending-id-specific-operation.ts +109 -0
- package/react-native/src/sources/bridge.ts +549 -0
- package/react-native/src/sources/build-time-constants.ts +4 -0
- package/react-native/src/sources/cbor.ts +35 -0
- package/react-native/src/sources/collection-interface.ts +67 -0
- package/react-native/src/sources/collection.ts +212 -0
- package/react-native/src/sources/collections-event.ts +99 -0
- package/react-native/src/sources/counter.ts +77 -0
- package/react-native/src/sources/ditto.ts +945 -0
- package/react-native/src/sources/document-id.ts +159 -0
- package/react-native/src/sources/document-path.ts +303 -0
- package/react-native/src/sources/document.ts +192 -0
- package/react-native/src/sources/epilogue.ts +24 -0
- package/react-native/src/sources/error-codes.ts +52 -0
- package/react-native/src/sources/error.ts +203 -0
- package/react-native/src/sources/essentials.ts +53 -0
- package/react-native/src/sources/ffi-error.ts +117 -0
- package/react-native/src/sources/ffi.ts +1972 -0
- package/react-native/src/sources/identity.ts +163 -0
- package/react-native/src/sources/init.ts +70 -0
- package/react-native/src/sources/internal.ts +113 -0
- package/react-native/src/sources/keep-alive.ts +69 -0
- package/react-native/src/sources/key-path.ts +195 -0
- package/react-native/src/sources/live-query-event.ts +208 -0
- package/react-native/src/sources/live-query-manager.ts +101 -0
- package/react-native/src/sources/live-query.ts +164 -0
- package/react-native/src/sources/logger.ts +196 -0
- package/react-native/src/sources/observer-manager.ts +175 -0
- package/react-native/src/sources/observer.ts +77 -0
- package/react-native/src/sources/pending-collections-operation.ts +232 -0
- package/react-native/src/sources/pending-cursor-operation.ts +218 -0
- package/react-native/src/sources/pending-id-specific-operation.ts +216 -0
- package/react-native/src/sources/presence-manager.ts +160 -0
- package/react-native/src/sources/presence.ts +238 -0
- package/react-native/src/sources/query-result-item.ts +116 -0
- package/react-native/src/sources/query-result.ts +55 -0
- package/react-native/src/sources/register.ts +92 -0
- package/react-native/src/sources/small-peer-info.ts +176 -0
- package/react-native/src/sources/static-tcp-client.ts +6 -0
- package/react-native/src/sources/store-observer.ts +176 -0
- package/react-native/src/sources/store.ts +365 -0
- package/react-native/src/sources/subscription-manager.ts +98 -0
- package/react-native/src/sources/subscription.ts +88 -0
- package/react-native/src/sources/sync-subscription.ts +90 -0
- package/react-native/src/sources/sync.ts +495 -0
- package/react-native/src/sources/test-helpers.ts +24 -0
- package/react-native/src/sources/transport-conditions-manager.ts +104 -0
- package/react-native/src/sources/transport-config.ts +428 -0
- package/react-native/src/sources/update-result.ts +66 -0
- package/react-native/src/sources/update-results-map.ts +57 -0
- package/react-native/src/sources/websocket-client.ts +6 -0
- package/react-native/src/sources/write-transaction-collection.ts +122 -0
- package/react-native/src/sources/write-transaction-pending-cursor-operation.ts +101 -0
- package/react-native/src/sources/write-transaction-pending-id-specific-operation.ts +72 -0
- package/react-native/src/sources/write-transaction.ts +119 -0
- package/react-native.config.js +9 -0
- package/types/ditto.d.ts +1230 -798
- package/web/ditto.es6.js +1 -1
- package/web/ditto.umd.js +1 -1
- package/web/ditto.wasm +0 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright © 2021 DittoLive Incorporated. All rights reserved.
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { generateEphemeralToken } from './internal'
|
|
6
|
+
import { KeepAlive } from './keep-alive'
|
|
7
|
+
|
|
8
|
+
/** @internal */
|
|
9
|
+
export type ObserverToken = string
|
|
10
|
+
|
|
11
|
+
/** @internal */
|
|
12
|
+
export type ObserverManagerConstructorOptions = {
|
|
13
|
+
keepAlive?: KeepAlive
|
|
14
|
+
register?: (callback: (...args: any[]) => void) => void
|
|
15
|
+
unregister?: () => void
|
|
16
|
+
process?: (...args: any[]) => any[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** @internal */
|
|
20
|
+
export class ObserverManager {
|
|
21
|
+
/** @internal */
|
|
22
|
+
readonly id: string
|
|
23
|
+
|
|
24
|
+
/** @internal */
|
|
25
|
+
readonly keepAlive: KeepAlive | null
|
|
26
|
+
|
|
27
|
+
/** @internal */
|
|
28
|
+
constructor(id: string, options: ObserverManagerConstructorOptions = {}) {
|
|
29
|
+
const keepAlive = options.keepAlive ?? null
|
|
30
|
+
const register = options.register ?? null
|
|
31
|
+
const unregister = options.unregister ?? null
|
|
32
|
+
const process = options.process ?? null
|
|
33
|
+
|
|
34
|
+
this.id = id
|
|
35
|
+
this.keepAlive = keepAlive
|
|
36
|
+
|
|
37
|
+
this.isClosed = false
|
|
38
|
+
this.isRegistered = false
|
|
39
|
+
this.callbacksByToken = {}
|
|
40
|
+
|
|
41
|
+
if (register !== null) {
|
|
42
|
+
this.register = register
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (unregister !== null) {
|
|
46
|
+
this.unregister = unregister
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (process !== null) {
|
|
50
|
+
this.process = process
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** @internal */
|
|
55
|
+
addObserver(callback: any): ObserverToken {
|
|
56
|
+
if (this.isClosed) {
|
|
57
|
+
|
|
58
|
+
throw new Error(`Internal inconsistency, can't add '${this.id}' observer, observer mananger close()-ed.`)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
this.registerIfNeeded()
|
|
62
|
+
|
|
63
|
+
const token = generateEphemeralToken()
|
|
64
|
+
this.callbacksByToken[token] = callback
|
|
65
|
+
|
|
66
|
+
this.keepAlive?.retain(`${this.id}.${token}`)
|
|
67
|
+
return token
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** @internal */
|
|
71
|
+
removeObserver(token: ObserverToken): void {
|
|
72
|
+
const callback = this.callbacksByToken[token]
|
|
73
|
+
|
|
74
|
+
if (typeof callback === 'undefined') {
|
|
75
|
+
throw new Error(`Can't remove '${this.id}' observer, token '${token}' has never been registered before.`)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (callback === null) {
|
|
79
|
+
// Observer has already been removed, no-op.
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
this.callbacksByToken[token] = null
|
|
84
|
+
|
|
85
|
+
this.keepAlive?.release(`${this.id}.${token}`)
|
|
86
|
+
this.unregisterIfNeeded()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
hasObserver(token: ObserverToken): boolean {
|
|
90
|
+
return typeof this.callbacksByToken[token] != 'undefined'
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** @internal */
|
|
94
|
+
notify(...args: any[]) {
|
|
95
|
+
if (this.isClosed) {
|
|
96
|
+
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const processedArgs = this.process(...args)
|
|
101
|
+
for (const token in this.callbacksByToken) {
|
|
102
|
+
const callback = this.callbacksByToken[token]
|
|
103
|
+
if (callback) callback(...processedArgs)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** @internal */
|
|
108
|
+
close() {
|
|
109
|
+
this.isClosed = true
|
|
110
|
+
for (const token in this.callbacksByToken) {
|
|
111
|
+
this.removeObserver(token)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Can be injected and replaced via constructor options.
|
|
117
|
+
*
|
|
118
|
+
* @abstract
|
|
119
|
+
*/
|
|
120
|
+
protected register(callback: (...args: any[]) => void) {
|
|
121
|
+
// No-op, subclasses may override and register.
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Can be injected and replaced via constructor options.
|
|
126
|
+
*
|
|
127
|
+
* @abstract
|
|
128
|
+
*/
|
|
129
|
+
protected unregister() {
|
|
130
|
+
// No-op, subclasses may override and unregister.
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Can be injected and replaced via constructor options.
|
|
135
|
+
*
|
|
136
|
+
* @abstract
|
|
137
|
+
*/
|
|
138
|
+
protected process(...args: any[]): any[] {
|
|
139
|
+
// No-op, subclasses may override and process/transform the callback parameters.
|
|
140
|
+
return args
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private isClosed: boolean
|
|
144
|
+
private isRegistered: boolean
|
|
145
|
+
private callbacksByToken: { [key: string]: ((...args: any[]) => void) | null }
|
|
146
|
+
private constructorOptions: ObserverManagerConstructorOptions
|
|
147
|
+
|
|
148
|
+
private hasObservers(): boolean {
|
|
149
|
+
return Object.keys(this.callbacksByToken).length > 0
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private registerIfNeeded() {
|
|
153
|
+
const needsToRegister = !this.isRegistered
|
|
154
|
+
if (needsToRegister) {
|
|
155
|
+
const weakThis = new WeakRef(this)
|
|
156
|
+
this.isRegistered = true
|
|
157
|
+
this.register(function (...args) {
|
|
158
|
+
const strongThis = weakThis.deref()
|
|
159
|
+
if (!strongThis) {
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
strongThis.notify(...args)
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private unregisterIfNeeded() {
|
|
169
|
+
const needsToUnregister = !this.hasObservers() && this.isRegistered
|
|
170
|
+
if (needsToUnregister) {
|
|
171
|
+
this.isRegistered = false
|
|
172
|
+
this.unregister()
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright © 2021 DittoLive Incorporated. All rights reserved.
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import type { ObserverToken } from './observer-manager'
|
|
6
|
+
|
|
7
|
+
/** @internal */
|
|
8
|
+
interface ObserverManaging {
|
|
9
|
+
hasObserver(token: ObserverToken): boolean
|
|
10
|
+
removeObserver(token: ObserverToken): void
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** @internal */
|
|
14
|
+
export type ObserverOptions = {
|
|
15
|
+
stopsWhenFinalized?: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Generic observer handle returned by various observation APIs. The observation
|
|
20
|
+
* remains active until the {@link stop | stop()} method is called explicitly or
|
|
21
|
+
* the observer instance is garbage collected. Therefore, to keep the observation
|
|
22
|
+
* alive, you have to keep a reference to the corresponding observer.
|
|
23
|
+
*/
|
|
24
|
+
export class Observer {
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
/** @internal */
|
|
28
|
+
readonly observerManager: ObserverManaging
|
|
29
|
+
|
|
30
|
+
/** @internal */
|
|
31
|
+
get token(): ObserverToken | undefined {
|
|
32
|
+
return this._token
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** @internal */
|
|
36
|
+
readonly options?: ObserverOptions
|
|
37
|
+
|
|
38
|
+
/** @internal */
|
|
39
|
+
constructor(observerManager: ObserverManaging, token: any, options: ObserverOptions = {}) {
|
|
40
|
+
this.observerManager = observerManager
|
|
41
|
+
this._token = token
|
|
42
|
+
this.options = options
|
|
43
|
+
|
|
44
|
+
if (options.stopsWhenFinalized) {
|
|
45
|
+
Observer.finalizationRegistry.register(this, { observerManager, token }, this)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Returns `true` if the observer has been explicitly stopped via the `stop()`
|
|
51
|
+
* method. Otherwise returns `false`.
|
|
52
|
+
*/
|
|
53
|
+
get isStopped(): boolean {
|
|
54
|
+
return this.token !== undefined && this.observerManager.hasObserver(this.token)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Stops the observation. Calling this method multiple times has no effect.
|
|
59
|
+
*/
|
|
60
|
+
stop() {
|
|
61
|
+
const token = this.token
|
|
62
|
+
if (token) {
|
|
63
|
+
delete this._token
|
|
64
|
+
Observer.finalizationRegistry.unregister(this)
|
|
65
|
+
this.observerManager.removeObserver(token)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private static finalizationRegistry = new FinalizationRegistry(Observer.finalize)
|
|
70
|
+
|
|
71
|
+
private _token?: ObserverToken
|
|
72
|
+
|
|
73
|
+
private static finalize(observerManagerAndToken: { observerManager: ObserverManaging; token: ObserverToken }) {
|
|
74
|
+
const { observerManager, token } = observerManagerAndToken
|
|
75
|
+
observerManager.removeObserver(token)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright (c) 2020 - 2021 DittoLive Inc. All rights reserved.
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Collection } from './collection'
|
|
6
|
+
import { Document } from './document'
|
|
7
|
+
import { Store } from './store'
|
|
8
|
+
import { Subscription } from './subscription'
|
|
9
|
+
import { PendingCursorOperation } from './pending-cursor-operation'
|
|
10
|
+
|
|
11
|
+
import { CollectionsEvent } from './collections-event'
|
|
12
|
+
import { LiveQuery } from './live-query'
|
|
13
|
+
|
|
14
|
+
import type { SortDirection } from './essentials'
|
|
15
|
+
// -----------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The closure that is called whenever the collections covered by a live query
|
|
19
|
+
* change.
|
|
20
|
+
*/
|
|
21
|
+
export type CollectionsObservationHandler = (event: CollectionsEvent, signalNext?: () => void) => void | Promise<void>
|
|
22
|
+
|
|
23
|
+
// -----------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* These objects are returned when calling
|
|
27
|
+
* {@link Store.collections | collections()} on {@link Store}.
|
|
28
|
+
*
|
|
29
|
+
* They allow chaining of further collections-related functions. You can either
|
|
30
|
+
* call {@link exec | exec()} on the object to get an array of
|
|
31
|
+
* {@link Collection}s as an immediate return value, or you can establish either
|
|
32
|
+
* a live query or a subscription, which both work over time.
|
|
33
|
+
*
|
|
34
|
+
* A live query, established by calling
|
|
35
|
+
* {@link PendingCollectionsOperation.observeLocal | observeLocal()}, will
|
|
36
|
+
* notify you every time there's a change in the collections that the device
|
|
37
|
+
* knows about.
|
|
38
|
+
*
|
|
39
|
+
* A subscription, established by calling {@link subscribe | subscribe()}, will
|
|
40
|
+
* act as a signal to other peers that the device connects to that you would
|
|
41
|
+
* like to receive updates from them about the collections that they know about.
|
|
42
|
+
*/
|
|
43
|
+
export class PendingCollectionsOperation implements PromiseLike<Collection[]> {
|
|
44
|
+
/**
|
|
45
|
+
* Sort the collections based on a property of the collection.
|
|
46
|
+
*
|
|
47
|
+
* @param propertyPath The property path specifies the logic to be used when
|
|
48
|
+
* sorting the matching collections.
|
|
49
|
+
*
|
|
50
|
+
* @param direction Specify whether you want the sorting order to be
|
|
51
|
+
* `Ascending` or `Descending`.
|
|
52
|
+
*
|
|
53
|
+
* @return A {@link PendingCollectionsOperation} that you can chain further
|
|
54
|
+
* function calls to.
|
|
55
|
+
*/
|
|
56
|
+
sort(propertyPath: string, direction: SortDirection = 'ascending'): PendingCollectionsOperation {
|
|
57
|
+
this.pendingCursorOperation.sort(propertyPath, direction)
|
|
58
|
+
return this
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Offset the resulting set of collections.
|
|
63
|
+
*
|
|
64
|
+
* This is useful if you aren't interested in the first N collections for one
|
|
65
|
+
* reason or another. For example, you might already have obtained the first
|
|
66
|
+
* 20 collections and so you might want to get the next 20 collections, and
|
|
67
|
+
* that is when you would use {@link offset | offset()}.
|
|
68
|
+
*
|
|
69
|
+
* @param offset The number of collections that you want the eventual
|
|
70
|
+
* resulting set of collections to be offset by (and thus not include).
|
|
71
|
+
*
|
|
72
|
+
* @return A {@link PendingCollectionsOperation} that you can chain further
|
|
73
|
+
* function calls to.
|
|
74
|
+
*/
|
|
75
|
+
offset(offset: number): PendingCollectionsOperation {
|
|
76
|
+
this.pendingCursorOperation.offset(offset)
|
|
77
|
+
return this
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Limit the number of collections that get returned.
|
|
82
|
+
*
|
|
83
|
+
* @param limit The maximum number of collections that will be returned.
|
|
84
|
+
*
|
|
85
|
+
* @return A {@link PendingCollectionsOperation} that you can chain further
|
|
86
|
+
* function calls to.
|
|
87
|
+
*/
|
|
88
|
+
limit(limit: number): PendingCollectionsOperation {
|
|
89
|
+
this.pendingCursorOperation.limit(limit)
|
|
90
|
+
return this
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Subscribes the device to updates about collections that other devices know
|
|
95
|
+
* about.
|
|
96
|
+
*
|
|
97
|
+
* The returned {@link Subscription} object must be kept in scope for as long
|
|
98
|
+
* as you want to keep receiving updates.
|
|
99
|
+
*
|
|
100
|
+
* @return A {@link Subscription} object that must be kept in scope for as
|
|
101
|
+
* long as you want to keep receiving updates from other devices about the
|
|
102
|
+
* collections that they know about.
|
|
103
|
+
*/
|
|
104
|
+
subscribe(): Subscription {
|
|
105
|
+
return this.pendingCursorOperation.subscribe()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Enables you to listen for changes that occur in relation to the collections
|
|
110
|
+
* that are known about locally.
|
|
111
|
+
*
|
|
112
|
+
* The returned {@link LiveQuery} object must be kept in scope for as long as
|
|
113
|
+
* you want the provided `handler` to be called when an update occurs.
|
|
114
|
+
*
|
|
115
|
+
* This won't subscribe to receive updates from other devices and so it will
|
|
116
|
+
* only fire when a local change to the known about collections occurs. If
|
|
117
|
+
* you want to receive remote updates as well, then create a subscription via
|
|
118
|
+
* {@link PendingCollectionsOperation.subscribe | subscribe()}.
|
|
119
|
+
*
|
|
120
|
+
* @param handler A closure that will be called every time there is an update
|
|
121
|
+
* about the list of known about collections.
|
|
122
|
+
*
|
|
123
|
+
* @return A {@link LiveQuery} object that must be kept in scope for as long
|
|
124
|
+
* as you want to keep receiving updates.
|
|
125
|
+
*/
|
|
126
|
+
observeLocal(handler: CollectionsObservationHandler): LiveQuery {
|
|
127
|
+
return this._observe(handler, false)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Enables you to listen for changes that occur in relation to the collections
|
|
132
|
+
* that are known about locally.
|
|
133
|
+
*
|
|
134
|
+
* The returned {@link LiveQuery} object must be kept in scope for as long as
|
|
135
|
+
* you want the provided `handler` to be called when an update occurs.
|
|
136
|
+
*
|
|
137
|
+
* This won't subscribe to receive updates from other devices and so it will
|
|
138
|
+
* only fire when a local change to the known about collections occurs. If
|
|
139
|
+
* you want to receive remote updates as well, then create a subscription via
|
|
140
|
+
* {@link PendingCollectionsOperation.subscribe | subscribe()}.
|
|
141
|
+
*
|
|
142
|
+
* @param handler A closure that will be called every time there is an update
|
|
143
|
+
* about the list of known about collections.
|
|
144
|
+
*
|
|
145
|
+
* @return A {@link LiveQuery} object that must be kept in scope for as long
|
|
146
|
+
* as you want to keep receiving updates.
|
|
147
|
+
*/
|
|
148
|
+
observeLocalWithNextSignal(handler: CollectionsObservationHandler): LiveQuery {
|
|
149
|
+
return this._observe(handler, true)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Return the list of collections requested based on the preceding function
|
|
154
|
+
* chaining.
|
|
155
|
+
*
|
|
156
|
+
* @return A list of {@link Collection}s based on the preceding function
|
|
157
|
+
* chaining.
|
|
158
|
+
*/
|
|
159
|
+
async exec(): Promise<Collection[]> {
|
|
160
|
+
const documents = await this.pendingCursorOperation.exec()
|
|
161
|
+
return collectionsFromDocuments(documents, this.store)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** @internal */
|
|
165
|
+
readonly store: Store
|
|
166
|
+
|
|
167
|
+
/** @internal */
|
|
168
|
+
constructor(store: Store) {
|
|
169
|
+
this.store = store
|
|
170
|
+
this.pendingCursorOperation = new PendingCursorOperation('true', null, new Collection('__collections', store))
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** @internal */
|
|
174
|
+
then<TResult1 = any, TResult2 = never>(onfulfilled?: ((value: any) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined): PromiseLike<TResult1 | TResult2> {
|
|
175
|
+
return this.exec().then(onfulfilled, onrejected)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ----------------------------------------------------------- Internal ------
|
|
179
|
+
|
|
180
|
+
/** @internal */
|
|
181
|
+
_observe(handler: CollectionsObservationHandler, waitForNextSignal: boolean): LiveQuery {
|
|
182
|
+
const weakStore = new WeakRef(this.store)
|
|
183
|
+
const collectionsObservationHandler = function (documents, event, nextSignal) {
|
|
184
|
+
const strongStore = weakStore.deref()
|
|
185
|
+
if (!strongStore) {
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const collections = collectionsFromDocuments(documents, strongStore)
|
|
190
|
+
let collEvent: CollectionsEvent
|
|
191
|
+
|
|
192
|
+
if (event.isInitial === true) {
|
|
193
|
+
collEvent = CollectionsEvent.initial(collections)
|
|
194
|
+
} else {
|
|
195
|
+
const oldCollections = collectionsFromDocuments(event.oldDocuments, strongStore)
|
|
196
|
+
collEvent = new CollectionsEvent({
|
|
197
|
+
isInitial: false,
|
|
198
|
+
collections,
|
|
199
|
+
oldCollections,
|
|
200
|
+
insertions: event.insertions,
|
|
201
|
+
deletions: event.deletions,
|
|
202
|
+
updates: event.updates,
|
|
203
|
+
moves: event.moves,
|
|
204
|
+
})
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (waitForNextSignal) {
|
|
208
|
+
handler(collEvent, nextSignal)
|
|
209
|
+
} else {
|
|
210
|
+
handler(collEvent)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return this.pendingCursorOperation._observe(collectionsObservationHandler, waitForNextSignal)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ------------------------------------------------------------ Private ------
|
|
218
|
+
|
|
219
|
+
private readonly pendingCursorOperation: PendingCursorOperation
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** @private */
|
|
223
|
+
function collectionsFromDocuments(documents: Document[], store: Store): Collection[] {
|
|
224
|
+
const collections: Collection[] = []
|
|
225
|
+
for (const document of documents) {
|
|
226
|
+
const collectionName = document.at('name').value
|
|
227
|
+
if (collectionName !== undefined && typeof collectionName === 'string') {
|
|
228
|
+
collections.push(new Collection(collectionName, store))
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return collections
|
|
232
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright © 2021 DittoLive Incorporated. All rights reserved.
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as FFI from './ffi'
|
|
6
|
+
|
|
7
|
+
import { Bridge } from './bridge'
|
|
8
|
+
import { Subscription } from './subscription'
|
|
9
|
+
import { DocumentID } from './document-id'
|
|
10
|
+
import { LiveQuery } from './live-query'
|
|
11
|
+
import { performAsyncToWorkaroundNonAsyncFFIAPI } from './internal'
|
|
12
|
+
import { BasePendingCursorOperation } from './base-pending-cursor-operation'
|
|
13
|
+
|
|
14
|
+
import type { QueryArguments, SortDirection } from './essentials'
|
|
15
|
+
import type { Document, MutableDocument } from './document'
|
|
16
|
+
import type { UpdateResultsMap } from './update-results-map'
|
|
17
|
+
import type { LiveQueryEvent } from './live-query-event'
|
|
18
|
+
import type { Collection } from './collection'
|
|
19
|
+
|
|
20
|
+
// -----------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The closure that is called whenever the documents covered by a live query
|
|
24
|
+
* change.
|
|
25
|
+
*/
|
|
26
|
+
export type QueryObservationHandler = (documents: Document[], event: LiveQueryEvent, signalNext?: () => void) => void | Promise<void>
|
|
27
|
+
|
|
28
|
+
// -----------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* These objects are returned when using `find`-like functionality on
|
|
32
|
+
* {@link Collection}.
|
|
33
|
+
*
|
|
34
|
+
* They allow chaining of further query-related functions to do things like add
|
|
35
|
+
* a limit to the number of documents you want returned or specify how you want
|
|
36
|
+
* the documents to be sorted and ordered.
|
|
37
|
+
*
|
|
38
|
+
* You can either call {@link exec | exec()} on the object to get an array of
|
|
39
|
+
* {@link Document | documents} as an immediate return value, or you can
|
|
40
|
+
* establish either a live query or a subscription, which both work over time.
|
|
41
|
+
*
|
|
42
|
+
* A live query, established by calling
|
|
43
|
+
* {@link PendingCursorOperation.observeLocal | observeLocal()}, will notify you
|
|
44
|
+
* every time there's an update to a document that matches the query you
|
|
45
|
+
* provided in the preceding `find`-like call.
|
|
46
|
+
*
|
|
47
|
+
* A subscription, established by calling
|
|
48
|
+
* {@link PendingCursorOperation.subscribe | subscribe()}, will act as a signal
|
|
49
|
+
* to other peers that the device connects to that you would like to receive
|
|
50
|
+
* updates from them about documents that match the query you provided in the
|
|
51
|
+
* preceding `find`-like call.
|
|
52
|
+
*
|
|
53
|
+
* Update and remove functionality is also exposed through this object.
|
|
54
|
+
*/
|
|
55
|
+
export class PendingCursorOperation extends BasePendingCursorOperation {
|
|
56
|
+
sort(propertyPath: string, direction: SortDirection = 'ascending'): PendingCursorOperation {
|
|
57
|
+
return super.sort(propertyPath, direction) as PendingCursorOperation
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
offset(offset: number): PendingCursorOperation {
|
|
61
|
+
return super.offset(offset) as PendingCursorOperation
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
limit(limit: number): PendingCursorOperation {
|
|
65
|
+
return super.limit(limit) as PendingCursorOperation
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async remove(): Promise<DocumentID[]> {
|
|
69
|
+
const ditto = this.collection.store.ditto
|
|
70
|
+
const dittoHandle = Bridge.ditto.handleFor(ditto)
|
|
71
|
+
return ditto.deferCloseAsync(async () => {
|
|
72
|
+
const query = this.query
|
|
73
|
+
const documentsX = await performAsyncToWorkaroundNonAsyncFFIAPI(async () => {
|
|
74
|
+
const writeTransactionX = await FFI.writeTransaction(dittoHandle.deref())
|
|
75
|
+
const results = await FFI.collectionRemoveQueryStr(dittoHandle.deref(), this.collection.name, writeTransactionX, query, this.queryArgsCBOR, this.orderBys, this.currentLimit, this.currentOffset)
|
|
76
|
+
await FFI.writeTransactionCommit(dittoHandle.deref(), writeTransactionX)
|
|
77
|
+
return results
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
return documentsX.map((idCBOR: Uint8Array) => {
|
|
81
|
+
return new DocumentID(idCBOR, true)
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async evict(): Promise<DocumentID[]> {
|
|
87
|
+
const ditto = this.collection.store.ditto
|
|
88
|
+
const dittoHandle = Bridge.ditto.handleFor(ditto)
|
|
89
|
+
return ditto.deferCloseAsync(async () => {
|
|
90
|
+
const query = this.query
|
|
91
|
+
const documentsX = await performAsyncToWorkaroundNonAsyncFFIAPI(async () => {
|
|
92
|
+
const writeTransactionX = await FFI.writeTransaction(dittoHandle.deref())
|
|
93
|
+
const results = await FFI.collectionEvictQueryStr(dittoHandle.deref(), this.collection.name, writeTransactionX, query, this.queryArgsCBOR, this.orderBys, this.currentLimit, this.currentOffset)
|
|
94
|
+
await FFI.writeTransactionCommit(dittoHandle.deref(), writeTransactionX)
|
|
95
|
+
return results
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
return documentsX.map((idCBOR: Uint8Array) => {
|
|
99
|
+
return new DocumentID(idCBOR, true)
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async update(closure: (documents: MutableDocument[]) => void): Promise<UpdateResultsMap> {
|
|
105
|
+
const ditto = this.collection.store.ditto
|
|
106
|
+
const dittoHandle = Bridge.ditto.handleFor(ditto)
|
|
107
|
+
return ditto.deferCloseAsync(async () => {
|
|
108
|
+
return await performAsyncToWorkaroundNonAsyncFFIAPI(async () => {
|
|
109
|
+
const writeTransactionX = await FFI.writeTransaction(dittoHandle.deref())
|
|
110
|
+
const results = await super.updateWithTransaction(closure, writeTransactionX)
|
|
111
|
+
await FFI.writeTransactionCommit(dittoHandle.deref(), writeTransactionX)
|
|
112
|
+
return results
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Enables you to subscribe to changes that occur in a collection remotely.
|
|
119
|
+
*
|
|
120
|
+
* Having a subscription acts as a signal to other peers that you are
|
|
121
|
+
* interested in receiving updates when local or remote changes are made to
|
|
122
|
+
* documents that match the query generated by the chain of operations that
|
|
123
|
+
* precedes the call to {@link subscribe | subscribe()}.
|
|
124
|
+
*
|
|
125
|
+
* The returned {@link Subscription} object must be kept in scope for as long
|
|
126
|
+
* as you want to keep receiving updates.
|
|
127
|
+
*
|
|
128
|
+
* @returns A {@link Subscription} object that must be kept in scope for as
|
|
129
|
+
* long as you want to keep receiving updates for documents that match the
|
|
130
|
+
* query specified in the preceding chain.
|
|
131
|
+
*/
|
|
132
|
+
subscribe(): Subscription {
|
|
133
|
+
const subscription = new Subscription(this.collection as Collection, this.query, this.queryArgsCBOR, this.orderBys, this.currentLimit, this.currentOffset)
|
|
134
|
+
this.collection.store.ditto.subscriptionManager.add(subscription)
|
|
135
|
+
return subscription
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Enables you to listen for changes that occur in a collection locally.
|
|
140
|
+
*
|
|
141
|
+
* The `handler` block will be called when local changes are
|
|
142
|
+
* made to documents that match the query generated by the chain of operations
|
|
143
|
+
* that precedes the call to {@link PendingCursorOperation.observeLocal | observeLocal()}.
|
|
144
|
+
* The returned {@link LiveQuery} object must be kept in scope for as long as
|
|
145
|
+
* you want the provided `handler` to be called when an update occurs.
|
|
146
|
+
*
|
|
147
|
+
* This won't subscribe to receive changes made remotely by others and so it
|
|
148
|
+
* will only fire updates when a local change is made. If you want to receive
|
|
149
|
+
* remotely performed updates as well, you'll have to create a subscription
|
|
150
|
+
* via {@link PendingCursorOperation.subscribe | subscribe()} with the
|
|
151
|
+
* relevant query. The returned {@link LiveQuery} object must be kept in scope
|
|
152
|
+
* for as long as you want the provided `eventHandler` to be called when an
|
|
153
|
+
* update occurs.
|
|
154
|
+
*
|
|
155
|
+
* @param handler A closure that will be called every time there is a
|
|
156
|
+
* transaction committed to the store that involves modifications to documents
|
|
157
|
+
* matching the query in the collection this method was called on.
|
|
158
|
+
*
|
|
159
|
+
* @return A {@link LiveQuery} object that must be kept in scope for as long
|
|
160
|
+
* as you want to keep receiving updates.
|
|
161
|
+
*/
|
|
162
|
+
observeLocal(handler: QueryObservationHandler): LiveQuery {
|
|
163
|
+
return this._observe(handler, false)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Enables you to listen for changes that occur in a collection locally and
|
|
168
|
+
* to signal when you are ready for the live query to deliver the next event.
|
|
169
|
+
*
|
|
170
|
+
* The `handler` block will be called when local changes are
|
|
171
|
+
* made to documents that match the query generated by the chain of operations
|
|
172
|
+
* that precedes the call to {@link PendingCursorOperation.observeLocalWithNextSignal | observeLocalWithNextSignal()}.
|
|
173
|
+
* The returned {@link LiveQuery} object must be kept in scope for as long as
|
|
174
|
+
* you want the provided `handler` to be called when an update occurs.
|
|
175
|
+
*
|
|
176
|
+
* This won't subscribe to receive changes made remotely by others and so it
|
|
177
|
+
* will only fire updates when a local change is made. If you want to receive
|
|
178
|
+
* remotely performed updates as well, you'll have to create a subscription
|
|
179
|
+
* via {@link PendingCursorOperation.subscribe | subscribe()} with the
|
|
180
|
+
* relevant query. The returned {@link LiveQuery} object must be kept in scope
|
|
181
|
+
* for as long as you want the provided `eventHandler` to be called when an
|
|
182
|
+
* update occurs.
|
|
183
|
+
*
|
|
184
|
+
* @param handler A closure that will be called every time there is a
|
|
185
|
+
* transaction committed to the store that involves modifications to
|
|
186
|
+
* documents matching the query in the collection that this method was called
|
|
187
|
+
* on.
|
|
188
|
+
*
|
|
189
|
+
* @return A {@link LiveQuery} object that must be kept in scope for as long
|
|
190
|
+
* as you want to keep receiving updates.
|
|
191
|
+
*/
|
|
192
|
+
observeLocalWithNextSignal(handler: QueryObservationHandler): LiveQuery {
|
|
193
|
+
return this._observe(handler, true)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// ----------------------------------------------------------- Internal ------
|
|
197
|
+
|
|
198
|
+
/** @internal */
|
|
199
|
+
constructor(query: string, queryArgs: QueryArguments | null, collection: Collection) {
|
|
200
|
+
super(query, queryArgs, collection)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** @internal */
|
|
204
|
+
_observe(handler: QueryObservationHandler, waitForNextSignal: boolean): LiveQuery {
|
|
205
|
+
function wrappedHandler(documents, event, nextSignal) {
|
|
206
|
+
try {
|
|
207
|
+
return handler.call(this, documents, event)
|
|
208
|
+
} finally {
|
|
209
|
+
nextSignal()
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const handlerOrWrapped: QueryObservationHandler = waitForNextSignal ? handler : wrappedHandler
|
|
214
|
+
const liveQuery = new LiveQuery(this.query, this.queryArgs, this.queryArgsCBOR, this.orderBys, this.currentLimit, this.currentOffset, this.collection as Collection, handlerOrWrapped)
|
|
215
|
+
this.collection.store.ditto.liveQueryManager.startLiveQuery(liveQuery)
|
|
216
|
+
return liveQuery
|
|
217
|
+
}
|
|
218
|
+
}
|