@digimuza/saas-core 0.0.2

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 (474) hide show
  1. package/CLAUDE.md +1165 -0
  2. package/LICENSE +21 -0
  3. package/README.md +234 -0
  4. package/dist/api-keys/index.d.ts +9 -0
  5. package/dist/api-keys/index.d.ts.map +1 -0
  6. package/dist/api-keys/index.js +37 -0
  7. package/dist/api-keys/index.js.map +1 -0
  8. package/dist/api-keys/keys.d.ts +55 -0
  9. package/dist/api-keys/keys.d.ts.map +1 -0
  10. package/dist/api-keys/keys.js +92 -0
  11. package/dist/api-keys/keys.js.map +1 -0
  12. package/dist/api-keys/service.d.ts +111 -0
  13. package/dist/api-keys/service.d.ts.map +1 -0
  14. package/dist/api-keys/service.js +210 -0
  15. package/dist/api-keys/service.js.map +1 -0
  16. package/dist/audit/index.d.ts +5 -0
  17. package/dist/audit/index.d.ts.map +1 -0
  18. package/dist/audit/index.js +44 -0
  19. package/dist/audit/index.js.map +1 -0
  20. package/dist/audit/service.d.ts +88 -0
  21. package/dist/audit/service.d.ts.map +1 -0
  22. package/dist/audit/service.js +128 -0
  23. package/dist/audit/service.js.map +1 -0
  24. package/dist/auth/client.d.ts +5 -0
  25. package/dist/auth/client.d.ts.map +1 -0
  26. package/dist/auth/client.js +26 -0
  27. package/dist/auth/client.js.map +1 -0
  28. package/dist/auth/cookies.d.ts +51 -0
  29. package/dist/auth/cookies.d.ts.map +1 -0
  30. package/dist/auth/cookies.js +58 -0
  31. package/dist/auth/cookies.js.map +1 -0
  32. package/dist/auth/index.d.ts +14 -0
  33. package/dist/auth/index.d.ts.map +1 -0
  34. package/dist/auth/index.js +46 -0
  35. package/dist/auth/index.js.map +1 -0
  36. package/dist/auth/service.d.ts +67 -0
  37. package/dist/auth/service.d.ts.map +1 -0
  38. package/dist/auth/service.js +275 -0
  39. package/dist/auth/service.js.map +1 -0
  40. package/dist/auth/types.d.ts +56 -0
  41. package/dist/auth/types.d.ts.map +1 -0
  42. package/dist/auth/types.js +2 -0
  43. package/dist/auth/types.js.map +1 -0
  44. package/dist/authorization/index.d.ts +4 -0
  45. package/dist/authorization/index.d.ts.map +1 -0
  46. package/dist/authorization/index.js +24 -0
  47. package/dist/authorization/index.js.map +1 -0
  48. package/dist/authorization/service.d.ts +92 -0
  49. package/dist/authorization/service.d.ts.map +1 -0
  50. package/dist/authorization/service.js +254 -0
  51. package/dist/authorization/service.js.map +1 -0
  52. package/dist/billing/index.d.ts +16 -0
  53. package/dist/billing/index.d.ts.map +1 -0
  54. package/dist/billing/index.js +47 -0
  55. package/dist/billing/index.js.map +1 -0
  56. package/dist/billing/provider.d.ts +114 -0
  57. package/dist/billing/provider.d.ts.map +1 -0
  58. package/dist/billing/provider.js +2 -0
  59. package/dist/billing/provider.js.map +1 -0
  60. package/dist/billing/revolut.d.ts +68 -0
  61. package/dist/billing/revolut.d.ts.map +1 -0
  62. package/dist/billing/revolut.js +181 -0
  63. package/dist/billing/revolut.js.map +1 -0
  64. package/dist/billing/service.d.ts +124 -0
  65. package/dist/billing/service.d.ts.map +1 -0
  66. package/dist/billing/service.js +470 -0
  67. package/dist/billing/service.js.map +1 -0
  68. package/dist/cli/commands/dev.d.ts +43 -0
  69. package/dist/cli/commands/dev.d.ts.map +1 -0
  70. package/dist/cli/commands/dev.js +212 -0
  71. package/dist/cli/commands/dev.js.map +1 -0
  72. package/dist/cli/commands/project.d.ts +12 -0
  73. package/dist/cli/commands/project.d.ts.map +1 -0
  74. package/dist/cli/commands/project.js +49 -0
  75. package/dist/cli/commands/project.js.map +1 -0
  76. package/dist/cli/docker.d.ts +50 -0
  77. package/dist/cli/docker.d.ts.map +1 -0
  78. package/dist/cli/docker.js +84 -0
  79. package/dist/cli/docker.js.map +1 -0
  80. package/dist/cli/index.d.ts +6 -0
  81. package/dist/cli/index.d.ts.map +1 -0
  82. package/dist/cli/index.js +198 -0
  83. package/dist/cli/index.js.map +1 -0
  84. package/dist/cli/output.d.ts +30 -0
  85. package/dist/cli/output.d.ts.map +1 -0
  86. package/dist/cli/output.js +66 -0
  87. package/dist/cli/output.js.map +1 -0
  88. package/dist/cli/templates.d.ts +52 -0
  89. package/dist/cli/templates.d.ts.map +1 -0
  90. package/dist/cli/templates.js +225 -0
  91. package/dist/cli/templates.js.map +1 -0
  92. package/dist/config/client.d.ts +60 -0
  93. package/dist/config/client.d.ts.map +1 -0
  94. package/dist/config/client.js +94 -0
  95. package/dist/config/client.js.map +1 -0
  96. package/dist/config/config-loader.d.ts +2 -0
  97. package/dist/config/config-loader.d.ts.map +1 -0
  98. package/dist/config/config-loader.js +2 -0
  99. package/dist/config/config-loader.js.map +1 -0
  100. package/dist/config/env.d.ts +24 -0
  101. package/dist/config/env.d.ts.map +1 -0
  102. package/dist/config/env.js +40 -0
  103. package/dist/config/env.js.map +1 -0
  104. package/dist/config/errors.d.ts +17 -0
  105. package/dist/config/errors.d.ts.map +1 -0
  106. package/dist/config/errors.js +26 -0
  107. package/dist/config/errors.js.map +1 -0
  108. package/dist/config/index.d.ts +72 -0
  109. package/dist/config/index.d.ts.map +1 -0
  110. package/dist/config/index.js +106 -0
  111. package/dist/config/index.js.map +1 -0
  112. package/dist/config/runtime.d.ts +15 -0
  113. package/dist/config/runtime.d.ts.map +1 -0
  114. package/dist/config/runtime.js +22 -0
  115. package/dist/config/runtime.js.map +1 -0
  116. package/dist/config/sections.d.ts +226 -0
  117. package/dist/config/sections.d.ts.map +1 -0
  118. package/dist/config/sections.js +141 -0
  119. package/dist/config/sections.js.map +1 -0
  120. package/dist/db/client.d.ts +43 -0
  121. package/dist/db/client.d.ts.map +1 -0
  122. package/dist/db/client.js +77 -0
  123. package/dist/db/client.js.map +1 -0
  124. package/dist/db/errors.d.ts +39 -0
  125. package/dist/db/errors.d.ts.map +1 -0
  126. package/dist/db/errors.js +67 -0
  127. package/dist/db/errors.js.map +1 -0
  128. package/dist/db/index.d.ts +10 -0
  129. package/dist/db/index.d.ts.map +1 -0
  130. package/dist/db/index.js +10 -0
  131. package/dist/db/index.js.map +1 -0
  132. package/dist/db/migrate.d.ts +21 -0
  133. package/dist/db/migrate.d.ts.map +1 -0
  134. package/dist/db/migrate.js +28 -0
  135. package/dist/db/migrate.js.map +1 -0
  136. package/dist/db/schema/_shared.d.ts +30 -0
  137. package/dist/db/schema/_shared.d.ts.map +1 -0
  138. package/dist/db/schema/_shared.js +36 -0
  139. package/dist/db/schema/_shared.js.map +1 -0
  140. package/dist/db/schema/apikeys.d.ts +263 -0
  141. package/dist/db/schema/apikeys.d.ts.map +1 -0
  142. package/dist/db/schema/apikeys.js +70 -0
  143. package/dist/db/schema/apikeys.js.map +1 -0
  144. package/dist/db/schema/authorization.d.ts +465 -0
  145. package/dist/db/schema/authorization.d.ts.map +1 -0
  146. package/dist/db/schema/authorization.js +134 -0
  147. package/dist/db/schema/authorization.js.map +1 -0
  148. package/dist/db/schema/billing.d.ts +1100 -0
  149. package/dist/db/schema/billing.d.ts.map +1 -0
  150. package/dist/db/schema/billing.js +223 -0
  151. package/dist/db/schema/billing.js.map +1 -0
  152. package/dist/db/schema/events.d.ts +161 -0
  153. package/dist/db/schema/events.d.ts.map +1 -0
  154. package/dist/db/schema/events.js +66 -0
  155. package/dist/db/schema/events.js.map +1 -0
  156. package/dist/db/schema/features.d.ts +243 -0
  157. package/dist/db/schema/features.d.ts.map +1 -0
  158. package/dist/db/schema/features.js +87 -0
  159. package/dist/db/schema/features.js.map +1 -0
  160. package/dist/db/schema/files.d.ts +253 -0
  161. package/dist/db/schema/files.d.ts.map +1 -0
  162. package/dist/db/schema/files.js +74 -0
  163. package/dist/db/schema/files.js.map +1 -0
  164. package/dist/db/schema/index.d.ts +38 -0
  165. package/dist/db/schema/index.d.ts.map +1 -0
  166. package/dist/db/schema/index.js +38 -0
  167. package/dist/db/schema/index.js.map +1 -0
  168. package/dist/db/schema/invitations.d.ts +214 -0
  169. package/dist/db/schema/invitations.d.ts.map +1 -0
  170. package/dist/db/schema/invitations.js +80 -0
  171. package/dist/db/schema/invitations.js.map +1 -0
  172. package/dist/db/schema/messaging.d.ts +442 -0
  173. package/dist/db/schema/messaging.d.ts.map +1 -0
  174. package/dist/db/schema/messaging.js +120 -0
  175. package/dist/db/schema/messaging.js.map +1 -0
  176. package/dist/db/schema/users.d.ts +246 -0
  177. package/dist/db/schema/users.d.ts.map +1 -0
  178. package/dist/db/schema/users.js +60 -0
  179. package/dist/db/schema/users.js.map +1 -0
  180. package/dist/db/schema/webhooks.d.ts +693 -0
  181. package/dist/db/schema/webhooks.d.ts.map +1 -0
  182. package/dist/db/schema/webhooks.js +147 -0
  183. package/dist/db/schema/webhooks.js.map +1 -0
  184. package/dist/db/schema/workspaces.d.ts +196 -0
  185. package/dist/db/schema/workspaces.d.ts.map +1 -0
  186. package/dist/db/schema/workspaces.js +57 -0
  187. package/dist/db/schema/workspaces.js.map +1 -0
  188. package/dist/db/types.d.ts +18 -0
  189. package/dist/db/types.d.ts.map +1 -0
  190. package/dist/db/types.js +2 -0
  191. package/dist/db/types.js.map +1 -0
  192. package/dist/email/adapters.d.ts +29 -0
  193. package/dist/email/adapters.d.ts.map +1 -0
  194. package/dist/email/adapters.js +60 -0
  195. package/dist/email/adapters.js.map +1 -0
  196. package/dist/email/index.d.ts +20 -0
  197. package/dist/email/index.d.ts.map +1 -0
  198. package/dist/email/index.js +79 -0
  199. package/dist/email/index.js.map +1 -0
  200. package/dist/email/provider.d.ts +47 -0
  201. package/dist/email/provider.d.ts.map +1 -0
  202. package/dist/email/provider.js +7 -0
  203. package/dist/email/provider.js.map +1 -0
  204. package/dist/email/resend.d.ts +22 -0
  205. package/dist/email/resend.d.ts.map +1 -0
  206. package/dist/email/resend.js +51 -0
  207. package/dist/email/resend.js.map +1 -0
  208. package/dist/email/service.d.ts +55 -0
  209. package/dist/email/service.d.ts.map +1 -0
  210. package/dist/email/service.js +87 -0
  211. package/dist/email/service.js.map +1 -0
  212. package/dist/email/templates.d.ts +81 -0
  213. package/dist/email/templates.d.ts.map +1 -0
  214. package/dist/email/templates.js +84 -0
  215. package/dist/email/templates.js.map +1 -0
  216. package/dist/entitlements/index.d.ts +10 -0
  217. package/dist/entitlements/index.d.ts.map +1 -0
  218. package/dist/entitlements/index.js +28 -0
  219. package/dist/entitlements/index.js.map +1 -0
  220. package/dist/entitlements/service.d.ts +83 -0
  221. package/dist/entitlements/service.d.ts.map +1 -0
  222. package/dist/entitlements/service.js +158 -0
  223. package/dist/entitlements/service.js.map +1 -0
  224. package/dist/errors.d.ts +85 -0
  225. package/dist/errors.d.ts.map +1 -0
  226. package/dist/errors.js +95 -0
  227. package/dist/errors.js.map +1 -0
  228. package/dist/events/core-events.d.ts +120 -0
  229. package/dist/events/core-events.d.ts.map +1 -0
  230. package/dist/events/core-events.js +109 -0
  231. package/dist/events/core-events.js.map +1 -0
  232. package/dist/events/index.d.ts +15 -0
  233. package/dist/events/index.d.ts.map +1 -0
  234. package/dist/events/index.js +58 -0
  235. package/dist/events/index.js.map +1 -0
  236. package/dist/events/publisher.d.ts +46 -0
  237. package/dist/events/publisher.d.ts.map +1 -0
  238. package/dist/events/publisher.js +54 -0
  239. package/dist/events/publisher.js.map +1 -0
  240. package/dist/events/registry.d.ts +87 -0
  241. package/dist/events/registry.d.ts.map +1 -0
  242. package/dist/events/registry.js +34 -0
  243. package/dist/events/registry.js.map +1 -0
  244. package/dist/events/service.d.ts +78 -0
  245. package/dist/events/service.d.ts.map +1 -0
  246. package/dist/events/service.js +182 -0
  247. package/dist/events/service.js.map +1 -0
  248. package/dist/features/bucket.d.ts +22 -0
  249. package/dist/features/bucket.d.ts.map +1 -0
  250. package/dist/features/bucket.js +42 -0
  251. package/dist/features/bucket.js.map +1 -0
  252. package/dist/features/index.d.ts +15 -0
  253. package/dist/features/index.d.ts.map +1 -0
  254. package/dist/features/index.js +78 -0
  255. package/dist/features/index.js.map +1 -0
  256. package/dist/features/registry.d.ts +51 -0
  257. package/dist/features/registry.d.ts.map +1 -0
  258. package/dist/features/registry.js +52 -0
  259. package/dist/features/registry.js.map +1 -0
  260. package/dist/features/service.d.ts +78 -0
  261. package/dist/features/service.d.ts.map +1 -0
  262. package/dist/features/service.js +207 -0
  263. package/dist/features/service.js.map +1 -0
  264. package/dist/files/index.d.ts +6 -0
  265. package/dist/files/index.d.ts.map +1 -0
  266. package/dist/files/index.js +64 -0
  267. package/dist/files/index.js.map +1 -0
  268. package/dist/files/service.d.ts +92 -0
  269. package/dist/files/service.d.ts.map +1 -0
  270. package/dist/files/service.js +303 -0
  271. package/dist/files/service.js.map +1 -0
  272. package/dist/index.d.ts +33 -0
  273. package/dist/index.d.ts.map +1 -0
  274. package/dist/index.js +33 -0
  275. package/dist/index.js.map +1 -0
  276. package/dist/jobs/backend.d.ts +23 -0
  277. package/dist/jobs/backend.d.ts.map +1 -0
  278. package/dist/jobs/backend.js +23 -0
  279. package/dist/jobs/backend.js.map +1 -0
  280. package/dist/jobs/index.d.ts +29 -0
  281. package/dist/jobs/index.d.ts.map +1 -0
  282. package/dist/jobs/index.js +114 -0
  283. package/dist/jobs/index.js.map +1 -0
  284. package/dist/jobs/service.d.ts +67 -0
  285. package/dist/jobs/service.d.ts.map +1 -0
  286. package/dist/jobs/service.js +139 -0
  287. package/dist/jobs/service.js.map +1 -0
  288. package/dist/jobs/types.d.ts +78 -0
  289. package/dist/jobs/types.d.ts.map +1 -0
  290. package/dist/jobs/types.js +4 -0
  291. package/dist/jobs/types.js.map +1 -0
  292. package/dist/logger/default.d.ts +7 -0
  293. package/dist/logger/default.d.ts.map +1 -0
  294. package/dist/logger/default.js +28 -0
  295. package/dist/logger/default.js.map +1 -0
  296. package/dist/logger/index.d.ts +24 -0
  297. package/dist/logger/index.d.ts.map +1 -0
  298. package/dist/logger/index.js +90 -0
  299. package/dist/logger/index.js.map +1 -0
  300. package/dist/logger/redact.d.ts +40 -0
  301. package/dist/logger/redact.d.ts.map +1 -0
  302. package/dist/logger/redact.js +178 -0
  303. package/dist/logger/redact.js.map +1 -0
  304. package/dist/logger/service.d.ts +14 -0
  305. package/dist/logger/service.d.ts.map +1 -0
  306. package/dist/logger/service.js +56 -0
  307. package/dist/logger/service.js.map +1 -0
  308. package/dist/logger/sinks.d.ts +37 -0
  309. package/dist/logger/sinks.d.ts.map +1 -0
  310. package/dist/logger/sinks.js +135 -0
  311. package/dist/logger/sinks.js.map +1 -0
  312. package/dist/logger/types.d.ts +47 -0
  313. package/dist/logger/types.d.ts.map +1 -0
  314. package/dist/logger/types.js +8 -0
  315. package/dist/logger/types.js.map +1 -0
  316. package/dist/notifications/index.d.ts +8 -0
  317. package/dist/notifications/index.d.ts.map +1 -0
  318. package/dist/notifications/index.js +72 -0
  319. package/dist/notifications/index.js.map +1 -0
  320. package/dist/notifications/service.d.ts +79 -0
  321. package/dist/notifications/service.d.ts.map +1 -0
  322. package/dist/notifications/service.js +164 -0
  323. package/dist/notifications/service.js.map +1 -0
  324. package/dist/realtime/channels.d.ts +37 -0
  325. package/dist/realtime/channels.d.ts.map +1 -0
  326. package/dist/realtime/channels.js +58 -0
  327. package/dist/realtime/channels.js.map +1 -0
  328. package/dist/realtime/index.d.ts +19 -0
  329. package/dist/realtime/index.d.ts.map +1 -0
  330. package/dist/realtime/index.js +118 -0
  331. package/dist/realtime/index.js.map +1 -0
  332. package/dist/realtime/postgres.d.ts +48 -0
  333. package/dist/realtime/postgres.d.ts.map +1 -0
  334. package/dist/realtime/postgres.js +151 -0
  335. package/dist/realtime/postgres.js.map +1 -0
  336. package/dist/realtime/service.d.ts +75 -0
  337. package/dist/realtime/service.d.ts.map +1 -0
  338. package/dist/realtime/service.js +103 -0
  339. package/dist/realtime/service.js.map +1 -0
  340. package/dist/realtime/sse.d.ts +55 -0
  341. package/dist/realtime/sse.d.ts.map +1 -0
  342. package/dist/realtime/sse.js +123 -0
  343. package/dist/realtime/sse.js.map +1 -0
  344. package/dist/realtime/transport.d.ts +52 -0
  345. package/dist/realtime/transport.d.ts.map +1 -0
  346. package/dist/realtime/transport.js +2 -0
  347. package/dist/realtime/transport.js.map +1 -0
  348. package/dist/storage/index.d.ts +18 -0
  349. package/dist/storage/index.d.ts.map +1 -0
  350. package/dist/storage/index.js +89 -0
  351. package/dist/storage/index.js.map +1 -0
  352. package/dist/storage/keys.d.ts +50 -0
  353. package/dist/storage/keys.d.ts.map +1 -0
  354. package/dist/storage/keys.js +120 -0
  355. package/dist/storage/keys.js.map +1 -0
  356. package/dist/storage/memory.d.ts +32 -0
  357. package/dist/storage/memory.d.ts.map +1 -0
  358. package/dist/storage/memory.js +84 -0
  359. package/dist/storage/memory.js.map +1 -0
  360. package/dist/storage/provider.d.ts +93 -0
  361. package/dist/storage/provider.d.ts.map +1 -0
  362. package/dist/storage/provider.js +2 -0
  363. package/dist/storage/provider.js.map +1 -0
  364. package/dist/storage/s3.d.ts +34 -0
  365. package/dist/storage/s3.d.ts.map +1 -0
  366. package/dist/storage/s3.js +175 -0
  367. package/dist/storage/s3.js.map +1 -0
  368. package/dist/storage/service.d.ts +86 -0
  369. package/dist/storage/service.d.ts.map +1 -0
  370. package/dist/storage/service.js +107 -0
  371. package/dist/storage/service.js.map +1 -0
  372. package/dist/storage/sigv4.d.ts +58 -0
  373. package/dist/storage/sigv4.d.ts.map +1 -0
  374. package/dist/storage/sigv4.js +114 -0
  375. package/dist/storage/sigv4.js.map +1 -0
  376. package/dist/streams/client.d.ts +91 -0
  377. package/dist/streams/client.d.ts.map +1 -0
  378. package/dist/streams/client.js +128 -0
  379. package/dist/streams/client.js.map +1 -0
  380. package/dist/streams/events.d.ts +68 -0
  381. package/dist/streams/events.d.ts.map +1 -0
  382. package/dist/streams/events.js +81 -0
  383. package/dist/streams/events.js.map +1 -0
  384. package/dist/streams/index.d.ts +47 -0
  385. package/dist/streams/index.d.ts.map +1 -0
  386. package/dist/streams/index.js +47 -0
  387. package/dist/streams/index.js.map +1 -0
  388. package/dist/streams/realtime.d.ts +27 -0
  389. package/dist/streams/realtime.d.ts.map +1 -0
  390. package/dist/streams/realtime.js +50 -0
  391. package/dist/streams/realtime.js.map +1 -0
  392. package/dist/streams/state.d.ts +26 -0
  393. package/dist/streams/state.d.ts.map +1 -0
  394. package/dist/streams/state.js +34 -0
  395. package/dist/streams/state.js.map +1 -0
  396. package/dist/users/index.d.ts +9 -0
  397. package/dist/users/index.d.ts.map +1 -0
  398. package/dist/users/index.js +23 -0
  399. package/dist/users/index.js.map +1 -0
  400. package/dist/users/service.d.ts +43 -0
  401. package/dist/users/service.d.ts.map +1 -0
  402. package/dist/users/service.js +113 -0
  403. package/dist/users/service.js.map +1 -0
  404. package/dist/webhooks/inbound.d.ts +70 -0
  405. package/dist/webhooks/inbound.d.ts.map +1 -0
  406. package/dist/webhooks/inbound.js +146 -0
  407. package/dist/webhooks/inbound.js.map +1 -0
  408. package/dist/webhooks/index.d.ts +12 -0
  409. package/dist/webhooks/index.d.ts.map +1 -0
  410. package/dist/webhooks/index.js +65 -0
  411. package/dist/webhooks/index.js.map +1 -0
  412. package/dist/webhooks/outgoing.d.ts +89 -0
  413. package/dist/webhooks/outgoing.d.ts.map +1 -0
  414. package/dist/webhooks/outgoing.js +375 -0
  415. package/dist/webhooks/outgoing.js.map +1 -0
  416. package/dist/webhooks/signature.d.ts +40 -0
  417. package/dist/webhooks/signature.d.ts.map +1 -0
  418. package/dist/webhooks/signature.js +77 -0
  419. package/dist/webhooks/signature.js.map +1 -0
  420. package/dist/workspaces/context.d.ts +30 -0
  421. package/dist/workspaces/context.d.ts.map +1 -0
  422. package/dist/workspaces/context.js +12 -0
  423. package/dist/workspaces/context.js.map +1 -0
  424. package/dist/workspaces/index.d.ts +5 -0
  425. package/dist/workspaces/index.d.ts.map +1 -0
  426. package/dist/workspaces/index.js +21 -0
  427. package/dist/workspaces/index.js.map +1 -0
  428. package/dist/workspaces/service.d.ts +126 -0
  429. package/dist/workspaces/service.d.ts.map +1 -0
  430. package/dist/workspaces/service.js +495 -0
  431. package/dist/workspaces/service.js.map +1 -0
  432. package/docs/README.md +71 -0
  433. package/docs/api-keys.md +184 -0
  434. package/docs/audit.md +198 -0
  435. package/docs/auth.md +196 -0
  436. package/docs/authorization.md +225 -0
  437. package/docs/billing.md +293 -0
  438. package/docs/cli.md +238 -0
  439. package/docs/config.md +163 -0
  440. package/docs/db.md +219 -0
  441. package/docs/email.md +222 -0
  442. package/docs/entitlements.md +194 -0
  443. package/docs/errors.md +158 -0
  444. package/docs/events.md +279 -0
  445. package/docs/feature-flags.md +237 -0
  446. package/docs/files.md +229 -0
  447. package/docs/jobs.md +288 -0
  448. package/docs/logger.md +269 -0
  449. package/docs/notifications.md +179 -0
  450. package/docs/publishing.md +128 -0
  451. package/docs/realtime.md +360 -0
  452. package/docs/storage.md +279 -0
  453. package/docs/streams.md +296 -0
  454. package/docs/users.md +117 -0
  455. package/docs/webhooks.md +272 -0
  456. package/docs/workspaces.md +269 -0
  457. package/drizzle/0000_init_users.sql +21 -0
  458. package/drizzle/0001_workspaces_roles_permissions.sql +86 -0
  459. package/drizzle/0002_billing_entitlements.sql +97 -0
  460. package/drizzle/0003_events.sql +17 -0
  461. package/drizzle/0004_notifications_audit.sql +64 -0
  462. package/drizzle/0005_api_keys_webhooks.sql +77 -0
  463. package/drizzle/0006_feature_flags.sql +22 -0
  464. package/drizzle/0007_files.sql +23 -0
  465. package/drizzle/meta/0000_snapshot.json +160 -0
  466. package/drizzle/meta/0001_snapshot.json +837 -0
  467. package/drizzle/meta/0002_snapshot.json +1580 -0
  468. package/drizzle/meta/0003_snapshot.json +1751 -0
  469. package/drizzle/meta/0004_snapshot.json +2109 -0
  470. package/drizzle/meta/0005_snapshot.json +2719 -0
  471. package/drizzle/meta/0006_snapshot.json +2909 -0
  472. package/drizzle/meta/0007_snapshot.json +3113 -0
  473. package/drizzle/meta/_journal.json +62 -0
  474. package/package.json +180 -0
