@casual-simulation/aux-records 3.4.6-alpha.14668890889 → 3.5.0-alpha.15119114602

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 (211) hide show
  1. package/AIController.js +835 -890
  2. package/AIController.js.map +1 -1
  3. package/AIHumeInterface.js +43 -54
  4. package/AIHumeInterface.js.map +1 -1
  5. package/AIOpenAIRealtimeInterface.js +60 -71
  6. package/AIOpenAIRealtimeInterface.js.map +1 -1
  7. package/AnthropicAIChatInterface.js +96 -142
  8. package/AnthropicAIChatInterface.js.map +1 -1
  9. package/AuthController.d.ts +3 -2
  10. package/AuthController.js +1907 -1933
  11. package/AuthController.js.map +1 -1
  12. package/AuthStore.d.ts +1 -10
  13. package/BlockadeLabsGenerateSkyboxInterface.js +57 -72
  14. package/BlockadeLabsGenerateSkyboxInterface.js.map +1 -1
  15. package/CachingConfigStore.js +30 -45
  16. package/CachingConfigStore.js.map +1 -1
  17. package/CachingPolicyStore.d.ts +8 -2
  18. package/CachingPolicyStore.js +108 -135
  19. package/CachingPolicyStore.js.map +1 -1
  20. package/ComIdConfig.d.ts +18 -18
  21. package/ComIdConfig.js.map +1 -1
  22. package/ConsoleAuthMessenger.js +7 -20
  23. package/ConsoleAuthMessenger.js.map +1 -1
  24. package/DataRecordsController.d.ts +2 -2
  25. package/DataRecordsController.js +369 -377
  26. package/DataRecordsController.js.map +1 -1
  27. package/DataRecordsStore.d.ts +1 -1
  28. package/DataRecordsStore.js +1 -1
  29. package/DataRecordsStore.js.map +1 -1
  30. package/EventRecordsController.js +226 -240
  31. package/EventRecordsController.js.map +1 -1
  32. package/FileRecordsController.d.ts +13 -2
  33. package/FileRecordsController.js +458 -450
  34. package/FileRecordsController.js.map +1 -1
  35. package/GoogleAIChatInterface.js +133 -179
  36. package/GoogleAIChatInterface.js.map +1 -1
  37. package/LivekitController.js +43 -54
  38. package/LivekitController.js.map +1 -1
  39. package/LoomController.js +64 -75
  40. package/LoomController.js.map +1 -1
  41. package/MemoryAuthMessenger.js +10 -23
  42. package/MemoryAuthMessenger.js.map +1 -1
  43. package/MemoryCache.js +18 -35
  44. package/MemoryCache.js.map +1 -1
  45. package/MemoryFileRecordsLookup.js +105 -125
  46. package/MemoryFileRecordsLookup.js.map +1 -1
  47. package/MemoryModerationJobProvider.js +17 -30
  48. package/MemoryModerationJobProvider.js.map +1 -1
  49. package/MemoryRateLimiter.js +12 -27
  50. package/MemoryRateLimiter.js.map +1 -1
  51. package/MemoryStore.d.ts +18 -6
  52. package/MemoryStore.js +1879 -1997
  53. package/MemoryStore.js.map +1 -1
  54. package/MetricsStore.d.ts +2 -2
  55. package/ModerationController.js +186 -200
  56. package/ModerationController.js.map +1 -1
  57. package/OpenAIChatInterface.js +105 -135
  58. package/OpenAIChatInterface.js.map +1 -1
  59. package/OpenAIImageInterface.js +57 -51
  60. package/OpenAIImageInterface.js.map +1 -1
  61. package/PolicyController.d.ts +150 -10
  62. package/PolicyController.js +1546 -1299
  63. package/PolicyController.js.map +1 -1
  64. package/PolicyStore.d.ts +110 -2
  65. package/PolicyStore.js +36 -1
  66. package/PolicyStore.js.map +1 -1
  67. package/PrivoClient.js +398 -435
  68. package/PrivoClient.js.map +1 -1
  69. package/RateLimitController.js +25 -36
  70. package/RateLimitController.js.map +1 -1
  71. package/RecordsClient.js +51 -74
  72. package/RecordsClient.js.map +1 -1
  73. package/RecordsController.d.ts +2 -42
  74. package/RecordsController.js +1026 -1182
  75. package/RecordsController.js.map +1 -1
  76. package/RecordsServer.d.ts +196 -27
  77. package/RecordsServer.js +1701 -1343
  78. package/RecordsServer.js.map +1 -1
  79. package/RecordsStore.d.ts +1 -10
  80. package/RecordsStore.js.map +1 -1
  81. package/ServerConfig.d.ts +339 -195
  82. package/ServerConfig.js +13 -0
  83. package/ServerConfig.js.map +1 -1
  84. package/SloydInterface.js +62 -75
  85. package/SloydInterface.js.map +1 -1
  86. package/StabilityAIImageInterface.js +150 -167
  87. package/StabilityAIImageInterface.js.map +1 -1
  88. package/SubscriptionConfigBuilder.d.ts +6 -1
  89. package/SubscriptionConfigBuilder.js +22 -0
  90. package/SubscriptionConfigBuilder.js.map +1 -1
  91. package/SubscriptionConfiguration.d.ts +266 -169
  92. package/SubscriptionConfiguration.js +101 -79
  93. package/SubscriptionConfiguration.js.map +1 -1
  94. package/SubscriptionController.d.ts +2 -1
  95. package/SubscriptionController.js +643 -650
  96. package/SubscriptionController.js.map +1 -1
  97. package/SystemNotificationMessenger.d.ts +21 -4
  98. package/SystemNotificationMessenger.js +36 -30
  99. package/SystemNotificationMessenger.js.map +1 -1
  100. package/TestUtils.d.ts +9 -1
  101. package/TestUtils.js +105 -129
  102. package/TestUtils.js.map +1 -1
  103. package/Utils.d.ts +2 -16
  104. package/Utils.js +21 -22
  105. package/Utils.js.map +1 -1
  106. package/crud/CrudHelpers.js +17 -26
  107. package/crud/CrudHelpers.js.map +1 -1
  108. package/crud/CrudRecordsController.d.ts +1 -1
  109. package/crud/CrudRecordsController.js +259 -267
  110. package/crud/CrudRecordsController.js.map +1 -1
  111. package/crud/CrudRecordsControllerTests.js +174 -185
  112. package/crud/CrudRecordsControllerTests.js.map +1 -1
  113. package/crud/CrudRecordsStore.d.ts +7 -3
  114. package/crud/MemoryCrudRecordsStore.d.ts +4 -4
  115. package/crud/MemoryCrudRecordsStore.js +98 -118
  116. package/crud/MemoryCrudRecordsStore.js.map +1 -1
  117. package/crud/sub/MemorySubCrudRecordsStore.d.ts +24 -0
  118. package/crud/sub/MemorySubCrudRecordsStore.js +146 -0
  119. package/crud/sub/MemorySubCrudRecordsStore.js.map +1 -0
  120. package/crud/sub/SubCrudRecordsController.d.ts +182 -0
  121. package/crud/sub/SubCrudRecordsController.js +360 -0
  122. package/crud/sub/SubCrudRecordsController.js.map +1 -0
  123. package/crud/sub/SubCrudRecordsControllerTests.d.ts +39 -0
  124. package/crud/sub/SubCrudRecordsControllerTests.js +821 -0
  125. package/crud/sub/SubCrudRecordsControllerTests.js.map +1 -0
  126. package/crud/sub/SubCrudRecordsStore.d.ts +95 -0
  127. package/{forms/index.js → crud/sub/SubCrudRecordsStore.js} +2 -2
  128. package/crud/sub/SubCrudRecordsStore.js.map +1 -0
  129. package/crud/sub/index.d.ts +3 -0
  130. package/crud/sub/index.js +20 -0
  131. package/{forms → crud/sub}/index.js.map +1 -1
  132. package/index.d.ts +1 -1
  133. package/index.js +1 -1
  134. package/index.js.map +1 -1
  135. package/notifications/MemoryNotificationRecordsStore.js +189 -198
  136. package/notifications/MemoryNotificationRecordsStore.js.map +1 -1
  137. package/notifications/NotificationRecordsController.js +438 -460
  138. package/notifications/NotificationRecordsController.js.map +1 -1
  139. package/notifications/NotificationRecordsStore.d.ts +2 -1
  140. package/notifications/WebPushInterface.d.ts +0 -1
  141. package/notifications/WebPushInterface.js +0 -1
  142. package/notifications/WebPushInterface.js.map +1 -1
  143. package/package.json +6 -6
  144. package/packages/MemoryPackageRecordsStore.d.ts +10 -0
  145. package/packages/MemoryPackageRecordsStore.js +38 -0
  146. package/packages/MemoryPackageRecordsStore.js.map +1 -0
  147. package/packages/PackageRecordsController.d.ts +26 -0
  148. package/packages/PackageRecordsController.js +49 -0
  149. package/packages/PackageRecordsController.js.map +1 -0
  150. package/packages/PackageRecordsStore.d.ts +32 -0
  151. package/packages/PackageRecordsStore.js +19 -0
  152. package/packages/PackageRecordsStore.js.map +1 -0
  153. package/packages/index.d.ts +4 -0
  154. package/packages/index.js +21 -0
  155. package/packages/index.js.map +1 -0
  156. package/packages/version/MemoryPackageVersionRecordsStore.d.ts +21 -0
  157. package/packages/version/MemoryPackageVersionRecordsStore.js +177 -0
  158. package/packages/version/MemoryPackageVersionRecordsStore.js.map +1 -0
  159. package/packages/version/PackageVersionRecordsController.d.ts +144 -0
  160. package/packages/version/PackageVersionRecordsController.js +656 -0
  161. package/packages/version/PackageVersionRecordsController.js.map +1 -0
  162. package/packages/version/PackageVersionRecordsStore.d.ts +342 -0
  163. package/packages/version/PackageVersionRecordsStore.js +126 -0
  164. package/packages/version/PackageVersionRecordsStore.js.map +1 -0
  165. package/packages/version/index.d.ts +4 -0
  166. package/packages/version/index.js +21 -0
  167. package/packages/version/index.js.map +1 -0
  168. package/tracing/TracingDecorators.js +31 -40
  169. package/tracing/TracingDecorators.js.map +1 -1
  170. package/webhooks/MemoryWebhookRecordsStore.js +56 -72
  171. package/webhooks/MemoryWebhookRecordsStore.js.map +1 -1
  172. package/webhooks/WebhookEnvironment.d.ts +3 -3
  173. package/webhooks/WebhookRecordsController.d.ts +2 -1
  174. package/webhooks/WebhookRecordsController.js +389 -382
  175. package/webhooks/WebhookRecordsController.js.map +1 -1
  176. package/webhooks/WebhookRecordsStore.d.ts +2 -1
  177. package/websockets/InstRecordsStore.d.ts +50 -0
  178. package/websockets/InstRecordsStore.js +17 -0
  179. package/websockets/InstRecordsStore.js.map +1 -1
  180. package/websockets/MemoryTempInstRecordsStore.d.ts +5 -0
  181. package/websockets/MemoryTempInstRecordsStore.js +168 -179
  182. package/websockets/MemoryTempInstRecordsStore.js.map +1 -1
  183. package/websockets/MemoryWebsocketConnectionStore.js +98 -135
  184. package/websockets/MemoryWebsocketConnectionStore.js.map +1 -1
  185. package/websockets/MemoryWebsocketMessenger.js +29 -48
  186. package/websockets/MemoryWebsocketMessenger.js.map +1 -1
  187. package/websockets/SplitInstRecordsStore.d.ts +4 -1
  188. package/websockets/SplitInstRecordsStore.js +167 -185
  189. package/websockets/SplitInstRecordsStore.js.map +1 -1
  190. package/websockets/TemporaryInstRecordsStore.d.ts +19 -1
  191. package/websockets/TemporaryInstRecordsStore.js +17 -0
  192. package/websockets/TemporaryInstRecordsStore.js.map +1 -1
  193. package/websockets/WebsocketController.d.ts +147 -3
  194. package/websockets/WebsocketController.js +1735 -1391
  195. package/websockets/WebsocketController.js.map +1 -1
  196. package/websockets/index.d.ts +0 -1
  197. package/websockets/index.js +0 -1
  198. package/websockets/index.js.map +1 -1
  199. package/AAGUID.d.ts +0 -11
  200. package/AAGUID.js +0 -116
  201. package/AAGUID.js.map +0 -1
  202. package/AuthUtils.d.ts +0 -162
  203. package/AuthUtils.js +0 -327
  204. package/AuthUtils.js.map +0 -1
  205. package/forms/FormError.d.ts +0 -43
  206. package/forms/FormError.js +0 -56
  207. package/forms/FormError.js.map +0 -1
  208. package/forms/index.d.ts +0 -2
  209. package/websockets/Utils.d.ts +0 -33
  210. package/websockets/Utils.js +0 -82
  211. package/websockets/Utils.js.map +0 -1
