monorise 0.1.0 → 1.1.0-dev.0

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 (275) hide show
  1. package/dist/base/index.d.ts +90 -5
  2. package/dist/base/index.js.map +1 -1
  3. package/dist/cli/cli.js +6 -0
  4. package/dist/cli/cli.js.map +1 -1
  5. package/dist/core/chunk-QV4Q5377.js +76 -0
  6. package/dist/core/chunk-QV4Q5377.js.map +1 -0
  7. package/dist/core/index.d.ts +187 -19
  8. package/dist/core/index.js +1583 -85
  9. package/dist/core/index.js.map +1 -1
  10. package/dist/core/service.config-ZJEZ6EKA.js +13 -0
  11. package/dist/core/service.config-ZJEZ6EKA.js.map +1 -0
  12. package/dist/proxy/index.d.ts +35 -0
  13. package/dist/proxy/index.js +75 -0
  14. package/dist/proxy/index.js.map +1 -0
  15. package/dist/react/actions/websocket.action.d.ts +71 -0
  16. package/dist/react/actions/websocket.action.d.ts.map +1 -0
  17. package/dist/react/chunk-4D22OCZG.js +65 -0
  18. package/dist/react/chunk-4D22OCZG.js.map +1 -0
  19. package/dist/react/chunk-4N3P4ONH.js +588 -0
  20. package/dist/react/chunk-4N3P4ONH.js.map +1 -0
  21. package/dist/react/chunk-4Y4KWGJD.js +182 -0
  22. package/dist/react/chunk-4Y4KWGJD.js.map +1 -0
  23. package/dist/react/chunk-757E5UYA.js +893 -0
  24. package/dist/react/chunk-757E5UYA.js.map +1 -0
  25. package/dist/react/chunk-A5TI2FW3.js +13 -0
  26. package/dist/react/chunk-A5TI2FW3.js.map +1 -0
  27. package/dist/react/chunk-B3XDGUFO.js +489 -0
  28. package/dist/react/chunk-B3XDGUFO.js.map +1 -0
  29. package/dist/react/chunk-BPBCUO2Z.js +248 -0
  30. package/dist/react/chunk-BPBCUO2Z.js.map +1 -0
  31. package/dist/react/chunk-CQBOIXWK.js +142 -0
  32. package/dist/react/chunk-CQBOIXWK.js.map +1 -0
  33. package/dist/react/chunk-DRH2BB7I.js +383 -0
  34. package/dist/react/chunk-DRH2BB7I.js.map +1 -0
  35. package/dist/react/chunk-EQ3PKQ2S.js +402 -0
  36. package/dist/react/chunk-EQ3PKQ2S.js.map +1 -0
  37. package/dist/react/chunk-H64MMAL7.js +245 -0
  38. package/dist/react/chunk-H64MMAL7.js.map +1 -0
  39. package/dist/react/chunk-KJX5LOMN.js +43 -0
  40. package/dist/react/chunk-KJX5LOMN.js.map +1 -0
  41. package/dist/react/chunk-MO35V2Y7.js +172 -0
  42. package/dist/react/chunk-MO35V2Y7.js.map +1 -0
  43. package/dist/react/chunk-UC3E72G7.js +73 -0
  44. package/dist/react/chunk-UC3E72G7.js.map +1 -0
  45. package/dist/react/chunk-UHMKB3OR.js +5568 -0
  46. package/dist/react/chunk-UHMKB3OR.js.map +1 -0
  47. package/dist/react/chunk-UQPQBWEQ.js +54 -0
  48. package/dist/react/chunk-UQPQBWEQ.js.map +1 -0
  49. package/dist/react/chunk-XCDCVRJR.js +43 -0
  50. package/dist/react/chunk-XCDCVRJR.js.map +1 -0
  51. package/dist/react/chunk-XOYAZDIH.js +47 -0
  52. package/dist/react/chunk-XOYAZDIH.js.map +1 -0
  53. package/dist/react/chunk-YNFQEPO5.js +29 -0
  54. package/dist/react/chunk-YNFQEPO5.js.map +1 -0
  55. package/dist/react/dist-es-35AO47NO.js +90 -0
  56. package/dist/react/dist-es-35AO47NO.js.map +1 -0
  57. package/dist/react/dist-es-5GDBXNKQ.js +333 -0
  58. package/dist/react/dist-es-5GDBXNKQ.js.map +1 -0
  59. package/dist/react/dist-es-B3JDGWY6.js +71 -0
  60. package/dist/react/dist-es-B3JDGWY6.js.map +1 -0
  61. package/dist/react/dist-es-IWIE5JLA.js +169 -0
  62. package/dist/react/dist-es-IWIE5JLA.js.map +1 -0
  63. package/dist/react/dist-es-NRIS3TYJ.js +494 -0
  64. package/dist/react/dist-es-NRIS3TYJ.js.map +1 -0
  65. package/dist/react/dist-es-VCXAEYYN.js +22 -0
  66. package/dist/react/dist-es-VCXAEYYN.js.map +1 -0
  67. package/dist/react/dist-es-VU33JFTZ.js +379 -0
  68. package/dist/react/dist-es-VU33JFTZ.js.map +1 -0
  69. package/dist/react/event-streams-OSOTOTTP.js +277 -0
  70. package/dist/react/event-streams-OSOTOTTP.js.map +1 -0
  71. package/dist/react/index.d.ts +53 -4
  72. package/dist/react/index.d.ts.map +1 -1
  73. package/dist/react/index.js +10948 -190
  74. package/dist/react/index.js.map +1 -1
  75. package/dist/react/loadSso-ME7MKAM3.js +556 -0
  76. package/dist/react/loadSso-ME7MKAM3.js.map +1 -0
  77. package/dist/react/service.config-ZJEZ6EKA-FC2TR3GH.js +14 -0
  78. package/dist/react/service.config-ZJEZ6EKA-FC2TR3GH.js.map +1 -0
  79. package/dist/react/services/core.service.d.ts +11 -1
  80. package/dist/react/services/core.service.d.ts.map +1 -1
  81. package/dist/react/signin-LOXYIE5I.js +653 -0
  82. package/dist/react/signin-LOXYIE5I.js.map +1 -0
  83. package/dist/react/sso-oidc-X63KRRLO.js +786 -0
  84. package/dist/react/sso-oidc-X63KRRLO.js.map +1 -0
  85. package/dist/react/sts-OXBEY7HY.js +3948 -0
  86. package/dist/react/sts-OXBEY7HY.js.map +1 -0
  87. package/dist/react/websocket/WebSocketManager.d.ts +68 -0
  88. package/dist/react/websocket/WebSocketManager.d.ts.map +1 -0
  89. package/dist/react/websocket/index.d.ts +3 -0
  90. package/dist/react/websocket/index.d.ts.map +1 -0
  91. package/dist/react/websocket/optimistic.d.ts +51 -0
  92. package/dist/react/websocket/optimistic.d.ts.map +1 -0
  93. package/dist/react/websocket-QHA7SQXG.js +10 -0
  94. package/dist/react/websocket-QHA7SQXG.js.map +1 -0
  95. package/dist/sst/.sst/platform/src/components/aws/alb.d.ts +280 -0
  96. package/dist/sst/.sst/platform/src/components/aws/alb.d.ts.map +1 -0
  97. package/dist/sst/.sst/platform/src/components/aws/apigateway-websocket-route.d.ts +1 -1
  98. package/dist/sst/.sst/platform/src/components/aws/apigateway-websocket-route.d.ts.map +1 -1
  99. package/dist/sst/.sst/platform/src/components/aws/apigateway-websocket.d.ts +13 -2
  100. package/dist/sst/.sst/platform/src/components/aws/apigateway-websocket.d.ts.map +1 -1
  101. package/dist/sst/.sst/platform/src/components/aws/apigatewayv1-authorizer.d.ts.map +1 -1
  102. package/dist/sst/.sst/platform/src/components/aws/apigatewayv1-lambda-route.d.ts +1 -1
  103. package/dist/sst/.sst/platform/src/components/aws/apigatewayv1-lambda-route.d.ts.map +1 -1
  104. package/dist/sst/.sst/platform/src/components/aws/apigatewayv1.d.ts +93 -83
  105. package/dist/sst/.sst/platform/src/components/aws/apigatewayv1.d.ts.map +1 -1
  106. package/dist/sst/.sst/platform/src/components/aws/apigatewayv2-authorizer.d.ts.map +1 -1
  107. package/dist/sst/.sst/platform/src/components/aws/apigatewayv2-lambda-route.d.ts +1 -1
  108. package/dist/sst/.sst/platform/src/components/aws/apigatewayv2-lambda-route.d.ts.map +1 -1
  109. package/dist/sst/.sst/platform/src/components/aws/apigatewayv2.d.ts +8 -2
  110. package/dist/sst/.sst/platform/src/components/aws/apigatewayv2.d.ts.map +1 -1
  111. package/dist/sst/.sst/platform/src/components/aws/app-sync-data-source.d.ts +1 -1
  112. package/dist/sst/.sst/platform/src/components/aws/app-sync-data-source.d.ts.map +1 -1
  113. package/dist/sst/.sst/platform/src/components/aws/app-sync.d.ts +1 -1
  114. package/dist/sst/.sst/platform/src/components/aws/app-sync.d.ts.map +1 -1
  115. package/dist/sst/.sst/platform/src/components/aws/aurora.d.ts +18 -0
  116. package/dist/sst/.sst/platform/src/components/aws/aurora.d.ts.map +1 -1
  117. package/dist/sst/.sst/platform/src/components/aws/auth-v1.d.ts +1 -1
  118. package/dist/sst/.sst/platform/src/components/aws/auth-v1.d.ts.map +1 -1
  119. package/dist/sst/.sst/platform/src/components/aws/auth.d.ts.map +1 -1
  120. package/dist/sst/.sst/platform/src/components/aws/bucket-lambda-subscriber.d.ts +1 -1
  121. package/dist/sst/.sst/platform/src/components/aws/bucket-lambda-subscriber.d.ts.map +1 -1
  122. package/dist/sst/.sst/platform/src/components/aws/bucket-notification.d.ts.map +1 -1
  123. package/dist/sst/.sst/platform/src/components/aws/bucket.d.ts +13 -8
  124. package/dist/sst/.sst/platform/src/components/aws/bucket.d.ts.map +1 -1
  125. package/dist/sst/.sst/platform/src/components/aws/bus-lambda-subscriber.d.ts +3 -2
  126. package/dist/sst/.sst/platform/src/components/aws/bus-lambda-subscriber.d.ts.map +1 -1
  127. package/dist/sst/.sst/platform/src/components/aws/bus.d.ts +34 -3
  128. package/dist/sst/.sst/platform/src/components/aws/bus.d.ts.map +1 -1
  129. package/dist/sst/.sst/platform/src/components/aws/cdn.d.ts +11 -0
  130. package/dist/sst/.sst/platform/src/components/aws/cdn.d.ts.map +1 -1
  131. package/dist/sst/.sst/platform/src/components/aws/cluster.d.ts +59 -1
  132. package/dist/sst/.sst/platform/src/components/aws/cluster.d.ts.map +1 -1
  133. package/dist/sst/.sst/platform/src/components/aws/cognito-identity-pool.d.ts +5 -0
  134. package/dist/sst/.sst/platform/src/components/aws/cognito-identity-pool.d.ts.map +1 -1
  135. package/dist/sst/.sst/platform/src/components/aws/cognito-user-pool.d.ts +100 -0
  136. package/dist/sst/.sst/platform/src/components/aws/cognito-user-pool.d.ts.map +1 -1
  137. package/dist/sst/.sst/platform/src/components/aws/cron-v2.d.ts +325 -0
  138. package/dist/sst/.sst/platform/src/components/aws/cron-v2.d.ts.map +1 -0
  139. package/dist/sst/.sst/platform/src/components/aws/cron.d.ts +15 -6
  140. package/dist/sst/.sst/platform/src/components/aws/cron.d.ts.map +1 -1
  141. package/dist/sst/.sst/platform/src/components/aws/dsql.d.ts +369 -0
  142. package/dist/sst/.sst/platform/src/components/aws/dsql.d.ts.map +1 -0
  143. package/dist/sst/.sst/platform/src/components/aws/dynamo-lambda-subscriber.d.ts +1 -1
  144. package/dist/sst/.sst/platform/src/components/aws/dynamo-lambda-subscriber.d.ts.map +1 -1
  145. package/dist/sst/.sst/platform/src/components/aws/dynamo.d.ts +63 -3
  146. package/dist/sst/.sst/platform/src/components/aws/dynamo.d.ts.map +1 -1
  147. package/dist/sst/.sst/platform/src/components/aws/email.d.ts +5 -0
  148. package/dist/sst/.sst/platform/src/components/aws/email.d.ts.map +1 -1
  149. package/dist/sst/.sst/platform/src/components/aws/fargate.d.ts +95 -4
  150. package/dist/sst/.sst/platform/src/components/aws/fargate.d.ts.map +1 -1
  151. package/dist/sst/.sst/platform/src/components/aws/function.d.ts +121 -21
  152. package/dist/sst/.sst/platform/src/components/aws/function.d.ts.map +1 -1
  153. package/dist/sst/.sst/platform/src/components/aws/helpers/arn.d.ts +11 -0
  154. package/dist/sst/.sst/platform/src/components/aws/helpers/arn.d.ts.map +1 -1
  155. package/dist/sst/.sst/platform/src/components/aws/helpers/container-builder.d.ts.map +1 -1
  156. package/dist/sst/.sst/platform/src/components/aws/helpers/function-builder.d.ts +7 -3
  157. package/dist/sst/.sst/platform/src/components/aws/helpers/function-builder.d.ts.map +1 -1
  158. package/dist/sst/.sst/platform/src/components/aws/helpers/load-balancer.d.ts +9 -0
  159. package/dist/sst/.sst/platform/src/components/aws/helpers/load-balancer.d.ts.map +1 -0
  160. package/dist/sst/.sst/platform/src/components/aws/helpers/provider.d.ts +2 -2
  161. package/dist/sst/.sst/platform/src/components/aws/helpers/provider.d.ts.map +1 -1
  162. package/dist/sst/.sst/platform/src/components/aws/helpers/site-builder.d.ts +1 -1
  163. package/dist/sst/.sst/platform/src/components/aws/helpers/site-builder.d.ts.map +1 -1
  164. package/dist/sst/.sst/platform/src/components/aws/helpers/subscriber.d.ts +1 -1
  165. package/dist/sst/.sst/platform/src/components/aws/helpers/subscriber.d.ts.map +1 -1
  166. package/dist/sst/.sst/platform/src/components/aws/https-redirect.d.ts.map +1 -1
  167. package/dist/sst/.sst/platform/src/components/aws/index.d.ts +4 -0
  168. package/dist/sst/.sst/platform/src/components/aws/index.d.ts.map +1 -1
  169. package/dist/sst/.sst/platform/src/components/aws/kinesis-stream-lambda-subscriber.d.ts.map +1 -1
  170. package/dist/sst/.sst/platform/src/components/aws/kinesis-stream.d.ts +8 -3
  171. package/dist/sst/.sst/platform/src/components/aws/kinesis-stream.d.ts.map +1 -1
  172. package/dist/sst/.sst/platform/src/components/aws/linkable.d.ts +1 -1
  173. package/dist/sst/.sst/platform/src/components/aws/linkable.d.ts.map +1 -1
  174. package/dist/sst/.sst/platform/src/components/aws/mysql.d.ts +34 -5
  175. package/dist/sst/.sst/platform/src/components/aws/mysql.d.ts.map +1 -1
  176. package/dist/sst/.sst/platform/src/components/aws/nextjs.d.ts +39 -5
  177. package/dist/sst/.sst/platform/src/components/aws/nextjs.d.ts.map +1 -1
  178. package/dist/sst/.sst/platform/src/components/aws/nuxt.d.ts.map +1 -1
  179. package/dist/sst/.sst/platform/src/components/aws/open-search.d.ts +12 -1
  180. package/dist/sst/.sst/platform/src/components/aws/open-search.d.ts.map +1 -1
  181. package/dist/sst/.sst/platform/src/components/aws/opencontrol.d.ts +7 -3
  182. package/dist/sst/.sst/platform/src/components/aws/opencontrol.d.ts.map +1 -1
  183. package/dist/sst/.sst/platform/src/components/aws/permission.d.ts +5 -0
  184. package/dist/sst/.sst/platform/src/components/aws/permission.d.ts.map +1 -1
  185. package/dist/sst/.sst/platform/src/components/aws/postgres-v1.d.ts +13 -2
  186. package/dist/sst/.sst/platform/src/components/aws/postgres-v1.d.ts.map +1 -1
  187. package/dist/sst/.sst/platform/src/components/aws/postgres.d.ts +34 -5
  188. package/dist/sst/.sst/platform/src/components/aws/postgres.d.ts.map +1 -1
  189. package/dist/sst/.sst/platform/src/components/aws/queue-lambda-subscriber.d.ts +6 -1
  190. package/dist/sst/.sst/platform/src/components/aws/queue-lambda-subscriber.d.ts.map +1 -1
  191. package/dist/sst/.sst/platform/src/components/aws/queue.d.ts +10 -1
  192. package/dist/sst/.sst/platform/src/components/aws/queue.d.ts.map +1 -1
  193. package/dist/sst/.sst/platform/src/components/aws/realtime-lambda-subscriber.d.ts +1 -1
  194. package/dist/sst/.sst/platform/src/components/aws/realtime-lambda-subscriber.d.ts.map +1 -1
  195. package/dist/sst/.sst/platform/src/components/aws/realtime.d.ts +6 -1
  196. package/dist/sst/.sst/platform/src/components/aws/realtime.d.ts.map +1 -1
  197. package/dist/sst/.sst/platform/src/components/aws/redis-v1.d.ts +10 -0
  198. package/dist/sst/.sst/platform/src/components/aws/redis-v1.d.ts.map +1 -1
  199. package/dist/sst/.sst/platform/src/components/aws/redis.d.ts +14 -0
  200. package/dist/sst/.sst/platform/src/components/aws/redis.d.ts.map +1 -1
  201. package/dist/sst/.sst/platform/src/components/aws/router.d.ts +482 -2
  202. package/dist/sst/.sst/platform/src/components/aws/router.d.ts.map +1 -1
  203. package/dist/sst/.sst/platform/src/components/aws/service-v1.d.ts.map +1 -1
  204. package/dist/sst/.sst/platform/src/components/aws/service.d.ts +125 -0
  205. package/dist/sst/.sst/platform/src/components/aws/service.d.ts.map +1 -1
  206. package/dist/sst/.sst/platform/src/components/aws/sns-topic-lambda-subscriber.d.ts +1 -1
  207. package/dist/sst/.sst/platform/src/components/aws/sns-topic-lambda-subscriber.d.ts.map +1 -1
  208. package/dist/sst/.sst/platform/src/components/aws/sns-topic.d.ts +6 -1
  209. package/dist/sst/.sst/platform/src/components/aws/sns-topic.d.ts.map +1 -1
  210. package/dist/sst/.sst/platform/src/components/aws/ssr-site.d.ts +7 -7
  211. package/dist/sst/.sst/platform/src/components/aws/ssr-site.d.ts.map +1 -1
  212. package/dist/sst/.sst/platform/src/components/aws/static-site.d.ts.map +1 -1
  213. package/dist/sst/.sst/platform/src/components/aws/step-functions/state.d.ts +1 -1
  214. package/dist/sst/.sst/platform/src/components/aws/step-functions/state.d.ts.map +1 -1
  215. package/dist/sst/.sst/platform/src/components/aws/step-functions/task.d.ts +10 -2
  216. package/dist/sst/.sst/platform/src/components/aws/step-functions/task.d.ts.map +1 -1
  217. package/dist/sst/.sst/platform/src/components/aws/step-functions.d.ts +5 -0
  218. package/dist/sst/.sst/platform/src/components/aws/step-functions.d.ts.map +1 -1
  219. package/dist/sst/.sst/platform/src/components/aws/tan-stack-start.d.ts +20 -6
  220. package/dist/sst/.sst/platform/src/components/aws/tan-stack-start.d.ts.map +1 -1
  221. package/dist/sst/.sst/platform/src/components/aws/task.d.ts +35 -15
  222. package/dist/sst/.sst/platform/src/components/aws/task.d.ts.map +1 -1
  223. package/dist/sst/.sst/platform/src/components/aws/vector.d.ts +5 -0
  224. package/dist/sst/.sst/platform/src/components/aws/vector.d.ts.map +1 -1
  225. package/dist/sst/.sst/platform/src/components/aws/vpc.d.ts +51 -4
  226. package/dist/sst/.sst/platform/src/components/aws/vpc.d.ts.map +1 -1
  227. package/dist/sst/.sst/platform/src/components/aws/workflow.d.ts +331 -0
  228. package/dist/sst/.sst/platform/src/components/aws/workflow.d.ts.map +1 -0
  229. package/dist/sst/.sst/platform/src/components/cloudflare/ai.d.ts +82 -0
  230. package/dist/sst/.sst/platform/src/components/cloudflare/ai.d.ts.map +1 -0
  231. package/dist/sst/.sst/platform/src/components/cloudflare/binding.d.ts +15 -1
  232. package/dist/sst/.sst/platform/src/components/cloudflare/binding.d.ts.map +1 -1
  233. package/dist/sst/.sst/platform/src/components/cloudflare/bucket.d.ts +4 -2
  234. package/dist/sst/.sst/platform/src/components/cloudflare/bucket.d.ts.map +1 -1
  235. package/dist/sst/.sst/platform/src/components/cloudflare/cron.d.ts +29 -5
  236. package/dist/sst/.sst/platform/src/components/cloudflare/cron.d.ts.map +1 -1
  237. package/dist/sst/.sst/platform/src/components/cloudflare/d1.d.ts +37 -2
  238. package/dist/sst/.sst/platform/src/components/cloudflare/d1.d.ts.map +1 -1
  239. package/dist/sst/.sst/platform/src/components/cloudflare/index.d.ts +1 -0
  240. package/dist/sst/.sst/platform/src/components/cloudflare/index.d.ts.map +1 -1
  241. package/dist/sst/.sst/platform/src/components/cloudflare/kv.d.ts +36 -2
  242. package/dist/sst/.sst/platform/src/components/cloudflare/kv.d.ts.map +1 -1
  243. package/dist/sst/.sst/platform/src/components/cloudflare/providers/worker-placement.d.ts +27 -0
  244. package/dist/sst/.sst/platform/src/components/cloudflare/providers/worker-placement.d.ts.map +1 -0
  245. package/dist/sst/.sst/platform/src/components/cloudflare/providers/zone-lookup.d.ts.map +1 -1
  246. package/dist/sst/.sst/platform/src/components/cloudflare/queue-worker-subscriber.d.ts +116 -0
  247. package/dist/sst/.sst/platform/src/components/cloudflare/queue-worker-subscriber.d.ts.map +1 -0
  248. package/dist/sst/.sst/platform/src/components/cloudflare/queue.d.ts +186 -3
  249. package/dist/sst/.sst/platform/src/components/cloudflare/queue.d.ts.map +1 -1
  250. package/dist/sst/.sst/platform/src/components/cloudflare/static-site.d.ts +2 -2
  251. package/dist/sst/.sst/platform/src/components/cloudflare/static-site.d.ts.map +1 -1
  252. package/dist/sst/.sst/platform/src/components/cloudflare/worker.d.ts +39 -5
  253. package/dist/sst/.sst/platform/src/components/cloudflare/worker.d.ts.map +1 -1
  254. package/dist/sst/.sst/platform/src/components/component.d.ts.map +1 -1
  255. package/dist/sst/.sst/platform/src/components/duration.d.ts +2 -0
  256. package/dist/sst/.sst/platform/src/components/duration.d.ts.map +1 -1
  257. package/dist/sst/.sst/platform/src/components/esbuild.d.ts +3 -0
  258. package/dist/sst/.sst/platform/src/components/esbuild.d.ts.map +1 -0
  259. package/dist/sst/.sst/platform/src/components/link.d.ts +2 -2
  260. package/dist/sst/.sst/platform/src/components/link.d.ts.map +1 -1
  261. package/dist/sst/.sst/platform/src/components/linkable.d.ts +32 -2
  262. package/dist/sst/.sst/platform/src/components/linkable.d.ts.map +1 -1
  263. package/dist/sst/.sst/platform/src/components/rpc/rpc.d.ts.map +1 -1
  264. package/dist/sst/.sst/platform/src/components/vercel/dns.d.ts +2 -2
  265. package/dist/sst/.sst/platform/src/util/minify.d.ts +2 -0
  266. package/dist/sst/.sst/platform/src/util/minify.d.ts.map +1 -0
  267. package/dist/sst/components/monorise-core.d.ts +10 -0
  268. package/dist/sst/components/monorise-core.d.ts.map +1 -1
  269. package/dist/sst/components/q-function.d.ts +2 -3
  270. package/dist/sst/components/q-function.d.ts.map +1 -1
  271. package/dist/sst/index.js +75 -12
  272. package/dist/sst/index.js.map +1 -1
  273. package/package.json +10 -2
  274. package/dist/sst/.sst/platform/src/components/aws/helpers/quota.d.ts +0 -7
  275. package/dist/sst/.sst/platform/src/components/aws/helpers/quota.d.ts.map +0 -1
