@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,35 @@
1
+ //
2
+ // Copyright © 2021 DittoLive Incorporated. All rights reserved.
3
+ //
4
+
5
+ import { CBOR as CBORRedux } from './@cbor-redux'
6
+
7
+ import { DocumentID } from './document-id'
8
+
9
+ /** @internal */
10
+ export class CBOR {
11
+ /** @internal */
12
+ static encode(data: any, replacer?: (key: any, value: any) => any): Uint8Array {
13
+ const arrayBuffer = CBORRedux.encode(data, replacer)
14
+ return new Uint8Array(arrayBuffer)
15
+ }
16
+
17
+ /** @internal */
18
+ static decode(data: Uint8Array, reviver?: (key: any, value: any) => any): any {
19
+ const arrayBuffer = data.buffer
20
+ return CBORRedux.decode(arrayBuffer, reviver)
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Custom replacer that converts `DocumentID` instances to their string
26
+ * representation.
27
+ *
28
+ * @internal
29
+ */
30
+ export function documentIDReplacer(key: any, value: any): any {
31
+ if (value instanceof DocumentID) {
32
+ return value.toString()
33
+ }
34
+ return value
35
+ }
@@ -0,0 +1,67 @@
1
+ //
2
+ // Copyright © 2023 DittoLive Incorporated. All rights reserved.
3
+ //
4
+
5
+ import type { DocumentValue } from './document'
6
+ import type { DocumentID, DocumentIDValue } from './document-id'
7
+ import type { WriteStrategy, QueryArguments } from './essentials'
8
+ import type { Store } from './store'
9
+ import type { BasePendingCursorOperation } from './base-pending-cursor-operation'
10
+ import type { BasePendingIDSpecificOperation } from './base-pending-id-specific-operation'
11
+
12
+ export type UpsertOptions = {
13
+ writeStrategy?: WriteStrategy
14
+ }
15
+
16
+ export interface CollectionInterface {
17
+ /** The name of the collection. */
18
+ readonly name: string
19
+
20
+ /**
21
+ * The store this collection belongs to.
22
+ * @internal
23
+ */
24
+ readonly store: Store
25
+
26
+ /**
27
+ * Search for documents in this collection using the provided query string.
28
+ *
29
+ * @param query The query to run against the collection.
30
+ * @param queryArgs These arguments replace placeholders in the provided
31
+ * query.
32
+ */
33
+ find(query: string, queryArgs?: QueryArguments): BasePendingCursorOperation
34
+
35
+ /**
36
+ * Convenience method, equivalent to calling {@link find | find()} and passing
37
+ * the query `"true"`.
38
+ */
39
+ findAll(): BasePendingCursorOperation
40
+
41
+ /**
42
+ * Find documents given a specific ID.
43
+ *
44
+ * Use the returned cursor instance to chain operations on the search result.
45
+ *
46
+ * @param id The document's identifier
47
+ */
48
+ findByID(id: DocumentID | DocumentIDValue): BasePendingIDSpecificOperation
49
+
50
+ /**
51
+ * TEMPORARY: helper to deal with non-canonical IDs.
52
+ *
53
+ * @internal
54
+ */
55
+ findByIDCBOR(idCBOR: Uint8Array): BasePendingIDSpecificOperation
56
+
57
+ /**
58
+ * Inserts a new document into the collection and returns its ID. If the
59
+ * document already exists, the contents of both are merged by default. You
60
+ * can change this by providing a different `writeStrategy` via `options`.
61
+ *
62
+ * @param value The content of the document to be inserted or updated.
63
+ * @param options.writeStrategy Specifies the desired strategy for inserting a
64
+ * document, defaults to `'merge'`.
65
+ */
66
+ upsert(value: DocumentValue, options: UpsertOptions): Promise<DocumentID>
67
+ }
@@ -0,0 +1,212 @@
1
+ //
2
+ // Copyright © 2021 DittoLive Incorporated. All rights reserved.
3
+ //
4
+
5
+ import * as FFI from './ffi'
6
+ import * as Environment from './@environment'
7
+
8
+ import { QueryArguments } from './essentials'
9
+ import { CBOR } from './cbor'
10
+ import { DocumentID } from './document-id'
11
+ import { Bridge } from './bridge'
12
+ import { Attachment } from './attachment'
13
+ import { AttachmentToken } from './attachment-token'
14
+ import { AttachmentFetcher } from './attachment-fetcher'
15
+ import { PendingCursorOperation } from './pending-cursor-operation'
16
+ import { PendingIDSpecificOperation } from './pending-id-specific-operation'
17
+
18
+ import { performAsyncToWorkaroundNonAsyncFFIAPI } from './internal'
19
+ import { desugarJSObject } from './augment'
20
+
21
+ import type { Store } from './store'
22
+ import type { DocumentValue } from './document'
23
+ import type { DocumentIDValue } from './document-id'
24
+ import type { CollectionInterface, UpsertOptions } from './collection-interface'
25
+ import type { AttachmentFetchEvent } from './attachment-fetch-event'
26
+
27
+ /**
28
+ * Represents a collection of a Ditto store.
29
+ *
30
+ * This is the entrypoint for inserting documents into a collection, as well as
31
+ * querying a collection. You can get a collection by calling
32
+ * {@link Store.collection | collection()} on a {@link Store} of a {@link Ditto}
33
+ * object.
34
+ */
35
+ export class Collection implements CollectionInterface {
36
+ /** The name of the collection. */
37
+ readonly name: string
38
+
39
+ /** The store this collection belongs to. */
40
+ readonly store: Store
41
+
42
+ /**
43
+ * Generates a {@link PendingCursorOperation} using the provided query.
44
+ *
45
+ * The returned object can be used to find and return the documents or you can
46
+ * chain a call to `observeLocal()` or `subscribe()` if you want to get
47
+ * updates about the list of matching documents over time. It can also be used
48
+ * to update, remove or evict the matching documents.
49
+ *
50
+ * You can incorporate dynamic data into the query string with placeholders in
51
+ * the form of `$args.my_arg_name`, along with providing an accompanying
52
+ * dictionary in the form of `{ "my_arg_name": "some value" }`. The
53
+ * placeholders will be appropriately replaced by the corresponding argument
54
+ * contained in `queryArgs`. This includes handling things like wrapping
55
+ * strings in quotation marks and arrays in square brackets, for example.
56
+ *
57
+ * Find more information about the query string format in the documentation's
58
+ * section on {@link https://docs.ditto.live/javascript/common/concepts/querying Querying}
59
+ *
60
+ * @param query The query to run against the collection.
61
+ * @param queryArgs The arguments to use to replace placeholders in the
62
+ * provided query.
63
+ */
64
+ find(query: string, queryArgs?: QueryArguments): PendingCursorOperation {
65
+ return new PendingCursorOperation(query, queryArgs ?? null, this)
66
+ }
67
+
68
+ findAll(): PendingCursorOperation {
69
+ return this.find('true')
70
+ }
71
+
72
+ /**
73
+ * Generates a {@link PendingIDSpecificOperation} with the provided document
74
+ * ID.
75
+ *
76
+ * The returned object can be used to find and return the document or you can
77
+ * chain a call to
78
+ * {@link PendingIDSpecificOperation.observeLocal | observeLocal()}, or
79
+ * {@link PendingIDSpecificOperation.subscribe | subscribe()} if you want to
80
+ * get updates about the document over time. It can also be used to update,
81
+ * remove or evict the document.
82
+ *
83
+ * @param id The ID of the document to find.
84
+ */
85
+ findByID(id: DocumentID | DocumentIDValue): PendingIDSpecificOperation {
86
+ const documentID: DocumentID = id instanceof DocumentID ? id : new DocumentID(id)
87
+ return new PendingIDSpecificOperation(documentID, this)
88
+ }
89
+
90
+ async upsert(value: DocumentValue, options: UpsertOptions = {}): Promise<DocumentID> {
91
+ const ditto = this.store.ditto
92
+ const dittoHandle = Bridge.ditto.handleFor(ditto)
93
+
94
+ return ditto.deferCloseAsync(async () => {
95
+ const writeStrategy = options.writeStrategy ?? 'merge'
96
+
97
+ const documentValueJSON = desugarJSObject(value, true)
98
+ const documentValueCBOR = CBOR.encode(documentValueJSON)
99
+
100
+ const idCBOR = await performAsyncToWorkaroundNonAsyncFFIAPI(async () => {
101
+ return await FFI.collectionInsertValue(dittoHandle.deref(), this.name, documentValueCBOR, writeStrategy, undefined)
102
+ })
103
+
104
+ return new DocumentID(idCBOR, true)
105
+ })
106
+ }
107
+
108
+ /**
109
+ * Creates a new {@link Attachment} object, which can then be inserted into a
110
+ * document. Node only, throws when running in the web browser.
111
+ *
112
+ * The file residing at the provided path will be copied into Ditto's store.
113
+ * The {@link Attachment} object that is returned is what you can then use to
114
+ * insert an attachment into a document.
115
+ *
116
+ * You can provide metadata about the attachment, which will be replicated to
117
+ * other peers alongside the file attachment.
118
+ *
119
+ * Below is a snippet to show how you can use the
120
+ * {@link newAttachment | newAttachment()} functionality to insert an
121
+ * attachment into a document.
122
+ *
123
+ * ``` JavaScript
124
+ * const attachment = await collection.newAttachment('/path/to/my/file.pdf')
125
+ * await collection.upsert({ _id: '123', attachment, other: 'some-string' })
126
+ * }
127
+ * ```
128
+ *
129
+ * @param pathOrData The path to the file that you want to create an
130
+ * attachment with or the raw data.
131
+ *
132
+ * @param metadata Metadata relating to the attachment.
133
+ */
134
+ async newAttachment(pathOrData: string | Uint8Array, metadata: { [key: string]: string } = {}): Promise<Attachment> {
135
+ const ditto = this.store.ditto
136
+ const dittoHandle = Bridge.ditto.handleFor(ditto)
137
+
138
+ return ditto.deferCloseAsync(async () => {
139
+ const { id, len, handle } = await (async () => {
140
+ if (typeof pathOrData === 'string') {
141
+ if (Environment.isWebBuild) {
142
+ throw new Error(`Can't create attachment from file when running in the browser. Please pass the raw data (as a Uint8Array) instead.`)
143
+ }
144
+
145
+ if (Environment.isNodeBuild) {
146
+ return FFI.dittoNewAttachmentFromFile(dittoHandle.deref(), pathOrData as string, 'Copy')
147
+ }
148
+ }
149
+
150
+ if (pathOrData instanceof Uint8Array) {
151
+ return await FFI.dittoNewAttachmentFromBytes(dittoHandle.deref(), pathOrData)
152
+ }
153
+
154
+ throw new Error(`Can't create new attachment, only file path as string or raw data as Uint8Array are supported, but got: ${typeof pathOrData}, ${pathOrData}`)
155
+ })()
156
+
157
+ const attachmentTokenJSON = { _id: id, _len: len, _meta: { ...metadata } }
158
+ attachmentTokenJSON[FFI.DittoCRDTTypeKey] = FFI.DittoCRDTType.attachment
159
+
160
+ const attachmentToken = new AttachmentToken(attachmentTokenJSON)
161
+ const attachment = new Attachment(ditto, attachmentToken)
162
+
163
+ return Bridge.attachment.bridge(handle, () => attachment)
164
+ })
165
+ }
166
+
167
+ /**
168
+ * Trigger an attachment to be downloaded locally to the device and observe
169
+ * its progress as it does so.
170
+ *
171
+ * When you encounter a document that contains an attachment the attachment
172
+ * will not automatically be downloaded along with the document. You trigger
173
+ * an attachment to be downloaded locally to a device by calling this method.
174
+ * It will report events relating to the attachment fetch attempt as it tries
175
+ * to download it. The `eventHandler` block may be called multiple times with
176
+ * progress events. It will then be called with either a `Completed` event or
177
+ * a `Deleted` event. If downloading the attachment succeeds then the
178
+ * `Completed` event that the `eventHandler` will be called with will hold a
179
+ * reference to the downloaded attachment.
180
+ *
181
+ * @param token The {@link AttachmentToken} relevant to the attachment that
182
+ * you wish to download and observe. Throws if token is invalid.
183
+ *
184
+ * @param eventHandler An optional callback that will be called when there is
185
+ * an update to the status of the attachment fetch attempt.
186
+ *
187
+ * @return An `AttachmentFetcher` object, which must be kept alive for the
188
+ * fetch request to proceed and for you to be notified about the attachment's
189
+ * fetch status changes.
190
+ */
191
+ fetchAttachment(token: AttachmentToken, eventHandler?: (event: AttachmentFetchEvent) => void): AttachmentFetcher {
192
+ if (token == null || !(token instanceof AttachmentToken)) {
193
+ throw new Error(`Invalid attachment token: ${token}`)
194
+ }
195
+ const ditto = this.store.ditto
196
+ return ditto.deferClose(() => {
197
+ return ditto.attachmentFetcherManager.startAttachmentFetcher(token, eventHandler)
198
+ })
199
+ }
200
+
201
+ /** @internal */
202
+ constructor(name: string, store: Store) {
203
+ this.name = name
204
+ this.store = store
205
+ }
206
+
207
+ /** @internal */
208
+ findByIDCBOR(idCBOR: Uint8Array): PendingIDSpecificOperation {
209
+ const documentID = new DocumentID(idCBOR, true, true)
210
+ return new PendingIDSpecificOperation(documentID, this)
211
+ }
212
+ }
@@ -0,0 +1,99 @@
1
+ //
2
+ // Copyright (c) 2020 - 2021 DittoLive Inc. All rights reserved.
3
+ //
4
+
5
+ import type { Collection } from './collection'
6
+ import type { LiveQueryMove } from './live-query-event'
7
+
8
+ // -----------------------------------------------------------------------------
9
+
10
+ /** @internal */
11
+ export interface CollectionsEventParams {
12
+ isInitial: boolean
13
+ collections: Collection[]
14
+ oldCollections: Collection[]
15
+ insertions: number[]
16
+ deletions: number[]
17
+ updates: number[]
18
+ moves: LiveQueryMove[]
19
+ }
20
+
21
+ // -----------------------------------------------------------------------------
22
+
23
+ /**
24
+ * Provides information about the changes that have occurred in relation to an
25
+ * event delivered when observing the collections in a {@link Store}.
26
+ *
27
+ * It contains information about the collections that are known about as well as
28
+ * the collections that were previously known about in the previous event, along
29
+ * with information about what collections have been inserted, deleted, updated,
30
+ * or moved since the last event.
31
+ */
32
+ export class CollectionsEvent {
33
+ /**
34
+ * Indicates whether or not this is the first event to be delivered when
35
+ * observing collections in the store.
36
+ */
37
+ readonly isInitial: boolean
38
+
39
+ /**
40
+ * A list of all of the known collections.
41
+ */
42
+ readonly collections: Collection[]
43
+
44
+ /**
45
+ * A list of all of the known collections at the time the previous event was
46
+ * delivered.
47
+ */
48
+ readonly oldCollections: Collection[]
49
+
50
+ /**
51
+ * A list of the indexes in the list of currently known about collections at
52
+ * which new collections have been inserted.
53
+ */
54
+ readonly insertions: number[]
55
+
56
+ /**
57
+ * A list of the indexes in the list of previously known about collections at
58
+ * which collections have been removed.
59
+ */
60
+ readonly deletions: number[]
61
+
62
+ /**
63
+ * A list of the indexes in the list of currently known about collections at
64
+ * which pre-existing collections have been updated.
65
+ */
66
+ readonly updates: number[]
67
+
68
+ /**
69
+ * A list of the tuples that provides the indexes, in relation to the list of
70
+ * previously known about collections, that already known about collections
71
+ * have moved from and the indexes, in relation to the list of currently known
72
+ * about collections, that the collections have moved to.
73
+ */
74
+ readonly moves: LiveQueryMove[]
75
+
76
+ /** @internal */
77
+ static initial(collections: Collection[]): CollectionsEvent {
78
+ return new CollectionsEvent({
79
+ isInitial: true,
80
+ collections: collections,
81
+ oldCollections: [],
82
+ insertions: [],
83
+ deletions: [],
84
+ updates: [],
85
+ moves: [],
86
+ })
87
+ }
88
+
89
+ /** @internal */
90
+ constructor(params: CollectionsEventParams) {
91
+ this.isInitial = params.isInitial
92
+ this.collections = params.collections
93
+ this.oldCollections = params.oldCollections
94
+ this.insertions = params.insertions
95
+ this.deletions = params.deletions
96
+ this.updates = params.updates
97
+ this.moves = params.moves
98
+ }
99
+ }
@@ -0,0 +1,82 @@
1
+ //
2
+ // Copyright © 2021 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 = Symbol('privateConstructorToken')
9
+
10
+ /**
11
+ * Represents a CRDT counter 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 Counter {
15
+ /** The value of the counter. */
16
+ get value(): number {
17
+ return this._value
18
+ }
19
+
20
+ /**
21
+ * Creates a new counter that can be used as part of a document's content.
22
+ */
23
+ constructor() {
24
+ this._value = 0.0
25
+ }
26
+
27
+ /** @internal */
28
+ static '@ditto.create'(mutDoc, path, value) {
29
+ // @ts-expect-error - using hidden argument
30
+ const counter = mutDoc ? new MutableCounter(privateToken) : new Counter()
31
+ counter.mutDoc = mutDoc
32
+ counter.path = path
33
+ counter._value = value
34
+ return counter
35
+ }
36
+
37
+ protected mutDoc: any
38
+ protected path: any
39
+ protected _value: number
40
+ }
41
+
42
+ // -----------------------------------------------------------------------------
43
+
44
+ /**
45
+ * Represents a mutable CRDT counter that can be incremented by a specific
46
+ * amount while updating a document.
47
+ *
48
+ * This class can't be instantiated directly, it's returned automatically for
49
+ * any counter property within an update block via {@link MutableDocumentPath.counter}.
50
+ */
51
+ export class MutableCounter extends Counter {
52
+ /**
53
+ * Increments the counter by `amount`, which can be any valid number.
54
+ *
55
+ * Only valid within the `update` closure of
56
+ * {@link PendingCursorOperation.update | PendingCursorOperation.update()} and
57
+ * {@link PendingIDSpecificOperation.update | PendingIDSpecificOperation.update()},
58
+ * otherwise an exception is thrown.
59
+ */
60
+ increment(amount: number) {
61
+ const mutDoc = this.mutDoc
62
+ const path = this.path
63
+
64
+ if (!mutDoc) {
65
+ throw new Error(`Can't increment counter, only possible within the closure of a collection's update() method.`)
66
+ }
67
+
68
+ mutDoc.at(path)['@ditto.increment'](amount)
69
+ // We also increment the local value to make sure that the change is
70
+ // reflected locally as well as in the underlying document
71
+ this._value += amount
72
+ }
73
+
74
+ /** @internal */
75
+ protected constructor() {
76
+ if (arguments[0] === privateToken) {
77
+ super()
78
+ } else {
79
+ throw new Error(`MutableCounter constructor is for internal use only.`)
80
+ }
81
+ }
82
+ }