happy2 0.0.5

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 (373) hide show
  1. package/README.md +82 -0
  2. package/package.json +74 -0
  3. package/packages/happy2-server/Dockerfile +18 -0
  4. package/packages/happy2-server/README.md +418 -0
  5. package/packages/happy2-server/bin/happy2.js +3 -0
  6. package/packages/happy2-server/dist/cli.d.ts +3 -0
  7. package/packages/happy2-server/dist/cli.d.ts.map +1 -0
  8. package/packages/happy2-server/dist/cli.js +44 -0
  9. package/packages/happy2-server/dist/cli.js.map +1 -0
  10. package/packages/happy2-server/dist/index.d.ts +24 -0
  11. package/packages/happy2-server/dist/index.d.ts.map +1 -0
  12. package/packages/happy2-server/dist/index.js +22 -0
  13. package/packages/happy2-server/dist/index.js.map +1 -0
  14. package/packages/happy2-server/dist/modules/agents/builtin-images.d.ts +8 -0
  15. package/packages/happy2-server/dist/modules/agents/builtin-images.d.ts.map +1 -0
  16. package/packages/happy2-server/dist/modules/agents/builtin-images.js +283 -0
  17. package/packages/happy2-server/dist/modules/agents/builtin-images.js.map +1 -0
  18. package/packages/happy2-server/dist/modules/agents/command.d.ts +3 -0
  19. package/packages/happy2-server/dist/modules/agents/command.d.ts.map +1 -0
  20. package/packages/happy2-server/dist/modules/agents/command.js +7 -0
  21. package/packages/happy2-server/dist/modules/agents/command.js.map +1 -0
  22. package/packages/happy2-server/dist/modules/agents/daemon.d.ts +106 -0
  23. package/packages/happy2-server/dist/modules/agents/daemon.d.ts.map +1 -0
  24. package/packages/happy2-server/dist/modules/agents/daemon.js +522 -0
  25. package/packages/happy2-server/dist/modules/agents/daemon.js.map +1 -0
  26. package/packages/happy2-server/dist/modules/agents/docker.d.ts +51 -0
  27. package/packages/happy2-server/dist/modules/agents/docker.d.ts.map +1 -0
  28. package/packages/happy2-server/dist/modules/agents/docker.js +256 -0
  29. package/packages/happy2-server/dist/modules/agents/docker.js.map +1 -0
  30. package/packages/happy2-server/dist/modules/agents/docker.test.d.ts +2 -0
  31. package/packages/happy2-server/dist/modules/agents/docker.test.d.ts.map +1 -0
  32. package/packages/happy2-server/dist/modules/agents/docker.test.js +155 -0
  33. package/packages/happy2-server/dist/modules/agents/docker.test.js.map +1 -0
  34. package/packages/happy2-server/dist/modules/agents/index.d.ts +5 -0
  35. package/packages/happy2-server/dist/modules/agents/index.d.ts.map +1 -0
  36. package/packages/happy2-server/dist/modules/agents/index.js +4 -0
  37. package/packages/happy2-server/dist/modules/agents/index.js.map +1 -0
  38. package/packages/happy2-server/dist/modules/agents/service.d.ts +140 -0
  39. package/packages/happy2-server/dist/modules/agents/service.d.ts.map +1 -0
  40. package/packages/happy2-server/dist/modules/agents/service.js +1283 -0
  41. package/packages/happy2-server/dist/modules/agents/service.js.map +1 -0
  42. package/packages/happy2-server/dist/modules/auth/cloudflare-access.d.ts +15 -0
  43. package/packages/happy2-server/dist/modules/auth/cloudflare-access.d.ts.map +1 -0
  44. package/packages/happy2-server/dist/modules/auth/cloudflare-access.js +49 -0
  45. package/packages/happy2-server/dist/modules/auth/cloudflare-access.js.map +1 -0
  46. package/packages/happy2-server/dist/modules/auth/crypto.d.ts +4 -0
  47. package/packages/happy2-server/dist/modules/auth/crypto.d.ts.map +1 -0
  48. package/packages/happy2-server/dist/modules/auth/crypto.js +31 -0
  49. package/packages/happy2-server/dist/modules/auth/crypto.js.map +1 -0
  50. package/packages/happy2-server/dist/modules/auth/crypto.test.d.ts +2 -0
  51. package/packages/happy2-server/dist/modules/auth/crypto.test.d.ts.map +1 -0
  52. package/packages/happy2-server/dist/modules/auth/crypto.test.js +11 -0
  53. package/packages/happy2-server/dist/modules/auth/crypto.test.js.map +1 -0
  54. package/packages/happy2-server/dist/modules/auth/email.d.ts +3 -0
  55. package/packages/happy2-server/dist/modules/auth/email.d.ts.map +1 -0
  56. package/packages/happy2-server/dist/modules/auth/email.js +22 -0
  57. package/packages/happy2-server/dist/modules/auth/email.js.map +1 -0
  58. package/packages/happy2-server/dist/modules/auth/metadata.d.ts +5 -0
  59. package/packages/happy2-server/dist/modules/auth/metadata.d.ts.map +1 -0
  60. package/packages/happy2-server/dist/modules/auth/metadata.js +28 -0
  61. package/packages/happy2-server/dist/modules/auth/metadata.js.map +1 -0
  62. package/packages/happy2-server/dist/modules/auth/metadata.test.d.ts +2 -0
  63. package/packages/happy2-server/dist/modules/auth/metadata.test.d.ts.map +1 -0
  64. package/packages/happy2-server/dist/modules/auth/metadata.test.js +10 -0
  65. package/packages/happy2-server/dist/modules/auth/metadata.test.js.map +1 -0
  66. package/packages/happy2-server/dist/modules/auth/methods.d.ts +10 -0
  67. package/packages/happy2-server/dist/modules/auth/methods.d.ts.map +1 -0
  68. package/packages/happy2-server/dist/modules/auth/methods.js +21 -0
  69. package/packages/happy2-server/dist/modules/auth/methods.js.map +1 -0
  70. package/packages/happy2-server/dist/modules/auth/methods.test.d.ts +2 -0
  71. package/packages/happy2-server/dist/modules/auth/methods.test.d.ts.map +1 -0
  72. package/packages/happy2-server/dist/modules/auth/methods.test.js +16 -0
  73. package/packages/happy2-server/dist/modules/auth/methods.test.js.map +1 -0
  74. package/packages/happy2-server/dist/modules/auth/oidc.d.ts +9 -0
  75. package/packages/happy2-server/dist/modules/auth/oidc.d.ts.map +1 -0
  76. package/packages/happy2-server/dist/modules/auth/oidc.js +68 -0
  77. package/packages/happy2-server/dist/modules/auth/oidc.js.map +1 -0
  78. package/packages/happy2-server/dist/modules/auth/service.d.ts +44 -0
  79. package/packages/happy2-server/dist/modules/auth/service.d.ts.map +1 -0
  80. package/packages/happy2-server/dist/modules/auth/service.js +208 -0
  81. package/packages/happy2-server/dist/modules/auth/service.js.map +1 -0
  82. package/packages/happy2-server/dist/modules/auth/tokens.d.ts +21 -0
  83. package/packages/happy2-server/dist/modules/auth/tokens.d.ts.map +1 -0
  84. package/packages/happy2-server/dist/modules/auth/tokens.js +79 -0
  85. package/packages/happy2-server/dist/modules/auth/tokens.js.map +1 -0
  86. package/packages/happy2-server/dist/modules/automation/repository.d.ts +127 -0
  87. package/packages/happy2-server/dist/modules/automation/repository.d.ts.map +1 -0
  88. package/packages/happy2-server/dist/modules/automation/repository.js +821 -0
  89. package/packages/happy2-server/dist/modules/automation/repository.js.map +1 -0
  90. package/packages/happy2-server/dist/modules/collaboration/repository.d.ts +839 -0
  91. package/packages/happy2-server/dist/modules/collaboration/repository.d.ts.map +1 -0
  92. package/packages/happy2-server/dist/modules/collaboration/repository.js +5795 -0
  93. package/packages/happy2-server/dist/modules/collaboration/repository.js.map +1 -0
  94. package/packages/happy2-server/dist/modules/collaboration/repository.test.d.ts +2 -0
  95. package/packages/happy2-server/dist/modules/collaboration/repository.test.d.ts.map +1 -0
  96. package/packages/happy2-server/dist/modules/collaboration/repository.test.js +620 -0
  97. package/packages/happy2-server/dist/modules/collaboration/repository.test.js.map +1 -0
  98. package/packages/happy2-server/dist/modules/collaboration/types.d.ts +243 -0
  99. package/packages/happy2-server/dist/modules/collaboration/types.d.ts.map +1 -0
  100. package/packages/happy2-server/dist/modules/collaboration/types.js +8 -0
  101. package/packages/happy2-server/dist/modules/collaboration/types.js.map +1 -0
  102. package/packages/happy2-server/dist/modules/config/defaults.d.ts +8 -0
  103. package/packages/happy2-server/dist/modules/config/defaults.d.ts.map +1 -0
  104. package/packages/happy2-server/dist/modules/config/defaults.js +70 -0
  105. package/packages/happy2-server/dist/modules/config/defaults.js.map +1 -0
  106. package/packages/happy2-server/dist/modules/config/defaults.test.d.ts +2 -0
  107. package/packages/happy2-server/dist/modules/config/defaults.test.d.ts.map +1 -0
  108. package/packages/happy2-server/dist/modules/config/defaults.test.js +27 -0
  109. package/packages/happy2-server/dist/modules/config/defaults.test.js.map +1 -0
  110. package/packages/happy2-server/dist/modules/config/environment.d.ts +4 -0
  111. package/packages/happy2-server/dist/modules/config/environment.d.ts.map +1 -0
  112. package/packages/happy2-server/dist/modules/config/environment.js +92 -0
  113. package/packages/happy2-server/dist/modules/config/environment.js.map +1 -0
  114. package/packages/happy2-server/dist/modules/config/loader.d.ts +5 -0
  115. package/packages/happy2-server/dist/modules/config/loader.d.ts.map +1 -0
  116. package/packages/happy2-server/dist/modules/config/loader.js +251 -0
  117. package/packages/happy2-server/dist/modules/config/loader.js.map +1 -0
  118. package/packages/happy2-server/dist/modules/config/loader.test.d.ts +2 -0
  119. package/packages/happy2-server/dist/modules/config/loader.test.d.ts.map +1 -0
  120. package/packages/happy2-server/dist/modules/config/loader.test.js +108 -0
  121. package/packages/happy2-server/dist/modules/config/loader.test.js.map +1 -0
  122. package/packages/happy2-server/dist/modules/config/paths.d.ts +7 -0
  123. package/packages/happy2-server/dist/modules/config/paths.d.ts.map +1 -0
  124. package/packages/happy2-server/dist/modules/config/paths.js +15 -0
  125. package/packages/happy2-server/dist/modules/config/paths.js.map +1 -0
  126. package/packages/happy2-server/dist/modules/config/paths.test.d.ts +2 -0
  127. package/packages/happy2-server/dist/modules/config/paths.test.d.ts.map +1 -0
  128. package/packages/happy2-server/dist/modules/config/paths.test.js +22 -0
  129. package/packages/happy2-server/dist/modules/config/paths.test.js.map +1 -0
  130. package/packages/happy2-server/dist/modules/config/runtime.d.ts +6 -0
  131. package/packages/happy2-server/dist/modules/config/runtime.d.ts.map +1 -0
  132. package/packages/happy2-server/dist/modules/config/runtime.js +14 -0
  133. package/packages/happy2-server/dist/modules/config/runtime.js.map +1 -0
  134. package/packages/happy2-server/dist/modules/config/type.d.ts +88 -0
  135. package/packages/happy2-server/dist/modules/config/type.d.ts.map +1 -0
  136. package/packages/happy2-server/dist/modules/config/type.js +2 -0
  137. package/packages/happy2-server/dist/modules/config/type.js.map +1 -0
  138. package/packages/happy2-server/dist/modules/database.d.ts +105 -0
  139. package/packages/happy2-server/dist/modules/database.d.ts.map +1 -0
  140. package/packages/happy2-server/dist/modules/database.js +583 -0
  141. package/packages/happy2-server/dist/modules/database.js.map +1 -0
  142. package/packages/happy2-server/dist/modules/drizzle.d.ts +11 -0
  143. package/packages/happy2-server/dist/modules/drizzle.d.ts.map +1 -0
  144. package/packages/happy2-server/dist/modules/drizzle.js +31 -0
  145. package/packages/happy2-server/dist/modules/drizzle.js.map +1 -0
  146. package/packages/happy2-server/dist/modules/files/lock.d.ts +3 -0
  147. package/packages/happy2-server/dist/modules/files/lock.d.ts.map +1 -0
  148. package/packages/happy2-server/dist/modules/files/lock.js +83 -0
  149. package/packages/happy2-server/dist/modules/files/lock.js.map +1 -0
  150. package/packages/happy2-server/dist/modules/files/media.d.ts +18 -0
  151. package/packages/happy2-server/dist/modules/files/media.d.ts.map +1 -0
  152. package/packages/happy2-server/dist/modules/files/media.js +352 -0
  153. package/packages/happy2-server/dist/modules/files/media.js.map +1 -0
  154. package/packages/happy2-server/dist/modules/files/provider.d.ts +130 -0
  155. package/packages/happy2-server/dist/modules/files/provider.d.ts.map +1 -0
  156. package/packages/happy2-server/dist/modules/files/provider.js +448 -0
  157. package/packages/happy2-server/dist/modules/files/provider.js.map +1 -0
  158. package/packages/happy2-server/dist/modules/files/quota.d.ts +58 -0
  159. package/packages/happy2-server/dist/modules/files/quota.d.ts.map +1 -0
  160. package/packages/happy2-server/dist/modules/files/quota.js +180 -0
  161. package/packages/happy2-server/dist/modules/files/quota.js.map +1 -0
  162. package/packages/happy2-server/dist/modules/files/routes.test.d.ts +2 -0
  163. package/packages/happy2-server/dist/modules/files/routes.test.d.ts.map +1 -0
  164. package/packages/happy2-server/dist/modules/files/routes.test.js +163 -0
  165. package/packages/happy2-server/dist/modules/files/routes.test.js.map +1 -0
  166. package/packages/happy2-server/dist/modules/files/scanner.d.ts +27 -0
  167. package/packages/happy2-server/dist/modules/files/scanner.d.ts.map +1 -0
  168. package/packages/happy2-server/dist/modules/files/scanner.js +66 -0
  169. package/packages/happy2-server/dist/modules/files/scanner.js.map +1 -0
  170. package/packages/happy2-server/dist/modules/files/storage.d.ts +95 -0
  171. package/packages/happy2-server/dist/modules/files/storage.d.ts.map +1 -0
  172. package/packages/happy2-server/dist/modules/files/storage.js +855 -0
  173. package/packages/happy2-server/dist/modules/files/storage.js.map +1 -0
  174. package/packages/happy2-server/dist/modules/files/storage.test.d.ts +2 -0
  175. package/packages/happy2-server/dist/modules/files/storage.test.d.ts.map +1 -0
  176. package/packages/happy2-server/dist/modules/files/storage.test.js +170 -0
  177. package/packages/happy2-server/dist/modules/files/storage.test.js.map +1 -0
  178. package/packages/happy2-server/dist/modules/integrations/index.d.ts +6 -0
  179. package/packages/happy2-server/dist/modules/integrations/index.d.ts.map +1 -0
  180. package/packages/happy2-server/dist/modules/integrations/index.js +6 -0
  181. package/packages/happy2-server/dist/modules/integrations/index.js.map +1 -0
  182. package/packages/happy2-server/dist/modules/integrations/repository.d.ts +136 -0
  183. package/packages/happy2-server/dist/modules/integrations/repository.d.ts.map +1 -0
  184. package/packages/happy2-server/dist/modules/integrations/repository.js +1229 -0
  185. package/packages/happy2-server/dist/modules/integrations/repository.js.map +1 -0
  186. package/packages/happy2-server/dist/modules/integrations/repository.test.d.ts +2 -0
  187. package/packages/happy2-server/dist/modules/integrations/repository.test.d.ts.map +1 -0
  188. package/packages/happy2-server/dist/modules/integrations/repository.test.js +345 -0
  189. package/packages/happy2-server/dist/modules/integrations/repository.test.js.map +1 -0
  190. package/packages/happy2-server/dist/modules/integrations/routes.test.d.ts +2 -0
  191. package/packages/happy2-server/dist/modules/integrations/routes.test.d.ts.map +1 -0
  192. package/packages/happy2-server/dist/modules/integrations/routes.test.js +161 -0
  193. package/packages/happy2-server/dist/modules/integrations/routes.test.js.map +1 -0
  194. package/packages/happy2-server/dist/modules/integrations/secrets.d.ts +19 -0
  195. package/packages/happy2-server/dist/modules/integrations/secrets.d.ts.map +1 -0
  196. package/packages/happy2-server/dist/modules/integrations/secrets.js +69 -0
  197. package/packages/happy2-server/dist/modules/integrations/secrets.js.map +1 -0
  198. package/packages/happy2-server/dist/modules/integrations/ssrf.d.ts +32 -0
  199. package/packages/happy2-server/dist/modules/integrations/ssrf.d.ts.map +1 -0
  200. package/packages/happy2-server/dist/modules/integrations/ssrf.js +185 -0
  201. package/packages/happy2-server/dist/modules/integrations/ssrf.js.map +1 -0
  202. package/packages/happy2-server/dist/modules/integrations/ssrf.test.d.ts +2 -0
  203. package/packages/happy2-server/dist/modules/integrations/ssrf.test.d.ts.map +1 -0
  204. package/packages/happy2-server/dist/modules/integrations/ssrf.test.js +56 -0
  205. package/packages/happy2-server/dist/modules/integrations/ssrf.test.js.map +1 -0
  206. package/packages/happy2-server/dist/modules/integrations/transport.d.ts +21 -0
  207. package/packages/happy2-server/dist/modules/integrations/transport.d.ts.map +1 -0
  208. package/packages/happy2-server/dist/modules/integrations/transport.js +108 -0
  209. package/packages/happy2-server/dist/modules/integrations/transport.js.map +1 -0
  210. package/packages/happy2-server/dist/modules/integrations/transport.test.d.ts +2 -0
  211. package/packages/happy2-server/dist/modules/integrations/transport.test.d.ts.map +1 -0
  212. package/packages/happy2-server/dist/modules/integrations/transport.test.js +66 -0
  213. package/packages/happy2-server/dist/modules/integrations/transport.test.js.map +1 -0
  214. package/packages/happy2-server/dist/modules/integrations/types.d.ts +155 -0
  215. package/packages/happy2-server/dist/modules/integrations/types.d.ts.map +1 -0
  216. package/packages/happy2-server/dist/modules/integrations/types.js +26 -0
  217. package/packages/happy2-server/dist/modules/integrations/types.js.map +1 -0
  218. package/packages/happy2-server/dist/modules/operations/export-worker.d.ts +16 -0
  219. package/packages/happy2-server/dist/modules/operations/export-worker.d.ts.map +1 -0
  220. package/packages/happy2-server/dist/modules/operations/export-worker.js +56 -0
  221. package/packages/happy2-server/dist/modules/operations/export-worker.js.map +1 -0
  222. package/packages/happy2-server/dist/modules/operations/repository.d.ts +215 -0
  223. package/packages/happy2-server/dist/modules/operations/repository.d.ts.map +1 -0
  224. package/packages/happy2-server/dist/modules/operations/repository.js +2011 -0
  225. package/packages/happy2-server/dist/modules/operations/repository.js.map +1 -0
  226. package/packages/happy2-server/dist/modules/operations/repository.test.d.ts +2 -0
  227. package/packages/happy2-server/dist/modules/operations/repository.test.d.ts.map +1 -0
  228. package/packages/happy2-server/dist/modules/operations/repository.test.js +610 -0
  229. package/packages/happy2-server/dist/modules/operations/repository.test.js.map +1 -0
  230. package/packages/happy2-server/dist/modules/operations/types.d.ts +144 -0
  231. package/packages/happy2-server/dist/modules/operations/types.d.ts.map +1 -0
  232. package/packages/happy2-server/dist/modules/operations/types.js +9 -0
  233. package/packages/happy2-server/dist/modules/operations/types.js.map +1 -0
  234. package/packages/happy2-server/dist/modules/realtime/events.d.ts +99 -0
  235. package/packages/happy2-server/dist/modules/realtime/events.d.ts.map +1 -0
  236. package/packages/happy2-server/dist/modules/realtime/events.js +173 -0
  237. package/packages/happy2-server/dist/modules/realtime/events.js.map +1 -0
  238. package/packages/happy2-server/dist/modules/realtime/index.d.ts +4 -0
  239. package/packages/happy2-server/dist/modules/realtime/index.d.ts.map +1 -0
  240. package/packages/happy2-server/dist/modules/realtime/index.js +4 -0
  241. package/packages/happy2-server/dist/modules/realtime/index.js.map +1 -0
  242. package/packages/happy2-server/dist/modules/realtime/local.d.ts +37 -0
  243. package/packages/happy2-server/dist/modules/realtime/local.d.ts.map +1 -0
  244. package/packages/happy2-server/dist/modules/realtime/local.js +181 -0
  245. package/packages/happy2-server/dist/modules/realtime/local.js.map +1 -0
  246. package/packages/happy2-server/dist/modules/realtime/local.test.d.ts +2 -0
  247. package/packages/happy2-server/dist/modules/realtime/local.test.d.ts.map +1 -0
  248. package/packages/happy2-server/dist/modules/realtime/local.test.js +186 -0
  249. package/packages/happy2-server/dist/modules/realtime/local.test.js.map +1 -0
  250. package/packages/happy2-server/dist/modules/realtime/pubsub.d.ts +26 -0
  251. package/packages/happy2-server/dist/modules/realtime/pubsub.d.ts.map +1 -0
  252. package/packages/happy2-server/dist/modules/realtime/pubsub.js +7 -0
  253. package/packages/happy2-server/dist/modules/realtime/pubsub.js.map +1 -0
  254. package/packages/happy2-server/dist/modules/request/database-idempotency.d.ts +15 -0
  255. package/packages/happy2-server/dist/modules/request/database-idempotency.d.ts.map +1 -0
  256. package/packages/happy2-server/dist/modules/request/database-idempotency.js +141 -0
  257. package/packages/happy2-server/dist/modules/request/database-idempotency.js.map +1 -0
  258. package/packages/happy2-server/dist/modules/request/idempotency-hook.d.ts +12 -0
  259. package/packages/happy2-server/dist/modules/request/idempotency-hook.d.ts.map +1 -0
  260. package/packages/happy2-server/dist/modules/request/idempotency-hook.js +98 -0
  261. package/packages/happy2-server/dist/modules/request/idempotency-hook.js.map +1 -0
  262. package/packages/happy2-server/dist/modules/request/idempotency.d.ts +146 -0
  263. package/packages/happy2-server/dist/modules/request/idempotency.d.ts.map +1 -0
  264. package/packages/happy2-server/dist/modules/request/idempotency.js +312 -0
  265. package/packages/happy2-server/dist/modules/request/idempotency.js.map +1 -0
  266. package/packages/happy2-server/dist/modules/request/idempotency.test.d.ts +2 -0
  267. package/packages/happy2-server/dist/modules/request/idempotency.test.d.ts.map +1 -0
  268. package/packages/happy2-server/dist/modules/request/idempotency.test.js +191 -0
  269. package/packages/happy2-server/dist/modules/request/idempotency.test.js.map +1 -0
  270. package/packages/happy2-server/dist/modules/request/index.d.ts +5 -0
  271. package/packages/happy2-server/dist/modules/request/index.d.ts.map +1 -0
  272. package/packages/happy2-server/dist/modules/request/index.js +5 -0
  273. package/packages/happy2-server/dist/modules/request/index.js.map +1 -0
  274. package/packages/happy2-server/dist/modules/request/rate-limit.d.ts +100 -0
  275. package/packages/happy2-server/dist/modules/request/rate-limit.d.ts.map +1 -0
  276. package/packages/happy2-server/dist/modules/request/rate-limit.js +239 -0
  277. package/packages/happy2-server/dist/modules/request/rate-limit.js.map +1 -0
  278. package/packages/happy2-server/dist/modules/request/rate-limit.test.d.ts +2 -0
  279. package/packages/happy2-server/dist/modules/request/rate-limit.test.d.ts.map +1 -0
  280. package/packages/happy2-server/dist/modules/request/rate-limit.test.js +123 -0
  281. package/packages/happy2-server/dist/modules/request/rate-limit.test.js.map +1 -0
  282. package/packages/happy2-server/dist/modules/schema.d.ts +31454 -0
  283. package/packages/happy2-server/dist/modules/schema.d.ts.map +1 -0
  284. package/packages/happy2-server/dist/modules/schema.js +1081 -0
  285. package/packages/happy2-server/dist/modules/schema.js.map +1 -0
  286. package/packages/happy2-server/dist/modules/workspace/index.d.ts +3 -0
  287. package/packages/happy2-server/dist/modules/workspace/index.d.ts.map +1 -0
  288. package/packages/happy2-server/dist/modules/workspace/index.js +3 -0
  289. package/packages/happy2-server/dist/modules/workspace/index.js.map +1 -0
  290. package/packages/happy2-server/dist/modules/workspace/service.d.ts +54 -0
  291. package/packages/happy2-server/dist/modules/workspace/service.d.ts.map +1 -0
  292. package/packages/happy2-server/dist/modules/workspace/service.js +997 -0
  293. package/packages/happy2-server/dist/modules/workspace/service.js.map +1 -0
  294. package/packages/happy2-server/dist/modules/workspace/types.d.ts +58 -0
  295. package/packages/happy2-server/dist/modules/workspace/types.d.ts.map +1 -0
  296. package/packages/happy2-server/dist/modules/workspace/types.js +11 -0
  297. package/packages/happy2-server/dist/modules/workspace/types.js.map +1 -0
  298. package/packages/happy2-server/dist/routes/agents.d.ts +5 -0
  299. package/packages/happy2-server/dist/routes/agents.d.ts.map +1 -0
  300. package/packages/happy2-server/dist/routes/agents.js +225 -0
  301. package/packages/happy2-server/dist/routes/agents.js.map +1 -0
  302. package/packages/happy2-server/dist/routes/auth.d.ts +5 -0
  303. package/packages/happy2-server/dist/routes/auth.d.ts.map +1 -0
  304. package/packages/happy2-server/dist/routes/auth.js +128 -0
  305. package/packages/happy2-server/dist/routes/auth.js.map +1 -0
  306. package/packages/happy2-server/dist/routes/automation.d.ts +6 -0
  307. package/packages/happy2-server/dist/routes/automation.d.ts.map +1 -0
  308. package/packages/happy2-server/dist/routes/automation.js +315 -0
  309. package/packages/happy2-server/dist/routes/automation.js.map +1 -0
  310. package/packages/happy2-server/dist/routes/basic.d.ts +3 -0
  311. package/packages/happy2-server/dist/routes/basic.d.ts.map +1 -0
  312. package/packages/happy2-server/dist/routes/basic.js +5 -0
  313. package/packages/happy2-server/dist/routes/basic.js.map +1 -0
  314. package/packages/happy2-server/dist/routes/collaboration.d.ts +7 -0
  315. package/packages/happy2-server/dist/routes/collaboration.d.ts.map +1 -0
  316. package/packages/happy2-server/dist/routes/collaboration.js +1285 -0
  317. package/packages/happy2-server/dist/routes/collaboration.js.map +1 -0
  318. package/packages/happy2-server/dist/routes/files.d.ts +9 -0
  319. package/packages/happy2-server/dist/routes/files.d.ts.map +1 -0
  320. package/packages/happy2-server/dist/routes/files.js +397 -0
  321. package/packages/happy2-server/dist/routes/files.js.map +1 -0
  322. package/packages/happy2-server/dist/routes/integrations.d.ts +6 -0
  323. package/packages/happy2-server/dist/routes/integrations.d.ts.map +1 -0
  324. package/packages/happy2-server/dist/routes/integrations.js +486 -0
  325. package/packages/happy2-server/dist/routes/integrations.js.map +1 -0
  326. package/packages/happy2-server/dist/routes/operations.d.ts +5 -0
  327. package/packages/happy2-server/dist/routes/operations.d.ts.map +1 -0
  328. package/packages/happy2-server/dist/routes/operations.js +588 -0
  329. package/packages/happy2-server/dist/routes/operations.js.map +1 -0
  330. package/packages/happy2-server/dist/routes/operations.test.d.ts +2 -0
  331. package/packages/happy2-server/dist/routes/operations.test.d.ts.map +1 -0
  332. package/packages/happy2-server/dist/routes/operations.test.js +106 -0
  333. package/packages/happy2-server/dist/routes/operations.test.js.map +1 -0
  334. package/packages/happy2-server/dist/routes/sync.d.ts +6 -0
  335. package/packages/happy2-server/dist/routes/sync.d.ts.map +1 -0
  336. package/packages/happy2-server/dist/routes/sync.js +549 -0
  337. package/packages/happy2-server/dist/routes/sync.js.map +1 -0
  338. package/packages/happy2-server/dist/routes/workspace.d.ts +5 -0
  339. package/packages/happy2-server/dist/routes/workspace.d.ts.map +1 -0
  340. package/packages/happy2-server/dist/routes/workspace.js +240 -0
  341. package/packages/happy2-server/dist/routes/workspace.js.map +1 -0
  342. package/packages/happy2-server/dist/runner.d.ts +3 -0
  343. package/packages/happy2-server/dist/runner.d.ts.map +1 -0
  344. package/packages/happy2-server/dist/runner.js +30 -0
  345. package/packages/happy2-server/dist/runner.js.map +1 -0
  346. package/packages/happy2-server/dist/server.d.ts +32 -0
  347. package/packages/happy2-server/dist/server.d.ts.map +1 -0
  348. package/packages/happy2-server/dist/server.js +284 -0
  349. package/packages/happy2-server/dist/server.js.map +1 -0
  350. package/packages/happy2-server/dist/standalone.d.ts +13 -0
  351. package/packages/happy2-server/dist/standalone.d.ts.map +1 -0
  352. package/packages/happy2-server/dist/standalone.js +99 -0
  353. package/packages/happy2-server/dist/standalone.js.map +1 -0
  354. package/packages/happy2-server/dist/web/assets/figtree-latin-wght-normal-D_ZTVpCC.woff2 +0 -0
  355. package/packages/happy2-server/dist/web/assets/happy-otter-Q2O_g-DT.png +0 -0
  356. package/packages/happy2-server/dist/web/assets/index-COvbX8JP.css +2 -0
  357. package/packages/happy2-server/dist/web/assets/index-DdpugxMO.js +57 -0
  358. package/packages/happy2-server/dist/web/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  359. package/packages/happy2-server/dist/web/assets/onboarding-CRUpq9xl.png +0 -0
  360. package/packages/happy2-server/dist/web/index.html +13 -0
  361. package/packages/happy2-server/drizzle/0000_initial.sql +13 -0
  362. package/packages/happy2-server/drizzle/0001_accounts_profiles_files.sql +42 -0
  363. package/packages/happy2-server/drizzle/0002_file_visibility_and_uploader.sql +5 -0
  364. package/packages/happy2-server/drizzle/0003_collaboration.sql +565 -0
  365. package/packages/happy2-server/drizzle/0004_collaboration_expansion.sql +1099 -0
  366. package/packages/happy2-server/drizzle/0005_ai_agents.sql +85 -0
  367. package/packages/happy2-server/drizzle/0006_rig_global_event_queue.sql +10 -0
  368. package/packages/happy2-server/drizzle/0007_rename_server_identity.sql +3 -0
  369. package/packages/happy2-server/drizzle/0008_agent_message_streaming.sql +47 -0
  370. package/packages/happy2-server/drizzle/0009_chat_workspace_binding_lookup.sql +2 -0
  371. package/packages/happy2-server/drizzle/0010_rig_secret_assignments.sql +21 -0
  372. package/packages/happy2-server/drizzle/meta/_journal.json +83 -0
  373. package/packages/happy2-server/happy2.example.toml +104 -0