@@ -1,46 +1,14 @@
1
- var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
- var __spreadValues = (a, b) => {
9
- for (var prop in b || (b = {}))
10
- if (__hasOwnProp.call(b, prop))
11
- __defNormalProp(a, prop, b[prop]);
12
- if (__getOwnPropSymbols)
13
- for (var prop of __getOwnPropSymbols(b)) {
14
- if (__propIsEnum.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- }
17
- return a;
18
- };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
- var __export = (target, all) => {
21
- for (var name in all)
22
- __defProp(target, name, { get: all[name], enumerable: true });
23
- };
24
- var __async = (__this, __arguments, generator) => {
25
- return new Promise((resolve, reject) => {
26
- var fulfilled = (value) => {
27
- try {
28
- step(generator.next(value));
29
- } catch (e) {
30
- reject(e);
31
- }
32
- };
33
- var rejected = (value) => {
34
- try {
35
- step(generator.throw(value));
36
- } catch (e) {
37
- reject(e);
38
- }
39
- };
40
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
41
- step((generator = generator.apply(__this, __arguments)).next());
42
- });
43
- };
1
+ import {
2
+ CORE_EVENT_BUS,
3
+ CORE_TABLE,
4
+ ENTITY_REPLICATION_INDEX,
5
+ MUTUAL_REPLICATION_INDEX,
6
+ __async,
7
+ __export,
8
+ __objRest,
9
+ __spreadProps,
10
+ __spreadValues
11
+ } from "./chunk-QV4Q5377.js";
44
12
 
45
13
  // controllers/setupRoutes.ts
46
14
  import { Hono } from "hono";
@@ -128,6 +96,11 @@ var setupCommonRoutes = (container) => {
128
96
  container.deleteEntityController.controller
129
97
  );
130
98
  app.get("/tag/:entityType/:tagName", container.listTagsController.controller);
99
+ app.post("/transaction", container.executeTransactionController.controller);
100
+ app.post(
101
+ "/ws/ticket/:entityType/:entityId",
102
+ container.createTicketController.controller
103
+ );
131
104
  return app;
132
105
  };
133
106
 
