@coursebuilder/adapter-drizzle 0.4.0 → 0.5.1
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.
- package/dist/{chunk-57CX5SOI.js → chunk-2UU2F4DM.js} +5 -4
- package/dist/{chunk-V23SCQL7.js → chunk-3NUCFLQJ.js} +2 -2
- package/dist/{chunk-Y7QZGEPT.js → chunk-4ZWS76VQ.js} +2 -2
- package/dist/{chunk-PPBEA4EM.js → chunk-6ON2O6UD.js} +2 -2
- package/dist/{chunk-ULEUIL2Y.js → chunk-7ISZNMPU.js} +3 -3
- package/dist/{chunk-DL3UMWB4.js → chunk-7X7TMG4A.js} +3 -3
- package/dist/{chunk-IDINCRHK.js → chunk-DAP5KOAO.js} +3 -3
- package/dist/{chunk-J4LBG2TH.js → chunk-GINRTL6J.js} +2 -2
- package/dist/{chunk-GLPDG7UE.js → chunk-KDEWFXEP.js} +2 -2
- package/dist/chunk-KDOSK7KN.js +62 -0
- package/dist/{chunk-MBB4GIJI.js → chunk-LERR6HQ3.js} +2 -2
- package/dist/{chunk-VDVCCU7D.js → chunk-LZHZDFNZ.js} +2 -2
- package/dist/{chunk-BX5SO2JG.js → chunk-P4VXXTVA.js} +2 -2
- package/dist/{chunk-VXZRMVNY.js → chunk-QP6YMUQX.js} +2 -2
- package/dist/{chunk-XJHSXR42.js → chunk-QPXUGIXO.js} +4 -4
- package/dist/{chunk-ZD3R6UPJ.js → chunk-SRTIWWLG.js} +7 -7
- package/dist/{chunk-N7UDJAI3.js → chunk-UHH4OVKA.js} +464 -349
- package/dist/chunk-UK6EHYS5.js +54 -0
- package/dist/{chunk-A26D3TCA.js → chunk-VUS77FG3.js} +577 -185
- package/dist/{chunk-FNYW3XKR.js → chunk-XIGJFVUM.js} +8 -8
- package/dist/{chunk-JKOYOL7A.js → chunk-YGRYHMCG.js} +2 -2
- package/dist/chunk-YVVXDJHI.js +56 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +26 -23
- package/dist/lib/mysql/index.cjs +1424 -786
- package/dist/lib/mysql/index.cjs.map +1 -1
- package/dist/lib/mysql/index.d.cts +2056 -1162
- package/dist/lib/mysql/index.d.ts +2056 -1162
- package/dist/lib/mysql/index.js +24 -19
- package/dist/lib/mysql/schemas/auth/accounts.cjs +85 -77
- package/dist/lib/mysql/schemas/auth/accounts.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/accounts.d.cts +17 -17
- package/dist/lib/mysql/schemas/auth/accounts.d.ts +17 -17
- package/dist/lib/mysql/schemas/auth/accounts.js +12 -12
- package/dist/lib/mysql/schemas/auth/device-access-token.cjs +214 -0
- package/dist/lib/mysql/schemas/auth/device-access-token.cjs.map +1 -0
- package/dist/lib/mysql/schemas/auth/device-access-token.d.cts +52 -0
- package/dist/lib/mysql/schemas/auth/device-access-token.d.ts +52 -0
- package/dist/lib/mysql/schemas/auth/device-access-token.js +22 -0
- package/dist/lib/mysql/schemas/auth/device-access-token.js.map +1 -0
- package/dist/lib/mysql/schemas/auth/device-verification.cjs +222 -0
- package/dist/lib/mysql/schemas/auth/device-verification.cjs.map +1 -0
- package/dist/lib/mysql/schemas/auth/device-verification.d.cts +88 -0
- package/dist/lib/mysql/schemas/auth/device-verification.d.ts +88 -0
- package/dist/lib/mysql/schemas/auth/device-verification.js +22 -0
- package/dist/lib/mysql/schemas/auth/device-verification.js.map +1 -0
- package/dist/lib/mysql/schemas/auth/permissions.cjs +1 -1
- package/dist/lib/mysql/schemas/auth/permissions.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/permissions.d.cts +9 -9
- package/dist/lib/mysql/schemas/auth/permissions.d.ts +9 -9
- package/dist/lib/mysql/schemas/auth/permissions.js +1 -1
- package/dist/lib/mysql/schemas/auth/role-permissions.cjs +74 -66
- package/dist/lib/mysql/schemas/auth/role-permissions.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/role-permissions.d.cts +10 -10
- package/dist/lib/mysql/schemas/auth/role-permissions.d.ts +10 -10
- package/dist/lib/mysql/schemas/auth/role-permissions.js +13 -13
- package/dist/lib/mysql/schemas/auth/roles.cjs +72 -64
- package/dist/lib/mysql/schemas/auth/roles.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/roles.d.cts +10 -10
- package/dist/lib/mysql/schemas/auth/roles.d.ts +10 -10
- package/dist/lib/mysql/schemas/auth/roles.js +12 -12
- package/dist/lib/mysql/schemas/auth/sessions.cjs +75 -67
- package/dist/lib/mysql/schemas/auth/sessions.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/sessions.d.cts +6 -6
- package/dist/lib/mysql/schemas/auth/sessions.d.ts +6 -6
- package/dist/lib/mysql/schemas/auth/sessions.js +13 -13
- package/dist/lib/mysql/schemas/auth/user-permissions.cjs +77 -69
- package/dist/lib/mysql/schemas/auth/user-permissions.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/user-permissions.d.cts +10 -10
- package/dist/lib/mysql/schemas/auth/user-permissions.d.ts +10 -10
- package/dist/lib/mysql/schemas/auth/user-permissions.js +12 -12
- package/dist/lib/mysql/schemas/auth/user-prefs.cjs +222 -0
- package/dist/lib/mysql/schemas/auth/user-prefs.cjs.map +1 -0
- package/dist/lib/mysql/schemas/auth/user-prefs.d.cts +100 -0
- package/dist/lib/mysql/schemas/auth/user-prefs.d.ts +100 -0
- package/dist/lib/mysql/schemas/auth/user-prefs.js +21 -0
- package/dist/lib/mysql/schemas/auth/user-prefs.js.map +1 -0
- package/dist/lib/mysql/schemas/auth/user-roles.cjs +77 -69
- package/dist/lib/mysql/schemas/auth/user-roles.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/user-roles.d.cts +10 -10
- package/dist/lib/mysql/schemas/auth/user-roles.d.ts +10 -10
- package/dist/lib/mysql/schemas/auth/user-roles.js +12 -12
- package/dist/lib/mysql/schemas/auth/users.cjs +263 -180
- package/dist/lib/mysql/schemas/auth/users.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/users.d.cts +35 -21
- package/dist/lib/mysql/schemas/auth/users.d.ts +35 -21
- package/dist/lib/mysql/schemas/auth/users.js +12 -12
- package/dist/lib/mysql/schemas/auth/verification-tokens.cjs +1 -1
- package/dist/lib/mysql/schemas/auth/verification-tokens.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/verification-tokens.d.cts +5 -5
- package/dist/lib/mysql/schemas/auth/verification-tokens.d.ts +5 -5
- package/dist/lib/mysql/schemas/auth/verification-tokens.js +1 -1
- package/dist/lib/mysql/schemas/commerce/coupon.cjs +76 -77
- package/dist/lib/mysql/schemas/commerce/coupon.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/coupon.d.cts +18 -30
- package/dist/lib/mysql/schemas/commerce/coupon.d.ts +18 -30
- package/dist/lib/mysql/schemas/commerce/coupon.js +12 -12
- package/dist/lib/mysql/schemas/commerce/merchant-account.cjs +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-account.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-account.d.cts +6 -6
- package/dist/lib/mysql/schemas/commerce/merchant-account.d.ts +6 -6
- package/dist/lib/mysql/schemas/commerce/merchant-account.js +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-charge.cjs +6 -5
- package/dist/lib/mysql/schemas/commerce/merchant-charge.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-charge.d.cts +13 -13
- package/dist/lib/mysql/schemas/commerce/merchant-charge.d.ts +13 -13
- package/dist/lib/mysql/schemas/commerce/merchant-charge.js +4 -4
- package/dist/lib/mysql/schemas/commerce/merchant-coupon.cjs +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-coupon.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-coupon.d.cts +7 -7
- package/dist/lib/mysql/schemas/commerce/merchant-coupon.d.ts +7 -7
- package/dist/lib/mysql/schemas/commerce/merchant-coupon.js +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-customer.cjs +3 -2
- package/dist/lib/mysql/schemas/commerce/merchant-customer.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-customer.d.cts +7 -7
- package/dist/lib/mysql/schemas/commerce/merchant-customer.d.ts +7 -7
- package/dist/lib/mysql/schemas/commerce/merchant-customer.js +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-price.cjs +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-price.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-price.d.cts +8 -8
- package/dist/lib/mysql/schemas/commerce/merchant-price.d.ts +8 -8
- package/dist/lib/mysql/schemas/commerce/merchant-price.js +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-product.cjs +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-product.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-product.d.cts +7 -7
- package/dist/lib/mysql/schemas/commerce/merchant-product.d.ts +7 -7
- package/dist/lib/mysql/schemas/commerce/merchant-product.js +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-session.cjs +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-session.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-session.d.cts +4 -4
- package/dist/lib/mysql/schemas/commerce/merchant-session.d.ts +4 -4
- package/dist/lib/mysql/schemas/commerce/merchant-session.js +1 -1
- package/dist/lib/mysql/schemas/commerce/price.cjs +60 -52
- package/dist/lib/mysql/schemas/commerce/price.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/price.d.cts +11 -11
- package/dist/lib/mysql/schemas/commerce/price.d.ts +11 -11
- package/dist/lib/mysql/schemas/commerce/price.js +12 -12
- package/dist/lib/mysql/schemas/commerce/product.cjs +75 -67
- package/dist/lib/mysql/schemas/commerce/product.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/product.d.cts +13 -13
- package/dist/lib/mysql/schemas/commerce/product.d.ts +13 -13
- package/dist/lib/mysql/schemas/commerce/product.js +12 -12
- package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.cjs +105 -96
- package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.d.cts +15 -15
- package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.d.ts +15 -15
- package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.js +13 -13
- package/dist/lib/mysql/schemas/commerce/purchase.cjs +136 -131
- package/dist/lib/mysql/schemas/commerce/purchase.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/purchase.d.cts +25 -25
- package/dist/lib/mysql/schemas/commerce/purchase.d.ts +25 -25
- package/dist/lib/mysql/schemas/commerce/purchase.js +12 -12
- package/dist/lib/mysql/schemas/commerce/upgradable-products.cjs +66 -58
- package/dist/lib/mysql/schemas/commerce/upgradable-products.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/upgradable-products.d.cts +11 -11
- package/dist/lib/mysql/schemas/commerce/upgradable-products.d.ts +11 -11
- package/dist/lib/mysql/schemas/commerce/upgradable-products.js +13 -13
- package/dist/lib/mysql/schemas/communication/comment.cjs +220 -0
- package/dist/lib/mysql/schemas/communication/comment.cjs.map +1 -0
- package/dist/lib/mysql/schemas/communication/comment.d.cts +100 -0
- package/dist/lib/mysql/schemas/communication/comment.d.ts +100 -0
- package/dist/lib/mysql/schemas/communication/comment.js +21 -0
- package/dist/lib/mysql/schemas/communication/comment.js.map +1 -0
- package/dist/lib/mysql/schemas/communication/communication-channel.cjs +1 -1
- package/dist/lib/mysql/schemas/communication/communication-channel.cjs.map +1 -1
- package/dist/lib/mysql/schemas/communication/communication-channel.d.cts +8 -8
- package/dist/lib/mysql/schemas/communication/communication-channel.d.ts +8 -8
- package/dist/lib/mysql/schemas/communication/communication-channel.js +1 -1
- package/dist/lib/mysql/schemas/communication/communication-preference-types.cjs +1 -1
- package/dist/lib/mysql/schemas/communication/communication-preference-types.cjs.map +1 -1
- package/dist/lib/mysql/schemas/communication/communication-preference-types.d.cts +8 -8
- package/dist/lib/mysql/schemas/communication/communication-preference-types.d.ts +8 -8
- package/dist/lib/mysql/schemas/communication/communication-preference-types.js +1 -1
- package/dist/lib/mysql/schemas/communication/communication-preferences.cjs +99 -91
- package/dist/lib/mysql/schemas/communication/communication-preferences.cjs.map +1 -1
- package/dist/lib/mysql/schemas/communication/communication-preferences.d.cts +16 -16
- package/dist/lib/mysql/schemas/communication/communication-preferences.d.ts +16 -16
- package/dist/lib/mysql/schemas/communication/communication-preferences.js +12 -12
- package/dist/lib/mysql/schemas/content/content-contributions.cjs +67 -59
- package/dist/lib/mysql/schemas/content/content-contributions.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-contributions.d.cts +13 -13
- package/dist/lib/mysql/schemas/content/content-contributions.d.ts +13 -13
- package/dist/lib/mysql/schemas/content/content-contributions.js +12 -12
- package/dist/lib/mysql/schemas/content/content-resource-product.cjs +61 -53
- package/dist/lib/mysql/schemas/content/content-resource-product.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-resource-product.d.cts +11 -11
- package/dist/lib/mysql/schemas/content/content-resource-product.d.ts +11 -11
- package/dist/lib/mysql/schemas/content/content-resource-product.js +12 -12
- package/dist/lib/mysql/schemas/content/content-resource-resource.cjs +58 -50
- package/dist/lib/mysql/schemas/content/content-resource-resource.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-resource-resource.d.cts +11 -11
- package/dist/lib/mysql/schemas/content/content-resource-resource.d.ts +11 -11
- package/dist/lib/mysql/schemas/content/content-resource-resource.js +12 -12
- package/dist/lib/mysql/schemas/content/content-resource.cjs +114 -66
- package/dist/lib/mysql/schemas/content/content-resource.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-resource.d.cts +14 -13
- package/dist/lib/mysql/schemas/content/content-resource.d.ts +14 -13
- package/dist/lib/mysql/schemas/content/content-resource.js +12 -12
- package/dist/lib/mysql/schemas/content/contribution-types.cjs +1 -1
- package/dist/lib/mysql/schemas/content/contribution-types.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/contribution-types.d.cts +10 -10
- package/dist/lib/mysql/schemas/content/contribution-types.d.ts +10 -10
- package/dist/lib/mysql/schemas/content/contribution-types.js +1 -1
- package/dist/lib/mysql/schemas/content/lesson-progress.cjs +77 -0
- package/dist/lib/mysql/schemas/content/lesson-progress.cjs.map +1 -0
- package/dist/lib/mysql/schemas/content/lesson-progress.d.cts +132 -0
- package/dist/lib/mysql/schemas/content/lesson-progress.d.ts +132 -0
- package/dist/lib/mysql/schemas/content/lesson-progress.js +8 -0
- package/dist/lib/mysql/schemas/content/lesson-progress.js.map +1 -0
- package/dist/lib/mysql/schemas/content/resource-progress.cjs +7 -7
- package/dist/lib/mysql/schemas/content/resource-progress.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/resource-progress.d.cts +9 -9
- package/dist/lib/mysql/schemas/content/resource-progress.d.ts +9 -9
- package/dist/lib/mysql/schemas/content/resource-progress.js +1 -1
- package/dist/lib/utils.d.cts +1 -0
- package/dist/lib/utils.d.ts +1 -0
- package/package.json +7 -5
- package/src/index.ts +14 -4
- package/src/lib/mysql/index.ts +675 -153
- package/src/lib/mysql/schemas/auth/accounts.ts +1 -1
- package/src/lib/mysql/schemas/auth/device-access-token.ts +40 -0
- package/src/lib/mysql/schemas/auth/device-verification.ts +48 -0
- package/src/lib/mysql/schemas/auth/permissions.ts +1 -1
- package/src/lib/mysql/schemas/auth/role-permissions.ts +1 -1
- package/src/lib/mysql/schemas/auth/roles.ts +1 -1
- package/src/lib/mysql/schemas/auth/sessions.ts +1 -1
- package/src/lib/mysql/schemas/auth/user-permissions.ts +1 -1
- package/src/lib/mysql/schemas/auth/user-prefs.ts +52 -0
- package/src/lib/mysql/schemas/auth/user-roles.ts +1 -1
- package/src/lib/mysql/schemas/auth/users.ts +14 -2
- package/src/lib/mysql/schemas/auth/verification-tokens.ts +1 -1
- package/src/lib/mysql/schemas/commerce/coupon.ts +4 -13
- package/src/lib/mysql/schemas/commerce/merchant-account.ts +1 -1
- package/src/lib/mysql/schemas/commerce/merchant-charge.ts +1 -1
- package/src/lib/mysql/schemas/commerce/merchant-coupon.ts +1 -1
- package/src/lib/mysql/schemas/commerce/merchant-customer.ts +3 -1
- package/src/lib/mysql/schemas/commerce/merchant-price.ts +1 -1
- package/src/lib/mysql/schemas/commerce/merchant-product.ts +1 -1
- package/src/lib/mysql/schemas/commerce/merchant-session.ts +1 -1
- package/src/lib/mysql/schemas/commerce/price.ts +1 -1
- package/src/lib/mysql/schemas/commerce/product.ts +1 -1
- package/src/lib/mysql/schemas/commerce/purchase-user-transfer.ts +1 -1
- package/src/lib/mysql/schemas/commerce/purchase.ts +5 -4
- package/src/lib/mysql/schemas/commerce/upgradable-products.ts +1 -1
- package/src/lib/mysql/schemas/communication/comment.ts +52 -0
- package/src/lib/mysql/schemas/communication/communication-channel.ts +1 -1
- package/src/lib/mysql/schemas/communication/communication-preference-types.ts +1 -1
- package/src/lib/mysql/schemas/communication/communication-preferences.ts +1 -1
- package/src/lib/mysql/schemas/content/content-contributions.ts +1 -1
- package/src/lib/mysql/schemas/content/content-resource-product.ts +1 -1
- package/src/lib/mysql/schemas/content/content-resource-resource.ts +1 -1
- package/src/lib/mysql/schemas/content/content-resource.ts +6 -2
- package/src/lib/mysql/schemas/content/contribution-types.ts +1 -1
- package/src/lib/mysql/schemas/content/lesson-progress.ts +39 -0
- package/src/lib/mysql/schemas/content/resource-progress.ts +6 -8
package/src/lib/mysql/index.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { AdapterSession, AdapterUser } from '@auth/core/adapters'
|
|
2
|
+
import slugify from '@sindresorhus/slugify'
|
|
2
3
|
import { addSeconds, isAfter } from 'date-fns'
|
|
3
4
|
import {
|
|
4
5
|
and,
|
|
5
6
|
asc,
|
|
7
|
+
count,
|
|
6
8
|
desc,
|
|
7
9
|
eq,
|
|
8
10
|
gte,
|
|
@@ -18,6 +20,7 @@ import {
|
|
|
18
20
|
MySqlDatabase,
|
|
19
21
|
MySqlTableFn,
|
|
20
22
|
} from 'drizzle-orm/mysql-core'
|
|
23
|
+
import { customAlphabet } from 'nanoid'
|
|
21
24
|
import { v4 } from 'uuid'
|
|
22
25
|
import { z } from 'zod'
|
|
23
26
|
|
|
@@ -33,6 +36,7 @@ import {
|
|
|
33
36
|
merchantPriceSchema,
|
|
34
37
|
MerchantProduct,
|
|
35
38
|
merchantProductSchema,
|
|
39
|
+
NewProduct,
|
|
36
40
|
Price,
|
|
37
41
|
priceSchema,
|
|
38
42
|
Product,
|
|
@@ -50,13 +54,16 @@ import {
|
|
|
50
54
|
userSchema,
|
|
51
55
|
} from '@coursebuilder/core/schemas'
|
|
52
56
|
import {
|
|
57
|
+
ContentResourceProductSchema,
|
|
53
58
|
ContentResourceResourceSchema,
|
|
54
59
|
ContentResourceSchema,
|
|
60
|
+
type ContentResource,
|
|
55
61
|
} from '@coursebuilder/core/schemas/content-resource-schema'
|
|
56
62
|
import { merchantAccountSchema } from '@coursebuilder/core/schemas/merchant-account-schema'
|
|
57
63
|
import { merchantCustomerSchema } from '@coursebuilder/core/schemas/merchant-customer-schema'
|
|
58
64
|
import { type ModuleProgress } from '@coursebuilder/core/schemas/resource-progress-schema'
|
|
59
65
|
import { VideoResourceSchema } from '@coursebuilder/core/schemas/video-resource'
|
|
66
|
+
import { PaymentsProviderConfig } from '@coursebuilder/core/types'
|
|
60
67
|
import { logger } from '@coursebuilder/core/utils/logger'
|
|
61
68
|
import { validateCoupon } from '@coursebuilder/core/utils/validate-coupon'
|
|
62
69
|
|
|
@@ -64,6 +71,14 @@ import {
|
|
|
64
71
|
getAccountsRelationsSchema,
|
|
65
72
|
getAccountsSchema,
|
|
66
73
|
} from './schemas/auth/accounts.js'
|
|
74
|
+
import {
|
|
75
|
+
getDeviceAccessTokenRelationsSchema,
|
|
76
|
+
getDeviceAccessTokenSchema,
|
|
77
|
+
} from './schemas/auth/device-access-token.js'
|
|
78
|
+
import {
|
|
79
|
+
getDeviceVerificationRelationsSchema,
|
|
80
|
+
getDeviceVerificationSchema,
|
|
81
|
+
} from './schemas/auth/device-verification.js'
|
|
67
82
|
import {
|
|
68
83
|
getPermissionsRelationsSchema,
|
|
69
84
|
getPermissionsSchema,
|
|
@@ -84,6 +99,10 @@ import {
|
|
|
84
99
|
getUserPermissionsRelationsSchema,
|
|
85
100
|
getUserPermissionsSchema,
|
|
86
101
|
} from './schemas/auth/user-permissions.js'
|
|
102
|
+
import {
|
|
103
|
+
getUserPrefsRelationsSchema,
|
|
104
|
+
getUserPrefsSchema,
|
|
105
|
+
} from './schemas/auth/user-prefs.js'
|
|
87
106
|
import {
|
|
88
107
|
getUserRolesRelationsSchema,
|
|
89
108
|
getUserRolesSchema,
|
|
@@ -124,6 +143,10 @@ import {
|
|
|
124
143
|
getUpgradableProductsRelationsSchema,
|
|
125
144
|
getUpgradableProductsSchema,
|
|
126
145
|
} from './schemas/commerce/upgradable-products.js'
|
|
146
|
+
import {
|
|
147
|
+
getCommentRelationsSchema,
|
|
148
|
+
getCommentsSchema,
|
|
149
|
+
} from './schemas/communication/comment.js'
|
|
127
150
|
import { getCommunicationChannelSchema } from './schemas/communication/communication-channel.js'
|
|
128
151
|
import { getCommunicationPreferenceTypesSchema } from './schemas/communication/communication-preference-types.js'
|
|
129
152
|
import {
|
|
@@ -150,8 +173,11 @@ import {
|
|
|
150
173
|
getContributionTypesRelationsSchema,
|
|
151
174
|
getContributionTypesSchema,
|
|
152
175
|
} from './schemas/content/contribution-types.js'
|
|
176
|
+
import { getLessonProgressSchema } from './schemas/content/lesson-progress.js'
|
|
153
177
|
import { getResourceProgressSchema } from './schemas/content/resource-progress.js'
|
|
154
178
|
|
|
179
|
+
export const guid = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz', 5)
|
|
180
|
+
|
|
155
181
|
export function getCourseBuilderSchema(mysqlTable: MySqlTableFn) {
|
|
156
182
|
return {
|
|
157
183
|
accounts: getAccountsSchema(mysqlTable),
|
|
@@ -173,6 +199,7 @@ export function getCourseBuilderSchema(mysqlTable: MySqlTableFn) {
|
|
|
173
199
|
verificationTokens: getVerificationTokensSchema(mysqlTable),
|
|
174
200
|
coupon: getCouponSchema(mysqlTable),
|
|
175
201
|
couponRelations: getCouponRelationsSchema(mysqlTable),
|
|
202
|
+
lessonProgress: getLessonProgressSchema(mysqlTable),
|
|
176
203
|
merchantAccount: getMerchantAccountSchema(mysqlTable),
|
|
177
204
|
merchantCharge: getMerchantChargeSchema(mysqlTable),
|
|
178
205
|
merchantChargeRelations: getMerchantChargeRelationsSchema(mysqlTable),
|
|
@@ -212,6 +239,15 @@ export function getCourseBuilderSchema(mysqlTable: MySqlTableFn) {
|
|
|
212
239
|
contentResourceProductRelations:
|
|
213
240
|
getContentResourceProductRelationsSchema(mysqlTable),
|
|
214
241
|
productRelations: getProductRelationsSchema(mysqlTable),
|
|
242
|
+
comments: getCommentsSchema(mysqlTable),
|
|
243
|
+
commentsRelations: getCommentRelationsSchema(mysqlTable),
|
|
244
|
+
deviceVerifications: getDeviceVerificationSchema(mysqlTable),
|
|
245
|
+
deviceVerificationRelations:
|
|
246
|
+
getDeviceVerificationRelationsSchema(mysqlTable),
|
|
247
|
+
deviceAccessToken: getDeviceAccessTokenSchema(mysqlTable),
|
|
248
|
+
deviceAccessTokenRelations: getDeviceAccessTokenRelationsSchema(mysqlTable),
|
|
249
|
+
userPrefs: getUserPrefsSchema(mysqlTable),
|
|
250
|
+
userPrefsRelations: getUserPrefsRelationsSchema(mysqlTable),
|
|
215
251
|
} as const
|
|
216
252
|
}
|
|
217
253
|
|
|
@@ -224,6 +260,7 @@ export type DefaultSchema = ReturnType<typeof createTables>
|
|
|
224
260
|
export function mySqlDrizzleAdapter(
|
|
225
261
|
client: InstanceType<typeof MySqlDatabase>,
|
|
226
262
|
tableFn = defaultMySqlTableFn,
|
|
263
|
+
paymentProvider?: PaymentsProviderConfig,
|
|
227
264
|
): CourseBuilderAdapter<typeof MySqlDatabase> {
|
|
228
265
|
const {
|
|
229
266
|
users,
|
|
@@ -232,6 +269,7 @@ export function mySqlDrizzleAdapter(
|
|
|
232
269
|
verificationTokens,
|
|
233
270
|
contentResource,
|
|
234
271
|
contentResourceResource,
|
|
272
|
+
contentResourceProduct,
|
|
235
273
|
purchases: purchaseTable,
|
|
236
274
|
purchaseUserTransfer,
|
|
237
275
|
coupon,
|
|
@@ -246,6 +284,7 @@ export function mySqlDrizzleAdapter(
|
|
|
246
284
|
products,
|
|
247
285
|
upgradableProducts,
|
|
248
286
|
resourceProgress,
|
|
287
|
+
comments,
|
|
249
288
|
} = createTables(tableFn)
|
|
250
289
|
|
|
251
290
|
const adapter: CourseBuilderAdapter = {
|
|
@@ -273,7 +312,7 @@ export function mySqlDrizzleAdapter(
|
|
|
273
312
|
if (coupon && couponValidation.isRedeemable) {
|
|
274
313
|
// if the Coupon is the Bulk Coupon of a Bulk Purchase,
|
|
275
314
|
// then a bulk coupon is being redeemed
|
|
276
|
-
const bulkCouponRedemption = Boolean(coupon.
|
|
315
|
+
const bulkCouponRedemption = Boolean(coupon.maxUses > 1)
|
|
277
316
|
|
|
278
317
|
const { user } = await adapter.findOrCreateUser(email)
|
|
279
318
|
|
|
@@ -294,8 +333,18 @@ export function mySqlDrizzleAdapter(
|
|
|
294
333
|
productId,
|
|
295
334
|
})
|
|
296
335
|
|
|
297
|
-
if (existingPurchases.length > 0)
|
|
298
|
-
|
|
336
|
+
if (existingPurchases.length > 0) {
|
|
337
|
+
const errorMessage = `already-purchased-${email}`
|
|
338
|
+
console.error(errorMessage)
|
|
339
|
+
return {
|
|
340
|
+
error: {
|
|
341
|
+
message: errorMessage,
|
|
342
|
+
},
|
|
343
|
+
redeemingForCurrentUser,
|
|
344
|
+
purchase: null,
|
|
345
|
+
}
|
|
346
|
+
throw new Error(errorMessage)
|
|
347
|
+
}
|
|
299
348
|
|
|
300
349
|
const purchaseId = `purchase-${v4()}`
|
|
301
350
|
|
|
@@ -379,7 +428,10 @@ export function mySqlDrizzleAdapter(
|
|
|
379
428
|
},
|
|
380
429
|
getMerchantPriceForProductId: async (productId) => {
|
|
381
430
|
const merchantPriceData = await client.query.merchantPrice.findFirst({
|
|
382
|
-
where:
|
|
431
|
+
where: and(
|
|
432
|
+
eq(merchantPrice.merchantProductId, productId),
|
|
433
|
+
eq(merchantPrice.status, 1),
|
|
434
|
+
),
|
|
383
435
|
})
|
|
384
436
|
|
|
385
437
|
const parsedMerchantPrice =
|
|
@@ -432,7 +484,7 @@ export function mySqlDrizzleAdapter(
|
|
|
432
484
|
)
|
|
433
485
|
|
|
434
486
|
if (previousPurchaseProductIds.length > 0) {
|
|
435
|
-
return
|
|
487
|
+
return client.query.upgradableProducts.findMany({
|
|
436
488
|
where: and(
|
|
437
489
|
eq(upgradableProducts.upgradableToId, productId),
|
|
438
490
|
inArray(
|
|
@@ -461,7 +513,7 @@ export function mySqlDrizzleAdapter(
|
|
|
461
513
|
let lessonProgress = await client.query.resourceProgress.findFirst({
|
|
462
514
|
where: and(
|
|
463
515
|
eq(resourceProgress.userId, options.userId),
|
|
464
|
-
eq(resourceProgress.
|
|
516
|
+
eq(resourceProgress.resourceId, options.lessonId),
|
|
465
517
|
),
|
|
466
518
|
})
|
|
467
519
|
|
|
@@ -475,12 +527,12 @@ export function mySqlDrizzleAdapter(
|
|
|
475
527
|
completedAt: now,
|
|
476
528
|
updatedAt: now,
|
|
477
529
|
})
|
|
478
|
-
.where(eq(resourceProgress.
|
|
530
|
+
.where(eq(resourceProgress.resourceId, options.lessonId))
|
|
479
531
|
}
|
|
480
532
|
} else {
|
|
481
533
|
await client.insert(resourceProgress).values({
|
|
482
534
|
userId: options.userId,
|
|
483
|
-
|
|
535
|
+
resourceId: options.lessonId,
|
|
484
536
|
completedAt: now,
|
|
485
537
|
updatedAt: now,
|
|
486
538
|
})
|
|
@@ -488,7 +540,7 @@ export function mySqlDrizzleAdapter(
|
|
|
488
540
|
lessonProgress = await client.query.resourceProgress.findFirst({
|
|
489
541
|
where: and(
|
|
490
542
|
eq(resourceProgress.userId, options.userId),
|
|
491
|
-
eq(resourceProgress.
|
|
543
|
+
eq(resourceProgress.resourceId, options.lessonId),
|
|
492
544
|
),
|
|
493
545
|
})
|
|
494
546
|
const parsedLessonProgress =
|
|
@@ -530,11 +582,21 @@ export function mySqlDrizzleAdapter(
|
|
|
530
582
|
|
|
531
583
|
if (!couponForIdOrCode) return null
|
|
532
584
|
|
|
533
|
-
|
|
585
|
+
const parsedCoupon = couponSchema
|
|
534
586
|
.extend({
|
|
535
587
|
merchantCoupon: merchantCouponSchema,
|
|
536
588
|
})
|
|
537
|
-
.
|
|
589
|
+
.safeParse(couponForIdOrCode)
|
|
590
|
+
|
|
591
|
+
if (!parsedCoupon.success) {
|
|
592
|
+
console.error(
|
|
593
|
+
'Error parsing coupon',
|
|
594
|
+
JSON.stringify(parsedCoupon.error),
|
|
595
|
+
)
|
|
596
|
+
return null
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
return parsedCoupon.data
|
|
538
600
|
},
|
|
539
601
|
async createMerchantChargeAndPurchase(options): Promise<Purchase> {
|
|
540
602
|
const purchaseId = await client.transaction(async (trx) => {
|
|
@@ -620,7 +682,7 @@ export function mySqlDrizzleAdapter(
|
|
|
620
682
|
),
|
|
621
683
|
)
|
|
622
684
|
.then((res) => {
|
|
623
|
-
return res[0]?.
|
|
685
|
+
return res[0]?.Coupon ?? null
|
|
624
686
|
}),
|
|
625
687
|
)
|
|
626
688
|
|
|
@@ -830,20 +892,21 @@ export function mySqlDrizzleAdapter(
|
|
|
830
892
|
},
|
|
831
893
|
async getCouponWithBulkPurchases(couponId: string): Promise<
|
|
832
894
|
| (Coupon & {
|
|
833
|
-
|
|
834
|
-
|
|
895
|
+
bulkPurchases?: Purchase[] | null
|
|
896
|
+
redeemedBulkCouponPurchases: { bulkCouponId?: string | null }[]
|
|
835
897
|
})
|
|
836
898
|
| null
|
|
837
899
|
> {
|
|
838
900
|
logger.debug('getCouponWithBulkPurchases', { couponId })
|
|
839
901
|
let couponData
|
|
902
|
+
let bulkCouponPurchases
|
|
840
903
|
try {
|
|
841
904
|
couponData =
|
|
842
905
|
(await client.query.coupon.findFirst({
|
|
843
906
|
where: eq(coupon.id, couponId),
|
|
844
907
|
with: {
|
|
845
|
-
|
|
846
|
-
|
|
908
|
+
bulkPurchases: true,
|
|
909
|
+
redeemedBulkCouponPurchases: true,
|
|
847
910
|
},
|
|
848
911
|
})) || null
|
|
849
912
|
} catch (e) {
|
|
@@ -851,6 +914,19 @@ export function mySqlDrizzleAdapter(
|
|
|
851
914
|
logger.error(e as Error)
|
|
852
915
|
}
|
|
853
916
|
|
|
917
|
+
try {
|
|
918
|
+
bulkCouponPurchases = await client.query.purchases.findMany({
|
|
919
|
+
where: eq(purchaseTable.redeemedBulkCouponId, couponId),
|
|
920
|
+
with: {
|
|
921
|
+
user: true,
|
|
922
|
+
},
|
|
923
|
+
})
|
|
924
|
+
console.log('purchases with redeemedBulkCouponId', bulkCouponPurchases)
|
|
925
|
+
} catch (e) {
|
|
926
|
+
console.log('getCouponWithBulkPurchases')
|
|
927
|
+
logger.error(e as Error)
|
|
928
|
+
}
|
|
929
|
+
|
|
854
930
|
if (!couponData) {
|
|
855
931
|
logger.debug('getCouponWithBulkPurchases', {
|
|
856
932
|
couponId,
|
|
@@ -859,20 +935,29 @@ export function mySqlDrizzleAdapter(
|
|
|
859
935
|
return null
|
|
860
936
|
}
|
|
861
937
|
|
|
938
|
+
const couponWithBulkPurchases = {
|
|
939
|
+
...couponData,
|
|
940
|
+
redeemedBulkCouponPurchases: bulkCouponPurchases || [],
|
|
941
|
+
}
|
|
942
|
+
|
|
862
943
|
const parsedCoupon = couponSchema
|
|
863
944
|
.merge(
|
|
864
945
|
z.object({
|
|
865
|
-
|
|
866
|
-
bulkPurchase: purchaseSchema.nullable().optional(),
|
|
946
|
+
redeemedBulkCouponPurchases: z.array(purchaseSchema),
|
|
867
947
|
}),
|
|
868
948
|
)
|
|
869
949
|
.nullable()
|
|
870
|
-
.safeParse(
|
|
950
|
+
.safeParse(couponWithBulkPurchases)
|
|
871
951
|
|
|
872
952
|
if (!parsedCoupon.success) {
|
|
873
|
-
console.error(
|
|
953
|
+
console.error(
|
|
954
|
+
'Error parsing coupon',
|
|
955
|
+
JSON.stringify(parsedCoupon.error),
|
|
956
|
+
couponData,
|
|
957
|
+
)
|
|
874
958
|
return null
|
|
875
959
|
}
|
|
960
|
+
|
|
876
961
|
return parsedCoupon.data
|
|
877
962
|
},
|
|
878
963
|
async getDefaultCoupon(productIds?: string[]): Promise<{
|
|
@@ -941,146 +1026,115 @@ export function mySqlDrizzleAdapter(
|
|
|
941
1026
|
async getModuleProgressForUser(
|
|
942
1027
|
userIdOrEmail: string,
|
|
943
1028
|
moduleIdOrSlug: string,
|
|
944
|
-
): Promise<ModuleProgress> {
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
moduleIdOrSlug,
|
|
951
|
-
),
|
|
952
|
-
),
|
|
953
|
-
with: {
|
|
954
|
-
resources: {
|
|
955
|
-
orderBy: asc(contentResourceResource.position),
|
|
956
|
-
},
|
|
1029
|
+
): Promise<ModuleProgress | null> {
|
|
1030
|
+
// First, get the user ID
|
|
1031
|
+
const user = await client.query.users.findFirst({
|
|
1032
|
+
where: or(eq(users.id, userIdOrEmail), eq(users.email, userIdOrEmail)),
|
|
1033
|
+
columns: {
|
|
1034
|
+
id: true,
|
|
957
1035
|
},
|
|
958
1036
|
})
|
|
959
1037
|
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
await client.query.contentResourceResource.findMany({
|
|
964
|
-
where: inArray(
|
|
965
|
-
contentResourceResource.resourceOfId,
|
|
966
|
-
parsedModule.resources?.map((r) => r.resourceId) ?? [],
|
|
967
|
-
),
|
|
968
|
-
orderBy: asc(contentResourceResource.position),
|
|
969
|
-
})
|
|
1038
|
+
if (!user) {
|
|
1039
|
+
return null
|
|
1040
|
+
}
|
|
970
1041
|
|
|
971
|
-
const
|
|
972
|
-
.
|
|
973
|
-
.
|
|
1042
|
+
const ResultRowSchema = z.object({
|
|
1043
|
+
resource_id: z.string(),
|
|
1044
|
+
resource_type: z.enum(['lesson', 'exercise']),
|
|
1045
|
+
resource_slug: z.string().nullable(),
|
|
1046
|
+
completed_at: z
|
|
1047
|
+
.string()
|
|
1048
|
+
.nullable()
|
|
1049
|
+
.transform((val) => (val ? new Date(val) : null)),
|
|
1050
|
+
})
|
|
974
1051
|
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1052
|
+
// Execute the optimized query
|
|
1053
|
+
const results: any = await client.execute(sql`
|
|
1054
|
+
SELECT
|
|
1055
|
+
cr.id AS resource_id,
|
|
1056
|
+
cr.type AS resource_type,
|
|
1057
|
+
cr.fields->>'$.slug' AS resource_slug,
|
|
1058
|
+
rp.completedAt AS completed_at
|
|
1059
|
+
FROM
|
|
1060
|
+
(SELECT id, fields->>'$.slug' AS slug
|
|
1061
|
+
FROM ${contentResource}
|
|
1062
|
+
WHERE id = ${moduleIdOrSlug}
|
|
1063
|
+
OR fields->>'$.slug' = ${moduleIdOrSlug}) AS w
|
|
1064
|
+
LEFT JOIN
|
|
1065
|
+
(SELECT
|
|
1066
|
+
crr.resourceOfId AS workshop_id,
|
|
1067
|
+
crr.resourceId,
|
|
1068
|
+
crr.position
|
|
1069
|
+
FROM ${contentResourceResource} crr) AS tlr ON w.id = tlr.workshop_id
|
|
1070
|
+
LEFT JOIN ${contentResource} sections ON sections.id = tlr.resourceId AND sections.type = 'section'
|
|
1071
|
+
LEFT JOIN
|
|
1072
|
+
(SELECT
|
|
1073
|
+
crr.resourceOfId AS section_id,
|
|
1074
|
+
crr.resourceId AS resource_id,
|
|
1075
|
+
crr.position AS position_in_section,
|
|
1076
|
+
section_crr.position AS section_position
|
|
1077
|
+
FROM ${contentResourceResource} crr
|
|
1078
|
+
JOIN ${contentResourceResource} section_crr ON crr.resourceOfId = section_crr.resourceId) AS sr
|
|
1079
|
+
ON sr.section_id = sections.id
|
|
1080
|
+
JOIN ${contentResource} cr ON cr.id = COALESCE(sr.resource_id, tlr.resourceId)
|
|
1081
|
+
LEFT JOIN ${resourceProgress} rp ON rp.resourceId = cr.id
|
|
1082
|
+
AND rp.userId = ${user.id}
|
|
1083
|
+
WHERE
|
|
1084
|
+
cr.type IN ('lesson', 'exercise')
|
|
1085
|
+
|
|
1086
|
+
`)
|
|
1087
|
+
|
|
1088
|
+
// Process the results
|
|
1089
|
+
const completedLessons: ResourceProgress[] = []
|
|
1090
|
+
let nextResource: Partial<ContentResource> | null = null
|
|
1091
|
+
let completedLessonsCount = 0
|
|
1092
|
+
let totalLessonsCount = results.rows.length
|
|
1093
|
+
|
|
1094
|
+
const parsedRows = z.array(ResultRowSchema).safeParse(results.rows)
|
|
1095
|
+
|
|
1096
|
+
if (!parsedRows.success) {
|
|
1097
|
+
console.error('Error parsing rows', parsedRows.error)
|
|
980
1098
|
return {
|
|
981
1099
|
completedLessons: [],
|
|
982
1100
|
nextResource: null,
|
|
983
1101
|
percentCompleted: 0,
|
|
984
1102
|
completedLessonsCount: 0,
|
|
985
|
-
totalLessonsCount
|
|
1103
|
+
totalLessonsCount,
|
|
986
1104
|
}
|
|
987
1105
|
}
|
|
988
1106
|
|
|
989
|
-
const
|
|
990
|
-
.
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1107
|
+
for (const row of parsedRows.data) {
|
|
1108
|
+
if (row.completed_at) {
|
|
1109
|
+
completedLessonsCount++
|
|
1110
|
+
completedLessons.push({
|
|
1111
|
+
userId: user.id as string,
|
|
1112
|
+
resourceId: row.resource_id,
|
|
1113
|
+
completedAt: new Date(row.completed_at),
|
|
1114
|
+
// Add other fields as needed
|
|
1115
|
+
})
|
|
1116
|
+
} else if (!nextResource) {
|
|
1117
|
+
nextResource = {
|
|
1118
|
+
id: row.resource_id,
|
|
1119
|
+
type: row.resource_type,
|
|
1120
|
+
fields: {
|
|
1121
|
+
slug: row.resource_slug,
|
|
1000
1122
|
},
|
|
1001
|
-
},
|
|
1002
|
-
})
|
|
1003
|
-
.then(async (res) => {
|
|
1004
|
-
if (res) {
|
|
1005
|
-
return {
|
|
1006
|
-
...res,
|
|
1007
|
-
roles: res.roles.map((r) => r.role),
|
|
1008
|
-
}
|
|
1009
1123
|
}
|
|
1010
|
-
})
|
|
1011
|
-
|
|
1012
|
-
if (!user) {
|
|
1013
|
-
console.error('User not found', userIdOrEmail)
|
|
1014
|
-
return {
|
|
1015
|
-
completedLessons: [],
|
|
1016
|
-
nextResource: null,
|
|
1017
|
-
percentCompleted: 0,
|
|
1018
|
-
completedLessonsCount: 0,
|
|
1019
|
-
totalLessonsCount: parsedModuleResources.data.length,
|
|
1020
1124
|
}
|
|
1021
1125
|
}
|
|
1022
1126
|
|
|
1023
|
-
const
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
return {
|
|
1028
|
-
completedLessons: [],
|
|
1029
|
-
nextResource: null,
|
|
1030
|
-
percentCompleted: 0,
|
|
1031
|
-
completedLessonsCount: 0,
|
|
1032
|
-
totalLessonsCount: parsedModuleResources.data.length,
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
const userProgress = await client.query.resourceProgress.findMany({
|
|
1037
|
-
where: and(
|
|
1038
|
-
eq(resourceProgress.userId, parsedUser.data.id),
|
|
1039
|
-
isNotNull(resourceProgress.completedAt),
|
|
1040
|
-
inArray(
|
|
1041
|
-
resourceProgress.contentResourceId,
|
|
1042
|
-
parsedModuleResources.data.map((r) => r.resourceId),
|
|
1043
|
-
),
|
|
1044
|
-
),
|
|
1045
|
-
orderBy: asc(resourceProgress.completedAt),
|
|
1046
|
-
})
|
|
1047
|
-
|
|
1048
|
-
const nextResourceId = moduleResources.find(
|
|
1049
|
-
(r) => !userProgress.find((p) => p.contentResourceId === r.resourceId),
|
|
1050
|
-
)?.resourceId
|
|
1051
|
-
|
|
1052
|
-
const nextResource = await client.query.contentResource.findFirst({
|
|
1053
|
-
where: eq(contentResource.id, nextResourceId as string),
|
|
1054
|
-
})
|
|
1055
|
-
|
|
1056
|
-
const parsedNextResource = ContentResourceSchema.nullable()
|
|
1057
|
-
.optional()
|
|
1058
|
-
.default(null)
|
|
1059
|
-
.parse(nextResource)
|
|
1060
|
-
|
|
1061
|
-
const parsedProgress = z
|
|
1062
|
-
.array(resourceProgressSchema)
|
|
1063
|
-
.safeParse(userProgress)
|
|
1064
|
-
if (!parsedProgress.success) {
|
|
1065
|
-
console.error('Error parsing user progress', parsedProgress.error)
|
|
1066
|
-
return {
|
|
1067
|
-
completedLessons: [],
|
|
1068
|
-
nextResource: null,
|
|
1069
|
-
percentCompleted: 0,
|
|
1070
|
-
completedLessonsCount: 0,
|
|
1071
|
-
totalLessonsCount: parsedModuleResources.data.length,
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
const percentCompleted = Math.round(
|
|
1075
|
-
(parsedProgress.data.length / parsedModuleResources.data.length) * 100,
|
|
1076
|
-
)
|
|
1127
|
+
const percentCompleted =
|
|
1128
|
+
totalLessonsCount > 0
|
|
1129
|
+
? Math.ceil((completedLessonsCount / totalLessonsCount) * 100)
|
|
1130
|
+
: 0
|
|
1077
1131
|
|
|
1078
1132
|
return {
|
|
1079
|
-
completedLessons
|
|
1080
|
-
nextResource
|
|
1133
|
+
completedLessons,
|
|
1134
|
+
nextResource,
|
|
1081
1135
|
percentCompleted,
|
|
1082
|
-
completedLessonsCount
|
|
1083
|
-
totalLessonsCount
|
|
1136
|
+
completedLessonsCount,
|
|
1137
|
+
totalLessonsCount,
|
|
1084
1138
|
}
|
|
1085
1139
|
},
|
|
1086
1140
|
getLessonProgresses(): Promise<ResourceProgress[]> {
|
|
@@ -1094,7 +1148,7 @@ export function mySqlDrizzleAdapter(
|
|
|
1094
1148
|
})
|
|
1095
1149
|
const parsed = merchantChargeSchema.safeParse(mCharge)
|
|
1096
1150
|
if (!parsed.success) {
|
|
1097
|
-
console.
|
|
1151
|
+
console.info('Error parsing merchantCharge', mCharge)
|
|
1098
1152
|
return null
|
|
1099
1153
|
}
|
|
1100
1154
|
return parsed.data
|
|
@@ -1173,12 +1227,366 @@ export function mySqlDrizzleAdapter(
|
|
|
1173
1227
|
}),
|
|
1174
1228
|
)
|
|
1175
1229
|
},
|
|
1176
|
-
async
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1230
|
+
async archiveProduct(productId) {
|
|
1231
|
+
if (!paymentProvider) throw new Error('Payment provider not found')
|
|
1232
|
+
const product = await adapter.getProduct(productId)
|
|
1233
|
+
|
|
1234
|
+
if (!product) {
|
|
1235
|
+
throw new Error(`Product not found for id (${productId})`)
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
if (!product.price) {
|
|
1239
|
+
throw new Error(`Product has no price`)
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
await client
|
|
1243
|
+
.update(products)
|
|
1244
|
+
.set({ status: 0, name: `${product.name} (Archived)` })
|
|
1245
|
+
.where(eq(products.id, productId))
|
|
1246
|
+
|
|
1247
|
+
await client
|
|
1248
|
+
.update(prices)
|
|
1249
|
+
.set({ status: 0, nickname: `${product.name} (Archived)` })
|
|
1250
|
+
.where(eq(prices.productId, productId))
|
|
1251
|
+
|
|
1252
|
+
await client
|
|
1253
|
+
.update(merchantProduct)
|
|
1254
|
+
.set({ status: 0 })
|
|
1255
|
+
.where(eq(merchantProduct.productId, productId))
|
|
1256
|
+
|
|
1257
|
+
await client
|
|
1258
|
+
.update(merchantPrice)
|
|
1259
|
+
.set({ status: 0 })
|
|
1260
|
+
.where(eq(merchantPrice.priceId, product.price.id))
|
|
1261
|
+
|
|
1262
|
+
const currentMerchantProduct = merchantProductSchema.nullish().parse(
|
|
1263
|
+
await client.query.merchantProduct.findFirst({
|
|
1264
|
+
where: eq(merchantProduct.productId, productId),
|
|
1180
1265
|
}),
|
|
1181
1266
|
)
|
|
1267
|
+
|
|
1268
|
+
if (!currentMerchantProduct || !currentMerchantProduct.identifier) {
|
|
1269
|
+
throw new Error(`Merchant product not found for id (${productId})`)
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
await paymentProvider.updateProduct(currentMerchantProduct.identifier, {
|
|
1273
|
+
active: false,
|
|
1274
|
+
})
|
|
1275
|
+
|
|
1276
|
+
const currentMerchantPrice = merchantPriceSchema.nullish().parse(
|
|
1277
|
+
await client.query.merchantPrice.findFirst({
|
|
1278
|
+
where: and(
|
|
1279
|
+
eq(merchantPrice.priceId, product.price.id),
|
|
1280
|
+
eq(merchantPrice.status, 1),
|
|
1281
|
+
),
|
|
1282
|
+
}),
|
|
1283
|
+
)
|
|
1284
|
+
|
|
1285
|
+
if (!currentMerchantPrice || !currentMerchantPrice.identifier) {
|
|
1286
|
+
throw new Error(`Merchant price not found for id (${productId})`)
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
await paymentProvider.updatePrice(currentMerchantPrice.identifier, {
|
|
1290
|
+
active: false,
|
|
1291
|
+
})
|
|
1292
|
+
|
|
1293
|
+
return adapter.getProduct(productId)
|
|
1294
|
+
},
|
|
1295
|
+
async updateProduct(input: Product) {
|
|
1296
|
+
if (!paymentProvider) throw new Error('Payment provider not found')
|
|
1297
|
+
const currentProduct = await adapter.getProduct(input.id)
|
|
1298
|
+
if (!currentProduct) {
|
|
1299
|
+
throw new Error(`Product not found`)
|
|
1300
|
+
}
|
|
1301
|
+
if (!currentProduct.price) {
|
|
1302
|
+
throw new Error(`Product has no price`)
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
const merchantProduct = merchantProductSchema.nullish().parse(
|
|
1306
|
+
await client.query.merchantProduct.findFirst({
|
|
1307
|
+
where: (merchantProduct, { eq }) =>
|
|
1308
|
+
eq(merchantProduct.productId, input.id),
|
|
1309
|
+
}),
|
|
1310
|
+
)
|
|
1311
|
+
|
|
1312
|
+
if (!merchantProduct || !merchantProduct.identifier) {
|
|
1313
|
+
throw new Error(`Merchant product not found`)
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
// TODO: handle upgrades
|
|
1317
|
+
|
|
1318
|
+
const stripeProduct = await paymentProvider.getProduct(
|
|
1319
|
+
merchantProduct.identifier,
|
|
1320
|
+
)
|
|
1321
|
+
|
|
1322
|
+
const priceChanged =
|
|
1323
|
+
currentProduct.price.unitAmount.toString() !==
|
|
1324
|
+
input.price?.unitAmount.toString()
|
|
1325
|
+
|
|
1326
|
+
if (priceChanged) {
|
|
1327
|
+
const currentMerchantPrice = merchantPriceSchema.nullish().parse(
|
|
1328
|
+
await client.query.merchantPrice.findFirst({
|
|
1329
|
+
where: (merchantPrice, { eq, and }) =>
|
|
1330
|
+
and(
|
|
1331
|
+
eq(merchantPrice.merchantProductId, merchantProduct.id),
|
|
1332
|
+
eq(merchantPrice.status, 1),
|
|
1333
|
+
),
|
|
1334
|
+
}),
|
|
1335
|
+
)
|
|
1336
|
+
|
|
1337
|
+
if (!currentMerchantPrice || !currentMerchantPrice.identifier) {
|
|
1338
|
+
throw new Error(`Merchant price not found`)
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
const currentStripePrice = await paymentProvider.getPrice(
|
|
1342
|
+
currentMerchantPrice.identifier,
|
|
1343
|
+
)
|
|
1344
|
+
|
|
1345
|
+
const newStripePrice = await paymentProvider.createPrice({
|
|
1346
|
+
product: stripeProduct.id,
|
|
1347
|
+
unit_amount: Math.floor(Number(input.price?.unitAmount || 0) * 100),
|
|
1348
|
+
currency: 'usd',
|
|
1349
|
+
metadata: {
|
|
1350
|
+
slug: input.fields.slug,
|
|
1351
|
+
},
|
|
1352
|
+
active: true,
|
|
1353
|
+
})
|
|
1354
|
+
|
|
1355
|
+
await paymentProvider.updateProduct(stripeProduct.id, {
|
|
1356
|
+
default_price: newStripePrice.id,
|
|
1357
|
+
})
|
|
1358
|
+
|
|
1359
|
+
const newMerchantPriceId = `mprice_${v4()}`
|
|
1360
|
+
await client.insert(merchantPrice).values({
|
|
1361
|
+
id: newMerchantPriceId,
|
|
1362
|
+
merchantProductId: merchantProduct.id,
|
|
1363
|
+
merchantAccountId: merchantProduct.merchantAccountId,
|
|
1364
|
+
priceId: currentProduct.price.id,
|
|
1365
|
+
status: 1,
|
|
1366
|
+
identifier: newStripePrice.id,
|
|
1367
|
+
})
|
|
1368
|
+
|
|
1369
|
+
if (currentMerchantPrice) {
|
|
1370
|
+
await client
|
|
1371
|
+
.update(merchantPrice)
|
|
1372
|
+
.set({
|
|
1373
|
+
status: 0,
|
|
1374
|
+
})
|
|
1375
|
+
.where(eq(merchantPrice.id, currentMerchantPrice.id))
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
await client
|
|
1379
|
+
.update(prices)
|
|
1380
|
+
.set({
|
|
1381
|
+
unitAmount: Math.floor(
|
|
1382
|
+
Number(input.price?.unitAmount || 0),
|
|
1383
|
+
).toString(),
|
|
1384
|
+
nickname: input.name,
|
|
1385
|
+
})
|
|
1386
|
+
.where(eq(prices.id, currentProduct.price.id))
|
|
1387
|
+
|
|
1388
|
+
if (currentStripePrice) {
|
|
1389
|
+
await paymentProvider.updatePrice(currentStripePrice.id, {
|
|
1390
|
+
active: false,
|
|
1391
|
+
})
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
await paymentProvider.updateProduct(stripeProduct.id, {
|
|
1396
|
+
name: input.name,
|
|
1397
|
+
active: true,
|
|
1398
|
+
images: input.fields.image?.url ? [input.fields.image.url] : undefined,
|
|
1399
|
+
description: input.fields.description || '',
|
|
1400
|
+
metadata: {
|
|
1401
|
+
slug: input.fields.slug,
|
|
1402
|
+
},
|
|
1403
|
+
})
|
|
1404
|
+
|
|
1405
|
+
const { image, ...fieldsNoImage } = input.fields
|
|
1406
|
+
|
|
1407
|
+
await client
|
|
1408
|
+
.update(products)
|
|
1409
|
+
.set({
|
|
1410
|
+
name: input.name,
|
|
1411
|
+
quantityAvailable: input.quantityAvailable,
|
|
1412
|
+
status: 1,
|
|
1413
|
+
fields: {
|
|
1414
|
+
...fieldsNoImage,
|
|
1415
|
+
...(image?.url && { image }),
|
|
1416
|
+
},
|
|
1417
|
+
})
|
|
1418
|
+
.where(eq(products.id, currentProduct.id))
|
|
1419
|
+
|
|
1420
|
+
return adapter.getProduct(currentProduct.id)
|
|
1421
|
+
},
|
|
1422
|
+
async createProduct(input: NewProduct) {
|
|
1423
|
+
if (!paymentProvider) throw new Error('Payment provider not found')
|
|
1424
|
+
const merchantAccount = merchantAccountSchema.nullish().parse(
|
|
1425
|
+
await client.query.merchantAccount.findFirst({
|
|
1426
|
+
where: (merchantAccount, { eq }) =>
|
|
1427
|
+
eq(merchantAccount.label, 'stripe'),
|
|
1428
|
+
}),
|
|
1429
|
+
)
|
|
1430
|
+
|
|
1431
|
+
if (!merchantAccount) {
|
|
1432
|
+
throw new Error('Merchant account not found')
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
const hash = guid()
|
|
1436
|
+
const newProductId = slugify(`product-${hash}`)
|
|
1437
|
+
|
|
1438
|
+
const newProduct = {
|
|
1439
|
+
id: newProductId,
|
|
1440
|
+
name: input.name,
|
|
1441
|
+
status: 1,
|
|
1442
|
+
type: 'self-paced',
|
|
1443
|
+
quantityAvailable: input.quantityAvailable,
|
|
1444
|
+
fields: {
|
|
1445
|
+
state: 'draft',
|
|
1446
|
+
visibility: 'unlisted',
|
|
1447
|
+
slug: slugify(`${input.name}-${hash}`),
|
|
1448
|
+
},
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
await client.insert(products).values(newProduct)
|
|
1452
|
+
|
|
1453
|
+
const priceHash = guid()
|
|
1454
|
+
const newPriceId = `price-${priceHash}`
|
|
1455
|
+
|
|
1456
|
+
await client.insert(prices).values({
|
|
1457
|
+
id: newPriceId,
|
|
1458
|
+
productId: newProductId,
|
|
1459
|
+
unitAmount: input.price.toString(),
|
|
1460
|
+
status: 1,
|
|
1461
|
+
})
|
|
1462
|
+
|
|
1463
|
+
const product = await adapter.getProduct(newProductId)
|
|
1464
|
+
|
|
1465
|
+
const stripeProduct = await paymentProvider.createProduct({
|
|
1466
|
+
name: input.name,
|
|
1467
|
+
metadata: {
|
|
1468
|
+
slug: product?.fields?.slug || null,
|
|
1469
|
+
},
|
|
1470
|
+
})
|
|
1471
|
+
|
|
1472
|
+
const stripePrice = await paymentProvider.createPrice({
|
|
1473
|
+
product: stripeProduct.id,
|
|
1474
|
+
unit_amount: Math.floor(Number(input.price) * 100),
|
|
1475
|
+
currency: 'usd',
|
|
1476
|
+
nickname: input.name,
|
|
1477
|
+
metadata: {
|
|
1478
|
+
slug: product?.fields?.slug || null,
|
|
1479
|
+
},
|
|
1480
|
+
})
|
|
1481
|
+
|
|
1482
|
+
const newMerchantProductId = `mproduct_${v4()}`
|
|
1483
|
+
|
|
1484
|
+
await client.insert(merchantProduct).values({
|
|
1485
|
+
id: newMerchantProductId,
|
|
1486
|
+
merchantAccountId: merchantAccount.id,
|
|
1487
|
+
productId: newProductId,
|
|
1488
|
+
identifier: stripeProduct.id,
|
|
1489
|
+
status: 1,
|
|
1490
|
+
})
|
|
1491
|
+
|
|
1492
|
+
const newMerchantPriceId = `mprice_${v4()}`
|
|
1493
|
+
await client.insert(merchantPrice).values({
|
|
1494
|
+
id: newMerchantPriceId,
|
|
1495
|
+
merchantAccountId: merchantAccount.id,
|
|
1496
|
+
merchantProductId: newMerchantProductId,
|
|
1497
|
+
priceId: newPriceId,
|
|
1498
|
+
identifier: stripePrice.id,
|
|
1499
|
+
status: 1,
|
|
1500
|
+
})
|
|
1501
|
+
|
|
1502
|
+
// TODO: handle upgrades
|
|
1503
|
+
|
|
1504
|
+
return product
|
|
1505
|
+
},
|
|
1506
|
+
async getProduct(
|
|
1507
|
+
productSlugOrId?: string,
|
|
1508
|
+
withResources: boolean = true,
|
|
1509
|
+
): Promise<Product | null> {
|
|
1510
|
+
if (!productSlugOrId) {
|
|
1511
|
+
return null
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
try {
|
|
1515
|
+
const productData = await client.query.products.findFirst({
|
|
1516
|
+
where: and(
|
|
1517
|
+
or(
|
|
1518
|
+
eq(
|
|
1519
|
+
sql`JSON_EXTRACT (${products.fields}, "$.slug")`,
|
|
1520
|
+
`${productSlugOrId}`,
|
|
1521
|
+
),
|
|
1522
|
+
eq(products.id, productSlugOrId),
|
|
1523
|
+
),
|
|
1524
|
+
),
|
|
1525
|
+
with: {
|
|
1526
|
+
price: true,
|
|
1527
|
+
...(withResources && {
|
|
1528
|
+
resources: {
|
|
1529
|
+
with: {
|
|
1530
|
+
resource: {
|
|
1531
|
+
with: {
|
|
1532
|
+
resources: true,
|
|
1533
|
+
},
|
|
1534
|
+
},
|
|
1535
|
+
},
|
|
1536
|
+
},
|
|
1537
|
+
}),
|
|
1538
|
+
},
|
|
1539
|
+
})
|
|
1540
|
+
const parsedProduct = productSchema.safeParse(productData)
|
|
1541
|
+
if (!parsedProduct.success) {
|
|
1542
|
+
console.error(
|
|
1543
|
+
'Error parsing product',
|
|
1544
|
+
JSON.stringify(parsedProduct.error),
|
|
1545
|
+
JSON.stringify(productData),
|
|
1546
|
+
)
|
|
1547
|
+
return null
|
|
1548
|
+
}
|
|
1549
|
+
return parsedProduct.data
|
|
1550
|
+
} catch (e) {
|
|
1551
|
+
console.log('getProduct error', e)
|
|
1552
|
+
return null
|
|
1553
|
+
}
|
|
1554
|
+
},
|
|
1555
|
+
async getProductResources(
|
|
1556
|
+
productId: string,
|
|
1557
|
+
): Promise<ContentResource[] | null> {
|
|
1558
|
+
const contentResourceProductsForProduct = z
|
|
1559
|
+
.array(ContentResourceProductSchema)
|
|
1560
|
+
.nullable()
|
|
1561
|
+
.parse(
|
|
1562
|
+
await client.query.contentResourceProduct.findMany({
|
|
1563
|
+
where: eq(contentResourceProduct.productId, productId),
|
|
1564
|
+
}),
|
|
1565
|
+
)
|
|
1566
|
+
|
|
1567
|
+
if (!contentResourceProductsForProduct) {
|
|
1568
|
+
return null
|
|
1569
|
+
} else {
|
|
1570
|
+
const contentResources = z.array(ContentResourceSchema).parse(
|
|
1571
|
+
await client.query.contentResource.findMany({
|
|
1572
|
+
where: inArray(
|
|
1573
|
+
contentResource.id,
|
|
1574
|
+
contentResourceProductsForProduct.map((crp) => crp.resourceId),
|
|
1575
|
+
),
|
|
1576
|
+
}),
|
|
1577
|
+
)
|
|
1578
|
+
return contentResources
|
|
1579
|
+
}
|
|
1580
|
+
},
|
|
1581
|
+
async getPurchaseCountForProduct(productId: string): Promise<number> {
|
|
1582
|
+
return await client.query.purchases
|
|
1583
|
+
.findMany({
|
|
1584
|
+
where: and(
|
|
1585
|
+
eq(purchaseTable.productId, productId),
|
|
1586
|
+
inArray(purchaseTable.status, ['Valid', 'Restricted']),
|
|
1587
|
+
),
|
|
1588
|
+
})
|
|
1589
|
+
.then((res) => res.length)
|
|
1182
1590
|
},
|
|
1183
1591
|
async getPurchase(purchaseId: string): Promise<Purchase | null> {
|
|
1184
1592
|
const purchase = await client.query.purchases.findFirst({
|
|
@@ -1211,7 +1619,11 @@ export function mySqlDrizzleAdapter(
|
|
|
1211
1619
|
)
|
|
1212
1620
|
|
|
1213
1621
|
if (!chargeForPurchase) {
|
|
1214
|
-
logger.error(
|
|
1622
|
+
logger.error(
|
|
1623
|
+
new Error(
|
|
1624
|
+
`No charge found for purchase: Stripe Charge ID: ${stripeChargeId}`,
|
|
1625
|
+
),
|
|
1626
|
+
)
|
|
1215
1627
|
return null
|
|
1216
1628
|
}
|
|
1217
1629
|
|
|
@@ -1421,6 +1833,34 @@ export function mySqlDrizzleAdapter(
|
|
|
1421
1833
|
purchase: parsedPurchase.data,
|
|
1422
1834
|
}
|
|
1423
1835
|
},
|
|
1836
|
+
async getUserWithPurchasersByEmail(email: string): Promise<any | null> {
|
|
1837
|
+
const user = await client.query.users.findFirst({
|
|
1838
|
+
where: eq(users.email, email.trim().toLowerCase()),
|
|
1839
|
+
with: {
|
|
1840
|
+
// merchantCustomer: true,
|
|
1841
|
+
roles: {
|
|
1842
|
+
with: {
|
|
1843
|
+
role: true,
|
|
1844
|
+
},
|
|
1845
|
+
},
|
|
1846
|
+
purchases: {
|
|
1847
|
+
with: {
|
|
1848
|
+
bulkCoupon: true,
|
|
1849
|
+
merchantCharge: true,
|
|
1850
|
+
product: {
|
|
1851
|
+
columns: {
|
|
1852
|
+
id: true,
|
|
1853
|
+
name: true,
|
|
1854
|
+
key: true,
|
|
1855
|
+
},
|
|
1856
|
+
},
|
|
1857
|
+
},
|
|
1858
|
+
},
|
|
1859
|
+
},
|
|
1860
|
+
})
|
|
1861
|
+
|
|
1862
|
+
return user
|
|
1863
|
+
},
|
|
1424
1864
|
async getUserById(userId: string): Promise<User | null> {
|
|
1425
1865
|
const user = await client.query.users
|
|
1426
1866
|
.findFirst({
|
|
@@ -1497,7 +1937,7 @@ export function mySqlDrizzleAdapter(
|
|
|
1497
1937
|
let lessonProgress = await client.query.resourceProgress.findFirst({
|
|
1498
1938
|
where: and(
|
|
1499
1939
|
eq(resourceProgress.userId, options.userId),
|
|
1500
|
-
eq(resourceProgress.
|
|
1940
|
+
eq(resourceProgress.resourceId, options.lessonId),
|
|
1501
1941
|
),
|
|
1502
1942
|
})
|
|
1503
1943
|
|
|
@@ -1510,11 +1950,11 @@ export function mySqlDrizzleAdapter(
|
|
|
1510
1950
|
completedAt: lessonProgress.completedAt ? null : now,
|
|
1511
1951
|
updatedAt: now,
|
|
1512
1952
|
})
|
|
1513
|
-
.where(eq(resourceProgress.
|
|
1953
|
+
.where(eq(resourceProgress.resourceId, options.lessonId))
|
|
1514
1954
|
} else {
|
|
1515
1955
|
await client.insert(resourceProgress).values({
|
|
1516
1956
|
userId: options.userId,
|
|
1517
|
-
|
|
1957
|
+
resourceId: options.lessonId,
|
|
1518
1958
|
completedAt: now,
|
|
1519
1959
|
updatedAt: now,
|
|
1520
1960
|
})
|
|
@@ -1523,7 +1963,7 @@ export function mySqlDrizzleAdapter(
|
|
|
1523
1963
|
lessonProgress = await client.query.resourceProgress.findFirst({
|
|
1524
1964
|
where: and(
|
|
1525
1965
|
eq(resourceProgress.userId, options.userId),
|
|
1526
|
-
eq(resourceProgress.
|
|
1966
|
+
eq(resourceProgress.resourceId, options.lessonId),
|
|
1527
1967
|
),
|
|
1528
1968
|
})
|
|
1529
1969
|
|
|
@@ -1543,11 +1983,56 @@ export function mySqlDrizzleAdapter(
|
|
|
1543
1983
|
}): Promise<unknown> {
|
|
1544
1984
|
throw new Error('Method not implemented.')
|
|
1545
1985
|
},
|
|
1546
|
-
updatePurchaseStatusForCharge(
|
|
1986
|
+
async updatePurchaseStatusForCharge(
|
|
1547
1987
|
chargeId: string,
|
|
1548
1988
|
status: 'Valid' | 'Refunded' | 'Disputed' | 'Banned' | 'Restricted',
|
|
1549
1989
|
): Promise<Purchase | undefined> {
|
|
1550
|
-
|
|
1990
|
+
try {
|
|
1991
|
+
console.log('updatePurchaseStatusForCharge', { chargeId, status })
|
|
1992
|
+
const merchantChargeForPurchase =
|
|
1993
|
+
await client.query.merchantCharge.findFirst({
|
|
1994
|
+
where: or(
|
|
1995
|
+
eq(merchantCharge.identifier, chargeId),
|
|
1996
|
+
eq(merchantCharge.id, chargeId),
|
|
1997
|
+
),
|
|
1998
|
+
})
|
|
1999
|
+
|
|
2000
|
+
console.log('merchantChargeForPurchase', { merchantChargeForPurchase })
|
|
2001
|
+
|
|
2002
|
+
const parsedMerchantChargeForPurchase = merchantChargeSchema.parse(
|
|
2003
|
+
merchantChargeForPurchase,
|
|
2004
|
+
)
|
|
2005
|
+
|
|
2006
|
+
if (!parsedMerchantChargeForPurchase)
|
|
2007
|
+
throw new Error(`no-charge-found-for-purchase ${chargeId}`)
|
|
2008
|
+
|
|
2009
|
+
const purchase = await client.query.purchases.findFirst({
|
|
2010
|
+
where: eq(
|
|
2011
|
+
purchaseTable.merchantChargeId,
|
|
2012
|
+
parsedMerchantChargeForPurchase.id,
|
|
2013
|
+
),
|
|
2014
|
+
})
|
|
2015
|
+
|
|
2016
|
+
const parsedPurchase = purchaseSchema.nullable().parse(purchase)
|
|
2017
|
+
|
|
2018
|
+
if (parsedPurchase) {
|
|
2019
|
+
await client
|
|
2020
|
+
.update(purchaseTable)
|
|
2021
|
+
.set({ status: status })
|
|
2022
|
+
.where(eq(purchaseTable.id, parsedPurchase.id))
|
|
2023
|
+
|
|
2024
|
+
const newPurchase = await client.query.purchases.findFirst({
|
|
2025
|
+
where: eq(purchaseTable.id, parsedPurchase.id),
|
|
2026
|
+
})
|
|
2027
|
+
|
|
2028
|
+
return purchaseSchema.optional().parse(newPurchase)
|
|
2029
|
+
} else {
|
|
2030
|
+
throw new Error(`no-purchase-found-for-charge ${chargeId}`)
|
|
2031
|
+
}
|
|
2032
|
+
} catch (e) {
|
|
2033
|
+
console.log('error updating purchase status', e)
|
|
2034
|
+
throw e
|
|
2035
|
+
}
|
|
1551
2036
|
},
|
|
1552
2037
|
async updatePurchaseUserTransferTransferState(options: {
|
|
1553
2038
|
id: string
|
|
@@ -1611,6 +2096,35 @@ export function mySqlDrizzleAdapter(
|
|
|
1611
2096
|
|
|
1612
2097
|
return parsedResourceJoin.data
|
|
1613
2098
|
},
|
|
2099
|
+
async removeResourceFromResource(options) {
|
|
2100
|
+
const { childResourceId, parentResourceId } = options
|
|
2101
|
+
|
|
2102
|
+
const resourceJoin = await client.query.contentResourceResource.findFirst(
|
|
2103
|
+
{
|
|
2104
|
+
where: and(
|
|
2105
|
+
eq(contentResourceResource.resourceOfId, parentResourceId),
|
|
2106
|
+
eq(contentResourceResource.resourceId, childResourceId),
|
|
2107
|
+
),
|
|
2108
|
+
},
|
|
2109
|
+
)
|
|
2110
|
+
|
|
2111
|
+
const parsedResourceJoin =
|
|
2112
|
+
ContentResourceResourceSchema.safeParse(resourceJoin)
|
|
2113
|
+
if (!parsedResourceJoin.success) {
|
|
2114
|
+
return null
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
await client
|
|
2118
|
+
.delete(contentResourceResource)
|
|
2119
|
+
.where(
|
|
2120
|
+
and(
|
|
2121
|
+
eq(contentResourceResource.resourceOfId, parentResourceId),
|
|
2122
|
+
eq(contentResourceResource.resourceId, childResourceId),
|
|
2123
|
+
),
|
|
2124
|
+
)
|
|
2125
|
+
|
|
2126
|
+
return parsedResourceJoin.data.resource
|
|
2127
|
+
},
|
|
1614
2128
|
async updateContentResourceFields(options) {
|
|
1615
2129
|
if (!options.id) {
|
|
1616
2130
|
throw new Error('No content resource id.')
|
|
@@ -1741,7 +2255,15 @@ export function mySqlDrizzleAdapter(
|
|
|
1741
2255
|
with: {
|
|
1742
2256
|
resources: {
|
|
1743
2257
|
with: {
|
|
1744
|
-
resource:
|
|
2258
|
+
resource: {
|
|
2259
|
+
with: {
|
|
2260
|
+
resources: {
|
|
2261
|
+
with: {
|
|
2262
|
+
resource: true,
|
|
2263
|
+
},
|
|
2264
|
+
},
|
|
2265
|
+
},
|
|
2266
|
+
},
|
|
1745
2267
|
},
|
|
1746
2268
|
orderBy: asc(contentResourceResource.position),
|
|
1747
2269
|
},
|
|
@@ -1864,7 +2386,7 @@ export function mySqlDrizzleAdapter(
|
|
|
1864
2386
|
return null
|
|
1865
2387
|
}
|
|
1866
2388
|
|
|
1867
|
-
return dbAccount.
|
|
2389
|
+
return dbAccount.User
|
|
1868
2390
|
},
|
|
1869
2391
|
async deleteSession(sessionToken) {
|
|
1870
2392
|
const session =
|