@@ -0,0 +1,181 @@
1
+ import { assertRealtimeEvent, assertRealtimeId, assertRealtimeTopic, DEFAULT_REALTIME_LIMITS, realtimeTopics, } from "./events.js";
2
+ import { PubSubClosedError, } from "./pubsub.js";
3
+ /** In-memory, process-local pubsub. All state disappears on close or restart. */
4
+ export class LocalPubSub {
5
+ clock;
6
+ limits;
7
+ onSubscriberError;
8
+ subscribers = new Map();
9
+ connections = new Map();
10
+ connectionsByUser = new Map();
11
+ lastActivityByUser = new Map();
12
+ closed = false;
13
+ constructor(options = {}) {
14
+ this.clock = options.clock ?? Date.now;
15
+ this.limits = { ...DEFAULT_REALTIME_LIMITS, ...options.limits };
16
+ this.onSubscriberError = options.onSubscriberError;
17
+ assertLimits(this.limits);
18
+ }
19
+ async publish(topic, event) {
20
+ this.assertOpen();
21
+ assertRealtimeTopic(topic, this.limits);
22
+ assertRealtimeEvent(event, this.limits);
23
+ const safeEvent = deepFreeze(structuredClone(event));
24
+ const subscribers = [...(this.subscribers.get(topic) ?? [])];
25
+ await Promise.all(subscribers.map(async (subscriber) => {
26
+ try {
27
+ await subscriber(safeEvent);
28
+ }
29
+ catch (error) {
30
+ this.reportSubscriberError(error, { topic, event: safeEvent });
31
+ }
32
+ }));
33
+ }
34
+ subscribe(topic, subscriber) {
35
+ this.assertOpen();
36
+ assertRealtimeTopic(topic, this.limits);
37
+ if (typeof subscriber !== "function")
38
+ throw new Error("Subscriber must be a function");
39
+ const subscribers = this.subscribers.get(topic) ?? new Set();
40
+ subscribers.add(subscriber);
41
+ this.subscribers.set(topic, subscribers);
42
+ let subscribed = true;
43
+ return () => {
44
+ if (!subscribed)
45
+ return;
46
+ subscribed = false;
47
+ subscribers.delete(subscriber);
48
+ if (subscribers.size === 0)
49
+ this.subscribers.delete(topic);
50
+ };
51
+ }
52
+ async connectPresence(connection) {
53
+ this.assertOpen();
54
+ assertRealtimeId(connection.connectionId, "connection id", this.limits);
55
+ assertRealtimeId(connection.userId, "user id", this.limits);
56
+ const occurredAt = this.occurredAt(connection.occurredAt);
57
+ const existing = this.connections.get(connection.connectionId);
58
+ if (existing) {
59
+ if (existing.userId !== connection.userId)
60
+ throw new Error("Presence connection id is already in use");
61
+ if (occurredAt > existing.lastActiveAt) {
62
+ existing.lastActiveAt = occurredAt;
63
+ this.rememberActivity(existing.userId, occurredAt);
64
+ }
65
+ return this.snapshot(existing.userId);
66
+ }
67
+ const local = {
68
+ connectionId: connection.connectionId,
69
+ userId: connection.userId,
70
+ lastActiveAt: occurredAt,
71
+ };
72
+ this.connections.set(local.connectionId, local);
73
+ const userConnections = this.connectionsByUser.get(local.userId) ?? new Set();
74
+ userConnections.add(local.connectionId);
75
+ this.connectionsByUser.set(local.userId, userConnections);
76
+ this.rememberActivity(local.userId, occurredAt);
77
+ return this.emitPresence("connected", local.userId, occurredAt);
78
+ }
79
+ async recordPresenceActivity(connectionId, occurredAt) {
80
+ this.assertOpen();
81
+ assertRealtimeId(connectionId, "connection id", this.limits);
82
+ const connection = this.connections.get(connectionId);
83
+ if (!connection)
84
+ return undefined;
85
+ const time = this.occurredAt(occurredAt);
86
+ connection.lastActiveAt = Math.max(connection.lastActiveAt, time);
87
+ this.rememberActivity(connection.userId, connection.lastActiveAt);
88
+ return this.emitPresence("activity", connection.userId, time);
89
+ }
90
+ async disconnectPresence(connectionId, occurredAt) {
91
+ this.assertOpen();
92
+ assertRealtimeId(connectionId, "connection id", this.limits);
93
+ const connection = this.connections.get(connectionId);
94
+ if (!connection)
95
+ return undefined;
96
+ const time = this.occurredAt(occurredAt);
97
+ this.connections.delete(connectionId);
98
+ const userConnections = this.connectionsByUser.get(connection.userId);
99
+ userConnections?.delete(connectionId);
100
+ if (userConnections?.size === 0)
101
+ this.connectionsByUser.delete(connection.userId);
102
+ this.rememberActivity(connection.userId, Math.max(connection.lastActiveAt, time));
103
+ return this.emitPresence("disconnected", connection.userId, time);
104
+ }
105
+ async getPresenceSnapshot(userIds) {
106
+ this.assertOpen();
107
+ const ids = userIds
108
+ ? [...userIds]
109
+ : [...new Set([...this.connectionsByUser.keys(), ...this.lastActivityByUser.keys()])];
110
+ for (const userId of ids)
111
+ assertRealtimeId(userId, "user id", this.limits);
112
+ return ids.map((userId) => this.snapshot(userId));
113
+ }
114
+ async close() {
115
+ if (this.closed)
116
+ return;
117
+ this.closed = true;
118
+ this.subscribers.clear();
119
+ this.connections.clear();
120
+ this.connectionsByUser.clear();
121
+ this.lastActivityByUser.clear();
122
+ }
123
+ async emitPresence(change, userId, occurredAt) {
124
+ const snapshot = this.snapshot(userId);
125
+ const event = { type: "presence", change, snapshot, occurredAt };
126
+ await this.publish(realtimeTopics.presence, event);
127
+ return snapshot;
128
+ }
129
+ snapshot(userId) {
130
+ const connectionCount = this.connectionsByUser.get(userId)?.size ?? 0;
131
+ return Object.freeze({
132
+ userId,
133
+ status: connectionCount > 0 ? "online" : "offline",
134
+ connectionCount,
135
+ lastActiveAt: this.lastActivityByUser.get(userId),
136
+ });
137
+ }
138
+ rememberActivity(userId, occurredAt) {
139
+ this.lastActivityByUser.set(userId, Math.max(this.lastActivityByUser.get(userId) ?? 0, occurredAt));
140
+ while (this.lastActivityByUser.size > this.limits.maxPresenceUsers) {
141
+ const removable = [...this.lastActivityByUser.keys()].find((candidate) => !this.connectionsByUser.has(candidate));
142
+ if (!removable)
143
+ break;
144
+ this.lastActivityByUser.delete(removable);
145
+ }
146
+ }
147
+ occurredAt(value) {
148
+ const result = value ?? this.clock();
149
+ if (!Number.isSafeInteger(result) || result < 0)
150
+ throw new Error("Invalid presence time");
151
+ return result;
152
+ }
153
+ assertOpen() {
154
+ if (this.closed)
155
+ throw new PubSubClosedError();
156
+ }
157
+ reportSubscriberError(error, context) {
158
+ try {
159
+ const reported = this.onSubscriberError?.(error, context);
160
+ if (reported)
161
+ void reported.catch(() => undefined);
162
+ }
163
+ catch {
164
+ // Subscriber error reporting must never break fanout.
165
+ }
166
+ }
167
+ }
168
+ function deepFreeze(value) {
169
+ if (!value || typeof value !== "object" || Object.isFrozen(value))
170
+ return value;
171
+ for (const child of Object.values(value))
172
+ deepFreeze(child);
173
+ return Object.freeze(value);
174
+ }
175
+ function assertLimits(limits) {
176
+ for (const [name, value] of Object.entries(limits)) {
177
+ if (!Number.isSafeInteger(value) || value < 1)
178
+ throw new Error(`Realtime limit ${name} must be a positive safe integer`);
179
+ }
180
+ }
181
+ //# sourceMappingURL=local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../../sources/modules/realtime/local.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=local.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.test.d.ts","sourceRoot":"","sources":["../../../sources/modules/realtime/local.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,186 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { LocalPubSub, PubSubClosedError, realtimeTopics, } from "./index.js";
3
+ const syncEvent = {
4
+ type: "sync",
5
+ sequence: "9007199254740993",
6
+ chats: [{ chatId: "chat-one", pts: "9007199254740992" }],
7
+ areas: ["messages"],
8
+ };
9
+ describe("LocalPubSub contract", () => {
10
+ it("fans out by topic, awaits async subscribers, and unsubscribes idempotently", async () => {
11
+ const pubsub = new LocalPubSub();
12
+ const received = [];
13
+ const listener = vi.fn(async (event) => {
14
+ await Promise.resolve();
15
+ received.push(event);
16
+ });
17
+ const unsubscribe = pubsub.subscribe(realtimeTopics.user("user-one"), listener);
18
+ await pubsub.publish(realtimeTopics.chat("chat-one"), syncEvent);
19
+ await pubsub.publish(realtimeTopics.user("user-one"), syncEvent);
20
+ expect(received).toEqual([syncEvent]);
21
+ expect(Object.isFrozen(received[0])).toBe(true);
22
+ expect(Object.isFrozen(received[0].chats)).toBe(true);
23
+ unsubscribe();
24
+ unsubscribe();
25
+ await pubsub.publish(realtimeTopics.user("user-one"), syncEvent);
26
+ expect(listener).toHaveBeenCalledTimes(1);
27
+ });
28
+ it("isolates subscriber failures so every async subscriber receives the event", async () => {
29
+ const errors = [];
30
+ const pubsub = new LocalPubSub({
31
+ onSubscriberError: (error) => {
32
+ errors.push(error);
33
+ },
34
+ });
35
+ const delivered = vi.fn();
36
+ pubsub.subscribe(realtimeTopics.server, async () => {
37
+ await Promise.resolve();
38
+ throw new Error("listener failed");
39
+ });
40
+ pubsub.subscribe(realtimeTopics.server, delivered);
41
+ await expect(pubsub.publish(realtimeTopics.server, syncEvent)).resolves.toBeUndefined();
42
+ expect(delivered).toHaveBeenCalledWith(syncEvent);
43
+ expect(errors).toHaveLength(1);
44
+ });
45
+ it("consumes asynchronous subscriber-error reporter failures", async () => {
46
+ const pubsub = new LocalPubSub({
47
+ onSubscriberError: async () => {
48
+ throw new Error("reporter failed");
49
+ },
50
+ });
51
+ pubsub.subscribe(realtimeTopics.server, () => {
52
+ throw new Error("subscriber failed");
53
+ });
54
+ await expect(pubsub.publish(realtimeTopics.server, syncEvent)).resolves.toBeUndefined();
55
+ await Promise.resolve();
56
+ });
57
+ it("bounds retained offline presence history", async () => {
58
+ let now = 1;
59
+ const pubsub = new LocalPubSub({
60
+ clock: () => now++,
61
+ limits: { maxPresenceUsers: 2 },
62
+ });
63
+ for (const userId of ["one", "two", "three"]) {
64
+ const connectionId = `connection-${userId}`;
65
+ await pubsub.connectPresence({ connectionId, userId });
66
+ await pubsub.disconnectPresence(connectionId);
67
+ }
68
+ expect(await pubsub.getPresenceSnapshot()).toHaveLength(2);
69
+ });
70
+ it("accepts lossless SQLite sequences and rejects malformed or oversized hints", async () => {
71
+ const pubsub = new LocalPubSub({ limits: { maxSyncChats: 1 } });
72
+ await expect(pubsub.publish(realtimeTopics.server, syncEvent)).resolves.toBeUndefined();
73
+ await expect(pubsub.publish(realtimeTopics.server, { ...syncEvent, sequence: "01" })).rejects.toThrow("unsigned decimal string");
74
+ await expect(pubsub.publish(realtimeTopics.server, {
75
+ ...syncEvent,
76
+ chats: [...syncEvent.chats, { chatId: "chat-two", pts: "1" }],
77
+ })).rejects.toThrow("at most 1 chats");
78
+ await expect(pubsub.publish(realtimeTopics.server, {
79
+ type: "unknown",
80
+ })).rejects.toThrow("Invalid realtime event type");
81
+ });
82
+ it("enforces typing expiry and WebRTC signaling bounds", async () => {
83
+ const pubsub = new LocalPubSub({
84
+ limits: { maxTypingTtlMs: 5_000, maxSessionDescriptionBytes: 16 },
85
+ });
86
+ const typing = {
87
+ type: "typing",
88
+ chatId: "chat-one",
89
+ userId: "user-one",
90
+ active: true,
91
+ occurredAt: 1_000,
92
+ expiresAt: 6_000,
93
+ };
94
+ const offer = {
95
+ type: "call.signal",
96
+ callId: "call-one",
97
+ chatId: "chat-one",
98
+ senderUserId: "user-one",
99
+ recipientUserId: "user-two",
100
+ signal: { kind: "offer", sdp: "v=0" },
101
+ occurredAt: 1_000,
102
+ };
103
+ await expect(pubsub.publish(realtimeTopics.chat("chat-one"), typing)).resolves.toBeUndefined();
104
+ await expect(pubsub.publish(realtimeTopics.call("call-one"), offer)).resolves.toBeUndefined();
105
+ await expect(pubsub.publish(realtimeTopics.chat("chat-one"), {
106
+ ...typing,
107
+ expiresAt: 6_001,
108
+ })).rejects.toThrow("within 5000 ms");
109
+ await expect(pubsub.publish(realtimeTopics.call("call-one"), {
110
+ ...offer,
111
+ signal: { kind: "offer", sdp: "x".repeat(17) },
112
+ })).rejects.toThrow("session description");
113
+ });
114
+ it("tracks multiple presence connections, activity, and offline snapshots", async () => {
115
+ let now = 100;
116
+ const pubsub = new LocalPubSub({ clock: () => now });
117
+ const events = [];
118
+ pubsub.subscribe(realtimeTopics.presence, (event) => {
119
+ if (event.type === "presence")
120
+ events.push(event);
121
+ });
122
+ await expect(pubsub.connectPresence({ connectionId: "connection-one", userId: "user-one" })).resolves.toEqual({
123
+ userId: "user-one",
124
+ status: "online",
125
+ connectionCount: 1,
126
+ lastActiveAt: 100,
127
+ });
128
+ now = 110;
129
+ await pubsub.connectPresence({ connectionId: "connection-two", userId: "user-one" });
130
+ now = 120;
131
+ await pubsub.recordPresenceActivity("connection-one");
132
+ now = 130;
133
+ await pubsub.disconnectPresence("connection-one");
134
+ expect(await pubsub.getPresenceSnapshot(["user-one", "never-online"])).toEqual([
135
+ {
136
+ userId: "user-one",
137
+ status: "online",
138
+ connectionCount: 1,
139
+ lastActiveAt: 130,
140
+ },
141
+ {
142
+ userId: "never-online",
143
+ status: "offline",
144
+ connectionCount: 0,
145
+ lastActiveAt: undefined,
146
+ },
147
+ ]);
148
+ now = 140;
149
+ await pubsub.disconnectPresence("connection-two");
150
+ expect(await pubsub.getPresenceSnapshot(["user-one"])).toEqual([
151
+ {
152
+ userId: "user-one",
153
+ status: "offline",
154
+ connectionCount: 0,
155
+ lastActiveAt: 140,
156
+ },
157
+ ]);
158
+ expect(events.map((event) => event.change)).toEqual([
159
+ "connected",
160
+ "connected",
161
+ "activity",
162
+ "disconnected",
163
+ "disconnected",
164
+ ]);
165
+ });
166
+ it("makes repeated presence connection safe but rejects cross-user reuse", async () => {
167
+ const pubsub = new LocalPubSub({ clock: () => 100 });
168
+ await pubsub.connectPresence({ connectionId: "same", userId: "user-one" });
169
+ await expect(pubsub.connectPresence({ connectionId: "same", userId: "user-one" })).resolves.toMatchObject({ connectionCount: 1 });
170
+ await expect(pubsub.connectPresence({ connectionId: "same", userId: "user-two" })).rejects.toThrow("already in use");
171
+ await expect(pubsub.recordPresenceActivity("unknown")).resolves.toBeUndefined();
172
+ await expect(pubsub.disconnectPresence("unknown")).resolves.toBeUndefined();
173
+ });
174
+ it("clears subscriptions and ephemeral presence state when closed", async () => {
175
+ const pubsub = new LocalPubSub();
176
+ const listener = vi.fn();
177
+ pubsub.subscribe(realtimeTopics.server, listener);
178
+ await pubsub.connectPresence({ connectionId: "connection-one", userId: "user-one" });
179
+ await pubsub.close();
180
+ await pubsub.close();
181
+ await expect(pubsub.publish(realtimeTopics.server, syncEvent)).rejects.toBeInstanceOf(PubSubClosedError);
182
+ await expect(pubsub.getPresenceSnapshot()).rejects.toBeInstanceOf(PubSubClosedError);
183
+ expect(listener).not.toHaveBeenCalled();
184
+ });
185
+ });
186
+ //# sourceMappingURL=local.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.test.js","sourceRoot":"","sources":["../../../sources/modules/realtime/local.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { PresenceSnapshot, RealtimeEvent, RealtimeTopic } from "./events.js";
2
+ export type RealtimeSubscriber = (event: RealtimeEvent) => void | Promise<void>;
3
+ export type Unsubscribe = () => void;
4
+ export interface PresenceConnection {
5
+ readonly connectionId: string;
6
+ readonly userId: string;
7
+ readonly occurredAt?: number;
8
+ }
9
+ /**
10
+ * Transport-neutral ephemeral fanout. A Redis adapter can implement the same
11
+ * contract without changing route code. No implementation may treat it as the
12
+ * source of truth for sync state.
13
+ */
14
+ export interface PubSub {
15
+ publish(topic: RealtimeTopic, event: RealtimeEvent): Promise<void>;
16
+ subscribe(topic: RealtimeTopic, subscriber: RealtimeSubscriber): Unsubscribe;
17
+ connectPresence(connection: PresenceConnection): Promise<PresenceSnapshot>;
18
+ recordPresenceActivity(connectionId: string, occurredAt?: number): Promise<PresenceSnapshot | undefined>;
19
+ disconnectPresence(connectionId: string, occurredAt?: number): Promise<PresenceSnapshot | undefined>;
20
+ getPresenceSnapshot(userIds?: readonly string[]): Promise<readonly PresenceSnapshot[]>;
21
+ close(): Promise<void>;
22
+ }
23
+ export declare class PubSubClosedError extends Error {
24
+ constructor();
25
+ }
26
+ //# sourceMappingURL=pubsub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pubsub.d.ts","sourceRoot":"","sources":["../../../sources/modules/realtime/pubsub.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAElF,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAChF,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;GAIG;AACH,MAAM,WAAW,MAAM;IACnB,OAAO,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,SAAS,CAAC,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,kBAAkB,GAAG,WAAW,CAAC;IAE7E,eAAe,CAAC,UAAU,EAAE,kBAAkB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC3E,sBAAsB,CAClB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;IACzC,kBAAkB,CACd,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;IACzC,mBAAmB,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,gBAAgB,EAAE,CAAC,CAAC;IAEvF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IACxC,cAGC;CACJ"}
@@ -0,0 +1,7 @@
1
+ export class PubSubClosedError extends Error {
2
+ constructor() {
3
+ super("PubSub is closed");
4
+ this.name = "PubSubClosedError";
5
+ }
6
+ }
7
+ //# sourceMappingURL=pubsub.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pubsub.js","sourceRoot":"","sources":["../../../sources/modules/realtime/pubsub.ts"],"names":[],"mappings":"AAkCA,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACxC;QACI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IACpC,CAAC;CACJ"}
@@ -0,0 +1,15 @@
1
+ import { type Client } from "@libsql/client";
2
+ import type { IdempotencyAcquireInput, IdempotencyAcquireResult, IdempotencyCompleteInput, IdempotencyStore } from "./idempotency.js";
3
+ /** Shared SQLite/libSQL adapter; leases and fencing remain authoritative across processes. */
4
+ export declare class DatabaseIdempotencyStore<TResponse> implements IdempotencyStore<TResponse> {
5
+ private readonly client;
6
+ private readonly db;
7
+ private readonly ownsClient;
8
+ constructor(source: string | Client, authToken?: string);
9
+ acquire(input: IdempotencyAcquireInput): Promise<IdempotencyAcquireResult<TResponse>>;
10
+ complete(input: IdempotencyCompleteInput<TResponse>): Promise<boolean>;
11
+ release(storageKey: string, token: string): Promise<boolean>;
12
+ purgeExpired(now: number, limit?: number): Promise<number>;
13
+ close(): void;
14
+ }
15
+ //# sourceMappingURL=database-idempotency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-idempotency.d.ts","sourceRoot":"","sources":["../../../sources/modules/request/database-idempotency.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAG3D,OAAO,KAAK,EACR,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,gBAAgB,EACnB,MAAM,kBAAkB,CAAC;AAU1B,8FAA8F;AAC9F,qBAAa,wBAAwB,CAAC,SAAS,CAAE,YAAW,gBAAgB,CAAC,SAAS,CAAC;IACnF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;IACpB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IAErC,YAAY,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAKtD;IAEK,OAAO,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,wBAAwB,CAAC,SAAS,CAAC,CAAC,CA8C1F;IAEK,QAAQ,CAAC,KAAK,EAAE,wBAAwB,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAyB3E;IAEK,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAkBjE;IAEK,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAuB9D;IAED,KAAK,IAAI,IAAI,CAEZ;CACJ"}
@@ -0,0 +1,141 @@
1
+ import { createId } from "@paralleldrive/cuid2";
2
+ import { and, asc, eq, inArray, lte, sql } from "drizzle-orm";
3
+ import { createClient } from "@libsql/client";
4
+ import { createDatabase, retrySqliteBusy } from "../drizzle.js";
5
+ import { idempotencyKeys } from "../schema.js";
6
+ const requestKey = (storageKey) => and(eq(idempotencyKeys.principalType, "system"), eq(idempotencyKeys.principalId, "http"), eq(idempotencyKeys.scope, "request"), eq(idempotencyKeys.idempotencyKey, storageKey));
7
+ /** Shared SQLite/libSQL adapter; leases and fencing remain authoritative across processes. */
8
+ export class DatabaseIdempotencyStore {
9
+ client;
10
+ db;
11
+ ownsClient;
12
+ constructor(source, authToken) {
13
+ this.ownsClient = typeof source === "string";
14
+ this.client =
15
+ typeof source === "string" ? createClient({ url: source, authToken }) : source;
16
+ this.db = createDatabase(this.client);
17
+ }
18
+ async acquire(input) {
19
+ return retrySqliteBusy(() => this.db.transaction(async (tx) => {
20
+ let row = await find(tx, input.storageKey);
21
+ if (row && Date.parse(row.expiresAt) <= input.now) {
22
+ await tx.delete(idempotencyKeys).where(eq(idempotencyKeys.id, row.id));
23
+ row = undefined;
24
+ }
25
+ if (row) {
26
+ if (row.requestHash !== input.fingerprint)
27
+ return { kind: "conflict" };
28
+ if (row.status === "completed")
29
+ return {
30
+ kind: "replay",
31
+ response: JSON.parse(requiredJson(row.responseJson)),
32
+ };
33
+ if (row.lockedUntil && Date.parse(row.lockedUntil) > input.now)
34
+ return { kind: "in_progress", retryAt: Date.parse(row.lockedUntil) };
35
+ await tx
36
+ .update(idempotencyKeys)
37
+ .set({
38
+ status: "in_progress",
39
+ requestHash: input.fingerprint,
40
+ responseStatus: null,
41
+ responseJson: JSON.stringify({ leaseToken: input.leaseToken }),
42
+ lockedUntil: iso(input.leaseExpiresAt),
43
+ expiresAt: iso(input.recordExpiresAt),
44
+ updatedAt: sql `CURRENT_TIMESTAMP`,
45
+ })
46
+ .where(eq(idempotencyKeys.id, row.id));
47
+ return { kind: "acquired" };
48
+ }
49
+ await tx.insert(idempotencyKeys).values({
50
+ id: createId(),
51
+ principalType: "system",
52
+ principalId: "http",
53
+ scope: "request",
54
+ idempotencyKey: input.storageKey,
55
+ requestHash: input.fingerprint,
56
+ status: "in_progress",
57
+ responseJson: JSON.stringify({ leaseToken: input.leaseToken }),
58
+ lockedUntil: iso(input.leaseExpiresAt),
59
+ expiresAt: iso(input.recordExpiresAt),
60
+ });
61
+ return { kind: "acquired" };
62
+ }));
63
+ }
64
+ async complete(input) {
65
+ return retrySqliteBusy(() => this.db.transaction(async (tx) => {
66
+ const row = await find(tx, input.storageKey);
67
+ if (!row || row.status !== "in_progress")
68
+ return false;
69
+ if (leaseToken(row.responseJson) !== input.leaseToken)
70
+ return false;
71
+ const changed = await tx
72
+ .update(idempotencyKeys)
73
+ .set({
74
+ status: "completed",
75
+ responseJson: JSON.stringify(input.response),
76
+ lockedUntil: null,
77
+ expiresAt: iso(input.recordExpiresAt),
78
+ updatedAt: sql `CURRENT_TIMESTAMP`,
79
+ })
80
+ .where(and(eq(idempotencyKeys.id, row.id), eq(idempotencyKeys.status, "in_progress")))
81
+ .returning({ id: idempotencyKeys.id });
82
+ return changed.length === 1;
83
+ }));
84
+ }
85
+ async release(storageKey, token) {
86
+ return retrySqliteBusy(() => this.db.transaction(async (tx) => {
87
+ const row = await find(tx, storageKey);
88
+ if (!row || row.status !== "in_progress" || leaseToken(row.responseJson) !== token)
89
+ return false;
90
+ const changed = await tx
91
+ .delete(idempotencyKeys)
92
+ .where(and(eq(idempotencyKeys.id, row.id), eq(idempotencyKeys.status, "in_progress")))
93
+ .returning({ id: idempotencyKeys.id });
94
+ return changed.length === 1;
95
+ }));
96
+ }
97
+ async purgeExpired(now, limit = 1_000) {
98
+ return retrySqliteBusy(() => this.db.transaction(async (tx) => {
99
+ const due = await tx
100
+ .select({ id: idempotencyKeys.id })
101
+ .from(idempotencyKeys)
102
+ .where(lte(idempotencyKeys.expiresAt, iso(now)))
103
+ .orderBy(asc(idempotencyKeys.expiresAt), asc(idempotencyKeys.id))
104
+ .limit(limit);
105
+ if (due.length === 0)
106
+ return 0;
107
+ return (await tx
108
+ .delete(idempotencyKeys)
109
+ .where(inArray(idempotencyKeys.id, due.map(({ id }) => id)))
110
+ .returning({ id: idempotencyKeys.id })).length;
111
+ }));
112
+ }
113
+ close() {
114
+ if (this.ownsClient)
115
+ this.client.close();
116
+ }
117
+ }
118
+ async function find(executor, storageKey) {
119
+ const rows = await executor.select().from(idempotencyKeys).where(requestKey(storageKey));
120
+ return rows[0];
121
+ }
122
+ function leaseToken(value) {
123
+ if (typeof value !== "string")
124
+ return undefined;
125
+ try {
126
+ const parsed = JSON.parse(value);
127
+ return typeof parsed.leaseToken === "string" ? parsed.leaseToken : undefined;
128
+ }
129
+ catch {
130
+ return undefined;
131
+ }
132
+ }
133
+ function requiredJson(value) {
134
+ if (value === null)
135
+ throw new Error("Idempotency response is missing");
136
+ return value;
137
+ }
138
+ function iso(value) {
139
+ return new Date(value).toISOString();
140
+ }
141
+ //# sourceMappingURL=database-idempotency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-idempotency.js","sourceRoot":"","sources":["../../../sources/modules/request/database-idempotency.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAe,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAwB,MAAM,eAAe,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAQ/C,MAAM,UAAU,GAAG,CAAC,UAAkB,EAAE,EAAE,CACtC,GAAG,CACC,EAAE,CAAC,eAAe,CAAC,aAAa,EAAE,QAAQ,CAAC,EAC3C,EAAE,CAAC,eAAe,CAAC,WAAW,EAAE,MAAM,CAAC,EACvC,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,SAAS,CAAC,EACpC,EAAE,CAAC,eAAe,CAAC,cAAc,EAAE,UAAU,CAAC,CACjD,CAAC;AAEN,8FAA8F;AAC9F,MAAM,OAAO,wBAAwB;IAChB,MAAM,CAAS;IACf,EAAE,CAAC;IACH,UAAU,CAAU;IAErC,YAAY,MAAuB,EAAE,SAAkB;QACnD,IAAI,CAAC,UAAU,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC;QAC7C,IAAI,CAAC,MAAM;YACP,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACnF,IAAI,CAAC,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAA8B;QACxC,OAAO,eAAe,CAAC,GAAG,EAAE,CACxB,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YAC7B,IAAI,GAAG,GAAuB,MAAM,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;YAC/D,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;gBAChD,MAAM,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;gBACvE,GAAG,GAAG,SAAS,CAAC;YACpB,CAAC;YACD,IAAI,GAAG,EAAE,CAAC;gBACN,IAAI,GAAG,CAAC,WAAW,KAAK,KAAK,CAAC,WAAW;oBAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;gBACvE,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW;oBAC1B,OAAO;wBACH,IAAI,EAAE,QAAQ;wBACd,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAc;qBACpE,CAAC;gBACN,IAAI,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC,GAAG;oBAC1D,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;gBACzE,MAAM,EAAE;qBACH,MAAM,CAAC,eAAe,CAAC;qBACvB,GAAG,CAAC;oBACD,MAAM,EAAE,aAAa;oBACrB,WAAW,EAAE,KAAK,CAAC,WAAW;oBAC9B,cAAc,EAAE,IAAI;oBACpB,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;oBAC9D,WAAW,EAAE,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC;oBACtC,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC;oBACrC,SAAS,EAAE,GAAG,CAAA,mBAAmB;iBACpC,CAAC;qBACD,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC3C,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;YAChC,CAAC;YACD,MAAM,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC;gBACpC,EAAE,EAAE,QAAQ,EAAE;gBACd,aAAa,EAAE,QAAQ;gBACvB,WAAW,EAAE,MAAM;gBACnB,KAAK,EAAE,SAAS;gBAChB,cAAc,EAAE,KAAK,CAAC,UAAU;gBAChC,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,MAAM,EAAE,aAAa;gBACrB,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;gBAC9D,WAAW,EAAE,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC;gBACtC,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC;aACxC,CAAC,CAAC;YACH,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;QAChC,CAAC,CAAC,CACL,CAAC;IACN,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAA0C;QACrD,OAAO,eAAe,CAAC,GAAG,EAAE,CACxB,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YAC7B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;YAC7C,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,aAAa;gBAAE,OAAO,KAAK,CAAC;YACvD,IAAI,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,KAAK,CAAC,UAAU;gBAAE,OAAO,KAAK,CAAC;YACpE,MAAM,OAAO,GAAG,MAAM,EAAE;iBACnB,MAAM,CAAC,eAAe,CAAC;iBACvB,GAAG,CAAC;gBACD,MAAM,EAAE,WAAW;gBACnB,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC;gBAC5C,WAAW,EAAE,IAAI;gBACjB,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC;gBACrC,SAAS,EAAE,GAAG,CAAA,mBAAmB;aACpC,CAAC;iBACD,KAAK,CACF,GAAG,CACC,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,EAC9B,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,aAAa,CAAC,CAC5C,CACJ;iBACA,SAAS,CAAC,EAAE,EAAE,EAAE,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3C,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;QAChC,CAAC,CAAC,CACL,CAAC;IACN,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAAkB,EAAE,KAAa;QAC3C,OAAO,eAAe,CAAC,GAAG,EAAE,CACxB,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YAC7B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACvC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,aAAa,IAAI,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,KAAK;gBAC9E,OAAO,KAAK,CAAC;YACjB,MAAM,OAAO,GAAG,MAAM,EAAE;iBACnB,MAAM,CAAC,eAAe,CAAC;iBACvB,KAAK,CACF,GAAG,CACC,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,EAC9B,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,aAAa,CAAC,CAC5C,CACJ;iBACA,SAAS,CAAC,EAAE,EAAE,EAAE,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3C,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;QAChC,CAAC,CAAC,CACL,CAAC;IACN,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,GAAW,EAAE,KAAK,GAAG,KAAK;QACzC,OAAO,eAAe,CAAC,GAAG,EAAE,CACxB,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YAC7B,MAAM,GAAG,GAAG,MAAM,EAAE;iBACf,MAAM,CAAC,EAAE,EAAE,EAAE,eAAe,CAAC,EAAE,EAAE,CAAC;iBAClC,IAAI,CAAC,eAAe,CAAC;iBACrB,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;iBAC/C,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;iBAChE,KAAK,CAAC,KAAK,CAAC,CAAC;YAClB,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,CAAC,CAAC;YAC/B,OAAO,CACH,MAAM,EAAE;iBACH,MAAM,CAAC,eAAe,CAAC;iBACvB,KAAK,CACF,OAAO,CACH,eAAe,CAAC,EAAE,EAClB,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAC1B,CACJ;iBACA,SAAS,CAAC,EAAE,EAAE,EAAE,eAAe,CAAC,EAAE,EAAE,CAAC,CAC7C,CAAC,MAAM,CAAC;QACb,CAAC,CAAC,CACL,CAAC;IACN,CAAC;IAED,KAAK;QACD,IAAI,IAAI,CAAC,UAAU;YAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC7C,CAAC;CACJ;AAID,KAAK,UAAU,IAAI,CAAC,QAAyB,EAAE,UAAkB;IAC7D,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IACzF,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChD,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAA6B,CAAC;QAC7D,OAAO,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IACjF,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,SAAS,CAAC;IACrB,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,KAAoB;IACtC,IAAI,KAAK,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACvE,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,GAAG,CAAC,KAAa;IACtB,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;AACzC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { FastifyInstance } from "fastify";
2
+ import type { AuthService } from "../auth/service.js";
3
+ import { type IdempotencyCoordinator } from "./idempotency.js";
4
+ export interface StoredHttpResponse {
5
+ statusCode: number;
6
+ contentType?: string;
7
+ payload: string;
8
+ encoding: "utf8" | "base64";
9
+ }
10
+ /** Adds optional Idempotency-Key support uniformly to authenticated JSON POST actions. */
11
+ export declare function registerIdempotencyHooks(app: FastifyInstance, auth: AuthService, coordinator: IdempotencyCoordinator<StoredHttpResponse>): void;
12
+ //# sourceMappingURL=idempotency-hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency-hook.d.ts","sourceRoot":"","sources":["../../../sources/modules/request/idempotency-hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAKH,KAAK,sBAAsB,EAE9B,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,kBAAkB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC;CAC/B;AAED,0FAA0F;AAC1F,wBAAgB,wBAAwB,CACpC,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,WAAW,EACjB,WAAW,EAAE,sBAAsB,CAAC,kBAAkB,CAAC,GACxD,IAAI,CAwFN"}