@powersync/service-module-mongodb-storage 0.0.0-dev-20250820110726 → 0.0.0-dev-20250827072023

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 (55) hide show
  1. package/CHANGELOG.md +11 -7
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.js +1 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/migrations/db/migrations/1752661449910-connection-reporting.js +0 -12
  6. package/dist/migrations/db/migrations/1752661449910-connection-reporting.js.map +1 -1
  7. package/dist/storage/MongoBucketStorage.js +1 -1
  8. package/dist/storage/MongoBucketStorage.js.map +1 -1
  9. package/dist/storage/MongoReportStorage.d.ts +2 -3
  10. package/dist/storage/MongoReportStorage.js +8 -25
  11. package/dist/storage/MongoReportStorage.js.map +1 -1
  12. package/dist/storage/implementation/MongoBucketBatch.js +1 -1
  13. package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
  14. package/dist/storage/implementation/MongoSyncBucketStorage.js +1 -1
  15. package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
  16. package/dist/storage/implementation/PersistedBatch.js +1 -1
  17. package/dist/storage/implementation/PersistedBatch.js.map +1 -1
  18. package/dist/storage/storage-index.d.ts +2 -2
  19. package/dist/storage/storage-index.js +2 -2
  20. package/dist/storage/storage-index.js.map +1 -1
  21. package/dist/utils/test-utils.d.ts +11 -0
  22. package/dist/utils/test-utils.js +40 -0
  23. package/dist/utils/test-utils.js.map +1 -0
  24. package/dist/{storage/implementation → utils}/util.d.ts +1 -6
  25. package/dist/{storage/implementation → utils}/util.js +0 -15
  26. package/dist/utils/util.js.map +1 -0
  27. package/dist/utils/utils-index.d.ts +2 -0
  28. package/dist/utils/utils-index.js +3 -0
  29. package/dist/utils/utils-index.js.map +1 -0
  30. package/package.json +8 -8
  31. package/src/index.ts +1 -0
  32. package/src/migrations/db/migrations/1752661449910-connection-reporting.ts +0 -12
  33. package/src/storage/MongoBucketStorage.ts +1 -1
  34. package/src/storage/MongoReportStorage.ts +11 -29
  35. package/src/storage/implementation/MongoBucketBatch.ts +1 -1
  36. package/src/storage/implementation/MongoSyncBucketStorage.ts +1 -1
  37. package/src/storage/implementation/PersistedBatch.ts +1 -1
  38. package/src/storage/storage-index.ts +2 -2
  39. package/src/utils/test-utils.ts +55 -0
  40. package/src/{storage/implementation → utils}/util.ts +1 -17
  41. package/src/utils/utils-index.ts +2 -0
  42. package/test/src/__snapshots__/connection-report-storage.test.ts.snap +63 -46
  43. package/test/src/__snapshots__/storage_sync.test.ts.snap +12 -11
  44. package/test/src/connection-report-storage.test.ts +69 -192
  45. package/test/src/util.ts +3 -5
  46. package/tsconfig.tsbuildinfo +1 -1
  47. package/dist/storage/implementation/MongoTestReportStorageFactoryGenerator.d.ts +0 -7
  48. package/dist/storage/implementation/MongoTestReportStorageFactoryGenerator.js +0 -13
  49. package/dist/storage/implementation/MongoTestReportStorageFactoryGenerator.js.map +0 -1
  50. package/dist/storage/implementation/MongoTestStorageFactoryGenerator.d.ts +0 -7
  51. package/dist/storage/implementation/MongoTestStorageFactoryGenerator.js +0 -18
  52. package/dist/storage/implementation/MongoTestStorageFactoryGenerator.js.map +0 -1
  53. package/dist/storage/implementation/util.js.map +0 -1
  54. package/src/storage/implementation/MongoTestReportStorageFactoryGenerator.ts +0 -22
  55. package/src/storage/implementation/MongoTestStorageFactoryGenerator.ts +0 -28
