@dittolive/ditto 4.5.1-experimental.aarch64-linux.1.aarch64 → 4.5.2-rc.2

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.
Files changed (152) hide show
  1. package/DittoReactNative.podspec +25 -0
  2. package/README.md +2 -2
  3. package/node/ditto.cjs.js +1 -1
  4. package/node/ditto.cjs.js.map +1 -0
  5. package/node/ditto.cjs.pretty.js +9655 -0
  6. package/node/ditto.cjs.pretty.js.map +1 -0
  7. package/node/ditto.darwin-arm64.node +0 -0
  8. package/node/ditto.darwin-x64.node +0 -0
  9. package/node/{ditto.linux-arm64.node → ditto.linux-x64.node} +0 -0
  10. package/node/transports.darwin-arm64.node +0 -0
  11. package/node/transports.darwin-x64.node +0 -0
  12. package/package.json +2 -1
  13. package/react-native/android/CMakeLists.txt +37 -0
  14. package/react-native/android/build.gradle +186 -0
  15. package/react-native/android/cpp-adapter.cpp +254 -0
  16. package/react-native/android/gradle.properties +5 -0
  17. package/react-native/android/src/main/AndroidManifest.xml +4 -0
  18. package/react-native/android/src/main/java/com/dittolive/rnsdk/DittoRNSDKModule.java +85 -0
  19. package/react-native/android/src/main/java/com/dittolive/rnsdk/DittoRNSDKPackage.java +28 -0
  20. package/react-native/cpp/include/Arc.hpp +141 -0
  21. package/react-native/cpp/include/Attachment.h +16 -0
  22. package/react-native/cpp/include/Authentication.h +23 -0
  23. package/react-native/cpp/include/Collection.h +13 -0
  24. package/react-native/cpp/include/DQL.h +21 -0
  25. package/react-native/cpp/include/Document.h +17 -0
  26. package/react-native/cpp/include/Identity.h +17 -0
  27. package/react-native/cpp/include/Lifecycle.h +17 -0
  28. package/react-native/cpp/include/LiveQuery.h +17 -0
  29. package/react-native/cpp/include/Logger.h +22 -0
  30. package/react-native/cpp/include/Misc.h +27 -0
  31. package/react-native/cpp/include/Presence.h +14 -0
  32. package/react-native/cpp/include/SmallPeerInfo.h +19 -0
  33. package/react-native/cpp/include/Transports.h +25 -0
  34. package/react-native/cpp/include/TypedArray.hpp +167 -0
  35. package/react-native/cpp/include/Utils.h +61 -0
  36. package/react-native/cpp/include/main.h +10 -0
  37. package/react-native/cpp/src/Attachment.cpp +86 -0
  38. package/react-native/cpp/src/Authentication.cpp +227 -0
  39. package/react-native/cpp/src/Collection.cpp +54 -0
  40. package/react-native/cpp/src/DQL.cpp +256 -0
  41. package/react-native/cpp/src/Document.cpp +146 -0
  42. package/react-native/cpp/src/Identity.cpp +123 -0
  43. package/react-native/cpp/src/Lifecycle.cpp +110 -0
  44. package/react-native/cpp/src/LiveQuery.cpp +63 -0
  45. package/react-native/cpp/src/Logger.cpp +200 -0
  46. package/react-native/cpp/src/Misc.cpp +283 -0
  47. package/react-native/cpp/src/Presence.cpp +79 -0
  48. package/react-native/cpp/src/SmallPeerInfo.cpp +142 -0
  49. package/react-native/cpp/src/Transports.cpp +270 -0
  50. package/react-native/cpp/src/TypedArray.cpp +303 -0
  51. package/react-native/cpp/src/Utils.cpp +138 -0
  52. package/react-native/cpp/src/main.cpp +152 -0
  53. package/react-native/dittoffi/dittoffi.h +4700 -0
  54. package/react-native/dittoffi/ifaddrs.cpp +385 -0
  55. package/react-native/dittoffi/ifaddrs.h +206 -0
  56. package/react-native/ios/DittoRNSDK.h +7 -0
  57. package/react-native/ios/DittoRNSDK.mm +107 -0
  58. package/react-native/ios/YeetJSIUtils.h +60 -0
  59. package/react-native/ios/YeetJSIUtils.mm +196 -0
  60. package/react-native/lib/commonjs/ditto.rn.js +92 -0
  61. package/react-native/lib/commonjs/ditto.rn.js.map +1 -0
  62. package/react-native/lib/commonjs/index.js +61 -0
  63. package/react-native/lib/commonjs/index.js.map +1 -0
  64. package/react-native/lib/module/ditto.rn.js +88 -0
  65. package/react-native/lib/module/ditto.rn.js.map +1 -0
  66. package/react-native/lib/module/index.js +27 -0
  67. package/react-native/lib/module/index.js.map +1 -0
  68. package/react-native/lib/typescript/ditto.rn.d.ts +15 -0
  69. package/react-native/lib/typescript/ditto.rn.d.ts.map +1 -0
  70. package/react-native/lib/typescript/index.d.ts +1 -0
  71. package/react-native/lib/typescript/index.d.ts.map +1 -0
  72. package/react-native/src/ditto.rn.ts +91 -0
  73. package/react-native/src/environment/environment.fallback.ts +4 -0
  74. package/react-native/src/index.ts +26 -0
  75. package/react-native/src/sources/@cbor-redux.ts +2 -0
  76. package/react-native/src/sources/@ditto.core.ts +1 -0
  77. package/react-native/src/sources/@environment.ts +1 -0
  78. package/react-native/src/sources/attachment-fetch-event.ts +54 -0
  79. package/react-native/src/sources/attachment-fetcher-manager.ts +144 -0
  80. package/react-native/src/sources/attachment-fetcher.ts +134 -0
  81. package/react-native/src/sources/attachment-token.ts +48 -0
  82. package/react-native/src/sources/attachment.ts +74 -0
  83. package/react-native/src/sources/augment.ts +101 -0
  84. package/react-native/src/sources/authenticator.ts +314 -0
  85. package/react-native/src/sources/base-pending-cursor-operation.ts +239 -0
  86. package/react-native/src/sources/base-pending-id-specific-operation.ts +109 -0
  87. package/react-native/src/sources/bridge.ts +553 -0
  88. package/react-native/src/sources/build-time-constants.ts +8 -0
  89. package/react-native/src/sources/cbor.ts +35 -0
  90. package/react-native/src/sources/collection-interface.ts +67 -0
  91. package/react-native/src/sources/collection.ts +212 -0
  92. package/react-native/src/sources/collections-event.ts +99 -0
  93. package/react-native/src/sources/counter.ts +82 -0
  94. package/react-native/src/sources/ditto.ts +979 -0
  95. package/react-native/src/sources/document-id.ts +159 -0
  96. package/react-native/src/sources/document-path.ts +306 -0
  97. package/react-native/src/sources/document.ts +193 -0
  98. package/react-native/src/sources/epilogue.ts +30 -0
  99. package/react-native/src/sources/error-codes.ts +52 -0
  100. package/react-native/src/sources/error.ts +208 -0
  101. package/react-native/src/sources/essentials.ts +53 -0
  102. package/react-native/src/sources/ffi-error.ts +122 -0
  103. package/react-native/src/sources/ffi.ts +2012 -0
  104. package/react-native/src/sources/identity.ts +163 -0
  105. package/react-native/src/sources/init.ts +71 -0
  106. package/react-native/src/sources/internal.ts +109 -0
  107. package/react-native/src/sources/keep-alive.ts +73 -0
  108. package/react-native/src/sources/key-path.ts +198 -0
  109. package/react-native/src/sources/live-query-event.ts +208 -0
  110. package/react-native/src/sources/live-query-manager.ts +102 -0
  111. package/react-native/src/sources/live-query.ts +166 -0
  112. package/react-native/src/sources/logger.ts +196 -0
  113. package/react-native/src/sources/main.ts +60 -0
  114. package/react-native/src/sources/observer-manager.ts +178 -0
  115. package/react-native/src/sources/observer.ts +79 -0
  116. package/react-native/src/sources/pending-collections-operation.ts +232 -0
  117. package/react-native/src/sources/pending-cursor-operation.ts +218 -0
  118. package/react-native/src/sources/pending-id-specific-operation.ts +218 -0
  119. package/react-native/src/sources/presence-manager.ts +161 -0
  120. package/react-native/src/sources/presence.ts +233 -0
  121. package/react-native/src/sources/query-result-item.ts +116 -0
  122. package/react-native/src/sources/query-result.ts +55 -0
  123. package/react-native/src/sources/register.ts +95 -0
  124. package/react-native/src/sources/small-peer-info.ts +177 -0
  125. package/react-native/src/sources/static-tcp-client.ts +6 -0
  126. package/react-native/src/sources/store-observer.ts +177 -0
  127. package/react-native/src/sources/store.ts +385 -0
  128. package/react-native/src/sources/subscription-manager.ts +99 -0
  129. package/react-native/src/sources/subscription.ts +89 -0
  130. package/react-native/src/sources/sync-subscription.ts +90 -0
  131. package/react-native/src/sources/sync.ts +559 -0
  132. package/react-native/src/sources/test-helpers.ts +24 -0
  133. package/react-native/src/sources/transport-conditions-manager.ts +104 -0
  134. package/react-native/src/sources/transport-config.ts +430 -0
  135. package/react-native/src/sources/update-result.ts +66 -0
  136. package/react-native/src/sources/update-results-map.ts +57 -0
  137. package/react-native/src/sources/websocket-client.ts +7 -0
  138. package/react-native/src/sources/write-transaction-collection.ts +122 -0
  139. package/react-native/src/sources/write-transaction-pending-cursor-operation.ts +101 -0
  140. package/react-native/src/sources/write-transaction-pending-id-specific-operation.ts +74 -0
  141. package/react-native/src/sources/write-transaction.ts +121 -0
  142. package/react-native.config.js +9 -0
  143. package/types/ditto.d.ts.map +1 -0
  144. package/web/ditto.es6.js +1 -1
  145. package/web/ditto.es6.js.map +1 -0
  146. package/web/ditto.es6.pretty.js +12600 -0
  147. package/web/ditto.es6.pretty.js.map +1 -0
  148. package/web/ditto.umd.js +1 -1
  149. package/web/ditto.umd.js.map +1 -0
  150. package/web/ditto.umd.pretty.js +12669 -0
  151. package/web/ditto.umd.pretty.js.map +1 -0
  152. package/web/ditto.wasm +0 -0
