@powersync/service-module-mongodb-storage 0.0.0-dev-20250722090128 → 0.0.0-dev-20250722122401

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.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @powersync/service-module-mongodb-storage
2
2
 
3
- ## 0.0.0-dev-20250722090128
3
+ ## 0.0.0-dev-20250722122401
4
4
 
5
5
  ### Patch Changes
6
6
 
@@ -10,10 +10,10 @@
10
10
  - Updated dependencies [4ebc3bf]
11
11
  - Updated dependencies [1aafdaf]
12
12
  - Updated dependencies [a700ec9]
13
- - @powersync/service-core@0.0.0-dev-20250722090128
14
- - @powersync/service-types@0.0.0-dev-20250722090128
15
- - @powersync/lib-services-framework@0.0.0-dev-20250722090128
16
- - @powersync/lib-service-mongodb@0.0.0-dev-20250722090128
13
+ - @powersync/service-core@0.0.0-dev-20250722122401
14
+ - @powersync/service-types@0.0.0-dev-20250722122401
15
+ - @powersync/lib-services-framework@0.0.0-dev-20250722122401
16
+ - @powersync/lib-service-mongodb@0.0.0-dev-20250722122401
17
17
 
18
18
  ## 0.10.4
19
19
 
@@ -1,15 +1,14 @@
1
1
  import { storage } from '@powersync/service-core';
2
2
  import { event_types } from '@powersync/service-types';
3
3
  import { PowerSyncMongo } from './implementation/db.js';
4
- import { ListCurrentConnectionsResponse, SdkConnectBucketData, SdkDisconnectEventData } from '@powersync/service-types/dist/events.js';
5
4
  export declare class MongoReportStorage implements storage.ReportStorageFactory {
6
5
  private readonly client;
7
6
  readonly db: PowerSyncMongo;
8
7
  constructor(db: PowerSyncMongo);
9
8
  deleteOldSdkData(data: event_types.DeleteOldSdkData): Promise<void>;
10
- scrapeSdkData(data: event_types.InstanceRequest): Promise<ListCurrentConnectionsResponse>;
11
- reportSdkConnect(data: SdkConnectBucketData): Promise<void>;
12
- reportSdkDisconnect(data: SdkDisconnectEventData): Promise<void>;
13
- listCurrentConnections(data: event_types.InstanceRequest): Promise<ListCurrentConnectionsResponse>;
9
+ scrapeSdkData(data: event_types.ScrapeSdkDataRequest): Promise<event_types.ListCurrentConnectionsResponse>;
10
+ reportSdkConnect(data: event_types.SdkConnectBucketData): Promise<void>;
11
+ reportSdkDisconnect(data: event_types.SdkDisconnectEventData): Promise<void>;
12
+ listCurrentConnections(data: event_types.InstanceRequest): Promise<event_types.ListCurrentConnectionsResponse>;
14
13
  [Symbol.asyncDispose](): Promise<void>;
15
14
  }