@@ -0,0 +1,11 @@
1
+ import { PowerSyncMongo } from '../storage/implementation/db.js';
2
+ import { TestStorageOptions } from '@powersync/service-core';
3
+ import { MongoReportStorage } from '../storage/MongoReportStorage.js';
4
+ import { MongoBucketStorage } from '../storage/MongoBucketStorage.js';
5
+ export type MongoTestStorageOptions = {
6
+ url: string;
7
+ isCI: boolean;
8
+ };
9
+ export declare function mongoTestStorageFactoryGenerator(factoryOptions: MongoTestStorageOptions): (options?: TestStorageOptions) => Promise<MongoBucketStorage>;
10
+ export declare function mongoTestReportStorageFactoryGenerator(factoryOptions: MongoTestStorageOptions): (options?: TestStorageOptions) => Promise<MongoReportStorage>;
11
+ export declare const connectMongoForTests: (url: string, isCI: boolean) => PowerSyncMongo;
@@ -0,0 +1,40 @@
1
+ import { mongo } from '@powersync/lib-service-mongodb';
2
+ import { PowerSyncMongo } from '../storage/implementation/db.js';
3
+ import { MongoReportStorage } from '../storage/MongoReportStorage.js';
4
+ import { MongoBucketStorage } from '../storage/MongoBucketStorage.js';
5
+ export function mongoTestStorageFactoryGenerator(factoryOptions) {
6
+ return async (options) => {
7
+ const db = connectMongoForTests(factoryOptions.url, factoryOptions.isCI);
8
+ // None of the tests insert data into this collection, so it was never created
9
+ if (!(await db.db.listCollections({ name: db.bucket_parameters.collectionName }).hasNext())) {
10
+ await db.db.createCollection('bucket_parameters');
11
+ }
12
+ // Full migrations are not currently run for tests, so we manually create this
13
+ await db.createCheckpointEventsCollection();
14
+ if (!options?.doNotClear) {
15
+ await db.clear();
16
+ }
17
+ return new MongoBucketStorage(db, { slot_name_prefix: 'test_' });
18
+ };
19
+ }
20
+ export function mongoTestReportStorageFactoryGenerator(factoryOptions) {
21
+ return async (options) => {
22
+ const db = connectMongoForTests(factoryOptions.url, factoryOptions.isCI);
23
+ await db.createConnectionReportingCollection();
24
+ if (!options?.doNotClear) {
25
+ await db.clear();
26
+ }
27
+ return new MongoReportStorage(db);
28
+ };
29
+ }
30
+ export const connectMongoForTests = (url, isCI) => {
31
+ // Short timeout for tests, to fail fast when the server is not available.
32
+ // Slightly longer timeouts for CI, to avoid arbitrary test failures
33
+ const client = new mongo.MongoClient(url, {
34
+ connectTimeoutMS: isCI ? 15_000 : 5_000,
35
+ socketTimeoutMS: isCI ? 15_000 : 5_000,
36
+ serverSelectionTimeoutMS: isCI ? 15_000 : 2_500
37
+ });
38
+ return new PowerSyncMongo(client);
39
+ };
40
+ //# sourceMappingURL=test-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../../src/utils/test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAOtE,MAAM,UAAU,gCAAgC,CAAC,cAAuC;IACtF,OAAO,KAAK,EAAE,OAA4B,EAAE,EAAE;QAC5C,MAAM,EAAE,GAAG,oBAAoB,CAAC,cAAc,CAAC,GAAG,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;QAEzE,8EAA8E;QAC9E,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,iBAAiB,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;YAC5F,MAAM,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;QACpD,CAAC;QAED,8EAA8E;QAC9E,MAAM,EAAE,CAAC,gCAAgC,EAAE,CAAC;QAE5C,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;YACzB,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;QAED,OAAO,IAAI,kBAAkB,CAAC,EAAE,EAAE,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sCAAsC,CAAC,cAAuC;IAC5F,OAAO,KAAK,EAAE,OAA4B,EAAE,EAAE;QAC5C,MAAM,EAAE,GAAG,oBAAoB,CAAC,cAAc,CAAC,GAAG,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;QAEzE,MAAM,EAAE,CAAC,mCAAmC,EAAE,CAAC;QAE/C,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;YACzB,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;QAED,OAAO,IAAI,kBAAkB,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,GAAW,EAAE,IAAa,EAAE,EAAE;IACjE,0EAA0E;IAC1E,oEAAoE;IACpE,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QACxC,gBAAgB,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK;QACvC,eAAe,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK;QACtC,wBAAwB,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK;KAChD,CAAC,CAAC;IACH,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC,CAAC"}
@@ -1,8 +1,7 @@
1
1
  import * as bson from 'bson';
