@casual-simulation/aux-records 3.4.6-alpha.14601027727 → 3.5.0-alpha.15117651144

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
@@ -0,0 +1,656 @@
1
+ /* CasualOS is a set of web-based tools designed to facilitate the creation of real-time, multi-user, context-aware interactive experiences.
2
+ *
3
+ * Copyright (c) 2019-2025 Casual Simulation, Inc.
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU Affero General Public License as
7
+ * published by the Free Software Foundation, either version 3 of the
8
+ * License, or (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU Affero General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License
16
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ 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;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ import { PRIVATE_MARKER, isPackageReviewerRole, } from '@casual-simulation/aux-common';
25
+ import { getMarkerResourcesForCreation, getMarkerResourcesForUpdate, } from '../../PolicyController';
26
+ import { getPackageFeatures } from '../../SubscriptionConfiguration';
27
+ import { getHash } from '@casual-simulation/crypto';
28
+ import { traced } from '../../tracing/TracingDecorators';
29
+ import { SpanStatusCode, trace } from '@opentelemetry/api';
30
+ import { v7 as uuid } from 'uuid';
31
+ import { isEqual } from 'lodash';
32
+ const TRACE_NAME = 'PackageVersionRecordsController';
33
+ /**
34
+ * Defines a controller that can be used to interact with NotificationRecords.
35
+ */
36
+ export class PackageVersionRecordsController {
37
+ get store() {
38
+ return this._store;
39
+ }
40
+ get config() {
41
+ return this._config;
42
+ }
43
+ get policies() {
44
+ return this._policies;
45
+ }
46
+ get files() {
47
+ return this._files;
48
+ }
49
+ constructor(config) {
50
+ this._name = 'PackageVersionRecordsController';
51
+ this._store = config.store;
52
+ this._recordStore = config.recordItemStore;
53
+ this._policies = config.policies;
54
+ this._packages = config.packages;
55
+ this._config = config.config;
56
+ this._files = config.files;
57
+ this._systemNotifications = config.systemNotifications;
58
+ this._resourceKind = 'package.version';
59
+ }
60
+ /**
61
+ * Creates or updates an item in the given record.
62
+ * @param request The request.
63
+ */
64
+ async recordItem(request) {
65
+ var _a, _b;
66
+ try {
67
+ const contextResult = await this._policies.constructAuthorizationContext({
68
+ recordKeyOrRecordName: request.recordKeyOrRecordName,
69
+ userId: request.userId,
70
+ });
71
+ if (contextResult.success === false) {
72
+ return contextResult;
73
+ }
74
+ const recordName = contextResult.context.recordName;
75
+ const existingItem = await this._store.getItemByKey(recordName, request.item.address, request.item.key);
76
+ let parentMarkers;
77
+ if (!existingItem.parentMarkers) {
78
+ console.log(`[${this._name}] Parent package not found.`);
79
+ parentMarkers = [PRIVATE_MARKER];
80
+ const result = await this._packages.recordItem({
81
+ userId: request.userId,
82
+ recordKeyOrRecordName: recordName,
83
+ instances: request.instances,
84
+ item: {
85
+ address: request.item.address,
86
+ markers: parentMarkers,
87
+ },
88
+ });
89
+ if (result.success === false) {
90
+ return result;
91
+ }
92
+ else {
93
+ console.log(`[${this._name}] Created parent package ${request.item.address}`);
94
+ }
95
+ }
96
+ else {
97
+ parentMarkers = existingItem.parentMarkers;
98
+ }
99
+ let resourceMarkers;
100
+ let action = existingItem.item
101
+ ? 'update'
102
+ : 'create';
103
+ let authorization;
104
+ if (action === 'update') {
105
+ const existingMarkers = existingItem.item.markers;
106
+ resourceMarkers = (_a = request.item.markers) !== null && _a !== void 0 ? _a : existingMarkers;
107
+ // resourceMarkers = existingItem.item.markers;
108
+ action = 'update';
109
+ authorization =
110
+ await this._policies.authorizeUserAndInstancesForResources(contextResult.context, {
111
+ userId: request.userId,
112
+ instances: request.instances,
113
+ resources: [
114
+ {
115
+ resourceKind: this._resourceKind,
116
+ resourceId: existingItem.item.address,
117
+ action: action,
118
+ markers: resourceMarkers,
119
+ },
120
+ ...getMarkerResourcesForUpdate(existingMarkers, resourceMarkers),
121
+ ],
122
+ });
123
+ if (authorization.success === false) {
124
+ return authorization;
125
+ }
126
+ }
127
+ else {
128
+ // TODO: Allow these markers to be inherited from the parent package.
129
+ // When the markers are inherited, then the user shouldn't need permission to assign them.
130
+ let usingGivenMarkers = true;
131
+ resourceMarkers = request.item.markers;
132
+ if (!resourceMarkers) {
133
+ resourceMarkers = parentMarkers;
134
+ usingGivenMarkers = false;
135
+ }
136
+ let resources = [
137
+ {
138
+ resourceKind: this._resourceKind,
139
+ resourceId: request.item.address,
140
+ action: action,
141
+ markers: resourceMarkers,
142
+ },
143
+ ];
144
+ if (!usingGivenMarkers) {
145
+ resources.push(...getMarkerResourcesForCreation(resourceMarkers));
146
+ }
147
+ // TODO: Make sure that whenever the user is selecting markers that they also have permissions to
148
+ // assign the markers they are selecting.
149
+ authorization =
150
+ await this._policies.authorizeUserAndInstancesForResources(contextResult.context, {
151
+ userId: request.userId,
152
+ instances: request.instances,
153
+ resources,
154
+ });
155
+ if (authorization.success === false) {
156
+ return authorization;
157
+ }
158
+ }
159
+ if (!resourceMarkers || resourceMarkers.length <= 0) {
160
+ return {
161
+ success: false,
162
+ errorCode: 'invalid_request',
163
+ errorMessage: 'The item must have markers.',
164
+ };
165
+ }
166
+ const subscriptionResult = await this._checkSubscriptionMetrics(action, contextResult.context, authorization, request.item);
167
+ if (subscriptionResult.success === false) {
168
+ return subscriptionResult;
169
+ }
170
+ if (action === 'update') {
171
+ const sizeInBytes = request.item.auxFileRequest.fileByteLength;
172
+ const fileName = existingItem.item.auxFileName;
173
+ const sha256 = getHash({
174
+ auxFileName: fileName,
175
+ auxSha256: request.item.auxFileRequest.fileSha256Hex,
176
+ createdAtMs: existingItem.item.createdAtMs,
177
+ entitlements: request.item.entitlements,
178
+ description: request.item.description,
179
+ sizeInBytes: sizeInBytes,
180
+ });
181
+ if (sha256 !== existingItem.item.sha256) {
182
+ return {
183
+ success: false,
184
+ errorCode: 'not_supported',
185
+ errorMessage: 'Updating package versions is not supported.',
186
+ };
187
+ }
188
+ }
189
+ // TODO: File records should always be private if the system is creating them
190
+ // so that the file can only be accessed via the package version API unless the user has access
191
+ // to private items.
192
+ //record file
193
+ let recordFileResult = await this.files.recordFile(recordName, null, {
194
+ ...request.item.auxFileRequest,
195
+ markers: [PRIVATE_MARKER],
196
+ instances: request.instances,
197
+ userRole: 'system',
198
+ });
199
+ if (recordFileResult.success === false) {
200
+ if (recordFileResult.errorCode === 'file_already_exists') {
201
+ // Retry the request to see if the user has the ability to upload to a file record
202
+ // that has already been made but may not yet be uploaded.
203
+ // If the file record has been made, but not uplaoded, then this will succeed.
204
+ recordFileResult = await this.files.recordFile(recordName, contextResult.context.userId, {
205
+ ...request.item.auxFileRequest,
206
+ markers: resourceMarkers,
207
+ instances: request.instances,
208
+ });
209
+ }
210
+ if (recordFileResult.success === false &&
211
+ recordFileResult.errorCode !== 'file_already_exists') {
212
+ return recordFileResult;
213
+ // if (recordFileResult.errorCode === 'file_already_exists') {
214
+ // // TODO:
215
+ // // If the file already exists and has already been uploaded, then
216
+ // // we should see if we need to update the file record markers to match the package version markers.
217
+ // // if(recordFileResult.existingFileName) {
218
+ // // }
219
+ // } else {
220
+ // return recordFileResult;
221
+ // }
222
+ }
223
+ }
224
+ else if (!isEqual(recordFileResult.markers, [PRIVATE_MARKER])) {
225
+ // System is able to upload the file, but the file record has already been made with different markers and not uploaded.
226
+ // In this case, we want to retry the request but with the user so that we can be sure the user has permission to upload the file.
227
+ // Retry the request to see if the user has the ability to upload to a file record
228
+ // that has already been made but may not yet be uploaded.
229
+ // If the file record has been made, but not uplaoded, then this will succeed.
230
+ recordFileResult = await this.files.recordFile(recordName, contextResult.context.userId, {
231
+ ...request.item.auxFileRequest,
232
+ markers: resourceMarkers,
233
+ instances: request.instances,
234
+ });
235
+ if (recordFileResult.success === false &&
236
+ recordFileResult.errorCode !== 'file_already_exists') {
237
+ return recordFileResult;
238
+ }
239
+ }
240
+ const address = request.item.address;
241
+ let item;
242
+ if (action === 'create') {
243
+ const createdAtMs = Date.now();
244
+ const sizeInBytes = request.item.auxFileRequest.fileByteLength;
245
+ const fileName = recordFileResult.success === true
246
+ ? recordFileResult.fileName
247
+ : recordFileResult.existingFileName;
248
+ if (!fileName) {
249
+ throw new Error('Unable to determine file name for package');
250
+ }
251
+ const sha256 = getHash({
252
+ auxFileName: fileName,
253
+ auxSha256: request.item.auxFileRequest.fileSha256Hex,
254
+ createdAtMs: createdAtMs,
255
+ entitlements: request.item.entitlements,
256
+ description: request.item.description,
257
+ sizeInBytes: sizeInBytes,
258
+ });
259
+ item = {
260
+ id: uuid(),
261
+ address: address,
262
+ entitlements: request.item.entitlements,
263
+ key: request.item.key,
264
+ description: request.item.description,
265
+ auxFileName: fileName,
266
+ auxSha256: request.item.auxFileRequest.fileSha256Hex,
267
+ sha256,
268
+ sizeInBytes,
269
+ createdAtMs,
270
+ createdFile: recordFileResult.success,
271
+ requiresReview: request.item.entitlements.some((e) => entitlementRequiresApproval(e)),
272
+ markers: resourceMarkers,
273
+ };
274
+ const crudResult = await this._store.putItem(recordName, item);
275
+ if (crudResult.success === false) {
276
+ return crudResult;
277
+ }
278
+ await ((_b = this._systemNotifications) === null || _b === void 0 ? void 0 : _b.sendRecordNotification({
279
+ resource: 'package_version_publish',
280
+ action: 'created',
281
+ recordName: recordName,
282
+ resourceId: address,
283
+ timeMs: createdAtMs,
284
+ package: item,
285
+ markers: resourceMarkers,
286
+ }));
287
+ }
288
+ else {
289
+ item = {
290
+ ...existingItem.item,
291
+ markers: resourceMarkers,
292
+ };
293
+ const crudResult = await this._store.putItem(recordName, item);
294
+ if (crudResult.success === false) {
295
+ return crudResult;
296
+ }
297
+ }
298
+ return {
299
+ success: true,
300
+ recordName,
301
+ address: item.address,
302
+ auxFileResult: recordFileResult,
303
+ };
304
+ }
305
+ catch (err) {
306
+ const span = trace.getActiveSpan();
307
+ if (err instanceof Error) {
308
+ span === null || span === void 0 ? void 0 : span.recordException(err);
309
+ }
310
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
311
+ console.error(`[${this._name}] Error recording item:`, err);
312
+ return {
313
+ success: false,
314
+ errorCode: 'server_error',
315
+ errorMessage: 'A server error occurred.',
316
+ };
317
+ }
318
+ }
319
+ /**
320
+ * Gets the item with the given address from the given record.
321
+ * @param request The request to get the item.
322
+ */
323
+ async getItem(request) {
324
+ var _a, _b;
325
+ try {
326
+ const baseRequest = {
327
+ recordKeyOrRecordName: request.recordName,
328
+ userId: request.userId,
329
+ instances: request.instances,
330
+ };
331
+ const context = await this._policies.constructAuthorizationContext(baseRequest);
332
+ if (context.success === false) {
333
+ return context;
334
+ }
335
+ const result = await this._store.getItemBySpecifier(context.context.recordName, request.address, request.key);
336
+ if (!result.item) {
337
+ return {
338
+ success: false,
339
+ errorCode: 'data_not_found',
340
+ errorMessage: 'The item was not found.',
341
+ };
342
+ }
343
+ const markers = result.parentMarkers;
344
+ const authorization = await this._policies.authorizeUserAndInstances(context.context, {
345
+ userId: request.userId,
346
+ instances: request.instances,
347
+ resourceKind: this._resourceKind,
348
+ resourceId: request.address,
349
+ action: 'read',
350
+ markers: markers,
351
+ });
352
+ if (authorization.success === false) {
353
+ return authorization;
354
+ }
355
+ const item = {
356
+ id: result.item.id,
357
+ address: result.item.address,
358
+ key: result.item.key,
359
+ auxFileName: result.item.auxFileName,
360
+ createdAtMs: result.item.createdAtMs,
361
+ auxSha256: result.item.auxSha256,
362
+ createdFile: result.item.createdFile,
363
+ entitlements: result.item.entitlements,
364
+ markers: result.item.markers,
365
+ description: result.item.description,
366
+ requiresReview: result.item.requiresReview,
367
+ sha256: result.item.sha256,
368
+ sizeInBytes: result.item.sizeInBytes,
369
+ packageId: result.packageId,
370
+ approved: true,
371
+ approvalType: 'normal',
372
+ };
373
+ if (item.requiresReview) {
374
+ let review = await this.store.getMostRecentPackageVersionReview(item.id);
375
+ item.approved = (_a = review === null || review === void 0 ? void 0 : review.approved) !== null && _a !== void 0 ? _a : false;
376
+ item.approvalType = (_b = review === null || review === void 0 ? void 0 : review.approvalType) !== null && _b !== void 0 ? _b : null;
377
+ }
378
+ const auxFile = item.createdFile
379
+ ? await this.files.readFile(context.context.recordName, item.auxFileName, null, undefined, 'system')
380
+ : await this.files.readFile(context.context.recordName, item.auxFileName, context.context.userId);
381
+ return {
382
+ success: true,
383
+ item: item,
384
+ auxFile,
385
+ };
386
+ }
387
+ catch (err) {
388
+ const span = trace.getActiveSpan();
389
+ if (err instanceof Error) {
390
+ span === null || span === void 0 ? void 0 : span.recordException(err);
391
+ }
392
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
393
+ console.error(`[${this._name}] Error getting item:`, err);
394
+ return {
395
+ success: false,
396
+ errorCode: 'server_error',
397
+ errorMessage: 'A server error occurred.',
398
+ };
399
+ }
400
+ }
401
+ /**
402
+ * Deletes the item with the given address from the given record.
403
+ * @param request The request.
404
+ */
405
+ async eraseItem(request) {
406
+ try {
407
+ const context = await this._policies.constructAuthorizationContext({
408
+ recordKeyOrRecordName: request.recordName,
409
+ userId: request.userId,
410
+ });
411
+ if (context.success === false) {
412
+ return context;
413
+ }
414
+ const result = await this._store.getItemByKey(context.context.recordName, request.address, request.key);
415
+ if (!result.item || !result.parentMarkers) {
416
+ return {
417
+ success: false,
418
+ errorCode: 'data_not_found',
419
+ errorMessage: 'The item was not found.',
420
+ };
421
+ }
422
+ const markers = result.parentMarkers;
423
+ const authorization = await this._policies.authorizeUserAndInstances(context.context, {
424
+ userId: request.userId,
425
+ instances: request.instances,
426
+ resourceKind: this._resourceKind,
427
+ resourceId: request.address,
428
+ action: 'delete',
429
+ markers,
430
+ });
431
+ if (authorization.success === false) {
432
+ return authorization;
433
+ }
434
+ const recordName = context.context.recordName;
435
+ const subscriptionResult = await this._checkSubscriptionMetrics('delete', context.context, authorization);
436
+ if (subscriptionResult.success === false) {
437
+ return subscriptionResult;
438
+ }
439
+ await this._store.deleteItem(recordName, request.address, request.key);
440
+ return {
441
+ success: true,
442
+ };
443
+ }
444
+ catch (err) {
445
+ const span = trace.getActiveSpan();
446
+ if (err instanceof Error) {
447
+ span === null || span === void 0 ? void 0 : span.recordException(err);
448
+ }
449
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
450
+ console.error(`[${this._name}] Error erasing item:`, err);
451
+ return {
452
+ success: false,
453
+ errorCode: 'server_error',
454
+ errorMessage: 'A server error occurred.',
455
+ };
456
+ }
457
+ }
458
+ /**
459
+ * Lists items in the given record.
460
+ * @param request The request.
461
+ */
462
+ async listItems(request) {
463
+ try {
464
+ const baseRequest = {
465
+ recordKeyOrRecordName: request.recordName,
466
+ userId: request.userId,
467
+ instances: request.instances,
468
+ };
469
+ const context = await this._policies.constructAuthorizationContext(baseRequest);
470
+ if (context.success === false) {
471
+ return context;
472
+ }
473
+ const recordName = context.context.recordName;
474
+ const packageRecord = await this._recordStore.getItemByAddress(recordName, request.address);
475
+ if (!packageRecord) {
476
+ return {
477
+ success: false,
478
+ errorCode: 'data_not_found',
479
+ errorMessage: 'The parent item was not found.',
480
+ };
481
+ }
482
+ const authorization = await this._policies.authorizeUserAndInstances(context.context, {
483
+ userId: request.userId,
484
+ instances: request.instances,
485
+ resourceKind: this._resourceKind,
486
+ action: 'list',
487
+ markers: packageRecord.markers,
488
+ });
489
+ if (authorization.success === false) {
490
+ return authorization;
491
+ }
492
+ const result2 = await this._store.listItems(context.context.recordName, request.address);
493
+ return {
494
+ success: true,
495
+ recordName: context.context.recordName,
496
+ items: result2.items.map((item) => item),
497
+ totalCount: result2.totalCount,
498
+ };
499
+ }
500
+ catch (err) {
501
+ const span = trace.getActiveSpan();
502
+ if (err instanceof Error) {
503
+ span === null || span === void 0 ? void 0 : span.recordException(err);
504
+ }
505
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
506
+ console.error(`[${this._name}] Error listing items:`, err);
507
+ return {
508
+ success: false,
509
+ errorCode: 'server_error',
510
+ errorMessage: 'A server error occurred.',
511
+ };
512
+ }
513
+ }
514
+ async reviewItem(request) {
515
+ var _a;
516
+ try {
517
+ const packageVersion = await this.store.getItemById(request.packageVersionId);
518
+ if (!packageVersion.item || !packageVersion.recordName) {
519
+ return {
520
+ success: false,
521
+ errorCode: 'not_found',
522
+ errorMessage: 'The package version was not found.',
523
+ };
524
+ }
525
+ const baseRequest = {
526
+ recordKeyOrRecordName: packageVersion.recordName,
527
+ userId: request.userId,
528
+ userRole: request.userRole,
529
+ sendNotLoggedIn: true,
530
+ };
531
+ const context = await this._policies.constructAuthorizationContext(baseRequest);
532
+ if (context.success === false) {
533
+ return context;
534
+ }
535
+ if (!isPackageReviewerRole(context.context.userRole)) {
536
+ return {
537
+ success: false,
538
+ errorCode: 'not_authorized',
539
+ errorMessage: 'You are not authorized to submit reviews for package versions.',
540
+ };
541
+ }
542
+ const now = Date.now();
543
+ const reviewId = (_a = request.review.id) !== null && _a !== void 0 ? _a : uuid();
544
+ const result = await this.store.putReviewForVersion({
545
+ id: reviewId,
546
+ packageVersionId: request.packageVersionId,
547
+ approved: request.review.approved,
548
+ approvalType: request.review.approvalType,
549
+ reviewComments: request.review.reviewComments,
550
+ reviewingUserId: context.context.userId,
551
+ reviewStatus: request.review.reviewStatus,
552
+ createdAtMs: now,
553
+ updatedAtMs: now,
554
+ });
555
+ if (result.success === false) {
556
+ return result;
557
+ }
558
+ return {
559
+ success: true,
560
+ reviewId: reviewId,
561
+ };
562
+ }
563
+ catch (err) {
564
+ const span = trace.getActiveSpan();
565
+ if (err instanceof Error) {
566
+ span === null || span === void 0 ? void 0 : span.recordException(err);
567
+ }
568
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
569
+ console.error(`[${this._name}] Error reviewing item:`, err);
570
+ return {
571
+ success: false,
572
+ errorCode: 'server_error',
573
+ errorMessage: 'A server error occurred.',
574
+ };
575
+ }
576
+ }
577
+ async _checkSubscriptionMetrics(action, context, authorization, item) {
578
+ var _a, _b;
579
+ const config = await this.config.getSubscriptionConfiguration();
580
+ const metrics = await this.store.getSubscriptionMetrics({
581
+ ownerId: (_a = context.recordOwnerId) !== null && _a !== void 0 ? _a : undefined,
582
+ studioId: (_b = context.recordStudioId) !== null && _b !== void 0 ? _b : undefined,
583
+ });
584
+ const features = getPackageFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, metrics.subscriptionType, metrics.currentPeriodStartMs, metrics.currentPeriodEndMs);
585
+ if (!features.allowed) {
586
+ return {
587
+ success: false,
588
+ errorCode: 'not_authorized',
589
+ errorMessage: 'Packages are not allowed for this subscription.',
590
+ };
591
+ }
592
+ if (action === 'create') {
593
+ if (typeof features.maxPackageVersions === 'number') {
594
+ if (metrics.totalItems >= features.maxPackageVersions) {
595
+ return {
596
+ success: false,
597
+ errorCode: 'subscription_limit_reached',
598
+ errorMessage: 'The maximum number of package versions has been reached for your subscription.',
599
+ };
600
+ }
601
+ }
602
+ if (typeof features.maxPackageVersionSizeInBytes === 'number' &&
603
+ item &&
604
+ item.auxFileRequest.fileByteLength >=
605
+ features.maxPackageVersionSizeInBytes) {
606
+ return {
607
+ success: false,
608
+ errorCode: 'subscription_limit_reached',
609
+ errorMessage: 'The package version is too large for your subscription.',
610
+ };
611
+ }
612
+ if (action === 'create' &&
613
+ typeof features.maxPackageBytesTotal === 'number') {
614
+ if (item &&
615
+ metrics.totalPackageVersionBytes +
616
+ item.auxFileRequest.fileByteLength >=
617
+ features.maxPackageBytesTotal) {
618
+ return {
619
+ success: false,
620
+ errorCode: 'subscription_limit_reached',
621
+ errorMessage: 'The maximum size of package versions has been reached for your subscription.',
622
+ };
623
+ }
624
+ }
625
+ }
626
+ return {
627
+ success: true,
628
+ config,
629
+ metrics,
630
+ features,
631
+ };
632
+ }
633
+ }
634
+ __decorate([
635
+ traced(TRACE_NAME)
636
+ ], PackageVersionRecordsController.prototype, "recordItem", null);
637
+ __decorate([
638
+ traced(TRACE_NAME)
639
+ ], PackageVersionRecordsController.prototype, "getItem", null);
640
+ __decorate([
641
+ traced(TRACE_NAME)
642
+ ], PackageVersionRecordsController.prototype, "eraseItem", null);
643
+ __decorate([
644
+ traced(TRACE_NAME)
645
+ ], PackageVersionRecordsController.prototype, "listItems", null);
646
+ __decorate([
647
+ traced(TRACE_NAME)
648
+ ], PackageVersionRecordsController.prototype, "reviewItem", null);
649
+ /**
650
+ * Determines whether the given entitlement requires approval.
651
+ * @param entitlement The entitlement to test.
652
+ */
653
+ export function entitlementRequiresApproval(entitlement) {
654
+ return entitlement.scope === 'shared' || entitlement.scope === 'designated';
655
+ }
656
+ //# sourceMappingURL=PackageVersionRecordsController.js.map