@m5kdev/backend 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/dist/src/lib/posthog.d.ts +0 -1
  2. package/dist/src/lib/sentry.d.ts +0 -1
  3. package/dist/src/modules/access/access.repository.d.ts +0 -1
  4. package/dist/src/modules/access/access.service.d.ts +0 -1
  5. package/dist/src/modules/access/access.test.d.ts +0 -1
  6. package/dist/src/modules/access/access.utils.d.ts +0 -1
  7. package/dist/src/modules/ai/ai.db.d.ts +0 -1
  8. package/dist/src/modules/ai/ai.prompt.d.ts +0 -1
  9. package/dist/src/modules/ai/ai.repository.d.ts +0 -1
  10. package/dist/src/modules/ai/ai.router.d.ts +0 -1
  11. package/dist/src/modules/ai/ai.service.d.ts +0 -1
  12. package/dist/src/modules/ai/ai.trpc.d.ts +5 -42
  13. package/dist/src/modules/ai/ai.trpc.js +5 -5
  14. package/dist/src/modules/ai/ideogram/ideogram.constants.d.ts +0 -1
  15. package/dist/src/modules/ai/ideogram/ideogram.dto.d.ts +0 -1
  16. package/dist/src/modules/ai/ideogram/ideogram.prompt.d.ts +0 -1
  17. package/dist/src/modules/ai/ideogram/ideogram.repository.d.ts +0 -1
  18. package/dist/src/modules/ai/ideogram/ideogram.service.d.ts +0 -1
  19. package/dist/src/modules/auth/auth.db.d.ts +0 -1
  20. package/dist/src/modules/auth/auth.dto.d.ts +7 -8
  21. package/dist/src/modules/auth/auth.lib.d.ts +8 -9
  22. package/dist/src/modules/auth/auth.middleware.d.ts +0 -1
  23. package/dist/src/modules/auth/auth.repository.d.ts +0 -1
  24. package/dist/src/modules/auth/auth.service.d.ts +0 -1
  25. package/dist/src/modules/auth/auth.trpc.d.ts +52 -89
  26. package/dist/src/modules/auth/auth.trpc.js +55 -53
  27. package/dist/src/modules/auth/auth.utils.d.ts +0 -1
  28. package/dist/src/modules/base/base.abstract.d.ts +0 -1
  29. package/dist/src/modules/base/base.dto.d.ts +2 -3
  30. package/dist/src/modules/base/base.grants.d.ts +0 -1
  31. package/dist/src/modules/base/base.grants.test.d.ts +0 -1
  32. package/dist/src/modules/base/base.repository.d.ts +0 -1
  33. package/dist/src/modules/base/base.service.d.ts +2 -4
  34. package/dist/src/modules/base/base.types.d.ts +0 -1
  35. package/dist/src/modules/billing/billing.db.d.ts +0 -1
  36. package/dist/src/modules/billing/billing.repository.d.ts +0 -1
  37. package/dist/src/modules/billing/billing.router.d.ts +0 -1
  38. package/dist/src/modules/billing/billing.service.d.ts +0 -1
  39. package/dist/src/modules/billing/billing.trpc.d.ts +6 -43
  40. package/dist/src/modules/billing/billing.trpc.js +7 -7
  41. package/dist/src/modules/clay/clay.repository.d.ts +0 -1
  42. package/dist/src/modules/clay/clay.service.d.ts +0 -1
  43. package/dist/src/modules/connect/connect.db.d.ts +0 -1
  44. package/dist/src/modules/connect/connect.dto.d.ts +8 -9
  45. package/dist/src/modules/connect/connect.linkedin.d.ts +0 -1
  46. package/dist/src/modules/connect/connect.oauth.d.ts +0 -1
  47. package/dist/src/modules/connect/connect.repository.d.ts +3 -4
  48. package/dist/src/modules/connect/connect.router.d.ts +0 -1
  49. package/dist/src/modules/connect/connect.service.d.ts +6 -7
  50. package/dist/src/modules/connect/connect.trpc.d.ts +9 -46
  51. package/dist/src/modules/connect/connect.trpc.js +7 -7
  52. package/dist/src/modules/connect/connect.types.d.ts +0 -1
  53. package/dist/src/modules/crypto/crypto.db.d.ts +0 -1
  54. package/dist/src/modules/crypto/crypto.repository.d.ts +0 -1
  55. package/dist/src/modules/crypto/crypto.service.d.ts +0 -1
  56. package/dist/src/modules/email/email.service.d.ts +0 -1
  57. package/dist/src/modules/file/file.repository.d.ts +0 -1
  58. package/dist/src/modules/file/file.router.d.ts +0 -1
  59. package/dist/src/modules/file/file.service.d.ts +0 -1
  60. package/dist/src/modules/recurrence/recurrence.db.d.ts +0 -1
  61. package/dist/src/modules/recurrence/recurrence.repository.d.ts +0 -1
  62. package/dist/src/modules/recurrence/recurrence.service.d.ts +0 -1
  63. package/dist/src/modules/recurrence/recurrence.trpc.d.ts +11 -48
  64. package/dist/src/modules/recurrence/recurrence.trpc.js +17 -17
  65. package/dist/src/modules/social/social.dto.d.ts +0 -1
  66. package/dist/src/modules/social/social.linkedin.d.ts +0 -1
  67. package/dist/src/modules/social/social.linkedin.test.d.ts +0 -1
  68. package/dist/src/modules/social/social.service.d.ts +0 -1
  69. package/dist/src/modules/social/social.types.d.ts +0 -1
  70. package/dist/src/modules/tag/tag.db.d.ts +0 -1
  71. package/dist/src/modules/tag/tag.dto.d.ts +0 -1
  72. package/dist/src/modules/tag/tag.repository.d.ts +0 -1
  73. package/dist/src/modules/tag/tag.service.d.ts +0 -1
  74. package/dist/src/modules/tag/tag.trpc.d.ts +10 -47
  75. package/dist/src/modules/tag/tag.trpc.js +15 -15
  76. package/dist/src/modules/utils/applyPagination.d.ts +0 -1
  77. package/dist/src/modules/utils/applySorting.d.ts +0 -1
  78. package/dist/src/modules/utils/getConditionsFromFilters.d.ts +0 -1
  79. package/dist/src/modules/video/video.service.d.ts +0 -1
  80. package/dist/src/modules/webhook/webhook.constants.d.ts +0 -1
  81. package/dist/src/modules/webhook/webhook.db.d.ts +0 -1
  82. package/dist/src/modules/webhook/webhook.dto.d.ts +0 -1
  83. package/dist/src/modules/webhook/webhook.repository.d.ts +0 -1
  84. package/dist/src/modules/webhook/webhook.router.d.ts +0 -1
  85. package/dist/src/modules/webhook/webhook.service.d.ts +0 -1
  86. package/dist/src/modules/workflow/workflow.db.d.ts +0 -1
  87. package/dist/src/modules/workflow/workflow.repository.d.ts +0 -1
  88. package/dist/src/modules/workflow/workflow.service.d.ts +0 -1
  89. package/dist/src/modules/workflow/workflow.trpc.d.ts +6 -43
  90. package/dist/src/modules/workflow/workflow.trpc.js +7 -7
  91. package/dist/src/modules/workflow/workflow.types.d.ts +0 -1
  92. package/dist/src/modules/workflow/workflow.utils.d.ts +0 -1
  93. package/dist/src/test/stubs/utils.d.ts +0 -1
  94. package/dist/src/trpc/context.d.ts +4 -5
  95. package/dist/src/trpc/index.d.ts +0 -1
  96. package/dist/src/trpc/procedures.d.ts +24 -25
  97. package/dist/src/trpc/utils.d.ts +0 -1
  98. package/dist/src/types.d.ts +61 -209
  99. package/dist/src/types.js +4 -5
  100. package/dist/src/utils/errors.d.ts +0 -1
  101. package/dist/src/utils/logger.d.ts +0 -1
  102. package/dist/src/utils/posthog.d.ts +0 -1
  103. package/dist/src/utils/trpc.d.ts +58 -0
  104. package/dist/src/utils/trpc.js +63 -0
  105. package/dist/src/utils/types.d.ts +0 -1
  106. package/dist/tsconfig.tsbuildinfo +1 -1
  107. package/package.json +6 -8
  108. package/.cursor/rules/backend.mdc +0 -70
  109. package/.turbo/turbo-build.log +0 -5
  110. package/.turbo/turbo-check-types.log +0 -5
  111. package/.turbo/turbo-lint$colon$fix.log +0 -255
  112. package/CHANGELOG.md +0 -37
  113. package/dist/src/lib/posthog.d.ts.map +0 -1
  114. package/dist/src/lib/sentry.d.ts.map +0 -1
  115. package/dist/src/modules/access/access.repository.d.ts.map +0 -1
  116. package/dist/src/modules/access/access.service.d.ts.map +0 -1
  117. package/dist/src/modules/access/access.test.d.ts.map +0 -1
  118. package/dist/src/modules/access/access.utils.d.ts.map +0 -1
  119. package/dist/src/modules/ai/ai.db.d.ts.map +0 -1
  120. package/dist/src/modules/ai/ai.prompt.d.ts.map +0 -1
  121. package/dist/src/modules/ai/ai.repository.d.ts.map +0 -1
  122. package/dist/src/modules/ai/ai.router.d.ts.map +0 -1
  123. package/dist/src/modules/ai/ai.service.d.ts.map +0 -1
  124. package/dist/src/modules/ai/ai.trpc.d.ts.map +0 -1
  125. package/dist/src/modules/ai/ideogram/ideogram.constants.d.ts.map +0 -1
  126. package/dist/src/modules/ai/ideogram/ideogram.dto.d.ts.map +0 -1
  127. package/dist/src/modules/ai/ideogram/ideogram.prompt.d.ts.map +0 -1
  128. package/dist/src/modules/ai/ideogram/ideogram.repository.d.ts.map +0 -1
  129. package/dist/src/modules/ai/ideogram/ideogram.service.d.ts.map +0 -1
  130. package/dist/src/modules/auth/auth.db.d.ts.map +0 -1
  131. package/dist/src/modules/auth/auth.dto.d.ts.map +0 -1
  132. package/dist/src/modules/auth/auth.lib.d.ts.map +0 -1
  133. package/dist/src/modules/auth/auth.middleware.d.ts.map +0 -1
  134. package/dist/src/modules/auth/auth.repository.d.ts.map +0 -1
  135. package/dist/src/modules/auth/auth.service.d.ts.map +0 -1
  136. package/dist/src/modules/auth/auth.trpc.d.ts.map +0 -1
  137. package/dist/src/modules/auth/auth.utils.d.ts.map +0 -1
  138. package/dist/src/modules/base/base.abstract.d.ts.map +0 -1
  139. package/dist/src/modules/base/base.dto.d.ts.map +0 -1
  140. package/dist/src/modules/base/base.grants.d.ts.map +0 -1
  141. package/dist/src/modules/base/base.grants.test.d.ts.map +0 -1
  142. package/dist/src/modules/base/base.repository.d.ts.map +0 -1
  143. package/dist/src/modules/base/base.service.d.ts.map +0 -1
  144. package/dist/src/modules/base/base.types.d.ts.map +0 -1
  145. package/dist/src/modules/billing/billing.db.d.ts.map +0 -1
  146. package/dist/src/modules/billing/billing.repository.d.ts.map +0 -1
  147. package/dist/src/modules/billing/billing.router.d.ts.map +0 -1
  148. package/dist/src/modules/billing/billing.service.d.ts.map +0 -1
  149. package/dist/src/modules/billing/billing.trpc.d.ts.map +0 -1
  150. package/dist/src/modules/clay/clay.repository.d.ts.map +0 -1
  151. package/dist/src/modules/clay/clay.service.d.ts.map +0 -1
  152. package/dist/src/modules/connect/connect.db.d.ts.map +0 -1
  153. package/dist/src/modules/connect/connect.dto.d.ts.map +0 -1
  154. package/dist/src/modules/connect/connect.linkedin.d.ts.map +0 -1
  155. package/dist/src/modules/connect/connect.oauth.d.ts.map +0 -1
  156. package/dist/src/modules/connect/connect.repository.d.ts.map +0 -1
  157. package/dist/src/modules/connect/connect.router.d.ts.map +0 -1
  158. package/dist/src/modules/connect/connect.service.d.ts.map +0 -1
  159. package/dist/src/modules/connect/connect.trpc.d.ts.map +0 -1
  160. package/dist/src/modules/connect/connect.types.d.ts.map +0 -1
  161. package/dist/src/modules/crypto/crypto.db.d.ts.map +0 -1
  162. package/dist/src/modules/crypto/crypto.repository.d.ts.map +0 -1
  163. package/dist/src/modules/crypto/crypto.service.d.ts.map +0 -1
  164. package/dist/src/modules/email/email.service.d.ts.map +0 -1
  165. package/dist/src/modules/file/file.repository.d.ts.map +0 -1
  166. package/dist/src/modules/file/file.router.d.ts.map +0 -1
  167. package/dist/src/modules/file/file.service.d.ts.map +0 -1
  168. package/dist/src/modules/recurrence/recurrence.db.d.ts.map +0 -1
  169. package/dist/src/modules/recurrence/recurrence.repository.d.ts.map +0 -1
  170. package/dist/src/modules/recurrence/recurrence.service.d.ts.map +0 -1
  171. package/dist/src/modules/recurrence/recurrence.trpc.d.ts.map +0 -1
  172. package/dist/src/modules/social/social.dto.d.ts.map +0 -1
  173. package/dist/src/modules/social/social.linkedin.d.ts.map +0 -1
  174. package/dist/src/modules/social/social.linkedin.test.d.ts.map +0 -1
  175. package/dist/src/modules/social/social.service.d.ts.map +0 -1
  176. package/dist/src/modules/social/social.types.d.ts.map +0 -1
  177. package/dist/src/modules/tag/tag.db.d.ts.map +0 -1
  178. package/dist/src/modules/tag/tag.dto.d.ts.map +0 -1
  179. package/dist/src/modules/tag/tag.repository.d.ts.map +0 -1
  180. package/dist/src/modules/tag/tag.service.d.ts.map +0 -1
  181. package/dist/src/modules/tag/tag.trpc.d.ts.map +0 -1
  182. package/dist/src/modules/utils/applyPagination.d.ts.map +0 -1
  183. package/dist/src/modules/utils/applySorting.d.ts.map +0 -1
  184. package/dist/src/modules/utils/getConditionsFromFilters.d.ts.map +0 -1
  185. package/dist/src/modules/video/video.service.d.ts.map +0 -1
  186. package/dist/src/modules/webhook/webhook.constants.d.ts.map +0 -1
  187. package/dist/src/modules/webhook/webhook.db.d.ts.map +0 -1
  188. package/dist/src/modules/webhook/webhook.dto.d.ts.map +0 -1
  189. package/dist/src/modules/webhook/webhook.repository.d.ts.map +0 -1
  190. package/dist/src/modules/webhook/webhook.router.d.ts.map +0 -1
  191. package/dist/src/modules/webhook/webhook.service.d.ts.map +0 -1
  192. package/dist/src/modules/workflow/workflow.db.d.ts.map +0 -1
  193. package/dist/src/modules/workflow/workflow.repository.d.ts.map +0 -1
  194. package/dist/src/modules/workflow/workflow.service.d.ts.map +0 -1
  195. package/dist/src/modules/workflow/workflow.trpc.d.ts.map +0 -1
  196. package/dist/src/modules/workflow/workflow.types.d.ts.map +0 -1
  197. package/dist/src/modules/workflow/workflow.utils.d.ts.map +0 -1
  198. package/dist/src/test/stubs/utils.d.ts.map +0 -1
  199. package/dist/src/trpc/context.d.ts.map +0 -1
  200. package/dist/src/trpc/index.d.ts.map +0 -1
  201. package/dist/src/trpc/procedures.d.ts.map +0 -1
  202. package/dist/src/trpc/utils.d.ts.map +0 -1
  203. package/dist/src/types.d.ts.map +0 -1
  204. package/dist/src/utils/errors.d.ts.map +0 -1
  205. package/dist/src/utils/logger.d.ts.map +0 -1
  206. package/dist/src/utils/posthog.d.ts.map +0 -1
  207. package/dist/src/utils/types.d.ts.map +0 -1
  208. package/jest.config.ts +0 -19
  209. package/src/lib/posthog.ts +0 -5
  210. package/src/lib/sentry.ts +0 -8
  211. package/src/modules/access/access.repository.ts +0 -36
  212. package/src/modules/access/access.service.ts +0 -81
  213. package/src/modules/access/access.test.ts +0 -216
  214. package/src/modules/access/access.utils.ts +0 -46
  215. package/src/modules/ai/ai.db.ts +0 -38
  216. package/src/modules/ai/ai.prompt.ts +0 -47
  217. package/src/modules/ai/ai.repository.ts +0 -53
  218. package/src/modules/ai/ai.router.ts +0 -148
  219. package/src/modules/ai/ai.service.ts +0 -310
  220. package/src/modules/ai/ai.trpc.ts +0 -22
  221. package/src/modules/ai/ideogram/ideogram.constants.ts +0 -170
  222. package/src/modules/ai/ideogram/ideogram.dto.ts +0 -64
  223. package/src/modules/ai/ideogram/ideogram.prompt.ts +0 -858
  224. package/src/modules/ai/ideogram/ideogram.repository.ts +0 -39
  225. package/src/modules/ai/ideogram/ideogram.service.ts +0 -14
  226. package/src/modules/auth/auth.db.ts +0 -224
  227. package/src/modules/auth/auth.dto.ts +0 -47
  228. package/src/modules/auth/auth.lib.ts +0 -349
  229. package/src/modules/auth/auth.middleware.ts +0 -62
  230. package/src/modules/auth/auth.repository.ts +0 -672
  231. package/src/modules/auth/auth.service.ts +0 -261
  232. package/src/modules/auth/auth.trpc.ts +0 -208
  233. package/src/modules/auth/auth.utils.ts +0 -117
  234. package/src/modules/base/base.abstract.ts +0 -62
  235. package/src/modules/base/base.dto.ts +0 -206
  236. package/src/modules/base/base.grants.test.ts +0 -861
  237. package/src/modules/base/base.grants.ts +0 -199
  238. package/src/modules/base/base.repository.ts +0 -433
  239. package/src/modules/base/base.service.ts +0 -154
  240. package/src/modules/base/base.types.ts +0 -7
  241. package/src/modules/billing/billing.db.ts +0 -27
  242. package/src/modules/billing/billing.repository.ts +0 -328
  243. package/src/modules/billing/billing.router.ts +0 -77
  244. package/src/modules/billing/billing.service.ts +0 -177
  245. package/src/modules/billing/billing.trpc.ts +0 -17
  246. package/src/modules/clay/clay.repository.ts +0 -29
  247. package/src/modules/clay/clay.service.ts +0 -61
  248. package/src/modules/connect/connect.db.ts +0 -32
  249. package/src/modules/connect/connect.dto.ts +0 -44
  250. package/src/modules/connect/connect.linkedin.ts +0 -70
  251. package/src/modules/connect/connect.oauth.ts +0 -288
  252. package/src/modules/connect/connect.repository.ts +0 -65
  253. package/src/modules/connect/connect.router.ts +0 -76
  254. package/src/modules/connect/connect.service.ts +0 -171
  255. package/src/modules/connect/connect.trpc.ts +0 -26
  256. package/src/modules/connect/connect.types.ts +0 -27
  257. package/src/modules/crypto/crypto.db.ts +0 -15
  258. package/src/modules/crypto/crypto.repository.ts +0 -13
  259. package/src/modules/crypto/crypto.service.ts +0 -57
  260. package/src/modules/email/email.service.ts +0 -222
  261. package/src/modules/file/file.repository.ts +0 -95
  262. package/src/modules/file/file.router.ts +0 -108
  263. package/src/modules/file/file.service.ts +0 -186
  264. package/src/modules/recurrence/recurrence.db.ts +0 -79
  265. package/src/modules/recurrence/recurrence.repository.ts +0 -70
  266. package/src/modules/recurrence/recurrence.service.ts +0 -105
  267. package/src/modules/recurrence/recurrence.trpc.ts +0 -82
  268. package/src/modules/social/social.dto.ts +0 -22
  269. package/src/modules/social/social.linkedin.test.ts +0 -277
  270. package/src/modules/social/social.linkedin.ts +0 -593
  271. package/src/modules/social/social.service.ts +0 -112
  272. package/src/modules/social/social.types.ts +0 -43
  273. package/src/modules/tag/tag.db.ts +0 -41
  274. package/src/modules/tag/tag.dto.ts +0 -18
  275. package/src/modules/tag/tag.repository.ts +0 -222
  276. package/src/modules/tag/tag.service.ts +0 -48
  277. package/src/modules/tag/tag.trpc.ts +0 -62
  278. package/src/modules/uploads/0581796b-8845-420d-bd95-cd7de79f6d37.webm +0 -0
  279. package/src/modules/uploads/33b1e649-6727-4bd0-94d0-a0b363646865.webm +0 -0
  280. package/src/modules/uploads/49a8c4c0-54d7-4c94-bef4-c93c029f9ed0.webm +0 -0
  281. package/src/modules/uploads/50e31e38-a2f0-47ca-8b7d-2d7fcad9267d.webm +0 -0
  282. package/src/modules/uploads/72ac8cf9-c3a7-4cd8-8a78-6d8e137a4c7e.webm +0 -0
  283. package/src/modules/uploads/75293649-d966-46cd-a675-67518958ae9c.png +0 -0
  284. package/src/modules/uploads/88b7b867-ce15-4891-bf73-81305a7de1f7.wav +0 -0
  285. package/src/modules/uploads/a5d6fee8-6a59-42c6-9d4a-ac8a3c5e7245.webm +0 -0
  286. package/src/modules/uploads/c13a9785-ca5a-4983-af30-b338ed76d370.webm +0 -0
  287. package/src/modules/uploads/caa1a5a7-71ba-4381-902d-7e2cafdf6dcb.webm +0 -0
  288. package/src/modules/uploads/cbeb0b81-374d-445b-914b-40ace7c8e031.webm +0 -0
  289. package/src/modules/uploads/d626aa82-b10f-493f-aee7-87bfb3361dfc.webm +0 -0
  290. package/src/modules/uploads/d7de4c16-de0c-495d-9612-e72260a6ecca.png +0 -0
  291. package/src/modules/uploads/e532e38a-6421-400e-8a5f-8e7bc8ce411b.wav +0 -0
  292. package/src/modules/uploads/e86ec867-6adf-4c51-84e0-00b0836625e8.webm +0 -0
  293. package/src/modules/utils/applyPagination.ts +0 -13
  294. package/src/modules/utils/applySorting.ts +0 -21
  295. package/src/modules/utils/getConditionsFromFilters.ts +0 -216
  296. package/src/modules/video/video.service.ts +0 -89
  297. package/src/modules/webhook/webhook.constants.ts +0 -9
  298. package/src/modules/webhook/webhook.db.ts +0 -15
  299. package/src/modules/webhook/webhook.dto.ts +0 -9
  300. package/src/modules/webhook/webhook.repository.ts +0 -68
  301. package/src/modules/webhook/webhook.router.ts +0 -29
  302. package/src/modules/webhook/webhook.service.ts +0 -78
  303. package/src/modules/workflow/workflow.db.ts +0 -29
  304. package/src/modules/workflow/workflow.repository.ts +0 -171
  305. package/src/modules/workflow/workflow.service.ts +0 -56
  306. package/src/modules/workflow/workflow.trpc.ts +0 -26
  307. package/src/modules/workflow/workflow.types.ts +0 -30
  308. package/src/modules/workflow/workflow.utils.ts +0 -259
  309. package/src/test/stubs/utils.ts +0 -2
  310. package/src/trpc/context.ts +0 -21
  311. package/src/trpc/index.ts +0 -3
  312. package/src/trpc/procedures.ts +0 -43
  313. package/src/trpc/utils.ts +0 -20
  314. package/src/types.ts +0 -22
  315. package/src/utils/errors.ts +0 -148
  316. package/src/utils/logger.ts +0 -8
  317. package/src/utils/posthog.ts +0 -43
  318. package/src/utils/types.ts +0 -5
  319. package/tsconfig.json +0 -21
