@coursebuilder/adapter-drizzle 0.1.2 → 0.1.4

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 (173) hide show
  1. package/dist/{chunk-QZOBGJSV.js → chunk-2CI3IGR2.js} +4 -4
  2. package/dist/{chunk-ISURSRBK.js → chunk-3RJVKNXB.js} +425 -142
  3. package/dist/{chunk-RVYJDDZD.js → chunk-53266VWH.js} +3 -3
  4. package/dist/{chunk-OIUOQ3TT.js → chunk-57CX5SOI.js} +2 -2
  5. package/dist/{chunk-75V6F7LZ.js → chunk-5HT43CVZ.js} +2 -2
  6. package/dist/{chunk-SFJM6FKE.js → chunk-BX5SO2JG.js} +2 -2
  7. package/dist/{chunk-LSOPFMDB.js → chunk-FNYW3XKR.js} +3 -3
  8. package/dist/{chunk-V6QEDDFG.js → chunk-GLPDG7UE.js} +2 -2
  9. package/dist/{chunk-VNI36MMC.js → chunk-H736K5TN.js} +1 -1
  10. package/dist/{chunk-6CBAFOL3.js → chunk-J4LBG2TH.js} +2 -2
  11. package/dist/{chunk-JD4KFACE.js → chunk-JKOYOL7A.js} +2 -2
  12. package/dist/{chunk-TMQIGK3N.js → chunk-MBB4GIJI.js} +2 -2
  13. package/dist/{chunk-27KREOQW.js → chunk-PJHGIRZM.js} +2 -2
  14. package/dist/{chunk-L2TQQYG4.js → chunk-PPBEA4EM.js} +2 -2
  15. package/dist/{chunk-MYRB6GLJ.js → chunk-Q5WENQT6.js} +3 -3
  16. package/dist/{chunk-H4MXNDWO.js → chunk-V23SCQL7.js} +2 -2
  17. package/dist/{chunk-NZDLUQWP.js → chunk-VDVCCU7D.js} +2 -2
  18. package/dist/{chunk-IN6G6MTW.js → chunk-VXZRMVNY.js} +2 -2
  19. package/dist/chunk-WQ7UXKZC.js +9293 -0
  20. package/dist/{chunk-JKRFXYAR.js → chunk-Y7QZGEPT.js} +2 -2
  21. package/dist/index.d.ts +0 -2
  22. package/dist/index.js +20 -37
  23. package/dist/lib/mysql/index.cjs +1775 -1155
  24. package/dist/lib/mysql/index.cjs.map +1 -1
  25. package/dist/lib/mysql/index.d.cts +6143 -0
  26. package/dist/lib/mysql/index.d.ts +253 -19
  27. package/dist/lib/mysql/index.js +20 -24
  28. package/dist/lib/mysql/schemas/auth/accounts.cjs +73 -57
  29. package/dist/lib/mysql/schemas/auth/accounts.cjs.map +1 -1
  30. package/dist/lib/mysql/schemas/auth/accounts.d.cts +184 -0
  31. package/dist/lib/mysql/schemas/auth/accounts.js +10 -10
  32. package/dist/lib/mysql/schemas/auth/permissions.d.cts +98 -0
  33. package/dist/lib/mysql/schemas/auth/permissions.js +2 -2
  34. package/dist/lib/mysql/schemas/auth/role-permissions.cjs +64 -48
  35. package/dist/lib/mysql/schemas/auth/role-permissions.cjs.map +1 -1
  36. package/dist/lib/mysql/schemas/auth/role-permissions.d.cts +89 -0
  37. package/dist/lib/mysql/schemas/auth/role-permissions.js +11 -11
  38. package/dist/lib/mysql/schemas/auth/roles.cjs +64 -48
  39. package/dist/lib/mysql/schemas/auth/roles.cjs.map +1 -1
  40. package/dist/lib/mysql/schemas/auth/roles.d.cts +100 -0
  41. package/dist/lib/mysql/schemas/auth/roles.js +10 -10
  42. package/dist/lib/mysql/schemas/auth/sessions.cjs +64 -48
  43. package/dist/lib/mysql/schemas/auth/sessions.cjs.map +1 -1
  44. package/dist/lib/mysql/schemas/auth/sessions.d.cts +52 -0
  45. package/dist/lib/mysql/schemas/auth/sessions.js +11 -11
  46. package/dist/lib/mysql/schemas/auth/user-permissions.cjs +65 -49
  47. package/dist/lib/mysql/schemas/auth/user-permissions.cjs.map +1 -1
  48. package/dist/lib/mysql/schemas/auth/user-permissions.d.cts +89 -0
  49. package/dist/lib/mysql/schemas/auth/user-permissions.js +10 -10
  50. package/dist/lib/mysql/schemas/auth/user-roles.cjs +67 -51
  51. package/dist/lib/mysql/schemas/auth/user-roles.cjs.map +1 -1
  52. package/dist/lib/mysql/schemas/auth/user-roles.d.cts +89 -0
  53. package/dist/lib/mysql/schemas/auth/user-roles.js +10 -10
  54. package/dist/lib/mysql/schemas/auth/users.cjs +170 -154
  55. package/dist/lib/mysql/schemas/auth/users.cjs.map +1 -1
  56. package/dist/lib/mysql/schemas/auth/users.d.cts +106 -0
  57. package/dist/lib/mysql/schemas/auth/users.js +10 -10
  58. package/dist/lib/mysql/schemas/auth/verification-tokens.d.cts +60 -0
  59. package/dist/lib/mysql/schemas/auth/verification-tokens.js +2 -2
  60. package/dist/lib/mysql/schemas/commerce/coupon.cjs +180 -17
  61. package/dist/lib/mysql/schemas/commerce/coupon.cjs.map +1 -1
  62. package/dist/lib/mysql/schemas/commerce/coupon.d.cts +172 -0
  63. package/dist/lib/mysql/schemas/commerce/coupon.d.ts +10 -6
  64. package/dist/lib/mysql/schemas/commerce/coupon.js +12 -2
  65. package/dist/lib/mysql/schemas/commerce/merchant-account.d.cts +72 -0
  66. package/dist/lib/mysql/schemas/commerce/merchant-account.js +2 -2
  67. package/dist/lib/mysql/schemas/commerce/merchant-charge.d.cts +108 -0
  68. package/dist/lib/mysql/schemas/commerce/merchant-charge.js +2 -2
  69. package/dist/lib/mysql/schemas/commerce/merchant-coupon.d.cts +84 -0
  70. package/dist/lib/mysql/schemas/commerce/merchant-coupon.js +2 -2
  71. package/dist/lib/mysql/schemas/commerce/merchant-customer.d.cts +84 -0
  72. package/dist/lib/mysql/schemas/commerce/merchant-customer.js +2 -2
  73. package/dist/lib/mysql/schemas/commerce/merchant-price.d.cts +96 -0
  74. package/dist/lib/mysql/schemas/commerce/merchant-price.js +2 -2
  75. package/dist/lib/mysql/schemas/commerce/merchant-product.d.cts +84 -0
  76. package/dist/lib/mysql/schemas/commerce/merchant-product.js +2 -2
  77. package/dist/lib/mysql/schemas/commerce/merchant-session.d.cts +48 -0
  78. package/dist/lib/mysql/schemas/commerce/merchant-session.js +2 -2
  79. package/dist/lib/mysql/schemas/commerce/price.cjs +192 -11
  80. package/dist/lib/mysql/schemas/commerce/price.cjs.map +1 -1
  81. package/dist/lib/mysql/schemas/commerce/price.d.cts +101 -0
  82. package/dist/lib/mysql/schemas/commerce/price.d.ts +7 -2
  83. package/dist/lib/mysql/schemas/commerce/price.js +14 -4
  84. package/dist/lib/mysql/schemas/commerce/product.cjs +230 -9
  85. package/dist/lib/mysql/schemas/commerce/product.cjs.map +1 -1
  86. package/dist/lib/mysql/schemas/commerce/product.d.cts +114 -0
  87. package/dist/lib/mysql/schemas/commerce/product.d.ts +20 -2
  88. package/dist/lib/mysql/schemas/commerce/product.js +12 -2
  89. package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.d.cts +132 -0
  90. package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.js +2 -2
  91. package/dist/lib/mysql/schemas/commerce/purchase.cjs +152 -122
  92. package/dist/lib/mysql/schemas/commerce/purchase.cjs.map +1 -1
  93. package/dist/lib/mysql/schemas/commerce/purchase.d.cts +225 -0
  94. package/dist/lib/mysql/schemas/commerce/purchase.d.ts +2 -1
  95. package/dist/lib/mysql/schemas/commerce/purchase.js +10 -10
  96. package/dist/lib/mysql/schemas/commerce/upgradable-products.cjs +110 -24
  97. package/dist/lib/mysql/schemas/commerce/upgradable-products.cjs.map +1 -1
  98. package/dist/lib/mysql/schemas/commerce/upgradable-products.d.cts +101 -0
  99. package/dist/lib/mysql/schemas/commerce/upgradable-products.js +11 -3
  100. package/dist/lib/mysql/schemas/communication/communication-channel.d.cts +96 -0
  101. package/dist/lib/mysql/schemas/communication/communication-channel.js +2 -2
  102. package/dist/lib/mysql/schemas/communication/communication-preference-types.d.cts +96 -0
  103. package/dist/lib/mysql/schemas/communication/communication-preference-types.js +2 -2
  104. package/dist/lib/mysql/schemas/communication/communication-preferences.cjs +84 -68
  105. package/dist/lib/mysql/schemas/communication/communication-preferences.cjs.map +1 -1
  106. package/dist/lib/mysql/schemas/communication/communication-preferences.d.cts +150 -0
  107. package/dist/lib/mysql/schemas/communication/communication-preferences.js +10 -10
  108. package/dist/lib/mysql/schemas/content/content-contributions.cjs +92 -76
  109. package/dist/lib/mysql/schemas/content/content-contributions.cjs.map +1 -1
  110. package/dist/lib/mysql/schemas/content/content-contributions.d.cts +114 -0
  111. package/dist/lib/mysql/schemas/content/content-contributions.js +10 -10
  112. package/dist/lib/mysql/schemas/content/content-resource-product.cjs +246 -0
  113. package/dist/lib/mysql/schemas/content/content-resource-product.cjs.map +1 -0
  114. package/dist/lib/mysql/schemas/content/content-resource-product.d.cts +101 -0
  115. package/dist/lib/mysql/schemas/content/content-resource-product.d.ts +101 -0
  116. package/dist/lib/mysql/schemas/content/content-resource-product.js +18 -0
  117. package/dist/lib/mysql/schemas/content/content-resource-resource.cjs +67 -51
  118. package/dist/lib/mysql/schemas/content/content-resource-resource.cjs.map +1 -1
  119. package/dist/lib/mysql/schemas/content/content-resource-resource.d.cts +101 -0
  120. package/dist/lib/mysql/schemas/content/content-resource-resource.js +10 -10
  121. package/dist/lib/mysql/schemas/content/content-resource.cjs +116 -62
  122. package/dist/lib/mysql/schemas/content/content-resource.cjs.map +1 -1
  123. package/dist/lib/mysql/schemas/content/content-resource.d.cts +103 -0
  124. package/dist/lib/mysql/schemas/content/content-resource.d.ts +1 -0
  125. package/dist/lib/mysql/schemas/content/content-resource.js +10 -10
  126. package/dist/lib/mysql/schemas/content/contribution-types.d.cts +110 -0
  127. package/dist/lib/mysql/schemas/content/contribution-types.js +2 -2
  128. package/dist/lib/mysql/schemas/content/resource-progress.cjs +1 -1
  129. package/dist/lib/mysql/schemas/content/resource-progress.cjs.map +1 -1
  130. package/dist/lib/mysql/schemas/content/resource-progress.d.cts +84 -0
  131. package/dist/lib/mysql/schemas/content/resource-progress.d.ts +1 -1
  132. package/dist/lib/mysql/schemas/content/resource-progress.js +2 -2
  133. package/dist/lib/mysql/utils.cjs.map +1 -1
  134. package/dist/lib/mysql/utils.d.cts +12 -0
  135. package/dist/lib/mysql/utils.js +1 -1
  136. package/dist/lib/mysql/utils.js.map +1 -1
  137. package/dist/lib/utils.cjs.map +1 -1
  138. package/dist/lib/utils.d.cts +22 -0
  139. package/dist/lib/utils.d.ts +4 -8
  140. package/dist/lib/utils.js +12 -3
  141. package/dist/lib/utils.js.map +1 -1
  142. package/package.json +5 -5
  143. package/src/index.ts +0 -8
  144. package/src/lib/mysql/index.ts +611 -129
  145. package/src/lib/mysql/schemas/auth/user-roles.ts +2 -2
  146. package/src/lib/mysql/schemas/commerce/coupon.ts +20 -4
  147. package/src/lib/mysql/schemas/commerce/price.ts +23 -2
  148. package/src/lib/mysql/schemas/commerce/product.ts +27 -2
  149. package/src/lib/mysql/schemas/commerce/purchase.ts +6 -1
  150. package/src/lib/mysql/schemas/content/content-resource-product.ts +62 -0
  151. package/src/lib/mysql/schemas/content/content-resource.ts +5 -0
  152. package/src/lib/mysql/schemas/content/resource-progress.ts +1 -1
  153. package/src/lib/utils.ts +1 -9
  154. package/dist/chunk-44VDBYFU.js +0 -60
  155. package/dist/chunk-7LAAAEVE.js +0 -379
  156. package/dist/chunk-AFQGYW7Z.js +0 -45
  157. package/dist/chunk-CPE4P26C.js +0 -42
  158. package/dist/chunk-DHYYRN35.js +0 -4679
  159. package/dist/chunk-GFUUJRX7.js +0 -18
  160. package/dist/chunk-O2KKII62.js +0 -381
  161. package/dist/chunk-Y34AIPU7.js +0 -4137
  162. package/dist/lib/pg.cjs +0 -4527
  163. package/dist/lib/pg.cjs.map +0 -1
  164. package/dist/lib/pg.d.ts +0 -496
  165. package/dist/lib/pg.js +0 -11
  166. package/dist/lib/sqlite.cjs +0 -4536
  167. package/dist/lib/sqlite.cjs.map +0 -1
  168. package/dist/lib/sqlite.d.ts +0 -496
  169. package/dist/lib/sqlite.js +0 -12
  170. package/dist/lib/sqlite.js.map +0 -1
  171. package/src/lib/pg.ts +0 -579
  172. package/src/lib/sqlite.ts +0 -562
  173. /package/dist/lib/{pg.js.map → mysql/schemas/content/content-resource-product.js.map} +0 -0
