@powersync/common 1.51.0 → 1.53.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.
Files changed (91) hide show
  1. package/dist/bundle.cjs +510 -1129
  2. package/dist/bundle.cjs.map +1 -1
  3. package/dist/bundle.mjs +511 -1116
  4. package/dist/bundle.mjs.map +1 -1
  5. package/dist/bundle.node.cjs +508 -1129
  6. package/dist/bundle.node.cjs.map +1 -1
  7. package/dist/bundle.node.mjs +509 -1116
  8. package/dist/bundle.node.mjs.map +1 -1
  9. package/dist/index.d.cts +73 -433
  10. package/legacy/sync_protocol.d.ts +103 -0
  11. package/lib/client/AbstractPowerSyncDatabase.js +3 -3
  12. package/lib/client/AbstractPowerSyncDatabase.js.map +1 -1
  13. package/lib/client/ConnectionManager.js +1 -1
  14. package/lib/client/ConnectionManager.js.map +1 -1
  15. package/lib/client/sync/bucket/BucketStorageAdapter.d.ts +6 -64
  16. package/lib/client/sync/bucket/BucketStorageAdapter.js +4 -0
  17. package/lib/client/sync/bucket/BucketStorageAdapter.js.map +1 -1
  18. package/lib/client/sync/bucket/SqliteBucketStorage.d.ts +1 -28
  19. package/lib/client/sync/bucket/SqliteBucketStorage.js +0 -162
  20. package/lib/client/sync/bucket/SqliteBucketStorage.js.map +1 -1
  21. package/lib/client/sync/stream/AbstractRemote.d.ts +29 -18
  22. package/lib/client/sync/stream/AbstractRemote.js +155 -188
  23. package/lib/client/sync/stream/AbstractRemote.js.map +1 -1
  24. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +13 -35
  25. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +150 -448
  26. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js.map +1 -1
  27. package/lib/client/sync/stream/JsonValue.d.ts +7 -0
  28. package/lib/client/sync/stream/JsonValue.js +2 -0
  29. package/lib/client/sync/stream/JsonValue.js.map +1 -0
  30. package/lib/client/sync/stream/core-instruction.d.ts +14 -9
  31. package/lib/client/sync/stream/core-instruction.js +3 -0
  32. package/lib/client/sync/stream/core-instruction.js.map +1 -1
  33. package/lib/db/DBAdapter.d.ts +9 -0
  34. package/lib/db/DBAdapter.js +8 -1
  35. package/lib/db/DBAdapter.js.map +1 -1
  36. package/lib/db/crud/SyncStatus.d.ts +3 -4
  37. package/lib/db/crud/SyncStatus.js +0 -4
  38. package/lib/db/crud/SyncStatus.js.map +1 -1
  39. package/lib/db/schema/RawTable.d.ts +0 -5
  40. package/lib/db/schema/Schema.d.ts +0 -2
  41. package/lib/db/schema/Schema.js +0 -2
  42. package/lib/db/schema/Schema.js.map +1 -1
  43. package/lib/index.d.ts +2 -6
  44. package/lib/index.js +1 -6
  45. package/lib/index.js.map +1 -1
  46. package/lib/utils/async.d.ts +0 -9
  47. package/lib/utils/async.js +0 -9
  48. package/lib/utils/async.js.map +1 -1
  49. package/lib/utils/stream_transform.d.ts +39 -0
  50. package/lib/utils/stream_transform.js +206 -0
  51. package/lib/utils/stream_transform.js.map +1 -0
  52. package/package.json +15 -10
  53. package/src/client/AbstractPowerSyncDatabase.ts +3 -3
  54. package/src/client/ConnectionManager.ts +1 -1
  55. package/src/client/sync/bucket/BucketStorageAdapter.ts +6 -71
  56. package/src/client/sync/bucket/SqliteBucketStorage.ts +1 -197
  57. package/src/client/sync/stream/AbstractRemote.ts +183 -229
  58. package/src/client/sync/stream/AbstractStreamingSyncImplementation.ts +181 -510
  59. package/src/client/sync/stream/JsonValue.ts +8 -0
  60. package/src/client/sync/stream/core-instruction.ts +15 -5
  61. package/src/db/DBAdapter.ts +20 -2
  62. package/src/db/crud/SyncStatus.ts +4 -5
  63. package/src/db/schema/RawTable.ts +0 -5
  64. package/src/db/schema/Schema.ts +0 -2
  65. package/src/index.ts +2 -6
  66. package/src/utils/async.ts +0 -11
  67. package/src/utils/stream_transform.ts +252 -0
  68. package/lib/client/sync/bucket/OpType.d.ts +0 -16
  69. package/lib/client/sync/bucket/OpType.js +0 -23
  70. package/lib/client/sync/bucket/OpType.js.map +0 -1
  71. package/lib/client/sync/bucket/OplogEntry.d.ts +0 -23
  72. package/lib/client/sync/bucket/OplogEntry.js +0 -36
  73. package/lib/client/sync/bucket/OplogEntry.js.map +0 -1
  74. package/lib/client/sync/bucket/SyncDataBatch.d.ts +0 -6
  75. package/lib/client/sync/bucket/SyncDataBatch.js +0 -12
  76. package/lib/client/sync/bucket/SyncDataBatch.js.map +0 -1
  77. package/lib/client/sync/bucket/SyncDataBucket.d.ts +0 -40
  78. package/lib/client/sync/bucket/SyncDataBucket.js +0 -40
  79. package/lib/client/sync/bucket/SyncDataBucket.js.map +0 -1
  80. package/lib/client/sync/stream/streaming-sync-types.d.ts +0 -143
  81. package/lib/client/sync/stream/streaming-sync-types.js +0 -26
  82. package/lib/client/sync/stream/streaming-sync-types.js.map +0 -1
  83. package/lib/utils/DataStream.d.ts +0 -62
  84. package/lib/utils/DataStream.js +0 -169
  85. package/lib/utils/DataStream.js.map +0 -1
  86. package/src/client/sync/bucket/OpType.ts +0 -23
  87. package/src/client/sync/bucket/OplogEntry.ts +0 -50
  88. package/src/client/sync/bucket/SyncDataBatch.ts +0 -11
  89. package/src/client/sync/bucket/SyncDataBucket.ts +0 -49
  90. package/src/client/sync/stream/streaming-sync-types.ts +0 -210
  91. package/src/utils/DataStream.ts +0 -222