2
2
  import { mongo } from '@powersync/lib-service-mongodb';
3
3
  import { storage, utils } from '@powersync/service-core';
4
- import { PowerSyncMongo } from './db.js';
5
- import { BucketDataDocument } from './models.js';
4
+ import { BucketDataDocument } from '../storage/implementation/models.js';
6
5
  export declare function idPrefixFilter<T>(prefix: Partial<T>, rest: (keyof T)[]): mongo.Condition<T>;
7
6
  export declare function generateSlotName(prefix: string, sync_rules_id: number): string;
8
7
  /**
@@ -22,8 +21,4 @@ export declare function readSingleBatch<T>(cursor: mongo.FindCursor<T>): Promise
22
21
  }>;
23
22
  export declare function mapOpEntry(row: BucketDataDocument): utils.OplogEntry;
24
23
  export declare function replicaIdToSubkey(table: bson.ObjectId, id: storage.ReplicaId): string;
25
- /**
26
- * Helper for unit tests
27
- */
28
- export declare const connectMongoForTests: (url: string, isCI: boolean) => PowerSyncMongo;
29
24
  export declare function setSessionSnapshotTime(session: mongo.ClientSession, time: bson.Timestamp): void;
@@ -1,9 +1,7 @@
1
1
  import * as bson from 'bson';
2
2
  import * as crypto from 'crypto';
3
3
  import * as uuid from 'uuid';
4
- import { mongo } from '@powersync/lib-service-mongodb';
5
4
  import { storage, utils } from '@powersync/service-core';
6
- import { PowerSyncMongo } from './db.js';
7
5
  import { ServiceAssertionError } from '@powersync/lib-services-framework';