@@ -0,0 +1,233 @@
1
+ //
2
+ // Copyright © 2021 DittoLive Incorporated. All rights reserved.
3
+ //
4
+
5
+ import * as FFI from './ffi'
6
+ import { Bridge } from './bridge'
7
+ import { Observer } from './observer'
8
+ import { ObserverManager } from './observer-manager'
9
+ import type { Ditto } from './ditto'
10
+
11
+ /** Types of connections that can be established between two peers. */
12
+ export type ConnectionType = 'P2PWiFi' | 'WebSocket' | 'AccessPoint' | 'Bluetooth'
13
+
14
+ // -----------------------------------------------------------------------------
15
+
16
+ /**
17
+ * An opaque address uniquely identifying another peer on the Ditto mesh
18
+ * network.
19
+ *
20
+ * IMPORTANT: You should not rely on the individual components of the address,
21
+ * those can change at any time. Please use
22
+ * {@link addressToString | addressToString()} to compare individual addresses
23
+ * with each other.
24
+ */
25
+ export type Address = {
26
+ siteId: number | BigInt
27
+ pubkey: Uint8Array
28
+ }
29
+
30
+ // -----------------------------------------------------------------------------
31
+
32
+ /**
33
+ * Returns a string representation of the given address. Use this function
34
+ * to compare multiple addresses or whenever you need the address to be a key
35
+ * in a hash object.
36
+ */
37
+ export function addressToString(address: Address) {
38
+ return `${address.siteId}-${address.pubkey}`
39
+ }
40
+
41
+ // -----------------------------------------------------------------------------
42
+
43
+ /** Represents a connection between two peers on the Ditto mesh network. */
44
+ export type Connection = {
45
+ /** Unique identifier for the connection.
46
+ *
47
+ * These IDs are stable for any two peer keys and a given connection type.
48
+ *
49
+ * **Example ID**
50
+ *
51
+ * "1<->2:Bluetooth"
52
+ */
53
+ id: string
54
+
55
+ /** Type of transport enabling this connection. */
56
+ connectionType: ConnectionType
57
+
58
+ /**
59
+ * Peer key of the peer at one end of the connection.
60
+ *
61
+ * This peer key is lexicographically smaller than `peer2`.
62
+ */
63
+ peer1: Uint8Array
64
+
65
+ /**
66
+ * Peer key of the peer at the other end of the connection.
67
+ *
68
+ * This peer key is lexicographically larger than `peer1`.
69
+ */
70
+ peer2: Uint8Array
71
+
72
+ /*
73
+ * Gets an estimate of distance to the remote peer. This value is inaccurate.
74
+ * The environment, hardware, and several other factors can greatly affect
75
+ * this value. It is currently derived from RSSI. Can be (yet) unknown and
76
+ * therefore not set.
77
+ */
78
+ approximateDistanceInMeters?: number
79
+ }
80
+
81
+ // -----------------------------------------------------------------------------
82
+
83
+ /** An instance of Ditto taking part in the Ditto mesh network. */
84
+ export type Peer = {
85
+ /**
86
+ * Address to contact this peer via Ditto Bus, unique with a Ditto mesh
87
+ * network.
88
+ */
89
+ address: Address
90
+
91
+ /**
92
+ * The peer key is a unique identifier for a given peer, equal to or derived
93
+ * from the cryptographic public key used to authenticate it.
94
+ *
95
+ * NOTE: This will be be empty when a peer is not updated to the latest
96
+ * version of the SDK.
97
+ */
98
+ peerKey: Uint8Array
99
+
100
+ /**
101
+ * The human-readable device name of the peer. This defaults to the hostname
102
+ * but can be manually set by the application developer of the other peer.
103
+ * It is not necessarily unique.
104
+ */
105
+ deviceName: string
106
+
107
+ /**
108
+ * Currently active connections of the peer.
109
+ */
110
+ connections: Connection[]
111
+
112
+ /**
113
+ * Indicates whether the peer is connected to Ditto Cloud.
114
+ */
115
+ isConnectedToDittoCloud: boolean
116
+
117
+ /** The operating system the peer is running on, `undefined` if (yet) unknown. */
118
+ os?: string
119
+
120
+ /** The Ditto SDK version the peer is running with, `undefined` if (yet) unknown. */
121
+ dittoSDKVersion?: string
122
+ }
123
+
124
+ // -----------------------------------------------------------------------------
125
+
126
+ /**
127
+ * Represents the Ditto mesh network of peers and their connections between each
128
+ * other. The `localPeer` is the entry point, all others are remote peers known
129
+ * by the local peer (either directly or via other remote peers).
130
+ */
131
+ export type PresenceGraph = {
132
+ /**
133
+ * Returns the local peer (usually the peer that is represented by the
134
+ * currently running Ditto instance). The `localPeer` is the entry point, all
135
+ * others are remote peers known by the local peer (either directly or via
136
+ * other remote peers).
137
+ */
138
+ localPeer: Peer
139
+
140
+ /**
141
+ * Returns all remote peers known by the `localPeer`, either directly or via
142
+ * other remote peers.
143
+ */
144
+ remotePeers: Peer[]
145
+
146
+ /**
147
+ * Returns the underlying CBOR data if the presence graph has been initialized
148
+ * with CBOR. All of Ditto API returning a presence graph has this property
149
+ * set.
150
+ */
151
+ underlyingCBOR?: Uint8Array
152
+ }
153
+
154
+ // -----------------------------------------------------------------------------
155
+
156
+ /**
157
+ * The entrypoint for all actions that relate presence of other peers known by
158
+ * the current peer, either directly or through other peers.
159
+ *
160
+ * You don't create one directly but can access it from a particular `Ditto`
161
+ * instance via its `presence` property.
162
+ */
163
+ export class Presence {
164
+ /** The Ditto instance this object belongs to. */
165
+ readonly ditto: Ditto
166
+
167
+ /**
168
+ * Returns the current presence graph capturing all known peers and
169
+ * connections between them.
170
+ */
171
+ get graph(): PresenceGraph {
172
+ const ditto = this.ditto
173
+ const dittoHandle = Bridge.ditto.handleFor(ditto)
174
+ return ditto.deferClose(() => {
175
+ const graphJSONString = FFI.dittoPresenceV3(dittoHandle.deref())
176
+ return JSON.parse(graphJSONString)
177
+ })
178
+ }
179
+
180
+ /**
181
+ * Request information about Ditto peers in range of this device.
182
+ *
183
+ * This method returns an observer which should be held as long as updates are
184
+ * required. A newly registered observer will have a peers update delivered to
185
+ * it immediately. From then on it will be invoked repeatedly when Ditto
186
+ * devices come and go, or the active connections to them change.
187
+ */
188
+ observe(didChangeHandler: (presenceGraph: PresenceGraph) => void): Observer {
189
+ const observerToken = this.observerManager.addObserver(didChangeHandler)
190
+ const observer = new Observer(this.observerManager, observerToken, { stopsWhenFinalized: true })
191
+
192
+ didChangeHandler(this.graph)
193
+
194
+ return observer
195
+ }
196
+
197
+ /** @internal */
198
+ constructor(ditto: Ditto) {
199
+ this.ditto = ditto
200
+
201
+ this.observerManager = new ObserverManager('PresenceObservation', {
202
+ keepAlive: ditto.keepAlive,
203
+
204
+ register: (callback) => {
205
+ const ditto = this.ditto
206
+ const dittoHandle = Bridge.ditto.handleFor(ditto)
207
+ ditto.deferClose(() => {
208
+ FFI.dittoRegisterPresenceV3Callback(dittoHandle.deref(), callback)
209
+ })
210
+ },
211
+
212
+ unregister: () => {
213
+ const ditto = this.ditto
214
+ const dittoHandle = Bridge.ditto.handleFor(ditto)
215
+ ditto.deferClose(() => {
216
+ FFI.dittoClearPresenceV3Callback(dittoHandle.deref())
217
+ })
218
+ },
219
+
220
+ process: (presenceGraphJSONString) => {
221
+ const presenceGraph = JSON.parse(presenceGraphJSONString)
222
+ return [presenceGraph]
223
+ },
224
+ })
225
+ }
226
+
227
+ /** @internal */
228
+ close() {
229
+ this.observerManager.close()
230
+ }
231
+
232
+ private observerManager: ObserverManager
233
+ }
@@ -0,0 +1,116 @@
1
+ //
2
+ // Copyright © 2023 DittoLive Incorporated. All rights reserved.
3
+ //
4
+
5
+ import * as FFI from './ffi'
6
+ import { CBOR } from './cbor'
7
+ import { Bridge } from './bridge'
8
+ import { Document } from './document'
9
+
10
+ /**
11
+ * Represents a single match of a DQL query, similar to a “row” in SQL terms.
12
+ * It’s a reference type serving as a “cursor”, allowing for efficient access of
13
+ * the underlying data in various formats.
14
+ *
15
+ * The {@link QueryResultItem.value | value } property is lazily
16
+ * materialized and kept in memory until it goes out of scope. To reduce the
17
+ * memory footprint, structure your code such that items can be processed as a
18
+ * stream, i.e. one by one (or in batches) and
19
+ * {@link QueryResultItem.dematerialize | dematerialize() } them
20
+ * right after use.
21
+ */
22
+ export class QueryResultItem {
23
+ /**
24
+ * Returns the content as a materialized object.
25
+ *
26
+ * The item's value is
27
+ * {@link QueryResultItem.materialize | materialized() } on first access
28
+ * and subsequently on each access after performing
29
+ * {@link QueryResultItem.dematerialize | dematerialize() }. Once
30
+ * materialized, the value is kept in memory until explicitly
31
+ * {@link QueryResultItem.dematerialize | dematerialize() }-ed or the item
32
+ * goes out of scope.
33
+ *
34
+ * Note: This property is very similar to {@link Document.value}.
35
+ */
36
+ get value(): any {
37
+ this.materialize()
38
+ if (this.materializedValue === undefined) {
39
+ throw new Error('Internal Error: Materialized value is undefined')
40
+ }
41
+ return this.materializedValue
42
+ }
43
+
44
+ /**
45
+ * Returns `true` if value is currently held materialized in memory, otherwise
46
+ * returns `false`.
47
+ *
48
+ * See {@link QueryResultItem.materialize | materialize()} and
49
+ * {@link QueryResultItem.dematerialize | dematerialize()}.
50
+ */
51
+ get isMaterialized(): boolean {
52
+ return this.materializedValue !== undefined
53
+ }
54
+
55
+ /**
56
+ * Loads the CBOR representation of the item's content, decodes it as an
57
+ * object so it can be accessed via {@link QueryResultItem.value | value }.
58
+ * Keeps the object in memory until
59
+ * {@link QueryResultItem.dematerialize | dematerialize() } is called. No-op
60
+ * if {@link QueryResultItem.value | value } is already materialized.
61
+ */
62
+ materialize(): void {
63
+ if (!this.isMaterialized) {
64
+ const cborValue = this.cborData()
65
+ let materializedValue: any
66
+ try {
67
+ materializedValue = CBOR.decode(cborValue)
68
+ } catch (error: any) {
69
+ throw new Error(`Internal inconsistency: CBOR decoding error while materializing result item: ${error.message}`)
70
+ }
71
+
72
+ if (materializedValue === undefined) {
73
+ throw new Error('Internal inconsistency: Materialized value is undefined')
74
+ }
75
+
76
+ this.materializedValue = materializedValue
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Releases the materialized value from memory. No-op if item is not
82
+ * materialized.
83
+ */
84
+ dematerialize(): void {
85
+ this.materializedValue = undefined
86
+ }
87
+
88
+ /**
89
+ * Returns the content of the item as CBOR data.
90
+ *
91
+ * Important: The returned CBOR data is not cached, make sure to call this
92
+ * method once and keep it for as long as needed.
93
+ */
94
+ cborData(): Uint8Array {
95
+ const resultHandle = Bridge.dqlResult.handleFor(this)
96
+ return FFI.dqlResultCBOR(resultHandle.deref())
97
+ }
98
+
99
+ /**
100
+ * Returns the content of the item as a JSON string.
101
+ *
102
+ * Important: The returned JSON string is not cached, make sure to call this
103
+ * method once and keep it for as long as needed.
104
+ */
105
+ jsonString(): string {
106
+ const resultHandle = Bridge.dqlResult.handleFor(this)
107
+ return FFI.dqlResultJSON(resultHandle.deref())
108
+ }
109
+
110
+ // ----------------------------------------------------------- Internal ------
111
+
112
+ private materializedValue: any
113
+
114
+ /** @internal */
115
+ constructor() {}
116
+ }
@@ -0,0 +1,55 @@
1
+ //
2
+ // Copyright © 2023 DittoLive Incorporated. All rights reserved.
3
+ //
4
+ import * as FFI from './ffi'
5
+
6
+ import { Bridge } from './bridge'
7
+ import { QueryResultItem } from './query-result-item'
8
+ import { DocumentID } from './document-id'
9
+
10
+ import type { Store } from './store'
11
+
12
+ /**
13
+ * Represents results returned when executing a DQL query containing a
14
+ * {@link QueryResultItem} for each match.
15
+ *
16
+ * More info, such as metrics, will be provided in the near future.
17
+ */
18
+ export class QueryResult {
19
+ /**
20
+ * Individual items matching a DQL query.
21
+ */
22
+ readonly items: QueryResultItem[]
23
+
24
+ /**
25
+ * IDs of documents that were mutated _locally_ by a _mutating_ DQL query
26
+ * passed to {@link Store.execute | `execute()`}. Empty array if no documents
27
+ * have been mutated.
28
+ *
29
+ * **Note: Query results received from a {@link StoreObserver} never contain
30
+ * mutated document IDs because a store observer is always registered using a
31
+ * non-mutating `SELECT` query.
32
+ *
33
+ * **Important:** The returned document IDs are not cached, make sure to call
34
+ * this method once and keep the return value for as long as needed.
35
+ *
36
+ * @returns an array of document IDs
37
+ */
38
+ mutatedDocumentIDs(): DocumentID[] {
39
+ const responseHandle = Bridge.dqlResponse.handleFor(this)
40
+ const affectedCBORIDs = FFI.dqlMutatedDocumentIDs(responseHandle.deref())
41
+ return affectedCBORIDs.map((id) => new DocumentID(id, true))
42
+ }
43
+
44
+ // ----------------------------------------------------- Internal ------------
45
+
46
+ /** @internal */
47
+ constructor(responsePointer: FFI.Pointer<FFI.FFIDqlResponse>) {
48
+ if (responsePointer == null) {
49
+ throw new Error('Internal inconsistency, failed to initialize query result without a response pointer')
50
+ }
51
+
52
+ const results = FFI.dqlResponseResults(responsePointer)
53
+ this.items = results.map((r) => Bridge.dqlResult.bridge(r))
54
+ }
55
+ }
@@ -0,0 +1,95 @@
1
+ //
2
+ // Copyright © 2022 DittoLive Incorporated. All rights reserved.
3
+ //
4
+
5
+ // NOTE: we use a token to detect private invocation of the constructor. This is
6
+ // not secure and just to prevent accidental private invocation on the client
7
+ // side.
8
+ const privateToken = '@ditto.ff82dae89821c5ab822a8b539056bce4'
9
+
10
+ /**
11
+ * Represents a CRDT register that can be upserted as part of a document or
12
+ * assigned to a property during an update of a document.
13
+ */
14
+ export class Register {
15
+ /** Returns the value of the register. */
16
+ get value(): any {
17
+ return this['@ditto.value']
18
+ }
19
+
20
+ /**
21
+ * Creates a new Register that can be used as part of a document's content.
22
+ */
23
+ constructor(value: any) {
24
+ this['@ditto.value'] = value
25
+ }
26
+
27
+ /** @internal */
28
+ static '@ditto.create'(mutableDocument, path, value) {
29
+ const register = mutableDocument ? new (MutableRegister as any)(value, privateToken) : new Register(value)
30
+ register['@ditto.mutableDocument'] = mutableDocument
31
+ register['@ditto.path'] = path
32
+ register['@ditto.value'] = value
33
+ return register
34
+ }
35
+
36
+ /** @internal */
37
+ protected '@ditto.mutableDocument': any
38
+
39
+ /** @internal */
40
+ protected '@ditto.path': any
41
+
42
+ /** @internal */
43
+ protected '@ditto.value': any
44
+ }
45
+
46
+ // -----------------------------------------------------------------------------
47
+
48
+ /**
49
+ * Represents a mutable CRDT register that can be set to a specific value when
50
+ * updating a document.
51
+ *
52
+ * This class can't be instantiated directly, it's returned automatically for
53
+ * any register property of a document within an update block via {@link MutableDocumentPath.register}.
54
+ */
55
+ export class MutableRegister extends Register {
56
+ /** Returns the value of the register. */
57
+ get value(): any {
58
+ return super.value
59
+ }
60
+
61
+ /**
62
+ * Convenience setter, equivalent to {@link set | set()}.
63
+ */
64
+ set value(value: any) {
65
+ this.set(value)
66
+ }
67
+
68
+ /**
69
+ * Sets the register to the provided value.
70
+ *
71
+ * Only valid within the `update` closure of
72
+ * {@link PendingCursorOperation.update | PendingCursorOperation.update()} and
73
+ * {@link PendingIDSpecificOperation.update | PendingIDSpecificOperation.update()},
74
+ * otherwise an exception is thrown.
75
+ */
76
+ set(value: any) {
77
+ const mutableDocument = this['@ditto.mutableDocument']
78
+ const path = this['@ditto.path']
79
+
80
+ mutableDocument.at(path)['@ditto.set'](value)
81
+
82
+ // We also set the local value to make sure that the change is
83
+ // reflected locally as well as in the underlying document.
84
+ this['@ditto.value'] = value
85
+ }
86
+
87
+ /** @internal */
88
+ constructor(value: any) {
89
+ if (arguments[1] === privateToken) {
90
+ super(value)
91
+ } else {
92
+ throw new Error(`MutableRegister constructor is for internal use only.`)
93
+ }
94
+ }
95
+ }
@@ -0,0 +1,177 @@
1
+ //
2
+ // Copyright © 2023 DittoLive Incorporated. All rights reserved.
3
+ //
4
+
5
+ import * as FFI from './ffi'
6
+
7
+ import { Bridge } from './bridge'
8
+ import { Ditto } from './ditto'
9
+
10
+ /**
11
+ * Specifies which peers to replicate the small peer info to when enabled.
12
+ *
13
+ * Possible values are:
14
+ *
15
+ * - `LocalPeerOnly`: no replication (default)
16
+ * - `BigPeerOnly`: replicate to the Big Peer
17
+ */
18
+ export type SmallPeerInfoSyncScope = 'LocalPeerOnly' | 'BigPeerOnly'
19
+
20
+ /**
21
+ * The entrypoint for small peer user info collection. Small peer info consists
22
+ * of information gathered into a system collection on a regular interval and
23
+ * optionally synced to the Big Peer for device dashboard and debugging
24
+ * purposes.
25
+ *
26
+ * An instance of this class is available on each `Ditto` instance via its
27
+ * {@link Ditto.smallPeerInfo | `smallPeerInfo`} property. Instantiating this
28
+ * class directly is not supported.
29
+ */
30
+ export class SmallPeerInfo {
31
+ /**
32
+ * Indicates whether small peer info collection is currently enabled, defaults
33
+ * to `false`.
34
+ *
35
+ * **Note**: whether the background ingestion process is enabled or not is a
36
+ * separate decision to whether this information is allowed to sync to other
37
+ * peers (including the big peer). This is controlled by
38
+ * {@link getSyncScope | getSyncScope()} and
39
+ * {@link setSyncScope | setSyncScope()}.
40
+ */
41
+ get isEnabled(): boolean {
42
+ const dittoHandle = Bridge.ditto.handleFor(this.ditto)
43
+ return this.ditto.deferClose(() => {
44
+ return FFI.dittoSmallPeerInfoGetIsEnabled(dittoHandle.deref())
45
+ })
46
+ }
47
+
48
+ /**
49
+ * Set whether small peer info collection is enabled.
50
+ *
51
+ * @throws when set to a non-boolean value.
52
+ */
53
+ set isEnabled(newValue: boolean) {
54
+ if (typeof newValue !== 'boolean') {
55
+ throw new TypeError(`Expected boolean, got ${typeof newValue}`)
56
+ }
57
+
58
+ const dittoHandle = Bridge.ditto.handleFor(this.ditto)
59
+ this.ditto.deferClose(() => {
60
+ FFI.dittoSmallPeerInfoSetEnabled(dittoHandle.deref(), newValue)
61
+ })
62
+ }
63
+
64
+ /**
65
+ * The metadata associated with the small peer info.
66
+ *
67
+ * Small peer info metadata is a free-form, user-provided JSON object that
68
+ * is inserted into the small peer info system document at each collection
69
+ * interval.
70
+ */
71
+ get metadata(): Record<string, any> {
72
+ return JSON.parse(this.metadataJSONString)
73
+ }
74
+
75
+ /**
76
+ * Set the metadata associated with the small peer info.
77
+ *
78
+ * The metadata must be a JSON-serializable object that conforms to the
79
+ * following constraints:
80
+ *
81
+ * - Must be a JSON object (not an array, string, number, etc.)
82
+ * - The size when encoded as JSON must be less than 128 KB
83
+ * - May only be nested up to 2 levels deep
84
+ *
85
+ * @example <caption>Valid metadata</caption>
86
+ * ditto.smallPeerInfo.metadata = {
87
+ * "foo": "bar",
88
+ * "nested": {
89
+ * "inner": "value"
90
+ * }
91
+ * }
92
+ *
93
+ * @example <caption>Invalid metadata</caption>
94
+ * // This is invalid and results in an error.
95
+ * ditto.smallPeerInfo.metadata = {
96
+ * "foo": "bar",
97
+ * "nested": {
98
+ * "illegal": {
99
+ * "inner": "value"
100
+ * }
101
+ * }
102
+ * }
103
+ *
104
+ * @throws when set to a value that violates any of the constraints listed
105
+ * above.
106
+ */
107
+ set metadata(metadata: Record<string, any>) {
108
+ this.metadataJSONString = JSON.stringify(metadata)
109
+ }
110
+
111
+ /**
112
+ * The metadata associated with the small peer info, as a JSON string.
113
+ */
114
+ get metadataJSONString(): string {
115
+ const dittoHandle = Bridge.ditto.handleFor(this.ditto)
116
+ return this.ditto.deferClose(() => {
117
+ return FFI.dittoSmallPeerInfoGetMetadata(dittoHandle.deref())
118
+ })
119
+ }
120
+
121
+ /**
122
+ * Set the metadata associated with the small peer info, as a JSON string.
123
+ *
124
+ * @see {@link SmallPeerInfo.metadata | `metadata`} for more information on
125
+ * valid values.
126
+ * @throws when set to a value that violates any of the constraints listed in
127
+ * {@link SmallPeerInfo.metadata | `metadata`}.
128
+ */
129
+ set metadataJSONString(metadata: string) {
130
+ if (typeof metadata !== 'string') {
131
+ throw new TypeError(`Expected string, got ${typeof metadata}`)
132
+ }
133
+ const dittoHandle = Bridge.ditto.handleFor(this.ditto)
134
+ this.ditto.deferClose(() => {
135
+ // throws if any validation errors occur
136
+ FFI.dittoSmallPeerInfoSetMetadata(dittoHandle.deref(), metadata)
137
+ })
138
+ }
139
+
140
+ /**
141
+ * Determines which "kind" of peers the small peer info will be
142
+ * replicated to.
143
+ *
144
+ * Defaults to `LocalPeerOnly`, which means no replication. Set this to
145
+ * `BigPeerOnly` to replicate collected info to the Big Peer.
146
+ */
147
+ async getSyncScope(): Promise<SmallPeerInfoSyncScope> {
148
+ const dittoHandle = Bridge.ditto.handleFor(this.ditto)
149
+ return this.ditto.deferCloseAsync(async () => {
150
+ return FFI.dittoSmallPeerInfoGetSyncScope(dittoHandle.deref())
151
+ })
152
+ }
153
+
154
+ /**
155
+ * Set the sync scope.
156
+ *
157
+ * See {@link getSyncScope} for more information.
158
+ *
159
+ * @param syncScope the new sync scope.
160
+ * @throws when set to a value other than `BigPeerOnly` or `LocalPeerOnly`.
161
+ */
162
+ async setSyncScope(syncScope: SmallPeerInfoSyncScope): Promise<void> {
163
+ const dittoHandle = Bridge.ditto.handleFor(this.ditto)
164
+ return this.ditto.deferCloseAsync(async () => {
165
+ return FFI.dittoSmallPeerInfoSetSyncScope(dittoHandle.deref(), syncScope as any)
166
+ })
167
+ }
168
+
169
+ // ----------------------------------------------------------- Internal ------
170
+
171
+ private ditto: Ditto
172
+
173
+ /** @internal */
174
+ constructor(ditto: Ditto) {
175
+ this.ditto = ditto
176
+ }
177
+ }
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright © 2021 DittoLive Incorporated. All rights reserved.
3
+ //
4
+
5
+ /** @internal */
6
+ export class StaticTCPClient {}