@@ -0,0 +1,8 @@
1
+ type JSONValue = string | number | boolean | null | undefined | JSONObject | JSONArray;
2
+
3
+ interface JSONObject {
4
+ [key: string]: JSONValue;
5
+ }
6
+ type JSONArray = JSONValue[];
7
+
8
+ export type StreamingSyncRequestParameterType = JSONValue;
@@ -1,4 +1,3 @@
1
- import { StreamingSyncRequest } from './streaming-sync-types.js';
2
1
  import * as sync_status from '../../../db/crud/SyncStatus.js';
3
2
  import { FULL_SYNC_PRIORITY } from '../../../db/crud/SyncProgress.js';
4
3
 
@@ -6,12 +5,19 @@ import { FULL_SYNC_PRIORITY } from '../../../db/crud/SyncProgress.js';
6
5
  * An internal instruction emitted by the sync client in the core extension in response to the JS
7
6
  * SDK passing sync data into the extension.
8
7
  */
9
- export type Instruction =
8
+ export type Instruction = InterruptingInstruction | NonInterruptingInstruction;
9
+
10
+ export type InterruptingInstruction =
11
+ | { EstablishSyncStream: EstablishSyncStream }
12
+ | { CloseSyncStream: { hide_disconnect: boolean } };
13
+
14
+ /**
15
+ * An {@link Instruction} that doesn't start or stop a sync iteration.
16
+ */
17
+ export type NonInterruptingInstruction =
10
18
  | { LogLine: LogLine }
11
19
  | { UpdateSyncStatus: UpdateSyncStatus }
12
- | { EstablishSyncStream: EstablishSyncStream }
13
20
  | { FetchCredentials: FetchCredentials }
14
- | { CloseSyncStream: { hide_disconnect: boolean } }
15
21
  | { FlushFileSystem: any }
16
22
  | { DidCompleteSync: any };
17
23
 
@@ -21,7 +27,7 @@ export interface LogLine {
21
27
  }
22
28
 
23
29
  export interface EstablishSyncStream {
24
- request: StreamingSyncRequest;
30
+ request: unknown;
25
31
  }
26
32
 
27
33
  export interface UpdateSyncStatus {
@@ -97,3 +103,7 @@ export function coreStatusToJs(status: CoreSyncStatus): sync_status.SyncStatusOp
97
103
  priorityStatusEntries: status.priority_status.map(priorityToJs)
98
104
  };
99
105
  }
106
+
107
+ export function isInterruptingInstruction(instruction: Instruction): instruction is InterruptingInstruction {
108
+ return 'EstablishSyncStream' in instruction || 'CloseSyncStream' in instruction;
109
+ }
@@ -69,7 +69,17 @@ export interface SqlExecutor {
69
69
  executeBatch: (query: string, params?: any[][]) => Promise<QueryResult>;
70
70
  }
71
71
 
72
- export interface LockContext extends SqlExecutor, DBGetUtils {}
72
+ export interface LockContext extends SqlExecutor, DBGetUtils {
73
+ /**
74
+ * How the connection has been opened.
75
+ *
76
+ * `writer` indicates that the lock context is capable of writing to the database.
77
+ * `queryOnly` indicates that the lock context has been opened in a readwrite mode, but a `PRAGMA query_only = TRUE`
78
+ * disabled writes.
79
+ * `readOnly` indicates that the lock context has been opened by passing `SQLITE_OPEN_READONLY` to `sqlite3_open_v2`.
80
+ */
81
+ connectionType?: 'writer' | 'queryOnly' | 'readOnly';
82
+ }
73
83
 