@@ -4,145 +4,135 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
8
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
9
- return new (P || (P = Promise))(function (resolve, reject) {
10
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
11
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
12
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
13
- step((generator = generator.apply(thisArg, _arguments || [])).next());
14
- });
15
- };
16
- import { PRIVATE_MARKER } from '@casual-simulation/aux-common';
7
+ import { PRIVATE_MARKER, SUBSCRIPTION_ID_NAMESPACE, } from '@casual-simulation/aux-common';
17
8
  import { CrudRecordsController } from '../crud';
18
9
  import { getNotificationFeatures } from '../SubscriptionConfiguration';
19
10
  import { traced } from '../tracing/TracingDecorators';
20
11
  import { SpanStatusCode, trace } from '@opentelemetry/api';
21
12
  import { v7 as uuidv7, v5 as uuidv5 } from 'uuid';
22
- import { SUBSCRIPTION_ID_NAMESPACE } from './WebPushInterface';
23
13
  const TRACE_NAME = 'NotificationRecordsController';
24
14
  /**
25
15
  * Defines a controller that can be used to interact with NotificationRecords.
26
16
  */
27
17
  export class NotificationRecordsController extends CrudRecordsController {
28
18
  constructor(config) {
29
- super(Object.assign(Object.assign({}, config), { name: 'NotificationRecordsController', resourceKind: 'notification' }));
19
+ super({
20
+ ...config,
21
+ name: 'NotificationRecordsController',
22
+ resourceKind: 'notification',
23
+ });
30
24
  this._pushInterface = config.pushInterface;
31
25
  }
32
- getApplicationServerKey() {
33
- return __awaiter(this, void 0, void 0, function* () {
34
- try {
35
- const key = this._pushInterface.getServerApplicationKey();
36
- return {
37
- success: true,
38
- key,
39
- };
40
- }
41
- catch (err) {
42
- const span = trace.getActiveSpan();
43
- span === null || span === void 0 ? void 0 : span.recordException(err);
44
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
45
- console.error('[NotificationRecordsController] Error subscribing to notification:', err);
46
- return {
47
- success: false,
48
- errorCode: 'server_error',
49
- errorMessage: 'A server error occurred.',
50
- };
51
- }
52
- });
26
+ async getApplicationServerKey() {
27
+ try {
28
+ const key = this._pushInterface.getServerApplicationKey();
29
+ return {
30
+ success: true,
31
+ key,
32
+ };
33
+ }
34
+ catch (err) {
35
+ const span = trace.getActiveSpan();
36
+ span === null || span === void 0 ? void 0 : span.recordException(err);
37
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
38
+ console.error('[NotificationRecordsController] Error subscribing to notification:', err);
39
+ return {
40
+ success: false,
41
+ errorCode: 'server_error',
42
+ errorMessage: 'A server error occurred.',
43
+ };
44
+ }
53
45
  }
54
46
  /**
55
47
  * Subscribes the user to the given notification.
56
48
  * Does nothing if the user is already subscribed.
57
49
  * @param request The request.
58
50
  */
59
- subscribeToNotification(request) {
60
- return __awaiter(this, void 0, void 0, function* () {
61
- try {
62
- const context = yield this.policies.constructAuthorizationContext({
63
- userId: request.userId,
64
- recordKeyOrRecordName: request.recordName,
65
- });
66
- if (context.success === false) {
67
- return context;
68
- }
69
- const recordName = context.context.recordName;
70
- const userId = context.context.userId;
71
- const notification = yield this.store.getItemByAddress(recordName, request.address);
72
- if (!notification) {
73
- return {
74
- success: false,
75
- errorCode: 'data_not_found',
76
- errorMessage: 'Notification not found.',
77
- };
78
- }
79
- const authorization = yield this.policies.authorizeUserAndInstances(context.context, {
80
- action: 'subscribe',
81
- resourceKind: 'notification',
82
- resourceId: notification.address,
83
- markers: notification.markers,
84
- userId: userId,
85
- instances: request.instances,
86
- });
87
- if (authorization.success === false) {
88
- return authorization;
89
- }
90
- const metrics = yield this._checkSubscriptionMetrics('subscribe', context.context, authorization, notification);
91
- if (metrics.success === false) {
92
- return metrics;
93
- }
94
- const pushSubscriptionId = this._getPushSubscriptionId(request.pushSubscription.endpoint);
95
- yield this.store.savePushSubscription({
96
- id: pushSubscriptionId,
97
- active: true,
98
- endpoint: request.pushSubscription.endpoint,
99
- keys: request.pushSubscription.keys,
100
- });
101
- yield this.store.savePushSubscriptionUser({
102
- pushSubscriptionId: pushSubscriptionId,
103
- userId: userId,
104
- });
105
- let subscriptionId = null;
106
- if (userId) {
107
- const sub = yield this.store.getSubscriptionByRecordAddressAndUserId(recordName, notification.address, userId);
108
- if (sub) {
109
- subscriptionId = sub.id;
110
- }
111
- }
112
- else {
113
- const sub = yield this.store.getSubscriptionByRecordAddressAndPushSubscriptionId(recordName, notification.address, pushSubscriptionId);
114
- if (sub) {
115
- subscriptionId = sub.id;
116
- }
117
- }
118
- if (!subscriptionId) {
119
- subscriptionId = uuidv7();
120
- yield this.store.saveSubscription({
121
- id: subscriptionId,
122
- recordName,
123
- notificationAddress: notification.address,
124
- userId: userId,
125
- pushSubscriptionId: !userId ? pushSubscriptionId : null,
126
- });
127
- }
128
- console.log(`[NotificationRecordsController] [userId: ${userId} pushSubscriptionId: ${pushSubscriptionId} subscriptionId: ${subscriptionId}] Subscribed to notification`);
129
- return {
130
- success: true,
131
- subscriptionId,
132
- };
51
+ async subscribeToNotification(request) {
52
+ try {
53
+ const context = await this.policies.constructAuthorizationContext({
54
+ userId: request.userId,
55
+ recordKeyOrRecordName: request.recordName,
56
+ });
57
+ if (context.success === false) {
58
+ return context;
133
59
  }
134
- catch (err) {
135
- const span = trace.getActiveSpan();
136
- span === null || span === void 0 ? void 0 : span.recordException(err);
137
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
138
- console.error('[NotificationRecordsController] Error subscribing to notification:', err);
60
+ const recordName = context.context.recordName;
61
+ const userId = context.context.userId;
62
+ const notification = await this.store.getItemByAddress(recordName, request.address);
63
+ if (!notification) {
139
64
  return {
140
65
  success: false,
141
- errorCode: 'server_error',
142
- errorMessage: 'A server error occurred.',
66
+ errorCode: 'data_not_found',
67
+ errorMessage: 'Notification not found.',
143
68
  };
144
69
  }
145
- });
70
+ const authorization = await this.policies.authorizeUserAndInstances(context.context, {
71
+ action: 'subscribe',
72
+ resourceKind: 'notification',
73
+ resourceId: notification.address,
74
+ markers: notification.markers,
75
+ userId: userId,
76
+ instances: request.instances,
77
+ });
78
+ if (authorization.success === false) {
79
+ return authorization;
80
+ }
81
+ const metrics = await this._checkSubscriptionMetrics('subscribe', context.context, authorization, notification);
82
+ if (metrics.success === false) {
83
+ return metrics;
84
+ }
85
+ const pushSubscriptionId = this._getPushSubscriptionId(request.pushSubscription.endpoint);
86
+ await this.store.savePushSubscription({
87
+ id: pushSubscriptionId,
88
+ active: true,
89
+ endpoint: request.pushSubscription.endpoint,
90
+ keys: request.pushSubscription.keys,
91
+ });
92
+ await this.store.savePushSubscriptionUser({
93
+ pushSubscriptionId: pushSubscriptionId,
94
+ userId: userId,
95
+ });
96
+ let subscriptionId = null;
97
+ if (userId) {
98
+ const sub = await this.store.getSubscriptionByRecordAddressAndUserId(recordName, notification.address, userId);
99
+ if (sub) {
100
+ subscriptionId = sub.id;
101
+ }
102
+ }
103
+ else {
104
+ const sub = await this.store.getSubscriptionByRecordAddressAndPushSubscriptionId(recordName, notification.address, pushSubscriptionId);
105
+ if (sub) {
106
+ subscriptionId = sub.id;
107
+ }
108
+ }
109
+ if (!subscriptionId) {
110
+ subscriptionId = uuidv7();
111
+ await this.store.saveSubscription({
112
+ id: subscriptionId,
113
+ recordName,
114
+ notificationAddress: notification.address,
115
+ userId: userId,
116
+ pushSubscriptionId: !userId ? pushSubscriptionId : null,
117
+ });
118
+ }
119
+ console.log(`[NotificationRecordsController] [userId: ${userId} pushSubscriptionId: ${pushSubscriptionId} subscriptionId: ${subscriptionId}] Subscribed to notification`);
120
+ return {
121
+ success: true,
122
+ subscriptionId,
123
+ };
124
+ }
125
+ catch (err) {
126
+ const span = trace.getActiveSpan();
127
+ span === null || span === void 0 ? void 0 : span.recordException(err);
128
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
129
+ console.error('[NotificationRecordsController] Error subscribing to notification:', err);
130
+ return {
131
+ success: false,
132
+ errorCode: 'server_error',
133
+ errorMessage: 'A server error occurred.',
134
+ };
135
+ }
146
136
  }
147
137
  _getPushSubscriptionId(endpoint) {
148
138
  return uuidv5(endpoint, SUBSCRIPTION_ID_NAMESPACE);
@@ -151,144 +141,47 @@ export class NotificationRecordsController extends CrudRecordsController {
151
141
  * Unsubscribes the user from the given notification.
152
142
  * @param request The request.
153
143
  */
154
- unsubscribeFromNotification(request) {
155
- return __awaiter(this, void 0, void 0, function* () {
156
- try {
157
- const subscription = yield this.store.getSubscriptionById(request.subscriptionId);
158
- if (!subscription) {
159
- return {
160
- success: false,
161
- errorCode: 'data_not_found',
162
- errorMessage: 'Subscription not found.',
163
- };
164
- }
165
- const context = yield this.policies.constructAuthorizationContext({
144
+ async unsubscribeFromNotification(request) {
145
+ try {
146
+ const subscription = await this.store.getSubscriptionById(request.subscriptionId);
147
+ if (!subscription) {
148
+ return {
149
+ success: false,
150
+ errorCode: 'data_not_found',
151
+ errorMessage: 'Subscription not found.',
152
+ };
153
+ }
154
+ const context = await this.policies.constructAuthorizationContext({
155
+ userId: request.userId,
156
+ recordKeyOrRecordName: subscription.recordName,
157
+ });
158
+ if (context.success === false) {
159
+ return context;
160
+ }
161
+ let successfulAuthorization = false;
162
+ if (subscription.userId) {
163
+ const userContext = await this.policies.constructAuthorizationContext({
166
164
  userId: request.userId,
167
- recordKeyOrRecordName: subscription.recordName,
165
+ recordKeyOrRecordName: subscription.userId,
168
166
  });
169
- if (context.success === false) {
170
- return context;
171
- }
172
- let successfulAuthorization = false;
173
- if (subscription.userId) {
174
- const userContext = yield this.policies.constructAuthorizationContext({
167
+ if (userContext.success === true) {
168
+ const userAuthorization = await this.policies.authorizeUserAndInstances(userContext.context, {
175
169
  userId: request.userId,
176
- recordKeyOrRecordName: subscription.userId,
177
- });
178
- if (userContext.success === true) {
179
- const userAuthorization = yield this.policies.authorizeUserAndInstances(userContext.context, {
180
- userId: request.userId,
181
- action: 'unsubscribe',
182
- resourceKind: 'notification',
183
- resourceId: subscription.id,
184
- instances: request.instances,
185
- markers: [PRIVATE_MARKER],
186
- });
187
- if (userAuthorization.success === true) {
188
- successfulAuthorization = true;
189
- }
190
- }
191
- }
192
- const userId = context.context.userId;
193
- const recordName = context.context.recordName;
194
- if (!successfulAuthorization) {
195
- const notification = yield this.store.getItemByAddress(recordName, subscription.notificationAddress);
196
- if (!notification) {
197
- return {
198
- success: false,
199
- errorCode: 'data_not_found',
200
- errorMessage: 'Notification not found.',
201
- };
202
- }
203
- const authorization = yield this.policies.authorizeUserAndInstances(context.context, {
204
- userId,
205
170
  action: 'unsubscribe',
206
171
  resourceKind: 'notification',
207
- resourceId: notification.address,
172
+ resourceId: subscription.id,
208
173
  instances: request.instances,
209
- markers: notification.markers,
174
+ markers: [PRIVATE_MARKER],
210
175
  });
211
- if (authorization.success === false) {
212
- return authorization;
176
+ if (userAuthorization.success === true) {
177
+ successfulAuthorization = true;
213
178
  }
214
179
  }
215
- // allowed
216
- yield this.store.deleteSubscription(request.subscriptionId);
217
- console.log(`[NotificationRecordsController] [userId: ${userId} subscriptionId: ${request.subscriptionId}] Unsubscribed from notification`);
218
- return {
219
- success: true,
220
- };
221
180
  }
222
- catch (err) {
223
- const span = trace.getActiveSpan();
224
- span === null || span === void 0 ? void 0 : span.recordException(err);
225
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
226
- console.error('[NotificationRecordsController] Error subscribing to notification:', err);
227
- return {
228
- success: false,
229
- errorCode: 'server_error',
230
- errorMessage: 'A server error occurred.',
231
- };
232
- }
233
- });
234
- }
235
- /**
236
- * Registers a push subscription for the user.
237
- * This will allow the device to recieve push notifications for the user.
238
- * @param request The request.
239
- */
240
- registerPushSubscription(request) {
241
- return __awaiter(this, void 0, void 0, function* () {
242
- try {
243
- if (!request.userId) {
244
- return {
245
- success: false,
246
- errorCode: 'not_logged_in',
247
- errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
248
- };
249
- }
250
- const pushSubscriptionId = this._getPushSubscriptionId(request.pushSubscription.endpoint);
251
- yield this.store.savePushSubscription({
252
- id: pushSubscriptionId,
253
- active: true,
254
- endpoint: request.pushSubscription.endpoint,
255
- keys: request.pushSubscription.keys,
256
- });
257
- yield this.store.savePushSubscriptionUser({
258
- pushSubscriptionId: pushSubscriptionId,
259
- userId: request.userId,
260
- });
261
- console.log(`[NotificationRecordsController] [userId: ${request.userId} pushSubscriptionId: ${pushSubscriptionId}] Registered push subscription`);
262
- return {
263
- success: true,
264
- };
265
- }
266
- catch (err) {
267
- const span = trace.getActiveSpan();
268
- span === null || span === void 0 ? void 0 : span.recordException(err);
269
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
270
- console.error('[NotificationRecordsController] Error registering push subscription:', err);
271
- return {
272
- success: false,
273
- errorCode: 'server_error',
274
- errorMessage: 'A server error occurred.',
275
- };
276
- }
277
- });
278
- }
279
- sendNotification(request) {
280
- return __awaiter(this, void 0, void 0, function* () {
281
- try {
282
- const context = yield this.policies.constructAuthorizationContext({
283
- userId: request.userId,
284
- recordKeyOrRecordName: request.recordName,
285
- });
286
- if (context.success === false) {
287
- return context;
288
- }
289
- const recordName = context.context.recordName;
290
- const userId = context.context.userId;
291
- const notification = yield this.store.getItemByAddress(recordName, request.address);
181
+ const userId = context.context.userId;
182
+ const recordName = context.context.recordName;
183
+ if (!successfulAuthorization) {
184
+ const notification = await this.store.getItemByAddress(recordName, subscription.notificationAddress);
292
185
  if (!notification) {
293
186
  return {
294
187
  success: false,
@@ -296,264 +189,349 @@ export class NotificationRecordsController extends CrudRecordsController {
296
189
  errorMessage: 'Notification not found.',
297
190
  };
298
191
  }
299
- const authorization = yield this.policies.authorizeUserAndInstances(context.context, {
300
- action: 'send',
192
+ const authorization = await this.policies.authorizeUserAndInstances(context.context, {
193
+ userId,
194
+ action: 'unsubscribe',
301
195
  resourceKind: 'notification',
302
196
  resourceId: notification.address,
303
- markers: notification.markers,
304
- userId: userId,
305
197
  instances: request.instances,
198
+ markers: notification.markers,
306
199
  });
307
200
  if (authorization.success === false) {
308
201
  return authorization;
309
202
  }
310
- const metrics = yield this._checkSubscriptionMetrics('send', context.context, authorization, notification);
311
- if (metrics.success === false) {
312
- return metrics;
313
- }
314
- const pushSubs = yield this.store.listActivePushSubscriptionsForNotification(recordName, notification.address);
315
- if (typeof metrics.features.maxSentPushNotificationsPerPeriod ===
316
- 'number') {
317
- if (metrics.metrics.totalSentNotificationsInPeriod +
318
- pushSubs.length >=
319
- metrics.features.maxSentPushNotificationsPerPeriod) {
320
- return {
321
- success: false,
322
- errorCode: 'subscription_limit_reached',
323
- errorMessage: 'The maximum number of sent push notifications has been reached for this period.',
324
- };
325
- }
326
- }
327
- let promises = [];
328
- const sentTimeMs = Date.now();
329
- for (let push of pushSubs) {
330
- promises.push(this._pushInterface
331
- .sendNotification({
332
- endpoint: push.endpoint,
333
- keys: push.keys,
334
- }, request.payload, request.topic)
335
- .then((result) => {
336
- return [push, result];
337
- }));
338
- }
339
- const results = yield Promise.allSettled(promises);
340
- const notificationId = uuidv7();
341
- yield this.store.saveSentNotification({
342
- id: notificationId,
343
- recordName,
344
- notificationAddress: notification.address,
345
- title: request.payload.title,
346
- body: request.payload.body,
347
- icon: request.payload.icon,
348
- badge: request.payload.badge,
349
- defaultAction: request.payload.action,
350
- actions: request.payload.actions,
351
- silent: request.payload.silent,
352
- tag: request.payload.tag,
353
- timestamp: request.payload.timestamp,
354
- sentTimeMs: sentTimeMs,
355
- topic: request.topic,
356
- });
357
- let sentPushNotifications = [];
358
- let failedPushSubscriptions = [];
359
- for (let promiseResult of results) {
360
- if (promiseResult.status === 'rejected') {
361
- console.error('[NotificationRecordsController] Error sending notification:', promiseResult.reason);
362
- }
363
- else {
364
- const [push, result] = promiseResult.value;
365
- sentPushNotifications.push({
366
- id: uuidv7(),
367
- pushSubscriptionId: push.id,
368
- sentNotificationId: notificationId,
369
- userId: push.userId,
370
- subscriptionId: push.subscriptionId,
371
- success: result.success,
372
- errorCode: result.success === false ? result.errorCode : null,
373
- });
374
- if (result.success === false) {
375
- console.error(`[NotificationRecordsController] Error sending notification for ${push.id}:`, result.errorCode);
376
- if (result.errorCode === 'subscription_gone' ||
377
- result.errorCode === 'subscription_not_found') {
378
- failedPushSubscriptions.push(push.id);
379
- }
380
- }
381
- }
382
- }
383
- if (sentPushNotifications.length > 0) {
384
- yield this.store.createSentPushNotifications(sentPushNotifications);
385
- }
386
- if (failedPushSubscriptions.length > 0) {
387
- yield this.store.markPushSubscriptionsInactiveAndDeleteUserRelations(failedPushSubscriptions);
388
- }
389
- console.log(`[NotificationRecordsController] [userId: ${userId} notificationId: ${notificationId} sent: ${sentPushNotifications.length} failed: ${failedPushSubscriptions.length}] Sent notification`);
390
- return {
391
- success: true,
392
- };
393
203
  }
394
- catch (err) {
395
- const span = trace.getActiveSpan();
396
- span === null || span === void 0 ? void 0 : span.recordException(err);
397
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
398
- console.error('[NotificationRecordsController] Error sending notification:', err);
204
+ // allowed
205
+ await this.store.deleteSubscription(request.subscriptionId);
206
+ console.log(`[NotificationRecordsController] [userId: ${userId} subscriptionId: ${request.subscriptionId}] Unsubscribed from notification`);
207
+ return {
208
+ success: true,
209
+ };
210
+ }
211
+ catch (err) {
212
+ const span = trace.getActiveSpan();
213
+ span === null || span === void 0 ? void 0 : span.recordException(err);
214
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
215
+ console.error('[NotificationRecordsController] Error subscribing to notification:', err);
216
+ return {
217
+ success: false,
218
+ errorCode: 'server_error',
219
+ errorMessage: 'A server error occurred.',
220
+ };
221
+ }
222
+ }
223
+ /**
224
+ * Registers a push subscription for the user.
225
+ * This will allow the device to recieve push notifications for the user.
226
+ * @param request The request.
227
+ */
228
+ async registerPushSubscription(request) {
229
+ try {
230
+ if (!request.userId) {
399
231
  return {
400
232
  success: false,
401
- errorCode: 'server_error',
402
- errorMessage: 'A server error occurred.',
233
+ errorCode: 'not_logged_in',
234
+ errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
403
235
  };
404
236
  }
405
- });
237
+ const pushSubscriptionId = this._getPushSubscriptionId(request.pushSubscription.endpoint);
238
+ await this.store.savePushSubscription({
239
+ id: pushSubscriptionId,
240
+ active: true,
241
+ endpoint: request.pushSubscription.endpoint,
242
+ keys: request.pushSubscription.keys,
243
+ });
244
+ await this.store.savePushSubscriptionUser({
245
+ pushSubscriptionId: pushSubscriptionId,
246
+ userId: request.userId,
247
+ });
248
+ console.log(`[NotificationRecordsController] [userId: ${request.userId} pushSubscriptionId: ${pushSubscriptionId}] Registered push subscription`);
249
+ return {
250
+ success: true,
251
+ };
252
+ }
253
+ catch (err) {
254
+ const span = trace.getActiveSpan();
255
+ span === null || span === void 0 ? void 0 : span.recordException(err);
256
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
257
+ console.error('[NotificationRecordsController] Error registering push subscription:', err);
258
+ return {
259
+ success: false,
260
+ errorCode: 'server_error',
261
+ errorMessage: 'A server error occurred.',
262
+ };
263
+ }
406
264
  }
407
- listSubscriptionsForUser(request) {
408
- return __awaiter(this, void 0, void 0, function* () {
409
- try {
410
- if (!request.userId) {
411
- return {
412
- success: false,
413
- errorCode: 'not_logged_in',
414
- errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
415
- };
416
- }
417
- const subscriptions = yield this.store.listSubscriptionsForUser(request.userId);
418
- return {
419
- success: true,
420
- subscriptions: subscriptions.map((sub) => ({
421
- id: sub.id,
422
- userId: sub.userId,
423
- recordName: sub.recordName,
424
- notificationAddress: sub.notificationAddress,
425
- pushSubscriptionId: sub.pushSubscriptionId,
426
- })),
427
- };
265
+ async sendNotification(request) {
266
+ try {
267
+ const context = await this.policies.constructAuthorizationContext({
268
+ userId: request.userId,
269
+ recordKeyOrRecordName: request.recordName,
270
+ });
271
+ if (context.success === false) {
272
+ return context;
428
273
  }
429
- catch (err) {
430
- const span = trace.getActiveSpan();
431
- span === null || span === void 0 ? void 0 : span.recordException(err);
432
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
433
- console.error('[NotificationRecordsController] Error listing subscriptions for user:', err);
274
+ const recordName = context.context.recordName;
275
+ const userId = context.context.userId;
276
+ const notification = await this.store.getItemByAddress(recordName, request.address);
277
+ if (!notification) {
434
278
  return {
435
279
  success: false,
436
- errorCode: 'server_error',
437
- errorMessage: 'A server error occurred.',
280
+ errorCode: 'data_not_found',
281
+ errorMessage: 'Notification not found.',
438
282
  };
439
283
  }
440
- });
441
- }
442
- listSubscriptions(request) {
443
- return __awaiter(this, void 0, void 0, function* () {
444
- try {
445
- if (!request.userId) {
284
+ const authorization = await this.policies.authorizeUserAndInstances(context.context, {
285
+ action: 'send',
286
+ resourceKind: 'notification',
287
+ resourceId: notification.address,
288
+ markers: notification.markers,
289
+ userId: userId,
290
+ instances: request.instances,
291
+ });
292
+ if (authorization.success === false) {
293
+ return authorization;
294
+ }
295
+ const metrics = await this._checkSubscriptionMetrics('send', context.context, authorization, notification);
296
+ if (metrics.success === false) {
297
+ return metrics;
298
+ }
299
+ const pushSubs = await this.store.listActivePushSubscriptionsForNotification(recordName, notification.address);
300
+ if (typeof metrics.features.maxSentPushNotificationsPerPeriod ===
301
+ 'number') {
302
+ if (metrics.metrics.totalSentNotificationsInPeriod +
303
+ pushSubs.length >=
304
+ metrics.features.maxSentPushNotificationsPerPeriod) {
446
305
  return {
447
306
  success: false,
448
- errorCode: 'not_logged_in',
449
- errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
307
+ errorCode: 'subscription_limit_reached',
308
+ errorMessage: 'The maximum number of sent push notifications has been reached for this period.',
450
309
  };
451
310
  }
452
- const context = yield this.policies.constructAuthorizationContext({
453
- recordKeyOrRecordName: request.recordName,
454
- userId: request.userId,
455
- });
456
- if (context.success === false) {
457
- return context;
458
- }
459
- const recordName = context.context.recordName;
460
- const notification = yield this.store.getItemByAddress(recordName, request.address);
461
- if (!notification) {
462
- return {
463
- success: false,
464
- errorCode: 'data_not_found',
465
- errorMessage: 'Notification not found.',
466
- };
311
+ }
312
+ let promises = [];
313
+ const sentTimeMs = Date.now();
314
+ for (let push of pushSubs) {
315
+ promises.push(this._pushInterface
316
+ .sendNotification({
317
+ endpoint: push.endpoint,
318
+ keys: push.keys,
319
+ }, request.payload, request.topic)
320
+ .then((result) => {
321
+ return [push, result];
322
+ }));
323
+ }
324
+ const results = await Promise.allSettled(promises);
325
+ const notificationId = uuidv7();
326
+ await this.store.saveSentNotification({
327
+ id: notificationId,
328
+ recordName,
329
+ notificationAddress: notification.address,
330
+ title: request.payload.title,
331
+ body: request.payload.body,
332
+ icon: request.payload.icon,
333
+ badge: request.payload.badge,
334
+ defaultAction: request.payload.action,
335
+ actions: request.payload.actions,
336
+ silent: request.payload.silent,
337
+ tag: request.payload.tag,
338
+ timestamp: request.payload.timestamp,
339
+ sentTimeMs: sentTimeMs,
340
+ topic: request.topic,
341
+ });
342
+ let sentPushNotifications = [];
343
+ let failedPushSubscriptions = [];
344
+ for (let promiseResult of results) {
345
+ if (promiseResult.status === 'rejected') {
346
+ console.error('[NotificationRecordsController] Error sending notification:', promiseResult.reason);
467
347
  }
468
- const authorization = yield this.policies.authorizeUserAndInstances(context.context, {
469
- userId: request.userId,
470
- resourceKind: 'notification',
471
- markers: notification.markers,
472
- resourceId: notification.address,
473
- action: 'listSubscriptions',
474
- instances: request.instances,
475
- });
476
- if (authorization.success === false) {
477
- return authorization;
348
+ else {
349
+ const [push, result] = promiseResult.value;
350
+ sentPushNotifications.push({
351
+ id: uuidv7(),
352
+ pushSubscriptionId: push.id,
353
+ sentNotificationId: notificationId,
354
+ userId: push.userId,
355
+ subscriptionId: push.subscriptionId,
356
+ success: result.success,
357
+ errorCode: result.success === false ? result.errorCode : null,
358
+ });
359
+ if (result.success === false) {
360
+ console.error(`[NotificationRecordsController] Error sending notification for ${push.id}:`, result.errorCode);
361
+ if (result.errorCode === 'subscription_gone' ||
362
+ result.errorCode === 'subscription_not_found') {
363
+ failedPushSubscriptions.push(push.id);
364
+ }
365
+ }
478
366
  }
479
- const subscriptions = yield this.store.listSubscriptionsForNotification(recordName, request.address);
480
- return {
481
- success: true,
482
- subscriptions: subscriptions.map((sub) => ({
483
- id: sub.id,
484
- userId: sub.userId,
485
- recordName: sub.recordName,
486
- notificationAddress: sub.notificationAddress,
487
- pushSubscriptionId: sub.pushSubscriptionId,
488
- })),
489
- };
490
367
  }
491
- catch (err) {
492
- const span = trace.getActiveSpan();
493
- span === null || span === void 0 ? void 0 : span.recordException(err);
494
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
495
- console.error('[NotificationRecordsController] Error listing subscriptions for notification:', err);
368
+ if (sentPushNotifications.length > 0) {
369
+ await this.store.createSentPushNotifications(sentPushNotifications);
370
+ }
371
+ if (failedPushSubscriptions.length > 0) {
372
+ await this.store.markPushSubscriptionsInactiveAndDeleteUserRelations(failedPushSubscriptions);
373
+ }
374
+ console.log(`[NotificationRecordsController] [userId: ${userId} notificationId: ${notificationId} sent: ${sentPushNotifications.length} failed: ${failedPushSubscriptions.length}] Sent notification`);
375
+ return {
376
+ success: true,
377
+ };
378
+ }
379
+ catch (err) {
380
+ const span = trace.getActiveSpan();
381
+ span === null || span === void 0 ? void 0 : span.recordException(err);
382
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
383
+ console.error('[NotificationRecordsController] Error sending notification:', err);
384
+ return {
385
+ success: false,
386
+ errorCode: 'server_error',
387
+ errorMessage: 'A server error occurred.',
388
+ };
389
+ }
390
+ }
391
+ async listSubscriptionsForUser(request) {
392
+ try {
393
+ if (!request.userId) {
496
394
  return {
497
395
  success: false,
498
- errorCode: 'server_error',
499
- errorMessage: 'A server error occurred.',
396
+ errorCode: 'not_logged_in',
397
+ errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
500
398
  };
501
399
  }
502
- });
400
+ const subscriptions = await this.store.listSubscriptionsForUser(request.userId);
401
+ return {
402
+ success: true,
403
+ subscriptions: subscriptions.map((sub) => ({
404
+ id: sub.id,
405
+ userId: sub.userId,
406
+ recordName: sub.recordName,
407
+ notificationAddress: sub.notificationAddress,
408
+ pushSubscriptionId: sub.pushSubscriptionId,
409
+ })),
410
+ };
411
+ }
412
+ catch (err) {
413
+ const span = trace.getActiveSpan();
414
+ span === null || span === void 0 ? void 0 : span.recordException(err);
415
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
416
+ console.error('[NotificationRecordsController] Error listing subscriptions for user:', err);
417
+ return {
418
+ success: false,
419
+ errorCode: 'server_error',
420
+ errorMessage: 'A server error occurred.',
421
+ };
422
+ }
503
423
  }
504
- _checkSubscriptionMetrics(action, context, authorization, item) {
505
- return __awaiter(this, void 0, void 0, function* () {
506
- const config = yield this.config.getSubscriptionConfiguration();
507
- const metrics = yield this.store.getSubscriptionMetrics({
508
- ownerId: context.recordOwnerId,
509
- studioId: context.recordStudioId,
510
- });
511
- const features = getNotificationFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, metrics.subscriptionType, metrics.currentPeriodStartMs, metrics.currentPeriodEndMs);
512
- if (!features.allowed) {
424
+ async listSubscriptions(request) {
425
+ try {
426
+ if (!request.userId) {
513
427
  return {
514
428
  success: false,
515
- errorCode: 'not_authorized',
516
- errorMessage: 'Notifications are not allowed for this subscription.',
429
+ errorCode: 'not_logged_in',
430
+ errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
517
431
  };
518
432
  }
519
- if (action === 'create' && typeof features.maxItems === 'number') {
520
- if (metrics.totalItems >= features.maxItems) {
521
- return {
522
- success: false,
523
- errorCode: 'subscription_limit_reached',
524
- errorMessage: 'The maximum number of notification items has been reached for your subscription.',
525
- };
526
- }
433
+ const context = await this.policies.constructAuthorizationContext({
434
+ recordKeyOrRecordName: request.recordName,
435
+ userId: request.userId,
436
+ });
437
+ if (context.success === false) {
438
+ return context;
527
439
  }
528
- if (action === 'subscribe' &&
529
- typeof features.maxSubscribersPerItem === 'number') {
530
- const totalSubscriptions = yield this.store.countSubscriptionsForNotification(context.recordName, item.address);
531
- if (totalSubscriptions >= features.maxSubscribersPerItem) {
532
- return {
533
- success: false,
534
- errorCode: 'subscription_limit_reached',
535
- errorMessage: 'The maximum number of subscriptions has been reached for this notification.',
536
- };
537
- }
440
+ const recordName = context.context.recordName;
441
+ const notification = await this.store.getItemByAddress(recordName, request.address);
442
+ if (!notification) {
443
+ return {
444
+ success: false,
445
+ errorCode: 'data_not_found',
446
+ errorMessage: 'Notification not found.',
447
+ };
538
448
  }
539
- if (action === 'send') {
540
- if (typeof features.maxSentNotificationsPerPeriod === 'number' &&
541
- metrics.totalSentNotificationsInPeriod >=
542
- features.maxSentNotificationsPerPeriod) {
543
- return {
544
- success: false,
545
- errorCode: 'subscription_limit_reached',
546
- errorMessage: 'The maximum number of sent notifications has been reached for this period.',
547
- };
548
- }
449
+ const authorization = await this.policies.authorizeUserAndInstances(context.context, {
450
+ userId: request.userId,
451
+ resourceKind: 'notification',
452
+ markers: notification.markers,
453
+ resourceId: notification.address,
454
+ action: 'listSubscriptions',
455
+ instances: request.instances,
456
+ });
457
+ if (authorization.success === false) {
458
+ return authorization;
549
459
  }
460
+ const subscriptions = await this.store.listSubscriptionsForNotification(recordName, request.address);
550
461
  return {
551
462
  success: true,
552
- config,
553
- metrics,
554
- features,
463
+ subscriptions: subscriptions.map((sub) => ({
464
+ id: sub.id,
465
+ userId: sub.userId,
466
+ recordName: sub.recordName,
467
+ notificationAddress: sub.notificationAddress,
468
+ pushSubscriptionId: sub.pushSubscriptionId,
469
+ })),
470
+ };
471
+ }
472
+ catch (err) {
473
+ const span = trace.getActiveSpan();
474
+ span === null || span === void 0 ? void 0 : span.recordException(err);
475
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
476
+ console.error('[NotificationRecordsController] Error listing subscriptions for notification:', err);
477
+ return {
478
+ success: false,
479
+ errorCode: 'server_error',
480
+ errorMessage: 'A server error occurred.',
555
481
  };
482
+ }
483
+ }
484
+ async _checkSubscriptionMetrics(action, context, authorization, item) {
485
+ const config = await this.config.getSubscriptionConfiguration();
486
+ const metrics = await this.store.getSubscriptionMetrics({
487
+ ownerId: context.recordOwnerId,
488
+ studioId: context.recordStudioId,
556
489
  });
490
+ const features = getNotificationFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, metrics.subscriptionType, metrics.currentPeriodStartMs, metrics.currentPeriodEndMs);
491
+ if (!features.allowed) {
492
+ return {
493
+ success: false,
494
+ errorCode: 'not_authorized',
495
+ errorMessage: 'Notifications are not allowed for this subscription.',
496
+ };
497
+ }
498
+ if (action === 'create' && typeof features.maxItems === 'number') {
499
+ if (metrics.totalItems >= features.maxItems) {
500
+ return {
501
+ success: false,
502
+ errorCode: 'subscription_limit_reached',
503
+ errorMessage: 'The maximum number of notification items has been reached for your subscription.',
504
+ };
505
+ }
506
+ }
507
+ if (action === 'subscribe' &&
508
+ typeof features.maxSubscribersPerItem === 'number') {
509
+ const totalSubscriptions = await this.store.countSubscriptionsForNotification(context.recordName, item.address);
510
+ if (totalSubscriptions >= features.maxSubscribersPerItem) {
511
+ return {
512
+ success: false,
513
+ errorCode: 'subscription_limit_reached',
514
+ errorMessage: 'The maximum number of subscriptions has been reached for this notification.',
515
+ };
516
+ }
517
+ }
518
+ if (action === 'send') {
519
+ if (typeof features.maxSentNotificationsPerPeriod === 'number' &&
520
+ metrics.totalSentNotificationsInPeriod >=
521
+ features.maxSentNotificationsPerPeriod) {
522
+ return {
523
+ success: false,
524
+ errorCode: 'subscription_limit_reached',
525
+ errorMessage: 'The maximum number of sent notifications has been reached for this period.',
526
+ };
527
+ }
528
+ }
529
+ return {
530
+ success: true,
531
+ config,
532
+ metrics,
533
+ features,
534
+ };
557
535
  }
558
536
  }
559
537
  __decorate([