@coursebuilder/adapter-drizzle 2.1.1 → 3.0.0-canary.0.0c9beb2ae

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 (296) hide show
  1. package/dist/{chunk-KIQLUFJX.js → chunk-2GW3BJE2.js} +2 -2
  2. package/dist/{chunk-M3WM5Q7W.js → chunk-33ZN7FN7.js} +2 -2
  3. package/dist/chunk-4VZJQAPV.js +74 -0
  4. package/dist/chunk-5FLS4ZBX.js +109 -0
  5. package/dist/chunk-5YR5M22S.js +147 -0
  6. package/dist/chunk-6XQ6C3IX.js +18 -0
  7. package/dist/chunk-AIDM2CH6.js +146 -0
  8. package/dist/chunk-ALTODDUX.js +173 -0
  9. package/dist/chunk-AZY2VRAE.js +63 -0
  10. package/dist/chunk-BS7T27VL.js +239 -0
  11. package/dist/chunk-CN3FCRLR.js +55 -0
  12. package/dist/chunk-EAXC4CQD.js +245 -0
  13. package/dist/chunk-EDDG2YFS.js +249 -0
  14. package/dist/chunk-EDKWCMA7.js +210 -0
  15. package/dist/{chunk-7FBSP3VD.js → chunk-EDM6DKA5.js} +2 -2
  16. package/dist/{chunk-EZEQQJNH.js → chunk-EIQBTF5J.js} +2 -2
  17. package/dist/chunk-FYT7RTVW.js +248 -0
  18. package/dist/{chunk-F56AI52P.js → chunk-INZTF6QV.js} +2 -2
  19. package/dist/{chunk-AP5HBIV4.js → chunk-JVHX4JHA.js} +2 -2
  20. package/dist/chunk-LWEKWDLC.js +300 -0
  21. package/dist/chunk-OJPEBGGE.js +139 -0
  22. package/dist/chunk-QKOSV34V.js +16268 -0
  23. package/dist/chunk-QO3QE3LE.js +330 -0
  24. package/dist/chunk-QQKNNFFB.js +399 -0
  25. package/dist/chunk-RBHCV3UW.js +20 -0
  26. package/dist/chunk-TNH2C27F.js +252 -0
  27. package/dist/chunk-TNWNW666.js +133 -0
  28. package/dist/chunk-VBEXYQ6L.js +156 -0
  29. package/dist/chunk-W3ILNMLD.js +265 -0
  30. package/dist/chunk-WJ2ZUXL3.js +71 -0
  31. package/dist/{chunk-PJORQUQP.js → chunk-WUMDFFN3.js} +2 -2
  32. package/dist/{chunk-2AW5KYAK.js → chunk-X7DRYXB7.js} +2 -2
  33. package/dist/{chunk-PNPTKVJ4.js → chunk-XUBZKYH6.js} +24 -15
  34. package/dist/{chunk-WWBSNLRC.js → chunk-ZY4AFKUQ.js} +2 -2
  35. package/dist/index.d.ts +5 -11
  36. package/dist/index.js +41 -18
  37. package/dist/lib/mysql/cms-resource-actions.cjs +15912 -4127
  38. package/dist/lib/mysql/cms-resource-actions.cjs.map +1 -1
  39. package/dist/lib/mysql/cms-resource-actions.d.cts +8 -38
  40. package/dist/lib/mysql/cms-resource-actions.d.ts +8 -38
  41. package/dist/lib/mysql/cms-resource-actions.js +2 -1
  42. package/dist/lib/mysql/context.cjs +3380 -0
  43. package/dist/lib/mysql/context.cjs.map +1 -0
  44. package/dist/lib/mysql/context.d.cts +15 -0
  45. package/dist/lib/mysql/context.d.ts +15 -0
  46. package/dist/lib/mysql/context.js +34 -0
  47. package/dist/lib/mysql/context.js.map +1 -0
  48. package/dist/lib/mysql/index.cjs +21875 -15261
  49. package/dist/lib/mysql/index.cjs.map +1 -1
  50. package/dist/lib/mysql/index.d.cts +24 -14300
  51. package/dist/lib/mysql/index.d.ts +24 -14300
  52. package/dist/lib/mysql/index.js +46 -22
  53. package/dist/lib/mysql/ports/auth-storage.cjs +84 -0
  54. package/dist/lib/mysql/ports/auth-storage.cjs.map +1 -0
  55. package/dist/lib/mysql/ports/auth-storage.d.cts +22 -0
  56. package/dist/lib/mysql/ports/auth-storage.d.ts +22 -0
  57. package/dist/lib/mysql/ports/auth-storage.js +8 -0
  58. package/dist/lib/mysql/ports/auth-storage.js.map +1 -0
  59. package/dist/lib/mysql/ports/catalog.cjs +16688 -0
  60. package/dist/lib/mysql/ports/catalog.cjs.map +1 -0
  61. package/dist/lib/mysql/ports/catalog.d.cts +24 -0
  62. package/dist/lib/mysql/ports/catalog.d.ts +24 -0
  63. package/dist/lib/mysql/ports/catalog.js +9 -0
  64. package/dist/lib/mysql/ports/catalog.js.map +1 -0
  65. package/dist/lib/mysql/ports/content-resource.cjs +321 -0
  66. package/dist/lib/mysql/ports/content-resource.cjs.map +1 -0
  67. package/dist/lib/mysql/ports/content-resource.d.cts +23 -0
  68. package/dist/lib/mysql/ports/content-resource.d.ts +23 -0
  69. package/dist/lib/mysql/ports/content-resource.js +8 -0
  70. package/dist/lib/mysql/ports/content-resource.js.map +1 -0
  71. package/dist/lib/mysql/ports/coupon.cjs +16524 -0
  72. package/dist/lib/mysql/ports/coupon.cjs.map +1 -0
  73. package/dist/lib/mysql/ports/coupon.d.cts +22 -0
  74. package/dist/lib/mysql/ports/coupon.d.ts +22 -0
  75. package/dist/lib/mysql/ports/coupon.js +9 -0
  76. package/dist/lib/mysql/ports/coupon.js.map +1 -0
  77. package/dist/lib/mysql/ports/entitlement.cjs +16350 -0
  78. package/dist/lib/mysql/ports/entitlement.cjs.map +1 -0
  79. package/dist/lib/mysql/ports/entitlement.d.cts +22 -0
  80. package/dist/lib/mysql/ports/entitlement.d.ts +22 -0
  81. package/dist/lib/mysql/ports/entitlement.js +9 -0
  82. package/dist/lib/mysql/ports/entitlement.js.map +1 -0
  83. package/dist/lib/mysql/ports/identity.cjs +154 -0
  84. package/dist/lib/mysql/ports/identity.cjs.map +1 -0
  85. package/dist/lib/mysql/ports/identity.d.cts +22 -0
  86. package/dist/lib/mysql/ports/identity.d.ts +22 -0
  87. package/dist/lib/mysql/ports/identity.js +8 -0
  88. package/dist/lib/mysql/ports/identity.js.map +1 -0
  89. package/dist/lib/mysql/ports/merchant.cjs +194 -0
  90. package/dist/lib/mysql/ports/merchant.cjs.map +1 -0
  91. package/dist/lib/mysql/ports/merchant.d.cts +22 -0
  92. package/dist/lib/mysql/ports/merchant.d.ts +22 -0
  93. package/dist/lib/mysql/ports/merchant.js +8 -0
  94. package/dist/lib/mysql/ports/merchant.js.map +1 -0
  95. package/dist/lib/mysql/ports/organization.cjs +16426 -0
  96. package/dist/lib/mysql/ports/organization.cjs.map +1 -0
  97. package/dist/lib/mysql/ports/organization.d.cts +22 -0
  98. package/dist/lib/mysql/ports/organization.d.ts +22 -0
  99. package/dist/lib/mysql/ports/organization.js +9 -0
  100. package/dist/lib/mysql/ports/organization.js.map +1 -0
  101. package/dist/lib/mysql/ports/progress.cjs +16544 -0
  102. package/dist/lib/mysql/ports/progress.cjs.map +1 -0
  103. package/dist/lib/mysql/ports/progress.d.cts +22 -0
  104. package/dist/lib/mysql/ports/progress.d.ts +22 -0
  105. package/dist/lib/mysql/ports/progress.js +9 -0
  106. package/dist/lib/mysql/ports/progress.js.map +1 -0
  107. package/dist/lib/mysql/ports/purchase.cjs +16609 -0
  108. package/dist/lib/mysql/ports/purchase.cjs.map +1 -0
  109. package/dist/lib/mysql/ports/purchase.d.cts +23 -0
  110. package/dist/lib/mysql/ports/purchase.d.ts +23 -0
  111. package/dist/lib/mysql/ports/purchase.js +9 -0
  112. package/dist/lib/mysql/ports/purchase.js.map +1 -0
  113. package/dist/lib/mysql/ports/subscription.cjs +76 -0
  114. package/dist/lib/mysql/ports/subscription.cjs.map +1 -0
  115. package/dist/lib/mysql/ports/subscription.d.cts +22 -0
  116. package/dist/lib/mysql/ports/subscription.d.ts +22 -0
  117. package/dist/lib/mysql/ports/subscription.js +8 -0
  118. package/dist/lib/mysql/ports/subscription.js.map +1 -0
  119. package/dist/lib/mysql/schema.cjs +3373 -0
  120. package/dist/lib/mysql/schema.cjs.map +1 -0
  121. package/dist/lib/mysql/schema.d.cts +14385 -0
  122. package/dist/lib/mysql/schema.d.ts +14385 -0
  123. package/dist/lib/mysql/schema.js +35 -0
  124. package/dist/lib/mysql/schema.js.map +1 -0
  125. package/dist/lib/mysql/schemas/auth/accounts.cjs.map +1 -1
  126. package/dist/lib/mysql/schemas/auth/accounts.js +4 -4
  127. package/dist/lib/mysql/schemas/auth/device-access-token.cjs.map +1 -1
  128. package/dist/lib/mysql/schemas/auth/device-access-token.js +5 -5
  129. package/dist/lib/mysql/schemas/auth/device-verification.cjs.map +1 -1
  130. package/dist/lib/mysql/schemas/auth/device-verification.js +5 -5
  131. package/dist/lib/mysql/schemas/auth/personal-access-token.cjs.map +1 -1
  132. package/dist/lib/mysql/schemas/auth/personal-access-token.js +5 -5
  133. package/dist/lib/mysql/schemas/auth/profiles.cjs.map +1 -1
  134. package/dist/lib/mysql/schemas/auth/profiles.js +4 -4
  135. package/dist/lib/mysql/schemas/auth/role-permissions.cjs.map +1 -1
  136. package/dist/lib/mysql/schemas/auth/role-permissions.js +5 -5
  137. package/dist/lib/mysql/schemas/auth/roles.cjs.map +1 -1
  138. package/dist/lib/mysql/schemas/auth/roles.js +4 -4
  139. package/dist/lib/mysql/schemas/auth/sessions.cjs.map +1 -1
  140. package/dist/lib/mysql/schemas/auth/sessions.js +5 -5
  141. package/dist/lib/mysql/schemas/auth/user-permissions.cjs.map +1 -1
  142. package/dist/lib/mysql/schemas/auth/user-permissions.js +4 -4
  143. package/dist/lib/mysql/schemas/auth/user-prefs.cjs.map +1 -1
  144. package/dist/lib/mysql/schemas/auth/user-prefs.js +4 -4
  145. package/dist/lib/mysql/schemas/auth/user-roles.cjs.map +1 -1
  146. package/dist/lib/mysql/schemas/auth/user-roles.js +4 -4
  147. package/dist/lib/mysql/schemas/auth/users.cjs +5 -1
  148. package/dist/lib/mysql/schemas/auth/users.cjs.map +1 -1
  149. package/dist/lib/mysql/schemas/auth/users.js +4 -4
  150. package/dist/lib/mysql/schemas/commerce/coupon.cjs.map +1 -1
  151. package/dist/lib/mysql/schemas/commerce/coupon.js +4 -4
  152. package/dist/lib/mysql/schemas/commerce/merchant-charge.cjs.map +1 -1
  153. package/dist/lib/mysql/schemas/commerce/merchant-charge.js +4 -4
  154. package/dist/lib/mysql/schemas/commerce/merchant-subscription.cjs.map +1 -1
  155. package/dist/lib/mysql/schemas/commerce/merchant-subscription.js +4 -4
  156. package/dist/lib/mysql/schemas/commerce/price.cjs.map +1 -1
  157. package/dist/lib/mysql/schemas/commerce/price.js +4 -4
  158. package/dist/lib/mysql/schemas/commerce/product.cjs.map +1 -1
  159. package/dist/lib/mysql/schemas/commerce/product.js +4 -4
  160. package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.cjs.map +1 -1
  161. package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.js +5 -5
  162. package/dist/lib/mysql/schemas/commerce/purchase.cjs +11 -2
  163. package/dist/lib/mysql/schemas/commerce/purchase.cjs.map +1 -1
  164. package/dist/lib/mysql/schemas/commerce/purchase.js +4 -4
  165. package/dist/lib/mysql/schemas/commerce/subscription.cjs +6 -1
  166. package/dist/lib/mysql/schemas/commerce/subscription.cjs.map +1 -1
  167. package/dist/lib/mysql/schemas/commerce/subscription.js +4 -4
  168. package/dist/lib/mysql/schemas/commerce/upgradable-products.cjs.map +1 -1
  169. package/dist/lib/mysql/schemas/commerce/upgradable-products.js +5 -5
  170. package/dist/lib/mysql/schemas/communication/comment.cjs +5 -1
  171. package/dist/lib/mysql/schemas/communication/comment.cjs.map +1 -1
  172. package/dist/lib/mysql/schemas/communication/comment.js +4 -4
  173. package/dist/lib/mysql/schemas/communication/communication-preferences.cjs +5 -1
  174. package/dist/lib/mysql/schemas/communication/communication-preferences.cjs.map +1 -1
  175. package/dist/lib/mysql/schemas/communication/communication-preferences.js +4 -4
  176. package/dist/lib/mysql/schemas/communication/question-response.cjs.map +1 -1
  177. package/dist/lib/mysql/schemas/communication/question-response.js +5 -5
  178. package/dist/lib/mysql/schemas/content/content-contributions.cjs +5 -1
  179. package/dist/lib/mysql/schemas/content/content-contributions.cjs.map +1 -1
  180. package/dist/lib/mysql/schemas/content/content-contributions.js +4 -4
  181. package/dist/lib/mysql/schemas/content/content-resource-product.cjs.map +1 -1
  182. package/dist/lib/mysql/schemas/content/content-resource-product.js +4 -4
  183. package/dist/lib/mysql/schemas/content/content-resource-resource.cjs.map +1 -1
  184. package/dist/lib/mysql/schemas/content/content-resource-resource.js +4 -4
  185. package/dist/lib/mysql/schemas/content/content-resource-tag.cjs.map +1 -1
  186. package/dist/lib/mysql/schemas/content/content-resource-tag.js +4 -4
  187. package/dist/lib/mysql/schemas/content/content-resource-version.cjs.map +1 -1
  188. package/dist/lib/mysql/schemas/content/content-resource-version.js +4 -4
  189. package/dist/lib/mysql/schemas/content/content-resource.cjs +5 -1
  190. package/dist/lib/mysql/schemas/content/content-resource.cjs.map +1 -1
  191. package/dist/lib/mysql/schemas/content/content-resource.js +4 -4
  192. package/dist/lib/mysql/schemas/content/tag-tag.cjs.map +1 -1
  193. package/dist/lib/mysql/schemas/content/tag-tag.js +4 -4
  194. package/dist/lib/mysql/schemas/content/tag.cjs.map +1 -1
  195. package/dist/lib/mysql/schemas/content/tag.js +4 -4
  196. package/dist/lib/mysql/schemas/entitlements/entitlement.cjs +11 -2
  197. package/dist/lib/mysql/schemas/entitlements/entitlement.cjs.map +1 -1
  198. package/dist/lib/mysql/schemas/entitlements/entitlement.js +5 -5
  199. package/dist/lib/mysql/schemas/org/organization-membership-roles.cjs +11 -2
  200. package/dist/lib/mysql/schemas/org/organization-membership-roles.cjs.map +1 -1
  201. package/dist/lib/mysql/schemas/org/organization-membership-roles.js +4 -4
  202. package/dist/lib/mysql/schemas/org/organization-memberships.cjs +11 -2
  203. package/dist/lib/mysql/schemas/org/organization-memberships.cjs.map +1 -1
  204. package/dist/lib/mysql/schemas/org/organization-memberships.d.cts +16 -0
  205. package/dist/lib/mysql/schemas/org/organization-memberships.d.ts +16 -0
  206. package/dist/lib/mysql/schemas/org/organization-memberships.js +4 -4
  207. package/dist/lib/mysql/schemas/org/organizations.cjs +11 -2
  208. package/dist/lib/mysql/schemas/org/organizations.cjs.map +1 -1
  209. package/dist/lib/mysql/schemas/org/organizations.d.cts +16 -0
  210. package/dist/lib/mysql/schemas/org/organizations.d.ts +16 -0
  211. package/dist/lib/mysql/schemas/org/organizations.js +4 -4
  212. package/dist/lib/mysql/workflows/content-resource-workflow-utils.cjs +40 -0
  213. package/dist/lib/mysql/workflows/content-resource-workflow-utils.cjs.map +1 -0
  214. package/dist/lib/mysql/workflows/content-resource-workflow-utils.d.cts +4 -0
  215. package/dist/lib/mysql/workflows/content-resource-workflow-utils.d.ts +4 -0
  216. package/dist/lib/mysql/workflows/content-resource-workflow-utils.js +10 -0
  217. package/dist/lib/mysql/workflows/content-resource-workflow-utils.js.map +1 -0
  218. package/dist/lib/mysql/workflows/create-cohort.cjs +184 -0
  219. package/dist/lib/mysql/workflows/create-cohort.cjs.map +1 -0
  220. package/dist/lib/mysql/workflows/create-cohort.d.cts +24 -0
  221. package/dist/lib/mysql/workflows/create-cohort.d.ts +24 -0
  222. package/dist/lib/mysql/workflows/create-cohort.js +9 -0
  223. package/dist/lib/mysql/workflows/create-cohort.js.map +1 -0
  224. package/dist/lib/mysql/workflows/create-event-series.cjs +283 -0
  225. package/dist/lib/mysql/workflows/create-event-series.cjs.map +1 -0
  226. package/dist/lib/mysql/workflows/create-event-series.d.cts +24 -0
  227. package/dist/lib/mysql/workflows/create-event-series.d.ts +24 -0
  228. package/dist/lib/mysql/workflows/create-event-series.js +9 -0
  229. package/dist/lib/mysql/workflows/create-event-series.js.map +1 -0
  230. package/dist/lib/mysql/workflows/create-event.cjs +194 -0
  231. package/dist/lib/mysql/workflows/create-event.cjs.map +1 -0
  232. package/dist/lib/mysql/workflows/create-event.d.cts +24 -0
  233. package/dist/lib/mysql/workflows/create-event.d.ts +24 -0
  234. package/dist/lib/mysql/workflows/create-event.js +9 -0
  235. package/dist/lib/mysql/workflows/create-event.js.map +1 -0
  236. package/dist/lib/mysql/workflows/create-merchant-charge-and-purchase.cjs +231 -0
  237. package/dist/lib/mysql/workflows/create-merchant-charge-and-purchase.cjs.map +1 -0
  238. package/dist/lib/mysql/workflows/create-merchant-charge-and-purchase.d.cts +22 -0
  239. package/dist/lib/mysql/workflows/create-merchant-charge-and-purchase.d.ts +22 -0
  240. package/dist/lib/mysql/workflows/create-merchant-charge-and-purchase.js +8 -0
  241. package/dist/lib/mysql/workflows/create-merchant-charge-and-purchase.js.map +1 -0
  242. package/dist/lib/mysql/workflows/create-workshop.cjs +286 -0
  243. package/dist/lib/mysql/workflows/create-workshop.cjs.map +1 -0
  244. package/dist/lib/mysql/workflows/create-workshop.d.cts +24 -0
  245. package/dist/lib/mysql/workflows/create-workshop.d.ts +24 -0
  246. package/dist/lib/mysql/workflows/create-workshop.js +9 -0
  247. package/dist/lib/mysql/workflows/create-workshop.js.map +1 -0
  248. package/dist/lib/mysql/workflows/redeem-full-price-coupon.cjs +130 -0
  249. package/dist/lib/mysql/workflows/redeem-full-price-coupon.cjs.map +1 -0
  250. package/dist/lib/mysql/workflows/redeem-full-price-coupon.d.cts +24 -0
  251. package/dist/lib/mysql/workflows/redeem-full-price-coupon.d.ts +24 -0
  252. package/dist/lib/mysql/workflows/redeem-full-price-coupon.js +8 -0
  253. package/dist/lib/mysql/workflows/redeem-full-price-coupon.js.map +1 -0
  254. package/dist/lib/mysql/workflows/transfer-purchase-to-user.cjs +95 -0
  255. package/dist/lib/mysql/workflows/transfer-purchase-to-user.cjs.map +1 -0
  256. package/dist/lib/mysql/workflows/transfer-purchase-to-user.d.cts +30 -0
  257. package/dist/lib/mysql/workflows/transfer-purchase-to-user.d.ts +30 -0
  258. package/dist/lib/mysql/workflows/transfer-purchase-to-user.js +8 -0
  259. package/dist/lib/mysql/workflows/transfer-purchase-to-user.js.map +1 -0
  260. package/dist/lib/utils.d.cts +1 -10
  261. package/dist/lib/utils.d.ts +1 -10
  262. package/dist/types.d.ts +14 -0
  263. package/dist/types.js +1 -0
  264. package/package.json +9 -5
  265. package/src/index.ts +3 -2
  266. package/src/lib/mysql/context.ts +20 -0
  267. package/src/lib/mysql/index.ts +118 -4873
  268. package/src/lib/mysql/ports/auth-storage.ts +139 -0
  269. package/src/lib/mysql/ports/catalog.ts +610 -0
  270. package/src/lib/mysql/ports/content-resource.ts +442 -0
  271. package/src/lib/mysql/ports/coupon.ts +387 -0
  272. package/src/lib/mysql/ports/entitlement.ts +96 -0
  273. package/src/lib/mysql/ports/identity.ts +160 -0
  274. package/src/lib/mysql/ports/merchant.ts +274 -0
  275. package/src/lib/mysql/ports/organization.ts +216 -0
  276. package/src/lib/mysql/ports/progress.ts +366 -0
  277. package/src/lib/mysql/ports/purchase.ts +517 -0
  278. package/src/lib/mysql/ports/subscription.ts +93 -0
  279. package/src/lib/mysql/schema.ts +374 -0
  280. package/src/lib/mysql/schemas/org/organization-memberships.ts +7 -0
  281. package/src/lib/mysql/schemas/org/organizations.ts +8 -0
  282. package/src/lib/mysql/workflows/content-resource-workflow-utils.ts +22 -0
  283. package/src/lib/mysql/workflows/create-cohort.ts +239 -0
  284. package/src/lib/mysql/workflows/create-event-series.ts +384 -0
  285. package/src/lib/mysql/workflows/create-event.ts +232 -0
  286. package/src/lib/mysql/workflows/create-merchant-charge-and-purchase.ts +365 -0
  287. package/src/lib/mysql/workflows/create-workshop.ts +372 -0
  288. package/src/lib/mysql/workflows/redeem-full-price-coupon.ts +179 -0
  289. package/src/lib/mysql/workflows/transfer-purchase-to-user.ts +142 -0
  290. package/src/types.ts +33 -0
  291. package/dist/authjs.d.ts +0 -27
  292. package/dist/authjs.js +0 -1
  293. package/dist/chunk-62VSIVME.js +0 -4714
  294. package/dist/chunk-RVXF3JZ7.js +0 -8732
  295. package/dist/chunk-WEJL5OFI.js +0 -8732
  296. package/src/authjs.ts +0 -34