@@ -1,18 +1,67 @@
1
- function dateFilter(userId, clientId) {
2
- const date = new Date();
1
+ import { event_types } from '@powersync/service-types';
2
+ function parseDate(date) {
3
3
  const year = date.getFullYear();
4
- const month = date.getMonth() + 1;
5
- const day = date.getDate();
6
- const query = {
4
+ const month = date.getMonth();
5
+ const today = date.getDate();
6
+ const day = date.getDay();
7
+ return {
8
+ year,
9
+ month,
10
+ today,
11
+ day
12
+ };
13
+ }
14
+ function updateDocFilter(userId, clientId) {
15
+ const { year, month, today } = parseDate(new Date());
16
+ const nextDay = today + 1;
17
+ return {
7
18
  user_id: userId,
8
19
  client_id: clientId,
9
20
  connect_at: {
10
- $gte: new Date(year, month, day, 0, 0, 0),
11
- $lt: new Date(year, month, day + 1, 0, 0, 0)
21
+ $gte: new Date(year, month, today, 0, 0, 0),
22
+ $lt: new Date(year, month, nextDay, 0, 0, 0)
12
23
  }
13
24
  };
14
- console.log({ query, date });
15
- return query;
25
+ }
26
+ function timeSpan(timeframe) {
27
+ const date = new Date();
28
+ const { year, month, day, today } = parseDate(date);
29
+ switch (timeframe) {
30
+ case event_types.TimeFrames.MONTH: {
31
+ // Cron should run the first day of the new month, this then retrieves from the 1st to the last day of the month
32
+ const thisMonth = month;
33
+ const nextMonth = month == 11 ? 0 : month + 1;
34
+ return {
35
+ connect_at: { $gte: new Date(year, thisMonth, 1, 0, 0, 0), $lte: new Date(year, nextMonth, 1, 0, 0, 0) }
36
+ };
37
+ }
38
+ case event_types.TimeFrames.WEEK: {
39
+ // Back tracks the date to the previous week Monday to Sunday
40
+ const daysToSunday = 0 - day;
41
+ const weekEndDate = new Date(date);
42
+ weekEndDate.setDate(weekEndDate.getDate() + daysToSunday);
43
+ const weekStartDate = new Date(weekEndDate);
44
+ weekStartDate.setDate(weekStartDate.getDate() - 6);
45
+ const weekStart = parseDate(weekStartDate);
46
+ const weekEnd = parseDate(weekEndDate);
47
+ return {
48
+ connect_at: {
49
+ $gte: new Date(weekStart.year, weekStart.month, weekStart.today, 0, 0, 0),
50
+ $lte: new Date(weekEnd.year, weekEnd.month, weekEnd.today, 0, 0, 0)
51
+ }
52
+ };
53
+ }
54
+ default: {
55
+ // Start from today to just before tomorrow
56
+ const tomorrow = today + 1;
57
+ return {
58
+ connect_at: {
59
+ $gte: new Date(date.getFullYear(), date.getMonth(), today, 0, 0, 0),
60
+ $lte: new Date(date.getFullYear(), date.getMonth(), tomorrow, 0, 0, 0)
61
+ }
62
+ };
63
+ }
64
+ }
16
65
  }
17
66
  export class MongoReportStorage {
18
67
  client;
@@ -28,31 +77,57 @@ export class MongoReportStorage {
28
77
  const result = await this.db.sdk_report_events
29
78
  .aggregate([
30
79
  {
31
- $group: {
32
- _id: null,
33
- user_ids: { $addToSet: '$user_id' },
34
- client_ids: { $addToSet: '$client_id' },
35
- sdks: { $addToSet: '$sdk' }
80
+ $match: {
81
+ connect_at: timeSpan(data.scrape_time)
36
82
  }
37
83
  },
38
84
  {
39
- $project: {
40
- _id: 0,
41
- users: '$user_ids',
42
- clients: '$client_ids',
43
- sdks: '$sdks'
85
+ $facet: {
86
+ unique_user_ids: [
87
+ {
88
+ $group: {
89
+ _id: '$user_id'
90
+ }
91
+ },
92
+ {
93
+ $count: 'count'
94
+ }
95
+ ],
96
+ unique_user_sdk: [
97
+ {
98
+ $group: {
99
+ _id: {
100
+ user_id: '$user_id',
101
+ sdk: '$sdk'
102
+ }
103
+ }
104
+ },
105
+ {
106
+ $count: 'count'
107
+ }
108
+ ],
109
+ unique_user_client: [
110
+ {
111
+ $group: {
112
+ _id: {
113
+ user_id: '$user_id',
114
+ client_id: '$client_id'
115
+ }
116
+ }
117
+ },
118
+ {
119
+ $count: 'count'
120
+ }
121
+ ]
44
122
  }
45
123
  }
46
124
  ])
47
125
  .toArray();
48
- return {
49
- app_id: data.app_id,
50
- org_id: data.org_id,
51
- ...result[0]
52
- };
126
+ console.log(result[0]);
127
+ return result[0];
53
128
  }
54
129
  async reportSdkConnect(data) {
55
- await this.db.sdk_report_events.findOneAndUpdate(dateFilter(data.user_id, data.client_id), {
130
+ await this.db.sdk_report_events.findOneAndUpdate(updateDocFilter(data.user_id, data.client_id), {
56
131
  $set: data,
57
132
  $unset: {
58
133
  disconnect_at: ''
@@ -62,7 +137,7 @@ export class MongoReportStorage {
62
137
  });
63
138
  }
64
139
  async reportSdkDisconnect(data) {
65
- await this.db.sdk_report_events.findOneAndUpdate(dateFilter(data.user_id, data.client_id), {
140
+ await this.db.sdk_report_events.findOneAndUpdate(updateDocFilter(data.user_id, data.client_id), {
66
141
  $set: {
67
142
  disconnect_at: data.disconnect_at
68
143
  },
@@ -1 +1 @@
1
- {"version":3,"file":"MongoReportStorage.js","sourceRoot":"","sources":["../../src/storage/MongoReportStorage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MongoReportStorage.js","sourceRoot":"","sources":["../../src/storage/MongoReportStorage.ts"],"names":[],"mappings":"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"}
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-20250722090128",
5
+ "version": "0.0.0-dev-20250722122401",
6
6
  "main": "dist/index.js",
7
7
  "license": "FSL-1.1-Apache-2.0",
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-20250722090128",
31
- "@powersync/lib-services-framework": "0.0.0-dev-20250722090128",
32
- "@powersync/service-core": "0.0.0-dev-20250722090128",
33
- "@powersync/service-types": "0.0.0-dev-20250722090128",
30
+ "@powersync/lib-service-mongodb": "0.0.0-dev-20250722122401",
31
+ "@powersync/lib-services-framework": "0.0.0-dev-20250722122401",
32
+ "@powersync/service-core": "0.0.0-dev-20250722122401",
33
+ "@powersync/service-types": "0.0.0-dev-20250722122401",
34
34
  "@powersync/service-jsonbig": "0.17.10",
35
35
  "@powersync/service-sync-rules": "0.27.0"
36
36
  },
37
37
  "devDependencies": {
38
- "@powersync/service-core-tests": "0.0.0-dev-20250722090128"
38
+ "@powersync/service-core-tests": "0.0.0-dev-20250722122401"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "tsc -b",
@@ -2,28 +2,71 @@ import { mongo } from '@powersync/lib-service-mongodb';
2
2
  import { storage } from '@powersync/service-core';
3
3
  import { event_types } from '@powersync/service-types';
4
4
  import { PowerSyncMongo } from './implementation/db.js';
5
- import {
6
- ListCurrentConnections,
7
- ListCurrentConnectionsResponse,
8
- SdkConnectBucketData,
9
- SdkDisconnectEventData
10
- } from '@powersync/service-types/dist/events.js';
11
5
 
12
- function dateFilter(userId: string, clientId: string): mongo.Filter<mongo.Document> {
13
- const date = new Date();
6
+ function parseDate(date: Date) {
14
7
  const year = date.getFullYear();
15
- const month = date.getMonth() + 1;
16
- const day = date.getDate();
17
- const query = {
8
+ const month = date.getMonth();
9
+ const today = date.getDate();
10
+ const day = date.getDay();
11
+ return {
12
+ year,
13
+ month,
14
+ today,
15
+ day
16
+ };
17
+ }
18
+ function updateDocFilter(userId: string, clientId: string): mongo.Filter<mongo.Document> {
19
+ const { year, month, today } = parseDate(new Date());
20
+ const nextDay = today + 1;
21
+ return {
18
22
  user_id: userId,
19
23
  client_id: clientId,
20
24
  connect_at: {
21
- $gte: new Date(year, month, day, 0, 0, 0),
22
- $lt: new Date(year, month, day + 1, 0, 0, 0)
25
+ $gte: new Date(year, month, today, 0, 0, 0),
26
+ $lt: new Date(year, month, nextDay, 0, 0, 0)
23
27
  }
24
28
  };
25
- console.log({ query, date });
26
- return query;
29
+ }
30
+
31
+ function timeSpan(timeframe: event_types.TimeFrames): mongo.Filter<mongo.Document> {
32
+ const date = new Date();
33
+ const { year, month, day, today } = parseDate(date);
34
+ switch (timeframe) {
35
+ case event_types.TimeFrames.MONTH: {
36
+ // Cron should run the first day of the new month, this then retrieves from the 1st to the last day of the month
37
+ const thisMonth = month;
38
+ const nextMonth = month == 11 ? 0 : month + 1;
39
+ return {
40
+ connect_at: { $gte: new Date(year, thisMonth, 1, 0, 0, 0), $lte: new Date(year, nextMonth, 1, 0, 0, 0) }
41
+ };
42
+ }
43
+ case event_types.TimeFrames.WEEK: {
44
+ // Back tracks the date to the previous week Monday to Sunday
45
+ const daysToSunday = 0 - day;
46
+ const weekEndDate = new Date(date);
47
+ weekEndDate.setDate(weekEndDate.getDate() + daysToSunday);
48
+ const weekStartDate = new Date(weekEndDate);
49
+ weekStartDate.setDate(weekStartDate.getDate() - 6);
50
+ const weekStart = parseDate(weekStartDate);
51
+ const weekEnd = parseDate(weekEndDate);
52
+ return {
53
+ connect_at: {
54
+ $gte: new Date(weekStart.year, weekStart.month, weekStart.today, 0, 0, 0),
55
+ $lte: new Date(weekEnd.year, weekEnd.month, weekEnd.today, 0, 0, 0)
56
+ }
57
+ };
58
+ }
59
+ default: {
60
+ // Start from today to just before tomorrow
61
+ const tomorrow = today + 1;
62
+ return {
63
+ connect_at: {
64
+ $gte: new Date(date.getFullYear(), date.getMonth(), today, 0, 0, 0),
65
+ $lte: new Date(date.getFullYear(), date.getMonth(), tomorrow, 0, 0, 0)
66
+ }
67
+ };
68
+ }
69
+ }
27
70
  }
28
71
 
29
72
  export class MongoReportStorage implements storage.ReportStorageFactory {
@@ -39,37 +82,63 @@ export class MongoReportStorage implements storage.ReportStorageFactory {
39
82
  console.log(data);
40
83
  }
41
84
 
42
- async scrapeSdkData(data: event_types.InstanceRequest): Promise<ListCurrentConnectionsResponse> {
85
+ async scrapeSdkData(data: event_types.ScrapeSdkDataRequest): Promise<event_types.ListCurrentConnectionsResponse> {
43
86
  const result = await this.db.sdk_report_events
44
- .aggregate<ListCurrentConnections>([
87
+ .aggregate([
45
88
  {
46
- $group: {
47
- _id: null,
48
- user_ids: { $addToSet: '$user_id' },
49
- client_ids: { $addToSet: '$client_id' },
50
- sdks: { $addToSet: '$sdk' }
89
+ $match: {
90
+ connect_at: timeSpan(data.scrape_time)
51
91
  }
52
92
  },
53
93
  {
54
- $project: {
55
- _id: 0,
56
- users: '$user_ids',
57
- clients: '$client_ids',
58
- sdks: '$sdks'
94
+ $facet: {
95
+ unique_user_ids: [
96
+ {
97
+ $group: {
98
+ _id: '$user_id'
99
+ }
100
+ },
101
+ {
102
+ $count: 'count'
103
+ }
104
+ ],
105
+ unique_user_sdk: [
106
+ {
107
+ $group: {
108
+ _id: {
109
+ user_id: '$user_id',
110
+ sdk: '$sdk'
111
+ }
112
+ }
113
+ },
114
+ {
115
+ $count: 'count'
116
+ }
117
+ ],
118
+ unique_user_client: [
119
+ {
120
+ $group: {
121
+ _id: {
122
+ user_id: '$user_id',
123
+ client_id: '$client_id'
124
+ }
125
+ }
126
+ },
127
+ {
128
+ $count: 'count'
129
+ }
130
+ ]
59
131
  }
60
132
  }
61
133
  ])
62
134
  .toArray();
63
- return {
64
- app_id: data.app_id,
65
- org_id: data.org_id,
66
- ...result[0]
67
- };
135
+ console.log(result[0]);
136
+ return result[0] as event_types.ListCurrentConnectionsResponse;
68
137
  }
69
138
 
70
- async reportSdkConnect(data: SdkConnectBucketData): Promise<void> {
139
+ async reportSdkConnect(data: event_types.SdkConnectBucketData): Promise<void> {
71
140
  await this.db.sdk_report_events.findOneAndUpdate(
72
- dateFilter(data.user_id, data.client_id!),
141
+ updateDocFilter(data.user_id, data.client_id!),
73
142
  {
74
143
  $set: data,
75
144
  $unset: {
@@ -81,8 +150,8 @@ export class MongoReportStorage implements storage.ReportStorageFactory {
81
150
  }
82
151
  );
83
152
  }
84
- async reportSdkDisconnect(data: SdkDisconnectEventData): Promise<void> {
85
- await this.db.sdk_report_events.findOneAndUpdate(dateFilter(data.user_id, data.client_id!), {
153
+ async reportSdkDisconnect(data: event_types.SdkDisconnectEventData): Promise<void> {
154
+ await this.db.sdk_report_events.findOneAndUpdate(updateDocFilter(data.user_id, data.client_id!), {
86
155
  $set: {
87
156
  disconnect_at: data.disconnect_at
88
157
  },
@@ -91,9 +160,9 @@ export class MongoReportStorage implements storage.ReportStorageFactory {
91
160
  }
92
161
  });
93
162
  }
94
- async listCurrentConnections(data: event_types.InstanceRequest): Promise<ListCurrentConnectionsResponse> {
163
+ async listCurrentConnections(data: event_types.InstanceRequest): Promise<event_types.ListCurrentConnectionsResponse> {
95
164
  const result = await this.db.sdk_report_events
96
- .aggregate<ListCurrentConnections>([
165
+ .aggregate<event_types.ListCurrentConnections>([
97
166
  {
98
167
  $group: {
99
168
  _id: null,