@coursebuilder/adapter-drizzle 0.5.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-BM5UKWXI.js → chunk-7ISZNMPU.js} +2 -2
- package/dist/{chunk-TBM3AK3P.js → chunk-7X7TMG4A.js} +2 -2
- package/dist/{chunk-CQNKTFXE.js → chunk-DAP5KOAO.js} +2 -2
- package/dist/{chunk-JZQ666KH.js → chunk-KDOSK7KN.js} +2 -2
- package/dist/{chunk-O6JECJRY.js → chunk-QPXUGIXO.js} +2 -2
- package/dist/{chunk-FRA4ZCRA.js → chunk-UHH4OVKA.js} +4 -14
- package/dist/{chunk-QTGVGIRO.js → chunk-UK6EHYS5.js} +2 -2
- package/dist/{chunk-Z245DYMP.js → chunk-VUS77FG3.js} +493 -198
- package/dist/index.d.ts +2 -1
- package/dist/index.js +12 -12
- package/dist/lib/mysql/index.cjs +498 -202
- package/dist/lib/mysql/index.cjs.map +1 -1
- package/dist/lib/mysql/index.d.cts +8 -30
- package/dist/lib/mysql/index.d.ts +8 -30
- package/dist/lib/mysql/index.js +10 -8
- package/dist/lib/mysql/schemas/auth/accounts.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/accounts.js +1 -1
- package/dist/lib/mysql/schemas/auth/device-access-token.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/device-access-token.js +2 -2
- package/dist/lib/mysql/schemas/auth/device-verification.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/device-verification.js +2 -2
- package/dist/lib/mysql/schemas/auth/role-permissions.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/role-permissions.js +2 -2
- package/dist/lib/mysql/schemas/auth/roles.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/roles.js +1 -1
- package/dist/lib/mysql/schemas/auth/sessions.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/sessions.js +2 -2
- package/dist/lib/mysql/schemas/auth/user-permissions.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/user-permissions.js +1 -1
- package/dist/lib/mysql/schemas/auth/user-prefs.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/user-prefs.js +1 -1
- package/dist/lib/mysql/schemas/auth/user-roles.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/user-roles.js +1 -1
- package/dist/lib/mysql/schemas/auth/users.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/users.js +1 -1
- package/dist/lib/mysql/schemas/commerce/coupon.cjs +3 -13
- package/dist/lib/mysql/schemas/commerce/coupon.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/coupon.d.cts +2 -14
- package/dist/lib/mysql/schemas/commerce/coupon.d.ts +2 -14
- package/dist/lib/mysql/schemas/commerce/coupon.js +1 -1
- package/dist/lib/mysql/schemas/commerce/price.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/price.js +1 -1
- package/dist/lib/mysql/schemas/commerce/product.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/product.js +1 -1
- package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.js +2 -2
- package/dist/lib/mysql/schemas/commerce/purchase.cjs +0 -4
- package/dist/lib/mysql/schemas/commerce/purchase.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/purchase.js +1 -1
- package/dist/lib/mysql/schemas/commerce/upgradable-products.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/upgradable-products.js +2 -2
- package/dist/lib/mysql/schemas/communication/comment.cjs.map +1 -1
- package/dist/lib/mysql/schemas/communication/comment.js +1 -1
- package/dist/lib/mysql/schemas/communication/communication-preferences.cjs.map +1 -1
- package/dist/lib/mysql/schemas/communication/communication-preferences.js +1 -1
- package/dist/lib/mysql/schemas/content/content-contributions.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-contributions.js +1 -1
- package/dist/lib/mysql/schemas/content/content-resource-product.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-resource-product.js +1 -1
- package/dist/lib/mysql/schemas/content/content-resource-resource.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-resource-resource.js +1 -1
- package/dist/lib/mysql/schemas/content/content-resource.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-resource.js +1 -1
- package/dist/lib/utils.d.cts +1 -0
- package/dist/lib/utils.d.ts +1 -0
- package/package.json +4 -2
- package/src/index.ts +14 -4
- package/src/lib/mysql/index.ts +601 -182
- package/src/lib/mysql/schemas/commerce/coupon.ts +3 -9
|
@@ -7,30 +7,30 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
getPurchaseUserTransferRelationsSchema,
|
|
9
9
|
getPurchaseUserTransferSchema
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-DAP5KOAO.js";
|
|
11
11
|
import {
|
|
12
12
|
getUpgradableProductsRelationsSchema,
|
|
13
13
|
getUpgradableProductsSchema
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-7ISZNMPU.js";
|
|
15
15
|
import {
|
|
16
16
|
getRolePermissionsRelationsSchema,
|
|
17
17
|
getRolePermissionsSchema
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-QPXUGIXO.js";
|
|
19
19
|
import {
|
|
20
20
|
getSessionRelationsSchema,
|
|
21
21
|
getSessionsSchema
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-7X7TMG4A.js";
|
|
23
23
|
import {
|
|
24
24
|
getVerificationTokensSchema
|
|
25
25
|
} from "./chunk-LERR6HQ3.js";
|
|
26
26
|
import {
|
|
27
27
|
getDeviceAccessTokenRelationsSchema,
|
|
28
28
|
getDeviceAccessTokenSchema
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-UK6EHYS5.js";
|
|
30
30
|
import {
|
|
31
31
|
getDeviceVerificationRelationsSchema,
|
|
32
32
|
getDeviceVerificationSchema
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-KDOSK7KN.js";
|
|
34
34
|
import {
|
|
35
35
|
getAccountsRelationsSchema,
|
|
36
36
|
getAccountsSchema,
|
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
getUserRolesSchema,
|
|
64
64
|
getUsersRelationsSchema,
|
|
65
65
|
getUsersSchema
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-UHH4OVKA.js";
|
|
67
67
|
import {
|
|
68
68
|
getContributionTypesRelationsSchema,
|
|
69
69
|
getContributionTypesSchema
|
|
@@ -105,9 +105,11 @@ import {
|
|
|
105
105
|
} from "./chunk-H736K5TN.js";
|
|
106
106
|
|
|
107
107
|
// src/lib/mysql/index.ts
|
|
108
|
+
import slugify from "@sindresorhus/slugify";
|
|
108
109
|
import { addSeconds, isAfter } from "date-fns";
|
|
109
|
-
import { and, asc, desc, eq, gte, inArray,
|
|
110
|
+
import { and, asc, desc, eq, gte, inArray, isNull, not, or, sql } from "drizzle-orm";
|
|
110
111
|
import { mysqlTable as defaultMySqlTableFn } from "drizzle-orm/mysql-core";
|
|
112
|
+
import { customAlphabet } from "nanoid";
|
|
111
113
|
import { v4 } from "uuid";
|
|
112
114
|
|
|
113
115
|
// ../../node_modules/.pnpm/zod@3.22.4/node_modules/zod/lib/index.mjs
|
|
@@ -8123,6 +8125,29 @@ var z2 = /* @__PURE__ */ Object.freeze({
|
|
|
8123
8125
|
ZodError: ZodError2
|
|
8124
8126
|
});
|
|
8125
8127
|
|
|
8128
|
+
// ../core/dist/chunk-CMH4QQ3R.js
|
|
8129
|
+
var VideoResourceSchema = z2.object({
|
|
8130
|
+
id: z2.string(),
|
|
8131
|
+
updatedAt: z2.coerce.date().optional(),
|
|
8132
|
+
createdAt: z2.coerce.date().optional(),
|
|
8133
|
+
title: z2.string().optional().nullable(),
|
|
8134
|
+
duration: z2.number().optional().nullable(),
|
|
8135
|
+
muxPlaybackId: z2.string().optional().nullable(),
|
|
8136
|
+
muxAssetId: z2.string().optional().nullable(),
|
|
8137
|
+
transcript: z2.string().optional().nullable(),
|
|
8138
|
+
transcriptWithScreenshots: z2.string().optional().nullable(),
|
|
8139
|
+
srt: z2.string().optional().nullable(),
|
|
8140
|
+
wordLevelSrt: z2.string().optional().nullable(),
|
|
8141
|
+
state: z2.enum([
|
|
8142
|
+
"new",
|
|
8143
|
+
"processing",
|
|
8144
|
+
"preparing",
|
|
8145
|
+
"ready",
|
|
8146
|
+
"errored",
|
|
8147
|
+
"deleted"
|
|
8148
|
+
])
|
|
8149
|
+
});
|
|
8150
|
+
|
|
8126
8151
|
// ../core/dist/chunk-CHYUPSYW.js
|
|
8127
8152
|
var userSchema = z2.object({
|
|
8128
8153
|
id: z2.string().max(255),
|
|
@@ -8157,15 +8182,15 @@ var priceSchema = z2.object({
|
|
|
8157
8182
|
fields: z2.record(z2.any()).default({})
|
|
8158
8183
|
});
|
|
8159
8184
|
|
|
8160
|
-
// ../core/dist/chunk-
|
|
8185
|
+
// ../core/dist/chunk-5BAEWUNU.js
|
|
8161
8186
|
var ContentResourceResourceSchema = z2.object({
|
|
8162
8187
|
resourceId: z2.string(),
|
|
8163
8188
|
resourceOfId: z2.string(),
|
|
8164
8189
|
position: z2.number().default(0),
|
|
8165
8190
|
metadata: z2.record(z2.string(), z2.any()).default({}).nullable(),
|
|
8166
|
-
createdAt: z2.date().nullable(),
|
|
8167
|
-
updatedAt: z2.date().nullable(),
|
|
8168
|
-
deletedAt: z2.date().nullable(),
|
|
8191
|
+
createdAt: z2.coerce.date().nullable(),
|
|
8192
|
+
updatedAt: z2.coerce.date().nullable(),
|
|
8193
|
+
deletedAt: z2.coerce.date().nullable(),
|
|
8169
8194
|
resource: z2.any()
|
|
8170
8195
|
});
|
|
8171
8196
|
var ContentResourceSchema = z2.object({
|
|
@@ -8173,9 +8198,9 @@ var ContentResourceSchema = z2.object({
|
|
|
8173
8198
|
type: z2.string(),
|
|
8174
8199
|
createdById: z2.string(),
|
|
8175
8200
|
fields: z2.record(z2.string(), z2.any()).default({}).nullable().optional(),
|
|
8176
|
-
createdAt: z2.date().nullable(),
|
|
8177
|
-
updatedAt: z2.date().nullable(),
|
|
8178
|
-
deletedAt: z2.date().nullable(),
|
|
8201
|
+
createdAt: z2.coerce.date().nullable(),
|
|
8202
|
+
updatedAt: z2.coerce.date().nullable(),
|
|
8203
|
+
deletedAt: z2.coerce.date().nullable(),
|
|
8179
8204
|
resources: z2.array(ContentResourceResourceSchema).default([]).nullable()
|
|
8180
8205
|
});
|
|
8181
8206
|
var ContentResourceProductSchema = z2.object({
|
|
@@ -8183,9 +8208,9 @@ var ContentResourceProductSchema = z2.object({
|
|
|
8183
8208
|
productId: z2.string(),
|
|
8184
8209
|
position: z2.number().default(0),
|
|
8185
8210
|
metadata: z2.record(z2.string(), z2.any()).default({}).nullable(),
|
|
8186
|
-
createdAt: z2.date().nullable(),
|
|
8187
|
-
updatedAt: z2.date().nullable(),
|
|
8188
|
-
deletedAt: z2.date().nullable(),
|
|
8211
|
+
createdAt: z2.coerce.date().nullable(),
|
|
8212
|
+
updatedAt: z2.coerce.date().nullable(),
|
|
8213
|
+
deletedAt: z2.coerce.date().nullable(),
|
|
8189
8214
|
resource: z2.any(),
|
|
8190
8215
|
product: z2.any()
|
|
8191
8216
|
});
|
|
@@ -8201,7 +8226,7 @@ var ResourceVisibilitySchema = z2.union([
|
|
|
8201
8226
|
z2.literal("unlisted")
|
|
8202
8227
|
]);
|
|
8203
8228
|
|
|
8204
|
-
// ../core/dist/chunk-
|
|
8229
|
+
// ../core/dist/chunk-SVQMPVCK.js
|
|
8205
8230
|
var productSchema = z2.object({
|
|
8206
8231
|
id: z2.string().max(191),
|
|
8207
8232
|
name: z2.string().max(191),
|
|
@@ -8212,10 +8237,10 @@ var productSchema = z2.object({
|
|
|
8212
8237
|
]).default("self-paced"),
|
|
8213
8238
|
fields: z2.object({
|
|
8214
8239
|
body: z2.string().nullable().optional(),
|
|
8215
|
-
description: z2.string().
|
|
8240
|
+
description: z2.string().nullish(),
|
|
8216
8241
|
slug: z2.string(),
|
|
8217
8242
|
image: z2.object({
|
|
8218
|
-
url: z2.string()
|
|
8243
|
+
url: z2.string(),
|
|
8219
8244
|
alt: z2.string().optional().nullable(),
|
|
8220
8245
|
width: z2.number().optional().nullable(),
|
|
8221
8246
|
height: z2.number().optional().nullable()
|
|
@@ -8233,14 +8258,19 @@ var productSchema = z2.object({
|
|
|
8233
8258
|
"unlisted"
|
|
8234
8259
|
]).default("unlisted")
|
|
8235
8260
|
}),
|
|
8236
|
-
createdAt: z2.date().nullable(),
|
|
8261
|
+
createdAt: z2.coerce.date().nullable(),
|
|
8237
8262
|
status: z2.number().int().default(0),
|
|
8238
8263
|
quantityAvailable: z2.number().int().default(-1),
|
|
8239
8264
|
price: priceSchema.nullable().optional(),
|
|
8240
8265
|
resources: z2.array(ContentResourceProductSchema).default([]).nullable()
|
|
8241
8266
|
});
|
|
8267
|
+
var NewProductSchema = z2.object({
|
|
8268
|
+
name: z2.string().min(2).max(90),
|
|
8269
|
+
quantityAvailable: z2.coerce.number().default(-1),
|
|
8270
|
+
price: z2.coerce.number().gte(0).default(0)
|
|
8271
|
+
});
|
|
8242
8272
|
|
|
8243
|
-
// ../core/dist/chunk-
|
|
8273
|
+
// ../core/dist/chunk-RCFZC3SN.js
|
|
8244
8274
|
var couponSchema = z2.object({
|
|
8245
8275
|
id: z2.string(),
|
|
8246
8276
|
code: z2.string().max(191).optional().nullable(),
|
|
@@ -8257,11 +8287,12 @@ var couponSchema = z2.object({
|
|
|
8257
8287
|
return decimalPlaces <= 2;
|
|
8258
8288
|
}),
|
|
8259
8289
|
restrictedToProductId: z2.string().max(191).optional().nullable(),
|
|
8260
|
-
|
|
8261
|
-
|
|
8290
|
+
bulkPurchases: z2.array(z2.any()).default([]),
|
|
8291
|
+
redeemedBulkCouponPurchases: z2.array(z2.any()).default([]),
|
|
8292
|
+
bulkPurchaseId: z2.string().max(191).optional().nullable()
|
|
8262
8293
|
});
|
|
8263
8294
|
|
|
8264
|
-
// ../core/dist/chunk-
|
|
8295
|
+
// ../core/dist/chunk-5OFQV6YX.js
|
|
8265
8296
|
var purchaseSchema = z2.object({
|
|
8266
8297
|
id: z2.string().max(191),
|
|
8267
8298
|
userId: z2.string().max(191).optional().nullable(),
|
|
@@ -8310,18 +8341,15 @@ var purchaseUserTransferSchema = z2.object({
|
|
|
8310
8341
|
completedAt: z2.date().nullable()
|
|
8311
8342
|
});
|
|
8312
8343
|
|
|
8313
|
-
// ../core/dist/chunk-
|
|
8344
|
+
// ../core/dist/chunk-CWQHSOPP.js
|
|
8314
8345
|
var resourceProgressSchema = z2.object({
|
|
8315
8346
|
userId: z2.string().max(191),
|
|
8316
8347
|
resourceId: z2.string().max(191).optional().nullable(),
|
|
8317
|
-
|
|
8318
|
-
completedAt: z2.date().nullable(),
|
|
8319
|
-
updatedAt: z2.date().nullable(),
|
|
8320
|
-
createdAt: z2.date().nullable()
|
|
8348
|
+
completedAt: z2.date().nullable()
|
|
8321
8349
|
});
|
|
8322
8350
|
var moduleProgressSchema = z2.object({
|
|
8323
8351
|
completedLessons: z2.array(resourceProgressSchema),
|
|
8324
|
-
nextResource: ContentResourceSchema.nullable(),
|
|
8352
|
+
nextResource: ContentResourceSchema.partial().nullable(),
|
|
8325
8353
|
percentCompleted: z2.number().default(0),
|
|
8326
8354
|
completedLessonsCount: z2.number().default(0),
|
|
8327
8355
|
totalLessonsCount: z2.number().default(0)
|
|
@@ -8338,29 +8366,6 @@ var upgradableProductSchema = z2.object({
|
|
|
8338
8366
|
deletedAt: z2.date().nullable()
|
|
8339
8367
|
});
|
|
8340
8368
|
|
|
8341
|
-
// ../core/dist/chunk-5QZXOTEH.js
|
|
8342
|
-
var VideoResourceSchema = z2.object({
|
|
8343
|
-
id: z2.string(),
|
|
8344
|
-
updatedAt: z2.string().optional(),
|
|
8345
|
-
createdAt: z2.string().optional(),
|
|
8346
|
-
title: z2.string().optional().nullable(),
|
|
8347
|
-
duration: z2.number().optional().nullable(),
|
|
8348
|
-
muxPlaybackId: z2.string().optional().nullable(),
|
|
8349
|
-
muxAssetId: z2.string().optional().nullable(),
|
|
8350
|
-
transcript: z2.string().optional().nullable(),
|
|
8351
|
-
transcriptWithScreenshots: z2.string().optional().nullable(),
|
|
8352
|
-
srt: z2.string().optional().nullable(),
|
|
8353
|
-
wordLevelSrt: z2.string().optional().nullable(),
|
|
8354
|
-
state: z2.enum([
|
|
8355
|
-
"new",
|
|
8356
|
-
"processing",
|
|
8357
|
-
"preparing",
|
|
8358
|
-
"ready",
|
|
8359
|
-
"errored",
|
|
8360
|
-
"deleted"
|
|
8361
|
-
])
|
|
8362
|
-
});
|
|
8363
|
-
|
|
8364
8369
|
// ../core/dist/chunk-EDDT2FFU.js
|
|
8365
8370
|
var merchantCustomerSchema = z2.object({
|
|
8366
8371
|
id: z2.string().max(191),
|
|
@@ -8556,6 +8561,7 @@ var validateCoupon = /* @__PURE__ */ __name2((coupon, productIds = []) => {
|
|
|
8556
8561
|
}, "validateCoupon");
|
|
8557
8562
|
|
|
8558
8563
|
// src/lib/mysql/index.ts
|
|
8564
|
+
var guid = customAlphabet("1234567890abcdefghijklmnopqrstuvwxyz", 5);
|
|
8559
8565
|
function getCourseBuilderSchema(mysqlTable) {
|
|
8560
8566
|
return {
|
|
8561
8567
|
accounts: getAccountsSchema(mysqlTable),
|
|
@@ -8625,8 +8631,8 @@ function createTables(mySqlTable) {
|
|
|
8625
8631
|
return getCourseBuilderSchema(mySqlTable);
|
|
8626
8632
|
}
|
|
8627
8633
|
__name(createTables, "createTables");
|
|
8628
|
-
function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
8629
|
-
const { users, accounts, sessions, verificationTokens, contentResource, contentResourceResource, purchases: purchaseTable, purchaseUserTransfer, coupon, merchantCoupon, merchantCharge, merchantAccount, merchantPrice, merchantCustomer, merchantSession, merchantProduct, prices, products, upgradableProducts, resourceProgress, comments } = createTables(tableFn);
|
|
8634
|
+
function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn, paymentProvider) {
|
|
8635
|
+
const { users, accounts, sessions, verificationTokens, contentResource, contentResourceResource, contentResourceProduct, purchases: purchaseTable, purchaseUserTransfer, coupon, merchantCoupon, merchantCharge, merchantAccount, merchantPrice, merchantCustomer, merchantSession, merchantProduct, prices, products, upgradableProducts, resourceProgress, comments } = createTables(tableFn);
|
|
8630
8636
|
const adapter = {
|
|
8631
8637
|
client,
|
|
8632
8638
|
async redeemFullPriceCoupon(options) {
|
|
@@ -8638,7 +8644,7 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
8638
8644
|
throw new Error(`unable-to-find-any-product-id`);
|
|
8639
8645
|
const couponValidation = validateCoupon(coupon2, productIds);
|
|
8640
8646
|
if (coupon2 && couponValidation.isRedeemable) {
|
|
8641
|
-
const bulkCouponRedemption = Boolean(coupon2.
|
|
8647
|
+
const bulkCouponRedemption = Boolean(coupon2.maxUses > 1);
|
|
8642
8648
|
const { user } = await adapter.findOrCreateUser(email);
|
|
8643
8649
|
if (!user)
|
|
8644
8650
|
throw new Error(`unable-to-create-user-${email}`);
|
|
@@ -8648,8 +8654,18 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
8648
8654
|
userId: user.id,
|
|
8649
8655
|
productId
|
|
8650
8656
|
});
|
|
8651
|
-
if (existingPurchases.length > 0)
|
|
8652
|
-
|
|
8657
|
+
if (existingPurchases.length > 0) {
|
|
8658
|
+
const errorMessage = `already-purchased-${email}`;
|
|
8659
|
+
console.error(errorMessage);
|
|
8660
|
+
return {
|
|
8661
|
+
error: {
|
|
8662
|
+
message: errorMessage
|
|
8663
|
+
},
|
|
8664
|
+
redeemingForCurrentUser,
|
|
8665
|
+
purchase: null
|
|
8666
|
+
};
|
|
8667
|
+
throw new Error(errorMessage);
|
|
8668
|
+
}
|
|
8653
8669
|
const purchaseId = `purchase-${v4()}`;
|
|
8654
8670
|
await adapter.createPurchase({
|
|
8655
8671
|
id: purchaseId,
|
|
@@ -8715,7 +8731,7 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
8715
8731
|
},
|
|
8716
8732
|
getMerchantPriceForProductId: async (productId) => {
|
|
8717
8733
|
const merchantPriceData = await client.query.merchantPrice.findFirst({
|
|
8718
|
-
where: eq(merchantPrice.merchantProductId, productId)
|
|
8734
|
+
where: and(eq(merchantPrice.merchantProductId, productId), eq(merchantPrice.status, 1))
|
|
8719
8735
|
});
|
|
8720
8736
|
const parsedMerchantPrice = merchantPriceSchema.safeParse(merchantPriceData);
|
|
8721
8737
|
if (!parsedMerchantPrice.success) {
|
|
@@ -8749,7 +8765,7 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
8749
8765
|
async availableUpgradesForProduct(purchases, productId) {
|
|
8750
8766
|
const previousPurchaseProductIds = purchases.map(({ productId: productId2 }) => productId2);
|
|
8751
8767
|
if (previousPurchaseProductIds.length > 0) {
|
|
8752
|
-
return
|
|
8768
|
+
return client.query.upgradableProducts.findMany({
|
|
8753
8769
|
where: and(eq(upgradableProducts.upgradableToId, productId), inArray(upgradableProducts.upgradableFromId, previousPurchaseProductIds))
|
|
8754
8770
|
});
|
|
8755
8771
|
}
|
|
@@ -8971,18 +8987,31 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
8971
8987
|
couponId
|
|
8972
8988
|
});
|
|
8973
8989
|
let couponData;
|
|
8990
|
+
let bulkCouponPurchases;
|
|
8974
8991
|
try {
|
|
8975
8992
|
couponData = await client.query.coupon.findFirst({
|
|
8976
8993
|
where: eq(coupon.id, couponId),
|
|
8977
8994
|
with: {
|
|
8978
|
-
|
|
8979
|
-
|
|
8995
|
+
bulkPurchases: true,
|
|
8996
|
+
redeemedBulkCouponPurchases: true
|
|
8980
8997
|
}
|
|
8981
8998
|
}) || null;
|
|
8982
8999
|
} catch (e) {
|
|
8983
9000
|
console.log("getCouponWithBulkPurchases");
|
|
8984
9001
|
logger.error(e);
|
|
8985
9002
|
}
|
|
9003
|
+
try {
|
|
9004
|
+
bulkCouponPurchases = await client.query.purchases.findMany({
|
|
9005
|
+
where: eq(purchaseTable.redeemedBulkCouponId, couponId),
|
|
9006
|
+
with: {
|
|
9007
|
+
user: true
|
|
9008
|
+
}
|
|
9009
|
+
});
|
|
9010
|
+
console.log("purchases with redeemedBulkCouponId", bulkCouponPurchases);
|
|
9011
|
+
} catch (e) {
|
|
9012
|
+
console.log("getCouponWithBulkPurchases");
|
|
9013
|
+
logger.error(e);
|
|
9014
|
+
}
|
|
8986
9015
|
if (!couponData) {
|
|
8987
9016
|
logger.debug("getCouponWithBulkPurchases", {
|
|
8988
9017
|
couponId,
|
|
@@ -8990,12 +9019,15 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
8990
9019
|
});
|
|
8991
9020
|
return null;
|
|
8992
9021
|
}
|
|
9022
|
+
const couponWithBulkPurchases = {
|
|
9023
|
+
...couponData,
|
|
9024
|
+
redeemedBulkCouponPurchases: bulkCouponPurchases || []
|
|
9025
|
+
};
|
|
8993
9026
|
const parsedCoupon = couponSchema.merge(z.object({
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
})).nullable().safeParse(couponData);
|
|
9027
|
+
redeemedBulkCouponPurchases: z.array(purchaseSchema)
|
|
9028
|
+
})).nullable().safeParse(couponWithBulkPurchases);
|
|
8997
9029
|
if (!parsedCoupon.success) {
|
|
8998
|
-
console.error("Error parsing coupon", couponData);
|
|
9030
|
+
console.error("Error parsing coupon", JSON.stringify(parsedCoupon.error), couponData);
|
|
8999
9031
|
return null;
|
|
9000
9032
|
}
|
|
9001
9033
|
return parsedCoupon.data;
|
|
@@ -9037,109 +9069,65 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
9037
9069
|
return parsed.data;
|
|
9038
9070
|
},
|
|
9039
9071
|
async getModuleProgressForUser(userIdOrEmail, moduleIdOrSlug) {
|
|
9040
|
-
const ALLOWED_MODULE_RESOURCE_TYPES = [
|
|
9041
|
-
"lesson",
|
|
9042
|
-
"exercise",
|
|
9043
|
-
"solution"
|
|
9044
|
-
];
|
|
9045
|
-
const COUNTABLE_MODULE_RESOURCE_TYPES = [
|
|
9046
|
-
"lesson",
|
|
9047
|
-
"exercise"
|
|
9048
|
-
];
|
|
9049
|
-
const module = await client.query.contentResource.findFirst({
|
|
9050
|
-
where: or(eq(contentResource.id, moduleIdOrSlug), eq(sql`JSON_EXTRACT (${contentResource.fields}, "$.slug")`, moduleIdOrSlug)),
|
|
9051
|
-
with: {
|
|
9052
|
-
resources: {
|
|
9053
|
-
with: {
|
|
9054
|
-
resource: {
|
|
9055
|
-
with: {
|
|
9056
|
-
resources: {
|
|
9057
|
-
with: {
|
|
9058
|
-
resource: {
|
|
9059
|
-
with: {
|
|
9060
|
-
resources: {
|
|
9061
|
-
with: {
|
|
9062
|
-
resource: true
|
|
9063
|
-
}
|
|
9064
|
-
}
|
|
9065
|
-
}
|
|
9066
|
-
}
|
|
9067
|
-
},
|
|
9068
|
-
orderBy: asc(contentResourceResource.position)
|
|
9069
|
-
}
|
|
9070
|
-
}
|
|
9071
|
-
}
|
|
9072
|
-
},
|
|
9073
|
-
orderBy: asc(contentResourceResource.position)
|
|
9074
|
-
}
|
|
9075
|
-
}
|
|
9076
|
-
});
|
|
9077
|
-
const parsedModule = ContentResourceSchema.parse(module);
|
|
9078
|
-
function flattenResources(resources) {
|
|
9079
|
-
const result = [];
|
|
9080
|
-
function recurse(resources2) {
|
|
9081
|
-
for (const nestedResource of resources2) {
|
|
9082
|
-
const resource = nestedResource.resource;
|
|
9083
|
-
result.push(resource);
|
|
9084
|
-
if (resource.resources) {
|
|
9085
|
-
recurse(resource.resources);
|
|
9086
|
-
}
|
|
9087
|
-
}
|
|
9088
|
-
}
|
|
9089
|
-
__name(recurse, "recurse");
|
|
9090
|
-
recurse(resources);
|
|
9091
|
-
return result;
|
|
9092
|
-
}
|
|
9093
|
-
__name(flattenResources, "flattenResources");
|
|
9094
|
-
const allResources = parsedModule?.resources && flattenResources(parsedModule.resources);
|
|
9095
|
-
const filteredResources = allResources?.filter((resource) => {
|
|
9096
|
-
return ALLOWED_MODULE_RESOURCE_TYPES.includes(resource.type);
|
|
9097
|
-
});
|
|
9098
|
-
const parsedResources = z.array(ContentResourceSchema).safeParse(filteredResources);
|
|
9099
|
-
if (!parsedResources.success) {
|
|
9100
|
-
console.error("Error parsing module resources", parsedResources.error);
|
|
9101
|
-
return {
|
|
9102
|
-
completedLessons: [],
|
|
9103
|
-
nextResource: null,
|
|
9104
|
-
percentCompleted: 0,
|
|
9105
|
-
completedLessonsCount: 0,
|
|
9106
|
-
totalLessonsCount: 0
|
|
9107
|
-
};
|
|
9108
|
-
}
|
|
9109
|
-
const progressResources = parsedResources.data.filter((r) => {
|
|
9110
|
-
return COUNTABLE_MODULE_RESOURCE_TYPES.includes(r.type);
|
|
9111
|
-
});
|
|
9112
|
-
const totalLessonsCount = progressResources.length;
|
|
9113
9072
|
const user = await client.query.users.findFirst({
|
|
9114
9073
|
where: or(eq(users.id, userIdOrEmail), eq(users.email, userIdOrEmail)),
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
with: {
|
|
9118
|
-
role: true
|
|
9119
|
-
}
|
|
9120
|
-
}
|
|
9121
|
-
}
|
|
9122
|
-
}).then(async (res) => {
|
|
9123
|
-
if (res) {
|
|
9124
|
-
return {
|
|
9125
|
-
...res,
|
|
9126
|
-
roles: res.roles.map((r) => r.role)
|
|
9127
|
-
};
|
|
9074
|
+
columns: {
|
|
9075
|
+
id: true
|
|
9128
9076
|
}
|
|
9129
9077
|
});
|
|
9130
9078
|
if (!user) {
|
|
9131
|
-
|
|
9132
|
-
return {
|
|
9133
|
-
completedLessons: [],
|
|
9134
|
-
nextResource: null,
|
|
9135
|
-
percentCompleted: 0,
|
|
9136
|
-
completedLessonsCount: 0,
|
|
9137
|
-
totalLessonsCount
|
|
9138
|
-
};
|
|
9079
|
+
return null;
|
|
9139
9080
|
}
|
|
9140
|
-
const
|
|
9141
|
-
|
|
9142
|
-
|
|
9081
|
+
const ResultRowSchema = z.object({
|
|
9082
|
+
resource_id: z.string(),
|
|
9083
|
+
resource_type: z.enum([
|
|
9084
|
+
"lesson",
|
|
9085
|
+
"exercise"
|
|
9086
|
+
]),
|
|
9087
|
+
resource_slug: z.string().nullable(),
|
|
9088
|
+
completed_at: z.string().nullable().transform((val) => val ? new Date(val) : null)
|
|
9089
|
+
});
|
|
9090
|
+
const results = await client.execute(sql`
|
|
9091
|
+
SELECT
|
|
9092
|
+
cr.id AS resource_id,
|
|
9093
|
+
cr.type AS resource_type,
|
|
9094
|
+
cr.fields->>'$.slug' AS resource_slug,
|
|
9095
|
+
rp.completedAt AS completed_at
|
|
9096
|
+
FROM
|
|
9097
|
+
(SELECT id, fields->>'$.slug' AS slug
|
|
9098
|
+
FROM ${contentResource}
|
|
9099
|
+
WHERE id = ${moduleIdOrSlug}
|
|
9100
|
+
OR fields->>'$.slug' = ${moduleIdOrSlug}) AS w
|
|
9101
|
+
LEFT JOIN
|
|
9102
|
+
(SELECT
|
|
9103
|
+
crr.resourceOfId AS workshop_id,
|
|
9104
|
+
crr.resourceId,
|
|
9105
|
+
crr.position
|
|
9106
|
+
FROM ${contentResourceResource} crr) AS tlr ON w.id = tlr.workshop_id
|
|
9107
|
+
LEFT JOIN ${contentResource} sections ON sections.id = tlr.resourceId AND sections.type = 'section'
|
|
9108
|
+
LEFT JOIN
|
|
9109
|
+
(SELECT
|
|
9110
|
+
crr.resourceOfId AS section_id,
|
|
9111
|
+
crr.resourceId AS resource_id,
|
|
9112
|
+
crr.position AS position_in_section,
|
|
9113
|
+
section_crr.position AS section_position
|
|
9114
|
+
FROM ${contentResourceResource} crr
|
|
9115
|
+
JOIN ${contentResourceResource} section_crr ON crr.resourceOfId = section_crr.resourceId) AS sr
|
|
9116
|
+
ON sr.section_id = sections.id
|
|
9117
|
+
JOIN ${contentResource} cr ON cr.id = COALESCE(sr.resource_id, tlr.resourceId)
|
|
9118
|
+
LEFT JOIN ${resourceProgress} rp ON rp.resourceId = cr.id
|
|
9119
|
+
AND rp.userId = ${user.id}
|
|
9120
|
+
WHERE
|
|
9121
|
+
cr.type IN ('lesson', 'exercise')
|
|
9122
|
+
|
|
9123
|
+
`);
|
|
9124
|
+
const completedLessons = [];
|
|
9125
|
+
let nextResource = null;
|
|
9126
|
+
let completedLessonsCount = 0;
|
|
9127
|
+
let totalLessonsCount = results.rows.length;
|
|
9128
|
+
const parsedRows = z.array(ResultRowSchema).safeParse(results.rows);
|
|
9129
|
+
if (!parsedRows.success) {
|
|
9130
|
+
console.error("Error parsing rows", parsedRows.error);
|
|
9143
9131
|
return {
|
|
9144
9132
|
completedLessons: [],
|
|
9145
9133
|
nextResource: null,
|
|
@@ -9148,34 +9136,30 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
9148
9136
|
totalLessonsCount
|
|
9149
9137
|
};
|
|
9150
9138
|
}
|
|
9151
|
-
const
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9164
|
-
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
percentCompleted: 0,
|
|
9169
|
-
completedLessonsCount: 0,
|
|
9170
|
-
totalLessonsCount
|
|
9171
|
-
};
|
|
9139
|
+
for (const row of parsedRows.data) {
|
|
9140
|
+
if (row.completed_at) {
|
|
9141
|
+
completedLessonsCount++;
|
|
9142
|
+
completedLessons.push({
|
|
9143
|
+
userId: user.id,
|
|
9144
|
+
resourceId: row.resource_id,
|
|
9145
|
+
completedAt: new Date(row.completed_at)
|
|
9146
|
+
});
|
|
9147
|
+
} else if (!nextResource) {
|
|
9148
|
+
nextResource = {
|
|
9149
|
+
id: row.resource_id,
|
|
9150
|
+
type: row.resource_type,
|
|
9151
|
+
fields: {
|
|
9152
|
+
slug: row.resource_slug
|
|
9153
|
+
}
|
|
9154
|
+
};
|
|
9155
|
+
}
|
|
9172
9156
|
}
|
|
9173
|
-
const percentCompleted = Math.
|
|
9157
|
+
const percentCompleted = totalLessonsCount > 0 ? Math.ceil(completedLessonsCount / totalLessonsCount * 100) : 0;
|
|
9174
9158
|
return {
|
|
9175
|
-
completedLessons
|
|
9176
|
-
nextResource
|
|
9159
|
+
completedLessons,
|
|
9160
|
+
nextResource,
|
|
9177
9161
|
percentCompleted,
|
|
9178
|
-
completedLessonsCount
|
|
9162
|
+
completedLessonsCount,
|
|
9179
9163
|
totalLessonsCount
|
|
9180
9164
|
};
|
|
9181
9165
|
},
|
|
@@ -9188,7 +9172,7 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
9188
9172
|
});
|
|
9189
9173
|
const parsed = merchantChargeSchema.safeParse(mCharge);
|
|
9190
9174
|
if (!parsed.success) {
|
|
9191
|
-
console.
|
|
9175
|
+
console.info("Error parsing merchantCharge", mCharge);
|
|
9192
9176
|
return null;
|
|
9193
9177
|
}
|
|
9194
9178
|
return parsed.data;
|
|
@@ -9231,10 +9215,249 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
9231
9215
|
where: eq(prices.productId, productId)
|
|
9232
9216
|
}));
|
|
9233
9217
|
},
|
|
9234
|
-
async
|
|
9235
|
-
|
|
9236
|
-
|
|
9218
|
+
async archiveProduct(productId) {
|
|
9219
|
+
if (!paymentProvider)
|
|
9220
|
+
throw new Error("Payment provider not found");
|
|
9221
|
+
const product = await adapter.getProduct(productId);
|
|
9222
|
+
if (!product) {
|
|
9223
|
+
throw new Error(`Product not found for id (${productId})`);
|
|
9224
|
+
}
|
|
9225
|
+
if (!product.price) {
|
|
9226
|
+
throw new Error(`Product has no price`);
|
|
9227
|
+
}
|
|
9228
|
+
await client.update(products).set({
|
|
9229
|
+
status: 0,
|
|
9230
|
+
name: `${product.name} (Archived)`
|
|
9231
|
+
}).where(eq(products.id, productId));
|
|
9232
|
+
await client.update(prices).set({
|
|
9233
|
+
status: 0,
|
|
9234
|
+
nickname: `${product.name} (Archived)`
|
|
9235
|
+
}).where(eq(prices.productId, productId));
|
|
9236
|
+
await client.update(merchantProduct).set({
|
|
9237
|
+
status: 0
|
|
9238
|
+
}).where(eq(merchantProduct.productId, productId));
|
|
9239
|
+
await client.update(merchantPrice).set({
|
|
9240
|
+
status: 0
|
|
9241
|
+
}).where(eq(merchantPrice.priceId, product.price.id));
|
|
9242
|
+
const currentMerchantProduct = merchantProductSchema.nullish().parse(await client.query.merchantProduct.findFirst({
|
|
9243
|
+
where: eq(merchantProduct.productId, productId)
|
|
9237
9244
|
}));
|
|
9245
|
+
if (!currentMerchantProduct || !currentMerchantProduct.identifier) {
|
|
9246
|
+
throw new Error(`Merchant product not found for id (${productId})`);
|
|
9247
|
+
}
|
|
9248
|
+
await paymentProvider.updateProduct(currentMerchantProduct.identifier, {
|
|
9249
|
+
active: false
|
|
9250
|
+
});
|
|
9251
|
+
const currentMerchantPrice = merchantPriceSchema.nullish().parse(await client.query.merchantPrice.findFirst({
|
|
9252
|
+
where: and(eq(merchantPrice.priceId, product.price.id), eq(merchantPrice.status, 1))
|
|
9253
|
+
}));
|
|
9254
|
+
if (!currentMerchantPrice || !currentMerchantPrice.identifier) {
|
|
9255
|
+
throw new Error(`Merchant price not found for id (${productId})`);
|
|
9256
|
+
}
|
|
9257
|
+
await paymentProvider.updatePrice(currentMerchantPrice.identifier, {
|
|
9258
|
+
active: false
|
|
9259
|
+
});
|
|
9260
|
+
return adapter.getProduct(productId);
|
|
9261
|
+
},
|
|
9262
|
+
async updateProduct(input) {
|
|
9263
|
+
if (!paymentProvider)
|
|
9264
|
+
throw new Error("Payment provider not found");
|
|
9265
|
+
const currentProduct = await adapter.getProduct(input.id);
|
|
9266
|
+
if (!currentProduct) {
|
|
9267
|
+
throw new Error(`Product not found`);
|
|
9268
|
+
}
|
|
9269
|
+
if (!currentProduct.price) {
|
|
9270
|
+
throw new Error(`Product has no price`);
|
|
9271
|
+
}
|
|
9272
|
+
const merchantProduct2 = merchantProductSchema.nullish().parse(await client.query.merchantProduct.findFirst({
|
|
9273
|
+
where: (merchantProduct3, { eq: eq2 }) => eq2(merchantProduct3.productId, input.id)
|
|
9274
|
+
}));
|
|
9275
|
+
if (!merchantProduct2 || !merchantProduct2.identifier) {
|
|
9276
|
+
throw new Error(`Merchant product not found`);
|
|
9277
|
+
}
|
|
9278
|
+
const stripeProduct = await paymentProvider.getProduct(merchantProduct2.identifier);
|
|
9279
|
+
const priceChanged = currentProduct.price.unitAmount.toString() !== input.price?.unitAmount.toString();
|
|
9280
|
+
if (priceChanged) {
|
|
9281
|
+
const currentMerchantPrice = merchantPriceSchema.nullish().parse(await client.query.merchantPrice.findFirst({
|
|
9282
|
+
where: (merchantPrice2, { eq: eq2, and: and2 }) => and2(eq2(merchantPrice2.merchantProductId, merchantProduct2.id), eq2(merchantPrice2.status, 1))
|
|
9283
|
+
}));
|
|
9284
|
+
if (!currentMerchantPrice || !currentMerchantPrice.identifier) {
|
|
9285
|
+
throw new Error(`Merchant price not found`);
|
|
9286
|
+
}
|
|
9287
|
+
const currentStripePrice = await paymentProvider.getPrice(currentMerchantPrice.identifier);
|
|
9288
|
+
const newStripePrice = await paymentProvider.createPrice({
|
|
9289
|
+
product: stripeProduct.id,
|
|
9290
|
+
unit_amount: Math.floor(Number(input.price?.unitAmount || 0) * 100),
|
|
9291
|
+
currency: "usd",
|
|
9292
|
+
metadata: {
|
|
9293
|
+
slug: input.fields.slug
|
|
9294
|
+
},
|
|
9295
|
+
active: true
|
|
9296
|
+
});
|
|
9297
|
+
await paymentProvider.updateProduct(stripeProduct.id, {
|
|
9298
|
+
default_price: newStripePrice.id
|
|
9299
|
+
});
|
|
9300
|
+
const newMerchantPriceId = `mprice_${v4()}`;
|
|
9301
|
+
await client.insert(merchantPrice).values({
|
|
9302
|
+
id: newMerchantPriceId,
|
|
9303
|
+
merchantProductId: merchantProduct2.id,
|
|
9304
|
+
merchantAccountId: merchantProduct2.merchantAccountId,
|
|
9305
|
+
priceId: currentProduct.price.id,
|
|
9306
|
+
status: 1,
|
|
9307
|
+
identifier: newStripePrice.id
|
|
9308
|
+
});
|
|
9309
|
+
if (currentMerchantPrice) {
|
|
9310
|
+
await client.update(merchantPrice).set({
|
|
9311
|
+
status: 0
|
|
9312
|
+
}).where(eq(merchantPrice.id, currentMerchantPrice.id));
|
|
9313
|
+
}
|
|
9314
|
+
await client.update(prices).set({
|
|
9315
|
+
unitAmount: Math.floor(Number(input.price?.unitAmount || 0)).toString(),
|
|
9316
|
+
nickname: input.name
|
|
9317
|
+
}).where(eq(prices.id, currentProduct.price.id));
|
|
9318
|
+
if (currentStripePrice) {
|
|
9319
|
+
await paymentProvider.updatePrice(currentStripePrice.id, {
|
|
9320
|
+
active: false
|
|
9321
|
+
});
|
|
9322
|
+
}
|
|
9323
|
+
}
|
|
9324
|
+
await paymentProvider.updateProduct(stripeProduct.id, {
|
|
9325
|
+
name: input.name,
|
|
9326
|
+
active: true,
|
|
9327
|
+
images: input.fields.image?.url ? [
|
|
9328
|
+
input.fields.image.url
|
|
9329
|
+
] : void 0,
|
|
9330
|
+
description: input.fields.description || "",
|
|
9331
|
+
metadata: {
|
|
9332
|
+
slug: input.fields.slug
|
|
9333
|
+
}
|
|
9334
|
+
});
|
|
9335
|
+
const { image, ...fieldsNoImage } = input.fields;
|
|
9336
|
+
await client.update(products).set({
|
|
9337
|
+
name: input.name,
|
|
9338
|
+
quantityAvailable: input.quantityAvailable,
|
|
9339
|
+
status: 1,
|
|
9340
|
+
fields: {
|
|
9341
|
+
...fieldsNoImage,
|
|
9342
|
+
...image?.url && {
|
|
9343
|
+
image
|
|
9344
|
+
}
|
|
9345
|
+
}
|
|
9346
|
+
}).where(eq(products.id, currentProduct.id));
|
|
9347
|
+
return adapter.getProduct(currentProduct.id);
|
|
9348
|
+
},
|
|
9349
|
+
async createProduct(input) {
|
|
9350
|
+
if (!paymentProvider)
|
|
9351
|
+
throw new Error("Payment provider not found");
|
|
9352
|
+
const merchantAccount2 = merchantAccountSchema.nullish().parse(await client.query.merchantAccount.findFirst({
|
|
9353
|
+
where: (merchantAccount3, { eq: eq2 }) => eq2(merchantAccount3.label, "stripe")
|
|
9354
|
+
}));
|
|
9355
|
+
if (!merchantAccount2) {
|
|
9356
|
+
throw new Error("Merchant account not found");
|
|
9357
|
+
}
|
|
9358
|
+
const hash = guid();
|
|
9359
|
+
const newProductId = slugify(`product-${hash}`);
|
|
9360
|
+
const newProduct = {
|
|
9361
|
+
id: newProductId,
|
|
9362
|
+
name: input.name,
|
|
9363
|
+
status: 1,
|
|
9364
|
+
type: "self-paced",
|
|
9365
|
+
quantityAvailable: input.quantityAvailable,
|
|
9366
|
+
fields: {
|
|
9367
|
+
state: "draft",
|
|
9368
|
+
visibility: "unlisted",
|
|
9369
|
+
slug: slugify(`${input.name}-${hash}`)
|
|
9370
|
+
}
|
|
9371
|
+
};
|
|
9372
|
+
await client.insert(products).values(newProduct);
|
|
9373
|
+
const priceHash = guid();
|
|
9374
|
+
const newPriceId = `price-${priceHash}`;
|
|
9375
|
+
await client.insert(prices).values({
|
|
9376
|
+
id: newPriceId,
|
|
9377
|
+
productId: newProductId,
|
|
9378
|
+
unitAmount: input.price.toString(),
|
|
9379
|
+
status: 1
|
|
9380
|
+
});
|
|
9381
|
+
const product = await adapter.getProduct(newProductId);
|
|
9382
|
+
const stripeProduct = await paymentProvider.createProduct({
|
|
9383
|
+
name: input.name,
|
|
9384
|
+
metadata: {
|
|
9385
|
+
slug: product?.fields?.slug || null
|
|
9386
|
+
}
|
|
9387
|
+
});
|
|
9388
|
+
const stripePrice = await paymentProvider.createPrice({
|
|
9389
|
+
product: stripeProduct.id,
|
|
9390
|
+
unit_amount: Math.floor(Number(input.price) * 100),
|
|
9391
|
+
currency: "usd",
|
|
9392
|
+
nickname: input.name,
|
|
9393
|
+
metadata: {
|
|
9394
|
+
slug: product?.fields?.slug || null
|
|
9395
|
+
}
|
|
9396
|
+
});
|
|
9397
|
+
const newMerchantProductId = `mproduct_${v4()}`;
|
|
9398
|
+
await client.insert(merchantProduct).values({
|
|
9399
|
+
id: newMerchantProductId,
|
|
9400
|
+
merchantAccountId: merchantAccount2.id,
|
|
9401
|
+
productId: newProductId,
|
|
9402
|
+
identifier: stripeProduct.id,
|
|
9403
|
+
status: 1
|
|
9404
|
+
});
|
|
9405
|
+
const newMerchantPriceId = `mprice_${v4()}`;
|
|
9406
|
+
await client.insert(merchantPrice).values({
|
|
9407
|
+
id: newMerchantPriceId,
|
|
9408
|
+
merchantAccountId: merchantAccount2.id,
|
|
9409
|
+
merchantProductId: newMerchantProductId,
|
|
9410
|
+
priceId: newPriceId,
|
|
9411
|
+
identifier: stripePrice.id,
|
|
9412
|
+
status: 1
|
|
9413
|
+
});
|
|
9414
|
+
return product;
|
|
9415
|
+
},
|
|
9416
|
+
async getProduct(productSlugOrId, withResources = true) {
|
|
9417
|
+
if (!productSlugOrId) {
|
|
9418
|
+
return null;
|
|
9419
|
+
}
|
|
9420
|
+
try {
|
|
9421
|
+
const productData = await client.query.products.findFirst({
|
|
9422
|
+
where: and(or(eq(sql`JSON_EXTRACT (${products.fields}, "$.slug")`, `${productSlugOrId}`), eq(products.id, productSlugOrId))),
|
|
9423
|
+
with: {
|
|
9424
|
+
price: true,
|
|
9425
|
+
...withResources && {
|
|
9426
|
+
resources: {
|
|
9427
|
+
with: {
|
|
9428
|
+
resource: {
|
|
9429
|
+
with: {
|
|
9430
|
+
resources: true
|
|
9431
|
+
}
|
|
9432
|
+
}
|
|
9433
|
+
}
|
|
9434
|
+
}
|
|
9435
|
+
}
|
|
9436
|
+
}
|
|
9437
|
+
});
|
|
9438
|
+
const parsedProduct = productSchema.safeParse(productData);
|
|
9439
|
+
if (!parsedProduct.success) {
|
|
9440
|
+
console.error("Error parsing product", JSON.stringify(parsedProduct.error), JSON.stringify(productData));
|
|
9441
|
+
return null;
|
|
9442
|
+
}
|
|
9443
|
+
return parsedProduct.data;
|
|
9444
|
+
} catch (e) {
|
|
9445
|
+
console.log("getProduct error", e);
|
|
9446
|
+
return null;
|
|
9447
|
+
}
|
|
9448
|
+
},
|
|
9449
|
+
async getProductResources(productId) {
|
|
9450
|
+
const contentResourceProductsForProduct = z.array(ContentResourceProductSchema).nullable().parse(await client.query.contentResourceProduct.findMany({
|
|
9451
|
+
where: eq(contentResourceProduct.productId, productId)
|
|
9452
|
+
}));
|
|
9453
|
+
if (!contentResourceProductsForProduct) {
|
|
9454
|
+
return null;
|
|
9455
|
+
} else {
|
|
9456
|
+
const contentResources = z.array(ContentResourceSchema).parse(await client.query.contentResource.findMany({
|
|
9457
|
+
where: inArray(contentResource.id, contentResourceProductsForProduct.map((crp) => crp.resourceId))
|
|
9458
|
+
}));
|
|
9459
|
+
return contentResources;
|
|
9460
|
+
}
|
|
9238
9461
|
},
|
|
9239
9462
|
async getPurchaseCountForProduct(productId) {
|
|
9240
9463
|
return await client.query.purchases.findMany({
|
|
@@ -9267,7 +9490,7 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
9267
9490
|
where: eq(merchantCharge.identifier, stripeChargeId)
|
|
9268
9491
|
}) || null);
|
|
9269
9492
|
if (!chargeForPurchase) {
|
|
9270
|
-
logger.error(new Error(
|
|
9493
|
+
logger.error(new Error(`No charge found for purchase: Stripe Charge ID: ${stripeChargeId}`));
|
|
9271
9494
|
return null;
|
|
9272
9495
|
}
|
|
9273
9496
|
const purchase = purchaseSchema.safeParse(await client.query.purchases.findFirst({
|
|
@@ -9402,6 +9625,33 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
9402
9625
|
purchase: parsedPurchase.data
|
|
9403
9626
|
};
|
|
9404
9627
|
},
|
|
9628
|
+
async getUserWithPurchasersByEmail(email) {
|
|
9629
|
+
const user = await client.query.users.findFirst({
|
|
9630
|
+
where: eq(users.email, email.trim().toLowerCase()),
|
|
9631
|
+
with: {
|
|
9632
|
+
// merchantCustomer: true,
|
|
9633
|
+
roles: {
|
|
9634
|
+
with: {
|
|
9635
|
+
role: true
|
|
9636
|
+
}
|
|
9637
|
+
},
|
|
9638
|
+
purchases: {
|
|
9639
|
+
with: {
|
|
9640
|
+
bulkCoupon: true,
|
|
9641
|
+
merchantCharge: true,
|
|
9642
|
+
product: {
|
|
9643
|
+
columns: {
|
|
9644
|
+
id: true,
|
|
9645
|
+
name: true,
|
|
9646
|
+
key: true
|
|
9647
|
+
}
|
|
9648
|
+
}
|
|
9649
|
+
}
|
|
9650
|
+
}
|
|
9651
|
+
}
|
|
9652
|
+
});
|
|
9653
|
+
return user;
|
|
9654
|
+
},
|
|
9405
9655
|
async getUserById(userId) {
|
|
9406
9656
|
const user = await client.query.users.findFirst({
|
|
9407
9657
|
where: eq(users.id, userId),
|
|
@@ -9478,8 +9728,40 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
9478
9728
|
transferPurchasesToNewUser(options) {
|
|
9479
9729
|
throw new Error("Method not implemented.");
|
|
9480
9730
|
},
|
|
9481
|
-
updatePurchaseStatusForCharge(chargeId, status) {
|
|
9482
|
-
|
|
9731
|
+
async updatePurchaseStatusForCharge(chargeId, status) {
|
|
9732
|
+
try {
|
|
9733
|
+
console.log("updatePurchaseStatusForCharge", {
|
|
9734
|
+
chargeId,
|
|
9735
|
+
status
|
|
9736
|
+
});
|
|
9737
|
+
const merchantChargeForPurchase = await client.query.merchantCharge.findFirst({
|
|
9738
|
+
where: or(eq(merchantCharge.identifier, chargeId), eq(merchantCharge.id, chargeId))
|
|
9739
|
+
});
|
|
9740
|
+
console.log("merchantChargeForPurchase", {
|
|
9741
|
+
merchantChargeForPurchase
|
|
9742
|
+
});
|
|
9743
|
+
const parsedMerchantChargeForPurchase = merchantChargeSchema.parse(merchantChargeForPurchase);
|
|
9744
|
+
if (!parsedMerchantChargeForPurchase)
|
|
9745
|
+
throw new Error(`no-charge-found-for-purchase ${chargeId}`);
|
|
9746
|
+
const purchase = await client.query.purchases.findFirst({
|
|
9747
|
+
where: eq(purchaseTable.merchantChargeId, parsedMerchantChargeForPurchase.id)
|
|
9748
|
+
});
|
|
9749
|
+
const parsedPurchase = purchaseSchema.nullable().parse(purchase);
|
|
9750
|
+
if (parsedPurchase) {
|
|
9751
|
+
await client.update(purchaseTable).set({
|
|
9752
|
+
status
|
|
9753
|
+
}).where(eq(purchaseTable.id, parsedPurchase.id));
|
|
9754
|
+
const newPurchase = await client.query.purchases.findFirst({
|
|
9755
|
+
where: eq(purchaseTable.id, parsedPurchase.id)
|
|
9756
|
+
});
|
|
9757
|
+
return purchaseSchema.optional().parse(newPurchase);
|
|
9758
|
+
} else {
|
|
9759
|
+
throw new Error(`no-purchase-found-for-charge ${chargeId}`);
|
|
9760
|
+
}
|
|
9761
|
+
} catch (e) {
|
|
9762
|
+
console.log("error updating purchase status", e);
|
|
9763
|
+
throw e;
|
|
9764
|
+
}
|
|
9483
9765
|
},
|
|
9484
9766
|
async updatePurchaseUserTransferTransferState(options) {
|
|
9485
9767
|
await client.update(purchaseUserTransfer).set({
|
|
@@ -9516,6 +9798,18 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
9516
9798
|
}
|
|
9517
9799
|
return parsedResourceJoin.data;
|
|
9518
9800
|
},
|
|
9801
|
+
async removeResourceFromResource(options) {
|
|
9802
|
+
const { childResourceId, parentResourceId } = options;
|
|
9803
|
+
const resourceJoin = await client.query.contentResourceResource.findFirst({
|
|
9804
|
+
where: and(eq(contentResourceResource.resourceOfId, parentResourceId), eq(contentResourceResource.resourceId, childResourceId))
|
|
9805
|
+
});
|
|
9806
|
+
const parsedResourceJoin = ContentResourceResourceSchema.safeParse(resourceJoin);
|
|
9807
|
+
if (!parsedResourceJoin.success) {
|
|
9808
|
+
return null;
|
|
9809
|
+
}
|
|
9810
|
+
await client.delete(contentResourceResource).where(and(eq(contentResourceResource.resourceOfId, parentResourceId), eq(contentResourceResource.resourceId, childResourceId)));
|
|
9811
|
+
return parsedResourceJoin.data.resource;
|
|
9812
|
+
},
|
|
9519
9813
|
async updateContentResourceFields(options) {
|
|
9520
9814
|
if (!options.id) {
|
|
9521
9815
|
throw new Error("No content resource id.");
|
|
@@ -9748,8 +10042,9 @@ function mySqlDrizzleAdapter(client, tableFn = defaultMySqlTableFn) {
|
|
|
9748
10042
|
__name(mySqlDrizzleAdapter, "mySqlDrizzleAdapter");
|
|
9749
10043
|
|
|
9750
10044
|
export {
|
|
10045
|
+
guid,
|
|
9751
10046
|
getCourseBuilderSchema,
|
|
9752
10047
|
createTables,
|
|
9753
10048
|
mySqlDrizzleAdapter
|
|
9754
10049
|
};
|
|
9755
|
-
//# sourceMappingURL=chunk-
|
|
10050
|
+
//# sourceMappingURL=chunk-VUS77FG3.js.map
|