@@ -0,0 +1,366 @@
1
+ import { and, eq, inArray, or, sql } from 'drizzle-orm'
2
+ import { z } from 'zod'
3
+
4
+ import type { ProgressPort } from '@coursebuilder/core/ports'
5
+ import {
6
+ resourceProgressSchema,
7
+ type ResourceProgress,
8
+ } from '@coursebuilder/core/schemas'
9
+ import type { ContentResource } from '@coursebuilder/core/schemas/content-resource-schema'
10
+ import type { ModuleProgress } from '@coursebuilder/core/schemas/resource-progress-schema'
11
+ import { logger as baseLogger } from '@coursebuilder/utils/logger'
12
+
13
+ import type { MySqlContext } from '../context.js'
14
+
15
+ const logger = baseLogger as unknown as {
16
+ error: (error: Error, attrs?: Record<string, unknown>) => void
17
+ }
18
+
19
+ /**
20
+ * Creates the MySQL implementation of lesson and module progress tracking.
21
+ *
22
+ * @param context - The shared MySQL client and table set.
23
+ * @returns All seven progress operations.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const progressPort = createProgressPort(context)
28
+ * ```
29
+ */
30
+ export function createProgressPort({
31
+ client,
32
+ tables,
33
+ }: MySqlContext): ProgressPort {
34
+ const { contentResource, contentResourceResource, resourceProgress, users } =
35
+ tables
36
+
37
+ return {
38
+ async clearLessonProgressForUser(options: {
39
+ userId: string
40
+ lessons: { id: string; slug: string }[]
41
+ }): Promise<void> {
42
+ const lessonIds = options.lessons.map(({ id }) => id)
43
+ if (lessonIds.length === 0) return
44
+
45
+ await client
46
+ .delete(resourceProgress)
47
+ .where(
48
+ and(
49
+ eq(resourceProgress.userId, options.userId),
50
+ inArray(resourceProgress.resourceId, lessonIds),
51
+ ),
52
+ )
53
+ },
54
+ async completeLessonProgressForUser(options: {
55
+ userId: string
56
+ lessonId?: string
57
+ }): Promise<ResourceProgress | null> {
58
+ if (!options.lessonId) {
59
+ throw new Error('No lessonId provided')
60
+ }
61
+
62
+ let lessonProgress = await client.query.resourceProgress.findFirst({
63
+ where: and(
64
+ eq(resourceProgress.userId, options.userId),
65
+ eq(resourceProgress.resourceId, options.lessonId),
66
+ ),
67
+ })
68
+
69
+ const now = new Date()
70
+
71
+ if (lessonProgress) {
72
+ if (!lessonProgress.completedAt) {
73
+ await client
74
+ .update(resourceProgress)
75
+ .set({
76
+ completedAt: now,
77
+ updatedAt: now,
78
+ })
79
+ .where(
80
+ and(
81
+ eq(resourceProgress.userId, options.userId),
82
+ eq(resourceProgress.resourceId, options.lessonId),
83
+ ),
84
+ )
85
+ }
86
+ } else {
87
+ await client.insert(resourceProgress).values({
88
+ userId: options.userId,
89
+ resourceId: options.lessonId,
90
+ completedAt: now,
91
+ updatedAt: now,
92
+ })
93
+ }
94
+ lessonProgress = await client.query.resourceProgress.findFirst({
95
+ where: and(
96
+ eq(resourceProgress.userId, options.userId),
97
+ eq(resourceProgress.resourceId, options.lessonId),
98
+ ),
99
+ })
100
+ const parsedLessonProgress =
101
+ resourceProgressSchema.safeParse(lessonProgress)
102
+
103
+ if (!parsedLessonProgress.success) {
104
+ logger.error(parsedLessonProgress.error, {
105
+ event: 'adapter.lessonProgress.parse_failed',
106
+ lessonId: options.lessonId,
107
+ userId: options.userId,
108
+ })
109
+ return null
110
+ }
111
+
112
+ return parsedLessonProgress.data
113
+ },
114
+ async getLessonProgressCountsByDate(): Promise<
115
+ {
116
+ count: number
117
+ completedAt: string
118
+ }[]
119
+ > {
120
+ const completed = await client
121
+ .select({ completedAt: resourceProgress.completedAt })
122
+ .from(resourceProgress)
123
+ .where(sql`${resourceProgress.completedAt} IS NOT NULL`)
124
+
125
+ const counts = new Map<string, number>()
126
+ for (const { completedAt } of completed) {
127
+ if (!completedAt) continue
128
+ const date = completedAt.toISOString().slice(0, 10)
129
+ counts.set(date, (counts.get(date) ?? 0) + 1)
130
+ }
131
+
132
+ return Array.from(counts, ([completedAt, count]) => ({
133
+ count,
134
+ completedAt,
135
+ })).sort((left, right) =>
136
+ left.completedAt.localeCompare(right.completedAt),
137
+ )
138
+ },
139
+ async getLessonProgressForUser(
140
+ userId: string,
141
+ ): Promise<ResourceProgress[]> {
142
+ const userProgress = await client.query.resourceProgress.findMany({
143
+ where: eq(resourceProgress.userId, userId),
144
+ })
145
+ const parsed = z.array(resourceProgressSchema).safeParse(userProgress)
146
+ if (!parsed.success) {
147
+ logger.error(parsed.error, {
148
+ event: 'adapter.userProgress.parse_failed',
149
+ userId,
150
+ })
151
+ return []
152
+ }
153
+ return parsed.data
154
+ },
155
+ async getModuleProgressForUser(
156
+ userIdOrEmail: string,
157
+ moduleIdOrSlug: string,
158
+ ): Promise<ModuleProgress | null> {
159
+ // First, get the user ID
160
+ const user = await client.query.users.findFirst({
161
+ where: or(eq(users.id, userIdOrEmail), eq(users.email, userIdOrEmail)),
162
+ columns: {
163
+ id: true,
164
+ },
165
+ })
166
+
167
+ if (!user) {
168
+ return null
169
+ }
170
+
171
+ const ResultRowSchema = z.object({
172
+ resource_id: z.string(),
173
+ resource_type: z.enum(['lesson', 'exercise', 'post']),
174
+ resource_slug: z.string().nullable(),
175
+ completed_at: z
176
+ .string()
177
+ .nullable()
178
+ .transform((val) => (val ? new Date(val) : null)),
179
+ })
180
+
181
+ // Execute the optimized query - create a flattened, properly ordered list
182
+ const results: any = await client.execute(sql`
183
+ WITH RECURSIVE workshop AS (
184
+ SELECT id, fields->>'$.slug' AS slug
185
+ FROM ${contentResource}
186
+ WHERE id = ${moduleIdOrSlug} OR fields->>'$.slug' = ${moduleIdOrSlug}
187
+ ),
188
+ -- Get all workshop resources with their positions
189
+ workshop_structure AS (
190
+ SELECT
191
+ w.id AS workshop_id,
192
+ crr.resourceId,
193
+ crr.position AS position,
194
+ cr.type AS resource_type,
195
+ cr.fields->>'$.slug' AS resource_slug,
196
+ cr.id AS resource_content_id
197
+ FROM workshop w
198
+ JOIN ${contentResourceResource} crr ON w.id = crr.resourceOfId
199
+ JOIN ${contentResource} cr ON crr.resourceId = cr.id
200
+ ORDER BY crr.position
201
+ ),
202
+ -- Recursively expand sections and maintain global ordering
203
+ expanded_resources AS (
204
+ -- Base case: direct lessons/posts from workshop
205
+ SELECT
206
+ workshop_id,
207
+ position * 1000 AS global_order, -- Multiply by 1000 to leave room for section items
208
+ resource_content_id AS resource_id,
209
+ resource_type,
210
+ resource_slug
211
+ FROM workshop_structure
212
+ WHERE resource_type IN ('lesson', 'post')
213
+ UNION ALL
214
+ -- Recursive case: lessons within sections
215
+ SELECT
216
+ ws.workshop_id,
217
+ ws.position * 1000 + crr.position AS global_order, -- Section position * 1000 + lesson position
218
+ cr.id AS resource_id,
219
+ cr.type AS resource_type,
220
+ cr.fields->>'$.slug' AS resource_slug
221
+ FROM workshop_structure ws
222
+ JOIN ${contentResourceResource} crr ON ws.resource_content_id = crr.resourceOfId
223
+ JOIN ${contentResource} cr ON crr.resourceId = cr.id
224
+ WHERE ws.resource_type = 'section'
225
+ AND cr.type IN ('lesson', 'post')
226
+ )
227
+ SELECT
228
+ er.resource_id,
229
+ er.resource_type,
230
+ er.resource_slug,
231
+ rp.completedAt AS completed_at,
232
+ er.global_order
233
+ FROM expanded_resources er
234
+ LEFT JOIN ${resourceProgress} rp ON rp.resourceId = er.resource_id
235
+ AND rp.userId = ${user.id}
236
+ ORDER BY er.global_order ASC
237
+ `)
238
+ const rows = Array.isArray(results) ? results[0] : results.rows
239
+ const completedLessons: ResourceProgress[] = []
240
+ let nextResource: Partial<ContentResource> | null = null
241
+ let completedLessonsCount = 0
242
+ let totalLessonsCount = rows.length
243
+
244
+ const parsedRows = z.array(ResultRowSchema).safeParse(rows)
245
+
246
+ if (!parsedRows.success) {
247
+ logger.error(parsedRows.error, {
248
+ event: 'adapter.moduleProgress.rows.parse_failed',
249
+ moduleIdOrSlug,
250
+ userId: user.id,
251
+ })
252
+ return {
253
+ completedLessons: [],
254
+ nextResource: null,
255
+ percentCompleted: 0,
256
+ completedLessonsCount: 0,
257
+ totalLessonsCount,
258
+ }
259
+ }
260
+
261
+ for (const row of parsedRows.data) {
262
+ if (row.completed_at) {
263
+ completedLessonsCount++
264
+ completedLessons.push({
265
+ userId: user.id as string,
266
+ resourceId: row.resource_id,
267
+ completedAt: new Date(row.completed_at),
268
+ // Add other fields as needed
269
+ })
270
+ } else if (!nextResource) {
271
+ nextResource = {
272
+ id: row.resource_id,
273
+ type: row.resource_type,
274
+ fields: {
275
+ slug: row.resource_slug,
276
+ },
277
+ }
278
+ }
279
+ }
280
+
281
+ const percentCompleted =
282
+ totalLessonsCount > 0
283
+ ? Math.ceil((completedLessonsCount / totalLessonsCount) * 100)
284
+ : 0
285
+
286
+ return {
287
+ completedLessons,
288
+ nextResource,
289
+ percentCompleted,
290
+ completedLessonsCount,
291
+ totalLessonsCount,
292
+ }
293
+ },
294
+ async getLessonProgresses(): Promise<ResourceProgress[]> {
295
+ const progresses = await client.query.resourceProgress.findMany()
296
+ const parsed = z.array(resourceProgressSchema).safeParse(progresses)
297
+ if (!parsed.success) {
298
+ logger.error(parsed.error, {
299
+ event: 'adapter.lessonProgresses.parse_failed',
300
+ })
301
+ return []
302
+ }
303
+ return parsed.data
304
+ },
305
+ async toggleLessonProgressForUser(options: {
306
+ userId: string
307
+ lessonId?: string
308
+ }): Promise<ResourceProgress | null> {
309
+ if (!options.lessonId) {
310
+ throw new Error('No lessonId provided')
311
+ }
312
+
313
+ let lessonProgress = await client.query.resourceProgress.findFirst({
314
+ where: and(
315
+ eq(resourceProgress.userId, options.userId),
316
+ eq(resourceProgress.resourceId, options.lessonId),
317
+ ),
318
+ })
319
+
320
+ const now = new Date()
321
+
322
+ if (lessonProgress) {
323
+ await client
324
+ .update(resourceProgress)
325
+ .set({
326
+ completedAt: lessonProgress.completedAt ? null : now,
327
+ updatedAt: now,
328
+ })
329
+ .where(
330
+ and(
331
+ eq(resourceProgress.userId, options.userId),
332
+ eq(resourceProgress.resourceId, options.lessonId),
333
+ ),
334
+ )
335
+ } else {
336
+ await client.insert(resourceProgress).values({
337
+ userId: options.userId,
338
+ resourceId: options.lessonId,
339
+ completedAt: now,
340
+ updatedAt: now,
341
+ })
342
+ }
343
+
344
+ lessonProgress = await client.query.resourceProgress.findFirst({
345
+ where: and(
346
+ eq(resourceProgress.userId, options.userId),
347
+ eq(resourceProgress.resourceId, options.lessonId),
348
+ ),
349
+ })
350
+
351
+ const parsedLessonProgress =
352
+ resourceProgressSchema.safeParse(lessonProgress)
353
+
354
+ if (!parsedLessonProgress.success) {
355
+ logger.error(parsedLessonProgress.error, {
356
+ event: 'adapter.lessonProgress.parse_failed',
357
+ lessonId: options.lessonId,
358
+ userId: options.userId,
359
+ })
360
+ return null
361
+ }
362
+
363
+ return parsedLessonProgress.data
364
+ },
365
+ }
366
+ }