8
6
  export function idPrefixFilter(prefix, rest) {
9
7
  let filter = {
@@ -96,19 +94,6 @@ export function replicaIdToSubkey(table, id) {
96
94
  return uuid.v5(repr, utils.ID_NAMESPACE);
97
95
  }
98
96
  }
99
- /**
100
- * Helper for unit tests
101
- */
102
- export const connectMongoForTests = (url, isCI) => {
103
- // Short timeout for tests, to fail fast when the server is not available.
104
- // Slightly longer timeouts for CI, to avoid arbitrary test failures
105
- const client = new mongo.MongoClient(url, {
106
- connectTimeoutMS: isCI ? 15_000 : 5_000,
107
- socketTimeoutMS: isCI ? 15_000 : 5_000,
108
- serverSelectionTimeoutMS: isCI ? 15_000 : 2_500
109
- });
110
- return new PowerSyncMongo(client);
111
- };
112
97
  export function setSessionSnapshotTime(session, time) {
113
98
  // This is a workaround for the lack of direct support for snapshot reads in the MongoDB driver.
114
99
  if (!session.snapshotEnabled) {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/utils/util.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * as test_utils from './test-utils.js';
2
+ export * from './util.js';
@@ -0,0 +1,3 @@
1
+ export * as test_utils from './test-utils.js';
2
+ export * from './util.js';
3
+ //# sourceMappingURL=utils-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-index.js","sourceRoot":"","sources":["../../src/utils/utils-index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAC;AAC9C,cAAc,WAAW,CAAC"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@powersync/service-module-mongodb-storage",
3
3
  "repository": "https://github.com/powersync-ja/powersync-service",
4
4
  "types": "dist/index.d.ts",
5
- "version": "0.0.0-dev-20250820110726",
5
+ "version": "0.0.0-dev-20250827072023",
6
6
  "main": "dist/index.js",
7
7
  "license": "FSL-1.1-ALv2",
8
8
  "type": "module",
@@ -27,15 +27,15 @@
27
27
  "lru-cache": "^10.2.2",
28
28
  "ts-codec": "^1.3.0",
29
29
  "uuid": "^11.1.0",
30
- "@powersync/lib-service-mongodb": "0.0.0-dev-20250820110726",
31
- "@powersync/lib-services-framework": "0.0.0-dev-20250820110726",
32
- "@powersync/service-core": "0.0.0-dev-20250820110726",
33
- "@powersync/service-types": "0.0.0-dev-20250820110726",
34
- "@powersync/service-jsonbig": "0.0.0-dev-20250820110726",
35
- "@powersync/service-sync-rules": "0.0.0-dev-20250820110726"
30
+ "@powersync/lib-service-mongodb": "0.0.0-dev-20250827072023",
31
+ "@powersync/lib-services-framework": "0.0.0-dev-20250827072023",
32
+ "@powersync/service-core": "0.0.0-dev-20250827072023",
33
+ "@powersync/service-types": "0.0.0-dev-20250827072023",
34
+ "@powersync/service-jsonbig": "0.0.0-dev-20250827072023",
35
+ "@powersync/service-sync-rules": "0.0.0-dev-20250827072023"
36
36
  },
37
37
  "devDependencies": {
38
- "@powersync/service-core-tests": "0.0.0-dev-20250820110726"
38
+ "@powersync/service-core-tests": "0.0.0-dev-20250827072023"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "tsc -b",
package/src/index.ts CHANGED
@@ -5,3 +5,4 @@ export * as storage from './storage/storage-index.js';
5
5
 
6
6
  export * from './types/types.js';
7
7
  export * as types from './types/types.js';
8
+ export * as utils from './utils/utils-index.js';
@@ -51,18 +51,6 @@ export const down: migrations.PowerSyncMigrationFunction = async (context) => {
51
51
  const db = storage.createPowerSyncMongo(configuration.storage as MongoStorageConfig);
52
52
 
53
53
  try {
54
- if (await db.connection_report_events.indexExists('connection_list_index')) {
55
- await db.connection_report_events.dropIndex('connection_list_index');
56
- }
57
- if (await db.connection_report_events.indexExists('connection_user_id_index')) {
58
- await db.connection_report_events.dropIndex('connection_user_id_index');
59
- }
60
- if (await db.connection_report_events.indexExists('connection_client_id_index')) {
61
- await db.connection_report_events.dropIndex('connection_client_id_index');
62
- }
63
- if (await db.connection_report_events.indexExists('connection_index')) {
64
- await db.connection_report_events.dropIndex('connection_index');
65
- }
66
54
  await db.db.dropCollection('connection_report_events');
67
55
  } finally {
68
56
  await db.client.close();
@@ -12,7 +12,7 @@ import { PowerSyncMongo } from './implementation/db.js';
12
12
  import { SyncRuleDocument } from './implementation/models.js';
13
13
  import { MongoPersistedSyncRulesContent } from './implementation/MongoPersistedSyncRulesContent.js';
14
14
  import { MongoSyncBucketStorage } from './implementation/MongoSyncBucketStorage.js';
15
- import { generateSlotName } from './implementation/util.js';
15
+ import { generateSlotName } from '../utils/util.js';
16
16
 
17
17
  export class MongoBucketStorage
18
18
  extends BaseObserver<storage.BucketStorageFactoryListener>
@@ -30,10 +30,10 @@ export class MongoReportStorage implements storage.ReportStorage {
30
30
 
31
31
  async getClientConnectionReports(
32
32
  data: event_types.ClientConnectionReportRequest
33
- ): Promise<event_types.ClientConnectionReport> {
33
+ ): Promise<event_types.ClientConnectionReportResponse> {
34
34
  const { start, end } = data;
35
35
  const result = await this.db.connection_report_events
36
- .aggregate<event_types.ClientConnectionReport>([
36
+ .aggregate<event_types.ClientConnectionReportResponse>([
37
37
  {
38
38
  $match: {
39
39
  connected_at: { $lte: end, $gte: start }
@@ -79,15 +79,13 @@ export class MongoReportStorage implements storage.ReportStorage {
79
79
  }
80
80
  );
81
81
  }
82
- async getConnectedClients(data: event_types.ClientConnectionsRequest): Promise<event_types.ClientConnectionReport> {
83
- const timeframeFilter = this.listConnectionsDateRange(data);
82
+ async getConnectedClients(): Promise<event_types.ClientConnectionReportResponse> {
84
83
  const result = await this.db.connection_report_events
85
- .aggregate<event_types.ClientConnectionReport>([
84
+ .aggregate<event_types.ClientConnectionReportResponse>([
86
85
  {
87
86
  $match: {
88
87
  disconnected_at: { $exists: false },
89
- jwt_exp: { $gt: new Date() },
90
- ...timeframeFilter
88
+ jwt_exp: { $gt: new Date() }
91
89
  }
92
90
  },
93
91
  this.connectionsFacetPipeline(),
@@ -102,10 +100,10 @@ export class MongoReportStorage implements storage.ReportStorage {
102
100
  }
103
101
 
104
102
  private parseJsDate(date: Date) {
105
- const year = date.getFullYear();
106
- const month = date.getMonth();
107
- const today = date.getDate();
108
- const day = date.getDay();
103
+ const year = date.getUTCFullYear();
104
+ const month = date.getUTCMonth();
105
+ const today = date.getUTCDate();
106
+ const day = date.getUTCDay();
109
107
  return {
110
108
  year,
111
109
  month,
@@ -171,24 +169,8 @@ export class MongoReportStorage implements storage.ReportStorage {
171
169
  user_id: userId,
172
170
  client_id: clientId,
173
171
  connected_at: {
174
- // Need to create a new date here to sett the time to 00:00:00
175
- $gte: new Date(year, month, today),
176
- $lt: new Date(year, month, nextDay)
177
- }
178
- };
179
- }
180
-
181
- private listConnectionsDateRange(data: event_types.ClientConnectionsRequest) {
182
- const { range } = data;
183
- if (!range) {
184
- return undefined;
185
- }
186
- const endDate = data.range?.end ? new Date(data.range.end) : new Date();
187
- const startDate = new Date(range.start);
188
- return {
189
- connected_at: {
190
- $lte: endDate,
191
- $gte: startDate
172
+ $gte: new Date(Date.UTC(year, month, today)),
173
+ $lt: new Date(Date.UTC(year, month, nextDay))
192
174
  }
193
175
  };
194
176
  }
@@ -28,7 +28,7 @@ import { MongoIdSequence } from './MongoIdSequence.js';
28
28
  import { batchCreateCustomWriteCheckpoints } from './MongoWriteCheckpointAPI.js';
29
29
  import { cacheKey, OperationBatch, RecordOperation } from './OperationBatch.js';
30
30
  import { PersistedBatch } from './PersistedBatch.js';
31
- import { idPrefixFilter } from './util.js';
31
+ import { idPrefixFilter } from '../../utils/util.js';
32
32
 
33
33
  /**
34
34
  * 15MB
@@ -32,7 +32,7 @@ import { BucketDataDocument, BucketDataKey, BucketStateDocument, SourceKey, Sour
32
32
  import { MongoBucketBatch } from './MongoBucketBatch.js';
33
33
  import { MongoCompactor } from './MongoCompactor.js';
34
34
  import { MongoWriteCheckpointAPI } from './MongoWriteCheckpointAPI.js';
35
- import { idPrefixFilter, mapOpEntry, readSingleBatch, setSessionSnapshotTime } from './util.js';
35
+ import { idPrefixFilter, mapOpEntry, readSingleBatch, setSessionSnapshotTime } from '../../utils/util.js';
36
36
  import { MongoParameterCompactor } from './MongoParameterCompactor.js';
37
37
 
38
38
  export class MongoSyncBucketStorage
@@ -16,7 +16,7 @@ import {
16
16
  CurrentDataDocument,
17
17
  SourceKey
18
18
  } from './models.js';
19
- import { replicaIdToSubkey } from './util.js';
19
+ import { replicaIdToSubkey } from '../../utils/util.js';
20
20
 
21
21
  /**
22
22
  * Maximum size of operations we write in a single transaction.
@@ -7,9 +7,9 @@ export * from './implementation/MongoPersistedSyncRulesContent.js';
7
7
  export * from './implementation/MongoStorageProvider.js';
8
8
  export * from './implementation/MongoSyncBucketStorage.js';
9
9
  export * from './implementation/MongoSyncRulesLock.js';
10
- export * from './implementation/MongoTestStorageFactoryGenerator.js';
11
10
  export * from './implementation/OperationBatch.js';
12
11
  export * from './implementation/PersistedBatch.js';
13
- export * from './implementation/util.js';
12
+ export * from '../utils/util.js';
14
13
  export * from './MongoBucketStorage.js';
15
14
  export * from './MongoReportStorage.js';
15
+ export * as test_utils from '../utils/test-utils.js';
@@ -0,0 +1,55 @@
1
+ import { mongo } from '@powersync/lib-service-mongodb';
2
+ import { PowerSyncMongo } from '../storage/implementation/db.js';
3
+ import { TestStorageOptions } from '@powersync/service-core';
4
+ import { MongoReportStorage } from '../storage/MongoReportStorage.js';
5
+ import { MongoBucketStorage } from '../storage/MongoBucketStorage.js';
6
+
7
+ export type MongoTestStorageOptions = {
8
+ url: string;
9
+ isCI: boolean;
10
+ };
11
+
12
+ export function mongoTestStorageFactoryGenerator(factoryOptions: MongoTestStorageOptions) {
13
+ return async (options?: TestStorageOptions) => {
14
+ const db = connectMongoForTests(factoryOptions.url, factoryOptions.isCI);
15
+
16
+ // None of the tests insert data into this collection, so it was never created
17
+ if (!(await db.db.listCollections({ name: db.bucket_parameters.collectionName }).hasNext())) {
18
+ await db.db.createCollection('bucket_parameters');
19
+ }
20
+
21
+ // Full migrations are not currently run for tests, so we manually create this
22
+ await db.createCheckpointEventsCollection();
23
+
24
+ if (!options?.doNotClear) {
25
+ await db.clear();
26
+ }
27
+
28
+ return new MongoBucketStorage(db, { slot_name_prefix: 'test_' });
29
+ };
30
+ }
31
+
32
+ export function mongoTestReportStorageFactoryGenerator(factoryOptions: MongoTestStorageOptions) {
33
+ return async (options?: TestStorageOptions) => {
34
+ const db = connectMongoForTests(factoryOptions.url, factoryOptions.isCI);
35
+
36
+ await db.createConnectionReportingCollection();
37
+
38
+ if (!options?.doNotClear) {
39
+ await db.clear();
40
+ }
41
+
42
+ return new MongoReportStorage(db);
43
+ };
44
+ }
45
+
46
+ export const connectMongoForTests = (url: string, isCI: boolean) => {
47
+ // Short timeout for tests, to fail fast when the server is not available.
48
+ // Slightly longer timeouts for CI, to avoid arbitrary test failures
49
+ const client = new mongo.MongoClient(url, {
50
+ connectTimeoutMS: isCI ? 15_000 : 5_000,
51
+ socketTimeoutMS: isCI ? 15_000 : 5_000,
52
+ serverSelectionTimeoutMS: isCI ? 15_000 : 2_500
53
+ });
54
+ return new PowerSyncMongo(client);
55
+ };
@@ -3,9 +3,7 @@ import * as crypto from 'crypto';
3
3
  import * as uuid from 'uuid';
4
4
  import { mongo } from '@powersync/lib-service-mongodb';
5
5
  import { storage, utils } from '@powersync/service-core';
6
-
7
- import { PowerSyncMongo } from './db.js';
8
- import { BucketDataDocument } from './models.js';
6
+ import { BucketDataDocument } from '../storage/implementation/models.js';
9
7
  import { ServiceAssertionError } from '@powersync/lib-services-framework';
10
8
 
11
9
  export function idPrefixFilter<T>(prefix: Partial<T>, rest: (keyof T)[]): mongo.Condition<T> {
@@ -104,20 +102,6 @@ export function replicaIdToSubkey(table: bson.ObjectId, id: storage.ReplicaId):
104
102
  }
105
103
  }
106
104
 
107
- /**
108
- * Helper for unit tests
109
- */
110
- export const connectMongoForTests = (url: string, isCI: boolean) => {
111
- // Short timeout for tests, to fail fast when the server is not available.
112
- // Slightly longer timeouts for CI, to avoid arbitrary test failures
113
- const client = new mongo.MongoClient(url, {
114
- connectTimeoutMS: isCI ? 15_000 : 5_000,
115
- socketTimeoutMS: isCI ? 15_000 : 5_000,
116
- serverSelectionTimeoutMS: isCI ? 15_000 : 2_500
117
- });
118
- return new PowerSyncMongo(client);
119
- };
120
-
121
105
  export function setSessionSnapshotTime(session: mongo.ClientSession, time: bson.Timestamp) {
122
106
  // This is a workaround for the lack of direct support for snapshot reads in the MongoDB driver.
123
107
  if (!session.snapshotEnabled) {
@@ -0,0 +1,2 @@
1
+ export * as test_utils from './test-utils.js';
2
+ export * from './util.js';
@@ -1,6 +1,6 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`SDK reporting storage > Should create a connection report if its after a day 1`] = `
3
+ exports[`Connection reporting storage > Should create a connection report if its after a day 1`] = `
4
4
  [
5
5
  {
6
6
  "client_id": "client_week",
@@ -17,7 +17,7 @@ exports[`SDK reporting storage > Should create a connection report if its after
17
17
  ]
18
18
  `;
19
19
 
20
- exports[`SDK reporting storage > Should delete rows older than specified range 1`] = `
20
+ exports[`Connection reporting storage > Should delete rows older than specified range 1`] = `
21
21
  {
22
22
  "sdks": [
23
23
  {
@@ -45,38 +45,39 @@ exports[`SDK reporting storage > Should delete rows older than specified range 1
45
45
  "sdk": "powersync-js/1.24.5",
46
46
  "users": 1,
47
47
  },
48
- ],
49
- "users": 5,
50
- }
51
- `;
52
-
53
- exports[`SDK reporting storage > Should show connected users with start range 1`] = `
54
- {
55
- "sdks": [
56
48
  {
57
49
  "clients": 1,
58
- "sdk": "powersync-dart/1.6.4",
50
+ "sdk": "unknown",
59
51
  "users": 1,
60
52
  },
61
53
  ],
62
- "users": 1,
54
+ "users": 5,
63
55
  }
64
56
  `;
65
57
 
66
- exports[`SDK reporting storage > Should show connected users with start range and end range 1`] = `
67
- {
68
- "sdks": [
69
- {
70
- "clients": 1,
71
- "sdk": "powersync-js/1.21.1",
72
- "users": 1,
73
- },
74
- ],
75
- "users": 1,
76
- }
58
+ exports[`Connection reporting storage > Should update a connected connection report and make it disconnected 1`] = `
59
+ [
60
+ {
61
+ "client_id": "client_three",
62
+ "sdk": "powersync-js/1.21.2",
63
+ "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
64
+ "user_id": "user_three",
65
+ },
66
+ ]
77
67
  `;
78
68
 
79
- exports[`SDK reporting storage > Should show connection report data for user over the past day 1`] = `
69
+ exports[`Connection reporting storage > Should update a connection report if its within a day 1`] = `
70
+ [
71
+ {
72
+ "client_id": "client_one",
73
+ "sdk": "powersync-dart/1.6.4",
74
+ "user_agent": "powersync-dart/1.6.4 Dart (flutter-web) Chrome/128 android",
75
+ "user_id": "user_one",
76
+ },
77
+ ]
78
+ `;
79
+
80
+ exports[`Report storage tests > Should show connection report data for user over the past day 1`] = `
80
81
  {
81
82
  "sdks": [
82
83
  {
@@ -94,12 +95,17 @@ exports[`SDK reporting storage > Should show connection report data for user ove
94
95
  "sdk": "powersync-js/1.21.4",
95
96
  "users": 1,
96
97
  },
98
+ {
99
+ "clients": 1,
100
+ "sdk": "unknown",
101
+ "users": 1,
102
+ },
97
103
  ],
98
104
  "users": 3,
99
105
  }
100
106
  `;
101
107
 
102
- exports[`SDK reporting storage > Should show connection report data for user over the past month 1`] = `
108
+ exports[`Report storage tests > Should show connection report data for user over the past month 1`] = `
103
109
  {
104
110
  "sdks": [
105
111
  {
@@ -137,12 +143,17 @@ exports[`SDK reporting storage > Should show connection report data for user ove
137
143
  "sdk": "powersync-js/1.24.5",
138
144
  "users": 1,
139
145
  },
146
+ {
147
+ "clients": 1,
148
+ "sdk": "unknown",
149
+ "users": 1,
150
+ },
140
151
  ],
141
152
  "users": 7,
142
153
  }
143
154
  `;
144
155
 
145
- exports[`SDK reporting storage > Should show connection report data for user over the past week 1`] = `
156
+ exports[`Report storage tests > Should show connection report data for user over the past week 1`] = `
146
157
  {
147
158
  "sdks": [
148
159
  {
@@ -170,29 +181,35 @@ exports[`SDK reporting storage > Should show connection report data for user ove
170
181
  "sdk": "powersync-js/1.24.5",
171
182
  "users": 1,
172
183
  },
184
+ {
185
+ "clients": 1,
186
+ "sdk": "unknown",
187
+ "users": 1,
188
+ },
173
189
  ],
174
190
  "users": 5,
175
191
  }
176
192
  `;
177
193
 
178
- exports[`SDK reporting storage > Should update a connected connection report and make it disconnected 1`] = `
179
- [
180
- {
181
- "client_id": "client_three",
182
- "sdk": "powersync-js/1.21.2",
183
- "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
184
- "user_id": "user_three",
185
- },
186
- ]
187
- `;
188
-
189
- exports[`SDK reporting storage > Should update a connection report if its within a day 1`] = `
190
- [
191
- {
192
- "client_id": "client_one",
193
- "sdk": "powersync-dart/1.6.4",
194
- "user_agent": "powersync-dart/1.6.4 Dart (flutter-web) Chrome/128 android",
195
- "user_id": "user_one",
196
- },
197
- ]
194
+ exports[`Report storage tests > Should show currently connected users 1`] = `
195
+ {
196
+ "sdks": [
197
+ {
198
+ "clients": 1,
199
+ "sdk": "powersync-dart/1.6.4",
200
+ "users": 1,
201
+ },
202
+ {
203
+ "clients": 1,
204
+ "sdk": "powersync-js/1.21.1",
205
+ "users": 1,
206
+ },
207
+ {
208
+ "clients": 1,
209
+ "sdk": "unknown",
210
+ "users": 1,
211
+ },
212
+ ],
213
+ "users": 2,
214
+ }
198
215
  `;