74
84
  /**
75
85
  * Implements {@link DBGetUtils} on a {@link SqlRunner}.
@@ -263,8 +273,16 @@ class TransactionImplementation extends DBGetUtilsDefaultMixin(BaseTransaction)
263
273
  static async runWith<T>(ctx: LockContext, fn: (tx: Transaction) => Promise<T>): Promise<T> {
264
274
  let tx = new TransactionImplementation(ctx);
265
275
 
276
+ // For write transactions, use BEGIN IMMEDIATE to immediately obtain a write lock on the database (instead of doing
277
+ // that on the first statement). If we have a genuine read-only connection, we also use BEGIN IMMEDIATE there: In
278
+ // WAL mode, that ensures we pin the current state of the database (instead of the state at the first statement in
279
+ // the transaction). But if we have a "fake" read-only connection implemented through `pragma query_only = true`, we
280
+ // can't use this trick because it would attempt to lock the connection. So there, we use a regular `BEGIN`
281
+ // statement.
282
+ const useBeginImmediate = ctx.connectionType != 'queryOnly';
283
+
266
284
  try {
267
- await ctx.execute('BEGIN IMMEDIATE');
285
+ await ctx.execute(useBeginImmediate ? 'BEGIN IMMEDIATE' : 'BEGIN');
268
286
 
269
287
  const result = await fn(tx);
270
288
  await tx.commit();
@@ -39,6 +39,9 @@ export type SyncStatusOptions = {
39
39
  lastSyncedAt?: Date;
40
40
  hasSynced?: boolean;
41
41
  priorityStatusEntries?: SyncPriorityStatus[];
42
+ /**
43
+ * @deprecated This field is no longer set, since {@link SyncClientImplementation.RUST} is the only option.
44
+ */
42
45
  clientImplementation?: SyncClientImplementation;
43
46
  };
44
47
 