@@ -1,199 +0,0 @@
1
- import { err, ok } from "neverthrow";
2
- import type { Session, User } from "#modules/auth/auth.lib";
3
- import type { ServerResultAsync } from "#modules/base/base.dto";
4
-
5
- type Level = "user" | "team" | "organization";
6
- type Access = "all" | "own";
7
-
8
- export type Entity = Partial<{
9
- userId: string | null;
10
- teamId: string | null;
11
- organizationId: string | null;
12
- }>;
13
-
14
- export type Grant = {
15
- level: Level;
16
- role: string;
17
- action: string;
18
- resource: string;
19
- access: Access;
20
- attributes?: string[];
21
- };
22
-
23
- export type NestedGrants = Record<
24
- string,
25
- Partial<Record<Level, Record<string, Record<string, Access>>>>
26
- >;
27
-
28
- export type ResourceGrant = Omit<Grant, "resource">;
29
-
30
- export type ResourceActionGrant = Omit<ResourceGrant, "action">;
31
-
32
- export function flattenNestedGrants(nestedGrants: NestedGrants): Grant[] {
33
- return Object.entries(nestedGrants).flatMap(([resource, levels]) => {
34
- return Object.entries(levels).flatMap(([level, roles]) => {
35
- return Object.entries(roles).flatMap(([role, actions]) => {
36
- return Object.entries(actions).map(([action, access]) => {
37
- return {
38
- resource,
39
- level: level as Level,
40
- role,
41
- action,
42
- access,
43
- };
44
- });
45
- });
46
- });
47
- });
48
- }
49
-
50
- function checkOwnership(
51
- entityField: keyof Entity,
52
- contextValue: string | null | undefined,
53
- entities?: Entity | Entity[]
54
- ): boolean {
55
- if (!contextValue) return false;
56
- if (!entities) return false;
57
- return Array.isArray(entities)
58
- ? entities.every((e) => e[entityField] === contextValue)
59
- : entities[entityField] === contextValue;
60
- }
61
-
62
- interface PermissionContext {
63
- session: Session;
64
- user: User;
65
- }
66
-
67
- type GrantLevel = "user" | "team" | "organization";
68
-
69
- // Level priority: user -> team -> organization (bottom-up)
70
- const LEVEL_PRIORITY: readonly GrantLevel[] = ["user", "team", "organization"];
71
-
72
- interface RoleContext {
73
- userRole: string | null;
74
- teamRole: string | null;
75
- organizationRole: string | null;
76
- }
77
-
78
- interface ContextValues {
79
- userId: string;
80
- teamId: string | null;
81
- organizationId: string | null;
82
- }
83
-
84
- function getRoleForLevel(level: GrantLevel, ctx: RoleContext): string | null {
85
- switch (level) {
86
- case "user":
87
- return ctx.userRole;
88
- case "team":
89
- return ctx.teamRole;
90
- case "organization":
91
- return ctx.organizationRole;
92
- }
93
- }
94
-
95
- function getContextValueForLevel(level: GrantLevel, ctx: ContextValues): string | null {
96
- switch (level) {
97
- case "user":
98
- return ctx.userId;
99
- case "team":
100
- return ctx.teamId;
101
- case "organization":
102
- return ctx.organizationId;
103
- }
104
- }
105
-
106
- function getOwnershipFieldForLevel(level: GrantLevel): keyof Entity {
107
- switch (level) {
108
- case "user":
109
- return "userId";
110
- case "team":
111
- return "teamId";
112
- case "organization":
113
- return "organizationId";
114
- }
115
- }
116
-
117
- function hasAllAccess(grants: ResourceActionGrant[], roles: RoleContext): boolean {
118
- for (const level of LEVEL_PRIORITY) {
119
- for (const grant of grants) {
120
- if (grant.level !== level) continue;
121
- if (grant.access !== "all") continue;
122
- if (grant.role === getRoleForLevel(level, roles)) return true;
123
- }
124
- }
125
- return false;
126
- }
127
-
128
- function checkOwnAccess(
129
- grants: ResourceActionGrant[],
130
- roles: RoleContext,
131
- contextValues: ContextValues,
132
- entities: Entity | Entity[] | undefined
133
- ): boolean {
134
- for (const level of LEVEL_PRIORITY) {
135
- for (const grant of grants) {
136
- if (grant.level !== level) continue;
137
- if (grant.access !== "own") continue;
138
- if (grant.role !== getRoleForLevel(level, roles)) continue;
139
-
140
- const ownershipField = getOwnershipFieldForLevel(level);
141
- const contextValue = getContextValueForLevel(level, contextValues);
142
-
143
- if (checkOwnership(ownershipField, contextValue, entities)) return true;
144
- }
145
- }
146
- return false;
147
- }
148
-
149
- export function checkPermissionSync<T extends Entity>(
150
- ctx: PermissionContext,
151
- grants: ResourceActionGrant[],
152
- entities?: T | T[]
153
- ): boolean {
154
- if (!grants || grants.length === 0) return false;
155
-
156
- const { id: userId, role: userRole } = ctx.user;
157
- const {
158
- activeOrganizationRole: organizationRole,
159
- activeTeamRole: teamRole,
160
- activeOrganizationId: organizationId,
161
- activeTeamId: teamId,
162
- } = ctx.session;
163
-
164
- const roles = { userRole, teamRole, organizationRole };
165
- const contextValues = { userId, teamId, organizationId };
166
-
167
- // Pass 1: Check for "all" access first (no ownership check needed)
168
- if (hasAllAccess(grants, roles)) return true;
169
-
170
- // Pass 2: Check "own" access with ownership validation
171
- return checkOwnAccess(grants, roles, contextValues, entities);
172
- }
173
-
174
- export async function checkPermissionAsync<T extends Entity>(
175
- ctx: PermissionContext,
176
- grants: ResourceActionGrant[],
177
- getEntities: () => ServerResultAsync<T | T[] | undefined>
178
- ): ServerResultAsync<boolean> {
179
- if (!grants || grants.length === 0) return ok(false);
180
-
181
- const { id: userId, role: userRole } = ctx.user;
182
- const {
183
- activeOrganizationRole: organizationRole,
184
- activeTeamRole: teamRole,
185
- activeOrganizationId: organizationId,
186
- activeTeamId: teamId,
187
- } = ctx.session;
188
-
189
- const roles = { userRole, teamRole, organizationRole };
190
- const contextValues = { userId, teamId, organizationId };
191
-
192
- // Pass 1: Check for "all" access first (no entity fetch needed)
193
- if (hasAllAccess(grants, roles)) return ok(true);
194
-
195
- // Pass 2: Only fetch entities if we need to check ownership
196
- const entities = await getEntities();
197
- if (entities.isErr()) return err(entities.error);
198
- return ok(checkOwnAccess(grants, roles, contextValues, entities.value));
199
- }
@@ -1,433 +0,0 @@
1
- import type {
2
- QueryFilter,
3
- QueryFilters,
4
- QueryInput,
5
- } from "@m5kdev/commons/modules/schemas/query.schema";
6
- import {
7
- and,
8
- count,
9
- eq,
10
- type InferInsertModel,
11
- type InferSelectModel,
12
- inArray,
13
- like,
14
- or,
15
- type SelectedFields,
16
- type SQL,
17
- } from "drizzle-orm";
18
- import type { LibSQLDatabase } from "drizzle-orm/libsql";
19
- import type { SQLiteColumn, SQLiteTableWithColumns } from "drizzle-orm/sqlite-core";
20
- import { ok } from "neverthrow";
21
- import { Base } from "#modules/base/base.abstract";
22
- import { pickColumns, type ServerResult, type ServerResultAsync } from "#modules/base/base.dto";
23
- import { applyPagination } from "#modules/utils/applyPagination";
24
- import { applySorting } from "#modules/utils/applySorting";
25
- import { getConditionsFromFilters } from "#modules/utils/getConditionsFromFilters";
26
-
27
- /** Payload for update/updateMany: id key required (string), other table fields optional. */
28
- export type TableUpdatePayload<
29
- TTable extends SQLiteTableWithColumns<any>,
30
- TIdKey extends Extract<keyof InferSelectModel<TTable>, string> = "id",
31
- > = Record<TIdKey, string> & Partial<Omit<InferSelectModel<TTable>, TIdKey>>;
32
-
33
- export class ConditionBuilder {
34
- constructor(private conditions: SQL[] = []) {
35
- this.conditions = conditions;
36
- }
37
-
38
- push(condition?: SQL) {
39
- if (condition) this.conditions.push(condition);
40
- }
41
-
42
- join(type: "and" | "or" = "and") {
43
- if (this.conditions.length === 0) return undefined;
44
- if (this.conditions.length === 1) return this.conditions[0];
45
- return type === "and" ? and(...this.conditions) : or(...this.conditions);
46
- }
47
-
48
- [Symbol.iterator]() {
49
- return this.conditions[Symbol.iterator]();
50
- }
51
- }
52
-
53
- export class TableConditionBuilder<
54
- TTable extends SQLiteTableWithColumns<any>,
55
- > extends ConditionBuilder {
56
- private table: TTable;
57
-
58
- constructor(table: TTable) {
59
- super();
60
- this.table = table;
61
- }
62
-
63
- applyFilters({ filters }: { filters?: QueryFilters } = {}) {
64
- if (filters && filters.length > 0) getConditionsFromFilters(this, filters, this.table);
65
- }
66
- }
67
-
68
- export const arrayContains = (table: SQLiteColumn, values: string[]) => {
69
- const arrayContains: SQL[] = [];
70
- for (const value of values) {
71
- arrayContains.push(like(table, `%"${value}%"`));
72
- }
73
- return or(...arrayContains);
74
- };
75
-
76
- export class BaseRepository<
77
- O extends LibSQLDatabase<any>,
78
- S extends Record<string, SQLiteTableWithColumns<any>>,
79
- R extends Record<string, BaseRepository<any, any, any> | BaseExternaRepository>,
80
- > extends Base {
81
- protected orm: O;
82
- protected schema: S;
83
- public repository?: R;
84
-
85
- constructor(options: { orm: O; schema: S }, repository?: R) {
86
- super("repository");
87
- this.orm = options.orm;
88
- this.schema = options.schema;
89
- this.repository = repository;
90
- }
91
- getConditionBuilder(): ConditionBuilder;
92
- getConditionBuilder(table: undefined): ConditionBuilder;
93
- getConditionBuilder<TTable extends SQLiteTableWithColumns<any>>(
94
- table: TTable
95
- ): TableConditionBuilder<TTable>;
96
- getConditionBuilder<TTable extends SQLiteTableWithColumns<any>>(
97
- table?: TTable
98
- ): ConditionBuilder | TableConditionBuilder<TTable> {
99
- if (table === undefined) {
100
- return new ConditionBuilder();
101
- }
102
- return new TableConditionBuilder(table);
103
- }
104
-
105
- withPagination<TQuery>(
106
- query: TQuery,
107
- { page, limit }: Pick<QueryInput, "page" | "limit">
108
- ): TQuery {
109
- return applyPagination(query, limit, page);
110
- }
111
-
112
- withSorting<TTable extends SQLiteTableWithColumns<any>, TQuery>(
113
- query: TQuery,
114
- { sort, order }: Pick<QueryInput, "sort" | "order">,
115
- table?: TTable
116
- ): TQuery {
117
- if (!table) throw new Error("No table provided");
118
- return applySorting(query, table, sort, order);
119
- }
120
-
121
- withSortingAndPagination<TTable extends SQLiteTableWithColumns<any>, TQuery>(
122
- query: TQuery,
123
- { sort, order, page, limit }: Pick<QueryInput, "sort" | "order" | "page" | "limit">,
124
- table?: TTable
125
- ): TQuery {
126
- if (!table) throw new Error("No table provided");
127
- return this.withSorting(this.withPagination(query, { page, limit }), { sort, order }, table);
128
- }
129
-
130
- addUserIdFilter(userId: string, query?: QueryInput): QueryInput {
131
- const userIdFilter: QueryFilter = {
132
- columnId: "userId",
133
- type: "string",
134
- method: "equals",
135
- value: userId,
136
- };
137
- return query
138
- ? { ...query, filters: [...(query?.filters ?? []), userIdFilter] }
139
- : { filters: [userIdFilter] };
140
- }
141
-
142
- helpers = {
143
- pickColumns,
144
- arrayContains,
145
- ConditionBuilder,
146
- };
147
- }
148
-
149
- /**
150
- * Generic table-bound repository with typed CRUD, returning ServerResultAsync via throwableAsync.
151
- *
152
- * Example:
153
- * const userRepo = new UserRepository(db, schema);
154
- * class UserRepository extends BaseTableRepository<typeof schema.user> {
155
- * constructor(db: LibSQLDatabase<typeof schema>, schema: typeof schema) {
156
- * super(db, schema, schema.user);
157
- * }
158
- * }
159
- */
160
- export class BaseTableRepository<
161
- O extends LibSQLDatabase<any>,
162
- S extends Record<string, SQLiteTableWithColumns<any>>,
163
- R extends Record<string, BaseRepository<any, any, any> | BaseExternaRepository>,
164
- TTable extends SQLiteTableWithColumns<any>,
165
- TIdKey extends Extract<keyof InferSelectModel<TTable>, string> = "id",
166
- > extends BaseRepository<O, S, R> {
167
- protected readonly table: TTable;
168
- protected readonly idKey: TIdKey;
169
- protected readonly idColumn: SQLiteColumn;
170
-
171
- constructor(options: { orm: O; schema: S; table: TTable; idKey?: TIdKey }, repository?: R) {
172
- super({ orm: options.orm, schema: options.schema }, repository);
173
- this.table = options.table;
174
- this.idKey = options.idKey ?? ("id" as TIdKey);
175
- this.idColumn = (this.table as any)[this.idKey] as SQLiteColumn;
176
- }
177
-
178
- override withSorting<TQuery>(
179
- query: TQuery,
180
- { sort, order }: Pick<QueryInput, "sort" | "order">,
181
- table?: SQLiteTableWithColumns<any>
182
- ): TQuery {
183
- return super.withSorting(query, { sort, order }, table || this.table);
184
- }
185
-
186
- override withSortingAndPagination<MTable extends SQLiteTableWithColumns<any>, TQuery>(
187
- query: TQuery,
188
- { sort, order, page, limit }: Pick<QueryInput, "sort" | "order" | "page" | "limit">,
189
- table?: MTable
190
- ): TQuery {
191
- return super.withSortingAndPagination(query, { sort, order, page, limit }, table || this.table);
192
- }
193
-
194
- async queryList(
195
- query?: QueryInput,
196
- options?: {
197
- conditions?: TableConditionBuilder<TTable>;
198
- select?: SelectedFields<SQLiteColumn, TTable>;
199
- },
200
- tx?: O
201
- ): ServerResultAsync<{ rows: InferSelectModel<TTable>[]; total: number }> {
202
- return this.throwableAsync(async () => {
203
- type Row = InferSelectModel<TTable>;
204
-
205
- const db = tx ?? this.orm;
206
- const conditions = options?.conditions ?? this.getConditionBuilder(this.table);
207
- conditions.applyFilters(query);
208
- const whereClause = conditions.join();
209
- const rowsQuery = this.withSortingAndPagination(
210
- (options?.select ? db.select(options.select) : db.select())
211
- .from(this.table as any)
212
- .where(whereClause),
213
- query || {}
214
- );
215
- const countQuery = db
216
- .select({ count: count() })
217
- .from(this.table as any)
218
- .where(whereClause);
219
- const [rows, [totalResult]] = await Promise.all([rowsQuery, countQuery]);
220
-
221
- return ok({ rows: rows as Row[], total: totalResult?.count ?? 0 });
222
- });
223
- }
224
-
225
- async findById(id: string, tx?: O): ServerResultAsync<InferSelectModel<TTable> | undefined> {
226
- return this.throwableAsync(async () => {
227
- const db = tx ?? this.orm;
228
- type Row = InferSelectModel<TTable>;
229
-
230
- const rows = (await db
231
- .select()
232
- .from(this.table as any)
233
- .where(eq(this.idColumn as SQLiteColumn, id))) as Row[];
234
-
235
- return ok(rows[0]);
236
- });
237
- }
238
-
239
- async findManyById(
240
- ids: readonly string[],
241
- tx?: O
242
- ): ServerResultAsync<Array<InferSelectModel<TTable>>> {
243
- return this.throwableAsync(async () => {
244
- const db = tx ?? this.orm;
245
- type Row = InferSelectModel<TTable>;
246
-
247
- if (ids.length === 0) {
248
- return ok<Row[]>([]);
249
- }
250
-
251
- const rows = (await db
252
- .select()
253
- .from(this.table as any)
254
- .where(inArray(this.idColumn as SQLiteColumn, ids as string[]))) as Row[];
255
-
256
- return ok(rows);
257
- });
258
- }
259
-
260
- async create(
261
- data: InferInsertModel<TTable>,
262
- tx?: O
263
- ): ServerResultAsync<InferSelectModel<TTable>> {
264
- return this.throwableAsync(async () => {
265
- const db = tx ?? this.orm;
266
- type Row = InferSelectModel<TTable>;
267
-
268
- const rows = (await db
269
- .insert(this.table as any)
270
- .values(data as any)
271
- .returning()) as unknown as Row[];
272
-
273
- if (rows.length === 0) return this.error("UNPROCESSABLE_CONTENT");
274
- return ok(rows[0] as Row);
275
- });
276
- }
277
-
278
- async createMany(
279
- data: readonly InferInsertModel<TTable>[],
280
- tx?: O
281
- ): ServerResultAsync<Array<InferSelectModel<TTable>>> {
282
- return this.throwableAsync(async () => {
283
- const db = tx ?? this.orm;
284
- type Row = InferSelectModel<TTable>;
285
-
286
- if (data.length === 0) {
287
- return ok<Row[]>([]);
288
- }
289
-
290
- const rows = (await db
291
- .insert(this.table as any)
292
- .values(data as any)
293
- .returning()) as unknown as Row[];
294
-
295
- return ok(rows as Row[]);
296
- });
297
- }
298
-
299
- async update(
300
- data: TableUpdatePayload<TTable, TIdKey>,
301
- tx?: O
302
- ): ServerResultAsync<InferSelectModel<TTable>> {
303
- return this.throwableAsync(async () => {
304
- const db = tx ?? this.orm;
305
- type Row = InferSelectModel<TTable>;
306
-
307
- const single = data as Record<string, unknown>;
308
- const id = String(single[this.idKey]);
309
- const { [this.idKey]: _removed, ...rest } = single;
310
- const update = rest;
311
- if (this.table.updatedAt) (update as any).updatedAt = new Date();
312
- const rows = (await db
313
- .update(this.table as any)
314
- .set(update as unknown as Partial<InferInsertModel<TTable>>)
315
- .where(eq(this.idColumn as SQLiteColumn, id))
316
- .returning()) as unknown as Row[];
317
- const [row] = rows;
318
-
319
- if (!row) return this.error("NOT_FOUND");
320
- return ok(row) as ServerResult<Row>;
321
- });
322
- }
323
-
324
- async updateMany(
325
- data: readonly TableUpdatePayload<TTable, TIdKey>[],
326
- tx?: O
327
- ): ServerResultAsync<Array<InferSelectModel<TTable>>> {
328
- return this.throwableAsync(async () => {
329
- const db = tx ?? this.orm;
330
- type Row = InferSelectModel<TTable>;
331
-
332
- if (data.length === 0) {
333
- return ok<Row[]>([]);
334
- }
335
-
336
- const results: Row[] = [];
337
- for (const item of data) {
338
- const record = item as Record<string, unknown>;
339
- const id = String(record[this.idKey]);
340
- const { [this.idKey]: _removed, ...rest } = record;
341
- const update = rest;
342
- if (this.table.updatedAt) (update as any).updatedAt = new Date();
343
- const rows = (await db
344
- .update(this.table as any)
345
- .set(update as unknown as Partial<InferInsertModel<TTable>>)
346
- .where(eq(this.idColumn as SQLiteColumn, id))
347
- .returning()) as unknown as Row[];
348
- if (rows[0]) results.push(rows[0]);
349
- }
350
-
351
- return ok(results) as ServerResult<Row[]>;
352
- });
353
- }
354
-
355
- async softDeleteById(id: string, tx?: O): ServerResultAsync<{ id: string }> {
356
- return this.throwableAsync(async () => {
357
- const db = tx ?? this.orm;
358
- if (!this.table.deletedAt) return this.error("METHOD_NOT_SUPPORTED");
359
-
360
- const rows = await db
361
- .update(this.table as any)
362
- .set({ deletedAt: new Date() })
363
- .where(eq(this.idColumn as SQLiteColumn, id))
364
- .returning({
365
- id: this.idColumn as SQLiteColumn,
366
- });
367
-
368
- if (rows.length === 0) return this.error("NOT_FOUND");
369
- return ok(rows[0] as { id: string });
370
- });
371
- }
372
-
373
- async softDeleteManyById(
374
- ids: readonly string[],
375
- tx?: O
376
- ): ServerResultAsync<Array<{ id: string }>> {
377
- return this.throwableAsync(async () => {
378
- const db = tx ?? this.orm;
379
- if (!this.table.deletedAt) return this.error("METHOD_NOT_SUPPORTED");
380
-
381
- const rows = await db
382
- .update(this.table as any)
383
- .set({ deletedAt: new Date() })
384
- .where(inArray(this.idColumn as SQLiteColumn, ids as string[]))
385
- .returning({
386
- id: this.idColumn as SQLiteColumn,
387
- });
388
- if (rows.length === 0) return this.error("NOT_FOUND");
389
- return ok(rows as { id: string }[]);
390
- });
391
- }
392
-
393
- async deleteById(id: string, tx?: O): ServerResultAsync<{ id: string }> {
394
- return this.throwableAsync(async () => {
395
- const db = tx ?? this.orm;
396
-
397
- const rows = await db
398
- .delete(this.table as any)
399
- .where(eq(this.idColumn as SQLiteColumn, id))
400
- .returning({
401
- id: this.idColumn as SQLiteColumn,
402
- });
403
-
404
- if (rows.length === 0) return this.error("NOT_FOUND");
405
- return ok(rows[0] as { id: string });
406
- });
407
- }
408
-
409
- async deleteManyById(ids: readonly string[], tx?: O): ServerResultAsync<Array<{ id: string }>> {
410
- return this.throwableAsync(async () => {
411
- const db = tx ?? this.orm;
412
-
413
- if (ids.length === 0) {
414
- return ok<{ id: string }[]>([]);
415
- }
416
-
417
- const rows = await db
418
- .delete(this.table as any)
419
- .where(inArray(this.idColumn as SQLiteColumn, ids as string[]))
420
- .returning({
421
- id: this.idColumn as SQLiteColumn,
422
- });
423
-
424
- return ok(rows as { id: string }[]);
425
- });
426
- }
427
- }
428
-
429
- export class BaseExternaRepository extends Base {
430
- constructor() {
431
- super("repository");
432
- }
433
- }