@goscribe/server 1.3.4 → 1.6.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 (383) hide show
  1. package/.env.example +12 -0
  2. package/.vscode/settings.json +3 -0
  3. package/REFACTOR_NOTES.md +60 -0
  4. package/TESTING_PROMPT.md +225 -0
  5. package/dist/context.d.ts +14 -1
  6. package/dist/context.js +23 -2
  7. package/dist/controllers/admin.controller.d.ts +715 -0
  8. package/dist/controllers/admin.controller.js +9 -0
  9. package/dist/controllers/annotations.controller.d.ts +439 -0
  10. package/dist/controllers/annotations.controller.js +9 -0
  11. package/dist/controllers/app-router.controller.d.ts +3011 -0
  12. package/dist/controllers/app-router.controller.js +38 -0
  13. package/dist/controllers/app-router.controller.test.d.ts +1 -0
  14. package/dist/controllers/app-router.controller.test.js +36 -0
  15. package/dist/controllers/auth.controller.d.ts +323 -0
  16. package/dist/controllers/auth.controller.js +9 -0
  17. package/dist/controllers/base.controller.d.ts +4 -0
  18. package/dist/controllers/base.controller.js +5 -0
  19. package/dist/controllers/chat.controller.d.ts +341 -0
  20. package/dist/controllers/chat.controller.js +9 -0
  21. package/dist/controllers/copilot.controller.d.ts +397 -0
  22. package/dist/controllers/copilot.controller.js +9 -0
  23. package/dist/controllers/flashcards.controller.d.ts +651 -0
  24. package/dist/controllers/flashcards.controller.js +9 -0
  25. package/dist/controllers/members.controller.d.ts +339 -0
  26. package/dist/controllers/members.controller.js +9 -0
  27. package/dist/controllers/notifications.controller.d.ts +199 -0
  28. package/dist/controllers/notifications.controller.js +9 -0
  29. package/dist/controllers/payment.controller.d.ts +181 -0
  30. package/dist/controllers/payment.controller.js +9 -0
  31. package/dist/controllers/podcast.controller.d.ts +575 -0
  32. package/dist/controllers/podcast.controller.js +9 -0
  33. package/dist/controllers/router-module.controller.d.ts +5 -0
  34. package/dist/controllers/router-module.controller.js +6 -0
  35. package/dist/controllers/studyguide.controller.d.ts +73 -0
  36. package/dist/controllers/studyguide.controller.js +9 -0
  37. package/dist/controllers/worksheets.controller.d.ts +829 -0
  38. package/dist/controllers/worksheets.controller.js +9 -0
  39. package/dist/controllers/workspace.controller.d.ts +1207 -0
  40. package/dist/controllers/workspace.controller.js +9 -0
  41. package/dist/lib/activity_human_description.test.js +16 -15
  42. package/dist/lib/activity_log_service.test.js +28 -23
  43. package/dist/lib/ai/config.d.ts +20 -0
  44. package/dist/lib/ai/config.js +31 -0
  45. package/dist/lib/ai/embedding-client.d.ts +8 -0
  46. package/dist/lib/ai/embedding-client.js +30 -0
  47. package/dist/lib/ai/index.d.ts +48 -0
  48. package/dist/lib/ai/index.js +29 -0
  49. package/dist/lib/ai/inference-backend/client.d.ts +28 -0
  50. package/dist/lib/ai/inference-backend/client.js +301 -0
  51. package/dist/lib/ai/inference-backend/mocks.d.ts +12 -0
  52. package/dist/lib/ai/inference-backend/mocks.js +133 -0
  53. package/dist/lib/ai/inference-backend/types.d.ts +44 -0
  54. package/dist/lib/ai/inference-backend/types.js +1 -0
  55. package/dist/lib/ai/json-parse.d.ts +2 -0
  56. package/dist/lib/ai/json-parse.js +34 -0
  57. package/dist/lib/ai/llm-client.d.ts +7 -0
  58. package/dist/lib/ai/llm-client.js +36 -0
  59. package/dist/lib/ai/mock.d.ts +2 -0
  60. package/dist/lib/ai/mock.js +10 -0
  61. package/dist/lib/ai/types.d.ts +9 -0
  62. package/dist/lib/ai/types.js +1 -0
  63. package/dist/lib/chunking.d.ts +19 -0
  64. package/dist/lib/chunking.js +47 -0
  65. package/dist/lib/curated-kb-seed.d.ts +12 -0
  66. package/dist/lib/curated-kb-seed.js +155 -0
  67. package/dist/lib/email.js +67 -108
  68. package/dist/lib/embeddings.d.ts +2 -0
  69. package/dist/lib/embeddings.js +1 -0
  70. package/dist/lib/ensure-curated-kb-catalog.d.ts +6 -0
  71. package/dist/lib/ensure-curated-kb-catalog.js +53 -0
  72. package/dist/lib/env.d.ts +1 -5
  73. package/dist/lib/env.js +2 -7
  74. package/dist/lib/inference.d.ts +1 -8
  75. package/dist/lib/inference.js +1 -19
  76. package/dist/lib/kb-meta.d.ts +8 -0
  77. package/dist/lib/kb-meta.js +77 -0
  78. package/dist/lib/note-text.d.ts +1 -0
  79. package/dist/lib/note-text.js +47 -0
  80. package/dist/lib/notification-service.test.js +37 -36
  81. package/dist/lib/pdf.d.ts +11 -0
  82. package/dist/lib/pdf.js +11 -0
  83. package/dist/lib/usage_service.d.ts +2 -1
  84. package/dist/lib/usage_service.js +30 -12
  85. package/dist/lib/worksheet-generation.js +4 -4
  86. package/dist/lib/worksheet-generation.test.js +32 -17
  87. package/dist/lib/workspace-kb.d.ts +5 -0
  88. package/dist/lib/workspace-kb.js +7 -0
  89. package/dist/models/controller-context.model.d.ts +8 -0
  90. package/dist/models/controller-context.model.js +1 -0
  91. package/dist/repositories/artifact.repository.d.ts +60 -0
  92. package/dist/repositories/artifact.repository.js +40 -0
  93. package/dist/repositories/base.repository.d.ts +14 -0
  94. package/dist/repositories/base.repository.js +14 -0
  95. package/dist/repositories/invitation.repository.d.ts +94 -0
  96. package/dist/repositories/invitation.repository.js +44 -0
  97. package/dist/repositories/notification.repository.d.ts +72 -0
  98. package/dist/repositories/notification.repository.js +44 -0
  99. package/dist/repositories/router-module.repository.d.ts +10 -0
  100. package/dist/repositories/router-module.repository.js +14 -0
  101. package/dist/repositories/user.repository.d.ts +74 -0
  102. package/dist/repositories/user.repository.js +37 -0
  103. package/dist/repositories/workspace-member.repository.d.ts +31 -0
  104. package/dist/repositories/workspace-member.repository.js +31 -0
  105. package/dist/repositories/workspace.repository.d.ts +97 -0
  106. package/dist/repositories/workspace.repository.js +79 -0
  107. package/dist/routers/_app.d.ts +566 -111
  108. package/dist/routers/_app.js +4 -0
  109. package/dist/routers/admin.d.ts +0 -4
  110. package/dist/routers/admin.js +21 -549
  111. package/dist/routers/annotations.js +12 -170
  112. package/dist/routers/artifactVersions.d.ts +65 -0
  113. package/dist/routers/artifactVersions.js +14 -0
  114. package/dist/routers/auth.d.ts +0 -6
  115. package/dist/routers/auth.js +37 -422
  116. package/dist/routers/chat.js +15 -229
  117. package/dist/routers/copilot.d.ts +14 -13
  118. package/dist/routers/copilot.js +13 -532
  119. package/dist/routers/flashcards.d.ts +17 -6
  120. package/dist/routers/flashcards.js +23 -349
  121. package/dist/routers/knowledgeBase.d.ts +421 -0
  122. package/dist/routers/knowledgeBase.js +118 -0
  123. package/dist/routers/members.d.ts +0 -41
  124. package/dist/routers/members.js +22 -710
  125. package/dist/routers/notes.d.ts +94 -0
  126. package/dist/routers/notes.js +37 -0
  127. package/dist/routers/notifications.js +7 -109
  128. package/dist/routers/payment.d.ts +2 -12
  129. package/dist/routers/payment.js +11 -393
  130. package/dist/routers/podcast.d.ts +1 -1
  131. package/dist/routers/podcast.js +11 -784
  132. package/dist/routers/studyguide.js +3 -129
  133. package/dist/routers/worksheets.d.ts +29 -14
  134. package/dist/routers/worksheets.js +49 -628
  135. package/dist/routers/workspace.d.ts +27 -71
  136. package/dist/routers/workspace.js +29 -922
  137. package/dist/scripts/purge-deleted-users.js +2 -2
  138. package/dist/server.js +10 -3
  139. package/dist/services/activity/activity-human-description.service.d.ts +13 -0
  140. package/dist/services/activity/activity-human-description.service.js +221 -0
  141. package/dist/services/activity/activity-human-description.service.test.d.ts +1 -0
  142. package/dist/services/activity/activity-human-description.service.test.js +16 -0
  143. package/dist/services/activity/activity-log.service.d.ts +87 -0
  144. package/dist/services/activity/activity-log.service.js +276 -0
  145. package/dist/services/activity/activity-log.service.test.d.ts +1 -0
  146. package/dist/services/activity/activity-log.service.test.js +27 -0
  147. package/dist/services/activity-human-description.service.d.ts +13 -0
  148. package/dist/services/activity-human-description.service.js +221 -0
  149. package/dist/services/activity-human-description.service.test.d.ts +1 -0
  150. package/dist/services/activity-human-description.service.test.js +16 -0
  151. package/dist/services/activity-log.service.d.ts +87 -0
  152. package/dist/services/activity-log.service.js +276 -0
  153. package/dist/services/activity-log.service.test.d.ts +1 -0
  154. package/dist/services/activity-log.service.test.js +27 -0
  155. package/dist/services/admin/admin.service.d.ts +270 -0
  156. package/dist/services/admin/admin.service.js +476 -0
  157. package/dist/services/admin.service.d.ts +270 -0
  158. package/dist/services/admin.service.js +476 -0
  159. package/dist/services/ai/ai-session.service.d.ts +5 -0
  160. package/dist/services/ai/ai-session.service.js +4 -0
  161. package/dist/services/ai-session.service.d.ts +60 -0
  162. package/dist/services/ai-session.service.js +561 -0
  163. package/dist/services/annotation.service.d.ts +177 -0
  164. package/dist/services/annotation.service.js +154 -0
  165. package/dist/services/artifact-notification.service.d.ts +14 -0
  166. package/dist/services/artifact-notification.service.js +20 -0
  167. package/dist/services/artifact-version.service.d.ts +38 -0
  168. package/dist/services/artifact-version.service.js +129 -0
  169. package/dist/services/artifacts/annotation.service.d.ts +177 -0
  170. package/dist/services/artifacts/annotation.service.js +154 -0
  171. package/dist/services/artifacts/artifact-version.service.d.ts +38 -0
  172. package/dist/services/artifacts/artifact-version.service.js +129 -0
  173. package/dist/services/artifacts/chat.service.d.ts +127 -0
  174. package/dist/services/artifacts/chat.service.js +182 -0
  175. package/dist/services/artifacts/study-guide.service.d.ts +18 -0
  176. package/dist/services/artifacts/study-guide.service.js +65 -0
  177. package/dist/services/auth/auth.service.d.ts +94 -0
  178. package/dist/services/auth/auth.service.js +368 -0
  179. package/dist/services/auth.service.d.ts +94 -0
  180. package/dist/services/auth.service.js +368 -0
  181. package/dist/services/base.service.d.ts +14 -0
  182. package/dist/services/base.service.js +14 -0
  183. package/dist/services/billing/payment.service.d.ts +44 -0
  184. package/dist/services/billing/payment.service.js +365 -0
  185. package/dist/services/billing/subscription.service.d.ts +37 -0
  186. package/dist/services/billing/subscription.service.js +654 -0
  187. package/dist/services/billing/usage.service.d.ts +47 -0
  188. package/dist/services/billing/usage.service.js +149 -0
  189. package/dist/services/chat.service.d.ts +127 -0
  190. package/dist/services/chat.service.js +182 -0
  191. package/dist/services/content/copilot.service.d.ts +113 -0
  192. package/dist/services/content/copilot.service.js +439 -0
  193. package/dist/services/content/flashcard-progress.service.d.ts +159 -0
  194. package/dist/services/content/flashcard-progress.service.js +432 -0
  195. package/dist/services/content/flashcard.service.d.ts +184 -0
  196. package/dist/services/content/flashcard.service.js +339 -0
  197. package/dist/services/content/media-analysis.service.d.ts +23 -0
  198. package/dist/services/content/media-analysis.service.js +404 -0
  199. package/dist/services/content/podcast.service.d.ts +267 -0
  200. package/dist/services/content/podcast.service.js +653 -0
  201. package/dist/services/content/worksheet-content.service.d.ts +37 -0
  202. package/dist/services/content/worksheet-content.service.js +84 -0
  203. package/dist/services/content/worksheet-content.service.test.d.ts +1 -0
  204. package/dist/services/content/worksheet-content.service.test.js +69 -0
  205. package/dist/services/content/worksheet-generation.service.d.ts +91 -0
  206. package/dist/services/content/worksheet-generation.service.js +95 -0
  207. package/dist/services/content/worksheet-generation.service.test.d.ts +1 -0
  208. package/dist/services/content/worksheet-generation.service.test.js +20 -0
  209. package/dist/services/content/worksheet.service.d.ts +347 -0
  210. package/dist/services/content/worksheet.service.js +599 -0
  211. package/dist/services/copilot.service.d.ts +116 -0
  212. package/dist/services/copilot.service.js +447 -0
  213. package/dist/services/flashcard-progress.service.d.ts +2 -2
  214. package/dist/services/flashcard-progress.service.js +3 -2
  215. package/dist/services/flashcard.service.d.ts +140 -0
  216. package/dist/services/flashcard.service.js +325 -0
  217. package/dist/services/invitation.service.d.ts +66 -0
  218. package/dist/services/invitation.service.js +348 -0
  219. package/dist/services/knowledge/knowledge-base.service.d.ts +316 -0
  220. package/dist/services/knowledge/knowledge-base.service.js +544 -0
  221. package/dist/services/knowledge-base.service.d.ts +316 -0
  222. package/dist/services/knowledge-base.service.js +536 -0
  223. package/dist/services/media-analysis.service.d.ts +23 -0
  224. package/dist/services/media-analysis.service.js +384 -0
  225. package/dist/services/member.service.d.ts +36 -0
  226. package/dist/services/member.service.js +193 -0
  227. package/dist/services/members/invitation.service.d.ts +66 -0
  228. package/dist/services/members/invitation.service.js +348 -0
  229. package/dist/services/members/member.service.d.ts +36 -0
  230. package/dist/services/members/member.service.js +193 -0
  231. package/dist/services/note.service.d.ts +55 -0
  232. package/dist/services/note.service.js +111 -0
  233. package/dist/services/notification.service.d.ts +214 -0
  234. package/dist/services/notification.service.js +550 -0
  235. package/dist/services/notification.service.test.d.ts +1 -0
  236. package/dist/services/notification.service.test.js +87 -0
  237. package/dist/services/notifications/notification.service.d.ts +214 -0
  238. package/dist/services/notifications/notification.service.js +550 -0
  239. package/dist/services/notifications/notification.service.test.d.ts +1 -0
  240. package/dist/services/notifications/notification.service.test.js +87 -0
  241. package/dist/services/payment.service.d.ts +55 -0
  242. package/dist/services/payment.service.js +368 -0
  243. package/dist/services/podcast.service.d.ts +267 -0
  244. package/dist/services/podcast.service.js +654 -0
  245. package/dist/services/router-module.service.d.ts +7 -0
  246. package/dist/services/router-module.service.js +10 -0
  247. package/dist/services/study-guide.service.d.ts +18 -0
  248. package/dist/services/study-guide.service.js +65 -0
  249. package/dist/services/subscription.service.d.ts +37 -0
  250. package/dist/services/subscription.service.js +654 -0
  251. package/dist/services/usage-limit-policy.service.d.ts +12 -0
  252. package/dist/services/usage-limit-policy.service.js +22 -0
  253. package/dist/services/usage-limit-policy.service.test.d.ts +1 -0
  254. package/dist/services/usage-limit-policy.service.test.js +46 -0
  255. package/dist/services/usage.service.d.ts +27 -0
  256. package/dist/services/usage.service.js +77 -0
  257. package/dist/services/worksheet-content.service.d.ts +42 -0
  258. package/dist/services/worksheet-content.service.js +84 -0
  259. package/dist/services/worksheet-content.service.test.d.ts +1 -0
  260. package/dist/services/worksheet-content.service.test.js +69 -0
  261. package/dist/services/worksheet-generation.service.d.ts +91 -0
  262. package/dist/services/worksheet-generation.service.js +95 -0
  263. package/dist/services/worksheet-generation.service.test.d.ts +1 -0
  264. package/dist/services/worksheet-generation.service.test.js +20 -0
  265. package/dist/services/worksheet.service.d.ts +385 -0
  266. package/dist/services/worksheet.service.js +596 -0
  267. package/dist/services/workspace/workspace-analytics.service.d.ts +24 -0
  268. package/dist/services/workspace/workspace-analytics.service.js +95 -0
  269. package/dist/services/workspace/workspace-kb.service.d.ts +40 -0
  270. package/dist/services/workspace/workspace-kb.service.js +184 -0
  271. package/dist/services/workspace/workspace.service.d.ts +263 -0
  272. package/dist/services/workspace/workspace.service.js +401 -0
  273. package/dist/services/workspace-analytics.service.d.ts +24 -0
  274. package/dist/services/workspace-analytics.service.js +95 -0
  275. package/dist/services/workspace-kb.service.d.ts +40 -0
  276. package/dist/services/workspace-kb.service.js +184 -0
  277. package/dist/services/workspace-progress.service.d.ts +27 -0
  278. package/dist/services/workspace-progress.service.js +56 -0
  279. package/dist/services/workspace-progress.service.test.d.ts +1 -0
  280. package/dist/services/workspace-progress.service.test.js +49 -0
  281. package/dist/services/workspace.service.d.ts +307 -0
  282. package/dist/services/workspace.service.js +390 -0
  283. package/dist/trpc.d.ts +12 -4
  284. package/dist/trpc.js +7 -13
  285. package/package.json +5 -6
  286. package/prisma/migrations/20260509000001_add_knowledge_base/migration.sql +99 -0
  287. package/prisma/migrations/20260509000002_curate_knowledge_base/migration.sql +52 -0
  288. package/prisma/migrations/20260522000000_add_notes/migration.sql +27 -0
  289. package/prisma/migrations/20260524000000_remove_notes/migration.sql +3 -0
  290. package/prisma/schema.prisma +150 -48
  291. package/prisma/seed.mjs +67 -0
  292. package/scripts/debug/README.md +4 -0
  293. package/src/README.md +63 -0
  294. package/src/context.ts +33 -3
  295. package/src/lib/ai/config.ts +34 -0
  296. package/src/lib/ai/embedding-client.ts +47 -0
  297. package/src/lib/ai/index.ts +65 -0
  298. package/src/lib/ai/inference-backend/client.ts +479 -0
  299. package/src/lib/ai/inference-backend/mocks.ts +171 -0
  300. package/src/lib/ai/inference-backend/types.ts +50 -0
  301. package/src/lib/ai/json-parse.ts +35 -0
  302. package/src/lib/ai/llm-client.ts +54 -0
  303. package/src/lib/ai/mock.ts +12 -0
  304. package/src/lib/ai/types.ts +11 -0
  305. package/src/lib/chunking.ts +81 -0
  306. package/src/lib/curated-kb-seed.ts +164 -0
  307. package/src/lib/email.ts +77 -115
  308. package/src/lib/embeddings.ts +9 -0
  309. package/src/lib/ensure-curated-kb-catalog.ts +60 -0
  310. package/src/lib/env.ts +2 -7
  311. package/src/lib/inference.ts +1 -21
  312. package/src/lib/kb-meta.ts +81 -0
  313. package/src/lib/pdf.ts +23 -0
  314. package/src/lib/workspace-kb.ts +7 -0
  315. package/src/repositories/artifact.repository.ts +55 -0
  316. package/src/repositories/base.repository.ts +19 -0
  317. package/src/repositories/invitation.repository.ts +53 -0
  318. package/src/repositories/notification.repository.ts +53 -0
  319. package/src/repositories/user.repository.ts +44 -0
  320. package/src/repositories/workspace-member.repository.ts +38 -0
  321. package/src/repositories/workspace.repository.ts +89 -0
  322. package/src/routers/_app.ts +4 -0
  323. package/src/routers/admin.ts +124 -692
  324. package/src/routers/annotations.ts +25 -203
  325. package/src/routers/artifactVersions.ts +32 -0
  326. package/src/routers/auth.ts +82 -520
  327. package/src/routers/chat.ts +42 -245
  328. package/src/routers/copilot.ts +41 -666
  329. package/src/routers/flashcards.ts +108 -404
  330. package/src/routers/knowledgeBase.ts +216 -0
  331. package/src/routers/members.ts +60 -782
  332. package/src/routers/notifications.ts +15 -117
  333. package/src/routers/payment.ts +37 -446
  334. package/src/routers/podcast.ts +36 -898
  335. package/src/routers/studyguide.ts +5 -144
  336. package/src/routers/worksheets.ts +171 -735
  337. package/src/routers/workspace.ts +141 -1108
  338. package/src/scripts/purge-deleted-users.ts +2 -2
  339. package/src/server.ts +10 -3
  340. package/src/{lib/activity_human_description.test.ts → services/activity/activity-human-description.service.test.ts} +1 -1
  341. package/src/{lib/activity_log_service.test.ts → services/activity/activity-log.service.test.ts} +1 -1
  342. package/src/{lib/activity_log_service.ts → services/activity/activity-log.service.ts} +2 -2
  343. package/src/services/admin/admin.service.ts +612 -0
  344. package/src/services/ai/ai-session.service.ts +5 -0
  345. package/src/services/artifacts/annotation.service.ts +189 -0
  346. package/src/services/artifacts/artifact-version.service.ts +151 -0
  347. package/src/services/artifacts/chat.service.ts +197 -0
  348. package/src/services/artifacts/study-guide.service.ts +72 -0
  349. package/src/services/auth/auth.service.ts +473 -0
  350. package/src/services/base.service.ts +19 -0
  351. package/src/services/billing/payment.service.ts +433 -0
  352. package/src/{lib/subscription_service.ts → services/billing/subscription.service.ts} +5 -5
  353. package/src/services/billing/usage.service.ts +207 -0
  354. package/src/services/content/copilot.service.ts +587 -0
  355. package/src/services/{flashcard-progress.service.ts → content/flashcard-progress.service.ts} +18 -12
  356. package/src/services/content/flashcard.service.ts +417 -0
  357. package/src/services/content/media-analysis.service.ts +561 -0
  358. package/src/services/content/podcast.service.ts +777 -0
  359. package/src/services/content/worksheet-content.service.test.ts +83 -0
  360. package/src/services/content/worksheet-content.service.ts +117 -0
  361. package/src/{lib/worksheet-generation.test.ts → services/content/worksheet-generation.service.test.ts} +3 -3
  362. package/src/services/content/worksheet.service.ts +751 -0
  363. package/src/services/knowledge/knowledge-base.service.ts +705 -0
  364. package/src/services/members/invitation.service.ts +427 -0
  365. package/src/services/members/member.service.ts +241 -0
  366. package/src/{lib/notification-service.test.ts → services/notifications/notification.service.test.ts} +2 -2
  367. package/src/{lib/notification-service.ts → services/notifications/notification.service.ts} +102 -1
  368. package/src/services/workspace/workspace-analytics.service.ts +107 -0
  369. package/src/services/workspace/workspace-kb.service.ts +273 -0
  370. package/src/services/workspace/workspace.service.ts +488 -0
  371. package/src/trpc.ts +7 -15
  372. package/src/lib/ai-session.ts +0 -704
  373. package/src/lib/usage_service.ts +0 -74
  374. package/src/lib/workspace-access.ts +0 -13
  375. /package/{check-difficulty.cjs → scripts/debug/check-difficulty.cjs} +0 -0
  376. /package/{check-questions.cjs → scripts/debug/check-questions.cjs} +0 -0
  377. /package/{db-summary.cjs → scripts/debug/db-summary.cjs} +0 -0
  378. /package/{mcq-test.cjs → scripts/debug/mcq-test.cjs} +0 -0
  379. /package/{test-generate.js → scripts/debug/test-generate.js} +0 -0
  380. /package/{test-ratio.cjs → scripts/debug/test-ratio.cjs} +0 -0
  381. /package/{zod-test.cjs → scripts/debug/zod-test.cjs} +0 -0
  382. /package/src/{lib/activity_human_description.ts → services/activity/activity-human-description.service.ts} +0 -0
  383. /package/src/{lib/worksheet-generation.ts → services/content/worksheet-generation.service.ts} +0 -0