@@ -122,8 +125,6 @@ export class SyncStatus {
122
125
  *
123
126
  * This returns null when the database is currently being opened and we don't have reliable information about all
124
127
  * included streams yet.
125
- *
126
- * @experimental Sync streams are currently in alpha.
127
128
  */
128
129
  get syncStreams(): SyncStreamStatus[] | undefined {
129
130
  return this.options.dataFlow?.internalStreamSubscriptions?.map((core) => new SyncStreamStatusView(this, core));
@@ -131,8 +132,6 @@ export class SyncStatus {
131
132
 
132
133
  /**
133
134
  * If the `stream` appears in {@link syncStreams}, returns the current status for that stream.
134
- *
135
- * @experimental Sync streams are currently in alpha.
136
135
  */
137
136
  forStream(stream: SyncStreamDescription): SyncStreamStatus | undefined {
138
137
  const asJson = JSON.stringify(stream.parameters);
@@ -262,7 +261,7 @@ export class SyncStatus {
262
261
  }
263
262
 
264
263
  /**
265
- * Not all errors are serializable over a MessagePort. E.g. some `DomExceptions` fail to be passed across workers.
264
+ * Not all errors are serializable over a MessagePort. E.g. some `DomExceptions` fail to be passed across workers.
266
265
  * This explicitly serializes errors in the SyncStatus.
267
266
  */
268
267
  protected serializeError(error?: Error) {
@@ -9,11 +9,6 @@ import { TableOrRawTableOptions } from './Table.js';
9
9
  * To collect local writes to raw tables with PowerSync, custom triggers are required. See
10
10
  * {@link https://docs.powersync.com/usage/use-case-examples/raw-tables the documentation} for details and an example on
11
11
  * using raw tables.
12
- *
13
- * Note that raw tables are only supported when using the new `SyncClientImplementation.rust` sync client.
14
- *
15
- * @experimental Please note that this feature is experimental at the moment, and not covered by PowerSync semver or
16
- * stability guarantees.
17
12
  */
18
13
  export type RawTableType = RawTableTypeWithStatements | InferredRawTableType;
19
14
 
@@ -51,10 +51,8 @@ export class Schema<S extends SchemaType = SchemaType> {
51
51
  * developer instead of automatically by PowerSync.
52
52
  * Since raw tables are not backed by JSON, running complex queries on them may be more efficient. Further, they allow
53
53
  * using client-side table and column constraints.
54
- * Note that raw tables are only supported when using the new `SyncClientImplementation.rust` sync client.
55
54
  *
56
55
  * @param tables An object of (table name, raw table definition) entries.
57
- * @experimental Note that the raw tables API is still experimental and may change in the future.
58
56
  */
59
57
  withRawTables(tables: Record<string, RawTableType>) {
60
58
  for (const [name, rawTableDefinition] of Object.entries(tables)) {
package/src/index.ts CHANGED
@@ -20,14 +20,10 @@ export * from './client/sync/bucket/BucketStorageAdapter.js';
20
20
  export * from './client/sync/bucket/CrudBatch.js';
21
21
  export { CrudEntry, OpId, UpdateType } from './client/sync/bucket/CrudEntry.js';
22
22
  export * from './client/sync/bucket/CrudTransaction.js';
23
- export * from './client/sync/bucket/OplogEntry.js';
24
- export * from './client/sync/bucket/OpType.js';
25
23
  export * from './client/sync/bucket/SqliteBucketStorage.js';
26
- export * from './client/sync/bucket/SyncDataBatch.js';
27
- export * from './client/sync/bucket/SyncDataBucket.js';
28
24
  export * from './client/sync/stream/AbstractRemote.js';
29
25
  export * from './client/sync/stream/AbstractStreamingSyncImplementation.js';
30
- export * from './client/sync/stream/streaming-sync-types.js';
26
+ export * from './client/sync/stream/JsonValue.js';
31
27
  export * from './client/sync/sync-streams.js';
32
28
 
33
29
  export * from './client/ConnectionManager.js';
@@ -59,9 +55,9 @@ export * from './client/watched/WatchedQuery.js';
59
55
  export * from './utils/AbortOperation.js';
60
56
  export * from './utils/BaseObserver.js';
61
57
  export * from './utils/ControlledExecutor.js';
62
- export * from './utils/DataStream.js';
63
58
  export * from './utils/Logger.js';
64
59
  export * from './utils/mutex.js';
65
60
  export * from './utils/parseQuery.js';
61
+ export type { SimpleAsyncIterator } from './utils/stream_transform.js';
66
62
 
67
63
  export * from './types/types.js';
@@ -1,14 +1,3 @@
1
- /**
2
- * A ponyfill for `Symbol.asyncIterator` that is compatible with the
3
- * [recommended polyfill](https://github.com/Azure/azure-sdk-for-js/blob/%40azure/core-asynciterator-polyfill_1.0.2/sdk/core/core-asynciterator-polyfill/src/index.ts#L4-L6)
4
- * we recommend for React Native.
5
- *
6
- * As long as we use this symbol (instead of `for await` and `async *`) in this package, we can be compatible with async
7
- * iterators without requiring them.
8
- */
9
- export const symbolAsyncIterator: typeof Symbol.asyncIterator =
10
- Symbol.asyncIterator ?? Symbol.for('Symbol.asyncIterator');
11
-
12
1
  /**
13
2
  * Throttle a function to be called at most once every "wait" milliseconds,
14
3
  * on the trailing edge.
@@ -0,0 +1,252 @@
1
+ /**
2
+ * An async iterator that can't be cancelled.
3
+ *
4
+ * To keep data flow simple, we always pass an explicit cancellation token when subscribing to async streams. Once the
5
+ * {@link AbortSignal} aborts, iterators are supposed to clean up and then emit a final `{done: true}` event. This means
6
+ * that there's no way to distinguish between streams that have completed normally and streams that have been cancelled,
7
+ * but that is acceptable for our uses of this.
8
+ */
9
+ export type SimpleAsyncIterator<T> = Pick<AsyncIterator<T>, 'next'>;
10
+
11
+ export const doneResult: IteratorReturnResult<any> = { done: true, value: undefined };
12
+
13
+ export function valueResult<T>(value: T) {
14
+ return { done: false, value };
15
+ }
16
+
17
+ /**
18
+ * A variant of {@link Array.map} for async iterators.
19
+ */
20
+ export function map<T1, T2>(source: SimpleAsyncIterator<T1>, map: (source: T1) => T2): SimpleAsyncIterator<T2> {
21
+ return {
22
+ next: async () => {
23
+ const value = await source.next();
24
+ if (value.done) {
25
+ return value;
26
+ } else {
27
+ return { value: map(value.value) };
28
+ }
29
+ }
30
+ };
31
+ }
32
+
33
+ export interface InjectableIterator<T> extends SimpleAsyncIterator<T> {
34
+ inject(event: T): void;
35
+ }
36
+
37
+ /**
38
+ * Expands a source async iterator by allowing to inject events asynchronously.
39
+ *
40
+ * The resulting iterator will emit all events from its source. Additionally though, events can be injected. These
41
+ * events are dropped once the main iterator completes, but are otherwise forwarded.
42
+ *
43
+ * The iterator completes when its source completes, and it supports backpressure by only calling `next()` on the source
44
+ * in response to a `next()` call from downstream if no pending injected events can be dispatched.
45
+ */
46
+ export function injectable<T>(source: SimpleAsyncIterator<T>): InjectableIterator<T> {
47
+ type Waiter = { resolve: (t: IteratorResult<T>) => void; reject: (e: unknown) => void };
48
+
49
+ let sourceIsDone = false;
50
+ let waiter: Waiter | undefined = undefined; // An active, waiting next() call.
51
+ // A pending upstream event that couldn't be dispatched because inject() has been called before it was resolved.
52
+ let pendingSourceEvent: ((w: Waiter) => void) | null = null;
53
+
54
+ let pendingInjectedEvents: T[] = [];
55
+
56
+ const consumeWaiter = () => {
57
+ const pending = waiter;
58
+ waiter = undefined;
59
+ return pending;
60
+ };
61
+
62
+ const fetchFromSource = () => {
63
+ const resolveWaiter = (propagate: (w: Waiter) => void) => {
64
+ const active = consumeWaiter();
65
+ if (active) {
66
+ propagate(active);
67
+ } else {
68
+ pendingSourceEvent = propagate;
69
+ }
70
+ };
71
+
72
+ const nextFromSource = source.next();
73
+ nextFromSource.then(
74
+ (value) => {
75
+ sourceIsDone = value.done == true;
76
+ resolveWaiter((w) => w.resolve(value));
77
+ },
78
+ (error) => {
79
+ resolveWaiter((w) => w.reject(error));
80
+ }
81
+ );
82
+ };
83
+
84
+ return {
85
+ next: () => {
86
+ return new Promise((resolve, reject) => {
87
+ // First priority: Dispatch ready upstream events.
88
+ if (sourceIsDone) {
89
+ return resolve(doneResult);
90
+ }
91
+ if (pendingSourceEvent) {
92
+ pendingSourceEvent({ resolve, reject });
93
+ pendingSourceEvent = null;
94
+ return;
95
+ }
96
+
97
+ // Second priority: Dispatch injected events
98
+ if (pendingInjectedEvents.length) {
99
+ return resolve(valueResult(pendingInjectedEvents.shift()!));
100
+ }
101
+
102
+ // Nothing pending? Fetch from source
103
+ waiter = { resolve, reject };
104
+ return fetchFromSource();
105
+ });
106
+ },
107
+ inject: (event) => {
108
+ const pending = consumeWaiter();
109
+ if (pending != null) {
110
+ pending.resolve(valueResult(event));
111
+ } else {
112
+ pendingInjectedEvents.push(event);
113
+ }
114
+ }
115
+ };
116
+ }
117
+
118
+ /**
119
+ * Splits a byte stream at line endings, emitting each line as a string.
120
+ */
121
+ export function extractJsonLines(
122
+ source: SimpleAsyncIterator<Uint8Array>,
123
+ decoder: TextDecoder
124
+ ): SimpleAsyncIterator<string> {
125
+ let buffer = '';
126
+ const pendingLines: string[] = [];
127
+ let isFinalEvent = false;
128
+
129
+ return {
130
+ next: async () => {
131
+ while (true) {
132
+ if (isFinalEvent) {
133
+ return doneResult;
134
+ }
135
+
136
+ {
137
+ const first = pendingLines.shift();
138
+ if (first) {
139
+ return { done: false, value: first };
140
+ }
141
+ }
142
+
143
+ const { done, value } = await source.next();
144
+ if (done) {
145
+ const remaining = buffer.trim();
146
+ if (remaining.length != 0) {
147
+ isFinalEvent = true;
148
+ return { done: false, value: remaining };
149
+ }
150
+
151
+ return doneResult;
152
+ }
153
+
154
+ const data = decoder.decode(value, { stream: true });
155
+ buffer += data;
156
+
157
+ const lines = buffer.split('\n');
158
+ for (let i = 0; i < lines.length - 1; i++) {
159
+ const l = lines[i].trim();
160
+ if (l.length > 0) {
161
+ pendingLines.push(l);
162
+ }
163
+ }
164
+
165
+ buffer = lines[lines.length - 1];
166
+ }
167
+ }
168
+ };
169
+ }
170
+
171
+ /**
172
+ * Splits a concatenated stream of BSON objects by emitting individual objects.
173
+ */
174
+ export function extractBsonObjects(source: SimpleAsyncIterator<Uint8Array>): SimpleAsyncIterator<Uint8Array> {
175
+ // Fully read but not emitted yet.
176
+ const completedObjects: Uint8Array[] = [];
177
+
178
+ // Whether source has returned { done: true }. We do the same once completed objects have been emitted.
179
+ let isDone = false;
180
+
181
+ const lengthBuffer = new DataView(new ArrayBuffer(4));
182
+ let objectBody: Uint8Array | null = null;
183
+ // If we're parsing the length field, a number between 1 and 4 (inclusive) describing remaining bytes in the header.
184
+ // If we're consuming a document, the bytes remaining.
185
+ let remainingLength = 4;
186
+
187
+ return {
188
+ async next(): Promise<IteratorResult<Uint8Array>> {
189
+ while (true) {
190
+ // Before fetching new data from upstream, return completed objects.
191
+ if (completedObjects.length) {
192
+ return valueResult(completedObjects.shift()!);
193
+ }
194
+ if (isDone) {
195
+ return doneResult;
196
+ }
197
+
198
+ const upstreamEvent = await source.next();
199
+ if (upstreamEvent.done) {
200
+ isDone = true;
201
+ if (objectBody || remainingLength != 4) {
202
+ throw new Error('illegal end of stream in BSON object');
203
+ }
204
+ return doneResult;
205
+ }
206
+
207
+ const chunk = upstreamEvent.value;
208
+ for (let i = 0; i < chunk.length; ) {
209
+ const availableInData = chunk.length - i;
210
+
211
+ if (objectBody) {
212
+ // We're in the middle of reading a BSON document.
213
+ const bytesToRead = Math.min(availableInData, remainingLength);
214
+ const copySource = new Uint8Array(chunk.buffer, chunk.byteOffset + i, bytesToRead);
215
+ objectBody.set(copySource, objectBody.length - remainingLength);
216
+ i += bytesToRead;
217
+ remainingLength -= bytesToRead;
218
+
219
+ if (remainingLength == 0) {
220
+ completedObjects.push(objectBody);
221
+
222
+ // Prepare to read another document, starting with its length
223
+ objectBody = null;
224
+ remainingLength = 4;
225
+ }
226
+ } else {
227
+ // Copy up to 4 bytes into lengthBuffer, depending on how many we still need.
228
+ const bytesToRead = Math.min(availableInData, remainingLength);
229
+ for (let j = 0; j < bytesToRead; j++) {
230
+ lengthBuffer.setUint8(4 - remainingLength + j, chunk[i + j]);
231
+ }
232
+ i += bytesToRead;
233
+ remainingLength -= bytesToRead;
234
+
235
+ if (remainingLength == 0) {
236
+ // Transition from reading length header to reading document. Subtracting 4 because the length of the
237
+ // header is included in length.
238
+ const length = lengthBuffer.getInt32(0, true /* little endian */);
239
+ remainingLength = length - 4;
240
+ if (remainingLength < 1) {
241
+ throw new Error(`invalid length for bson: ${length}`);
242
+ }
243
+
244
+ objectBody = new Uint8Array(length);
245
+ new DataView(objectBody.buffer).setInt32(0, length, true);
246
+ }
247
+ }
248
+ }
249
+ }
250
+ }
251
+ };
252
+ }
@@ -1,16 +0,0 @@
1
- export declare enum OpTypeEnum {
2
- CLEAR = 1,
3
- MOVE = 2,
4
- PUT = 3,
5
- REMOVE = 4
6
- }
7
- export type OpTypeJSON = string;
8
- /**
9
- * Used internally for sync buckets.
10
- */
11
- export declare class OpType {
12
- value: OpTypeEnum;
13
- static fromJSON(jsonValue: OpTypeJSON): OpType;
14
- constructor(value: OpTypeEnum);
15
- toJSON(): string;
16
- }
@@ -1,23 +0,0 @@
1
- export var OpTypeEnum;
2
- (function (OpTypeEnum) {
3
- OpTypeEnum[OpTypeEnum["CLEAR"] = 1] = "CLEAR";
4
- OpTypeEnum[OpTypeEnum["MOVE"] = 2] = "MOVE";
5
- OpTypeEnum[OpTypeEnum["PUT"] = 3] = "PUT";
6
- OpTypeEnum[OpTypeEnum["REMOVE"] = 4] = "REMOVE";
7
- })(OpTypeEnum || (OpTypeEnum = {}));
8
- /**
9
- * Used internally for sync buckets.
10
- */
11
- export class OpType {
12
- value;
13
- static fromJSON(jsonValue) {
14
- return new OpType(OpTypeEnum[jsonValue]);
15
- }
16
- constructor(value) {
17
- this.value = value;
18
- }
19
- toJSON() {
20
- return Object.entries(OpTypeEnum).find(([, value]) => value === this.value)[0];
21
- }
22
- }
23
- //# sourceMappingURL=OpType.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"OpType.js","sourceRoot":"","sources":["../../../../src/client/sync/bucket/OpType.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,UAKX;AALD,WAAY,UAAU;IACpB,6CAAS,CAAA;IACT,2CAAQ,CAAA;IACR,yCAAO,CAAA;IACP,+CAAU,CAAA;AACZ,CAAC,EALW,UAAU,KAAV,UAAU,QAKrB;AAID;;GAEG;AACH,MAAM,OAAO,MAAM;IAKE;IAJnB,MAAM,CAAC,QAAQ,CAAC,SAAqB;QACnC,OAAO,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,YAAmB,KAAiB;QAAjB,UAAK,GAAL,KAAK,CAAY;IAAG,CAAC;IAExC,MAAM;QACJ,OAAO,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAE,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC;CACF"}
@@ -1,23 +0,0 @@
1
- import { OpId } from './CrudEntry.js';
2
- import { OpType, OpTypeJSON } from './OpType.js';
3
- export interface OplogEntryJSON {
4
- checksum: number;
5
- data?: string;
6
- object_id?: string;
7
- object_type?: string;
8
- op_id: string;
9
- op: OpTypeJSON;
10
- subkey?: string;
11
- }
12
- export declare class OplogEntry {
13
- op_id: OpId;
14
- op: OpType;
15
- checksum: number;
16
- subkey?: string | undefined;
17
- object_type?: string | undefined;
18
- object_id?: string | undefined;
19
- data?: string | undefined;
20
- static fromRow(row: OplogEntryJSON): OplogEntry;
21
- constructor(op_id: OpId, op: OpType, checksum: number, subkey?: string | undefined, object_type?: string | undefined, object_id?: string | undefined, data?: string | undefined);
22
- toJSON(fixedKeyEncoding?: boolean): OplogEntryJSON;
23
- }
@@ -1,36 +0,0 @@
1
- import { OpType } from './OpType.js';
2
- export class OplogEntry {
3
- op_id;
4
- op;
5
- checksum;
6
- subkey;
7
- object_type;
8
- object_id;
9
- data;
10
- static fromRow(row) {
11
- return new OplogEntry(row.op_id, OpType.fromJSON(row.op), row.checksum, row.subkey, row.object_type, row.object_id, row.data);
12
- }
13
- constructor(op_id, op, checksum, subkey, object_type, object_id, data) {
14
- this.op_id = op_id;
15
- this.op = op;
16
- this.checksum = checksum;
17
- this.subkey = subkey;
18
- this.object_type = object_type;
19
- this.object_id = object_id;
20
- this.data = data;
21
- }
22
- toJSON(fixedKeyEncoding = false) {
23
- return {
24
- op_id: this.op_id,
25
- op: this.op.toJSON(),
26
- object_type: this.object_type,
27
- object_id: this.object_id,
28
- checksum: this.checksum,
29
- data: this.data,
30
- // Older versions of the JS SDK used to always JSON.stringify here. That has always been wrong,
31
- // but we need to migrate gradually to not break existing databases.
32
- subkey: fixedKeyEncoding ? this.subkey : JSON.stringify(this.subkey)
33
- };
34
- }
35
- }
36
- //# sourceMappingURL=OplogEntry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"OplogEntry.js","sourceRoot":"","sources":["../../../../src/client/sync/bucket/OplogEntry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAc,MAAM,aAAa,CAAC;AAYjD,MAAM,OAAO,UAAU;IAcZ;IACA;IACA;IACA;IACA;IACA;IACA;IAnBT,MAAM,CAAC,OAAO,CAAC,GAAmB;QAChC,OAAO,IAAI,UAAU,CACnB,GAAG,CAAC,KAAK,EACT,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EACvB,GAAG,CAAC,QAAQ,EACZ,GAAG,CAAC,MAAM,EACV,GAAG,CAAC,WAAW,EACf,GAAG,CAAC,SAAS,EACb,GAAG,CAAC,IAAI,CACT,CAAC;IACJ,CAAC;IAED,YACS,KAAW,EACX,EAAU,EACV,QAAgB,EAChB,MAAe,EACf,WAAoB,EACpB,SAAkB,EAClB,IAAa;QANb,UAAK,GAAL,KAAK,CAAM;QACX,OAAE,GAAF,EAAE,CAAQ;QACV,aAAQ,GAAR,QAAQ,CAAQ;QAChB,WAAM,GAAN,MAAM,CAAS;QACf,gBAAW,GAAX,WAAW,CAAS;QACpB,cAAS,GAAT,SAAS,CAAS;QAClB,SAAI,GAAJ,IAAI,CAAS;IACnB,CAAC;IAEJ,MAAM,CAAC,gBAAgB,GAAG,KAAK;QAC7B,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE;YACpB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,+FAA+F;YAC/F,oEAAoE;YACpE,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;SACrE,CAAC;IACJ,CAAC;CACF"}
@@ -1,6 +0,0 @@
1
- import { SyncDataBucket } from './SyncDataBucket.js';
2
- export declare class SyncDataBatch {
3
- buckets: SyncDataBucket[];
4
- static fromJSON(json: any): SyncDataBatch;
5
- constructor(buckets: SyncDataBucket[]);
6
- }
@@ -1,12 +0,0 @@
1
- import { SyncDataBucket } from './SyncDataBucket.js';
2
- // TODO JSON
3
- export class SyncDataBatch {
4
- buckets;
5
- static fromJSON(json) {
6
- return new SyncDataBatch(json.buckets.map((bucket) => SyncDataBucket.fromRow(bucket)));
7
- }
8
- constructor(buckets) {
9
- this.buckets = buckets;
10
- }
11
- }
12
- //# sourceMappingURL=SyncDataBatch.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SyncDataBatch.js","sourceRoot":"","sources":["../../../../src/client/sync/bucket/SyncDataBatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,YAAY;AAEZ,MAAM,OAAO,aAAa;IAKL;IAJnB,MAAM,CAAC,QAAQ,CAAC,IAAS;QACvB,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAW,EAAE,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC9F,CAAC;IAED,YAAmB,OAAyB;QAAzB,YAAO,GAAP,OAAO,CAAkB;IAAG,CAAC;CACjD"}
@@ -1,40 +0,0 @@
1
- import { OpId } from './CrudEntry.js';
2
- import { OplogEntry, OplogEntryJSON } from './OplogEntry.js';
3
- export type SyncDataBucketJSON = {
4
- bucket: string;
5
- has_more?: boolean;
6
- after?: string;
7
- next_after?: string;
8
- data: OplogEntryJSON[];
9
- };
10
- export declare class SyncDataBucket {
11
- bucket: string;
12
- data: OplogEntry[];
13
- /**
14
- * True if the response does not contain all the data for this bucket, and another request must be made.
15
- */
16
- has_more: boolean;
17
- /**
18
- * The `after` specified in the request.
19
- */
20
- after?: OpId | undefined;
21
- /**
22
- * Use this for the next request.
23
- */
24
- next_after?: OpId | undefined;
25
- static fromRow(row: SyncDataBucketJSON): SyncDataBucket;
26
- constructor(bucket: string, data: OplogEntry[],
27
- /**
28
- * True if the response does not contain all the data for this bucket, and another request must be made.
29
- */
30
- has_more: boolean,
31
- /**
32
- * The `after` specified in the request.
33
- */
34
- after?: OpId | undefined,
35
- /**
36
- * Use this for the next request.
37
- */
38
- next_after?: OpId | undefined);
39
- toJSON(fixedKeyEncoding?: boolean): SyncDataBucketJSON;
40
- }
@@ -1,40 +0,0 @@
1
- import { OplogEntry } from './OplogEntry.js';
2
- export class SyncDataBucket {
3
- bucket;
4
- data;
5
- has_more;
6
- after;
7
- next_after;
8
- static fromRow(row) {
9
- return new SyncDataBucket(row.bucket, row.data.map((entry) => OplogEntry.fromRow(entry)), row.has_more ?? false, row.after, row.next_after);
10
- }
11
- constructor(bucket, data,
12
- /**
13
- * True if the response does not contain all the data for this bucket, and another request must be made.
14
- */
15
- has_more,
16
- /**
17
- * The `after` specified in the request.
18
- */
19
- after,
20
- /**
21
- * Use this for the next request.
22
- */
23
- next_after) {
24
- this.bucket = bucket;
25
- this.data = data;
26
- this.has_more = has_more;
27
- this.after = after;
28
- this.next_after = next_after;
29
- }
30
- toJSON(fixedKeyEncoding = false) {
31
- return {
32
- bucket: this.bucket,
33
- has_more: this.has_more,
34
- after: this.after,
35
- next_after: this.next_after,
36
- data: this.data.map((entry) => entry.toJSON(fixedKeyEncoding))
37
- };
38
- }
39
- }
40
- //# sourceMappingURL=SyncDataBucket.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SyncDataBucket.js","sourceRoot":"","sources":["../../../../src/client/sync/bucket/SyncDataBucket.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAkB,MAAM,iBAAiB,CAAC;AAU7D,MAAM,OAAO,cAAc;IAYhB;IACA;IAIA;IAIA;IAIA;IAxBT,MAAM,CAAC,OAAO,CAAC,GAAuB;QACpC,OAAO,IAAI,cAAc,CACvB,GAAG,CAAC,MAAM,EACV,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAClD,GAAG,CAAC,QAAQ,IAAI,KAAK,EACrB,GAAG,CAAC,KAAK,EACT,GAAG,CAAC,UAAU,CACf,CAAC;IACJ,CAAC;IAED,YACS,MAAc,EACd,IAAkB;IACzB;;OAEG;IACI,QAAiB;IACxB;;OAEG;IACI,KAAY;IACnB;;OAEG;IACI,UAAiB;QAbjB,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAc;QAIlB,aAAQ,GAAR,QAAQ,CAAS;QAIjB,UAAK,GAAL,KAAK,CAAO;QAIZ,eAAU,GAAV,UAAU,CAAO;IACvB,CAAC;IAEJ,MAAM,CAAC,gBAAgB,GAAG,KAAK;QAC7B,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;SAC/D,CAAC;IACJ,CAAC;CACF"}