@goscribe/server 1.5.0 → 1.7.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 (321) hide show
  1. package/dist/context.d.ts +14 -1
  2. package/dist/context.js +23 -2
  3. package/dist/generated/prisma/client.d.ts +224 -0
  4. package/dist/generated/prisma/client.js +34 -0
  5. package/dist/generated/prisma/commonInputTypes.d.ts +941 -0
  6. package/dist/generated/prisma/commonInputTypes.js +10 -0
  7. package/dist/generated/prisma/enums.d.ts +67 -0
  8. package/dist/generated/prisma/enums.js +66 -0
  9. package/dist/generated/prisma/internal/class.d.ts +539 -0
  10. package/dist/generated/prisma/internal/class.js +49 -0
  11. package/dist/generated/prisma/internal/prismaNamespace.d.ts +3924 -0
  12. package/dist/generated/prisma/internal/prismaNamespace.js +557 -0
  13. package/dist/generated/prisma/models/ActivityLog.d.ts +1847 -0
  14. package/dist/generated/prisma/models/ActivityLog.js +1 -0
  15. package/dist/generated/prisma/models/Artifact.d.ts +2345 -0
  16. package/dist/generated/prisma/models/Artifact.js +1 -0
  17. package/dist/generated/prisma/models/ArtifactVersion.d.ts +1550 -0
  18. package/dist/generated/prisma/models/ArtifactVersion.js +1 -0
  19. package/dist/generated/prisma/models/Channel.d.ts +1257 -0
  20. package/dist/generated/prisma/models/Channel.js +1 -0
  21. package/dist/generated/prisma/models/Chat.d.ts +1339 -0
  22. package/dist/generated/prisma/models/Chat.js +1 -0
  23. package/dist/generated/prisma/models/CopilotConversation.d.ts +1450 -0
  24. package/dist/generated/prisma/models/CopilotConversation.js +1 -0
  25. package/dist/generated/prisma/models/CopilotMessage.d.ts +1179 -0
  26. package/dist/generated/prisma/models/CopilotMessage.js +1 -0
  27. package/dist/generated/prisma/models/FileAsset.d.ts +1832 -0
  28. package/dist/generated/prisma/models/FileAsset.js +1 -0
  29. package/dist/generated/prisma/models/Flashcard.d.ts +1460 -0
  30. package/dist/generated/prisma/models/Flashcard.js +1 -0
  31. package/dist/generated/prisma/models/FlashcardProgress.d.ts +1782 -0
  32. package/dist/generated/prisma/models/FlashcardProgress.js +1 -0
  33. package/dist/generated/prisma/models/Folder.d.ts +1685 -0
  34. package/dist/generated/prisma/models/Folder.js +1 -0
  35. package/dist/generated/prisma/models/IdempotencyRecord.d.ts +1319 -0
  36. package/dist/generated/prisma/models/IdempotencyRecord.js +1 -0
  37. package/dist/generated/prisma/models/Invoice.d.ts +1586 -0
  38. package/dist/generated/prisma/models/Invoice.js +1 -0
  39. package/dist/generated/prisma/models/KnowledgeBase.d.ts +1721 -0
  40. package/dist/generated/prisma/models/KnowledgeBase.js +1 -0
  41. package/dist/generated/prisma/models/KnowledgeBaseChunk.d.ts +1333 -0
  42. package/dist/generated/prisma/models/KnowledgeBaseChunk.js +1 -0
  43. package/dist/generated/prisma/models/KnowledgeBaseDocument.d.ts +1695 -0
  44. package/dist/generated/prisma/models/KnowledgeBaseDocument.js +1 -0
  45. package/dist/generated/prisma/models/Notification.d.ts +1992 -0
  46. package/dist/generated/prisma/models/Notification.js +1 -0
  47. package/dist/generated/prisma/models/PasswordResetToken.d.ts +1210 -0
  48. package/dist/generated/prisma/models/PasswordResetToken.js +1 -0
  49. package/dist/generated/prisma/models/Plan.d.ts +1431 -0
  50. package/dist/generated/prisma/models/Plan.js +1 -0
  51. package/dist/generated/prisma/models/PlanLimit.d.ts +1328 -0
  52. package/dist/generated/prisma/models/PlanLimit.js +1 -0
  53. package/dist/generated/prisma/models/PodcastSegment.d.ts +1564 -0
  54. package/dist/generated/prisma/models/PodcastSegment.js +1 -0
  55. package/dist/generated/prisma/models/ResourcePrice.d.ts +1008 -0
  56. package/dist/generated/prisma/models/ResourcePrice.js +1 -0
  57. package/dist/generated/prisma/models/Role.d.ts +1065 -0
  58. package/dist/generated/prisma/models/Role.js +1 -0
  59. package/dist/generated/prisma/models/Session.d.ts +1105 -0
  60. package/dist/generated/prisma/models/Session.js +1 -0
  61. package/dist/generated/prisma/models/StripeEvent.d.ts +1081 -0
  62. package/dist/generated/prisma/models/StripeEvent.js +1 -0
  63. package/dist/generated/prisma/models/StudyGuideComment.d.ts +1321 -0
  64. package/dist/generated/prisma/models/StudyGuideComment.js +1 -0
  65. package/dist/generated/prisma/models/StudyGuideHighlight.d.ts +1629 -0
  66. package/dist/generated/prisma/models/StudyGuideHighlight.js +1 -0
  67. package/dist/generated/prisma/models/Subscription.d.ts +1677 -0
  68. package/dist/generated/prisma/models/Subscription.js +1 -0
  69. package/dist/generated/prisma/models/User.d.ts +7559 -0
  70. package/dist/generated/prisma/models/User.js +1 -0
  71. package/dist/generated/prisma/models/UserCredit.d.ts +1249 -0
  72. package/dist/generated/prisma/models/UserCredit.js +1 -0
  73. package/dist/generated/prisma/models/VerificationToken.d.ts +946 -0
  74. package/dist/generated/prisma/models/VerificationToken.js +1 -0
  75. package/dist/generated/prisma/models/WorksheetPreset.d.ts +1433 -0
  76. package/dist/generated/prisma/models/WorksheetPreset.js +1 -0
  77. package/dist/generated/prisma/models/WorksheetQuestion.d.ts +1491 -0
  78. package/dist/generated/prisma/models/WorksheetQuestion.js +1 -0
  79. package/dist/generated/prisma/models/WorksheetQuestionProgress.d.ts +1620 -0
  80. package/dist/generated/prisma/models/WorksheetQuestionProgress.js +1 -0
  81. package/dist/generated/prisma/models/Workspace.d.ts +3620 -0
  82. package/dist/generated/prisma/models/Workspace.js +1 -0
  83. package/dist/generated/prisma/models/WorkspaceInvitation.d.ts +1490 -0
  84. package/dist/generated/prisma/models/WorkspaceInvitation.js +1 -0
  85. package/dist/generated/prisma/models/WorkspaceKnowledgeBase.d.ts +1410 -0
  86. package/dist/generated/prisma/models/WorkspaceKnowledgeBase.js +1 -0
  87. package/dist/generated/prisma/models/WorkspaceMember.d.ts +1326 -0
  88. package/dist/generated/prisma/models/WorkspaceMember.js +1 -0
  89. package/dist/generated/prisma/models.d.ts +39 -0
  90. package/dist/generated/prisma/models.js +1 -0
  91. package/dist/lib/ai/index.d.ts +3 -2
  92. package/dist/lib/ai/index.js +3 -2
  93. package/dist/lib/ai/llm-client.d.ts +1 -0
  94. package/dist/lib/ai/llm-client.js +17 -0
  95. package/dist/routers/_app.d.ts +40 -80
  96. package/dist/routers/auth.js +1 -1
  97. package/dist/routers/flashcards.d.ts +12 -1
  98. package/dist/routers/payment.d.ts +1 -12
  99. package/dist/routers/workspace.d.ts +27 -67
  100. package/dist/routers/workspace.js +1 -0
  101. package/dist/services/billing/payment.service.d.ts +1 -12
  102. package/dist/services/billing/payment.service.js +3 -6
  103. package/dist/services/billing/usage.service.d.ts +30 -10
  104. package/dist/services/billing/usage.service.js +87 -15
  105. package/dist/services/content/copilot.service.js +15 -29
  106. package/dist/services/content/flashcard-progress.service.js +9 -9
  107. package/dist/services/content/flashcard.service.d.ts +45 -1
  108. package/dist/services/content/flashcard.service.js +81 -68
  109. package/dist/services/content/media-analysis.service.js +27 -27
  110. package/dist/services/content/worksheet-generation.service.test.js +2 -2
  111. package/dist/services/workspace/workspace.service.d.ts +23 -67
  112. package/dist/services/workspace/workspace.service.js +69 -62
  113. package/dist/src/context.d.ts +27 -0
  114. package/dist/src/context.js +33 -0
  115. package/dist/src/index.d.ts +3 -0
  116. package/dist/src/index.js +1 -0
  117. package/dist/src/lib/ai/config.d.ts +20 -0
  118. package/dist/src/lib/ai/config.js +31 -0
  119. package/dist/src/lib/ai/embedding-client.d.ts +8 -0
  120. package/dist/src/lib/ai/embedding-client.js +30 -0
  121. package/dist/src/lib/ai/index.d.ts +48 -0
  122. package/dist/src/lib/ai/index.js +29 -0
  123. package/dist/src/lib/ai/inference-backend/client.d.ts +28 -0
  124. package/dist/src/lib/ai/inference-backend/client.js +301 -0
  125. package/dist/src/lib/ai/inference-backend/mocks.d.ts +12 -0
  126. package/dist/src/lib/ai/inference-backend/mocks.js +133 -0
  127. package/dist/src/lib/ai/inference-backend/types.d.ts +44 -0
  128. package/dist/src/lib/ai/inference-backend/types.js +1 -0
  129. package/dist/src/lib/ai/json-parse.d.ts +2 -0
  130. package/dist/src/lib/ai/json-parse.js +34 -0
  131. package/dist/src/lib/ai/llm-client.d.ts +7 -0
  132. package/dist/src/lib/ai/llm-client.js +36 -0
  133. package/dist/src/lib/ai/mock.d.ts +2 -0
  134. package/dist/src/lib/ai/mock.js +10 -0
  135. package/dist/src/lib/ai/types.d.ts +9 -0
  136. package/dist/src/lib/ai/types.js +1 -0
  137. package/dist/src/lib/auth.d.ts +36 -0
  138. package/dist/src/lib/auth.js +117 -0
  139. package/dist/src/lib/chunking.d.ts +19 -0
  140. package/dist/src/lib/chunking.js +47 -0
  141. package/dist/src/lib/constants.d.ts +13 -0
  142. package/dist/src/lib/constants.js +12 -0
  143. package/dist/src/lib/curated-kb-seed.d.ts +12 -0
  144. package/dist/src/lib/curated-kb-seed.js +155 -0
  145. package/dist/src/lib/email.d.ts +11 -0
  146. package/dist/src/lib/email.js +152 -0
  147. package/dist/src/lib/embeddings.d.ts +2 -0
  148. package/dist/src/lib/embeddings.js +1 -0
  149. package/dist/src/lib/ensure-curated-kb-catalog.d.ts +6 -0
  150. package/dist/src/lib/ensure-curated-kb-catalog.js +53 -0
  151. package/dist/src/lib/env.d.ts +41 -0
  152. package/dist/src/lib/env.js +57 -0
  153. package/dist/src/lib/errors.d.ts +33 -0
  154. package/dist/src/lib/errors.js +78 -0
  155. package/dist/src/lib/file.d.ts +0 -0
  156. package/dist/src/lib/file.js +1 -0
  157. package/dist/src/lib/inference.d.ts +1 -0
  158. package/dist/src/lib/inference.js +1 -0
  159. package/dist/src/lib/kb-meta.d.ts +8 -0
  160. package/dist/src/lib/kb-meta.js +77 -0
  161. package/dist/src/lib/logger.d.ts +62 -0
  162. package/dist/src/lib/logger.js +364 -0
  163. package/dist/src/lib/pdf.d.ts +11 -0
  164. package/dist/src/lib/pdf.js +11 -0
  165. package/dist/src/lib/prisma.d.ts +3 -0
  166. package/dist/src/lib/prisma.js +15 -0
  167. package/dist/src/lib/pusher.d.ts +38 -0
  168. package/dist/src/lib/pusher.js +170 -0
  169. package/dist/src/lib/retry.d.ts +15 -0
  170. package/dist/src/lib/retry.js +37 -0
  171. package/dist/src/lib/storage.d.ts +11 -0
  172. package/dist/src/lib/storage.js +71 -0
  173. package/dist/src/lib/stripe.d.ts +10 -0
  174. package/dist/src/lib/stripe.js +36 -0
  175. package/dist/src/lib/validation.d.ts +51 -0
  176. package/dist/src/lib/validation.js +64 -0
  177. package/dist/src/lib/workspace-kb.d.ts +5 -0
  178. package/dist/src/lib/workspace-kb.js +7 -0
  179. package/dist/src/repositories/artifact.repository.d.ts +64 -0
  180. package/dist/src/repositories/artifact.repository.js +40 -0
  181. package/dist/src/repositories/base.repository.d.ts +14 -0
  182. package/dist/src/repositories/base.repository.js +14 -0
  183. package/dist/src/repositories/invitation.repository.d.ts +104 -0
  184. package/dist/src/repositories/invitation.repository.js +44 -0
  185. package/dist/src/repositories/notification.repository.d.ts +76 -0
  186. package/dist/src/repositories/notification.repository.js +44 -0
  187. package/dist/src/repositories/user.repository.d.ts +84 -0
  188. package/dist/src/repositories/user.repository.js +37 -0
  189. package/dist/src/repositories/workspace-member.repository.d.ts +35 -0
  190. package/dist/src/repositories/workspace-member.repository.js +31 -0
  191. package/dist/src/repositories/workspace.repository.d.ts +101 -0
  192. package/dist/src/repositories/workspace.repository.js +79 -0
  193. package/dist/src/routers/_app.d.ts +3464 -0
  194. package/dist/src/routers/_app.js +36 -0
  195. package/dist/src/routers/admin.d.ts +358 -0
  196. package/dist/src/routers/admin.js +105 -0
  197. package/dist/src/routers/annotations.d.ts +219 -0
  198. package/dist/src/routers/annotations.js +29 -0
  199. package/dist/src/routers/artifactVersions.d.ts +65 -0
  200. package/dist/src/routers/artifactVersions.js +14 -0
  201. package/dist/src/routers/auth.d.ts +161 -0
  202. package/dist/src/routers/auth.js +97 -0
  203. package/dist/src/routers/chat.d.ts +170 -0
  204. package/dist/src/routers/chat.js +32 -0
  205. package/dist/src/routers/copilot.d.ts +200 -0
  206. package/dist/src/routers/copilot.js +52 -0
  207. package/dist/src/routers/flashcards.d.ts +336 -0
  208. package/dist/src/routers/flashcards.js +93 -0
  209. package/dist/src/routers/knowledgeBase.d.ts +421 -0
  210. package/dist/src/routers/knowledgeBase.js +118 -0
  211. package/dist/src/routers/members.d.ts +169 -0
  212. package/dist/src/routers/members.js +47 -0
  213. package/dist/src/routers/notifications.d.ts +99 -0
  214. package/dist/src/routers/notifications.js +25 -0
  215. package/dist/src/routers/payment.d.ts +80 -0
  216. package/dist/src/routers/payment.js +21 -0
  217. package/dist/src/routers/podcast.d.ts +287 -0
  218. package/dist/src/routers/podcast.js +34 -0
  219. package/dist/src/routers/studyguide.d.ts +36 -0
  220. package/dist/src/routers/studyguide.js +8 -0
  221. package/dist/src/routers/worksheets.d.ts +429 -0
  222. package/dist/src/routers/worksheets.js +139 -0
  223. package/dist/src/routers/workspace.d.ts +563 -0
  224. package/dist/src/routers/workspace.js +104 -0
  225. package/dist/src/scripts/purge-deleted-users.d.ts +1 -0
  226. package/dist/src/scripts/purge-deleted-users.js +148 -0
  227. package/dist/src/server.d.ts +1 -0
  228. package/dist/src/server.js +190 -0
  229. package/dist/src/services/activity/activity-human-description.service.d.ts +13 -0
  230. package/dist/src/services/activity/activity-human-description.service.js +221 -0
  231. package/dist/src/services/activity/activity-human-description.service.test.d.ts +1 -0
  232. package/dist/src/services/activity/activity-human-description.service.test.js +16 -0
  233. package/dist/src/services/activity/activity-log.service.d.ts +87 -0
  234. package/dist/src/services/activity/activity-log.service.js +276 -0
  235. package/dist/src/services/activity/activity-log.service.test.d.ts +1 -0
  236. package/dist/src/services/activity/activity-log.service.test.js +27 -0
  237. package/dist/src/services/admin/admin.service.d.ts +270 -0
  238. package/dist/src/services/admin/admin.service.js +476 -0
  239. package/dist/src/services/ai/ai-session.service.d.ts +5 -0
  240. package/dist/src/services/ai/ai-session.service.js +4 -0
  241. package/dist/src/services/artifacts/annotation.service.d.ts +177 -0
  242. package/dist/src/services/artifacts/annotation.service.js +154 -0
  243. package/dist/src/services/artifacts/artifact-version.service.d.ts +38 -0
  244. package/dist/src/services/artifacts/artifact-version.service.js +129 -0
  245. package/dist/src/services/artifacts/chat.service.d.ts +127 -0
  246. package/dist/src/services/artifacts/chat.service.js +182 -0
  247. package/dist/src/services/artifacts/study-guide.service.d.ts +18 -0
  248. package/dist/src/services/artifacts/study-guide.service.js +65 -0
  249. package/dist/src/services/auth/auth.service.d.ts +94 -0
  250. package/dist/src/services/auth/auth.service.js +368 -0
  251. package/dist/src/services/base.service.d.ts +14 -0
  252. package/dist/src/services/base.service.js +14 -0
  253. package/dist/src/services/billing/payment.service.d.ts +44 -0
  254. package/dist/src/services/billing/payment.service.js +365 -0
  255. package/dist/src/services/billing/subscription.service.d.ts +37 -0
  256. package/dist/src/services/billing/subscription.service.js +654 -0
  257. package/dist/src/services/billing/usage.service.d.ts +47 -0
  258. package/dist/src/services/billing/usage.service.js +149 -0
  259. package/dist/src/services/content/copilot.service.d.ts +113 -0
  260. package/dist/src/services/content/copilot.service.js +439 -0
  261. package/dist/src/services/content/flashcard-progress.service.d.ts +159 -0
  262. package/dist/src/services/content/flashcard-progress.service.js +432 -0
  263. package/dist/src/services/content/flashcard.service.d.ts +184 -0
  264. package/dist/src/services/content/flashcard.service.js +339 -0
  265. package/dist/src/services/content/media-analysis.service.d.ts +23 -0
  266. package/dist/src/services/content/media-analysis.service.js +404 -0
  267. package/dist/src/services/content/podcast.service.d.ts +267 -0
  268. package/dist/src/services/content/podcast.service.js +653 -0
  269. package/dist/src/services/content/worksheet-content.service.d.ts +37 -0
  270. package/dist/src/services/content/worksheet-content.service.js +84 -0
  271. package/dist/src/services/content/worksheet-content.service.test.d.ts +1 -0
  272. package/dist/src/services/content/worksheet-content.service.test.js +69 -0
  273. package/dist/src/services/content/worksheet-generation.service.d.ts +91 -0
  274. package/dist/src/services/content/worksheet-generation.service.js +95 -0
  275. package/dist/src/services/content/worksheet-generation.service.test.d.ts +1 -0
  276. package/dist/src/services/content/worksheet-generation.service.test.js +20 -0
  277. package/dist/src/services/content/worksheet.service.d.ts +347 -0
  278. package/dist/src/services/content/worksheet.service.js +599 -0
  279. package/dist/src/services/knowledge/knowledge-base.service.d.ts +316 -0
  280. package/dist/src/services/knowledge/knowledge-base.service.js +544 -0
  281. package/dist/src/services/members/invitation.service.d.ts +66 -0
  282. package/dist/src/services/members/invitation.service.js +348 -0
  283. package/dist/src/services/members/member.service.d.ts +36 -0
  284. package/dist/src/services/members/member.service.js +193 -0
  285. package/dist/src/services/notifications/notification.service.d.ts +214 -0
  286. package/dist/src/services/notifications/notification.service.js +550 -0
  287. package/dist/src/services/notifications/notification.service.test.d.ts +1 -0
  288. package/dist/src/services/notifications/notification.service.test.js +87 -0
  289. package/dist/src/services/workspace/workspace-analytics.service.d.ts +24 -0
  290. package/dist/src/services/workspace/workspace-analytics.service.js +95 -0
  291. package/dist/src/services/workspace/workspace-kb.service.d.ts +40 -0
  292. package/dist/src/services/workspace/workspace-kb.service.js +184 -0
  293. package/dist/src/services/workspace/workspace.service.d.ts +263 -0
  294. package/dist/src/services/workspace/workspace.service.js +401 -0
  295. package/dist/src/trpc.d.ts +60 -0
  296. package/dist/src/trpc.js +217 -0
  297. package/dist/src/types/index.d.ts +126 -0
  298. package/dist/src/types/index.js +1 -0
  299. package/dist/trpc.d.ts +12 -4
  300. package/dist/trpc.js +5 -11
  301. package/package.json +8 -9
  302. package/prisma/schema.prisma +3 -4
  303. package/prisma/seed.mjs +5 -2
  304. package/prisma.config.ts +16 -0
  305. package/src/context.ts +33 -3
  306. package/src/lib/ai/index.ts +3 -0
  307. package/src/lib/ai/llm-client.ts +23 -0
  308. package/src/lib/prisma.ts +18 -9
  309. package/src/routers/auth.ts +1 -1
  310. package/src/routers/workspace.ts +4 -0
  311. package/src/scripts/purge-deleted-users.ts +1 -3
  312. package/src/services/billing/payment.service.ts +3 -6
  313. package/src/services/billing/usage.service.ts +190 -77
  314. package/src/services/content/copilot.service.ts +23 -32
  315. package/src/services/content/flashcard-progress.service.ts +12 -9
  316. package/src/services/content/flashcard.service.ts +89 -66
  317. package/src/services/content/media-analysis.service.ts +34 -29
  318. package/src/services/content/worksheet-generation.service.test.ts +2 -2
  319. package/src/services/workspace/workspace.service.ts +73 -66
  320. package/src/trpc.ts +5 -13
  321. package/tsconfig.json +3 -0
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Authentication utilities for custom HMAC-based cookie verification.
3
+ *
4
+ * This module provides secure authentication using HMAC-SHA256 signatures
5
+ * to verify user identity through signed cookies.
6
+ *
7
+ * @fileoverview Custom authentication system with HMAC cookie verification
8
+ * @author Scribe Team
9
+ * @version 1.0.0
10
+ */
11
+ import crypto from "node:crypto";
12
+ /**
13
+ * Verifies a custom HMAC-signed authentication cookie.
14
+ *
15
+ * The cookie format is: `base64(userId).hex(hmacSHA256(base64(userId), secret))`
16
+ *
17
+ * @param cookieValue - The raw cookie value to verify, or undefined if no cookie exists
18
+ * @returns Authentication result with userId if valid, null if invalid or missing
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const result = verifyCustomAuthCookie("dXNlcjEyMw.abc123def456...");
23
+ * if (result) {
24
+ * console.log(`Authenticated user: ${result.userId}`);
25
+ * }
26
+ * ```
27
+ *
28
+ * @throws {Error} Never throws - returns null for all error conditions
29
+ */
30
+ export function verifyCustomAuthCookie(cookieValue) {
31
+ // Early return for missing cookie
32
+ if (!cookieValue) {
33
+ return null;
34
+ }
35
+ // Get authentication secret from environment
36
+ const secret = process.env.AUTH_SECRET;
37
+ if (!secret) {
38
+ return null;
39
+ }
40
+ // Parse cookie format: base64UserId.signatureHex
41
+ const parts = cookieValue.split(".");
42
+ if (parts.length !== 2) {
43
+ return null;
44
+ }
45
+ const [base64UserId, signatureHex] = parts;
46
+ // Decode the user ID from base64url encoding
47
+ const userId = decodeBase64UrlUserId(base64UserId);
48
+ if (!userId) {
49
+ return null;
50
+ }
51
+ // Verify the HMAC signature
52
+ const isValidSignature = verifyHmacSignature(base64UserId, signatureHex, secret);
53
+ if (!isValidSignature) {
54
+ return null;
55
+ }
56
+ return { userId };
57
+ }
58
+ /**
59
+ * Decodes a base64url-encoded user ID string.
60
+ *
61
+ * @param base64UserId - The base64url-encoded user ID
62
+ * @returns The decoded user ID string, or null if decoding fails
63
+ *
64
+ * @private
65
+ */
66
+ function decodeBase64UrlUserId(base64UserId) {
67
+ try {
68
+ const buffer = Buffer.from(base64UserId, "base64url");
69
+ return buffer.toString("utf8");
70
+ }
71
+ catch (error) {
72
+ return null;
73
+ }
74
+ }
75
+ /**
76
+ * Verifies an HMAC-SHA256 signature against the expected value.
77
+ *
78
+ * @param data - The data that was signed (base64url-encoded user ID)
79
+ * @param signatureHex - The hex-encoded signature to verify
80
+ * @param secret - The secret key used for signing
81
+ * @returns True if the signature is valid, false otherwise
82
+ *
83
+ * @private
84
+ */
85
+ function verifyHmacSignature(data, signatureHex, secret) {
86
+ const hmac = crypto.createHmac("sha256", secret);
87
+ hmac.update(data);
88
+ const expectedSignature = hmac.digest("hex");
89
+ return timingSafeEqualHex(signatureHex, expectedSignature);
90
+ }
91
+ /**
92
+ * Performs a timing-safe comparison of two hex-encoded strings.
93
+ *
94
+ * This function prevents timing attacks by ensuring the comparison
95
+ * takes the same amount of time regardless of where the strings differ.
96
+ *
97
+ * @param a - First hex string to compare
98
+ * @param b - Second hex string to compare
99
+ * @returns True if the strings are equal, false otherwise
100
+ *
101
+ * @private
102
+ */
103
+ function timingSafeEqualHex(a, b) {
104
+ try {
105
+ const bufferA = Buffer.from(a, "hex");
106
+ const bufferB = Buffer.from(b, "hex");
107
+ // Length check prevents timing attacks on different-length inputs
108
+ if (bufferA.length !== bufferB.length) {
109
+ return false;
110
+ }
111
+ return crypto.timingSafeEqual(bufferA, bufferB);
112
+ }
113
+ catch {
114
+ // Return false for any parsing errors
115
+ return false;
116
+ }
117
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Approximate text chunker for RAG indexing.
3
+ *
4
+ * Splits a long document into overlapping windows aimed at a target token
5
+ * count. We don't have a tokenizer dependency, so we approximate using
6
+ * `chars / 4` (a rule of thumb that matches GPT-style BPE within ~10-20%).
7
+ * Chunk boundaries snap to paragraph / sentence breaks when possible so we
8
+ * don't slice mid-thought.
9
+ */
10
+ export interface ChunkOptions {
11
+ targetTokens?: number;
12
+ overlapTokens?: number;
13
+ }
14
+ export interface Chunk {
15
+ index: number;
16
+ content: string;
17
+ approxTokens: number;
18
+ }
19
+ export declare function chunkText(text: string, opts?: ChunkOptions): Chunk[];
@@ -0,0 +1,47 @@
1
+ const CHARS_PER_TOKEN = 4;
2
+ export function chunkText(text, opts = {}) {
3
+ const targetTokens = opts.targetTokens ?? 500;
4
+ const overlapTokens = opts.overlapTokens ?? 60;
5
+ const targetChars = targetTokens * CHARS_PER_TOKEN;
6
+ const overlapChars = overlapTokens * CHARS_PER_TOKEN;
7
+ const cleaned = text.replace(/\r\n/g, '\n').replace(/[ \t]+/g, ' ').trim();
8
+ if (!cleaned)
9
+ return [];
10
+ const chunks = [];
11
+ let cursor = 0;
12
+ let index = 0;
13
+ while (cursor < cleaned.length) {
14
+ const hardEnd = Math.min(cleaned.length, cursor + targetChars);
15
+ let end = hardEnd;
16
+ if (hardEnd < cleaned.length) {
17
+ // Prefer a paragraph break, then a sentence break, then a space.
18
+ const window = cleaned.slice(cursor, hardEnd);
19
+ const lastPara = window.lastIndexOf('\n\n');
20
+ const lastSentence = Math.max(window.lastIndexOf('. '), window.lastIndexOf('! '), window.lastIndexOf('? '), window.lastIndexOf('.\n'));
21
+ const lastSpace = window.lastIndexOf(' ');
22
+ const minBreak = Math.floor(targetChars * 0.5);
23
+ if (lastPara >= minBreak) {
24
+ end = cursor + lastPara + 2;
25
+ }
26
+ else if (lastSentence >= minBreak) {
27
+ end = cursor + lastSentence + 2;
28
+ }
29
+ else if (lastSpace >= minBreak) {
30
+ end = cursor + lastSpace + 1;
31
+ }
32
+ }
33
+ const piece = cleaned.slice(cursor, end).trim();
34
+ if (piece) {
35
+ chunks.push({
36
+ index,
37
+ content: piece,
38
+ approxTokens: Math.max(1, Math.round(piece.length / CHARS_PER_TOKEN)),
39
+ });
40
+ index += 1;
41
+ }
42
+ if (end >= cleaned.length)
43
+ break;
44
+ cursor = Math.max(end - overlapChars, cursor + 1);
45
+ }
46
+ return chunks;
47
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Shared constants for artifact types.
3
+ * Mirrors the Prisma ArtifactType enum to avoid direct type imports
4
+ * in contexts where Prisma client types may not be available.
5
+ */
6
+ export declare const ArtifactType: {
7
+ readonly STUDY_GUIDE: "STUDY_GUIDE";
8
+ readonly FLASHCARD_SET: "FLASHCARD_SET";
9
+ readonly WORKSHEET: "WORKSHEET";
10
+ readonly MEETING_SUMMARY: "MEETING_SUMMARY";
11
+ readonly PODCAST_EPISODE: "PODCAST_EPISODE";
12
+ };
13
+ export type ArtifactTypeValue = (typeof ArtifactType)[keyof typeof ArtifactType];
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Shared constants for artifact types.
3
+ * Mirrors the Prisma ArtifactType enum to avoid direct type imports
4
+ * in contexts where Prisma client types may not be available.
5
+ */
6
+ export const ArtifactType = {
7
+ STUDY_GUIDE: 'STUDY_GUIDE',
8
+ FLASHCARD_SET: 'FLASHCARD_SET',
9
+ WORKSHEET: 'WORKSHEET',
10
+ MEETING_SUMMARY: 'MEETING_SUMMARY',
11
+ PODCAST_EPISODE: 'PODCAST_EPISODE',
12
+ };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Curated AP & IB knowledge bases seeded on server startup.
3
+ * Each entry uses a stable slug in `meta` so the client can pick icons/colors.
4
+ */
5
+ export interface CuratedKbSeed {
6
+ slug: string;
7
+ name: string;
8
+ description: string;
9
+ category: 'AP' | 'IB';
10
+ subject: string;
11
+ }
12
+ export declare const CURATED_KB_SEEDS: CuratedKbSeed[];
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Curated AP & IB knowledge bases seeded on server startup.
3
+ * Each entry uses a stable slug in `meta` so the client can pick icons/colors.
4
+ */
5
+ export const CURATED_KB_SEEDS = [
6
+ // ── AP ──────────────────────────────────────────────────────────
7
+ {
8
+ slug: 'ap-biology',
9
+ name: 'AP Biology',
10
+ description: 'Cell biology, genetics, evolution, and ecology aligned with the AP Biology curriculum.',
11
+ category: 'AP',
12
+ subject: 'biology',
13
+ },
14
+ {
15
+ slug: 'ap-chemistry',
16
+ name: 'AP Chemistry',
17
+ description: 'Atomic structure, bonding, thermodynamics, and kinetics for AP Chemistry.',
18
+ category: 'AP',
19
+ subject: 'chemistry',
20
+ },
21
+ {
22
+ slug: 'ap-physics-1',
23
+ name: 'AP Physics 1',
24
+ description: 'Algebra-based mechanics, waves, and electricity for AP Physics 1.',
25
+ category: 'AP',
26
+ subject: 'physics',
27
+ },
28
+ {
29
+ slug: 'ap-calculus-ab',
30
+ name: 'AP Calculus AB',
31
+ description: 'Limits, derivatives, integrals, and the Fundamental Theorem of Calculus.',
32
+ category: 'AP',
33
+ subject: 'calculus',
34
+ },
35
+ {
36
+ slug: 'ap-calculus-bc',
37
+ name: 'AP Calculus BC',
38
+ description: 'Series, parametric equations, polar coordinates, and advanced integration.',
39
+ category: 'AP',
40
+ subject: 'calculus',
41
+ },
42
+ {
43
+ slug: 'ap-us-history',
44
+ name: 'AP US History',
45
+ description: 'Colonial America through the modern era with primary source analysis.',
46
+ category: 'AP',
47
+ subject: 'history',
48
+ },
49
+ {
50
+ slug: 'ap-world-history',
51
+ name: 'AP World History',
52
+ description: 'Global civilizations, trade networks, and historical thinking skills.',
53
+ category: 'AP',
54
+ subject: 'history',
55
+ },
56
+ {
57
+ slug: 'ap-english-lang',
58
+ name: 'AP English Language',
59
+ description: 'Rhetorical analysis, argumentation, and synthesis writing strategies.',
60
+ category: 'AP',
61
+ subject: 'english',
62
+ },
63
+ {
64
+ slug: 'ap-english-lit',
65
+ name: 'AP English Literature',
66
+ description: 'Literary analysis, poetry, prose fiction, and critical essay writing.',
67
+ category: 'AP',
68
+ subject: 'literature',
69
+ },
70
+ {
71
+ slug: 'ap-psychology',
72
+ name: 'AP Psychology',
73
+ description: 'Biological bases of behavior, cognition, development, and social psychology.',
74
+ category: 'AP',
75
+ subject: 'psychology',
76
+ },
77
+ {
78
+ slug: 'ap-environmental-science',
79
+ name: 'AP Environmental Science',
80
+ description: 'Ecosystems, biodiversity, pollution, and sustainability concepts.',
81
+ category: 'AP',
82
+ subject: 'environmental',
83
+ },
84
+ {
85
+ slug: 'ap-macroeconomics',
86
+ name: 'AP Macroeconomics',
87
+ description: 'GDP, inflation, fiscal and monetary policy, and international trade.',
88
+ category: 'AP',
89
+ subject: 'economics',
90
+ },
91
+ // ── IB ──────────────────────────────────────────────────────────
92
+ {
93
+ slug: 'ib-biology-hl',
94
+ name: 'IB Biology HL',
95
+ description: 'Higher Level biology: molecular biology, genetics, ecology, and human physiology.',
96
+ category: 'IB',
97
+ subject: 'biology',
98
+ },
99
+ {
100
+ slug: 'ib-chemistry-hl',
101
+ name: 'IB Chemistry HL',
102
+ description: 'Higher Level chemistry: organic, inorganic, physical, and analytical topics.',
103
+ category: 'IB',
104
+ subject: 'chemistry',
105
+ },
106
+ {
107
+ slug: 'ib-physics-hl',
108
+ name: 'IB Physics HL',
109
+ description: 'Higher Level physics: mechanics, fields, waves, and nuclear physics.',
110
+ category: 'IB',
111
+ subject: 'physics',
112
+ },
113
+ {
114
+ slug: 'ib-math-aa-hl',
115
+ name: 'IB Math AA HL',
116
+ description: 'Analysis & Approaches HL: calculus, proof, vectors, and complex numbers.',
117
+ category: 'IB',
118
+ subject: 'math',
119
+ },
120
+ {
121
+ slug: 'ib-math-ai-hl',
122
+ name: 'IB Math AI HL',
123
+ description: 'Applications & Interpretation HL: statistics, modelling, and technology use.',
124
+ category: 'IB',
125
+ subject: 'math',
126
+ },
127
+ {
128
+ slug: 'ib-history-hl',
129
+ name: 'IB History HL',
130
+ description: 'Higher Level history: 20th century world history and historical investigation.',
131
+ category: 'IB',
132
+ subject: 'history',
133
+ },
134
+ {
135
+ slug: 'ib-english-a-hl',
136
+ name: 'IB English A HL',
137
+ description: 'Language & Literature HL: textual analysis, comparative study, and IO prep.',
138
+ category: 'IB',
139
+ subject: 'literature',
140
+ },
141
+ {
142
+ slug: 'ib-economics-hl',
143
+ name: 'IB Economics HL',
144
+ description: 'Microeconomics, macroeconomics, international economics, and development.',
145
+ category: 'IB',
146
+ subject: 'economics',
147
+ },
148
+ {
149
+ slug: 'ib-psychology-hl',
150
+ name: 'IB Psychology HL',
151
+ description: 'Biological, cognitive, sociocultural, and abnormal psychology at HL depth.',
152
+ category: 'IB',
153
+ subject: 'psychology',
154
+ },
155
+ ];
@@ -0,0 +1,11 @@
1
+ export declare function sendVerificationEmail(email: string, token: string, name?: string | null): Promise<boolean>;
2
+ export declare function sendInvitationEmail(invitation: {
3
+ email: string;
4
+ token: string;
5
+ role: string;
6
+ workspaceTitle: string;
7
+ invitedByName: string;
8
+ }): Promise<boolean>;
9
+ export declare function sendAccountDeletionScheduledEmail(email: string, token: string): Promise<boolean>;
10
+ export declare function sendPasswordResetEmail(email: string, token: string, name?: string | null): Promise<boolean>;
11
+ export declare function sendAccountRestoredEmail(email: string): Promise<boolean>;
@@ -0,0 +1,152 @@
1
+ import { Resend } from 'resend';
2
+ import { logger } from './logger.js';
3
+ import { env } from './env.js';
4
+ const resend = env.RESEND_API_KEY ? new Resend(env.RESEND_API_KEY) : null;
5
+ const FROM_EMAIL = env.EMAIL_FROM;
6
+ const APP_URL = env.FRONTEND_URL;
7
+ async function sendEmail(options) {
8
+ try {
9
+ if (!resend) {
10
+ logger.warn(`${options.missingConfigLog} Logging instead:`);
11
+ logger.info(options.devLogDetail);
12
+ return true;
13
+ }
14
+ const { data, error } = await resend.emails.send({
15
+ from: FROM_EMAIL,
16
+ to: options.to,
17
+ subject: options.subject,
18
+ html: options.html,
19
+ });
20
+ if (error) {
21
+ logger.error('Email send error:', error);
22
+ return false;
23
+ }
24
+ logger.info(options.successLog + (data?.id ? ` (id: ${data.id})` : ''));
25
+ return true;
26
+ }
27
+ catch (err) {
28
+ logger.error('Email send error:', err);
29
+ return false;
30
+ }
31
+ }
32
+ export async function sendVerificationEmail(email, token, name) {
33
+ const verifyUrl = `${APP_URL}/verify-email?token=${token}`;
34
+ const greeting = name ? `, ${name}` : '';
35
+ const html = `
36
+ <div style="font-family:system-ui,sans-serif;max-width:480px;margin:0 auto;padding:40px 20px;">
37
+ <h2 style="font-size:20px;font-weight:600;margin-bottom:8px;">Welcome to Scribe${greeting}!</h2>
38
+ <p style="color:#6b7280;font-size:14px;line-height:1.6;margin-bottom:24px;">
39
+ Please verify your email address to get the most out of your account.
40
+ </p>
41
+ <a href="${verifyUrl}" style="display:inline-block;background-color:#7c3aed;color:#fff;text-decoration:none;padding:10px 24px;border-radius:6px;font-size:14px;font-weight:500;">Verify Email</a>
42
+ <p style="color:#9ca3af;font-size:12px;margin-top:32px;line-height:1.5;">
43
+ If you did not create an account on Scribe, you can safely ignore this email.
44
+ This link expires in 24 hours.
45
+ </p>
46
+ </div>
47
+ `;
48
+ return sendEmail({
49
+ to: email,
50
+ subject: 'Verify your email - Scribe',
51
+ html,
52
+ successLog: `Verification email sent to ${email}`,
53
+ missingConfigLog: 'Email service not configured (RESEND_API_KEY missing).',
54
+ devLogDetail: `Verification Email to ${email}: ${verifyUrl}`,
55
+ });
56
+ }
57
+ export async function sendInvitationEmail(invitation) {
58
+ const inviteUrl = `${APP_URL}/accept-invite?token=${invitation.token}`;
59
+ const html = `
60
+ <div style="font-family:system-ui,sans-serif;max-width:480px;margin:0 auto;padding:40px 20px;">
61
+ <h2 style="font-size:20px;font-weight:600;margin-bottom:8px;">Workspace Invitation</h2>
62
+ <p style="color:#374151;font-size:14px;line-height:1.6;margin-bottom:16px;">
63
+ <strong>${invitation.invitedByName}</strong> has invited you to join the <strong>${invitation.workspaceTitle}</strong> workspace as a <strong>${invitation.role}</strong>.
64
+ </p>
65
+ <p style="color:#6b7280;font-size:14px;line-height:1.6;margin-bottom:24px;">
66
+ Click the button below to accept the invitation and start collaborating.
67
+ </p>
68
+ <a href="${inviteUrl}" style="display:inline-block;background-color:#7c3aed;color:#fff;text-decoration:none;padding:10px 24px;border-radius:6px;font-size:14px;font-weight:500;">Accept Invitation</a>
69
+ <p style="color:#9ca3af;font-size:12px;margin-top:32px;line-height:1.5;">
70
+ This invitation was sent to ${invitation.email}. If you weren't expecting this invitation, you can safely ignore this email.
71
+ </p>
72
+ </div>
73
+ `;
74
+ return sendEmail({
75
+ to: invitation.email,
76
+ subject: `Invitation to join ${invitation.workspaceTitle} on Scribe`,
77
+ html,
78
+ successLog: `Invitation email sent to ${invitation.email}`,
79
+ missingConfigLog: 'Email service not configured (RESEND_API_KEY missing).',
80
+ devLogDetail: `Invitation Link for ${invitation.email}: ${inviteUrl}`,
81
+ });
82
+ }
83
+ export async function sendAccountDeletionScheduledEmail(email, token) {
84
+ const restoreUrl = `${APP_URL}/restore-account?token=${token}`;
85
+ const html = `
86
+ <div style="font-family:system-ui,sans-serif;max-width:480px;margin:0 auto;padding:40px 20px;">
87
+ <h2 style="font-size:20px;font-weight:600;margin-bottom:8px;color:#dc2626;">Account Deletion Scheduled</h2>
88
+ <p style="color:#374151;font-size:14px;line-height:1.6;margin-bottom:16px;">
89
+ Your account is scheduled for permanent deletion in 30 days.
90
+ </p>
91
+ <p style="color:#6b7280;font-size:14px;line-height:1.6;margin-bottom:24px;">
92
+ If you change your mind, you can restore your account by clicking the button below. This link will remain active during the 30-day grace period.
93
+ </p>
94
+ <a href="${restoreUrl}" style="display:inline-block;background-color:#7c3aed;color:#fff;text-decoration:none;padding:10px 24px;border-radius:6px;font-size:14px;font-weight:500;">Restore Account</a>
95
+ <p style="color:#9ca3af;font-size:12px;margin-top:32px;line-height:1.5;">
96
+ If you meant to delete your account, you can safely ignore this email.
97
+ </p>
98
+ </div>
99
+ `;
100
+ return sendEmail({
101
+ to: email,
102
+ subject: 'Account Deletion Scheduled - Scribe',
103
+ html,
104
+ successLog: `Account deletion scheduled email sent to ${email}`,
105
+ missingConfigLog: 'Email service not configured (RESEND_API_KEY missing).',
106
+ devLogDetail: `Account Deletion Scheduled Email to ${email}: ${restoreUrl}`,
107
+ });
108
+ }
109
+ export async function sendPasswordResetEmail(email, token, name) {
110
+ const resetUrl = `${APP_URL}/reset-password?token=${encodeURIComponent(token)}`;
111
+ const greeting = name ? `, ${name}` : '';
112
+ const html = `
113
+ <div style="font-family:system-ui,sans-serif;max-width:480px;margin:0 auto;padding:40px 20px;">
114
+ <h2 style="font-size:20px;font-weight:600;margin-bottom:8px;">Reset your password${greeting}</h2>
115
+ <p style="color:#6b7280;font-size:14px;line-height:1.6;margin-bottom:24px;">
116
+ We received a request to reset your Scribe password. Click the button below to choose a new password.
117
+ </p>
118
+ <a href="${resetUrl}" style="display:inline-block;background-color:#7c3aed;color:#fff;text-decoration:none;padding:10px 24px;border-radius:6px;font-size:14px;font-weight:500;">Reset password</a>
119
+ <p style="color:#9ca3af;font-size:12px;margin-top:32px;line-height:1.5;">
120
+ If you did not request this, you can ignore this email. This link expires in 1 hour.
121
+ </p>
122
+ </div>
123
+ `;
124
+ return sendEmail({
125
+ to: email,
126
+ subject: 'Reset your password - Scribe',
127
+ html,
128
+ successLog: `Password reset email sent to ${email}`,
129
+ missingConfigLog: 'Email service not configured (RESEND_API_KEY missing).',
130
+ devLogDetail: `Password reset for ${email}: ${resetUrl}`,
131
+ });
132
+ }
133
+ export async function sendAccountRestoredEmail(email) {
134
+ const loginUrl = `${APP_URL}/login`;
135
+ const html = `
136
+ <div style="font-family:system-ui,sans-serif;max-width:480px;margin:0 auto;padding:40px 20px;">
137
+ <h2 style="font-size:20px;font-weight:600;margin-bottom:8px;color:#16a34a;">Account Restored Successfully</h2>
138
+ <p style="color:#374151;font-size:14px;line-height:1.6;margin-bottom:16px;">
139
+ Your account has been successfully restored. Your data is safe and your account deletion process has been cancelled.
140
+ </p>
141
+ <a href="${loginUrl}" style="display:inline-block;background-color:#7c3aed;color:#fff;text-decoration:none;padding:10px 24px;border-radius:6px;font-size:14px;font-weight:500;">Log In</a>
142
+ </div>
143
+ `;
144
+ return sendEmail({
145
+ to: email,
146
+ subject: 'Account Restored - Scribe',
147
+ html,
148
+ successLog: `Account restored email sent to ${email}`,
149
+ missingConfigLog: 'Email service not configured (RESEND_API_KEY missing).',
150
+ devLogDetail: `Account Restored Email to ${email}: ${loginUrl}`,
151
+ });
152
+ }
@@ -0,0 +1,2 @@
1
+ export { DEFAULT_EMBEDDING_DIM, DEFAULT_EMBEDDING_MODEL, embedQuery, embedTexts, toVectorLiteral, } from './ai/embedding-client.js';
2
+ export type { EmbedOptions } from './ai/embedding-client.js';
@@ -0,0 +1 @@
1
+ export { DEFAULT_EMBEDDING_DIM, DEFAULT_EMBEDDING_MODEL, embedQuery, embedTexts, toVectorLiteral, } from './ai/embedding-client.js';
@@ -0,0 +1,6 @@
1
+ import type { PrismaClient } from '@prisma/client';
2
+ /**
3
+ * Ensures the curated AP/IB catalog exists. Idempotent — safe to call on every
4
+ * server boot. Matches existing KBs by slug stored in `meta.slug`.
5
+ */
6
+ export declare function ensureCuratedKbCatalog(db: PrismaClient): Promise<void>;
@@ -0,0 +1,53 @@
1
+ import { CURATED_KB_SEEDS } from '../lib/curated-kb-seed.js';
2
+ import { logger } from '../lib/logger.js';
3
+ /**
4
+ * Ensures the curated AP/IB catalog exists. Idempotent — safe to call on every
5
+ * server boot. Matches existing KBs by slug stored in `meta.slug`.
6
+ */
7
+ export async function ensureCuratedKbCatalog(db) {
8
+ let created = 0;
9
+ for (const seed of CURATED_KB_SEEDS) {
10
+ const existing = (await db.knowledgeBase.findFirst({
11
+ where: {
12
+ meta: { path: ['slug'], equals: seed.slug },
13
+ },
14
+ })) ??
15
+ (await db.knowledgeBase.findFirst({
16
+ where: {
17
+ name: { equals: seed.name, mode: 'insensitive' },
18
+ },
19
+ }));
20
+ if (existing) {
21
+ await db.knowledgeBase.update({
22
+ where: { id: existing.id },
23
+ data: {
24
+ name: seed.name,
25
+ description: seed.description,
26
+ isCurated: true,
27
+ meta: {
28
+ slug: seed.slug,
29
+ category: seed.category,
30
+ subject: seed.subject,
31
+ },
32
+ },
33
+ });
34
+ continue;
35
+ }
36
+ await db.knowledgeBase.create({
37
+ data: {
38
+ name: seed.name,
39
+ description: seed.description,
40
+ isCurated: true,
41
+ meta: {
42
+ slug: seed.slug,
43
+ category: seed.category,
44
+ subject: seed.subject,
45
+ },
46
+ },
47
+ });
48
+ created += 1;
49
+ }
50
+ if (created > 0) {
51
+ logger.info(`Seeded ${created} curated knowledge base(s)`, 'KB');
52
+ }
53
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Parsed and validated environment variables
3
+ */
4
+ export declare const env: {
5
+ DATABASE_URL: string;
6
+ PORT: number;
7
+ NODE_ENV: "production" | "development" | "test";
8
+ FRONTEND_URL: string;
9
+ EMAIL_FROM: string;
10
+ STRIPE_SUCCESS_URL: string;
11
+ STRIPE_CANCEL_URL: string;
12
+ DIRECT_URL?: string | undefined;
13
+ BETTER_AUTH_SECRET?: string | undefined;
14
+ BETTER_AUTH_URL?: string | undefined;
15
+ GOOGLE_CLOUD_PROJECT_ID?: string | undefined;
16
+ GOOGLE_CLOUD_BUCKET_NAME?: string | undefined;
17
+ GOOGLE_APPLICATION_CREDENTIALS?: string | undefined;
18
+ PUSHER_APP_ID?: string | undefined;
19
+ PUSHER_KEY?: string | undefined;
20
+ PUSHER_SECRET?: string | undefined;
21
+ PUSHER_CLUSTER?: string | undefined;
22
+ INFERENCE_API_URL?: string | undefined;
23
+ RESEND_API_KEY?: string | undefined;
24
+ STRIPE_SECRET_KEY?: string | undefined;
25
+ STRIPE_PRICE_SUB_BASIC?: string | undefined;
26
+ STRIPE_PRICE_SUB_PRO?: string | undefined;
27
+ STRIPE_PRICE_CREDITS_1000?: string | undefined;
28
+ STRIPE_WEBHOOK_SECRET?: string | undefined;
29
+ };
30
+ /**
31
+ * Check if running in production
32
+ */
33
+ export declare const isProduction: boolean;
34
+ /**
35
+ * Check if running in development
36
+ */
37
+ export declare const isDevelopment: boolean;
38
+ /**
39
+ * Check if running in test
40
+ */
41
+ export declare const isTest: boolean;