@powersync/service-module-postgres-storage 0.10.11 → 0.10.13

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.
@@ -14,10 +14,12 @@ export declare class PostgresReportStorage implements storage.ReportStorage {
14
14
  private mapListCurrentConnectionsResponse;
15
15
  private listConnectionsQuery;
16
16
  private updateTableFilter;
17
+ private clientsConnectionPagination;
17
18
  reportClientConnection(data: event_types.ClientConnectionBucketData): Promise<void>;
18
19
  reportClientDisconnection(data: event_types.ClientDisconnectionEventData): Promise<void>;
19
20
  getConnectedClients(): Promise<event_types.ClientConnectionReportResponse>;
20
21
  getClientConnectionReports(data: event_types.ClientConnectionReportRequest): Promise<event_types.ClientConnectionReportResponse>;
22
+ getGeneralClientConnectionAnalytics(data: event_types.ClientConnectionAnalyticsRequest): Promise<event_types.PaginatedResponse<event_types.ClientConnection>>;
21
23
  deleteOldConnectionData(data: event_types.DeleteOldConnectionData): Promise<void>;
22
24
  [Symbol.asyncDispose](): Promise<void>;
23
25
  prepareStatements(connection: pg_wire.PgConnection): Promise<void>;
@@ -20,10 +20,10 @@ export class PostgresReportStorage {
20
20
  });
21
21
  }