@@ -1,4 +1,13 @@
1
1
  import { prisma } from './prisma.js';
2
+ const FALLBACK_PLAN_LIMITS = {
3
+ id: 'fallback-free',
4
+ planId: 'fallback-free',
5
+ maxStorageBytes: BigInt(1024 * 1024 * 1024), // 1GB
6
+ maxWorksheets: 3,
7
+ maxFlashcards: 20,
8
+ maxPodcasts: 0,
9
+ maxStudyGuides: 1,
10
+ };
2
11
  /**
3
12
  * Counts all resources consumed by a user across the platform.
4
13
  */
@@ -26,34 +35,43 @@ export async function getUserUsage(userId) {
26
35
  * PLUS any extra credits purchased.
27
36
  */
28
37
  export async function getUserPlanLimits(userId) {
29
- const [activeSub, userCredits] = await Promise.all([
38
+ const [activeSub, freePlan, userCredits] = await Promise.all([
30
39
  prisma.subscription.findFirst({
31
40
  where: { userId, status: 'active' },
32
41
  include: { plan: { include: { limit: true } } },
33
42
  orderBy: { createdAt: 'desc' }
34
43
  }),
44
+ prisma.plan.findFirst({
45
+ where: {
46
+ active: true,
47
+ price: 0,
48
+ limit: { isNot: null }
49
+ },
50
+ include: { limit: true },
51
+ orderBy: { createdAt: 'asc' }
52
+ }),
35
53
  prisma.userCredit.groupBy({
36
54
  by: ['resourceType'],
37
55
  where: { userId },
38
56
  _sum: { amount: true }
39
57
  })
40
58
  ]);
41
- const baseLimit = activeSub?.plan?.limit;
42
- // If no active subscription and no credits, user has no active limits
43
- if (!baseLimit && userCredits.length === 0)
44
- return null;
59
+ const baseLimit = activeSub?.plan?.limit ?? freePlan?.limit;
60
+ // Prefer subscription limits, then DB free-plan limits, then hardcoded safety fallback.
61
+ const base = baseLimit ?? FALLBACK_PLAN_LIMITS;
45
62
  // Fast lookup for credits
46
63
  const getCreditSum = (type) => userCredits.find(c => c.resourceType === type)?._sum.amount || 0;
47
64
  // Return the merged total limit
48
65
  return {
49
- id: baseLimit?.id || 'credits-only',
50
- planId: baseLimit?.planId || 'credits-only',
51
- maxStorageBytes: BigInt(Number(baseLimit?.maxStorageBytes || 0) + (getCreditSum('STORAGE') * 1024 * 1024)),
52
- maxWorksheets: (baseLimit?.maxWorksheets || 0) + getCreditSum('WORKSHEET'),
53
- maxFlashcards: (baseLimit?.maxFlashcards || 0) + getCreditSum('FLASHCARD_SET'),
54
- maxPodcasts: (baseLimit?.maxPodcasts || 0) + getCreditSum('PODCAST_EPISODE'),
55
- maxStudyGuides: (baseLimit?.maxStudyGuides || 0) + getCreditSum('STUDY_GUIDE'),
66
+ id: base.id,
67
+ planId: base.planId,
68
+ maxStorageBytes: BigInt(Number(base.maxStorageBytes) + (getCreditSum('STORAGE') * 1024 * 1024)),
69
+ maxWorksheets: base.maxWorksheets + getCreditSum('WORKSHEET'),
70
+ maxFlashcards: base.maxFlashcards + getCreditSum('FLASHCARD_SET'),
71
+ maxPodcasts: base.maxPodcasts + getCreditSum('PODCAST_EPISODE'),
72
+ maxStudyGuides: base.maxStudyGuides + getCreditSum('STUDY_GUIDE'),
56
73
  createdAt: baseLimit?.createdAt || new Date(),
57
74
  updatedAt: baseLimit?.updatedAt || new Date(),
75
+ isFallbackPlan: !baseLimit,
58
76
  };
59
77
  }
@@ -26,16 +26,16 @@ export function parsePresetConfig(raw) {
26
26
  return worksheetPresetConfigSchema.parse(raw);
27
27
  }
28
28
  export function mergeWorksheetGenerationConfig(presetConfig, configOverride, legacy) {
29
- // Precedence: legacy flat fields > configOverride > preset > defaults
30
- // We place legacy AFTER configOverride because configOverride's Zod partial schema injects defaults (like medium)
31
- // that shouldn't overwrite explicit explicit user choices passing via legacy parameters.
29
+ // Precedence: configOverride > legacy flat fields > preset > defaults.
30
+ // An explicit configOverride from the caller always wins over the router's
31
+ // legacy top-level fields (which have zod defaults like 'medium').
32
32
  const merged = {
33
33
  ...defaultConfig,
34
34
  ...presetConfig,
35
- ...configOverride,
36
35
  ...(legacy.numQuestions !== undefined ? { numQuestions: legacy.numQuestions } : {}),
37
36
  ...(legacy.difficulty !== undefined ? { difficulty: legacy.difficulty } : {}),
38
37
  ...(legacy.mode !== undefined ? { mode: legacy.mode } : {}),
38
+ ...configOverride,
39
39
  };
40
40
  return worksheetPresetConfigSchema.parse(merged);
41
41
  }
@@ -1,20 +1,35 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
1
+ import { describe, it, expect } from 'vitest';
3
2
  import { mergeWorksheetGenerationConfig, normalizeWorksheetProblemForDb } from './worksheet-generation.js';
4
- test('mergeWorksheetGenerationConfig: override beats preset and legacy', () => {
5
- const r = mergeWorksheetGenerationConfig({ mode: 'practice', numQuestions: 5, difficulty: 'easy' }, { mode: 'quiz', numQuestions: 10, difficulty: 'medium' }, { numQuestions: 3, difficulty: 'hard' });
6
- assert.equal(r.mode, 'quiz');
7
- assert.equal(r.numQuestions, 10);
8
- assert.equal(r.difficulty, 'medium');
3
+ describe('mergeWorksheetGenerationConfig', () => {
4
+ it('override beats preset and legacy', () => {
5
+ const r = mergeWorksheetGenerationConfig({ mode: 'practice', numQuestions: 5, difficulty: 'easy' }, { mode: 'quiz', numQuestions: 10, difficulty: 'medium' }, { numQuestions: 3, difficulty: 'hard' });
6
+ expect(r.mode).toBe('quiz');
7
+ expect(r.numQuestions).toBe(10);
8
+ expect(r.difficulty).toBe('medium');
9
+ });
10
+ it('legacy beats preset when no override', () => {
11
+ const r = mergeWorksheetGenerationConfig({ mode: 'practice', numQuestions: 5, difficulty: 'easy' }, undefined, { numQuestions: 7, difficulty: 'hard' });
12
+ expect(r.numQuestions).toBe(7);
13
+ expect(r.difficulty).toBe('hard');
14
+ expect(r.mode).toBe('practice');
15
+ });
16
+ it('preset supplies defaults when override and legacy absent', () => {
17
+ const r = mergeWorksheetGenerationConfig({ mode: 'quiz', numQuestions: 5, difficulty: 'easy' }, undefined, {});
18
+ expect(r.mode).toBe('quiz');
19
+ expect(r.numQuestions).toBe(5);
20
+ expect(r.difficulty).toBe('easy');
21
+ });
9
22
  });
10
- test('normalizeWorksheetProblemForDb coerces MCQ answer to option index', () => {
11
- const row = normalizeWorksheetProblemForDb({
12
- question: 'Capital of France?',
13
- answer: 'Paris',
14
- type: 'MULTIPLE_CHOICE',
15
- options: ['London', 'Paris', 'Berlin'],
16
- }, 0, 'MEDIUM', true);
17
- assert.equal(row.type, 'MULTIPLE_CHOICE');
18
- assert.equal(row.answer, '1');
19
- assert.ok(row.meta.options && row.meta.options.length >= 2);
23
+ describe('normalizeWorksheetProblemForDb', () => {
24
+ it('coerces MCQ answer to option index', () => {
25
+ const row = normalizeWorksheetProblemForDb({
26
+ question: 'Capital of France?',
27
+ answer: 'Paris',
28
+ type: 'MULTIPLE_CHOICE',
29
+ options: ['London', 'Paris', 'Berlin'],
30
+ }, 0, 'MEDIUM', true);
31
+ expect(row.type).toBe('MULTIPLE_CHOICE');
32
+ expect(row.answer).toBe('1');
33
+ expect(row.meta.options?.length).toBeGreaterThanOrEqual(2);
34
+ });
20
35
  });
@@ -0,0 +1,5 @@
1
+ /** Meta.kind value for the private, auto-managed KB attached to each workspace. */
2
+ export declare const WORKSPACE_KB_KIND = "workspace";
3
+ export declare function isWorkspaceManagedKb(kb: {
4
+ meta: unknown;
5
+ }): boolean;
@@ -0,0 +1,7 @@
1
+ /** Meta.kind value for the private, auto-managed KB attached to each workspace. */
2
+ export const WORKSPACE_KB_KIND = 'workspace';
3
+ export function isWorkspaceManagedKb(kb) {
4
+ if (!kb.meta || typeof kb.meta !== 'object')
5
+ return false;
6
+ return kb.meta.kind === WORKSPACE_KB_KIND;
7
+ }
@@ -0,0 +1,8 @@
1
+ import type { Context } from '../context.js';
2
+ export interface ControllerContext {
3
+ ctx: Context;
4
+ }
5
+ export interface Controller<Input, Output> {
6
+ execute(input: Input, context: ControllerContext): Promise<Output> | Output;
7
+ }
8
+ export type TrpcRouterModule = Record<string, unknown>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,60 @@
1
+ import type { ArtifactType, Prisma, PrismaClient } from '@prisma/client';
2
+ import { BaseRepository } from './base.repository.js';
3
+ export declare class ArtifactRepository extends BaseRepository {
4
+ constructor(db: PrismaClient);
5
+ /**
6
+ * Fetch an artifact if the user can access the containing workspace
7
+ * (owner or member).
8
+ */
9
+ findByIdAccessible(artifactId: string, userId: string, include?: Prisma.ArtifactInclude): Prisma.Prisma__ArtifactClient<{
10
+ id: string;
11
+ createdAt: Date;
12
+ updatedAt: Date;
13
+ workspaceId: string;
14
+ type: import("@prisma/client").$Enums.ArtifactType;
15
+ title: string;
16
+ isArchived: boolean;
17
+ difficulty: import("@prisma/client").$Enums.Difficulty | null;
18
+ estimatedTime: string | null;
19
+ createdById: string | null;
20
+ description: string | null;
21
+ generating: boolean;
22
+ generatingMetadata: Prisma.JsonValue | null;
23
+ worksheetConfig: Prisma.JsonValue | null;
24
+ imageObjectKey: string | null;
25
+ } | null, null, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
26
+ findByIdAndTypeAccessible(artifactId: string, type: ArtifactType, userId: string, include?: Prisma.ArtifactInclude): Prisma.Prisma__ArtifactClient<{
27
+ id: string;
28
+ createdAt: Date;
29
+ updatedAt: Date;
30
+ workspaceId: string;
31
+ type: import("@prisma/client").$Enums.ArtifactType;
32
+ title: string;
33
+ isArchived: boolean;
34
+ difficulty: import("@prisma/client").$Enums.Difficulty | null;
35
+ estimatedTime: string | null;
36
+ createdById: string | null;
37
+ description: string | null;
38
+ generating: boolean;
39
+ generatingMetadata: Prisma.JsonValue | null;
40
+ worksheetConfig: Prisma.JsonValue | null;
41
+ imageObjectKey: string | null;
42
+ } | null, null, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
43
+ listByWorkspaceAndType(workspaceId: string, type: ArtifactType, userId: string, args?: Omit<Prisma.ArtifactFindManyArgs, 'where'>): Prisma.PrismaPromise<{
44
+ id: string;
45
+ createdAt: Date;
46
+ updatedAt: Date;
47
+ workspaceId: string;
48
+ type: import("@prisma/client").$Enums.ArtifactType;
49
+ title: string;
50
+ isArchived: boolean;
51
+ difficulty: import("@prisma/client").$Enums.Difficulty | null;
52
+ estimatedTime: string | null;
53
+ createdById: string | null;
54
+ description: string | null;
55
+ generating: boolean;
56
+ generatingMetadata: Prisma.JsonValue | null;
57
+ worksheetConfig: Prisma.JsonValue | null;
58
+ imageObjectKey: string | null;
59
+ }[]>;
60
+ }
@@ -0,0 +1,40 @@
1
+ import { BaseRepository } from './base.repository.js';
2
+ import { workspaceAccessWhere } from './workspace.repository.js';
3
+ export class ArtifactRepository extends BaseRepository {
4
+ constructor(db) {
5
+ super(db);
6
+ }
7
+ /**
8
+ * Fetch an artifact if the user can access the containing workspace
9
+ * (owner or member).
10
+ */
11
+ findByIdAccessible(artifactId, userId, include) {
12
+ return this.db.artifact.findFirst({
13
+ where: {
14
+ id: artifactId,
15
+ workspace: workspaceAccessWhere(userId),
16
+ },
17
+ include,
18
+ });
19
+ }
20
+ findByIdAndTypeAccessible(artifactId, type, userId, include) {
21
+ return this.db.artifact.findFirst({
22
+ where: {
23
+ id: artifactId,
24
+ type,
25
+ workspace: workspaceAccessWhere(userId),
26
+ },
27
+ include,
28
+ });
29
+ }
30
+ listByWorkspaceAndType(workspaceId, type, userId, args) {
31
+ return this.db.artifact.findMany({
32
+ ...args,
33
+ where: {
34
+ workspaceId,
35
+ type,
36
+ workspace: workspaceAccessWhere(userId),
37
+ },
38
+ });
39
+ }
40
+ }
@@ -0,0 +1,14 @@
1
+ import type { PrismaClient } from '@prisma/client';
2
+ import { logger } from '../lib/logger.js';
3
+ /**
4
+ * Shared base class for repositories.
5
+ *
6
+ * Repositories own data access. They wrap a Prisma client and expose
7
+ * intent-revealing methods (e.g. `findAccessibleById(workspaceId, userId)`)
8
+ * so that the shape of `where` clauses doesn't leak into services/routers.
9
+ */
10
+ export declare abstract class BaseRepository {
11
+ protected readonly db: PrismaClient;
12
+ protected readonly logger: typeof logger;
13
+ constructor(db: PrismaClient);
14
+ }
@@ -0,0 +1,14 @@
1
+ import { logger } from '../lib/logger.js';
2
+ /**
3
+ * Shared base class for repositories.
4
+ *
5
+ * Repositories own data access. They wrap a Prisma client and expose
6
+ * intent-revealing methods (e.g. `findAccessibleById(workspaceId, userId)`)
7
+ * so that the shape of `where` clauses doesn't leak into services/routers.
8
+ */
9
+ export class BaseRepository {
10
+ constructor(db) {
11
+ this.db = db;
12
+ this.logger = logger;
13
+ }
14
+ }
@@ -0,0 +1,94 @@
1
+ import type { Prisma, PrismaClient } from '@prisma/client';
2
+ import { BaseRepository } from './base.repository.js';
3
+ /**
4
+ * Data access for `WorkspaceInvitation`. Members router currently performs
5
+ * invitation CRUD + token validation directly against Prisma — this
6
+ * repository is the target of that extraction during Phase 4.
7
+ */
8
+ export declare class InvitationRepository extends BaseRepository {
9
+ constructor(db: PrismaClient);
10
+ findById(id: string, include?: Prisma.WorkspaceInvitationInclude): Prisma.Prisma__WorkspaceInvitationClient<{
11
+ id: string;
12
+ email: string;
13
+ createdAt: Date;
14
+ updatedAt: Date;
15
+ workspaceId: string;
16
+ role: string;
17
+ token: string;
18
+ invitedById: string;
19
+ acceptedAt: Date | null;
20
+ expiresAt: Date;
21
+ } | null, null, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
22
+ findFirst(args: Prisma.WorkspaceInvitationFindFirstArgs): Prisma.Prisma__WorkspaceInvitationClient<{
23
+ id: string;
24
+ email: string;
25
+ createdAt: Date;
26
+ updatedAt: Date;
27
+ workspaceId: string;
28
+ role: string;
29
+ token: string;
30
+ invitedById: string;
31
+ acceptedAt: Date | null;
32
+ expiresAt: Date;
33
+ } | null, null, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
34
+ listByWorkspace(workspaceId: string, args?: Omit<Prisma.WorkspaceInvitationFindManyArgs, 'where'>): Prisma.PrismaPromise<{
35
+ id: string;
36
+ email: string;
37
+ createdAt: Date;
38
+ updatedAt: Date;
39
+ workspaceId: string;
40
+ role: string;
41
+ token: string;
42
+ invitedById: string;
43
+ acceptedAt: Date | null;
44
+ expiresAt: Date;
45
+ }[]>;
46
+ listForUserEmail(email: string, args?: Omit<Prisma.WorkspaceInvitationFindManyArgs, 'where'>): Prisma.PrismaPromise<{
47
+ id: string;
48
+ email: string;
49
+ createdAt: Date;
50
+ updatedAt: Date;
51
+ workspaceId: string;
52
+ role: string;
53
+ token: string;
54
+ invitedById: string;
55
+ acceptedAt: Date | null;
56
+ expiresAt: Date;
57
+ }[]>;
58
+ create(data: Prisma.WorkspaceInvitationCreateInput): Prisma.Prisma__WorkspaceInvitationClient<{
59
+ id: string;
60
+ email: string;
61
+ createdAt: Date;
62
+ updatedAt: Date;
63
+ workspaceId: string;
64
+ role: string;
65
+ token: string;
66
+ invitedById: string;
67
+ acceptedAt: Date | null;
68
+ expiresAt: Date;
69
+ }, never, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
70
+ update(id: string, data: Prisma.WorkspaceInvitationUpdateInput): Prisma.Prisma__WorkspaceInvitationClient<{
71
+ id: string;
72
+ email: string;
73
+ createdAt: Date;
74
+ updatedAt: Date;
75
+ workspaceId: string;
76
+ role: string;
77
+ token: string;
78
+ invitedById: string;
79
+ acceptedAt: Date | null;
80
+ expiresAt: Date;
81
+ }, never, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
82
+ delete(id: string): Prisma.Prisma__WorkspaceInvitationClient<{
83
+ id: string;
84
+ email: string;
85
+ createdAt: Date;
86
+ updatedAt: Date;
87
+ workspaceId: string;
88
+ role: string;
89
+ token: string;
90
+ invitedById: string;
91
+ acceptedAt: Date | null;
92
+ expiresAt: Date;
93
+ }, never, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
94
+ }
@@ -0,0 +1,44 @@
1
+ import { BaseRepository } from './base.repository.js';
2
+ /**
3
+ * Data access for `WorkspaceInvitation`. Members router currently performs
4
+ * invitation CRUD + token validation directly against Prisma — this
5
+ * repository is the target of that extraction during Phase 4.
6
+ */
7
+ export class InvitationRepository extends BaseRepository {
8
+ constructor(db) {
9
+ super(db);
10
+ }
11
+ findById(id, include) {
12
+ return this.db.workspaceInvitation.findFirst({
13
+ where: { id },
14
+ include,
15
+ });
16
+ }
17
+ findFirst(args) {
18
+ return this.db.workspaceInvitation.findFirst(args);
19
+ }
20
+ listByWorkspace(workspaceId, args) {
21
+ return this.db.workspaceInvitation.findMany({
22
+ ...args,
23
+ where: { workspaceId },
24
+ });
25
+ }
26
+ listForUserEmail(email, args) {
27
+ return this.db.workspaceInvitation.findMany({
28
+ ...args,
29
+ where: { email },
30
+ });
31
+ }
32
+ create(data) {
33
+ return this.db.workspaceInvitation.create({ data });
34
+ }
35
+ update(id, data) {
36
+ return this.db.workspaceInvitation.update({
37
+ where: { id },
38
+ data,
39
+ });
40
+ }
41
+ delete(id) {
42
+ return this.db.workspaceInvitation.delete({ where: { id } });
43
+ }
44
+ }
@@ -0,0 +1,72 @@
1
+ import type { Prisma, PrismaClient } from '@prisma/client';
2
+ import { BaseRepository } from './base.repository.js';
3
+ /**
4
+ * Thin data-access wrapper around `Notification`. `NotificationService`
5
+ * currently calls `ctx.db.notification.*` directly; Phase 4 will migrate it
6
+ * to use this repository so services don't need Prisma-specific types at
7
+ * their API boundary.
8
+ */
9
+ export declare class NotificationRepository extends BaseRepository {
10
+ constructor(db: PrismaClient);
11
+ findFirst(args: Prisma.NotificationFindFirstArgs): Prisma.Prisma__NotificationClient<{
12
+ id: string;
13
+ createdAt: Date;
14
+ updatedAt: Date;
15
+ workspaceId: string | null;
16
+ type: string;
17
+ title: string;
18
+ content: string | null;
19
+ userId: string;
20
+ actorUserId: string | null;
21
+ body: string;
22
+ actionUrl: string | null;
23
+ metadata: Prisma.JsonValue | null;
24
+ priority: import("@prisma/client").$Enums.NotificationPriority;
25
+ sourceId: string | null;
26
+ read: boolean;
27
+ readAt: Date | null;
28
+ deliveredAt: Date | null;
29
+ } | null, null, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
30
+ listByUser(userId: string, args?: Omit<Prisma.NotificationFindManyArgs, 'where'>): Prisma.PrismaPromise<{
31
+ id: string;
32
+ createdAt: Date;
33
+ updatedAt: Date;
34
+ workspaceId: string | null;
35
+ type: string;
36
+ title: string;
37
+ content: string | null;
38
+ userId: string;
39
+ actorUserId: string | null;
40
+ body: string;
41
+ actionUrl: string | null;
42
+ metadata: Prisma.JsonValue | null;
43
+ priority: import("@prisma/client").$Enums.NotificationPriority;
44
+ sourceId: string | null;
45
+ read: boolean;
46
+ readAt: Date | null;
47
+ deliveredAt: Date | null;
48
+ }[]>;
49
+ count(args: Prisma.NotificationCountArgs): Prisma.PrismaPromise<number>;
50
+ create(data: Prisma.NotificationCreateInput): Prisma.Prisma__NotificationClient<{
51
+ id: string;
52
+ createdAt: Date;
53
+ updatedAt: Date;
54
+ workspaceId: string | null;
55
+ type: string;
56
+ title: string;
57
+ content: string | null;
58
+ userId: string;
59
+ actorUserId: string | null;
60
+ body: string;
61
+ actionUrl: string | null;
62
+ metadata: Prisma.JsonValue | null;
63
+ priority: import("@prisma/client").$Enums.NotificationPriority;
64
+ sourceId: string | null;
65
+ read: boolean;
66
+ readAt: Date | null;
67
+ deliveredAt: Date | null;
68
+ }, never, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
69
+ markRead(id: string, userId: string): Prisma.PrismaPromise<Prisma.BatchPayload>;
70
+ markAllRead(userId: string): Prisma.PrismaPromise<Prisma.BatchPayload>;
71
+ delete(id: string, userId: string): Prisma.PrismaPromise<Prisma.BatchPayload>;
72
+ }
@@ -0,0 +1,44 @@
1
+ import { BaseRepository } from './base.repository.js';
2
+ /**
3
+ * Thin data-access wrapper around `Notification`. `NotificationService`
4
+ * currently calls `ctx.db.notification.*` directly; Phase 4 will migrate it
5
+ * to use this repository so services don't need Prisma-specific types at
6
+ * their API boundary.
7
+ */
8
+ export class NotificationRepository extends BaseRepository {
9
+ constructor(db) {
10
+ super(db);
11
+ }
12
+ findFirst(args) {
13
+ return this.db.notification.findFirst(args);
14
+ }
15
+ listByUser(userId, args) {
16
+ return this.db.notification.findMany({
17
+ ...args,
18
+ where: { userId },
19
+ });
20
+ }
21
+ count(args) {
22
+ return this.db.notification.count(args);
23
+ }
24
+ create(data) {
25
+ return this.db.notification.create({ data });
26
+ }
27
+ markRead(id, userId) {
28
+ return this.db.notification.updateMany({
29
+ where: { id, userId },
30
+ data: { read: true },
31
+ });
32
+ }
33
+ markAllRead(userId) {
34
+ return this.db.notification.updateMany({
35
+ where: { userId, read: false },
36
+ data: { read: true },
37
+ });
38
+ }
39
+ delete(id, userId) {
40
+ return this.db.notification.deleteMany({
41
+ where: { id, userId },
42
+ });
43
+ }
44
+ }
@@ -0,0 +1,10 @@
1
+ import { BaseRepository } from './base.repository.js';
2
+ /**
3
+ * Adapter repository for legacy router modules during MVC migration.
4
+ * Keeps the transport contract stable while moving ownership boundaries.
5
+ */
6
+ export declare class RouterModuleRepository<TModule> extends BaseRepository {
7
+ private readonly module;
8
+ constructor(db: ConstructorParameters<typeof BaseRepository>[0], module: TModule);
9
+ getModule(): TModule;
10
+ }
@@ -0,0 +1,14 @@
1
+ import { BaseRepository } from './base.repository.js';
2
+ /**
3
+ * Adapter repository for legacy router modules during MVC migration.
4
+ * Keeps the transport contract stable while moving ownership boundaries.
5
+ */
6
+ export class RouterModuleRepository extends BaseRepository {
7
+ constructor(db, module) {
8
+ super(db);
9
+ this.module = module;
10
+ }
11
+ getModule() {
12
+ return this.module;
13
+ }
14
+ }
@@ -0,0 +1,74 @@
1
+ import type { Prisma, PrismaClient } from '@prisma/client';
2
+ import { BaseRepository } from './base.repository.js';
3
+ export declare class UserRepository extends BaseRepository {
4
+ constructor(db: PrismaClient);
5
+ findById(id: string, args?: Omit<Prisma.UserFindUniqueArgs, 'where'>): Prisma.Prisma__UserClient<{
6
+ name: string | null;
7
+ id: string;
8
+ email: string | null;
9
+ emailVerified: Date | null;
10
+ passwordHash: string | null;
11
+ createdAt: Date;
12
+ updatedAt: Date;
13
+ fileAssetId: string | null;
14
+ roleId: string | null;
15
+ deletedAt: Date | null;
16
+ stripe_customer_id: string | null;
17
+ } | null, null, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
18
+ findByEmail(email: string, args?: Omit<Prisma.UserFindUniqueArgs, 'where'>): Prisma.Prisma__UserClient<{
19
+ name: string | null;
20
+ id: string;
21
+ email: string | null;
22
+ emailVerified: Date | null;
23
+ passwordHash: string | null;
24
+ createdAt: Date;
25
+ updatedAt: Date;
26
+ fileAssetId: string | null;
27
+ roleId: string | null;
28
+ deletedAt: Date | null;
29
+ stripe_customer_id: string | null;
30
+ } | null, null, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
31
+ create(data: Prisma.UserCreateInput): Prisma.Prisma__UserClient<{
32
+ name: string | null;
33
+ id: string;
34
+ email: string | null;
35
+ emailVerified: Date | null;
36
+ passwordHash: string | null;
37
+ createdAt: Date;
38
+ updatedAt: Date;
39
+ fileAssetId: string | null;
40
+ roleId: string | null;
41
+ deletedAt: Date | null;
42
+ stripe_customer_id: string | null;
43
+ }, never, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
44
+ update(id: string, data: Prisma.UserUpdateInput): Prisma.Prisma__UserClient<{
45
+ name: string | null;
46
+ id: string;
47
+ email: string | null;
48
+ emailVerified: Date | null;
49
+ passwordHash: string | null;
50
+ createdAt: Date;
51
+ updatedAt: Date;
52
+ fileAssetId: string | null;
53
+ roleId: string | null;
54
+ deletedAt: Date | null;
55
+ stripe_customer_id: string | null;
56
+ }, never, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
57
+ /**
58
+ * Soft-delete marker: set `deletedAt`. Hard-delete happens in
59
+ * `scripts/purge-deleted-users.ts`.
60
+ */
61
+ softDelete(id: string): Prisma.Prisma__UserClient<{
62
+ name: string | null;
63
+ id: string;
64
+ email: string | null;
65
+ emailVerified: Date | null;
66
+ passwordHash: string | null;
67
+ createdAt: Date;
68
+ updatedAt: Date;
69
+ fileAssetId: string | null;
70
+ roleId: string | null;
71
+ deletedAt: Date | null;
72
+ stripe_customer_id: string | null;
73
+ }, never, import("@prisma/client/runtime/library").DefaultArgs, Prisma.PrismaClientOptions>;
74
+ }