@@ -1,6 +1,16 @@
1
1
  import type { AdapterSession, AdapterUser } from '@auth/core/adapters'
2
2
  import { addSeconds, isAfter } from 'date-fns'
3
- import { and, asc, eq, inArray, not, notInArray, or, sql } from 'drizzle-orm'
3
+ import {
4
+ and,
5
+ asc,
6
+ eq,
7
+ inArray,
8
+ isNotNull,
9
+ isNull,
10
+ not,
11
+ or,
12
+ sql,
13
+ } from 'drizzle-orm'
4
14
  import {
5
15
  mysqlTable as defaultMySqlTableFn,
6
16
  MySqlDatabase,
@@ -18,14 +28,19 @@ import {
18
28
  MerchantCoupon,
19
29
  merchantCouponSchema,
20
30
  MerchantCustomer,
31
+ merchantPriceSchema,
21
32
  MerchantProduct,
33
+ merchantProductSchema,
22
34
  Price,
35
+ priceSchema,
23
36
  Product,
37
+ productSchema,
24
38
  Purchase,
25
39
  purchaseSchema,
26
40
  PurchaseUserTransfer,
27
41
  PurchaseUserTransferState,
28
42
  ResourceProgress,
43
+ resourceProgressSchema,
29
44
  UpgradableProduct,
30
45
  upgradableProductSchema,
31
46
  User,
@@ -35,7 +50,10 @@ import {
35
50
  ContentResourceResourceSchema,
36
51
  ContentResourceSchema,
37
52
  } from '@coursebuilder/core/schemas/content-resource-schema'
53
+ import { merchantAccountSchema } from '@coursebuilder/core/schemas/merchant-account-schema'
54
+ import { merchantCustomerSchema } from '@coursebuilder/core/schemas/merchant-customer-schema'
38
55
  import { VideoResourceSchema } from '@coursebuilder/core/schemas/video-resource'
56
+ import { validateCoupon } from '@coursebuilder/core/utils/validate-coupon'
39
57
 
40
58
  import {
41
59
  getAccountsRelationsSchema,
@@ -70,7 +88,10 @@ import {
70
88
  getUsersSchema,
71
89
  } from './schemas/auth/users.js'
72
90
  import { getVerificationTokensSchema } from './schemas/auth/verification-tokens.js'
73
- import { getCouponSchema } from './schemas/commerce/coupon.js'
91
+ import {
92
+ getCouponRelationsSchema,
93
+ getCouponSchema,
94
+ } from './schemas/commerce/coupon.js'
74
95
  import { getMerchantAccountSchema } from './schemas/commerce/merchant-account.js'
75
96
  import { getMerchantChargeSchema } from './schemas/commerce/merchant-charge.js'
76
97
  import { getMerchantCouponSchema } from './schemas/commerce/merchant-coupon.js'
@@ -79,7 +100,10 @@ import { getMerchantPriceSchema } from './schemas/commerce/merchant-price.js'
79
100
  import { getMerchantProductSchema } from './schemas/commerce/merchant-product.js'
80
101
  import { getMerchantSessionSchema } from './schemas/commerce/merchant-session.js'
81
102
  import { getPriceSchema } from './schemas/commerce/price.js'
82
- import { getProductSchema } from './schemas/commerce/product.js'
103
+ import {
104
+ getProductRelationsSchema,
105
+ getProductSchema,
106
+ } from './schemas/commerce/product.js'
83
107
  import { getPurchaseUserTransferSchema } from './schemas/commerce/purchase-user-transfer.js'
84
108
  import {
85
109
  getPurchaseRelationsSchema,
@@ -99,6 +123,10 @@ import {
99
123
  getContentContributionRelationsSchema,
100
124
  getContentContributionsSchema,
101
125
  } from './schemas/content/content-contributions.js'
126
+ import {
127
+ getContentResourceProductRelationsSchema,
128
+ getContentResourceProductSchema,
129
+ } from './schemas/content/content-resource-product.js'
102
130
  import {
103
131
  getContentResourceResourceRelationsSchema,
104
132
  getContentResourceResourceSchema,
@@ -133,6 +161,7 @@ export function getCourseBuilderSchema(mysqlTable: MySqlTableFn) {
133
161
  usersRelations: getUsersRelationsSchema(mysqlTable),
134
162
  verificationTokens: getVerificationTokensSchema(mysqlTable),
135
163
  coupon: getCouponSchema(mysqlTable),
164
+ couponRelations: getCouponRelationsSchema(mysqlTable),
136
165
  merchantAccount: getMerchantAccountSchema(mysqlTable),
137
166
  merchantCharge: getMerchantChargeSchema(mysqlTable),
138
167
  merchantCoupon: getMerchantCouponSchema(mysqlTable),
@@ -165,6 +194,10 @@ export function getCourseBuilderSchema(mysqlTable: MySqlTableFn) {
165
194
  upgradableProducts: getUpgradableProductsSchema(mysqlTable),
166
195
  upgradableProductsRelations:
167
196
  getUpgradableProductsRelationsSchema(mysqlTable),
197
+ contentResourceProduct: getContentResourceProductSchema(mysqlTable),
198
+ contentResourceProductRelations:
199
+ getContentResourceProductRelationsSchema(mysqlTable),
200
+ productRelations: getProductRelationsSchema(mysqlTable),
168
201
  } as const
169
202
  }
170
203
 
@@ -198,20 +231,203 @@ export function mySqlDrizzleAdapter(
198
231
  prices,
199
232
  products,
200
233
  upgradableProducts,
234
+ resourceProgress,
201
235
  } = createTables(tableFn)
202
236
 
203
237
  return {
204
238
  client,
239
+ async redeemFullPriceCoupon(options) {
240
+ const {
241
+ email: baseEmail,
242
+ couponId,
243
+ productIds,
244
+ currentUserId,
245
+ redeemingProductId,
246
+ } = options
247
+ const email = String(baseEmail).replace(' ', '+')
248
+
249
+ const coupon = await this.getCouponWithBulkPurchases(couponId)
250
+
251
+ const productId =
252
+ (coupon && (coupon.restrictedToProductId as string)) ||
253
+ redeemingProductId
254
+
255
+ if (!productId) throw new Error(`unable-to-find-any-product-id`)
256
+
257
+ const couponValidation = validateCoupon(coupon, productIds)
258
+
259
+ if (coupon && couponValidation.isRedeemable) {
260
+ // if the Coupon is the Bulk Coupon of a Bulk Purchase,
261
+ // then a bulk coupon is being redeemed
262
+ const bulkCouponRedemption = Boolean(
263
+ coupon.bulkCouponPurchases[0]?.bulkCouponId,
264
+ )
265
+
266
+ const { user } = await this.findOrCreateUser(email)
267
+
268
+ if (!user) throw new Error(`unable-to-create-user-${email}`)
269
+
270
+ const currentUser = currentUserId
271
+ ? await this.getUserById(currentUserId)
272
+ : null
273
+
274
+ const redeemingForCurrentUser = currentUser?.id === user.id
275
+
276
+ // To prevent double-purchasing, check if this user already has a
277
+ // Purchase record for this product that is valid and wasn't a bulk
278
+ // coupon purchase.
279
+ const existingPurchases =
280
+ await this.getExistingNonBulkValidPurchasesOfProduct({
281
+ userId: user.id,
282
+ productId,
283
+ })
284
+
285
+ if (existingPurchases.length > 0)
286
+ throw new Error(`already-purchased-${email}`)
287
+
288
+ const purchaseId = `purchase-${v4()}`
289
+
290
+ await this.createPurchase({
291
+ id: purchaseId,
292
+ userId: user.id,
293
+ couponId: bulkCouponRedemption ? null : coupon.id,
294
+ redeemedBulkCouponId: bulkCouponRedemption ? coupon.id : null,
295
+ productId,
296
+ totalAmount: '0',
297
+ metadata: {
298
+ couponUsedId: bulkCouponRedemption ? null : coupon.id,
299
+ },
300
+ })
301
+
302
+ const newPurchase = await this.getPurchase(purchaseId)
303
+
304
+ await this.incrementCouponUsedCount(coupon.id)
305
+
306
+ await this.createPurchaseTransfer({
307
+ sourceUserId: user.id,
308
+ purchaseId: purchaseId,
309
+ expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7),
310
+ })
311
+
312
+ return { purchase: newPurchase, redeemingForCurrentUser }
313
+ }
314
+
315
+ return null
316
+ },
317
+ createPurchaseTransfer: async (options) => {
318
+ const id = `put_${v4()}`
319
+ await client.insert(purchaseUserTransfer).values({
320
+ id,
321
+ purchaseId: options.purchaseId,
322
+ sourceUserId: options.sourceUserId,
323
+ expiresAt: options.expiresAt,
324
+ })
325
+ },
326
+ incrementCouponUsedCount: async (couponId) => {
327
+ await client
328
+ .update(coupon)
329
+ .set({ usedCount: sql`${coupon.usedCount} + 1` })
330
+ .where(eq(coupon.id, couponId))
331
+ },
332
+ getExistingNonBulkValidPurchasesOfProduct: async ({
333
+ userId,
334
+ productId,
335
+ }) => {
336
+ const existingPurchases = await client.query.purchases.findMany({
337
+ where: and(
338
+ eq(purchaseTable.userId, userId),
339
+ productId ? eq(purchaseTable.productId, productId) : undefined,
340
+ eq(purchaseTable.status, 'Valid'),
341
+ isNull(purchaseTable.bulkCouponId),
342
+ ),
343
+ })
344
+
345
+ return z.array(purchaseSchema).parse(existingPurchases)
346
+ },
347
+ createMerchantCustomer: async (options) => {
348
+ await client.insert(merchantCustomer).values({
349
+ id: `mc_${v4()}`,
350
+ identifier: options.identifier,
351
+ merchantAccountId: options.merchantAccountId,
352
+ userId: options.userId,
353
+ status: 1,
354
+ })
355
+ return merchantCustomerSchema.parse(
356
+ await client.query.merchantCustomer.findFirst({
357
+ where: eq(merchantCustomer.identifier, options.identifier),
358
+ }),
359
+ )
360
+ },
361
+ getMerchantAccount: async (options) => {
362
+ return merchantAccountSchema.parse(
363
+ await client.query.merchantAccount.findFirst({
364
+ where: eq(merchantAccount.label, options.provider),
365
+ }),
366
+ )
367
+ },
368
+ getMerchantPriceForProductId: async (productId) => {
369
+ const merchantPriceData = await client.query.merchantPrice.findFirst({
370
+ where: eq(merchantPrice.merchantProductId, productId),
371
+ })
372
+
373
+ const parsedMerchantPrice =
374
+ merchantPriceSchema.safeParse(merchantPriceData)
375
+
376
+ if (!parsedMerchantPrice.success) {
377
+ console.error(
378
+ 'Error parsing merchant price',
379
+ JSON.stringify(parsedMerchantPrice.error),
380
+ )
381
+ return null
382
+ }
383
+
384
+ return parsedMerchantPrice.data
385
+ },
386
+ getMerchantProductForProductId: async (productId) => {
387
+ const merchantProductData = await client.query.merchantProduct.findFirst({
388
+ where: eq(merchantProduct.productId, productId),
389
+ })
390
+
391
+ if (!merchantProductData) return null
392
+ return merchantProductSchema.parse(merchantProductData)
393
+ },
394
+ getMerchantCustomerForUserId: async (userId) => {
395
+ const merchantCustomerData =
396
+ await client.query.merchantCustomer.findFirst({
397
+ where: eq(merchantCustomer.userId, userId),
398
+ })
399
+
400
+ if (!merchantCustomerData) return null
401
+ return merchantCustomerSchema.parse(merchantCustomerData)
402
+ },
403
+ getUpgradableProducts: async (options) => {
404
+ const { upgradableFromId, upgradableToId } = options
405
+ return z.array(upgradableProductSchema).parse(
406
+ await client.query.upgradableProducts.findMany({
407
+ where: and(
408
+ eq(upgradableProducts.upgradableFromId, upgradableFromId),
409
+ eq(upgradableProducts.upgradableToId, upgradableToId),
410
+ ),
411
+ }),
412
+ )
413
+ },
205
414
  availableUpgradesForProduct(
206
415
  purchases: any,
207
416
  productId: string,
208
- ): Promise<
209
- {
210
- upgradableTo: { id: string; name: string }
211
- upgradableFrom: { id: string; name: string }
212
- }[]
213
- > {
214
- throw new Error('Method not implemented.')
417
+ ): Promise<any[]> {
418
+ const previousPurchaseProductIds = purchases.map(
419
+ ({ productId }: Purchase) => productId,
420
+ )
421
+
422
+ return client.query.upgradableProducts.findMany({
423
+ where: and(
424
+ eq(upgradableProducts.upgradableToId, productId),
425
+ inArray(
426
+ upgradableProducts.upgradableFromId,
427
+ previousPurchaseProductIds,
428
+ ),
429
+ ),
430
+ })
215
431
  },
216
432
  clearLessonProgressForUser(options: {
217
433
  userId: string
@@ -219,11 +435,56 @@ export function mySqlDrizzleAdapter(
219
435
  }): Promise<void> {
220
436
  throw new Error('Method not implemented.')
221
437
  },
222
- completeLessonProgressForUser(options: {
438
+ async completeLessonProgressForUser(options: {
223
439
  userId: string
224
440
  lessonId?: string
225
441
  }): Promise<ResourceProgress | null> {
226
- throw new Error('Method not implemented.')
442
+ if (!options.lessonId) {
443
+ throw new Error('No lessonId provided')
444
+ }
445
+
446
+ let lessonProgress = await client.query.resourceProgress.findFirst({
447
+ where: and(
448
+ eq(resourceProgress.userId, options.userId),
449
+ eq(resourceProgress.contentResourceId, options.lessonId),
450
+ ),
451
+ })
452
+
453
+ const now = new Date()
454
+
455
+ if (lessonProgress) {
456
+ if (!lessonProgress.completedAt) {
457
+ await client
458
+ .update(resourceProgress)
459
+ .set({
460
+ completedAt: now,
461
+ updatedAt: now,
462
+ })
463
+ .where(eq(resourceProgress.contentResourceId, options.lessonId))
464
+ }
465
+ } else {
466
+ await client.insert(resourceProgress).values({
467
+ userId: options.userId,
468
+ contentResourceId: options.lessonId,
469
+ completedAt: now,
470
+ updatedAt: now,
471
+ })
472
+ }
473
+ lessonProgress = await client.query.resourceProgress.findFirst({
474
+ where: and(
475
+ eq(resourceProgress.userId, options.userId),
476
+ eq(resourceProgress.contentResourceId, options.lessonId),
477
+ ),
478
+ })
479
+ const parsedLessonProgress =
480
+ resourceProgressSchema.safeParse(lessonProgress)
481
+
482
+ if (!parsedLessonProgress.success) {
483
+ console.error('Error parsing lesson progress', lessonProgress)
484
+ return null
485
+ }
486
+
487
+ return parsedLessonProgress.data
227
488
  },
228
489
  couponForIdOrCode(options: {
229
490
  code?: string
@@ -258,7 +519,7 @@ export function mySqlDrizzleAdapter(
258
519
  )
259
520
 
260
521
  const existingPurchaseForCharge = existingMerchantCharge
261
- ? await client.query.purchase.findFirst({
522
+ ? await client.query.purchases.findFirst({
262
523
  where: eq(
263
524
  purchaseTable.merchantChargeId,
264
525
  existingMerchantCharge.id,
@@ -272,13 +533,13 @@ export function mySqlDrizzleAdapter(
272
533
  : null
273
534
 
274
535
  if (existingPurchaseForCharge) {
275
- return purchaseSchema.parse(existingPurchaseForCharge)
536
+ return existingPurchaseForCharge.id
276
537
  }
277
538
 
278
- const merchantChargeId = v4()
279
- const purchaseId = v4()
539
+ const merchantChargeId = `mc_${v4()}`
540
+ const purchaseId = `purch_${v4()}`
280
541
 
281
- const newMerchantCharge = trx.insert(merchantCharge).values({
542
+ const newMerchantCharge = await client.insert(merchantCharge).values({
282
543
  id: merchantChargeId,
283
544
  userId,
284
545
  identifier: stripeChargeId,
@@ -308,9 +569,20 @@ export function mySqlDrizzleAdapter(
308
569
  eq(purchaseTable.userId, userId),
309
570
  ),
310
571
  )
311
- .then((res) => res[0] ?? null),
572
+ .where(
573
+ and(
574
+ eq(coupon.restrictedToProductId, productId),
575
+ eq(purchaseTable.userId, userId),
576
+ ),
577
+ )
578
+ .then((res) => {
579
+ console.log({ res })
580
+ return res[0]?.coupons ?? null
581
+ }),
312
582
  )
313
583
 
584
+ console.log({ existingBulkCoupon })
585
+
314
586
  const isBulkPurchase =
315
587
  quantity > 1 ||
316
588
  Boolean(existingBulkCoupon) ||
@@ -325,7 +597,7 @@ export function mySqlDrizzleAdapter(
325
597
  existingBulkCoupon !== null ? existingBulkCoupon.id : v4()
326
598
 
327
599
  if (existingBulkCoupon !== null) {
328
- couponToUpdate = trx
600
+ couponToUpdate = await client
329
601
  .update(coupon)
330
602
  .set({
331
603
  maxUses: (existingBulkCoupon?.maxUses || 0) + quantity,
@@ -340,7 +612,7 @@ export function mySqlDrizzleAdapter(
340
612
  )
341
613
  : null
342
614
 
343
- couponToUpdate = await trx.insert(coupon).values({
615
+ couponToUpdate = await client.insert(coupon).values({
344
616
  id: bulkCouponId as string,
345
617
  percentageDiscount: '1.0',
346
618
  restrictedToProductId: productId,
@@ -355,13 +627,17 @@ export function mySqlDrizzleAdapter(
355
627
  }
356
628
  }
357
629
 
358
- const merchantSessionId = v4()
630
+ const merchantSessionId = `ms_${v4()}`
359
631
 
360
- const newMerchantSession = trx.insert(merchantSession).values({
361
- id: merchantSessionId,
362
- identifier: checkoutSessionId,
363
- merchantAccountId,
364
- })
632
+ const newMerchantSession = await client
633
+ .insert(merchantSession)
634
+ .values({
635
+ id: merchantSessionId,
636
+ identifier: checkoutSessionId,
637
+ merchantAccountId,
638
+ })
639
+
640
+ console.log({ newMerchantSession })
365
641
 
366
642
  const merchantCouponUsed = stripeCouponId
367
643
  ? await client.query.merchantCoupon.findFirst({
@@ -369,6 +645,8 @@ export function mySqlDrizzleAdapter(
369
645
  })
370
646
  : null
371
647
 
648
+ console.log({ merchantCouponUsed })
649
+
372
650
  const pppMerchantCoupon = appliedPPPStripeCouponId
373
651
  ? await client.query.merchantCoupon.findFirst({
374
652
  where: and(
@@ -378,12 +656,14 @@ export function mySqlDrizzleAdapter(
378
656
  })
379
657
  : null
380
658
 
659
+ console.log({ pppMerchantCoupon })
660
+
381
661
  const newPurchaseStatus =
382
662
  merchantCouponUsed?.type === 'ppp' || pppMerchantCoupon
383
663
  ? 'Restricted'
384
664
  : 'Valid'
385
665
 
386
- const newPurchase = trx.insert(purchaseTable).values({
666
+ const newPurchase = await client.insert(purchaseTable).values({
387
667
  id: purchaseId,
388
668
  status: newPurchaseStatus,
389
669
  userId,
@@ -397,12 +677,14 @@ export function mySqlDrizzleAdapter(
397
677
  couponId: usedCouponId || null,
398
678
  })
399
679
 
680
+ console.log({ newPurchase })
681
+
400
682
  const oneWeekInMilliseconds = 1000 * 60 * 60 * 24 * 7
401
683
 
402
- const newPurchaseUserTransfer = trx
684
+ const newPurchaseUserTransfer = await client
403
685
  .insert(purchaseUserTransfer)
404
686
  .values({
405
- id: v4(),
687
+ id: `put_${v4()}`,
406
688
  purchaseId: purchaseId as string,
407
689
  expiresAt: existingPurchase
408
690
  ? new Date()
@@ -410,13 +692,19 @@ export function mySqlDrizzleAdapter(
410
692
  sourceUserId: userId,
411
693
  })
412
694
 
413
- await Promise.all([
414
- newMerchantCharge,
415
- newPurchase,
416
- newPurchaseUserTransfer,
417
- newMerchantSession,
418
- ...(couponToUpdate ? [couponToUpdate] : []),
419
- ])
695
+ console.log({ newPurchaseUserTransfer })
696
+
697
+ // const result = await Promise.all([
698
+ // newMerchantCharge,
699
+ // newPurchase,
700
+ // newPurchaseUserTransfer,
701
+ // newMerchantSession,
702
+ // ...(couponToUpdate ? [couponToUpdate] : []),
703
+ // ])
704
+ //
705
+ // console.log('result', { result })
706
+
707
+ console.log('inside', { purchaseId })
420
708
 
421
709
  return purchaseId
422
710
  } catch (error) {
@@ -426,30 +714,90 @@ export function mySqlDrizzleAdapter(
426
714
  }
427
715
  })
428
716
 
429
- return purchaseSchema.parse(
717
+ console.log('putside', { purchaseId })
718
+
719
+ const parsedPurchase = purchaseSchema.safeParse(
430
720
  await client.query.purchases.findFirst({
431
721
  where: eq(purchaseTable.id, purchaseId as string),
432
722
  }),
433
723
  )
724
+
725
+ if (!parsedPurchase.success) {
726
+ console.error(
727
+ 'Error parsing purchase',
728
+ parsedPurchase,
729
+ JSON.stringify(parsedPurchase, null, 2),
730
+ )
731
+ throw new Error('Error parsing purchase')
732
+ }
733
+
734
+ return parsedPurchase.data
434
735
  },
435
- findOrCreateMerchantCustomer(options: {
736
+ async findOrCreateMerchantCustomer(options: {
436
737
  user: User
437
738
  identifier: string
438
739
  merchantAccountId: string
439
740
  }): Promise<MerchantCustomer | null> {
440
- throw new Error('Method not implemented.')
741
+ const merchantCustomer = merchantCustomerSchema
742
+ .nullable()
743
+ .optional()
744
+ .parse(
745
+ await client.query.merchantCustomer.findFirst({
746
+ where: (merchantCustomer, { eq }) =>
747
+ eq(merchantCustomer.identifier, options.identifier),
748
+ }),
749
+ )
750
+
751
+ if (merchantCustomer) {
752
+ return merchantCustomer
753
+ }
754
+
755
+ return await this.createMerchantCustomer({
756
+ identifier: options.identifier,
757
+ merchantAccountId: options.merchantAccountId,
758
+ userId: options.user.id,
759
+ })
441
760
  },
442
- findOrCreateUser(
761
+ async findOrCreateUser(
443
762
  email: string,
444
763
  name?: string | null,
445
764
  ): Promise<{
446
765
  user: User
447
766
  isNewUser: boolean
448
767
  }> {
449
- throw new Error('Method not implemented.')
768
+ const user = await this.getUserByEmail?.(email)
769
+
770
+ if (!user) {
771
+ const newUser = await this.createUser?.({
772
+ id: `u_${v4()}`,
773
+ email,
774
+ name,
775
+ emailVerified: null,
776
+ })
777
+ if (!newUser) {
778
+ throw new Error('Could not create user')
779
+ }
780
+ return {
781
+ user: newUser as User,
782
+ isNewUser: true,
783
+ }
784
+ }
785
+
786
+ return {
787
+ user: user as User,
788
+ isNewUser: false,
789
+ }
450
790
  },
451
- getCoupon(couponIdOrCode: string): Promise<Coupon | null> {
452
- throw new Error('Method not implemented.')
791
+ async getCoupon(couponIdOrCode: string): Promise<Coupon | null> {
792
+ return couponSchema.nullable().parse(
793
+ await client
794
+ .select()
795
+ .from(coupon)
796
+ .where(
797
+ or(eq(coupon.id, couponIdOrCode), eq(coupon.code, couponIdOrCode)),
798
+ )
799
+ .then((res) => res[0] ?? null),
800
+ )
453
801
  },
454
802
  getCouponWithBulkPurchases(couponId: string): Promise<
455
803
  | (Coupon & {
@@ -479,26 +827,100 @@ export function mySqlDrizzleAdapter(
479
827
  getLessonProgresses(): Promise<ResourceProgress[]> {
480
828
  throw new Error('Method not implemented.')
481
829
  },
482
- getMerchantCharge(
830
+ async getMerchantCharge(
483
831
  merchantChargeId: string,
484
832
  ): Promise<MerchantCharge | null> {
485
- throw new Error('Method not implemented.')
833
+ const mCharge = await client.query.merchantCharge.findFirst({
834
+ where: eq(merchantCharge.id, merchantChargeId),
835
+ })
836
+ console.log('mCharge', mCharge)
837
+ const parsed = merchantChargeSchema.safeParse(mCharge)
838
+ if (!parsed.success) {
839
+ console.error('Error parsing merchantCharge', mCharge)
840
+ return null
841
+ }
842
+ return parsed.data
486
843
  },
487
- getMerchantCoupon(
844
+ async getMerchantCouponsForTypeAndPercent(params: {
845
+ type: string
846
+ percentageDiscount: number
847
+ }): Promise<MerchantCoupon[]> {
848
+ return z.array(merchantCouponSchema).parse(
849
+ await client.query.merchantCoupon.findMany({
850
+ where: and(
851
+ eq(merchantCoupon.type, params.type),
852
+ eq(
853
+ merchantCoupon.percentageDiscount,
854
+ params.percentageDiscount.toString(),
855
+ ),
856
+ ),
857
+ }),
858
+ )
859
+ },
860
+ async getMerchantCouponForTypeAndPercent(params: {
861
+ type: string
862
+ percentageDiscount: number
863
+ }): Promise<MerchantCoupon | null> {
864
+ const foundMerchantCoupon = await client.query.merchantCoupon.findFirst({
865
+ where: and(
866
+ eq(merchantCoupon.type, params.type),
867
+ eq(
868
+ merchantCoupon.percentageDiscount,
869
+ params.percentageDiscount.toString(),
870
+ ),
871
+ ),
872
+ })
873
+
874
+ const parsed = merchantCouponSchema
875
+ .nullable()
876
+ .safeParse(foundMerchantCoupon)
877
+ if (parsed.success) {
878
+ return parsed.data
879
+ }
880
+
881
+ return null
882
+ },
883
+ async getMerchantCoupon(
488
884
  merchantCouponId: string,
489
885
  ): Promise<MerchantCoupon | null> {
490
- throw new Error('Method not implemented.')
886
+ const foundMerchantCoupon = await client.query.merchantCoupon.findFirst({
887
+ where: eq(merchantCoupon.id, merchantCouponId),
888
+ })
889
+
890
+ const parsed = merchantCouponSchema
891
+ .nullable()
892
+ .safeParse(foundMerchantCoupon)
893
+ if (parsed.success) {
894
+ return parsed.data
895
+ }
896
+
897
+ return null
491
898
  },
492
- getMerchantProduct(
899
+ async getMerchantProduct(
493
900
  stripeProductId: string,
494
901
  ): Promise<MerchantProduct | null> {
495
- throw new Error('Method not implemented.')
902
+ return merchantProductSchema.nullable().parse(
903
+ await client.query.merchantProduct.findFirst({
904
+ where: eq(merchantProduct.identifier, stripeProductId),
905
+ }),
906
+ )
496
907
  },
497
908
  getPrice(productId: string): Promise<Price | null> {
498
909
  throw new Error('Method not implemented.')
499
910
  },
500
- getProduct(productId: string): Promise<Product | null> {
501
- throw new Error('Method not implemented.')
911
+ async getPriceForProduct(productId: string): Promise<Price | null> {
912
+ return priceSchema.nullable().parse(
913
+ await client.query.prices.findFirst({
914
+ where: eq(prices.productId, productId),
915
+ }),
916
+ )
917
+ },
918
+ async getProduct(productId: string): Promise<Product | null> {
919
+ return productSchema.nullable().parse(
920
+ await client.query.products.findFirst({
921
+ where: eq(products.id, productId),
922
+ }),
923
+ )
502
924
  },
503
925
  async getPurchase(purchaseId: string): Promise<Purchase | null> {
504
926
  const purchase = await client.query.purchases.findFirst({
@@ -510,7 +932,6 @@ export function mySqlDrizzleAdapter(
510
932
  async createPurchase(options): Promise<Purchase> {
511
933
  const newPurchaseId = options.id || `purchase-${v4()}`
512
934
  await client.insert(purchaseTable).values({
513
- state: 'Valid',
514
935
  ...options,
515
936
  id: newPurchaseId,
516
937
  })
@@ -519,77 +940,7 @@ export function mySqlDrizzleAdapter(
519
940
 
520
941
  return purchaseSchema.parse(newPurchase)
521
942
  },
522
- async getPurchaseDetails(
523
- purchaseId: string,
524
- userId: string,
525
- ): Promise<{
526
- purchase?: Purchase
527
- existingPurchase?: Purchase
528
- availableUpgrades: UpgradableProduct[]
529
- }> {
530
- const allPurchases = await this.getPurchasesForUser(userId)
531
- const thePurchase = await client.query.purchases.findFirst({
532
- where: and(
533
- eq(purchaseTable.id, purchaseId),
534
- eq(purchaseTable.userId, userId),
535
- ),
536
- with: {
537
- user: true,
538
- product: true,
539
- bulkCoupon: true,
540
- },
541
- })
542
-
543
- const parsedPurchase = purchaseSchema.safeParse(thePurchase)
544
-
545
- if (!parsedPurchase.success) {
546
- console.error('Error parsing purchase', parsedPurchase)
547
- return {
548
- availableUpgrades: [],
549
- }
550
- }
551
-
552
- const purchaseCanUpgrade = ['Valid', 'Restricted'].includes(
553
- parsedPurchase.data.state || '',
554
- )
555
-
556
- if (!purchaseCanUpgrade) {
557
- return {
558
- availableUpgrades: [],
559
- }
560
- }
561
-
562
- const availableUpgrades = await client.query.upgradableProducts.findMany({
563
- where: and(
564
- eq(
565
- upgradableProducts.upgradableFromId,
566
- parsedPurchase.data.product?.id as string,
567
- ),
568
- not(
569
- inArray(
570
- upgradableProducts.upgradableToId,
571
- allPurchases.map((p) => p.product?.id as string),
572
- ),
573
- ),
574
- ),
575
- with: {
576
- upgradableTo: true,
577
- upgradableFrom: true,
578
- },
579
- })
580
-
581
- const existingPurchase = allPurchases.find(
582
- (p) => p.product?.id === parsedPurchase.data.product?.id,
583
- )
584
943
 
585
- return Promise.resolve({
586
- availableUpgrades: z
587
- .array(upgradableProductSchema)
588
- .parse(availableUpgrades),
589
- existingPurchase,
590
- purchase: parsedPurchase.data,
591
- })
592
- },
593
944
  async getPurchaseForStripeCharge(
594
945
  stripeChargeId: string,
595
946
  ): Promise<Purchase | null> {
@@ -604,7 +955,9 @@ export function mySqlDrizzleAdapter(
604
955
  eq(merchantCharge.id, purchaseTable.merchantChargeId),
605
956
  ),
606
957
  )
607
- .then((res) => res[0] ?? null),
958
+ .then((res) => {
959
+ return res[0]?.purchases ?? null
960
+ }),
608
961
  )
609
962
 
610
963
  if (!purchase.success) {
@@ -641,7 +994,7 @@ export function mySqlDrizzleAdapter(
641
994
  const userPurchases = await client.query.purchases.findMany({
642
995
  where: and(
643
996
  eq(purchaseTable.userId, userId),
644
- inArray(purchaseTable.state, visiblePurchaseStates),
997
+ inArray(purchaseTable.status, visiblePurchaseStates),
645
998
  ),
646
999
  with: {
647
1000
  user: true,
@@ -654,12 +1007,106 @@ export function mySqlDrizzleAdapter(
654
1007
  const parsedPurchases = z.array(purchaseSchema).safeParse(userPurchases)
655
1008
 
656
1009
  if (!parsedPurchases.success) {
657
- console.error('Error parsing purchases', parsedPurchases)
1010
+ console.error(
1011
+ 'Error parsing purchases',
1012
+ JSON.stringify(parsedPurchases.error),
1013
+ )
658
1014
  return []
659
1015
  }
660
1016
 
661
1017
  return parsedPurchases.data
662
1018
  },
1019
+ async getPurchaseDetails(
1020
+ purchaseId: string,
1021
+ userId: string,
1022
+ ): Promise<{
1023
+ purchase?: Purchase
1024
+ existingPurchase?: Purchase & { product?: Product | null }
1025
+ availableUpgrades: UpgradableProduct[]
1026
+ }> {
1027
+ const visiblePurchaseStates = ['Valid', 'Refunded', 'Restricted']
1028
+
1029
+ const userPurchases = await client.query.purchases.findMany({
1030
+ where: and(
1031
+ eq(purchaseTable.userId, userId),
1032
+ inArray(purchaseTable.status, visiblePurchaseStates),
1033
+ ),
1034
+ with: {
1035
+ user: true,
1036
+ product: true,
1037
+ bulkCoupon: true,
1038
+ },
1039
+ orderBy: asc(purchaseTable.createdAt),
1040
+ })
1041
+
1042
+ const parsedPurchases = z.array(purchaseSchema).safeParse(userPurchases)
1043
+
1044
+ const allPurchases = parsedPurchases.success ? parsedPurchases.data : []
1045
+
1046
+ console.log('🦦', { allPurchases })
1047
+
1048
+ const thePurchase = await client.query.purchases.findFirst({
1049
+ where: and(
1050
+ eq(purchaseTable.id, purchaseId),
1051
+ eq(purchaseTable.userId, userId),
1052
+ ),
1053
+ with: {
1054
+ user: true,
1055
+ product: true,
1056
+ bulkCoupon: true,
1057
+ },
1058
+ })
1059
+
1060
+ const parsedPurchase = purchaseSchema.safeParse(thePurchase)
1061
+
1062
+ if (!parsedPurchase.success) {
1063
+ console.error('Error parsing purchase', parsedPurchase)
1064
+ return {
1065
+ availableUpgrades: [],
1066
+ }
1067
+ }
1068
+
1069
+ console.log('🦦', { parsedPurchase: parsedPurchase.data })
1070
+
1071
+ const purchaseCanUpgrade = ['Valid', 'Restricted'].includes(
1072
+ parsedPurchase.data.state || '',
1073
+ )
1074
+
1075
+ let availableUpgrades: any[] = []
1076
+
1077
+ if (purchaseCanUpgrade) {
1078
+ availableUpgrades = await client.query.upgradableProducts.findMany({
1079
+ where: and(
1080
+ eq(
1081
+ upgradableProducts.upgradableFromId,
1082
+ parsedPurchase.data.product?.id as string,
1083
+ ),
1084
+ not(
1085
+ inArray(
1086
+ upgradableProducts.upgradableToId,
1087
+ allPurchases.map((p) => p.product?.id as string),
1088
+ ),
1089
+ ),
1090
+ ),
1091
+ with: {
1092
+ upgradableTo: true,
1093
+ upgradableFrom: true,
1094
+ },
1095
+ })
1096
+ }
1097
+
1098
+ const existingPurchase = allPurchases.find(
1099
+ (p) => p.product?.id === parsedPurchase.data.product?.id,
1100
+ )
1101
+
1102
+ return Promise.resolve({
1103
+ availableUpgrades: z
1104
+ .array(upgradableProductSchema)
1105
+ .parse(availableUpgrades),
1106
+ existingPurchase,
1107
+ purchase: parsedPurchase.data,
1108
+ })
1109
+ },
663
1110
  async getUserById(userId: string): Promise<User | null> {
664
1111
  return userSchema.nullable().parse(
665
1112
  await client.query.users.findFirst({
@@ -667,11 +1114,47 @@ export function mySqlDrizzleAdapter(
667
1114
  }),
668
1115
  )
669
1116
  },
670
- pricesOfPurchasesTowardOneBundle(options: {
1117
+ async pricesOfPurchasesTowardOneBundle({
1118
+ userId,
1119
+ bundleId,
1120
+ }: {
671
1121
  userId: string | undefined
672
1122
  bundleId: string
673
1123
  }): Promise<Price[]> {
674
- throw new Error('Method not implemented.')
1124
+ if (userId === undefined) return []
1125
+
1126
+ const canUpgradeProducts = await client.query.upgradableProducts.findMany(
1127
+ {
1128
+ where: eq(upgradableProducts.upgradableToId, bundleId),
1129
+ },
1130
+ )
1131
+
1132
+ const upgradableFrom = z.array(z.string()).parse(
1133
+ canUpgradeProducts.map((product) => {
1134
+ return product.upgradableFromId
1135
+ }),
1136
+ )
1137
+
1138
+ const purchases = await client.query.purchases.findMany({
1139
+ where: and(
1140
+ eq(purchaseTable.userId, userId),
1141
+ inArray(purchaseTable.productId, upgradableFrom),
1142
+ ),
1143
+ })
1144
+
1145
+ const productsPurchased = z.array(z.string()).parse(
1146
+ purchases.map((purchase) => {
1147
+ return purchase.productId
1148
+ }),
1149
+ )
1150
+
1151
+ if (productsPurchased.length === 0) return []
1152
+
1153
+ const foundPrices = await client.query.prices.findMany({
1154
+ where: inArray(prices.productId, productsPurchased),
1155
+ })
1156
+
1157
+ return z.array(priceSchema).parse(foundPrices)
675
1158
  },
676
1159
  toggleLessonProgressForUser(options: {
677
1160
  userId: string
@@ -806,7 +1289,7 @@ export function mySqlDrizzleAdapter(
806
1289
  WHERE
807
1290
  type = 'videoResource'
808
1291
  AND (id = ${id});
809
-
1292
+
810
1293
  `
811
1294
  return client
812
1295
  .execute(query)
@@ -892,7 +1375,6 @@ export function mySqlDrizzleAdapter(
892
1375
  return parsedResource.data
893
1376
  },
894
1377
  async createUser(data) {
895
- console.log(data)
896
1378
  try {
897
1379
  const id = crypto.randomUUID()
898
1380