@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,126 @@
1
+ import type { CoreDatabase } from "../db/types.ts";
2
+ import { type CoreEventPublisher } from "../events/publisher.ts";
3
+ import type { Role, Workspace, WorkspaceInvitation } from "../db/schema/index.ts";
4
+ import { type WorkspaceContext } from "./context.ts";
5
+ /** Roles created with every new workspace, so a workspace is never role-less. */
6
+ export interface SystemRoleDefinition {
7
+ readonly key: string;
8
+ readonly name: string;
9
+ readonly description?: string;
10
+ /** Granted to new members when an invitation names no role. */
11
+ readonly isDefault?: boolean;
12
+ /** Permission keys to grant. Must already exist in `permissions`. */
13
+ readonly permissions?: readonly string[];
14
+ }
15
+ /**
16
+ * Default role set for a new workspace.
17
+ *
18
+ * `admin` receives permissions explicitly registered by the application, so the
19
+ * core does not invent a permission vocabulary. See
20
+ * `authorization.registerPermissions()`.
21
+ */
22
+ export declare const DEFAULT_SYSTEM_ROLES: readonly SystemRoleDefinition[];
23
+ export interface WorkspaceMemberSummary {
24
+ readonly userId: string;
25
+ readonly email: string | null;
26
+ readonly displayName: string | null;
27
+ readonly avatarUrl: string | null;
28
+ readonly joinedAt: Date;
29
+ readonly roles: readonly Pick<Role, "id" | "key" | "name">[];
30
+ }
31
+ export interface CreateWorkspaceInput {
32
+ readonly name: string;
33
+ /** URL identifier. Derived from `name` when omitted. */
34
+ readonly slug?: string;
35
+ /** The creating user. Becomes the first member, with the `admin` role. */
36
+ readonly ownerUserId: string;
37
+ /** Overrides {@link DEFAULT_SYSTEM_ROLES}. */
38
+ readonly systemRoles?: readonly SystemRoleDefinition[];
39
+ }
40
+ export interface InviteMemberInput {
41
+ readonly email: string;
42
+ /** Role granted on acceptance. Falls back to the workspace default role. */
43
+ readonly roleId?: string;
44
+ readonly expiresInSeconds?: number;
45
+ }
46
+ export interface InvitationWithToken {
47
+ readonly invitation: WorkspaceInvitation;
48
+ /**
49
+ * The single-use token, to be emailed to the invitee.
50
+ *
51
+ * Only the hash is stored, so this is the one and only time the token is
52
+ * available. Losing it means revoking the invitation and issuing a new one.
53
+ */
54
+ readonly token: string;
55
+ }
56
+ export interface AcceptInvitationInput {
57
+ readonly token: string;
58
+ /** The authenticated user accepting. Never taken from the invitation payload. */
59
+ readonly userId: string;
60
+ }
61
+ export declare function slugify(value: string): string;
62
+ export interface WorkspacesService {
63
+ create(input: CreateWorkspaceInput): Promise<Workspace>;
64
+ /** Look up a workspace the caller is a member of. */
65
+ get(context: WorkspaceContext): Promise<Workspace>;
66
+ update(context: WorkspaceContext, patch: {
67
+ name?: string;
68
+ slug?: string;
69
+ }): Promise<Workspace>;
70
+ delete(context: WorkspaceContext): Promise<void>;
71
+ /** Every workspace the user belongs to. */
72
+ listForUser(userId: string): Promise<Workspace[]>;
73
+ /**
74
+ * Verify that `userId` is a member of `workspaceId` and return a context.
75
+ *
76
+ * This is the only sanctioned way to turn an untrusted workspace identifier
77
+ * into something the rest of the core will accept.
78
+ */
79
+ resolveContext(input: {
80
+ userId: string;
81
+ workspaceId: string;
82
+ }): Promise<WorkspaceContext | undefined>;
83
+ /**
84
+ * As {@link resolveContext}, but throws.
85
+ *
86
+ * Raises {@link NotFoundError} rather than a permission error: telling a
87
+ * non-member that a workspace exists would let them enumerate other tenants.
88
+ */
89
+ requireContext(input: {
90
+ userId: string;
91
+ workspaceId: string;
92
+ }): Promise<WorkspaceContext>;
93
+ /** Resolve by slug, still verifying membership. */
94
+ requireContextBySlug(input: {
95
+ userId: string;
96
+ slug: string;
97
+ }): Promise<WorkspaceContext>;
98
+ readonly members: {
99
+ list(context: WorkspaceContext): Promise<WorkspaceMemberSummary[]>;
100
+ /** Add an existing user directly, bypassing the invitation flow. */
101
+ add(context: WorkspaceContext, input: {
102
+ userId: string;
103
+ roleIds?: readonly string[];
104
+ }): Promise<void>;
105
+ remove(context: WorkspaceContext, userId: string): Promise<void>;
106
+ invite(context: WorkspaceContext, input: InviteMemberInput): Promise<InvitationWithToken>;
107
+ listInvitations(context: WorkspaceContext): Promise<WorkspaceInvitation[]>;
108
+ revokeInvitation(context: WorkspaceContext, invitationId: string): Promise<void>;
109
+ /** Redeem a token. Not workspace-scoped: the token identifies the workspace. */
110
+ acceptInvitation(input: AcceptInvitationInput): Promise<WorkspaceContext>;
111
+ };
112
+ }
113
+ export interface WorkspacesServiceDeps {
114
+ readonly db: CoreDatabase;
115
+ /**
116
+ * Optional event publisher.
117
+ *
118
+ * Omit it and the service behaves exactly as before, emitting nothing — so
119
+ * events are opt-in rather than a hidden dependency. When provided, each event
120
+ * is written in the same transaction as the state change it describes and
121
+ * dispatched only after that transaction commits.
122
+ */
123
+ readonly events?: CoreEventPublisher;
124
+ }
125
+ export declare function createWorkspacesService(deps: WorkspacesServiceDeps): WorkspacesService;
126
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/workspaces/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,495 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ import { and, eq, isNull, sql } from "drizzle-orm";
3
+ import { ConflictError, InvalidInputError, NotFoundError } from "../errors.js";
4
+ import { isUniqueViolation } from "../db/errors.js";
5
+ import { roles, userProfiles, users, workspaceInvitations, workspaceMemberRoles, workspaceMembers, workspaces, } from "../db/schema/index.js";
6
+ import { EventOutbox } from "../events/publisher.js";
7
+ import { unsafeWorkspaceContext } from "./context.js";
8
+ /**
9
+ * Default role set for a new workspace.
10
+ *
11
+ * `admin` receives permissions explicitly registered by the application, so the
12
+ * core does not invent a permission vocabulary. See
13
+ * `authorization.registerPermissions()`.
14
+ */
15
+ export const DEFAULT_SYSTEM_ROLES = [
16
+ { key: "admin", name: "Admin", description: "Full access to the workspace." },
17
+ { key: "member", name: "Member", description: "Standard access.", isDefault: true },
18
+ ];
19
+ /** 7 days. */
20
+ const DEFAULT_INVITATION_TTL_SECONDS = 60 * 60 * 24 * 7;
21
+ export function slugify(value) {
22
+ const slug = value
23
+ .normalize("NFKD")
24
+ .replace(/[̀-ͯ]/g, "")
25
+ .toLowerCase()
26
+ .replace(/[^a-z0-9]+/g, "-")
27
+ .replace(/^-+|-+$/g, "")
28
+ .slice(0, 60);
29
+ if (slug.length === 0) {
30
+ throw new InvalidInputError("Workspace name must contain at least one alphanumeric character.");
31
+ }
32
+ return slug;
33
+ }
34
+ /** Invitation tokens are compared by hash, so the digest must be deterministic. */
35
+ function hashToken(token) {
36
+ return createHash("sha256").update(token).digest("hex");
37
+ }
38
+ export function createWorkspacesService(deps) {
39
+ const outbox = () => new EventOutbox(deps.events);
40
+ async function findMembership(userId, workspaceId) {
41
+ const rows = await deps.db
42
+ .select({ userId: workspaceMembers.userId })
43
+ .from(workspaceMembers)
44
+ .where(and(eq(workspaceMembers.workspaceId, workspaceId), eq(workspaceMembers.userId, userId)))
45
+ .limit(1);
46
+ return rows.length > 0;
47
+ }
48
+ async function seedRoles(tx, workspaceId, definitions) {
49
+ return tx
50
+ .insert(roles)
51
+ .values(definitions.map((definition) => ({
52
+ workspaceId,
53
+ key: definition.key,
54
+ name: definition.name,
55
+ description: definition.description ?? null,
56
+ isSystem: true,
57
+ isDefault: definition.isDefault ?? false,
58
+ })))
59
+ .returning();
60
+ }
61
+ const members = {
62
+ async list(context) {
63
+ const rows = await deps.db
64
+ .select({
65
+ userId: workspaceMembers.userId,
66
+ joinedAt: workspaceMembers.createdAt,
67
+ email: userProfiles.email,
68
+ displayName: userProfiles.displayName,
69
+ avatarUrl: userProfiles.avatarUrl,
70
+ roleId: roles.id,
71
+ roleKey: roles.key,
72
+ roleName: roles.name,
73
+ })
74
+ .from(workspaceMembers)
75
+ .leftJoin(userProfiles, eq(userProfiles.userId, workspaceMembers.userId))
76
+ .leftJoin(workspaceMemberRoles, and(eq(workspaceMemberRoles.workspaceId, workspaceMembers.workspaceId), eq(workspaceMemberRoles.userId, workspaceMembers.userId)))
77
+ .leftJoin(roles, eq(roles.id, workspaceMemberRoles.roleId))
78
+ .where(eq(workspaceMembers.workspaceId, context.workspaceId));
79
+ // One row per member/role pair; fold roles into their member.
80
+ const byUser = new Map();
81
+ const collected = new Map();
82
+ for (const row of rows) {
83
+ if (!byUser.has(row.userId)) {
84
+ byUser.set(row.userId, {
85
+ userId: row.userId,
86
+ email: row.email,
87
+ displayName: row.displayName,
88
+ avatarUrl: row.avatarUrl,
89
+ joinedAt: row.joinedAt,
90
+ roles: [],
91
+ });
92
+ collected.set(row.userId, []);
93
+ }
94
+ if (row.roleId !== null && row.roleKey !== null && row.roleName !== null) {
95
+ collected.get(row.userId).push({ id: row.roleId, key: row.roleKey, name: row.roleName });
96
+ }
97
+ }
98
+ return [...byUser.values()].map((member) => ({
99
+ ...member,
100
+ roles: collected.get(member.userId) ?? [],
101
+ }));
102
+ },
103
+ async add(context, input) {
104
+ const events = outbox();
105
+ await deps.db.transaction(async (tx) => {
106
+ await tx
107
+ .insert(workspaceMembers)
108
+ .values({ workspaceId: context.workspaceId, userId: input.userId })
109
+ .onConflictDoNothing();
110
+ let roleIds;
111
+ if (input.roleIds !== undefined) {
112
+ roleIds = input.roleIds;
113
+ }
114
+ else {
115
+ const defaultRole = await tx
116
+ .select({ id: roles.id })
117
+ .from(roles)
118
+ .where(and(eq(roles.workspaceId, context.workspaceId), eq(roles.isDefault, true)))
119
+ .limit(1);
120
+ roleIds = defaultRole.map((row) => row.id);
121
+ }
122
+ if (roleIds.length > 0) {
123
+ await tx
124
+ .insert(workspaceMemberRoles)
125
+ .values(roleIds.map((roleId) => ({
126
+ workspaceId: context.workspaceId,
127
+ userId: input.userId,
128
+ roleId,
129
+ })))
130
+ .onConflictDoNothing();
131
+ }
132
+ await events.record({
133
+ type: "workspace.member.created",
134
+ workspaceId: context.workspaceId,
135
+ actorId: context.userId,
136
+ data: { userId: input.userId, roleIds: [...roleIds] },
137
+ }, tx);
138
+ });
139
+ await events.flush();
140
+ },
141
+ async remove(context, userId) {
142
+ /**
143
+ * Delete first, then check what is left, inside one transaction.
144
+ *
145
+ * Counting before deleting would be wrong twice over: it reports
146
+ * "last member" for a user who is not a member at all — leaking the
147
+ * workspace's member count to an outsider — and it races, since two
148
+ * concurrent removals could each see two members and both proceed.
149
+ * Throwing here rolls the delete back.
150
+ */
151
+ const events = outbox();
152
+ await deps.db.transaction(async (tx) => {
153
+ const deleted = await tx
154
+ .delete(workspaceMembers)
155
+ .where(and(eq(workspaceMembers.workspaceId, context.workspaceId), eq(workspaceMembers.userId, userId)))
156
+ .returning({ userId: workspaceMembers.userId });
157
+ // Scoped to the caller's workspace, so a member of another tenant
158
+ // matches nothing and is reported as not found.
159
+ if (deleted.length === 0) {
160
+ throw new NotFoundError("Workspace member not found.");
161
+ }
162
+ const remaining = await tx
163
+ .select({ count: sql `count(*)::int` })
164
+ .from(workspaceMembers)
165
+ .where(eq(workspaceMembers.workspaceId, context.workspaceId));
166
+ // An empty workspace is unreachable: nobody left to administer it.
167
+ if ((remaining[0]?.count ?? 0) === 0) {
168
+ throw new ConflictError("A workspace must keep at least one member.");
169
+ }
170
+ await events.record({
171
+ type: "workspace.member.removed",
172
+ workspaceId: context.workspaceId,
173
+ actorId: context.userId,
174
+ data: { userId },
175
+ }, tx);
176
+ });
177
+ await events.flush();
178
+ // Role grants cascade via workspace_member_roles_member_fk.
179
+ },
180
+ async invite(context, input) {
181
+ const email = input.email.trim().toLowerCase();
182
+ if (email.length === 0 || !email.includes("@")) {
183
+ throw new InvalidInputError("A valid email address is required.");
184
+ }
185
+ const token = randomBytes(32).toString("base64url");
186
+ const expiresAt = new Date(Date.now() + (input.expiresInSeconds ?? DEFAULT_INVITATION_TTL_SECONDS) * 1000);
187
+ const events = outbox();
188
+ try {
189
+ const invitation = await deps.db.transaction(async (tx) => {
190
+ const [created] = await tx
191
+ .insert(workspaceInvitations)
192
+ .values({
193
+ workspaceId: context.workspaceId,
194
+ email,
195
+ tokenHash: hashToken(token),
196
+ invitedByUserId: context.userId,
197
+ roleId: input.roleId ?? null,
198
+ expiresAt,
199
+ })
200
+ .returning();
201
+ await events.record({
202
+ type: "workspace.invitation.created",
203
+ workspaceId: context.workspaceId,
204
+ actorId: context.userId,
205
+ // The token is never included: events are durable and readable,
206
+ // and an invitation token is a bearer credential.
207
+ data: { invitationId: created.id, email, roleId: created.roleId },
208
+ }, tx);
209
+ return created;
210
+ });
211
+ await events.flush();
212
+ return { invitation, token };
213
+ }
214
+ catch (error) {
215
+ if (isUniqueViolation(error, "workspace_invitations_pending_idx")) {
216
+ throw new ConflictError("An invitation for this address is already outstanding.", {
217
+ cause: error,
218
+ });
219
+ }
220
+ throw error;
221
+ }
222
+ },
223
+ async listInvitations(context) {
224
+ return deps.db
225
+ .select()
226
+ .from(workspaceInvitations)
227
+ .where(and(eq(workspaceInvitations.workspaceId, context.workspaceId), isNull(workspaceInvitations.acceptedAt), isNull(workspaceInvitations.revokedAt)));
228
+ },
229
+ async revokeInvitation(context, invitationId) {
230
+ const events = outbox();
231
+ const revoked = await deps.db
232
+ .update(workspaceInvitations)
233
+ .set({ revokedAt: new Date(), updatedAt: new Date() })
234
+ .where(and(eq(workspaceInvitations.id, invitationId),
235
+ // Scoped to the caller's workspace, so an id from another tenant
236
+ // cannot be revoked.
237
+ eq(workspaceInvitations.workspaceId, context.workspaceId), isNull(workspaceInvitations.acceptedAt), isNull(workspaceInvitations.revokedAt)))
238
+ .returning({ id: workspaceInvitations.id });
239
+ if (revoked.length === 0) {
240
+ throw new NotFoundError("Outstanding invitation not found.");
241
+ }
242
+ await events.record({
243
+ type: "workspace.invitation.revoked",
244
+ workspaceId: context.workspaceId,
245
+ actorId: context.userId,
246
+ data: { invitationId },
247
+ }, deps.db);
248
+ await events.flush();
249
+ },
250
+ async acceptInvitation(input) {
251
+ const tokenHash = hashToken(input.token);
252
+ const events = outbox();
253
+ const accepted = await deps.db.transaction(async (tx) => {
254
+ const rows = await tx
255
+ .select()
256
+ .from(workspaceInvitations)
257
+ .where(eq(workspaceInvitations.tokenHash, tokenHash))
258
+ .limit(1);
259
+ const invitation = rows[0];
260
+ /**
261
+ * A single "invalid invitation" for missing, revoked, accepted and
262
+ * expired tokens: distinguishing them would tell a token-guessing
263
+ * attacker which guesses corresponded to real invitations.
264
+ */
265
+ if (invitation === undefined ||
266
+ invitation.acceptedAt !== null ||
267
+ invitation.revokedAt !== null ||
268
+ invitation.expiresAt.getTime() <= Date.now()) {
269
+ throw new NotFoundError("Invitation is invalid or has expired.");
270
+ }
271
+ /**
272
+ * Mark accepted with the same guard in the WHERE clause, so two
273
+ * concurrent redemptions cannot both succeed.
274
+ */
275
+ const claimed = await tx
276
+ .update(workspaceInvitations)
277
+ .set({ acceptedAt: new Date(), updatedAt: new Date() })
278
+ .where(and(eq(workspaceInvitations.id, invitation.id), isNull(workspaceInvitations.acceptedAt), isNull(workspaceInvitations.revokedAt)))
279
+ .returning({ id: workspaceInvitations.id });
280
+ if (claimed.length === 0) {
281
+ throw new NotFoundError("Invitation is invalid or has expired.");
282
+ }
283
+ await tx
284
+ .insert(workspaceMembers)
285
+ .values({ workspaceId: invitation.workspaceId, userId: input.userId })
286
+ .onConflictDoNothing();
287
+ const roleId = invitation.roleId ??
288
+ (await tx
289
+ .select({ id: roles.id })
290
+ .from(roles)
291
+ .where(and(eq(roles.workspaceId, invitation.workspaceId), eq(roles.isDefault, true)))
292
+ .limit(1))[0]?.id;
293
+ if (roleId !== undefined) {
294
+ await tx
295
+ .insert(workspaceMemberRoles)
296
+ .values({
297
+ workspaceId: invitation.workspaceId,
298
+ userId: input.userId,
299
+ roleId,
300
+ })
301
+ .onConflictDoNothing();
302
+ }
303
+ await events.record({
304
+ type: "workspace.invitation.accepted",
305
+ workspaceId: invitation.workspaceId,
306
+ actorId: input.userId,
307
+ data: { invitationId: invitation.id, userId: input.userId },
308
+ }, tx);
309
+ await events.record({
310
+ type: "workspace.member.created",
311
+ workspaceId: invitation.workspaceId,
312
+ actorId: input.userId,
313
+ data: { userId: input.userId, roleIds: roleId !== undefined ? [roleId] : [] },
314
+ }, tx);
315
+ return unsafeWorkspaceContext(input.userId, invitation.workspaceId);
316
+ });
317
+ await events.flush();
318
+ return accepted;
319
+ },
320
+ };
321
+ return {
322
+ async create(input) {
323
+ const slug = input.slug !== undefined ? slugify(input.slug) : slugify(input.name);
324
+ const definitions = input.systemRoles ?? DEFAULT_SYSTEM_ROLES;
325
+ const events = outbox();
326
+ try {
327
+ const workspace = await deps.db.transaction(async (tx) => {
328
+ const [workspace] = await tx
329
+ .insert(workspaces)
330
+ .values({ name: input.name, slug })
331
+ .returning();
332
+ const created = await seedRoles(tx, workspace.id, definitions);
333
+ await tx
334
+ .insert(workspaceMembers)
335
+ .values({ workspaceId: workspace.id, userId: input.ownerUserId });
336
+ /**
337
+ * The creator gets `admin` if it exists, otherwise the default role.
338
+ * Without this a new workspace would have no one able to administer it.
339
+ */
340
+ const ownerRole = created.find((role) => role.key === "admin") ??
341
+ created.find((role) => role.isDefault) ??
342
+ created[0];
343
+ if (ownerRole !== undefined) {
344
+ await tx.insert(workspaceMemberRoles).values({
345
+ workspaceId: workspace.id,
346
+ userId: input.ownerUserId,
347
+ roleId: ownerRole.id,
348
+ });
349
+ }
350
+ await events.record({
351
+ type: "workspace.created",
352
+ workspaceId: workspace.id,
353
+ actorId: input.ownerUserId,
354
+ data: { workspaceId: workspace.id, slug },
355
+ }, tx);
356
+ await events.record({
357
+ type: "workspace.member.created",
358
+ workspaceId: workspace.id,
359
+ actorId: input.ownerUserId,
360
+ data: {
361
+ userId: input.ownerUserId,
362
+ roleIds: ownerRole !== undefined ? [ownerRole.id] : [],
363
+ },
364
+ }, tx);
365
+ return workspace;
366
+ });
367
+ await events.flush();
368
+ return workspace;
369
+ }
370
+ catch (error) {
371
+ if (isUniqueViolation(error, "workspaces_slug_unique")) {
372
+ throw new ConflictError(`Workspace slug "${slug}" is already taken.`, { cause: error });
373
+ }
374
+ throw error;
375
+ }
376
+ },
377
+ async get(context) {
378
+ const rows = await deps.db
379
+ .select()
380
+ .from(workspaces)
381
+ .where(eq(workspaces.id, context.workspaceId))
382
+ .limit(1);
383
+ const workspace = rows[0];
384
+ if (workspace === undefined) {
385
+ throw new NotFoundError("Workspace not found.");
386
+ }
387
+ return workspace;
388
+ },
389
+ async update(context, patch) {
390
+ const next = { updatedAt: new Date() };
391
+ if (patch.name !== undefined) {
392
+ next.name = patch.name;
393
+ }
394
+ if (patch.slug !== undefined) {
395
+ next.slug = slugify(patch.slug);
396
+ }
397
+ const events = outbox();
398
+ try {
399
+ const workspace = await deps.db.transaction(async (tx) => {
400
+ const [updated] = await tx
401
+ .update(workspaces)
402
+ .set(next)
403
+ .where(eq(workspaces.id, context.workspaceId))
404
+ .returning();
405
+ if (updated === undefined) {
406
+ throw new NotFoundError("Workspace not found.");
407
+ }
408
+ const changed = ["name", "slug"].filter((field) => patch[field] !== undefined);
409
+ await events.record({
410
+ type: "workspace.updated",
411
+ workspaceId: context.workspaceId,
412
+ actorId: context.userId,
413
+ data: { workspaceId: context.workspaceId, changed },
414
+ }, tx);
415
+ return updated;
416
+ });
417
+ await events.flush();
418
+ return workspace;
419
+ }
420
+ catch (error) {
421
+ if (isUniqueViolation(error, "workspaces_slug_unique")) {
422
+ throw new ConflictError("Workspace slug is already taken.", { cause: error });
423
+ }
424
+ throw error;
425
+ }
426
+ },
427
+ async delete(context) {
428
+ /**
429
+ * The event is recorded before the delete in the same transaction, because
430
+ * `events.workspace_id` cascades — writing it afterwards would insert a row
431
+ * referencing a workspace that no longer exists.
432
+ */
433
+ const events = outbox();
434
+ await deps.db.transaction(async (tx) => {
435
+ const rows = await tx
436
+ .select({ slug: workspaces.slug })
437
+ .from(workspaces)
438
+ .where(eq(workspaces.id, context.workspaceId))
439
+ .limit(1);
440
+ const existing = rows[0];
441
+ if (existing === undefined) {
442
+ throw new NotFoundError("Workspace not found.");
443
+ }
444
+ await events.record({
445
+ type: "workspace.deleted",
446
+ // Deliberately not workspace-scoped: the cascade would remove it.
447
+ workspaceId: null,
448
+ actorId: context.userId,
449
+ data: { workspaceId: context.workspaceId, slug: existing.slug },
450
+ }, tx);
451
+ await tx.delete(workspaces).where(eq(workspaces.id, context.workspaceId));
452
+ });
453
+ await events.flush();
454
+ },
455
+ async listForUser(userId) {
456
+ return deps.db
457
+ .select({
458
+ id: workspaces.id,
459
+ name: workspaces.name,
460
+ slug: workspaces.slug,
461
+ createdAt: workspaces.createdAt,
462
+ updatedAt: workspaces.updatedAt,
463
+ })
464
+ .from(workspaces)
465
+ .innerJoin(workspaceMembers, eq(workspaceMembers.workspaceId, workspaces.id))
466
+ .where(eq(workspaceMembers.userId, userId));
467
+ },
468
+ async resolveContext({ userId, workspaceId }) {
469
+ const isMember = await findMembership(userId, workspaceId);
470
+ return isMember ? unsafeWorkspaceContext(userId, workspaceId) : undefined;
471
+ },
472
+ async requireContext({ userId, workspaceId }) {
473
+ const context = await this.resolveContext({ userId, workspaceId });
474
+ if (context === undefined) {
475
+ throw new NotFoundError("Workspace not found.");
476
+ }
477
+ return context;
478
+ },
479
+ async requireContextBySlug({ userId, slug }) {
480
+ const rows = await deps.db
481
+ .select({ workspaceId: workspaces.id })
482
+ .from(workspaces)
483
+ .innerJoin(workspaceMembers, and(eq(workspaceMembers.workspaceId, workspaces.id), eq(workspaceMembers.userId, userId)))
484
+ .where(eq(workspaces.slug, slug))
485
+ .limit(1);
486
+ const row = rows[0];
487
+ if (row === undefined) {
488
+ throw new NotFoundError("Workspace not found.");
489
+ }
490
+ return unsafeWorkspaceContext(userId, row.workspaceId);
491
+ },
492
+ members,
493
+ };
494
+ }
495
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/workspaces/service.ts"],"names":[],"mappings":"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"}