@@ -163,6 +136,7 @@ var StandardErrorCode = {
163
136
  ENTITY_ID_IS_UNDEFINED: "ENTITY_ID_IS_UNDEFINED",
164
137
  ENTITY_IS_UNDEFINED: "ENTITY_IS_UNDEFINED",
165
138
  ENTITY_NOT_FOUND: "ENTITY_NOT_FOUND",
139
+ INVALID_CONDITION: "INVALID_CONDITION",
166
140
  INVALID_ENTITY_TYPE: "INVALID_ENTITY_TYPE",
167
141
  INVALID_MUTUAL: "INVALID_MUTUAL",
168
142
  INVALID_QUERY: "INVALID_QUERY",
@@ -175,7 +149,10 @@ var StandardErrorCode = {
175
149
  REPLICATION_ERROR: "REPLICATION_ERROR",
176
150
  RETRYABLE_MUTUAL_LOCK_CONFLICT: "RETRYABLE_MUTUAL_LOCK_CONFLICT",
177
151
  TAG_IS_UNDEFINED: "TAG_IS_UNDEFINED",
152
+ TRANSACTION_EMPTY: "TRANSACTION_EMPTY",
178
153
  TRANSACTION_FAILED: "TRANSACTION_FAILED",
154
+ TRANSACTION_ITEM_LIMIT_EXCEEDED: "TRANSACTION_ITEM_LIMIT_EXCEEDED",
155
+ TRANSACTION_UNIQUE_FIELD_UPDATE: "TRANSACTION_UNIQUE_FIELD_UPDATE",
179
156
  UNIQUE_VALUE_EXISTS: "UNIQUE_VALUE_EXISTS"
180
157
  };
181
158
 
@@ -762,6 +739,22 @@ var EntityRepository = class extends Repository {
762
739
  } catch (err) {
763
740
  if (err instanceof TransactionCanceledException) {
764
741
  const [updateErr, ...uniqueFieldErr] = err.CancellationReasons || [];
742
+ if ((updateErr == null ? void 0 : updateErr.Code) === BatchStatementErrorCodeEnum.ConditionalCheckFailed) {
743
+ if (opts == null ? void 0 : opts.ConditionExpression) {
744
+ throw new StandardError(
745
+ StandardErrorCode.CONDITIONAL_CHECK_FAILED,
746
+ "Conditional check failed",
747
+ err,
748
+ { entityId, toUpdate }
749
+ );
750
+ }
751
+ throw new StandardError(
752
+ StandardErrorCode.ENTITY_NOT_FOUND,
753
+ "Entity not found",
754
+ err,
755
+ { entityId, toUpdate }
756
+ );
757
+ }
765
758
  for (let i = 0; i < uniqueFieldErr.length; i++) {
766
759
  if (i % 2 === 1 && uniqueFieldErr[i].Code === BatchStatementErrorCodeEnum.ConditionalCheckFailed) {
767
760
  const field = updatedUniqueFields[Math.floor(i / 2)];
@@ -782,6 +775,14 @@ var EntityRepository = class extends Repository {
782
775
  return updatedEntity;
783
776
  } catch (err) {
784
777
  if (err instanceof ConditionalCheckFailedException) {
778
+ if (opts == null ? void 0 : opts.ConditionExpression) {
779
+ throw new StandardError(
780
+ StandardErrorCode.CONDITIONAL_CHECK_FAILED,
781
+ "Conditional check failed",
782
+ err,
783
+ { entityId, toUpdate }
784
+ );
785
+ }
785
786
  throw new StandardError(
786
787
  StandardErrorCode.ENTITY_NOT_FOUND,
787
788
  "Entity not found",
@@ -796,22 +797,22 @@ var EntityRepository = class extends Repository {
796
797
  }
797
798
  });
798
799
  }
799
- adjustEntity(entityType, entityId, adjustments, constraints) {
800
+ adjustEntity(entityType, entityId, adjustments, opts) {
800
801
  return __async(this, null, function* () {
801
802
  const entity = new Entity(entityType, entityId);
802
- const { UpdateExpression, ConditionExpression, ExpressionAttributeNames, ExpressionAttributeValues } = this.toAdjustUpdate(adjustments, constraints);
803
+ const { UpdateExpression, ExpressionAttributeNames, ExpressionAttributeValues } = this.toAdjustUpdate(adjustments);
803
804
  const updatedAtExpression = ", #updatedAt = :updatedAt";
804
805
  ExpressionAttributeNames["#updatedAt"] = "updatedAt";
805
806
  ExpressionAttributeValues[":updatedAt"] = { S: (/* @__PURE__ */ new Date()).toISOString() };
806
- const resp = yield this.dynamodbClient.updateItem(__spreadProps(__spreadValues({
807
+ const resp = yield this.dynamodbClient.updateItem({
807
808
  TableName: this.TABLE_NAME,
808
809
  Key: entity.keys(),
809
- UpdateExpression: UpdateExpression + updatedAtExpression
810
- }, ConditionExpression && { ConditionExpression }), {
811
- ExpressionAttributeNames,
812
- ExpressionAttributeValues,
810
+ UpdateExpression: UpdateExpression + updatedAtExpression,
811
+ ConditionExpression: (opts == null ? void 0 : opts.ConditionExpression) || "attribute_exists(PK)",
812
+ ExpressionAttributeNames: __spreadValues(__spreadValues({}, ExpressionAttributeNames), opts == null ? void 0 : opts.ExpressionAttributeNames),
813
+ ExpressionAttributeValues: __spreadValues(__spreadValues({}, ExpressionAttributeValues), opts == null ? void 0 : opts.ExpressionAttributeValues),
813
814
  ReturnValues: "ALL_NEW"
814
- }));
815
+ });
815
816
  return Entity.fromItem(resp.Attributes);
816
817
  });
817
818
  }
@@ -1821,6 +1822,217 @@ var TagRepository = class extends Repository {
1821
1822
  }
1822
1823
  };
1823
1824
 
1825
+ // data/WebSocket.ts
1826
+ import {
1827
+ DeleteCommand,
1828
+ DynamoDBDocumentClient,
1829
+ PutCommand,
1830
+ QueryCommand
1831
+ } from "@aws-sdk/lib-dynamodb";
1832
+ var WebSocketRepository = class extends Repository {
1833
+ constructor(tableName, dynamodbClient) {
1834
+ super();
1835
+ this.tableName = tableName;
1836
+ this.dynamodbClient = dynamodbClient;
1837
+ this.docClient = DynamoDBDocumentClient.from(dynamodbClient);
1838
+ }
1839
+ createConnection(connectionId, metadata, expiresAt) {
1840
+ return __async(this, null, function* () {
1841
+ yield this.docClient.send(
1842
+ new PutCommand({
1843
+ TableName: this.tableName,
1844
+ Item: __spreadProps(__spreadValues({
1845
+ PK: `CONN#${connectionId}`,
1846
+ SK: "#METADATA#",
1847
+ connectionId
1848
+ }, metadata), {
1849
+ expiresAt
1850
+ })
1851
+ })
1852
+ );
1853
+ });
1854
+ }
1855
+ getConnection(connectionId) {
1856
+ return __async(this, null, function* () {
1857
+ var _a;
1858
+ const result = yield this.docClient.send(
1859
+ new QueryCommand({
1860
+ TableName: this.tableName,
1861
+ KeyConditionExpression: "PK = :pk",
1862
+ ExpressionAttributeValues: {
1863
+ ":pk": `CONN#${connectionId}`
1864
+ }
1865
+ })
1866
+ );
1867
+ return (_a = result.Items) == null ? void 0 : _a[0];
1868
+ });
1869
+ }
1870
+ deleteConnection(connectionId) {
1871
+ return __async(this, null, function* () {
1872
+ yield this.docClient.send(
1873
+ new DeleteCommand({
1874
+ TableName: this.tableName,
1875
+ Key: {
1876
+ PK: `CONN#${connectionId}`,
1877
+ SK: "#METADATA#"
1878
+ }
1879
+ })
1880
+ );
1881
+ });
1882
+ }
1883
+ createSubscription(subKey, connectionId, data) {
1884
+ return __async(this, null, function* () {
1885
+ yield this.docClient.send(
1886
+ new PutCommand({
1887
+ TableName: this.tableName,
1888
+ Item: __spreadValues({
1889
+ PK: subKey,
1890
+ SK: `CONN#${connectionId}`,
1891
+ R1PK: `CONN#${connectionId}`,
1892
+ R1SK: subKey,
1893
+ connectionId
1894
+ }, data)
1895
+ })
1896
+ );
1897
+ });
1898
+ }
1899
+ deleteSubscription(subKey, connectionId) {
1900
+ return __async(this, null, function* () {
1901
+ yield this.docClient.send(
1902
+ new DeleteCommand({
1903
+ TableName: this.tableName,
1904
+ Key: {
1905
+ PK: subKey,
1906
+ SK: `CONN#${connectionId}`
1907
+ }
1908
+ })
1909
+ );
1910
+ });
1911
+ }
1912
+ querySubscriptionsByKey(subKey) {
1913
+ return __async(this, null, function* () {
1914
+ const result = yield this.docClient.send(
1915
+ new QueryCommand({
1916
+ TableName: this.tableName,
1917
+ KeyConditionExpression: "PK = :pk",
1918
+ ExpressionAttributeValues: {
1919
+ ":pk": subKey
1920
+ },
1921
+ ConsistentRead: true
1922
+ })
1923
+ );
1924
+ return result.Items || [];
1925
+ });
1926
+ }
1927
+ querySubscriptionsByConnectionId(connectionId) {
1928
+ return __async(this, null, function* () {
1929
+ const { ENTITY_REPLICATION_INDEX: ENTITY_REPLICATION_INDEX2 } = yield import("./service.config-ZJEZ6EKA.js");
1930
+ const result = yield this.docClient.send(
1931
+ new QueryCommand({
1932
+ TableName: this.tableName,
1933
+ IndexName: ENTITY_REPLICATION_INDEX2,
1934
+ KeyConditionExpression: "R1PK = :r1pk",
1935
+ ExpressionAttributeValues: {
1936
+ ":r1pk": `CONN#${connectionId}`
1937
+ }
1938
+ })
1939
+ );
1940
+ return result.Items || [];
1941
+ });
1942
+ }
1943
+ createTicket(ticket, entityType, entityId, feedTypes, expiresAt) {
1944
+ return __async(this, null, function* () {
1945
+ yield this.docClient.send(
1946
+ new PutCommand({
1947
+ TableName: this.tableName,
1948
+ Item: {
1949
+ PK: `TICKET#${ticket}`,
1950
+ SK: "#METADATA#",
1951
+ entityType,
1952
+ entityId,
1953
+ feedTypes,
1954
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1955
+ expiresAt
1956
+ }
1957
+ })
1958
+ );
1959
+ });
1960
+ }
1961
+ consumeTicket(ticket) {
1962
+ return __async(this, null, function* () {
1963
+ try {
1964
+ const result = yield this.docClient.send(
1965
+ new DeleteCommand({
1966
+ TableName: this.tableName,
1967
+ Key: {
1968
+ PK: `TICKET#${ticket}`,
1969
+ SK: "#METADATA#"
1970
+ },
1971
+ ConditionExpression: "attribute_exists(PK)",
1972
+ ReturnValues: "ALL_OLD"
1973
+ })
1974
+ );
1975
+ const item = result.Attributes;
1976
+ if (!item) return null;
1977
+ const expiresAt = item.expiresAt;
1978
+ if (expiresAt && expiresAt < Math.floor(Date.now() / 1e3)) {
1979
+ return null;
1980
+ }
1981
+ return {
1982
+ entityType: item.entityType,
1983
+ entityId: item.entityId,
1984
+ feedTypes: item.feedTypes || []
1985
+ };
1986
+ } catch (error) {
1987
+ if (error instanceof Error && error.name === "ConditionalCheckFailedException") {
1988
+ return null;
1989
+ }
1990
+ throw error;
1991
+ }
1992
+ });
1993
+ }
1994
+ queryMutualConnections(byEntityType, byEntityId) {
1995
+ return __async(this, null, function* () {
1996
+ const result = yield this.docClient.send(
1997
+ new QueryCommand({
1998
+ TableName: this.tableName,
1999
+ KeyConditionExpression: "PK = :pk",
2000
+ ExpressionAttributeValues: {
2001
+ ":pk": `${byEntityType}#${byEntityId}`
2002
+ },
2003
+ ProjectionExpression: "SK",
2004
+ ConsistentRead: true
2005
+ })
2006
+ );
2007
+ const connections = [];
2008
+ for (const item of result.Items || []) {
2009
+ const sk = item.SK;
2010
+ if (!sk || sk === "#METADATA#" || sk.startsWith("#")) continue;
2011
+ const parts = sk.split("#");
2012
+ if (parts.length >= 2) {
2013
+ connections.push({ entityType: parts[0], entityId: parts[1] });
2014
+ }
2015
+ }
2016
+ return connections;
2017
+ });
2018
+ }
2019
+ queryFeedSubscriptions(entityType, entityId) {
2020
+ return __async(this, null, function* () {
2021
+ const result = yield this.docClient.send(
2022
+ new QueryCommand({
2023
+ TableName: this.tableName,
2024
+ KeyConditionExpression: "PK = :pk",
2025
+ ExpressionAttributeValues: {
2026
+ ":pk": `SUB#FEED#${entityType}#${entityId}`
2027
+ },
2028
+ ConsistentRead: true
2029
+ })
2030
+ );
2031
+ return result.Items || [];
2032
+ });
2033
+ }
2034
+ };
2035
+
1824
2036
  // handles/app.ts
1825
2037
  import { Hono as Hono2 } from "hono";
1826
2038
  import { handle } from "hono/aws-lambda";
@@ -1860,14 +2072,6 @@ import {
1860
2072
  PutEventsCommand
1861
2073
  } from "@aws-sdk/client-eventbridge";
1862
2074
 
1863
- // constants/table.ts
1864
- var ENTITY_REPLICATION_INDEX = "ENTITY_REPLICATION_INDEX";
1865
- var MUTUAL_REPLICATION_INDEX = "MUTUAL_REPLICATION_INDEX";
1866
-
1867
- // configs/service.config.ts
1868
- var CORE_TABLE = process.env.CORE_TABLE || "";
1869
- var CORE_EVENT_BUS = process.env.CORE_EVENT_BUS || "";
1870
-
1871
2075
  // types/event.ts
1872
2076
  var SOURCE = {
1873
2077
  CORE: "core-service",
@@ -2819,6 +3023,458 @@ var handler5 = (container) => (ev) => __async(null, null, function* () {
2819
3023
  return { batchItemFailures };
2820
3024
  });
2821
3025
 
3026
+ // processors/websocket-processor.ts
3027
+ import {
3028
+ ApiGatewayManagementApiClient,
3029
+ PostToConnectionCommand
3030
+ } from "@aws-sdk/client-apigatewaymanagementapi";
3031
+ import { unmarshall as unmarshall4 } from "@aws-sdk/util-dynamodb";
3032
+ import { ulid as ulid3 } from "ulid";
3033
+ var SUB_ENTITY_TYPE = "SUB#ENTITY#";
3034
+ var SUB_MUTUAL_TYPE = "SUB#MUTUAL#";
3035
+ var SUB_EPHEMERAL = "SUB#EPHEMERAL#";
3036
+ var SUB_FEED = "SUB#FEED#";
3037
+ var getWsEndpoint = () => process.env.WEBSOCKET_MANAGEMENT_ENDPOINT || "";
3038
+ var connect = (container) => (event) => __async(null, null, function* () {
3039
+ var _a, _b, _c, _d;
3040
+ const connectionId = event.requestContext.connectionId;
3041
+ if (!connectionId) {
3042
+ return { statusCode: 400, body: "Missing connection ID" };
3043
+ }
3044
+ const expiresAt = Math.floor(Date.now() / 1e3) + 2 * 60 * 60;
3045
+ const ticket = (_a = event.queryStringParameters) == null ? void 0 : _a.ticket;
3046
+ const token = ((_b = event.queryStringParameters) == null ? void 0 : _b.token) || ((_c = event.headers) == null ? void 0 : _c.authorization) || ((_d = event.headers) == null ? void 0 : _d.Authorization);
3047
+ if (!ticket && !token) {
3048
+ return { statusCode: 401, body: "Unauthorized" };
3049
+ }
3050
+ const wsRepo = container.websocketRepository;
3051
+ try {
3052
+ let entityType;
3053
+ let entityId;
3054
+ let feedTypes;
3055
+ if (ticket) {
3056
+ const ticketData = yield wsRepo.consumeTicket(ticket);
3057
+ if (!ticketData) {
3058
+ return { statusCode: 401, body: "Invalid or expired ticket" };
3059
+ }
3060
+ entityType = ticketData.entityType;
3061
+ entityId = ticketData.entityId;
3062
+ feedTypes = ticketData.feedTypes;
3063
+ } else {
3064
+ entityId = token;
3065
+ }
3066
+ yield wsRepo.createConnection(
3067
+ connectionId,
3068
+ __spreadProps(__spreadValues(__spreadValues({}, entityType && { entityType }), entityId && { entityId }), {
3069
+ connectedAt: (/* @__PURE__ */ new Date()).toISOString()
3070
+ }),
3071
+ expiresAt
3072
+ );
3073
+ if (entityType && entityId && feedTypes) {
3074
+ yield wsRepo.createSubscription(
3075
+ `${SUB_FEED}${entityType}#${entityId}`,
3076
+ connectionId,
3077
+ {
3078
+ subscriptionType: "feed",
3079
+ entityType,
3080
+ entityId,
3081
+ feedTypes,
3082
+ subscribedAt: (/* @__PURE__ */ new Date()).toISOString(),
3083
+ expiresAt
3084
+ }
3085
+ );
3086
+ }
3087
+ return { statusCode: 200, body: "Connected" };
3088
+ } catch (error) {
3089
+ console.error("Error in $connect:", error);
3090
+ return { statusCode: 500, body: "Failed to connect" };
3091
+ }
3092
+ });
3093
+ var disconnect = (container) => (event) => __async(null, null, function* () {
3094
+ const connectionId = event.requestContext.connectionId;
3095
+ if (!connectionId) {
3096
+ return { statusCode: 400, body: "Missing connection ID" };
3097
+ }
3098
+ const wsRepo = container.websocketRepository;
3099
+ try {
3100
+ const subscriptions = yield wsRepo.querySubscriptionsByConnectionId(connectionId);
3101
+ const deletePromises = [];
3102
+ for (const item of subscriptions) {
3103
+ if (item.PK && item.SK) {
3104
+ deletePromises.push(
3105
+ wsRepo.deleteSubscription(item.PK, item.connectionId).catch(
3106
+ (e) => console.warn("Failed to delete subscription on disconnect:", e)
3107
+ )
3108
+ );
3109
+ }
3110
+ }
3111
+ deletePromises.push(wsRepo.deleteConnection(connectionId));
3112
+ yield Promise.all(deletePromises);
3113
+ return { statusCode: 200, body: "Disconnected" };
3114
+ } catch (error) {
3115
+ console.error("Error cleaning up connection:", error);
3116
+ return { statusCode: 500, body: "Failed to disconnect" };
3117
+ }
3118
+ });
3119
+ var $default = (container) => (event) => __async(null, null, function* () {
3120
+ const connectionId = event.requestContext.connectionId;
3121
+ if (!connectionId || !event.body) {
3122
+ return { statusCode: 400, body: "Invalid message" };
3123
+ }
3124
+ let message;
3125
+ try {
3126
+ message = JSON.parse(event.body);
3127
+ } catch (e) {
3128
+ return { statusCode: 400, body: "Invalid JSON" };
3129
+ }
3130
+ const wsRepo = container.websocketRepository;
3131
+ const wsEndpoint = getWsEndpoint();
3132
+ const managementApi = new ApiGatewayManagementApiClient({
3133
+ endpoint: wsEndpoint
3134
+ });
3135
+ try {
3136
+ switch (message.action) {
3137
+ case "subscribe": {
3138
+ const {
3139
+ entityType,
3140
+ byEntityType,
3141
+ byEntityId,
3142
+ mutualEntityType,
3143
+ channel
3144
+ } = message.payload;
3145
+ if (entityType && !byEntityType) {
3146
+ yield wsRepo.createSubscription(
3147
+ `${SUB_ENTITY_TYPE}${entityType}`,
3148
+ connectionId,
3149
+ {
3150
+ subscriptionType: "entity-type",
3151
+ entityType,
3152
+ subscribedAt: (/* @__PURE__ */ new Date()).toISOString()
3153
+ }
3154
+ );
3155
+ } else if (byEntityType && byEntityId && mutualEntityType) {
3156
+ yield wsRepo.createSubscription(
3157
+ `${SUB_MUTUAL_TYPE}${byEntityType}#${byEntityId}#${mutualEntityType}`,
3158
+ connectionId,
3159
+ {
3160
+ subscriptionType: "mutual-type",
3161
+ byEntityType,
3162
+ byEntityId,
3163
+ entityType: mutualEntityType,
3164
+ subscribedAt: (/* @__PURE__ */ new Date()).toISOString()
3165
+ }
3166
+ );
3167
+ } else if (channel) {
3168
+ yield wsRepo.createSubscription(
3169
+ `${SUB_EPHEMERAL}${channel}`,
3170
+ connectionId,
3171
+ {
3172
+ subscriptionType: "ephemeral",
3173
+ channel,
3174
+ subscribedAt: (/* @__PURE__ */ new Date()).toISOString()
3175
+ }
3176
+ );
3177
+ } else {
3178
+ return { statusCode: 400, body: "Invalid subscription parameters" };
3179
+ }
3180
+ const ackMessage = {
3181
+ type: "ack",
3182
+ id: message.id,
3183
+ payload: { action: "subscribe", success: true }
3184
+ };
3185
+ yield managementApi.send(
3186
+ new PostToConnectionCommand({
3187
+ ConnectionId: connectionId,
3188
+ Data: JSON.stringify(ackMessage)
3189
+ })
3190
+ );
3191
+ return { statusCode: 200, body: "Subscribed" };
3192
+ }
3193
+ case "unsubscribe": {
3194
+ const {
3195
+ entityType,
3196
+ byEntityType,
3197
+ byEntityId,
3198
+ mutualEntityType,
3199
+ channel
3200
+ } = message.payload;
3201
+ if (entityType && !byEntityType) {
3202
+ yield wsRepo.deleteSubscription(
3203
+ `${SUB_ENTITY_TYPE}${entityType}`,
3204
+ connectionId
3205
+ );
3206
+ } else if (byEntityType && byEntityId && mutualEntityType) {
3207
+ yield wsRepo.deleteSubscription(
3208
+ `${SUB_MUTUAL_TYPE}${byEntityType}#${byEntityId}#${mutualEntityType}`,
3209
+ connectionId
3210
+ );
3211
+ } else if (channel) {
3212
+ yield wsRepo.deleteSubscription(
3213
+ `${SUB_EPHEMERAL}${channel}`,
3214
+ connectionId
3215
+ );
3216
+ }
3217
+ const ackMessage = {
3218
+ type: "ack",
3219
+ id: message.id,
3220
+ payload: { action: "unsubscribe", success: true }
3221
+ };
3222
+ yield managementApi.send(
3223
+ new PostToConnectionCommand({
3224
+ ConnectionId: connectionId,
3225
+ Data: JSON.stringify(ackMessage)
3226
+ })
3227
+ );
3228
+ return { statusCode: 200, body: "Unsubscribed" };
3229
+ }
3230
+ case "ping": {
3231
+ const pongMessage = {
3232
+ type: "pong",
3233
+ id: message.id,
3234
+ payload: { timestamp: Date.now() }
3235
+ };
3236
+ yield managementApi.send(
3237
+ new PostToConnectionCommand({
3238
+ ConnectionId: connectionId,
3239
+ Data: JSON.stringify(pongMessage)
3240
+ })
3241
+ );
3242
+ return { statusCode: 200, body: "Pong" };
3243
+ }
3244
+ case "ephemeral": {
3245
+ const { channel, data } = message.payload;
3246
+ if (!channel) {
3247
+ return { statusCode: 400, body: "Missing channel" };
3248
+ }
3249
+ const conn = yield wsRepo.getConnection(connectionId);
3250
+ const senderId = conn == null ? void 0 : conn.entityId;
3251
+ const subKey = `${SUB_EPHEMERAL}${channel}`;
3252
+ const ephemeralMessage = {
3253
+ type: "ephemeral",
3254
+ id: ulid3(),
3255
+ payload: { channel, data, senderId }
3256
+ };
3257
+ yield broadcastToSubscribers(
3258
+ managementApi,
3259
+ wsRepo,
3260
+ subKey,
3261
+ ephemeralMessage,
3262
+ connectionId
3263
+ // Exclude sender
3264
+ );
3265
+ return { statusCode: 200, body: "Broadcasted" };
3266
+ }
3267
+ default:
3268
+ return { statusCode: 400, body: "Unknown action" };
3269
+ }
3270
+ } catch (error) {
3271
+ console.error("Error handling message:", error);
3272
+ try {
3273
+ const errorMessage = {
3274
+ type: "error",
3275
+ id: message.id,
3276
+ payload: { message: "Internal server error" }
3277
+ };
3278
+ yield managementApi.send(
3279
+ new PostToConnectionCommand({
3280
+ ConnectionId: connectionId,
3281
+ Data: JSON.stringify(errorMessage)
3282
+ })
3283
+ );
3284
+ } catch (e) {
3285
+ }
3286
+ return { statusCode: 500, body: "Internal server error" };
3287
+ }
3288
+ });
3289
+ var broadcast = (container) => (event) => __async(null, null, function* () {
3290
+ var _a, _b, _c, _d;
3291
+ const wsRepo = container.websocketRepository;
3292
+ const wsEndpoint = getWsEndpoint();
3293
+ const managementApi = new ApiGatewayManagementApiClient({
3294
+ endpoint: wsEndpoint
3295
+ });
3296
+ for (const record of event.Records) {
3297
+ const isInsert = record.eventName === "INSERT";
3298
+ const isModify = record.eventName === "MODIFY";
3299
+ const isRemove = record.eventName === "REMOVE";
3300
+ if (!isInsert && !isModify && !isRemove) continue;
3301
+ const newImage = (_a = record.dynamodb) == null ? void 0 : _a.NewImage;
3302
+ const oldImage = (_b = record.dynamodb) == null ? void 0 : _b.OldImage;
3303
+ const image = newImage || oldImage;
3304
+ if (!image) continue;
3305
+ const pk = ((_c = image.PK) == null ? void 0 : _c.S) || "";
3306
+ const sk = ((_d = image.SK) == null ? void 0 : _d.S) || "";
3307
+ const pkParts = pk.split("#");
3308
+ if (pkParts.length < 2) continue;
3309
+ const firstPart = pkParts[0];
3310
+ if (firstPart === firstPart.toUpperCase() || firstPart.includes(":")) {
3311
+ continue;
3312
+ }
3313
+ const entityType = pkParts[0];
3314
+ const entityId = pkParts[1];
3315
+ const isMutual = !sk.startsWith("#METADATA#") && sk.includes("#");
3316
+ try {
3317
+ if (isMutual) {
3318
+ const skParts = sk.split("#");
3319
+ const mutualEntityType = skParts[0];
3320
+ const byEntityId = entityId;
3321
+ const subKey = `${SUB_MUTUAL_TYPE}${entityType}#${byEntityId}#${mutualEntityType}`;
3322
+ const subscribers = yield wsRepo.querySubscriptionsByKey(subKey);
3323
+ if (subscribers.length) {
3324
+ let eventType;
3325
+ if (isInsert) eventType = "mutual.created";
3326
+ else if (isModify) eventType = "mutual.updated";
3327
+ else eventType = "mutual.deleted";
3328
+ const message = {
3329
+ type: eventType,
3330
+ id: ulid3(),
3331
+ payload: {
3332
+ byEntityType: entityType,
3333
+ byEntityId,
3334
+ mutualEntityType,
3335
+ entityId: skParts[1],
3336
+ data: isRemove ? void 0 : unmarshall4(image)
3337
+ }
3338
+ };
3339
+ yield broadcastToSubscribers(
3340
+ managementApi,
3341
+ wsRepo,
3342
+ subKey,
3343
+ message
3344
+ );
3345
+ }
3346
+ } else {
3347
+ const subKey = `${SUB_ENTITY_TYPE}${entityType}`;
3348
+ const subscribers = yield wsRepo.querySubscriptionsByKey(subKey);
3349
+ if (subscribers.length) {
3350
+ let eventType;
3351
+ if (isInsert) eventType = "entity.created";
3352
+ else if (isModify) eventType = "entity.updated";
3353
+ else eventType = "entity.deleted";
3354
+ const message = {
3355
+ type: eventType,
3356
+ id: ulid3(),
3357
+ payload: {
3358
+ entityType,
3359
+ entityId,
3360
+ data: isRemove ? void 0 : unmarshall4(image)
3361
+ }
3362
+ };
3363
+ yield broadcastToSubscribers(
3364
+ managementApi,
3365
+ wsRepo,
3366
+ subKey,
3367
+ message
3368
+ );
3369
+ }
3370
+ }
3371
+ yield broadcastToFeedSubscribers(
3372
+ managementApi,
3373
+ wsRepo,
3374
+ entityType,
3375
+ entityId,
3376
+ isMutual ? sk.split("#")[0] : entityType,
3377
+ // the changed entity type
3378
+ isMutual ? {
3379
+ type: isInsert ? "mutual.created" : isModify ? "mutual.updated" : "mutual.deleted",
3380
+ id: ulid3(),
3381
+ payload: {
3382
+ byEntityType: entityType,
3383
+ byEntityId: entityId,
3384
+ mutualEntityType: sk.split("#")[0],
3385
+ entityId: sk.split("#")[1],
3386
+ data: isRemove ? void 0 : unmarshall4(image)
3387
+ }
3388
+ } : {
3389
+ type: isInsert ? "entity.created" : isModify ? "entity.updated" : "entity.deleted",
3390
+ id: ulid3(),
3391
+ payload: {
3392
+ entityType,
3393
+ entityId,
3394
+ data: isRemove ? void 0 : unmarshall4(image)
3395
+ }
3396
+ }
3397
+ );
3398
+ } catch (error) {
3399
+ console.error("Error broadcasting:", error);
3400
+ }
3401
+ }
3402
+ });
3403
+ function broadcastToSubscribers(managementApi, wsRepo, subKey, message, excludeConnectionId) {
3404
+ return __async(this, null, function* () {
3405
+ const subscribers = yield wsRepo.querySubscriptionsByKey(subKey);
3406
+ if (!subscribers.length) return;
3407
+ const messageData = JSON.stringify(message);
3408
+ const sends = subscribers.filter((subscriber) => {
3409
+ const id = subscriber.connectionId;
3410
+ return !excludeConnectionId || id !== excludeConnectionId;
3411
+ }).map((subscriber) => __async(null, null, function* () {
3412
+ var _a;
3413
+ try {
3414
+ yield managementApi.send(
3415
+ new PostToConnectionCommand({
3416
+ ConnectionId: subscriber.connectionId,
3417
+ Data: messageData
3418
+ })
3419
+ );
3420
+ } catch (error) {
3421
+ const isGone = (error == null ? void 0 : error.name) === "GoneException" || ((_a = error == null ? void 0 : error.$metadata) == null ? void 0 : _a.httpStatusCode) === 410;
3422
+ if (isGone) {
3423
+ yield wsRepo.deleteSubscription(subKey, subscriber.connectionId).catch(
3424
+ (e) => console.warn("Failed to clean up stale subscription:", e)
3425
+ );
3426
+ }
3427
+ }
3428
+ }));
3429
+ yield Promise.allSettled(sends);
3430
+ });
3431
+ }
3432
+ function broadcastToFeedSubscribers(managementApi, wsRepo, byEntityType, byEntityId, changedEntityType, message) {
3433
+ return __async(this, null, function* () {
3434
+ var _a;
3435
+ const connections = yield wsRepo.queryMutualConnections(
3436
+ byEntityType,
3437
+ byEntityId
3438
+ );
3439
+ if (!connections.length) return;
3440
+ const connectedEntities = new Set(
3441
+ connections.map((c) => `${c.entityType}:${c.entityId}`)
3442
+ );
3443
+ connectedEntities.add(`${byEntityType}:${byEntityId}`);
3444
+ const sentConnections = /* @__PURE__ */ new Set();
3445
+ for (const connEntity of connectedEntities) {
3446
+ const [entityType, entityId] = connEntity.split(":");
3447
+ const feedSubs = yield wsRepo.queryFeedSubscriptions(entityType, entityId);
3448
+ if (!feedSubs.length) continue;
3449
+ for (const feedSub of feedSubs) {
3450
+ const feedTypes = feedSub.feedTypes;
3451
+ const connectionId = feedSub.connectionId;
3452
+ if (feedTypes && !feedTypes.includes(changedEntityType)) continue;
3453
+ if (sentConnections.has(connectionId)) continue;
3454
+ sentConnections.add(connectionId);
3455
+ try {
3456
+ yield managementApi.send(
3457
+ new PostToConnectionCommand({
3458
+ ConnectionId: connectionId,
3459
+ Data: JSON.stringify(message)
3460
+ })
3461
+ );
3462
+ } catch (error) {
3463
+ const isGone = (error == null ? void 0 : error.name) === "GoneException" || ((_a = error == null ? void 0 : error.$metadata) == null ? void 0 : _a.httpStatusCode) === 410;
3464
+ if (isGone) {
3465
+ yield wsRepo.deleteSubscription(
3466
+ `SUB#FEED#${entityType}#${entityId}`,
3467
+ connectionId
3468
+ ).catch(
3469
+ (e) => console.warn("Failed to clean up stale feed subscription:", e)
3470
+ );
3471
+ }
3472
+ }
3473
+ }
3474
+ }
3475
+ });
3476
+ }
3477
+
2822
3478
  // services/DependencyContainer.ts
2823
3479
  import { DynamoDB } from "@aws-sdk/client-dynamodb";
2824
3480
 
@@ -7051,11 +7707,21 @@ var UpdateEntityController = class {
7051
7707
  constructor(entityService) {
7052
7708
  this.entityService = entityService;
7053
7709
  this.controller = createMiddleware8((c) => __async(this, null, function* () {
7054
- var _a;
7710
+ var _b;
7055
7711
  const accountId = c.req.header("account-id");
7056
7712
  const { entityType, entityId } = c.req.param();
7057
7713
  const body = yield c.req.json();
7058
- const errorContext = {
7714
+ const _a = body, { $condition: condition, $where: where } = _a, entityPayload = __objRest(_a, ["$condition", "$where"]);
7715
+ if (condition !== void 0) {
7716
+ if (typeof condition !== "string" || condition.trim().length === 0) {
7717
+ c.status(httpStatus8.BAD_REQUEST);
7718
+ return c.json({
7719
+ code: "API_VALIDATION_ERROR",
7720
+ message: "$condition must be a non-empty string"
7721
+ });
7722
+ }
7723
+ }
7724
+ const errorContext = {
7059
7725
  accountId,
7060
7726
  "req.params": c.req.param(),
7061
7727
  "req.body": body
@@ -7064,14 +7730,16 @@ var UpdateEntityController = class {
7064
7730
  const entity = yield this.entityService.updateEntity({
7065
7731
  entityType,
7066
7732
  entityId,
7067
- entityPayload: body,
7068
- accountId
7733
+ entityPayload,
7734
+ accountId,
7735
+ condition,
7736
+ where
7069
7737
  });
7070
7738
  errorContext.entity = entity;
7071
7739
  c.status(httpStatus8.OK);
7072
7740
  return c.json(entity);
7073
7741
  } catch (err) {
7074
- if (((_a = err.constructor) == null ? void 0 : _a.name) === "ZodError") {
7742
+ if (((_b = err.constructor) == null ? void 0 : _b.name) === "ZodError") {
7075
7743
  c.status(httpStatus8.BAD_REQUEST);
7076
7744
  return c.json({
7077
7745
  code: "API_VALIDATION_ERROR",
@@ -7083,10 +7751,18 @@ var UpdateEntityController = class {
7083
7751
  c.status(httpStatus8.NOT_FOUND);
7084
7752
  return c.json(__spreadValues({}, err.toJSON()));
7085
7753
  }
7754
+ if (err instanceof StandardError && err.code === StandardErrorCode.INVALID_CONDITION) {
7755
+ c.status(httpStatus8.BAD_REQUEST);
7756
+ return c.json(__spreadValues({}, err.toJSON()));
7757
+ }
7086
7758
  if (err instanceof StandardError && err.code === StandardErrorCode.UNIQUE_VALUE_EXISTS) {
7087
7759
  c.status(httpStatus8.BAD_REQUEST);
7088
7760
  return c.json(__spreadValues({}, err.toJSON()));
7089
7761
  }
7762
+ if (err instanceof StandardError && err.code === StandardErrorCode.CONDITIONAL_CHECK_FAILED) {
7763
+ c.status(httpStatus8.CONFLICT);
7764
+ return c.json(__spreadValues({}, err.toJSON()));
7765
+ }
7090
7766
  console.log(
7091
7767
  "====UPDATE_ENTITY_CONTROLLER_ERROR",
7092
7768
  err,
@@ -7105,11 +7781,21 @@ var AdjustEntityController = class {
7105
7781
  constructor(entityService) {
7106
7782
  this.entityService = entityService;
7107
7783
  this.controller = createMiddleware9((c) => __async(this, null, function* () {
7108
- var _a;
7784
+ var _b;
7109
7785
  const accountId = c.req.header("account-id") || "";
7110
7786
  const { entityType, entityId } = c.req.param();
7111
7787
  const body = yield c.req.json();
7112
- for (const [key, value] of Object.entries(body)) {
7788
+ const _a = body, { $condition: condition } = _a, adjustments = __objRest(_a, ["$condition"]);
7789
+ if (condition !== void 0) {
7790
+ if (typeof condition !== "string" || condition.trim().length === 0) {
7791
+ c.status(httpStatus9.BAD_REQUEST);
7792
+ return c.json({
7793
+ code: "API_VALIDATION_ERROR",
7794
+ message: "$condition must be a non-empty string"
7795
+ });
7796
+ }
7797
+ }
7798
+ for (const [key, value] of Object.entries(adjustments)) {
7113
7799
  if (typeof value !== "number") {
7114
7800
  c.status(httpStatus9.BAD_REQUEST);
7115
7801
  return c.json({
@@ -7122,8 +7808,9 @@ var AdjustEntityController = class {
7122
7808
  const entity = yield this.entityService.adjustEntity({
7123
7809
  entityType,
7124
7810
  entityId,
7125
- adjustments: body,
7126
- accountId
7811
+ adjustments,
7812
+ accountId,
7813
+ condition
7127
7814
  });
7128
7815
  c.status(httpStatus9.OK);
7129
7816
  return c.json(entity.toJSON());
@@ -7132,7 +7819,11 @@ var AdjustEntityController = class {
7132
7819
  c.status(httpStatus9.NOT_FOUND);
7133
7820
  return c.json(__spreadValues({}, err.toJSON()));
7134
7821
  }
7135
- if ((err == null ? void 0 : err.name) === "ConditionalCheckFailedException" || ((_a = err == null ? void 0 : err.__type) == null ? void 0 : _a.includes("ConditionalCheckFailed"))) {
7822
+ if (err instanceof StandardError && err.code === StandardErrorCode.INVALID_CONDITION) {
7823
+ c.status(httpStatus9.BAD_REQUEST);
7824
+ return c.json(__spreadValues({}, err.toJSON()));
7825
+ }
7826
+ if ((err == null ? void 0 : err.name) === "ConditionalCheckFailedException" || ((_b = err == null ? void 0 : err.__type) == null ? void 0 : _b.includes("ConditionalCheckFailed"))) {
7136
7827
  c.status(httpStatus9.CONFLICT);
7137
7828
  return c.json({
7138
7829
  code: "ADJUSTMENT_CONSTRAINT_VIOLATED",
@@ -7437,6 +8128,119 @@ var UpdateMutualController = class {
7437
8128
  }
7438
8129
  };
7439
8130
 
8131
+ // services/entity.service.ts
8132
+ import { marshall as marshall6 } from "@aws-sdk/util-dynamodb";
8133
+
8134
+ // data/utils/build-condition-expression.ts
8135
+ import { marshall as marshall5 } from "@aws-sdk/util-dynamodb";
8136
+ function buildConditionExpression(where) {
8137
+ const conditions = ["attribute_exists(PK)"];
8138
+ const expressionAttributeNames = { "#data": "data" };
8139
+ const expressionAttributeValues = {};
8140
+ for (const [field, clause] of Object.entries(where)) {
8141
+ const namePlaceholder = `#where_${field}`;
8142
+ expressionAttributeNames[namePlaceholder] = field;
8143
+ const fieldRef = `#data.${namePlaceholder}`;
8144
+ if (clause === null || clause === void 0) continue;
8145
+ if (typeof clause !== "object") {
8146
+ const valPlaceholder = `:where_${field}`;
8147
+ expressionAttributeValues[valPlaceholder] = clause;
8148
+ conditions.push(`${fieldRef} = ${valPlaceholder}`);
8149
+ continue;
8150
+ }
8151
+ const op = clause;
8152
+ if ("$eq" in op) {
8153
+ const valPlaceholder = `:where_${field}_eq`;
8154
+ expressionAttributeValues[valPlaceholder] = op.$eq;
8155
+ conditions.push(`${fieldRef} = ${valPlaceholder}`);
8156
+ } else if ("$ne" in op) {
8157
+ const valPlaceholder = `:where_${field}_ne`;
8158
+ expressionAttributeValues[valPlaceholder] = op.$ne;
8159
+ conditions.push(`${fieldRef} <> ${valPlaceholder}`);
8160
+ } else if ("$gt" in op) {
8161
+ const valPlaceholder = `:where_${field}_gt`;
8162
+ expressionAttributeValues[valPlaceholder] = op.$gt;
8163
+ conditions.push(`${fieldRef} > ${valPlaceholder}`);
8164
+ } else if ("$lt" in op) {
8165
+ const valPlaceholder = `:where_${field}_lt`;
8166
+ expressionAttributeValues[valPlaceholder] = op.$lt;
8167
+ conditions.push(`${fieldRef} < ${valPlaceholder}`);
8168
+ } else if ("$gte" in op) {
8169
+ const valPlaceholder = `:where_${field}_gte`;
8170
+ expressionAttributeValues[valPlaceholder] = op.$gte;
8171
+ conditions.push(`${fieldRef} >= ${valPlaceholder}`);
8172
+ } else if ("$lte" in op) {
8173
+ const valPlaceholder = `:where_${field}_lte`;
8174
+ expressionAttributeValues[valPlaceholder] = op.$lte;
8175
+ conditions.push(`${fieldRef} <= ${valPlaceholder}`);
8176
+ } else if ("$exists" in op) {
8177
+ if (op.$exists) {
8178
+ conditions.push(`attribute_exists(${fieldRef})`);
8179
+ } else {
8180
+ conditions.push(`attribute_not_exists(${fieldRef})`);
8181
+ }
8182
+ } else if ("$beginsWith" in op) {
8183
+ const valPlaceholder = `:where_${field}_beginsWith`;
8184
+ expressionAttributeValues[valPlaceholder] = op.$beginsWith;
8185
+ conditions.push(`begins_with(${fieldRef}, ${valPlaceholder})`);
8186
+ }
8187
+ }
8188
+ return {
8189
+ ConditionExpression: conditions.join(" AND "),
8190
+ ExpressionAttributeNames: expressionAttributeNames,
8191
+ ExpressionAttributeValues: marshall5(expressionAttributeValues)
8192
+ };
8193
+ }
8194
+
8195
+ // services/resolve-condition.ts
8196
+ function resolveAdjustmentCondition(_0) {
8197
+ return __async(this, arguments, function* ({
8198
+ conditionName,
8199
+ conditions,
8200
+ adjustments,
8201
+ getEntityData
8202
+ }) {
8203
+ if (!Object.hasOwn(conditions, conditionName)) {
8204
+ throw new StandardError(
8205
+ StandardErrorCode.INVALID_CONDITION,
8206
+ `Unknown adjustment condition: '${conditionName}'`
8207
+ );
8208
+ }
8209
+ const condition = conditions[conditionName];
8210
+ let resolved;
8211
+ if (typeof condition === "function") {
8212
+ const data = yield getEntityData();
8213
+ resolved = condition(data, adjustments);
8214
+ } else {
8215
+ resolved = condition;
8216
+ }
8217
+ return buildConditionExpression(resolved);
8218
+ });
8219
+ }
8220
+ function resolveUpdateCondition(_0) {
8221
+ return __async(this, arguments, function* ({
8222
+ conditionName,
8223
+ conditions,
8224
+ getEntityData
8225
+ }) {
8226
+ if (!Object.hasOwn(conditions, conditionName)) {
8227
+ throw new StandardError(
8228
+ StandardErrorCode.INVALID_CONDITION,
8229
+ `Unknown update condition: '${conditionName}'`
8230
+ );
8231
+ }
8232
+ const condition = conditions[conditionName];
8233
+ let resolved;
8234
+ if (typeof condition === "function") {
8235
+ const data = yield getEntityData();
8236
+ resolved = condition(data);
8237
+ } else {
8238
+ resolved = condition;
8239
+ }
8240
+ return buildConditionExpression(resolved);
8241
+ });
8242
+ }
8243
+
7440
8244
  // services/entity.service.ts
7441
8245
  var EntityService = class {
7442
8246
  constructor(EntityConfig, EmailAuthEnabledEntities, entityRepository, publishEvent2, entityServiceLifeCycle) {
@@ -7492,34 +8296,59 @@ var EntityService = class {
7492
8296
  entityType,
7493
8297
  entityId,
7494
8298
  adjustments,
7495
- accountId
8299
+ accountId,
8300
+ condition
7496
8301
  }) {
7497
- var _a, _b, _c, _d;
7498
- const rawConstraints = (_a = this.EntityConfig[entityType]) == null ? void 0 : _a.adjustmentConstraints;
7499
- let resolvedConstraints = rawConstraints;
7500
- if (rawConstraints) {
8302
+ var _a, _b, _c;
8303
+ const entityConfig = this.EntityConfig[entityType];
8304
+ const adjustmentConditions = entityConfig == null ? void 0 : entityConfig.adjustmentConditions;
8305
+ const rawConstraints = entityConfig == null ? void 0 : entityConfig.adjustmentConstraints;
8306
+ let opts;
8307
+ if (adjustmentConditions) {
8308
+ if (!condition) {
8309
+ throw new StandardError(
8310
+ StandardErrorCode.INVALID_CONDITION,
8311
+ "Entity has adjustmentConditions defined; $condition is required for adjustEntity"
8312
+ );
8313
+ }
8314
+ opts = yield resolveAdjustmentCondition({
8315
+ conditionName: condition,
8316
+ conditions: adjustmentConditions,
8317
+ adjustments,
8318
+ getEntityData: () => __async(this, null, function* () {
8319
+ var _a2;
8320
+ const entity2 = yield this.entityRepository.getEntity(entityType, entityId);
8321
+ return (_a2 = entity2 == null ? void 0 : entity2.data) != null ? _a2 : {};
8322
+ })
8323
+ });
8324
+ } else if (rawConstraints) {
8325
+ console.warn(
8326
+ "[monorise] adjustmentConstraints is deprecated. Use adjustmentConditions instead."
8327
+ );
8328
+ let resolvedConstraints = rawConstraints;
7501
8329
  const hasDynamicFields = Object.values(rawConstraints).some(
7502
8330
  (c) => c.minField || c.maxField
7503
8331
  );
7504
8332
  if (hasDynamicFields) {
7505
8333
  const currentEntity = yield this.entityRepository.getEntity(entityType, entityId);
7506
- const data = (_b = currentEntity == null ? void 0 : currentEntity.data) != null ? _b : {};
8334
+ const data = (_a = currentEntity == null ? void 0 : currentEntity.data) != null ? _a : {};
7507
8335
  resolvedConstraints = {};
7508
8336
  for (const [field, constraint] of Object.entries(rawConstraints)) {
7509
8337
  const resolved = {};
7510
8338
  if (constraint.min !== void 0) resolved.min = constraint.min;
7511
8339
  if (constraint.max !== void 0) resolved.max = constraint.max;
7512
- if (constraint.minField) resolved.min = (_c = data[constraint.minField]) != null ? _c : 0;
7513
- if (constraint.maxField) resolved.max = (_d = data[constraint.maxField]) != null ? _d : Number.MAX_SAFE_INTEGER;
8340
+ if (constraint.minField) resolved.min = (_b = data[constraint.minField]) != null ? _b : 0;
8341
+ if (constraint.maxField) resolved.max = (_c = data[constraint.maxField]) != null ? _c : Number.MAX_SAFE_INTEGER;
7514
8342
  resolvedConstraints[field] = resolved;
7515
8343
  }
7516
8344
  }
8345
+ opts = this.buildLegacyAdjustCondition(adjustments, resolvedConstraints);
7517
8346
  }
7518
8347
  const entity = yield this.entityRepository.adjustEntity(
7519
8348
  entityType,
7520
8349
  entityId,
7521
8350
  adjustments,
7522
- resolvedConstraints
8351
+ opts
7523
8352
  );
7524
8353
  yield this.publishEvent({
7525
8354
  event: EVENT.CORE.ENTITY_UPDATED,
@@ -7537,9 +8366,11 @@ var EntityService = class {
7537
8366
  entityType,
7538
8367
  entityId,
7539
8368
  entityPayload,
7540
- accountId
8369
+ accountId,
8370
+ condition,
8371
+ where
7541
8372
  }) {
7542
- var _a, _b;
8373
+ var _a, _b, _c;
7543
8374
  const errorContext = {};
7544
8375
  try {
7545
8376
  const entitySchema = this.EntityConfig[entityType].baseSchema;
@@ -7553,10 +8384,35 @@ var EntityService = class {
7553
8384
  const parsedEntityPayload = entitySchema.parse(entityPayload);
7554
8385
  const parsedMutualPayload = mutualSchema == null ? void 0 : mutualSchema.parse(entityPayload);
7555
8386
  errorContext.parsedMutualPayload = parsedMutualPayload;
8387
+ let opts;
8388
+ if (condition) {
8389
+ const updateConditions = (_b = this.EntityConfig[entityType]) == null ? void 0 : _b.updateConditions;
8390
+ if (!updateConditions) {
8391
+ throw new StandardError(
8392
+ StandardErrorCode.INVALID_CONDITION,
8393
+ `Entity '${entityType}' has no updateConditions defined`
8394
+ );
8395
+ }
8396
+ opts = yield resolveUpdateCondition({
8397
+ conditionName: condition,
8398
+ conditions: updateConditions,
8399
+ getEntityData: () => __async(this, null, function* () {
8400
+ var _a2;
8401
+ const entity2 = yield this.entityRepository.getEntity(entityType, entityId);
8402
+ return (_a2 = entity2 == null ? void 0 : entity2.data) != null ? _a2 : {};
8403
+ })
8404
+ });
8405
+ } else if (where && Object.keys(where).length > 0) {
8406
+ console.warn(
8407
+ "[monorise] $where is deprecated. Use named conditions via $condition instead."
8408
+ );
8409
+ opts = buildConditionExpression(where);
8410
+ }
7556
8411
  const entity = yield this.entityRepository.updateEntity(
7557
8412
  entityType,
7558
8413
  entityId,
7559
- { data: parsedEntityPayload }
8414
+ { data: parsedEntityPayload },
8415
+ opts
7560
8416
  );
7561
8417
  errorContext.entity = entity;
7562
8418
  if (parsedMutualPayload) {
@@ -7564,7 +8420,7 @@ var EntityService = class {
7564
8420
  const byEntityId = entityId;
7565
8421
  const publishEventPromises = [];
7566
8422
  for (const [fieldKey, config] of Object.entries(
7567
- ((_b = this.EntityConfig[entityType].mutual) == null ? void 0 : _b.mutualFields) || {}
8423
+ ((_c = this.EntityConfig[entityType].mutual) == null ? void 0 : _c.mutualFields) || {}
7568
8424
  )) {
7569
8425
  const toMutualIds = config.toMutualIds;
7570
8426
  const mutualPayload = parsedMutualPayload[fieldKey];
@@ -7620,10 +8476,39 @@ var EntityService = class {
7620
8476
  });
7621
8477
  });
7622
8478
  }
8479
+ /** @deprecated Converts legacy adjustmentConstraints to condition expression opts. */
8480
+ buildLegacyAdjustCondition(adjustments, constraints) {
8481
+ const conditionParts = [];
8482
+ const names = { "#data": "data" };
8483
+ const values = {};
8484
+ for (const [field, constraint] of Object.entries(constraints)) {
8485
+ const delta = adjustments[field];
8486
+ if (delta === void 0) continue;
8487
+ const namePlaceholder = `#where_${field}`;
8488
+ names[namePlaceholder] = field;
8489
+ const fieldRef = `#data.${namePlaceholder}`;
8490
+ if (constraint.min !== void 0 && delta < 0) {
8491
+ const valKey = `:where_${field}_min_threshold`;
8492
+ conditionParts.push(`${fieldRef} >= ${valKey}`);
8493
+ values[valKey] = constraint.min - delta;
8494
+ }
8495
+ if (constraint.max !== void 0 && delta > 0) {
8496
+ const valKey = `:where_${field}_max_threshold`;
8497
+ conditionParts.push(`${fieldRef} <= ${valKey}`);
8498
+ values[valKey] = constraint.max - delta;
8499
+ }
8500
+ }
8501
+ if (conditionParts.length === 0) return void 0;
8502
+ return {
8503
+ ConditionExpression: conditionParts.join(" AND "),
8504
+ ExpressionAttributeNames: names,
8505
+ ExpressionAttributeValues: marshall6(values)
8506
+ };
8507
+ }
7623
8508
  };
7624
8509
 
7625
8510
  // services/mutual.service.ts
7626
- import { ulid as ulid3 } from "ulid";
8511
+ import { ulid as ulid4 } from "ulid";
7627
8512
  var MutualService = class {
7628
8513
  constructor(entityRepository, mutualRepository, publishEvent2, ddbUtils, entityServiceLifeCycle) {
7629
8514
  this.entityRepository = entityRepository;
@@ -7683,7 +8568,7 @@ var MutualService = class {
7683
8568
  entityId,
7684
8569
  entityData,
7685
8570
  parsedMutualPayload,
7686
- mutualId || ulid3(),
8571
+ mutualId || ulid4(),
7687
8572
  currentDatetime,
7688
8573
  currentDatetime,
7689
8574
  currentDatetime
@@ -7861,6 +8746,116 @@ var ListTagsController = class {
7861
8746
  }
7862
8747
  };
7863
8748
 
8749
+ // controllers/transaction/execute-transaction.controller.ts
8750
+ import { createMiddleware as createMiddleware17 } from "hono/factory";
8751
+ import httpStatus15 from "http-status";
8752
+ var ExecuteTransactionController = class {
8753
+ constructor(transactionService) {
8754
+ this.transactionService = transactionService;
8755
+ // biome-ignore lint/suspicious/noExplicitAny: Hono createMiddleware requires consistent return types
8756
+ this.controller = createMiddleware17((c) => __async(this, null, function* () {
8757
+ var _a;
8758
+ const accountId = c.req.header("account-id") || "";
8759
+ const body = yield c.req.json();
8760
+ if (!body.operations || !Array.isArray(body.operations)) {
8761
+ c.status(httpStatus15.BAD_REQUEST);
8762
+ return c.json({
8763
+ code: "API_VALIDATION_ERROR",
8764
+ message: 'Request body must contain an "operations" array'
8765
+ });
8766
+ }
8767
+ try {
8768
+ const result = yield this.transactionService.executeTransaction(
8769
+ body.operations,
8770
+ accountId
8771
+ );
8772
+ c.status(httpStatus15.OK);
8773
+ return c.json(result);
8774
+ } catch (err) {
8775
+ if (((_a = err.constructor) == null ? void 0 : _a.name) === "ZodError") {
8776
+ c.status(httpStatus15.BAD_REQUEST);
8777
+ return c.json({
8778
+ code: "API_VALIDATION_ERROR",
8779
+ message: "Validation failed",
8780
+ details: err.flatten()
8781
+ });
8782
+ }
8783
+ if (err instanceof StandardError) {
8784
+ const code = err.code;
8785
+ if (code === StandardErrorCode.TRANSACTION_EMPTY || code === StandardErrorCode.TRANSACTION_ITEM_LIMIT_EXCEEDED || code === StandardErrorCode.TRANSACTION_UNIQUE_FIELD_UPDATE || code === StandardErrorCode.INVALID_ENTITY_TYPE || code === StandardErrorCode.INVALID_CONDITION || code === StandardErrorCode.INVALID_UNIQUE_VALUE_TYPE) {
8786
+ c.status(httpStatus15.BAD_REQUEST);
8787
+ return c.json(__spreadValues({}, err.toJSON()));
8788
+ }
8789
+ if (code === StandardErrorCode.TRANSACTION_FAILED || code === StandardErrorCode.CONDITIONAL_CHECK_FAILED || code === StandardErrorCode.UNIQUE_VALUE_EXISTS) {
8790
+ c.status(httpStatus15.CONFLICT);
8791
+ return c.json(__spreadValues({}, err.toJSON()));
8792
+ }
8793
+ }
8794
+ throw err;
8795
+ }
8796
+ }));
8797
+ }
8798
+ };
8799
+
8800
+ // controllers/ws/create-ticket.controller.ts
8801
+ import { createMiddleware as createMiddleware18 } from "hono/factory";
8802
+ import { ulid as ulid5 } from "ulid";
8803
+ var TICKET_TTL_SECONDS = 30 * 60;
8804
+ var CreateTicketController = class {
8805
+ constructor(container) {
8806
+ this.container = container;
8807
+ this.controller = createMiddleware18((c) => __async(this, null, function* () {
8808
+ var _a;
8809
+ const { entityType, entityId } = c.req.param();
8810
+ let feedTypes;
8811
+ try {
8812
+ const body = yield c.req.json();
8813
+ feedTypes = body.feedTypes;
8814
+ } catch (e) {
8815
+ }
8816
+ if (!feedTypes || feedTypes.length === 0) {
8817
+ const allConfigs = this.container.config.EntityConfig;
8818
+ const visited = /* @__PURE__ */ new Set();
8819
+ const queue = [entityType];
8820
+ while (queue.length > 0) {
8821
+ const current = queue.shift();
8822
+ if (!current) continue;
8823
+ if (visited.has(current)) continue;
8824
+ visited.add(current);
8825
+ const config = allConfigs[current];
8826
+ if ((_a = config == null ? void 0 : config.mutual) == null ? void 0 : _a.mutualFields) {
8827
+ for (const field of Object.values(
8828
+ config.mutual.mutualFields
8829
+ )) {
8830
+ if (!visited.has(field.entityType)) {
8831
+ queue.push(field.entityType);
8832
+ }
8833
+ }
8834
+ }
8835
+ }
8836
+ visited.delete(entityType);
8837
+ feedTypes = Array.from(visited);
8838
+ }
8839
+ const ticket = ulid5();
8840
+ const now = Math.floor(Date.now() / 1e3);
8841
+ const expiresAt = now + TICKET_TTL_SECONDS;
8842
+ yield this.container.websocketRepository.createTicket(
8843
+ ticket,
8844
+ entityType,
8845
+ entityId,
8846
+ feedTypes,
8847
+ expiresAt
8848
+ );
8849
+ const wsEndpoint = process.env.WEBSOCKET_URL || "";
8850
+ return c.json({
8851
+ ticket,
8852
+ wsUrl: wsEndpoint,
8853
+ expiresIn: TICKET_TTL_SECONDS
8854
+ });
8855
+ }));
8856
+ }
8857
+ };
8858
+
7864
8859
  // services/entity-service-lifecycle.ts
7865
8860
  var EntityServiceLifeCycle = class {
7866
8861
  constructor(EntityConfig, publishEvent2, eventUtils) {
@@ -7893,6 +8888,435 @@ var EntityServiceLifeCycle = class {
7893
8888
  }
7894
8889
  };
7895
8890
 
8891
+ // services/transaction.service.ts
8892
+ import { TransactionCanceledException as TransactionCanceledException5 } from "@aws-sdk/client-dynamodb";
8893
+ import { ulid as ulid6 } from "ulid";
8894
+ var MAX_TRANSACTION_ITEMS = 100;
8895
+ var TransactionService = class {
8896
+ constructor(EntityConfig, EmailAuthEnabledEntities, entityRepository, dynamodbClient, publishEvent2, entityServiceLifeCycle, eventUtils) {
8897
+ this.EntityConfig = EntityConfig;
8898
+ this.EmailAuthEnabledEntities = EmailAuthEnabledEntities;
8899
+ this.entityRepository = entityRepository;
8900
+ this.dynamodbClient = dynamodbClient;
8901
+ this.publishEvent = publishEvent2;
8902
+ this.entityServiceLifeCycle = entityServiceLifeCycle;
8903
+ this.eventUtils = eventUtils;
8904
+ this.executeTransaction = (operations, accountId) => __async(this, null, function* () {
8905
+ var _a;
8906
+ if (!operations || operations.length === 0) {
8907
+ throw new StandardError(
8908
+ StandardErrorCode.TRANSACTION_EMPTY,
8909
+ "Transaction must contain at least one operation"
8910
+ );
8911
+ }
8912
+ const allTransactItems = [];
8913
+ const pendingEvents = [];
8914
+ const resultEntries = [];
8915
+ for (const op of operations) {
8916
+ switch (op.operation) {
8917
+ case "createEntity": {
8918
+ const { items, entity } = yield this.buildCreateItems(op);
8919
+ allTransactItems.push(...items);
8920
+ pendingEvents.push(
8921
+ ...this.collectCreateEvents(
8922
+ entity,
8923
+ op.payload,
8924
+ accountId
8925
+ )
8926
+ );
8927
+ resultEntries.push({
8928
+ operation: "createEntity",
8929
+ entityType: op.entityType,
8930
+ entityId: entity.entityId,
8931
+ data: entity.data
8932
+ });
8933
+ break;
8934
+ }
8935
+ case "updateEntity": {
8936
+ const { item, updatedAt } = yield this.buildUpdateItem(op);
8937
+ allTransactItems.push(item);
8938
+ pendingEvents.push(
8939
+ ...this.collectUpdateEvents(
8940
+ op,
8941
+ updatedAt,
8942
+ accountId
8943
+ )
8944
+ );
8945
+ resultEntries.push({
8946
+ operation: "updateEntity",
8947
+ entityType: op.entityType,
8948
+ entityId: op.entityId
8949
+ });
8950
+ break;
8951
+ }
8952
+ case "adjustEntity": {
8953
+ const { item, updatedAt } = yield this.buildAdjustItem(op);
8954
+ allTransactItems.push(item);
8955
+ pendingEvents.push({
8956
+ event: EVENT.CORE.ENTITY_UPDATED,
8957
+ payload: {
8958
+ entityType: op.entityType,
8959
+ entityId: op.entityId,
8960
+ updatedByAccountId: accountId,
8961
+ publishedAt: updatedAt
8962
+ }
8963
+ });
8964
+ resultEntries.push({
8965
+ operation: "adjustEntity",
8966
+ entityType: op.entityType,
8967
+ entityId: op.entityId
8968
+ });
8969
+ break;
8970
+ }
8971
+ case "deleteEntity": {
8972
+ const item = this.buildDeleteItem(op);
8973
+ allTransactItems.push(item);
8974
+ pendingEvents.push({
8975
+ event: EVENT.CORE.ENTITY_DELETED,
8976
+ payload: {
8977
+ entityType: op.entityType,
8978
+ entityId: op.entityId,
8979
+ deletedByAccountId: accountId
8980
+ }
8981
+ });
8982
+ resultEntries.push({
8983
+ operation: "deleteEntity",
8984
+ entityType: op.entityType,
8985
+ entityId: op.entityId
8986
+ });
8987
+ break;
8988
+ }
8989
+ default:
8990
+ throw new StandardError(
8991
+ StandardErrorCode.INVALID_ENTITY_TYPE,
8992
+ `Unknown operation: '${op.operation}'`
8993
+ );
8994
+ }
8995
+ }
8996
+ if (allTransactItems.length > MAX_TRANSACTION_ITEMS) {
8997
+ throw new StandardError(
8998
+ StandardErrorCode.TRANSACTION_ITEM_LIMIT_EXCEEDED,
8999
+ `Transaction contains ${allTransactItems.length} items, exceeds limit of ${MAX_TRANSACTION_ITEMS}`
9000
+ );
9001
+ }
9002
+ try {
9003
+ yield this.dynamodbClient.transactWriteItems({
9004
+ TransactItems: allTransactItems
9005
+ });
9006
+ } catch (err) {
9007
+ if (err instanceof TransactionCanceledException5) {
9008
+ throw new StandardError(
9009
+ StandardErrorCode.TRANSACTION_FAILED,
9010
+ "Transaction failed",
9011
+ err,
9012
+ {
9013
+ reasons: (_a = err.CancellationReasons) == null ? void 0 : _a.map((r, i) => ({
9014
+ index: i,
9015
+ code: r.Code,
9016
+ message: r.Message
9017
+ }))
9018
+ }
9019
+ );
9020
+ }
9021
+ throw err;
9022
+ }
9023
+ const readPromises = resultEntries.map((entry) => __async(this, null, function* () {
9024
+ if ((entry.operation === "updateEntity" || entry.operation === "adjustEntity") && !entry.data) {
9025
+ try {
9026
+ const entity = yield this.entityRepository.getEntity(
9027
+ entry.entityType,
9028
+ entry.entityId
9029
+ );
9030
+ entry.data = entity.data;
9031
+ } catch (e) {
9032
+ }
9033
+ }
9034
+ }));
9035
+ yield Promise.all(readPromises);
9036
+ yield Promise.allSettled(pendingEvents.map((ev) => this.publishEvent(ev)));
9037
+ return { results: resultEntries };
9038
+ });
9039
+ }
9040
+ buildCreateItems(op) {
9041
+ return __async(this, null, function* () {
9042
+ const config = this.EntityConfig[op.entityType];
9043
+ if (!config) {
9044
+ throw new StandardError(
9045
+ StandardErrorCode.INVALID_ENTITY_TYPE,
9046
+ `Unknown entity type: '${op.entityType}'`
9047
+ );
9048
+ }
9049
+ const entitySchema = config.createSchema || config.baseSchema;
9050
+ if (!entitySchema) {
9051
+ throw new StandardError(
9052
+ StandardErrorCode.INVALID_ENTITY_TYPE,
9053
+ `No schema defined for entity type: '${op.entityType}'`
9054
+ );
9055
+ }
9056
+ if (config.finalSchema) {
9057
+ config.finalSchema.parse(op.payload);
9058
+ }
9059
+ const parsedPayload = entitySchema.parse(
9060
+ op.payload
9061
+ );
9062
+ const currentDatetime = /* @__PURE__ */ new Date();
9063
+ const entity = new Entity(
9064
+ op.entityType,
9065
+ op.entityId || ulid6(),
9066
+ parsedPayload,
9067
+ currentDatetime,
9068
+ currentDatetime
9069
+ );
9070
+ const uniqueFields = config.uniqueFields || [];
9071
+ const uniqueFieldValues = {};
9072
+ for (const field of uniqueFields) {
9073
+ if (!(field in parsedPayload)) continue;
9074
+ const value = parsedPayload[field];
9075
+ if (typeof value !== "string") {
9076
+ throw new StandardError(
9077
+ StandardErrorCode.INVALID_UNIQUE_VALUE_TYPE,
9078
+ `Invalid type. ${field} is not a 'string'.`
9079
+ );
9080
+ }
9081
+ uniqueFieldValues[field] = value;
9082
+ }
9083
+ const items = this.entityRepository.createEntityTransactItems(entity, {
9084
+ uniqueFieldValues
9085
+ });
9086
+ return { items, entity };
9087
+ });
9088
+ }
9089
+ buildUpdateItem(op) {
9090
+ return __async(this, null, function* () {
9091
+ const config = this.EntityConfig[op.entityType];
9092
+ if (!config) {
9093
+ throw new StandardError(
9094
+ StandardErrorCode.INVALID_ENTITY_TYPE,
9095
+ `Unknown entity type: '${op.entityType}'`
9096
+ );
9097
+ }
9098
+ const uniqueFields = config.uniqueFields || [];
9099
+ for (const field of uniqueFields) {
9100
+ if (field in op.payload) {
9101
+ throw new StandardError(
9102
+ StandardErrorCode.TRANSACTION_UNIQUE_FIELD_UPDATE,
9103
+ `Cannot update unique field '${field}' within a transaction. Use a standalone updateEntity call instead.`
9104
+ );
9105
+ }
9106
+ }
9107
+ const entitySchema = config.baseSchema;
9108
+ if (!entitySchema) {
9109
+ throw new StandardError(
9110
+ StandardErrorCode.INVALID_ENTITY_TYPE,
9111
+ `No schema defined for entity type: '${op.entityType}'`
9112
+ );
9113
+ }
9114
+ const parsedPayload = entitySchema.partial().parse(op.payload);
9115
+ const currentDatetime = (/* @__PURE__ */ new Date()).toISOString();
9116
+ const toUpdateExpressions = this.entityRepository.toUpdate({
9117
+ updatedAt: currentDatetime,
9118
+ data: parsedPayload
9119
+ });
9120
+ let conditionOpts;
9121
+ if (op.condition) {
9122
+ const updateConditions = config.updateConditions;
9123
+ if (!updateConditions) {
9124
+ throw new StandardError(
9125
+ StandardErrorCode.INVALID_CONDITION,
9126
+ `Entity '${op.entityType}' has no updateConditions defined`
9127
+ );
9128
+ }
9129
+ conditionOpts = yield resolveUpdateCondition({
9130
+ conditionName: op.condition,
9131
+ conditions: updateConditions,
9132
+ getEntityData: () => __async(this, null, function* () {
9133
+ var _a;
9134
+ const entity2 = yield this.entityRepository.getEntity(
9135
+ op.entityType,
9136
+ op.entityId
9137
+ );
9138
+ return (_a = entity2 == null ? void 0 : entity2.data) != null ? _a : {};
9139
+ })
9140
+ });
9141
+ }
9142
+ const entity = new Entity(op.entityType, op.entityId);
9143
+ const item = {
9144
+ Update: {
9145
+ TableName: this.entityRepository.TABLE_NAME,
9146
+ Key: entity.keys(),
9147
+ ConditionExpression: (conditionOpts == null ? void 0 : conditionOpts.ConditionExpression) || "attribute_exists(PK)",
9148
+ UpdateExpression: toUpdateExpressions.UpdateExpression,
9149
+ ExpressionAttributeNames: __spreadValues(__spreadValues({}, toUpdateExpressions.ExpressionAttributeNames), conditionOpts == null ? void 0 : conditionOpts.ExpressionAttributeNames),
9150
+ ExpressionAttributeValues: __spreadValues(__spreadValues({}, toUpdateExpressions.ExpressionAttributeValues), conditionOpts == null ? void 0 : conditionOpts.ExpressionAttributeValues)
9151
+ }
9152
+ };
9153
+ return { item, updatedAt: currentDatetime };
9154
+ });
9155
+ }
9156
+ buildAdjustItem(op) {
9157
+ return __async(this, null, function* () {
9158
+ const config = this.EntityConfig[op.entityType];
9159
+ if (!config) {
9160
+ throw new StandardError(
9161
+ StandardErrorCode.INVALID_ENTITY_TYPE,
9162
+ `Unknown entity type: '${op.entityType}'`
9163
+ );
9164
+ }
9165
+ for (const [key, value] of Object.entries(op.adjustments)) {
9166
+ if (typeof value !== "number" || !Number.isFinite(value)) {
9167
+ throw new StandardError(
9168
+ StandardErrorCode.INVALID_ENTITY_TYPE,
9169
+ `Adjustment field "${key}" must be a finite number`
9170
+ );
9171
+ }
9172
+ }
9173
+ const {
9174
+ UpdateExpression,
9175
+ ExpressionAttributeNames,
9176
+ ExpressionAttributeValues
9177
+ } = this.entityRepository.toAdjustUpdate(op.adjustments);
9178
+ const currentDatetime = (/* @__PURE__ */ new Date()).toISOString();
9179
+ ExpressionAttributeNames["#updatedAt"] = "updatedAt";
9180
+ ExpressionAttributeValues[":updatedAt"] = { S: currentDatetime };
9181
+ const fullUpdateExpression = `${UpdateExpression}, #updatedAt = :updatedAt`;
9182
+ let conditionOpts;
9183
+ const adjustmentConditions = config.adjustmentConditions;
9184
+ if (adjustmentConditions) {
9185
+ if (!op.condition) {
9186
+ throw new StandardError(
9187
+ StandardErrorCode.INVALID_CONDITION,
9188
+ `Entity '${op.entityType}' has adjustmentConditions defined; condition is required`
9189
+ );
9190
+ }
9191
+ conditionOpts = yield resolveAdjustmentCondition({
9192
+ conditionName: op.condition,
9193
+ conditions: adjustmentConditions,
9194
+ adjustments: op.adjustments,
9195
+ getEntityData: () => __async(this, null, function* () {
9196
+ var _a;
9197
+ const entity2 = yield this.entityRepository.getEntity(
9198
+ op.entityType,
9199
+ op.entityId
9200
+ );
9201
+ return (_a = entity2 == null ? void 0 : entity2.data) != null ? _a : {};
9202
+ })
9203
+ });
9204
+ }
9205
+ const entity = new Entity(op.entityType, op.entityId);
9206
+ const item = {
9207
+ Update: {
9208
+ TableName: this.entityRepository.TABLE_NAME,
9209
+ Key: entity.keys(),
9210
+ UpdateExpression: fullUpdateExpression,
9211
+ ConditionExpression: (conditionOpts == null ? void 0 : conditionOpts.ConditionExpression) || "attribute_exists(PK)",
9212
+ ExpressionAttributeNames: __spreadValues(__spreadValues({}, ExpressionAttributeNames), conditionOpts == null ? void 0 : conditionOpts.ExpressionAttributeNames),
9213
+ ExpressionAttributeValues: __spreadValues(__spreadValues({}, ExpressionAttributeValues), conditionOpts == null ? void 0 : conditionOpts.ExpressionAttributeValues)
9214
+ }
9215
+ };
9216
+ return { item, updatedAt: currentDatetime };
9217
+ });
9218
+ }
9219
+ buildDeleteItem(op) {
9220
+ const config = this.EntityConfig[op.entityType];
9221
+ if (!config) {
9222
+ throw new StandardError(
9223
+ StandardErrorCode.INVALID_ENTITY_TYPE,
9224
+ `Unknown entity type: '${op.entityType}'`
9225
+ );
9226
+ }
9227
+ const entity = new Entity(op.entityType, op.entityId);
9228
+ return {
9229
+ Delete: {
9230
+ TableName: this.entityRepository.TABLE_NAME,
9231
+ Key: entity.keys(),
9232
+ ConditionExpression: "attribute_exists(PK)"
9233
+ }
9234
+ };
9235
+ }
9236
+ collectCreateEvents(entity, payload, accountId) {
9237
+ var _a, _b;
9238
+ const events = [];
9239
+ const publishedAt = entity.updatedAt || (/* @__PURE__ */ new Date()).toISOString();
9240
+ const config = this.EntityConfig[entity.entityType];
9241
+ const mutualSchema = (_a = config == null ? void 0 : config.mutual) == null ? void 0 : _a.mutualSchema;
9242
+ if (mutualSchema) {
9243
+ const parsedMutualPayload = mutualSchema.parse(payload);
9244
+ if (parsedMutualPayload) {
9245
+ for (const [fieldKey, fieldConfig] of Object.entries(
9246
+ ((_b = config.mutual) == null ? void 0 : _b.mutualFields) || {}
9247
+ )) {
9248
+ const toMutualIds = fieldConfig.toMutualIds;
9249
+ const mutualPayload = parsedMutualPayload[fieldKey];
9250
+ if (!mutualPayload) continue;
9251
+ events.push({
9252
+ event: EVENT.CORE.ENTITY_MUTUAL_TO_CREATE,
9253
+ payload: {
9254
+ byEntityType: entity.entityType,
9255
+ byEntityId: entity.entityId,
9256
+ entityType: fieldConfig.entityType,
9257
+ field: fieldKey,
9258
+ mutualIds: toMutualIds ? toMutualIds(mutualPayload) : mutualPayload,
9259
+ customContext: toMutualIds ? mutualPayload : {},
9260
+ publishedAt
9261
+ }
9262
+ });
9263
+ }
9264
+ }
9265
+ }
9266
+ events.push({
9267
+ event: EVENT.CORE.ENTITY_CREATED,
9268
+ payload: {
9269
+ entityType: entity.entityType,
9270
+ entityId: entity.entityId,
9271
+ data: entity.data,
9272
+ createdByAccountId: accountId,
9273
+ publishedAt
9274
+ }
9275
+ });
9276
+ return events;
9277
+ }
9278
+ collectUpdateEvents(op, updatedAt, accountId) {
9279
+ var _a, _b;
9280
+ const events = [];
9281
+ const config = this.EntityConfig[op.entityType];
9282
+ const mutualSchema = (_a = config == null ? void 0 : config.mutual) == null ? void 0 : _a.mutualSchema;
9283
+ if (mutualSchema) {
9284
+ const parsedMutualPayload = mutualSchema.parse(op.payload);
9285
+ if (parsedMutualPayload) {
9286
+ for (const [fieldKey, fieldConfig] of Object.entries(
9287
+ ((_b = config.mutual) == null ? void 0 : _b.mutualFields) || {}
9288
+ )) {
9289
+ const toMutualIds = fieldConfig.toMutualIds;
9290
+ const mutualPayload = parsedMutualPayload[fieldKey];
9291
+ if (!mutualPayload) continue;
9292
+ events.push({
9293
+ event: EVENT.CORE.ENTITY_MUTUAL_TO_UPDATE,
9294
+ payload: {
9295
+ byEntityType: op.entityType,
9296
+ byEntityId: op.entityId,
9297
+ entityType: fieldConfig.entityType,
9298
+ field: fieldKey,
9299
+ mutualIds: toMutualIds ? toMutualIds(mutualPayload) : mutualPayload,
9300
+ customContext: toMutualIds ? mutualPayload : {},
9301
+ publishedAt: updatedAt
9302
+ }
9303
+ });
9304
+ }
9305
+ }
9306
+ }
9307
+ events.push({
9308
+ event: EVENT.CORE.ENTITY_UPDATED,
9309
+ payload: {
9310
+ entityType: op.entityType,
9311
+ entityId: op.entityId,
9312
+ updatedByAccountId: accountId,
9313
+ publishedAt: updatedAt
9314
+ }
9315
+ });
9316
+ return events;
9317
+ }
9318
+ };
9319
+
7896
9320
  // services/DependencyContainer.ts
7897
9321
  var DependencyContainer = class {
7898
9322
  constructor(config) {
@@ -7985,6 +9409,13 @@ var DependencyContainer = class {
7985
9409
  this.dynamodbClient
7986
9410
  );
7987
9411
  }
9412
+ get websocketRepository() {
9413
+ return this.createCachedInstance(
9414
+ WebSocketRepository,
9415
+ this.coreTable,
9416
+ this.dynamodbClient
9417
+ );
9418
+ }
7988
9419
  get getEntityController() {
7989
9420
  return this.createCachedInstance(
7990
9421
  GetEntityController,
@@ -8068,6 +9499,62 @@ var DependencyContainer = class {
8068
9499
  get listTagsController() {
8069
9500
  return this.createCachedInstance(ListTagsController, this.tagRepository);
8070
9501
  }
9502
+ get transactionService() {
9503
+ return this.createCachedInstance(
9504
+ TransactionService,
9505
+ this.config.EntityConfig,
9506
+ this.config.EmailAuthEnabledEntities,
9507
+ this.entityRepository,
9508
+ this.dynamodbClient,
9509
+ this.publishEvent,
9510
+ this.entityServiceLifeCycle,
9511
+ this.eventUtils
9512
+ );
9513
+ }
9514
+ get executeTransactionController() {
9515
+ return this.createCachedInstance(
9516
+ ExecuteTransactionController,
9517
+ this.transactionService
9518
+ );
9519
+ }
9520
+ get createTicketController() {
9521
+ return this.createCachedInstance(CreateTicketController, this);
9522
+ }
9523
+ };
9524
+
9525
+ // helpers/transactional.ts
9526
+ var transactional = {
9527
+ createEntity: (entityType, payload) => {
9528
+ const _a = payload, { entityId } = _a, rest = __objRest(_a, ["entityId"]);
9529
+ return __spreadValues({
9530
+ operation: "createEntity",
9531
+ entityType,
9532
+ payload: rest
9533
+ }, entityId && { entityId });
9534
+ },
9535
+ updateEntity: (entityType, entityId, payload) => {
9536
+ const _a = payload, { $condition } = _a, rest = __objRest(_a, ["$condition"]);
9537
+ return __spreadValues({
9538
+ operation: "updateEntity",
9539
+ entityType,
9540
+ entityId,
9541
+ payload: rest
9542
+ }, $condition && { condition: $condition });
9543
+ },
9544
+ adjustEntity: (entityType, entityId, adjustments) => {
9545
+ const _a = adjustments, { $condition } = _a, rest = __objRest(_a, ["$condition"]);
9546
+ return __spreadValues({
9547
+ operation: "adjustEntity",
9548
+ entityType,
9549
+ entityId,
9550
+ adjustments: rest
9551
+ }, $condition && { condition: $condition });
9552
+ },
9553
+ deleteEntity: (entityType, entityId) => ({
9554
+ operation: "deleteEntity",
9555
+ entityType,
9556
+ entityId
9557
+ })
8071
9558
  };
8072
9559
 
8073
9560
  // index.ts
@@ -8083,6 +9570,10 @@ var CoreFactory = class {
8083
9570
  this.prejoinProcessor = handler3(dependencyContainer);
8084
9571
  this.tagProcessor = handler5(dependencyContainer);
8085
9572
  this.appHandler = appHandler(dependencyContainer);
9573
+ this.wsConnect = connect(dependencyContainer);
9574
+ this.wsDisconnect = disconnect(dependencyContainer);
9575
+ this.wsDefault = $default(dependencyContainer);
9576
+ this.wsBroadcast = broadcast(dependencyContainer);
8086
9577
  }
8087
9578
  };
8088
9579
  var index_default = CoreFactory;
@@ -8098,6 +9589,8 @@ export {
8098
9589
  StandardError,
8099
9590
  StandardErrorCode,
8100
9591
  TagRepository,
9592
+ TransactionService,
9593
+ WebSocketRepository,
8101
9594
  appHandler,
8102
9595
  handler as createEntityProcessor,
8103
9596
  index_default as default,
@@ -8105,6 +9598,11 @@ export {
8105
9598
  handler3 as prejoinProcessor,
8106
9599
  handler4 as replicationProcessor,
8107
9600
  setupCommonRoutes,
8108
- handler5 as tagProcessor
9601
+ handler5 as tagProcessor,
9602
+ transactional,
9603
+ broadcast as wsBroadcast,
9604
+ connect as wsConnect,
9605
+ $default as wsDefault,
9606
+ disconnect as wsDisconnect
8109
9607
  };
8110
9608
  //# sourceMappingURL=index.js.map