22
22
  parseJsDate(date) {
23
- const year = date.getFullYear();
24
- const month = date.getMonth();
25
- const today = date.getDate();
26
- const day = date.getDay();
23
+ const year = date.getUTCFullYear();
24
+ const month = date.getUTCMonth();
25
+ const today = date.getUTCDate();
26
+ const day = date.getUTCDay();
27
27
  return {
28
28
  year,
29
29
  month,
@@ -93,8 +93,63 @@ export class PostgresReportStorage {
93
93
  const { year, month, today } = this.parseJsDate(new Date());
94
94
  const nextDay = today + 1;
95
95
  return {
96
- gte: new Date(year, month, today).toISOString(),
97
- lt: new Date(year, month, nextDay).toISOString()
96
+ gte: new Date(Date.UTC(year, month, today)).toISOString(),
97
+ lt: new Date(Date.UTC(year, month, nextDay)).toISOString()
98
+ };
99
+ }
100
+ clientsConnectionPagination(params) {
101
+ const { cursor, limit, client_id, user_id, date_range } = params;
102
+ const queryLimit = limit || 100;
103
+ const queryParams = [];
104
+ let countQuery = `SELECT COUNT(*) AS total FROM connection_report_events`;
105
+ let query = `SELECT id, user_id, client_id, user_agent, sdk, jwt_exp::text AS jwt_exp, disconnected_at, connected_at::text AS connected_at, disconnected_at::text AS disconnected_at FROM connection_report_events`;
106
+ let intermediateQuery = '';
107
+ /** Create a user_id/ client_id filter is they exist */
108
+ if (client_id != null || user_id) {
109
+ if (client_id && !user_id) {
110
+ intermediateQuery += ` WHERE client_id = $1`;
111
+ queryParams.push({ type: 'varchar', value: client_id });
112
+ }
113
+ else if (!client_id && user_id != null) {
114
+ intermediateQuery += ` WHERE user_id = $1`;
115
+ queryParams.push({ type: 'varchar', value: user_id });
116
+ }
117
+ else {
118
+ intermediateQuery += ' WHERE client_id = $1 AND user_id = $2';
119
+ queryParams.push({ type: 'varchar', value: client_id });
120
+ queryParams.push({ type: 'varchar', value: user_id });
121
+ }
122
+ }
123
+ /** Create a date range filter if it exists */
124
+ if (date_range) {
125
+ const { start, end } = date_range;
126
+ intermediateQuery +=
127
+ queryParams.length === 0
128
+ ? ` WHERE connected_at >= $1 AND connected_at <= $2`
129
+ : ` AND connected_at >= $${queryParams.length + 1} AND connected_at <= $${queryParams.length + 2}`;
130
+ queryParams.push({ type: 1184, value: start.toISOString() });
131
+ queryParams.push({ type: 1184, value: end.toISOString() });
132
+ }
133
+ countQuery += intermediateQuery;
134
+ /** Create a cursor filter if it exists. The cursor in postgres is the last item connection date, the id is an uuid so we cant use the same logic as in MongoReportStorage.ts */
135
+ if (cursor) {
136
+ intermediateQuery +=
137
+ queryParams.length === 0 ? ` WHERE connected_at < $1` : ` AND connected_at < $${queryParams.length + 1}`;
138
+ queryParams.push({ type: 1184, value: new Date(cursor).toISOString() });
139
+ }
140
+ /** Order in descending connected at range to match Mongo sort=-1*/
141
+ intermediateQuery += ` ORDER BY connected_at DESC`;
142
+ query += intermediateQuery;
143
+ return {
144
+ mainQuery: {
145
+ statement: query,
146
+ params: queryParams,
147
+ limit: queryLimit
148
+ },
149
+ countQuery: {
150
+ statement: countQuery,
151
+ params: queryParams
152
+ }
98
153
  };
99
154
  }
100
155
  async reportClientConnection(data) {
@@ -208,6 +263,29 @@ export class PostgresReportStorage {
208
263
  .first();
209
264
  return this.mapListCurrentConnectionsResponse(result);
210
265
  }
266
+ async getGeneralClientConnectionAnalytics(data) {
267
+ const limit = data.limit || 100;
268
+ const statement = this.clientsConnectionPagination(data);
269
+ const result = await this.db.queryRows(statement.mainQuery);
270
+ const items = result.map((item) => ({
271
+ ...item,
272
+ /** JS Date conversion to match document schema used for Mongo storage */
273
+ connected_at: new Date(item.connected_at),
274
+ disconnected_at: item.disconnected_at ? new Date(item.disconnected_at) : undefined,
275
+ jwt_exp: item.jwt_exp ? new Date(item.jwt_exp) : undefined
276
+ }));
277
+ const count = items.length;
278
+ /** The returned total has been defaulted to 0 due to the overhead using documentCount from the mogo driver this is just to keep consistency with Mongo implementation.
279
+ * cursor.count has been deprecated.
280
+ * */
281
+ return {
282
+ items,
283
+ /** Setting the cursor to the connected at date of the last item in the list */
284
+ cursor: count === limit ? items[items.length - 1].connected_at.toISOString() : undefined,
285
+ count,
286
+ more: !(count !== limit)
287
+ };
288
+ }
211
289
  async deleteOldConnectionData(data) {
212
290
  const { date } = data;
213
291
  const result = await this.db.sql `
@@ -1 +1 @@
1
- {"version":3,"file":"PostgresReportStorage.js","sourceRoot":"","sources":["../../src/storage/PostgresReportStorage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PostgresReportStorage.js","sourceRoot":"","sources":["../../src/storage/PostgresReportStorage.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@powersync/service-module-postgres-storage",
3
3
  "repository": "https://github.com/powersync-ja/powersync-service",
4
4
  "types": "dist/@types/index.d.ts",
5
- "version": "0.10.11",
5
+ "version": "0.10.13",
6
6
  "main": "dist/index.js",
7
7
  "license": "FSL-1.1-ALv2",
8
8
  "type": "module",
@@ -11,16 +11,16 @@
11
11
  },
12
12
  "exports": {
13
13
  ".": {
14
+ "types": "./dist/@types/index.d.ts",
14
15
  "import": "./dist/index.js",
15
16
  "require": "./dist/index.js",
16
- "default": "./dist/index.js",
17
- "types": "./dist/@types/index.d.ts"
17
+ "default": "./dist/index.js"
18
18
  },
19
19
  "./types": {
20
+ "types": "./dist/@types/index.d.ts",
20
21
  "import": "./dist/types/types.js",
21
22
  "require": "./dist/types/types.js",
22
- "default": "./dist/types/types.js",
23
- "types": "./dist/@types/index.d.ts"
23
+ "default": "./dist/types/types.js"
24
24
  }
25
25
  },
26
26
  "dependencies": {
@@ -29,17 +29,17 @@
29
29
  "p-defer": "^4.0.1",
30
30
  "ts-codec": "^1.3.0",
31
31
  "uuid": "^11.1.0",
32
- "@powersync/lib-service-postgres": "0.4.13",
33
- "@powersync/lib-services-framework": "0.7.9",
34
- "@powersync/service-core": "1.16.2",
35
- "@powersync/service-types": "0.13.1",
36
- "@powersync/service-jpgwire": "0.21.5",
32
+ "@powersync/lib-service-postgres": "0.4.15",
33
+ "@powersync/lib-services-framework": "0.7.11",
34
+ "@powersync/service-core": "1.17.0",
35
+ "@powersync/service-types": "0.13.2",
36
+ "@powersync/service-jpgwire": "0.21.7",
37
37
  "@powersync/service-jsonbig": "0.17.12",
38
- "@powersync/service-sync-rules": "0.29.6"
38
+ "@powersync/service-sync-rules": "0.29.8"
39
39
  },
40
40
  "devDependencies": {
41
41
  "typescript": "^5.7.3",
42
- "@powersync/service-core-tests": "0.12.11"
42
+ "@powersync/service-core-tests": "0.12.13"
43
43
  },
44
44
  "scripts": {
45
45
  "build": "tsc -b",
@@ -9,6 +9,7 @@ import { toInteger } from 'ix/util/tointeger.js';
9
9
  import { logger } from '@powersync/lib-services-framework';
10
10
  import { getStorageApplicationName } from '../utils/application-name.js';
11
11
  import { STORAGE_SCHEMA_NAME } from '../utils/db.js';
12
+ import { ClientConnectionResponse } from '@powersync/service-types/dist/reports.js';
12
13
 
13
14
  export type PostgresReportStorageOptions = {
14
15
  config: NormalizedPostgresStorageConfig;
@@ -29,10 +30,10 @@ export class PostgresReportStorage implements storage.ReportStorage {
29
30
  }
30
31
 
31
32
  private parseJsDate(date: Date) {
32
- const year = date.getFullYear();
33
- const month = date.getMonth();
34
- const today = date.getDate();
35
- const day = date.getDay();
33
+ const year = date.getUTCFullYear();
34
+ const month = date.getUTCMonth();
35
+ const today = date.getUTCDate();
36
+ const day = date.getUTCDay();
36
37
  return {
37
38
  year,
38
39
  month,
@@ -106,8 +107,70 @@ export class PostgresReportStorage implements storage.ReportStorage {
106
107
  const { year, month, today } = this.parseJsDate(new Date());
107
108
  const nextDay = today + 1;
108
109
  return {
109
- gte: new Date(year, month, today).toISOString(),
110
- lt: new Date(year, month, nextDay).toISOString()
110
+ gte: new Date(Date.UTC(year, month, today)).toISOString(),
111
+ lt: new Date(Date.UTC(year, month, nextDay)).toISOString()
112
+ };
113
+ }
114
+
115
+ private clientsConnectionPagination(params: event_types.ClientConnectionAnalyticsRequest): {
116
+ mainQuery: pg_wire.Statement;
117
+ countQuery: pg_wire.Statement;
118
+ } {
119
+ const { cursor, limit, client_id, user_id, date_range } = params;
120
+ const queryLimit = limit || 100;
121
+ const queryParams: pg_wire.StatementParam[] = [];
122
+ let countQuery = `SELECT COUNT(*) AS total FROM connection_report_events`;
123
+ let query = `SELECT id, user_id, client_id, user_agent, sdk, jwt_exp::text AS jwt_exp, disconnected_at, connected_at::text AS connected_at, disconnected_at::text AS disconnected_at FROM connection_report_events`;
124
+ let intermediateQuery = '';
125
+ /** Create a user_id/ client_id filter is they exist */
126
+ if (client_id != null || user_id) {
127
+ if (client_id && !user_id) {
128
+ intermediateQuery += ` WHERE client_id = $1`;
129
+ queryParams.push({ type: 'varchar', value: client_id });
130
+ } else if (!client_id && user_id != null) {
131
+ intermediateQuery += ` WHERE user_id = $1`;
132
+ queryParams.push({ type: 'varchar', value: user_id });
133
+ } else {
134
+ intermediateQuery += ' WHERE client_id = $1 AND user_id = $2';
135
+ queryParams.push({ type: 'varchar', value: client_id! });
136
+ queryParams.push({ type: 'varchar', value: user_id! });
137
+ }
138
+ }
139
+
140
+ /** Create a date range filter if it exists */
141
+ if (date_range) {
142
+ const { start, end } = date_range;
143
+ intermediateQuery +=
144
+ queryParams.length === 0
145
+ ? ` WHERE connected_at >= $1 AND connected_at <= $2`
146
+ : ` AND connected_at >= $${queryParams.length + 1} AND connected_at <= $${queryParams.length + 2}`;
147
+ queryParams.push({ type: 1184, value: start.toISOString() });
148
+ queryParams.push({ type: 1184, value: end.toISOString() });
149
+ }
150
+
151
+ countQuery += intermediateQuery;
152
+
153
+ /** Create a cursor filter if it exists. The cursor in postgres is the last item connection date, the id is an uuid so we cant use the same logic as in MongoReportStorage.ts */
154
+ if (cursor) {
155
+ intermediateQuery +=
156
+ queryParams.length === 0 ? ` WHERE connected_at < $1` : ` AND connected_at < $${queryParams.length + 1}`;
157
+ queryParams.push({ type: 1184, value: new Date(cursor).toISOString() });
158
+ }
159
+
160
+ /** Order in descending connected at range to match Mongo sort=-1*/
161
+ intermediateQuery += ` ORDER BY connected_at DESC`;
162
+ query += intermediateQuery;
163
+
164
+ return {
165
+ mainQuery: {
166
+ statement: query,
167
+ params: queryParams,
168
+ limit: queryLimit
169
+ },
170
+ countQuery: {
171
+ statement: countQuery,
172
+ params: queryParams
173
+ }
111
174
  };
112
175
  }
113
176
 
@@ -225,6 +288,34 @@ export class PostgresReportStorage implements storage.ReportStorage {
225
288
  .first();
226
289
  return this.mapListCurrentConnectionsResponse(result);
227
290
  }
291
+
292
+ async getGeneralClientConnectionAnalytics(
293
+ data: event_types.ClientConnectionAnalyticsRequest
294
+ ): Promise<event_types.PaginatedResponse<event_types.ClientConnection>> {
295
+ const limit = data.limit || 100;
296
+ const statement = this.clientsConnectionPagination(data);
297
+
298
+ const result = await this.db.queryRows<ClientConnectionResponse>(statement.mainQuery);
299
+ const items = result.map((item) => ({
300
+ ...item,
301
+ /** JS Date conversion to match document schema used for Mongo storage */
302
+ connected_at: new Date(item.connected_at),
303
+ disconnected_at: item.disconnected_at ? new Date(item.disconnected_at) : undefined,
304
+ jwt_exp: item.jwt_exp ? new Date(item.jwt_exp) : undefined
305
+ }));
306
+ const count = items.length;
307
+ /** The returned total has been defaulted to 0 due to the overhead using documentCount from the mogo driver this is just to keep consistency with Mongo implementation.
308
+ * cursor.count has been deprecated.
309
+ * */
310
+ return {
311
+ items,
312
+ /** Setting the cursor to the connected at date of the last item in the list */
313
+ cursor: count === limit ? items[items.length - 1].connected_at.toISOString() : undefined,
314
+ count,
315
+ more: !(count !== limit)
316
+ };
317
+ }
318
+
228
319
  async deleteOldConnectionData(data: event_types.DeleteOldConnectionData): Promise<void> {
229
320
  const { date } = data;
230
321
  const result = await this.db.sql`
@@ -3,13 +3,13 @@
3
3
  exports[`Connection report storage > Should create a connection event if its after a day 1`] = `
4
4
  [
5
5
  {
6
- "client_id": "client_week",
6
+ "client_id": "client_one",
7
7
  "sdk": "powersync-js/1.24.5",
8
8
  "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
9
9
  "user_id": "user_week",
10
10
  },
11
11
  {
12
- "client_id": "client_week",
12
+ "client_id": "client_one",
13
13
  "sdk": "powersync-js/1.24.5",
14
14
  "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
15
15
  "user_id": "user_week",
@@ -213,3 +213,265 @@ exports[`Report storage tests > Should show currently connected users 1`] = `
213
213
  "users": 2,
214
214
  }
215
215
  `;
216
+
217
+ exports[`Report storage tests > Should show paginated response of all connections of specified client_id 1`] = `
218
+ {
219
+ "count": 1,
220
+ "cursor": undefined,
221
+ "items": [
222
+ {
223
+ "client_id": "client_two",
224
+ "id": "2",
225
+ "sdk": "powersync-js/1.21.1",
226
+ "user_agent": "powersync-js/1.21.0 powersync-web Chromium/138 linux",
227
+ "user_id": "user_two",
228
+ },
229
+ ],
230
+ "more": false,
231
+ }
232
+ `;
233
+
234
+ exports[`Report storage tests > Should show paginated response of all connections with a limit 1`] = `
235
+ {
236
+ "count": 4,
237
+ "cursor": "<removed-for-snapshot>",
238
+ "items": [
239
+ {
240
+ "client_id": "client_one",
241
+ "id": "1",
242
+ "sdk": "powersync-dart/1.6.4",
243
+ "user_agent": "powersync-dart/1.6.4 Dart (flutter-web) Chrome/128 android",
244
+ "user_id": "user_one",
245
+ },
246
+ {
247
+ "client_id": "client_four",
248
+ "id": "4",
249
+ "sdk": "powersync-js/1.21.4",
250
+ "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
251
+ "user_id": "user_four",
252
+ },
253
+ {
254
+ "client_id": "client_two",
255
+ "id": "2",
256
+ "sdk": "powersync-js/1.21.1",
257
+ "user_agent": "powersync-js/1.21.0 powersync-web Chromium/138 linux",
258
+ "user_id": "user_two",
259
+ },
260
+ {
261
+ "client_id": "",
262
+ "id": "5",
263
+ "sdk": "unknown",
264
+ "user_agent": "Dart (flutter-web) Chrome/128 android",
265
+ "user_id": "user_one",
266
+ },
267
+ ],
268
+ "more": true,
269
+ }
270
+ `;
271
+
272
+ exports[`Report storage tests > Should show paginated response of all connections with a limit 2`] = `
273
+ {
274
+ "count": 4,
275
+ "cursor": undefined,
276
+ "items": [
277
+ {
278
+ "client_id": "client_three",
279
+ "id": "3",
280
+ "sdk": "powersync-js/1.21.2",
281
+ "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
282
+ "user_id": "user_three",
283
+ },
284
+ {
285
+ "client_id": "client_one",
286
+ "id": "week",
287
+ "sdk": "powersync-js/1.24.5",
288
+ "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
289
+ "user_id": "user_week",
290
+ },
291
+ {
292
+ "client_id": "client_month",
293
+ "id": "month",
294
+ "sdk": "powersync-js/1.23.6",
295
+ "user_agent": "powersync-js/1.23.0 powersync-web Firefox/141 linux",
296
+ "user_id": "user_month",
297
+ },
298
+ {
299
+ "client_id": "client_expired",
300
+ "id": "expired",
301
+ "sdk": "powersync-js/1.23.7",
302
+ "user_agent": "powersync-js/1.23.0 powersync-web Firefox/141 linux",
303
+ "user_id": "user_expired",
304
+ },
305
+ ],
306
+ "more": false,
307
+ }
308
+ `;
309
+
310
+ exports[`Report storage tests > Should show paginated response of all connections with a limit with date range 1`] = `
311
+ {
312
+ "count": 4,
313
+ "cursor": "<removed-for-snapshot>",
314
+ "items": [
315
+ {
316
+ "client_id": "client_two",
317
+ "id": "2",
318
+ "sdk": "powersync-js/1.21.1",
319
+ "user_agent": "powersync-js/1.21.0 powersync-web Chromium/138 linux",
320
+ "user_id": "user_two",
321
+ },
322
+ {
323
+ "client_id": "",
324
+ "id": "5",
325
+ "sdk": "unknown",
326
+ "user_agent": "Dart (flutter-web) Chrome/128 android",
327
+ "user_id": "user_one",
328
+ },
329
+ {
330
+ "client_id": "client_three",
331
+ "id": "3",
332
+ "sdk": "powersync-js/1.21.2",
333
+ "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
334
+ "user_id": "user_three",
335
+ },
336
+ {
337
+ "client_id": "client_one",
338
+ "id": "week",
339
+ "sdk": "powersync-js/1.24.5",
340
+ "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
341
+ "user_id": "user_week",
342
+ },
343
+ ],
344
+ "more": true,
345
+ }
346
+ `;
347
+
348
+ exports[`Report storage tests > Should show paginated response of all connections with a limit with date range 2`] = `
349
+ {
350
+ "count": 2,
351
+ "cursor": undefined,
352
+ "items": [
353
+ {
354
+ "client_id": "client_two",
355
+ "id": "2",
356
+ "sdk": "powersync-js/1.21.1",
357
+ "user_agent": "powersync-js/1.21.0 powersync-web Chromium/138 linux",
358
+ "user_id": "user_two",
359
+ },
360
+ {
361
+ "client_id": "",
362
+ "id": "5",
363
+ "sdk": "unknown",
364
+ "user_agent": "Dart (flutter-web) Chrome/128 android",
365
+ "user_id": "user_one",
366
+ },
367
+ {
368
+ "client_id": "client_three",
369
+ "id": "3",
370
+ "sdk": "powersync-js/1.21.2",
371
+ "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
372
+ "user_id": "user_three",
373
+ },
374
+ {
375
+ "client_id": "client_one",
376
+ "id": "week",
377
+ "sdk": "powersync-js/1.24.5",
378
+ "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
379
+ "user_id": "user_week",
380
+ },
381
+ ],
382
+ "more": false,
383
+ }
384
+ `;
385
+
386
+ exports[`Report storage tests > Should show paginated response of connections of specified user_id 1`] = `
387
+ {
388
+ "count": 2,
389
+ "cursor": undefined,
390
+ "items": [
391
+ {
392
+ "client_id": "client_one",
393
+ "id": "1",
394
+ "sdk": "powersync-dart/1.6.4",
395
+ "user_agent": "powersync-dart/1.6.4 Dart (flutter-web) Chrome/128 android",
396
+ "user_id": "user_one",
397
+ },
398
+ {
399
+ "client_id": "",
400
+ "id": "5",
401
+ "sdk": "unknown",
402
+ "user_agent": "Dart (flutter-web) Chrome/128 android",
403
+ "user_id": "user_one",
404
+ },
405
+ ],
406
+ "more": false,
407
+ }
408
+ `;
409
+
410
+ exports[`Report storage tests > Should show paginated response of connections over a date range 1`] = `
411
+ {
412
+ "count": 6,
413
+ "cursor": undefined,
414
+ "items": [
415
+ {
416
+ "client_id": "client_one",
417
+ "id": "1",
418
+ "sdk": "powersync-dart/1.6.4",
419
+ "user_agent": "powersync-dart/1.6.4 Dart (flutter-web) Chrome/128 android",
420
+ "user_id": "user_one",
421
+ },
422
+ {
423
+ "client_id": "client_four",
424
+ "id": "4",
425
+ "sdk": "powersync-js/1.21.4",
426
+ "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
427
+ "user_id": "user_four",
428
+ },
429
+ {
430
+ "client_id": "client_two",
431
+ "id": "2",
432
+ "sdk": "powersync-js/1.21.1",
433
+ "user_agent": "powersync-js/1.21.0 powersync-web Chromium/138 linux",
434
+ "user_id": "user_two",
435
+ },
436
+ {
437
+ "client_id": "",
438
+ "id": "5",
439
+ "sdk": "unknown",
440
+ "user_agent": "Dart (flutter-web) Chrome/128 android",
441
+ "user_id": "user_one",
442
+ },
443
+ {
444
+ "client_id": "client_three",
445
+ "id": "3",
446
+ "sdk": "powersync-js/1.21.2",
447
+ "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
448
+ "user_id": "user_three",
449
+ },
450
+ {
451
+ "client_id": "client_one",
452
+ "id": "week",
453
+ "sdk": "powersync-js/1.24.5",
454
+ "user_agent": "powersync-js/1.21.0 powersync-web Firefox/141 linux",
455
+ "user_id": "user_week",
456
+ },
457
+ ],
458
+ "more": false,
459
+ }
460
+ `;
461
+
462
+ exports[`Report storage tests > Should show paginated response of connections over a date range of specified client_id and user_id 1`] = `
463
+ {
464
+ "count": 1,
465
+ "cursor": undefined,
466
+ "items": [
467
+ {
468
+ "client_id": "client_one",
469
+ "id": "1",
470
+ "sdk": "powersync-dart/1.6.4",
471
+ "user_agent": "powersync-dart/1.6.4 Dart (flutter-web) Chrome/128 android",
472
+ "user_id": "user_one",
473
+ },
474
+ ],
475
+ "more": false,
476
+ }
477
+ `;
@@ -185,7 +185,6 @@ describe('Connection report storage', async () => {
185
185
  const sdk = await factory.db
186
186
  .sql`SELECT * FROM connection_report_events WHERE user_id = ${{ type: 'varchar', value: userData.user_three.user_id }}`.rows<event_types.ClientConnection>();
187
187
  expect(sdk).toHaveLength(1);
188
- console.log(sdk[0]);
189
188
  expect(new Date((sdk[0].disconnected_at! as unknown as DateTimeValue).iso8601Representation).toISOString()).toEqual(
190
189
  disconnectAt.toISOString()
191
190
  );