@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,178 @@
1
+ /**
2
+ * Redaction.
3
+ *
4
+ * The core handles API keys, session cookies, invitation tokens and webhook
5
+ * signing secrets. A logger that faithfully serialises whatever it is handed is
6
+ * the easiest way to move all of them into a log aggregator that a wider audience
7
+ * can read — so redaction is on by default, and errs toward over-redacting.
8
+ *
9
+ * Two independent passes, because either alone has a hole:
10
+ *
11
+ * - **By key.** `{ apiKey: "..." }` is redacted whatever the value looks like.
12
+ * - **By value.** A credential under an innocent key — `{ input: "dgk_..." }` —
13
+ * is caught by its shape.
14
+ */
15
+ export const REDACTED = "[redacted]";
16
+ /**
17
+ * Field names whose values are never logged.
18
+ *
19
+ * Matched as case-insensitive substrings of the key, so `workosCookiePassword`
20
+ * and `cookie_password` are both caught without enumerating spellings.
21
+ */
22
+ export const DEFAULT_REDACT_KEYS = [
23
+ "password",
24
+ "passwd",
25
+ "secret",
26
+ "token",
27
+ "apikey",
28
+ "api_key",
29
+ "authorization",
30
+ "cookie",
31
+ "credential",
32
+ "privatekey",
33
+ "private_key",
34
+ "signature",
35
+ "keyhash",
36
+ "key_hash",
37
+ "sessiondata",
38
+ "bearer",
39
+ "otp",
40
+ "mfa",
41
+ ];
42
+ /**
43
+ * Value shapes that are credentials wherever they appear.
44
+ *
45
+ * Deliberately anchored on the *prefixes this system and its providers issue*
46
+ * rather than on generic entropy heuristics: "looks random" would redact ids,
47
+ * hashes and slugs, and a log with every identifier removed is not useful.
48
+ */
49
+ const CREDENTIAL_PATTERNS = [
50
+ // This package's API keys: <prefix>_<32 hex>_<64 hex>.
51
+ /\b[a-z][a-z0-9]{1,15}_[0-9a-f]{32}_[0-9a-f]{64}\b/,
52
+ // Webhook signing secrets, ours and Revolut's.
53
+ /\bwhsec_[A-Za-z0-9_-]{20,}\b/,
54
+ /\bwsk_[A-Za-z0-9_-]{16,}\b/,
55
+ // Provider secret/publishable/restricted keys — Stripe, Resend, WorkOS shapes.
56
+ /\b(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{10,}\b/,
57
+ /\bre_[A-Za-z0-9_-]{16,}\b/,
58
+ // JSON Web Tokens, including the sealed session cookie.
59
+ /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/,
60
+ // An Authorization header value that arrived as a plain string.
61
+ /\bBearer\s+[A-Za-z0-9._~+/=-]{16,}/i,
62
+ ];
63
+ /** Bounds, so one pathological object cannot stall the process or fill a disk. */
64
+ const MAX_DEPTH = 6;
65
+ const MAX_ARRAY_ITEMS = 100;
66
+ const MAX_STRING_LENGTH = 8192;
67
+ export function createRedactor(options = {}) {
68
+ const keys = [
69
+ ...(options.keys ?? DEFAULT_REDACT_KEYS),
70
+ ...(options.additionalKeys ?? []),
71
+ ].map((key) => key.toLowerCase());
72
+ const scanValues = options.disableValueScanning !== true;
73
+ function isSensitiveKey(key) {
74
+ const lower = key.toLowerCase();
75
+ return keys.some((needle) => lower.includes(needle));
76
+ }
77
+ function redactString(value) {
78
+ if (scanValues && CREDENTIAL_PATTERNS.some((pattern) => pattern.test(value))) {
79
+ return REDACTED;
80
+ }
81
+ return value.length > MAX_STRING_LENGTH
82
+ ? `${value.slice(0, MAX_STRING_LENGTH)}…[truncated]`
83
+ : value;
84
+ }
85
+ function walk(value, depth, seen) {
86
+ if (value === null || value === undefined) {
87
+ return value;
88
+ }
89
+ if (typeof value === "string") {
90
+ return redactString(value);
91
+ }
92
+ if (typeof value === "number" || typeof value === "boolean") {
93
+ return value;
94
+ }
95
+ if (typeof value === "bigint") {
96
+ return value.toString();
97
+ }
98
+ // Never serialise a function; its source can embed a literal secret.
99
+ if (typeof value === "function") {
100
+ return "[function]";
101
+ }
102
+ if (typeof value === "symbol") {
103
+ return value.toString();
104
+ }
105
+ if (value instanceof Date) {
106
+ return value.toISOString();
107
+ }
108
+ if (value instanceof Error) {
109
+ return serializeError(value, depth, seen, walk);
110
+ }
111
+ if (depth >= MAX_DEPTH) {
112
+ return "[max depth]";
113
+ }
114
+ if (typeof value === "object") {
115
+ // A cyclic structure would otherwise recurse until the stack gives out.
116
+ if (seen.has(value)) {
117
+ return "[circular]";
118
+ }
119
+ seen.add(value);
120
+ if (Array.isArray(value)) {
121
+ const items = value.slice(0, MAX_ARRAY_ITEMS).map((item) => walk(item, depth + 1, seen));
122
+ return value.length > MAX_ARRAY_ITEMS
123
+ ? [...items, `[${value.length - MAX_ARRAY_ITEMS} more]`]
124
+ : items;
125
+ }
126
+ if (value instanceof Map) {
127
+ return walk(Object.fromEntries(value), depth, seen);
128
+ }
129
+ if (value instanceof Set) {
130
+ return walk([...value], depth, seen);
131
+ }
132
+ const result = {};
133
+ for (const [key, entry] of Object.entries(value)) {
134
+ result[key] = isSensitiveKey(key) ? REDACTED : walk(entry, depth + 1, seen);
135
+ }
136
+ return result;
137
+ }
138
+ return String(value);
139
+ }
140
+ return (value) => walk(value, 0, new WeakSet());
141
+ }
142
+ /** Error depth limit, so a long `cause` chain cannot blow the stack. */
143
+ const MAX_CAUSE_DEPTH = 4;
144
+ function serializeError(error, depth, seen, walk) {
145
+ const serialized = {
146
+ name: error.name,
147
+ /**
148
+ * The message is passed through value scanning. The core never puts a secret
149
+ * in one, but a caller's error might — and a message is the likeliest place
150
+ * for a token to end up by accident.
151
+ */
152
+ message: walk(error.message, depth + 1, seen),
153
+ };
154
+ if (typeof error.stack === "string") {
155
+ serialized.stack = error.stack.split("\n").slice(0, 20).join("\n");
156
+ }
157
+ /**
158
+ * `AggregateError.errors` and `cause` both carry the detail that makes a
159
+ * failure diagnosable — dropping them would leave "Invalid configuration" with
160
+ * no indication of which section.
161
+ */
162
+ if (error instanceof AggregateError && Array.isArray(error.errors)) {
163
+ serialized.errors = error.errors
164
+ .slice(0, MAX_ARRAY_ITEMS)
165
+ .map((inner) => walk(inner, depth + 1, seen));
166
+ }
167
+ const cause = error.cause;
168
+ if (cause !== undefined && depth < MAX_CAUSE_DEPTH) {
169
+ serialized.cause = walk(cause, depth + 1, seen);
170
+ }
171
+ // Domain errors carry a machine-readable code; keep it for filtering.
172
+ const code = error.code;
173
+ if (typeof code === "string" || typeof code === "number") {
174
+ serialized.code = code;
175
+ }
176
+ return serialized;
177
+ }
178
+ //# sourceMappingURL=redact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/logger/redact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type RedactOptions } from "./redact.ts";
2
+ import { type LogFields, type Logger, type LogLevel, type LogSink } from "./types.ts";
3
+ export interface CreateLoggerOptions {
4
+ /** Records below this are dropped before any serialisation. Default `"info"`. */
5
+ readonly level?: LogLevel;
6
+ readonly sink?: LogSink;
7
+ /** Context bound to every record. */
8
+ readonly base?: LogFields;
9
+ readonly redact?: RedactOptions;
10
+ /** Injectable clock, for deterministic tests. */
11
+ readonly now?: () => Date;
12
+ }
13
+ export declare function createLogger(options?: CreateLoggerOptions): Logger;
14
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/logger/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,aAAa,EAAiB,MAAM,aAAa,CAAC;AAEhF,OAAO,EAAkB,KAAK,SAAS,EAAE,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAEtG,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,qCAAqC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,iDAAiD;IACjD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,MAAM,CAMtE"}
@@ -0,0 +1,56 @@
1
+ import { createRedactor } from "./redact.js";
2
+ import { createJsonSink } from "./sinks.js";
3
+ import { LOG_LEVEL_RANK } from "./types.js";
4
+ export function createLogger(options = {}) {
5
+ const sink = options.sink ?? createJsonSink();
6
+ const redactor = createRedactor(options.redact ?? {});
7
+ const now = options.now ?? (() => new Date());
8
+ return build(options.level ?? "info", options.base ?? {}, sink, redactor, now);
9
+ }
10
+ function build(level, base, sink, redact, now) {
11
+ const threshold = LOG_LEVEL_RANK[level];
12
+ function isEnabled(candidate) {
13
+ return LOG_LEVEL_RANK[candidate] >= threshold;
14
+ }
15
+ function emit(candidate, message, fields) {
16
+ /**
17
+ * The level check happens *before* anything is merged or redacted. A `debug`
18
+ * call on an `info` logger must cost nothing beyond a comparison — otherwise
19
+ * debug logging becomes something you strip out for performance, which
20
+ * defeats the point of having levels.
21
+ */
22
+ if (!isEnabled(candidate)) {
23
+ return;
24
+ }
25
+ const merged = fields === undefined ? base : { ...base, ...fields };
26
+ /**
27
+ * A failure here must not propagate. Logging is diagnostic: a broken sink or
28
+ * an unserialisable field is never a reason for the operation being logged to
29
+ * fail.
30
+ */
31
+ try {
32
+ sink.write({
33
+ level: candidate,
34
+ time: now().toISOString(),
35
+ message,
36
+ fields: redact(merged),
37
+ });
38
+ }
39
+ catch {
40
+ // Deliberately silent. There is nowhere left to report it.
41
+ }
42
+ }
43
+ return {
44
+ level,
45
+ isEnabled,
46
+ debug: (message, fields) => emit("debug", message, fields),
47
+ info: (message, fields) => emit("info", message, fields),
48
+ warn: (message, fields) => emit("warn", message, fields),
49
+ error: (message, fields) => emit("error", message, fields),
50
+ child(fields) {
51
+ // Shares the sink and redactor; only the bound context differs.
52
+ return build(level, { ...base, ...fields }, sink, redact, now);
53
+ },
54
+ };
55
+ }
56
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/logger/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAqC,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,cAAc,EAA4D,MAAM,YAAY,CAAC;AAatG,MAAM,UAAU,YAAY,CAAC,OAAO,GAAwB,EAAE;IAC5D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,cAAc,EAAE,CAAC;IAC9C,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAE9C,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI,MAAM,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,KAAK,CACZ,KAAe,EACf,IAAe,EACf,IAAa,EACb,MAAgB,EAChB,GAAe;IAEf,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAExC,SAAS,SAAS,CAAC,SAAmB;QACpC,OAAO,cAAc,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC;IAChD,CAAC;IAED,SAAS,IAAI,CAAC,SAAmB,EAAE,OAAe,EAAE,MAAkB;QACpE;;;;;WAKG;QACH,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC;QAEpE;;;;WAIG;QACH,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC;gBACT,KAAK,EAAE,SAAS;gBAChB,IAAI,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE;gBACzB,OAAO;gBACP,MAAM,EAAE,MAAM,CAAC,MAAM,CAA4B;aAClD,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,2DAA2D;QAC7D,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK;QACL,SAAS;QACT,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC;QAC1D,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC;QACxD,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC;QACxD,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC;QAE1D,KAAK,CAAC,MAAM;YACV,gEAAgE;YAChE,OAAO,KAAK,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QACjE,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { LogRecord, LogSink } from "./types.ts";
2
+ export interface StreamSinkOptions {
3
+ /** Defaults to `process.stdout.write`. */
4
+ readonly write?: (line: string) => void;
5
+ }
6
+ /**
7
+ * One JSON object per line.
8
+ *
9
+ * The production default. Every log collector parses it, and a structured record
10
+ * survives the trip to an aggregator with its fields intact — which is the only
11
+ * reason to have bound context at all.
12
+ *
13
+ * Everything goes to **stdout**, including errors. Many collectors treat anything
14
+ * on stderr as an error regardless of the record's own level, which would
15
+ * double-count warnings and mislabel info.
16
+ */
17
+ export declare function createJsonSink(options?: StreamSinkOptions): LogSink;
18
+ /**
19
+ * Human-readable, for a terminal.
20
+ *
21
+ * Development only. It is lossy by design — fields are flattened for scanning
22
+ * rather than preserved for querying.
23
+ */
24
+ export declare function createPrettySink(options?: StreamSinkOptions): LogSink;
25
+ /** Collects records. For tests. */
26
+ export interface MemorySink extends LogSink {
27
+ readonly records: LogRecord[];
28
+ /** Records at one level. */
29
+ at(level: LogRecord["level"]): LogRecord[];
30
+ clear(): void;
31
+ }
32
+ export declare function createMemorySink(): MemorySink;
33
+ /** Discards everything. For tests that assert on something else. */
34
+ export declare function createNoopSink(): LogSink;
35
+ /** Writes to several sinks. Useful for stdout plus an aggregator. */
36
+ export declare function createMultiSink(sinks: readonly LogSink[]): LogSink;
37
+ //# sourceMappingURL=sinks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sinks.d.ts","sourceRoot":"","sources":["../../src/logger/sinks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAwBvE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAkCzE;AAED,mCAAmC;AACnC,MAAM,WAAW,UAAW,SAAQ,OAAO;IACzC,QAAQ,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC;IAC9B,4BAA4B;IAC5B,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,SAAS,EAAE,CAAC;IAC3C,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,gBAAgB,IAAI,UAAU,CAgB7C;AAED,oEAAoE;AACpE,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAiBlE"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * One JSON object per line.
3
+ *
4
+ * The production default. Every log collector parses it, and a structured record
5
+ * survives the trip to an aggregator with its fields intact — which is the only
6
+ * reason to have bound context at all.
7
+ *
8
+ * Everything goes to **stdout**, including errors. Many collectors treat anything
9
+ * on stderr as an error regardless of the record's own level, which would
10
+ * double-count warnings and mislabel info.
11
+ */
12
+ export function createJsonSink(options = {}) {
13
+ const write = options.write ??
14
+ ((line) => {
15
+ process.stdout.write(line);
16
+ });
17
+ return {
18
+ name: "json",
19
+ write(record) {
20
+ /**
21
+ * Fields are spread *under* the reserved keys, so a caller cannot shadow
22
+ * `level` or `time` and make a record lie about itself.
23
+ */
24
+ const line = safeStringify({
25
+ ...record.fields,
26
+ level: record.level,
27
+ time: record.time,
28
+ message: record.message,
29
+ });
30
+ write(`${line}\n`);
31
+ },
32
+ };
33
+ }
34
+ /**
35
+ * Human-readable, for a terminal.
36
+ *
37
+ * Development only. It is lossy by design — fields are flattened for scanning
38
+ * rather than preserved for querying.
39
+ */
40
+ export function createPrettySink(options = {}) {
41
+ const write = options.write ??
42
+ ((line) => {
43
+ process.stdout.write(line);
44
+ });
45
+ const label = {
46
+ debug: "DEBUG",
47
+ info: " INFO",
48
+ warn: " WARN",
49
+ error: "ERROR",
50
+ };
51
+ return {
52
+ name: "pretty",
53
+ write(record) {
54
+ const time = record.time.slice(11, 23);
55
+ const entries = Object.entries(record.fields).filter(([key]) => key !== "error");
56
+ const suffix = entries.length === 0
57
+ ? ""
58
+ : ` ${entries.map(([key, value]) => `${key}=${format(value)}`).join(" ")}`;
59
+ write(`${time} ${label[record.level] ?? record.level} ${record.message}${suffix}\n`);
60
+ // The error goes on its own lines; a stack is unreadable inline.
61
+ const error = record.fields.error;
62
+ if (error !== undefined) {
63
+ write(`${indent(safeStringify(error, 2))}\n`);
64
+ }
65
+ },
66
+ };
67
+ }
68
+ export function createMemorySink() {
69
+ const records = [];
70
+ return {
71
+ name: "memory",
72
+ records,
73
+ write(record) {
74
+ records.push(record);
75
+ },
76
+ at(level) {
77
+ return records.filter((record) => record.level === level);
78
+ },
79
+ clear() {
80
+ records.length = 0;
81
+ },
82
+ };
83
+ }
84
+ /** Discards everything. For tests that assert on something else. */
85
+ export function createNoopSink() {
86
+ return { name: "noop", write: () => undefined };
87
+ }
88
+ /** Writes to several sinks. Useful for stdout plus an aggregator. */
89
+ export function createMultiSink(sinks) {
90
+ return {
91
+ name: `multi(${sinks.map((sink) => sink.name).join(",")})`,
92
+ write(record) {
93
+ for (const sink of sinks) {
94
+ /**
95
+ * A sink that throws must not take the others down with it, or lose the
96
+ * record. Logging is never the reason a request fails.
97
+ */
98
+ try {
99
+ sink.write(record);
100
+ }
101
+ catch {
102
+ // Nowhere left to report it; the remaining sinks still get the record.
103
+ }
104
+ }
105
+ },
106
+ };
107
+ }
108
+ function format(value) {
109
+ return typeof value === "string" ? value : safeStringify(value);
110
+ }
111
+ function indent(text) {
112
+ return text
113
+ .split("\n")
114
+ .map((line) => ` ${line}`)
115
+ .join("\n");
116
+ }
117
+ /**
118
+ * `JSON.stringify` that cannot throw.
119
+ *
120
+ * The redactor already removes cycles and BigInts, but a sink is the last thing
121
+ * between a record and the operator reading it — a throw here would lose the
122
+ * line entirely, which is worse than losing its shape.
123
+ */
124
+ function safeStringify(value, space) {
125
+ try {
126
+ return JSON.stringify(value, undefined, space) ?? "undefined";
127
+ }
128
+ catch (error) {
129
+ return JSON.stringify({
130
+ message: "[unserializable log record]",
131
+ reason: error instanceof Error ? error.message : "unknown",
132
+ });
133
+ }
134
+ }
135
+ //# sourceMappingURL=sinks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sinks.js","sourceRoot":"","sources":["../../src/logger/sinks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /** Ordered from most to least verbose. */
2
+ export type LogLevel = "debug" | "info" | "warn" | "error";
3
+ /** Numeric ranks, so a level check is a comparison rather than a lookup. */
4
+ export declare const LOG_LEVEL_RANK: Readonly<Record<LogLevel, number>>;
5
+ export interface LogFields {
6
+ readonly [key: string]: unknown;
7
+ }
8
+ /** What a sink receives. Already levelled, timestamped and redacted. */
9
+ export interface LogRecord {
10
+ readonly level: LogLevel;
11
+ readonly time: string;
12
+ readonly message: string;
13
+ /** Merged bound context and per-call fields, after redaction. */
14
+ readonly fields: Readonly<Record<string, unknown>>;
15
+ }
16
+ /**
17
+ * Where records go.
18
+ *
19
+ * One method, because that is the whole job. Sampling, buffering and shipping
20
+ * belong to whatever you plug in here — wrapping them would mean maintaining a
21
+ * lowest common denominator of every logging backend.
22
+ */
23
+ export interface LogSink {
24
+ readonly name: string;
25
+ write(record: LogRecord): void;
26
+ }
27
+ export interface Logger {
28
+ readonly level: LogLevel;
29
+ debug(message: string, fields?: LogFields): void;
30
+ info(message: string, fields?: LogFields): void;
31
+ warn(message: string, fields?: LogFields): void;
32
+ /** `error` accepts a throwable, serialised with its `cause` chain. */
33
+ error(message: string, fields?: LogFields & {
34
+ readonly error?: unknown;
35
+ }): void;
36
+ /**
37
+ * A logger with extra context bound to every record it writes.
38
+ *
39
+ * The point of the whole module: bind `requestId`, `workspaceId` and `userId`
40
+ * once at the edge and every line beneath it is attributable, without threading
41
+ * them through call signatures.
42
+ */
43
+ child(fields: LogFields): Logger;
44
+ /** Whether a level would be emitted. Guard expensive field construction. */
45
+ isEnabled(level: LogLevel): boolean;
46
+ }
47
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/logger/types.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D,4EAA4E;AAC5E,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAK7D,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,wEAAwE;AACxE,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACpD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IAEzB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAChD,sEAAsE;IACtE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAEhF;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;IAEjC,4EAA4E;IAC5E,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC;CACrC"}
@@ -0,0 +1,8 @@
1
+ /** Numeric ranks, so a level check is a comparison rather than a lookup. */
2
+ export const LOG_LEVEL_RANK = {
3
+ debug: 10,
4
+ info: 20,
5
+ warn: 30,
6
+ error: 40,
7
+ };
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/logger/types.ts"],"names":[],"mappings":"AAGA,4EAA4E;AAC5E,MAAM,CAAC,MAAM,cAAc,GAAuC;IAChE,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;CACV,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { type NotificationsService } from "./service.ts";
2
+ export { createNotificationsService, type CreateNotificationInput, type ListNotificationsOptions, type NotificationsService, type NotificationsServiceDeps, } from "./service.ts";
3
+ /**
4
+ * Default service, bound to the database and to membership verification — so a
5
+ * notification cannot be addressed to someone outside the workspace it names.
6
+ */
7
+ export declare const notifications: NotificationsService;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/notifications/index.ts"],"names":[],"mappings":"AA2DA,OAAO,EAA8B,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAErF,OAAO,EACL,0BAA0B,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,GAC9B,MAAM,cAAc,CAAC;AAEtB;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,oBAK1B,CAAC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Public notifications surface: `@digimuza/saas-core/notifications`. Server-only.
3
+ *
4
+ * In-app notifications, addressed to a person. `workspace_id` only records which
5
+ * tenant a notification concerns — the row belongs to its recipient, and every
6
+ * read filters on `user_id`, so one user's notifications can never surface in
7
+ * another's list.
8
+ *
9
+ * ```ts
10
+ * import { notifications } from "@digimuza/saas-core/notifications";
11
+ *
12
+ * await notifications.create({
13
+ * userId: member.id,
14
+ * workspaceId: context.workspaceId,
15
+ * type: "project.shared",
16
+ * title: "Apollo was shared with you",
17
+ * url: `/w/${slug}/projects/${projectId}`,
18
+ * dedupeKey: `project.shared:${projectId}:${member.id}`,
19
+ * });
20
+ *
21
+ * // The bell icon.
22
+ * const unread = await notifications.countUnread(user.id);
23
+ * const inbox = await notifications.list(user.id, { unreadOnly: true });
24
+ * ```
25
+ *
26
+ * ## Email notifications
27
+ *
28
+ * Deliberately not automatic. Which notifications also warrant an email is a
29
+ * product decision — and per-user preferences, digests and quiet hours are
30
+ * product features, not core ones. Compose the two explicitly:
31
+ *
32
+ * ```ts
33
+ * const notification = await notifications.create({ ... });
34
+ * if (await wantsEmail(member.id, notification.type)) {
35
+ * await email.sendTemplate({ to: profile.email, template: "...", data: { ... } });
36
+ * }
37
+ * ```
38
+ *
39
+ * ## Consuming events
40
+ *
41
+ * ```ts
42
+ * events.on("workspace.member.created", async (event) => {
43
+ * await notifications.create({
44
+ * userId: event.data.userId,
45
+ * workspaceId: event.workspaceId,
46
+ * type: "workspace.joined",
47
+ * title: "Welcome to the workspace",
48
+ * // Handlers can run twice; the key makes that harmless.
49
+ * dedupeKey: event.id,
50
+ * });
51
+ * });
52
+ * ```
53
+ *
54
+ * Note that a handler is **not durable** — a crash between the commit and the
55
+ * handler loses the notification. For anything that must not be missed, create it
56
+ * in the same transaction as the change, or from a Trigger.dev task.
57
+ */
58
+ import { getDatabase } from "../db/client.js";
59
+ import { workspaces } from "../workspaces/index.js";
60
+ import { createNotificationsService } from "./service.js";
61
+ export { createNotificationsService, } from "./service.js";
62
+ /**
63
+ * Default service, bound to the database and to membership verification — so a
64
+ * notification cannot be addressed to someone outside the workspace it names.
65
+ */
66
+ export const notifications = createNotificationsService({
67
+ get db() {
68
+ return getDatabase();
69
+ },
70
+ workspaces,
71
+ });
72
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/notifications/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,0BAA0B,EAA6B,MAAM,cAAc,CAAC;AAErF,OAAO,EACL,0BAA0B,GAK3B,MAAM,cAAc,CAAC;AAEtB;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAyB,0BAA0B,CAAC;IAC5E,IAAI,EAAE;QACJ,OAAO,WAAW,EAAE,CAAC;IACvB,CAAC;IACD,UAAU;CACX,CAAC,CAAC"}