@@ -0,0 +1,147 @@
1
+ import { relations, sql } from "drizzle-orm";
2
+ import { boolean, index, integer, jsonb, pgEnum, pgTable, text, timestamp, unique, uuid, } from "drizzle-orm/pg-core";
3
+ import { events } from "./events.js";
4
+ import { primaryId, timestamps } from "./_shared.js";
5
+ import { workspaces } from "./workspaces.js";
6
+ export const webhookDeliveryStatus = pgEnum("webhook_delivery_status", [
7
+ "pending",
8
+ "succeeded",
9
+ "failed",
10
+ /** Retries exhausted. Terminal, and worth alerting on. */
11
+ "exhausted",
12
+ ]);
13
+ export const inboundWebhookStatus = pgEnum("inbound_webhook_status", [
14
+ "pending",
15
+ "processed",
16
+ "failed",
17
+ "ignored",
18
+ ]);
19
+ /**
20
+ * An outgoing webhook endpoint a workspace has registered.
21
+ *
22
+ * The signing secret is stored in the clear, unlike an API key. It has to be: the
23
+ * core signs every payload with it, and the receiving system needs the same value
24
+ * to verify. A one-way hash would make both impossible. Encryption at rest is the
25
+ * mitigation, and rotation is exposed so a leaked secret can be replaced without
26
+ * recreating the endpoint.
27
+ */
28
+ export const webhookEndpoints = pgTable("webhook_endpoints", {
29
+ id: primaryId(),
30
+ workspaceId: uuid("workspace_id")
31
+ .notNull()
32
+ .references(() => workspaces.id, { onDelete: "cascade" }),
33
+ url: text("url").notNull(),
34
+ description: text("description"),
35
+ /** HMAC-SHA256 signing secret. Rotatable. */
36
+ secret: text("secret").notNull(),
37
+ /** Event types this endpoint wants. Empty means every type. */
38
+ eventTypes: text("event_types").array().notNull().default(sql `'{}'::text[]`),
39
+ isActive: boolean("is_active").notNull().default(true),
40
+ /**
41
+ * Consecutive failed deliveries, reset by any success.
42
+ *
43
+ * An endpoint that has been broken for days should stop consuming retry
44
+ * budget — this is what lets a caller decide when to give up on it, without
45
+ * having to aggregate the delivery table on every dispatch.
46
+ */
47
+ consecutiveFailures: integer("consecutive_failures").notNull().default(0),
48
+ /** Set when the endpoint was disabled for repeated failure. */
49
+ disabledAt: timestamp("disabled_at", { withTimezone: true, mode: "date" }),
50
+ ...timestamps,
51
+ }, (table) => [
52
+ index("webhook_endpoints_workspace_idx").on(table.workspaceId),
53
+ // One registration per URL per workspace; a duplicate is always a mistake.
54
+ unique("webhook_endpoints_workspace_url_unique").on(table.workspaceId, table.url),
55
+ ]);
56
+ /**
57
+ * One attempt-tracked delivery of one event to one endpoint.
58
+ *
59
+ * A row per (endpoint, event) pair, created when the event is dispatched and
60
+ * updated as attempts happen. The unique constraint is the idempotency guarantee:
61
+ * dispatching the same event twice — a retried job, a replayed event — cannot
62
+ * produce a second delivery.
63
+ *
64
+ * Delivery is deliberately a *record*, not an in-flight promise. The HTTP call is
65
+ * driven by a durable worker reading this table, so a process dying mid-attempt
66
+ * loses nothing.
67
+ */
68
+ export const webhookDeliveries = pgTable("webhook_deliveries", {
69
+ id: primaryId(),
70
+ endpointId: uuid("endpoint_id")
71
+ .notNull()
72
+ .references(() => webhookEndpoints.id, { onDelete: "cascade" }),
73
+ /**
74
+ * The event being delivered. Cascades: an event that has been pruned has no
75
+ * delivery worth retrying.
76
+ */
77
+ eventId: uuid("event_id")
78
+ .notNull()
79
+ .references(() => events.id, { onDelete: "cascade" }),
80
+ /** Denormalised so a worker can filter without joining. */
81
+ eventType: text("event_type").notNull(),
82
+ /** Exactly what will be sent, frozen at dispatch. */
83
+ payload: jsonb("payload").notNull(),
84
+ status: webhookDeliveryStatus("status").notNull().default("pending"),
85
+ attemptCount: integer("attempt_count").notNull().default(0),
86
+ /** When the next attempt becomes due. Null once terminal. */
87
+ nextAttemptAt: timestamp("next_attempt_at", { withTimezone: true, mode: "date" }),
88
+ lastAttemptedAt: timestamp("last_attempted_at", { withTimezone: true, mode: "date" }),
89
+ /** HTTP status of the last attempt, when there was a response at all. */
90
+ responseStatus: integer("response_status"),
91
+ /** Truncated failure detail. Never contains the signing secret. */
92
+ error: text("error"),
93
+ ...timestamps,
94
+ }, (table) => [
95
+ unique("webhook_deliveries_endpoint_event_unique").on(table.endpointId, table.eventId),
96
+ /**
97
+ * The worker's query: "what is due now?". Ordered so pending work is found
98
+ * without scanning succeeded history.
99
+ */
100
+ index("webhook_deliveries_due_idx").on(table.status, table.nextAttemptAt),
101
+ index("webhook_deliveries_endpoint_idx").on(table.endpointId, table.createdAt.desc()),
102
+ ]);
103
+ /**
104
+ * A webhook received *from* an external system.
105
+ *
106
+ * Generalises what billing already does for Revolut: `(source, external_id)` is
107
+ * unique, and the insert is what claims an event for processing — so at-least-once
108
+ * delivery is handled by PostgreSQL rather than a check-then-act two concurrent
109
+ * requests could both pass.
110
+ *
111
+ * The raw payload is retained so a failed handler can be replayed without asking
112
+ * the sender to redeliver.
113
+ */
114
+ export const inboundWebhooks = pgTable("inbound_webhooks", {
115
+ id: primaryId(),
116
+ /** Which system sent it, e.g. `"github"`. */
117
+ source: text("source").notNull(),
118
+ /** The sender's own event id. The idempotency key. */
119
+ externalId: text("external_id").notNull(),
120
+ type: text("type").notNull(),
121
+ payload: jsonb("payload").notNull(),
122
+ /** Set when the sender identifies a tenant we can resolve. */
123
+ workspaceId: uuid("workspace_id").references(() => workspaces.id, { onDelete: "cascade" }),
124
+ status: inboundWebhookStatus("status").notNull().default("pending"),
125
+ processedAt: timestamp("processed_at", { withTimezone: true, mode: "date" }),
126
+ error: text("error"),
127
+ ...timestamps,
128
+ }, (table) => [
129
+ unique("inbound_webhooks_source_external_unique").on(table.source, table.externalId),
130
+ index("inbound_webhooks_status_idx").on(table.status),
131
+ index("inbound_webhooks_source_idx").on(table.source, table.createdAt.desc()),
132
+ ]);
133
+ export const webhookEndpointsRelations = relations(webhookEndpoints, ({ one, many }) => ({
134
+ workspace: one(workspaces, {
135
+ fields: [webhookEndpoints.workspaceId],
136
+ references: [workspaces.id],
137
+ }),
138
+ deliveries: many(webhookDeliveries),
139
+ }));
140
+ export const webhookDeliveriesRelations = relations(webhookDeliveries, ({ one }) => ({
141
+ endpoint: one(webhookEndpoints, {
142
+ fields: [webhookDeliveries.endpointId],
143
+ references: [webhookEndpoints.id],
144
+ }),
145
+ event: one(events, { fields: [webhookDeliveries.eventId], references: [events.id] }),
146
+ }));
147
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../../src/db/schema/webhooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,196 @@
1
+ /**
2
+ * A tenant. Every tenant-scoped row in the system hangs off a workspace.
3
+ *
4
+ * `slug` is not in the original column list but is included because workspaces
5
+ * are addressed in URLs (`/w/acme/projects`); without it every route would have
6
+ * to expose a UUID.
7
+ */
8
+ export declare const workspaces: import("drizzle-orm/pg-core").PgTableWithColumns<{
9
+ name: "workspaces";
10
+ schema: undefined;
11
+ columns: {
12
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
13
+ name: "created_at";
14
+ tableName: "workspaces";
15
+ dataType: "date";
16
+ columnType: "PgTimestamp";
17
+ data: Date;
18
+ driverParam: string;
19
+ notNull: true;
20
+ hasDefault: true;
21
+ isPrimaryKey: false;
22
+ isAutoincrement: false;
23
+ hasRuntimeDefault: false;
24
+ enumValues: undefined;
25
+ baseColumn: never;
26
+ identity: undefined;
27
+ generated: undefined;
28
+ }, {}, {}>;
29
+ updatedAt: import("drizzle-orm/pg-core").PgColumn<{
30
+ name: "updated_at";
31
+ tableName: "workspaces";
32
+ dataType: "date";
33
+ columnType: "PgTimestamp";
34
+ data: Date;
35
+ driverParam: string;
36
+ notNull: true;
37
+ hasDefault: true;
38
+ isPrimaryKey: false;
39
+ isAutoincrement: false;
40
+ hasRuntimeDefault: false;
41
+ enumValues: undefined;
42
+ baseColumn: never;
43
+ identity: undefined;
44
+ generated: undefined;
45
+ }, {}, {}>;
46
+ id: import("drizzle-orm/pg-core").PgColumn<{
47
+ name: "id";
48
+ tableName: "workspaces";
49
+ dataType: "string";
50
+ columnType: "PgUUID";
51
+ data: string;
52
+ driverParam: string;
53
+ notNull: true;
54
+ hasDefault: true;
55
+ isPrimaryKey: true;
56
+ isAutoincrement: false;
57
+ hasRuntimeDefault: false;
58
+ enumValues: undefined;
59
+ baseColumn: never;
60
+ identity: undefined;
61
+ generated: undefined;
62
+ }, {}, {}>;
63
+ name: import("drizzle-orm/pg-core").PgColumn<{
64
+ name: "name";
65
+ tableName: "workspaces";
66
+ dataType: "string";
67
+ columnType: "PgText";
68
+ data: string;
69
+ driverParam: string;
70
+ notNull: true;
71
+ hasDefault: false;
72
+ isPrimaryKey: false;
73
+ isAutoincrement: false;
74
+ hasRuntimeDefault: false;
75
+ enumValues: [string, ...string[]];
76
+ baseColumn: never;
77
+ identity: undefined;
78
+ generated: undefined;
79
+ }, {}, {}>;
80
+ slug: import("drizzle-orm/pg-core").PgColumn<{
81
+ name: "slug";
82
+ tableName: "workspaces";
83
+ dataType: "string";
84
+ columnType: "PgText";
85
+ data: string;
86
+ driverParam: string;
87
+ notNull: true;
88
+ hasDefault: false;
89
+ isPrimaryKey: false;
90
+ isAutoincrement: false;
91
+ hasRuntimeDefault: false;
92
+ enumValues: [string, ...string[]];
93
+ baseColumn: never;
94
+ identity: undefined;
95
+ generated: undefined;
96
+ }, {}, {}>;
97
+ };
98
+ dialect: 'pg';
99
+ }>;
100
+ /**
101
+ * The user-to-workspace relationship.
102
+ *
103
+ * A user's membership is the *only* thing that grants access to a workspace, so
104
+ * `workspace_id` never appears on `users`: a user belongs to many workspaces.
105
+ *
106
+ * The composite primary key doubles as the foreign-key target that
107
+ * `workspace_member_roles` uses to make cross-workspace role assignment
108
+ * structurally impossible.
109
+ */
110
+ export declare const workspaceMembers: import("drizzle-orm/pg-core").PgTableWithColumns<{
111
+ name: "workspace_members";
112
+ schema: undefined;
113
+ columns: {
114
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
115
+ name: "created_at";
116
+ tableName: "workspace_members";
117
+ dataType: "date";
118
+ columnType: "PgTimestamp";
119
+ data: Date;
120
+ driverParam: string;
121
+ notNull: true;
122
+ hasDefault: true;
123
+ isPrimaryKey: false;
124
+ isAutoincrement: false;
125
+ hasRuntimeDefault: false;
126
+ enumValues: undefined;
127
+ baseColumn: never;
128
+ identity: undefined;
129
+ generated: undefined;
130
+ }, {}, {}>;
131
+ updatedAt: import("drizzle-orm/pg-core").PgColumn<{
132
+ name: "updated_at";
133
+ tableName: "workspace_members";
134
+ dataType: "date";
135
+ columnType: "PgTimestamp";
136
+ data: Date;
137
+ driverParam: string;
138
+ notNull: true;
139
+ hasDefault: true;
140
+ isPrimaryKey: false;
141
+ isAutoincrement: false;
142
+ hasRuntimeDefault: false;
143
+ enumValues: undefined;
144
+ baseColumn: never;
145
+ identity: undefined;
146
+ generated: undefined;
147
+ }, {}, {}>;
148
+ workspaceId: import("drizzle-orm/pg-core").PgColumn<{
149
+ name: "workspace_id";
150
+ tableName: "workspace_members";
151
+ dataType: "string";
152
+ columnType: "PgUUID";
153
+ data: string;
154
+ driverParam: string;
155
+ notNull: true;
156
+ hasDefault: false;
157
+ isPrimaryKey: false;
158
+ isAutoincrement: false;
159
+ hasRuntimeDefault: false;
160
+ enumValues: undefined;
161
+ baseColumn: never;
162
+ identity: undefined;
163
+ generated: undefined;
164
+ }, {}, {}>;
165
+ userId: import("drizzle-orm/pg-core").PgColumn<{
166
+ name: "user_id";
167
+ tableName: "workspace_members";
168
+ dataType: "string";
169
+ columnType: "PgUUID";
170
+ data: string;
171
+ driverParam: string;
172
+ notNull: true;
173
+ hasDefault: false;
174
+ isPrimaryKey: false;
175
+ isAutoincrement: false;
176
+ hasRuntimeDefault: false;
177
+ enumValues: undefined;
178
+ baseColumn: never;
179
+ identity: undefined;
180
+ generated: undefined;
181
+ }, {}, {}>;
182
+ };
183
+ dialect: 'pg';
184
+ }>;
185
+ export declare const workspacesRelations: import("drizzle-orm").Relations<"workspaces", {
186
+ members: import("drizzle-orm").Many<"workspace_members">;
187
+ }>;
188
+ export declare const workspaceMembersRelations: import("drizzle-orm").Relations<"workspace_members", {
189
+ workspace: import("drizzle-orm").One<"workspaces", true>;
190
+ user: import("drizzle-orm").One<"users", true>;
191
+ }>;
192
+ export type Workspace = typeof workspaces.$inferSelect;
193
+ export type NewWorkspace = typeof workspaces.$inferInsert;
194
+ export type WorkspaceMember = typeof workspaceMembers.$inferSelect;
195
+ export type NewWorkspaceMember = typeof workspaceMembers.$inferInsert;
196
+ //# sourceMappingURL=workspaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../../src/db/schema/workspaces.ts"],"names":[],"mappings":"AAMA;;;;;;GAMG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKrB,CAAC;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmB5B,CAAC;AAEF,eAAO,MAAM,mBAAmB;;EAE7B,CAAC;AAEJ,eAAO,MAAM,yBAAyB;;;EASnC,CAAC;AAEJ,MAAM,MAAM,SAAS,GAAG,OAAO,UAAU,CAAC,YAAY,CAAC;AACvD,MAAM,MAAM,YAAY,GAAG,OAAO,UAAU,CAAC,YAAY,CAAC;AAC1D,MAAM,MAAM,eAAe,GAAG,OAAO,gBAAgB,CAAC,YAAY,CAAC;AACnE,MAAM,MAAM,kBAAkB,GAAG,OAAO,gBAAgB,CAAC,YAAY,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { relations } from "drizzle-orm";
2
+ import { index, pgTable, primaryKey, text, uuid } from "drizzle-orm/pg-core";
3
+ import { primaryId, timestamps } from "./_shared.js";
4
+ import { users } from "./users.js";
5
+ /**
6
+ * A tenant. Every tenant-scoped row in the system hangs off a workspace.
7
+ *
8
+ * `slug` is not in the original column list but is included because workspaces
9
+ * are addressed in URLs (`/w/acme/projects`); without it every route would have
10
+ * to expose a UUID.
11
+ */
12
+ export const workspaces = pgTable("workspaces", {
13
+ id: primaryId(),
14
+ name: text("name").notNull(),
15
+ slug: text("slug").notNull().unique(),
16
+ ...timestamps,
17
+ });
18
+ /**
19
+ * The user-to-workspace relationship.
20
+ *
21
+ * A user's membership is the *only* thing that grants access to a workspace, so
22
+ * `workspace_id` never appears on `users`: a user belongs to many workspaces.
23
+ *
24
+ * The composite primary key doubles as the foreign-key target that
25
+ * `workspace_member_roles` uses to make cross-workspace role assignment
26
+ * structurally impossible.
27
+ */
28
+ export const workspaceMembers = pgTable("workspace_members", {
29
+ workspaceId: uuid("workspace_id")
30
+ .notNull()
31
+ .references(() => workspaces.id, { onDelete: "cascade" }),
32
+ userId: uuid("user_id")
33
+ .notNull()
34
+ .references(() => users.id, { onDelete: "cascade" }),
35
+ ...timestamps,
36
+ }, (table) => [
37
+ primaryKey({ columns: [table.workspaceId, table.userId] }),
38
+ /**
39
+ * "Which workspaces does this user belong to?" cannot use the primary key,
40
+ * whose leading column is `workspace_id`.
41
+ */
42
+ index("workspace_members_user_id_idx").on(table.userId),
43
+ ]);
44
+ export const workspacesRelations = relations(workspaces, ({ many }) => ({
45
+ members: many(workspaceMembers),
46
+ }));
47
+ export const workspaceMembersRelations = relations(workspaceMembers, ({ one }) => ({
48
+ workspace: one(workspaces, {
49
+ fields: [workspaceMembers.workspaceId],
50
+ references: [workspaces.id],
51
+ }),
52
+ user: one(users, {
53
+ fields: [workspaceMembers.userId],
54
+ references: [users.id],
55
+ }),
56
+ }));
57
+ //# sourceMappingURL=workspaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../../../src/db/schema/workspaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE7E,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,EAAE;IAC9C,EAAE,EAAE,SAAS,EAAE;IACf,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE;IACrC,GAAG,UAAU;CACd,CAAC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CACrC,mBAAmB,EACnB;IACE,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC;SAC9B,OAAO,EAAE;SACT,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAC3D,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;SACpB,OAAO,EAAE;SACT,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtD,GAAG,UAAU;CACd,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1D;;;OAGG;IACH,KAAK,CAAC,+BAA+B,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;CACxD,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACtE,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAAC;CAChC,CAAC,CAAC,CAAC;AAEJ,MAAM,CAAC,MAAM,yBAAyB,GAAG,SAAS,CAAC,gBAAgB,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IACjF,SAAS,EAAE,GAAG,CAAC,UAAU,EAAE;QACzB,MAAM,EAAE,CAAC,gBAAgB,CAAC,WAAW,CAAC;QACtC,UAAU,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;KAC5B,CAAC;IACF,IAAI,EAAE,GAAG,CAAC,KAAK,EAAE;QACf,MAAM,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC;QACjC,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;KACvB,CAAC;CACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { ExtractTablesWithRelations } from "drizzle-orm";
2
+ import type { PgDatabase, PgQueryResultHKT, PgTransaction } from "drizzle-orm/pg-core";
3
+ import type * as schema from "./schema/index.ts";
4
+ export type CoreSchema = typeof schema;
5
+ type CoreRelations = ExtractTablesWithRelations<CoreSchema>;
6
+ /**
7
+ * A database handle typed against the core schema, independent of the driver.
8
+ *
9
+ * Services accept this rather than a concrete `PostgresJsDatabase` so the same
10
+ * code runs against postgres.js in production and PGlite in tests. A
11
+ * `PgTransaction` is assignable to it, so any service also composes inside a
12
+ * transaction.
13
+ */
14
+ export type CoreDatabase = PgDatabase<PgQueryResultHKT, CoreSchema, CoreRelations>;
15
+ /** A transaction over the core schema, as passed to `db.transaction(...)`. */
16
+ export type CoreTransaction = PgTransaction<PgQueryResultHKT, CoreSchema, CoreRelations>;
17
+ export {};
18
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/db/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEvF,OAAO,KAAK,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAEjD,MAAM,MAAM,UAAU,GAAG,OAAO,MAAM,CAAC;AAEvC,KAAK,aAAa,GAAG,0BAA0B,CAAC,UAAU,CAAC,CAAC;AAE5D;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,gBAAgB,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;AAEnF,8EAA8E;AAC9E,MAAM,MAAM,eAAe,GAAG,aAAa,CAAC,gBAAgB,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/db/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ import type { EmailProvider, OutgoingEmail } from "./provider.ts";
2
+ /**
3
+ * Logs instead of sending.
4
+ *
5
+ * The right default for local development: it needs no credentials, and it makes
6
+ * the message visible without a third-party inbox. Deliberately refuses to run in
7
+ * production, because silently discarding a password reset is worse than failing.
8
+ */
9
+ export interface ConsoleEmailOptions {
10
+ readonly log?: (line: string) => void;
11
+ /** Set true to allow it outside development. Almost always a mistake. */
12
+ readonly allowInProduction?: boolean;
13
+ readonly isProduction?: boolean;
14
+ }
15
+ export declare function createConsoleEmailProvider(options?: ConsoleEmailOptions): EmailProvider;
16
+ export interface MemoryEmailProvider extends EmailProvider {
17
+ readonly sent: OutgoingEmail[];
18
+ /** Every message sent to this address, for assertions. */
19
+ to(address: string): OutgoingEmail[];
20
+ clear(): void;
21
+ }
22
+ /**
23
+ * Collects messages in memory. For tests.
24
+ *
25
+ * Deduplicates on `idempotencyKey` so a test can assert retry-safety without a
26
+ * real provider — the behaviour a good provider gives you, made observable.
27
+ */
28
+ export declare function createMemoryEmailProvider(): MemoryEmailProvider;
29
+ //# sourceMappingURL=adapters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../../src/email/adapters.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAa,MAAM,eAAe,CAAC;AAG7E;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,yEAAyE;IACzE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,mBAAwB,GAAG,aAAa,CA6B3F;AAED,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,QAAQ,CAAC,IAAI,EAAE,aAAa,EAAE,CAAC;IAC/B,0DAA0D;IAC1D,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAAC;IACrC,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,IAAI,mBAAmB,CAmC/D"}
@@ -0,0 +1,60 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { formatAddress } from "./provider.js";
3
+ export function createConsoleEmailProvider(options = {}) {
4
+ const log = options.log ?? ((line) => console.info(line));
5
+ return {
6
+ name: "console",
7
+ async send(message) {
8
+ if (options.isProduction === true && options.allowInProduction !== true) {
9
+ throw new Error("The console email provider is refusing to run in production. " +
10
+ "Configure a real provider, or pass allowInProduction to override.");
11
+ }
12
+ log([
13
+ "--- email ---",
14
+ `to: ${message.to.map(formatAddress).join(", ")}`,
15
+ `from: ${formatAddress(message.from)}`,
16
+ `subject: ${message.subject}`,
17
+ "",
18
+ message.text,
19
+ "-------------",
20
+ ].join("\n"));
21
+ return { id: `console_${randomUUID()}`, provider: "console" };
22
+ },
23
+ };
24
+ }
25
+ /**
26
+ * Collects messages in memory. For tests.
27
+ *
28
+ * Deduplicates on `idempotencyKey` so a test can assert retry-safety without a
29
+ * real provider — the behaviour a good provider gives you, made observable.
30
+ */
31
+ export function createMemoryEmailProvider() {
32
+ const sent = [];
33
+ const seenKeys = new Set();
34
+ return {
35
+ name: "memory",
36
+ sent,
37
+ async send(message) {
38
+ if (message.idempotencyKey !== undefined) {
39
+ if (seenKeys.has(message.idempotencyKey)) {
40
+ return { id: `memory_dedup_${message.idempotencyKey}`, provider: "memory" };
41
+ }
42
+ seenKeys.add(message.idempotencyKey);
43
+ }
44
+ sent.push(message);
45
+ const digest = createHash("sha256")
46
+ .update(`${message.subject}:${sent.length}`)
47
+ .digest("hex")
48
+ .slice(0, 16);
49
+ return { id: `memory_${digest}`, provider: "memory" };
50
+ },
51
+ to(address) {
52
+ return sent.filter((message) => message.to.some((recipient) => recipient.address.toLowerCase() === address.toLowerCase()));
53
+ },
54
+ clear() {
55
+ sent.length = 0;
56
+ seenKeys.clear();
57
+ },
58
+ };
59
+ }
60
+ //# sourceMappingURL=adapters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.js","sourceRoot":"","sources":["../../src/email/adapters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGrD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAgB9C,MAAM,UAAU,0BAA0B,CAAC,OAAO,GAAwB,EAAE;IAC1E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAElE,OAAO;QACL,IAAI,EAAE,SAAS;QAEf,KAAK,CAAC,IAAI,CAAC,OAAsB;YAC/B,IAAI,OAAO,CAAC,YAAY,KAAK,IAAI,IAAI,OAAO,CAAC,iBAAiB,KAAK,IAAI,EAAE,CAAC;gBACxE,MAAM,IAAI,KAAK,CACb,+DAA+D;oBAC7D,mEAAmE,CACtE,CAAC;YACJ,CAAC;YAED,GAAG,CACD;gBACE,eAAe;gBACf,YAAY,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACtD,YAAY,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;gBACzC,YAAY,OAAO,CAAC,OAAO,EAAE;gBAC7B,EAAE;gBACF,OAAO,CAAC,IAAI;gBACZ,eAAe;aAChB,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;YAEF,OAAO,EAAE,EAAE,EAAE,WAAW,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;QAChE,CAAC;KACF,CAAC;AACJ,CAAC;AASD;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB;IACvC,MAAM,IAAI,GAAoB,EAAE,CAAC;IACjC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAEnC,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,IAAI;QAEJ,KAAK,CAAC,IAAI,CAAC,OAAO;YAChB,IAAI,OAAO,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;gBACzC,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;oBACzC,OAAO,EAAE,EAAE,EAAE,gBAAgB,OAAO,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;gBAC9E,CAAC;gBACD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YACvC,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACnB,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC;iBAChC,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;iBAC3C,MAAM,CAAC,KAAK,CAAC;iBACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAChB,OAAO,EAAE,EAAE,EAAE,UAAU,MAAM,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;QACxD,CAAC;QAED,EAAE,CAAC,OAAO;YACR,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAC7B,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAC1F,CAAC;QACJ,CAAC;QAED,KAAK;YACH,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;YAChB,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { EmailProvider } from "./provider.ts";
2
+ export { createConsoleEmailProvider, createMemoryEmailProvider, type ConsoleEmailOptions, type MemoryEmailProvider, } from "./adapters.ts";
3
+ export { formatAddress, type EmailAddress, type EmailProvider, type OutgoingEmail, type SentEmail, } from "./provider.ts";
4
+ export { createResendProvider, type ResendAdapterOptions } from "./resend.ts";
5
+ export { createEmailService, type EmailService, type EmailServiceDeps, type SendEmailInput, type SendTemplateInput, } from "./service.ts";
6
+ export { coreEmailTemplates, defineEmailTemplates, emailTemplate, mergeEmailTemplates, overrideEmailTemplates, type CoreEmailTemplates, type EmailTemplate, type EmailTemplateMap, type EmailTemplateName, type EmailTemplateRegistry, } from "./templates.ts";
7
+ /**
8
+ * A provider built from the `email` configuration section.
9
+ *
10
+ * Resend outside development, the console logger inside it — so a fresh checkout
11
+ * can send an invitation without credentials, while production refuses to
12
+ * silently discard one.
13
+ */
14
+ export declare function createConfiguredEmailProvider(): EmailProvider;
15
+ /** The configured default sender. */
16
+ export declare function configuredSender(): {
17
+ address: string;
18
+ name?: string;
19
+ };
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/email/index.ts"],"names":[],"mappings":"AAkDA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,oBAAoB,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAE9E,OAAO,EACL,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,iBAAiB,GACvB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,gBAAgB,CAAC;AAExB;;;;;;GAMG;AACH,wBAAgB,6BAA6B,IAAI,aAAa,CAQ7D;AAED,qCAAqC;AACrC,wBAAgB,gBAAgB,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAMrE"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Public email surface: `@digimuza/saas-core/email`. Server-only.
3
+ *
4
+ * Provider-independent by construction: everything above {@link EmailProvider} is
5
+ * generic, so adopting another provider means writing a ~20-line adapter.
6
+ *
7
+ * Templates are typed the same way events are — a Zod schema per template gives
8
+ * the compile-time payload type *and* validates at runtime, so a template
9
+ * rendered with the wrong data fails before a message is built rather than
10
+ * emailing a customer the word "undefined".
11
+ *
12
+ * ```ts
13
+ * import { z } from "zod";
14
+ * import {
15
+ * coreEmailTemplates, createEmailService, defineEmailTemplates,
16
+ * emailTemplate, mergeEmailTemplates, createResendProvider,
17
+ * } from "@digimuza/saas-core/email";
18
+ * import { config } from "@digimuza/saas-core/config";
19
+ *
20
+ * const templates = mergeEmailTemplates(
21
+ * coreEmailTemplates,
22
+ * defineEmailTemplates({
23
+ * "project.shared": emailTemplate({
24
+ * schema: z.object({ projectName: z.string() }),
25
+ * subject: (data) => `${data.projectName} was shared with you`,
26
+ * text: (data) => `Someone shared ${data.projectName}.`,
27
+ * }),
28
+ * }),
29
+ * );
30
+ *
31
+ * export const email = createEmailService({
32
+ * provider: createResendProvider({ apiKey: config.email.apiKey }),
33
+ * templates,
34
+ * from: { address: config.email.fromAddress, name: config.email.fromName },
35
+ * });
36
+ *
37
+ * await email.sendTemplate({
38
+ * to: "new@example.com",
39
+ * template: "project.shared", // autocompleted
40
+ * data: { projectName: "Apollo" }, // narrowed to that template's schema
41
+ * idempotencyKey: requestId,
42
+ * });
43
+ * ```
44
+ *
45
+ * Sending is **not** transactional with the database. A retried request can send
46
+ * twice, and `idempotencyKey` is the only defence — pass one for anything a
47
+ * customer would notice receiving twice.
48
+ */
49
+ import { config } from "../config/index.js";
50
+ import { createConsoleEmailProvider } from "./adapters.js";
51
+ import { createResendProvider } from "./resend.js";
52
+ export { createConsoleEmailProvider, createMemoryEmailProvider, } from "./adapters.js";
53
+ export { formatAddress, } from "./provider.js";
54
+ export { createResendProvider } from "./resend.js";
55
+ export { createEmailService, } from "./service.js";
56
+ export { coreEmailTemplates, defineEmailTemplates, emailTemplate, mergeEmailTemplates, overrideEmailTemplates, } from "./templates.js";
57
+ /**
58
+ * A provider built from the `email` configuration section.
59
+ *
60
+ * Resend outside development, the console logger inside it — so a fresh checkout
61
+ * can send an invitation without credentials, while production refuses to
62
+ * silently discard one.
63
+ */
64
+ export function createConfiguredEmailProvider() {
65
+ const emailConfig = config.email;
66
+ if (!config.app.isProduction && emailConfig.apiKey.startsWith("console")) {
67
+ return createConsoleEmailProvider({ isProduction: false });
68
+ }
69
+ return createResendProvider({ apiKey: emailConfig.apiKey });
70
+ }
71
+ /** The configured default sender. */
72
+ export function configuredSender() {
73
+ const emailConfig = config.email;
74
+ return {
75
+ address: emailConfig.fromAddress,
76
+ ...(emailConfig.fromName !== undefined ? { name: emailConfig.fromName } : {}),
77
+ };
78
+ }
79
+ //# sourceMappingURL=index.js.map