@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.
Files changed (69) hide show
  1. package/dist/{chunk-BM5UKWXI.js → chunk-7ISZNMPU.js} +2 -2
  2. package/dist/{chunk-TBM3AK3P.js → chunk-7X7TMG4A.js} +2 -2
  3. package/dist/{chunk-CQNKTFXE.js → chunk-DAP5KOAO.js} +2 -2
  4. package/dist/{chunk-JZQ666KH.js → chunk-KDOSK7KN.js} +2 -2
  5. package/dist/{chunk-O6JECJRY.js → chunk-QPXUGIXO.js} +2 -2
  6. package/dist/{chunk-FRA4ZCRA.js → chunk-UHH4OVKA.js} +4 -14
  7. package/dist/{chunk-QTGVGIRO.js → chunk-UK6EHYS5.js} +2 -2
  8. package/dist/{chunk-Z245DYMP.js → chunk-VUS77FG3.js} +493 -198
  9. package/dist/index.d.ts +2 -1
  10. package/dist/index.js +12 -12
  11. package/dist/lib/mysql/index.cjs +498 -202
  12. package/dist/lib/mysql/index.cjs.map +1 -1
  13. package/dist/lib/mysql/index.d.cts +8 -30
  14. package/dist/lib/mysql/index.d.ts +8 -30
  15. package/dist/lib/mysql/index.js +10 -8
  16. package/dist/lib/mysql/schemas/auth/accounts.cjs.map +1 -1
  17. package/dist/lib/mysql/schemas/auth/accounts.js +1 -1
  18. package/dist/lib/mysql/schemas/auth/device-access-token.cjs.map +1 -1
  19. package/dist/lib/mysql/schemas/auth/device-access-token.js +2 -2
  20. package/dist/lib/mysql/schemas/auth/device-verification.cjs.map +1 -1
  21. package/dist/lib/mysql/schemas/auth/device-verification.js +2 -2
  22. package/dist/lib/mysql/schemas/auth/role-permissions.cjs.map +1 -1
  23. package/dist/lib/mysql/schemas/auth/role-permissions.js +2 -2
  24. package/dist/lib/mysql/schemas/auth/roles.cjs.map +1 -1
  25. package/dist/lib/mysql/schemas/auth/roles.js +1 -1
  26. package/dist/lib/mysql/schemas/auth/sessions.cjs.map +1 -1
  27. package/dist/lib/mysql/schemas/auth/sessions.js +2 -2
  28. package/dist/lib/mysql/schemas/auth/user-permissions.cjs.map +1 -1
  29. package/dist/lib/mysql/schemas/auth/user-permissions.js +1 -1
  30. package/dist/lib/mysql/schemas/auth/user-prefs.cjs.map +1 -1
  31. package/dist/lib/mysql/schemas/auth/user-prefs.js +1 -1
  32. package/dist/lib/mysql/schemas/auth/user-roles.cjs.map +1 -1
  33. package/dist/lib/mysql/schemas/auth/user-roles.js +1 -1
  34. package/dist/lib/mysql/schemas/auth/users.cjs.map +1 -1
  35. package/dist/lib/mysql/schemas/auth/users.js +1 -1
  36. package/dist/lib/mysql/schemas/commerce/coupon.cjs +3 -13
  37. package/dist/lib/mysql/schemas/commerce/coupon.cjs.map +1 -1
  38. package/dist/lib/mysql/schemas/commerce/coupon.d.cts +2 -14
  39. package/dist/lib/mysql/schemas/commerce/coupon.d.ts +2 -14
  40. package/dist/lib/mysql/schemas/commerce/coupon.js +1 -1
  41. package/dist/lib/mysql/schemas/commerce/price.cjs.map +1 -1
  42. package/dist/lib/mysql/schemas/commerce/price.js +1 -1
  43. package/dist/lib/mysql/schemas/commerce/product.cjs.map +1 -1
  44. package/dist/lib/mysql/schemas/commerce/product.js +1 -1
  45. package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.cjs.map +1 -1
  46. package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.js +2 -2
  47. package/dist/lib/mysql/schemas/commerce/purchase.cjs +0 -4
  48. package/dist/lib/mysql/schemas/commerce/purchase.cjs.map +1 -1
  49. package/dist/lib/mysql/schemas/commerce/purchase.js +1 -1
  50. package/dist/lib/mysql/schemas/commerce/upgradable-products.cjs.map +1 -1
  51. package/dist/lib/mysql/schemas/commerce/upgradable-products.js +2 -2
  52. package/dist/lib/mysql/schemas/communication/comment.cjs.map +1 -1
  53. package/dist/lib/mysql/schemas/communication/comment.js +1 -1
  54. package/dist/lib/mysql/schemas/communication/communication-preferences.cjs.map +1 -1
  55. package/dist/lib/mysql/schemas/communication/communication-preferences.js +1 -1
  56. package/dist/lib/mysql/schemas/content/content-contributions.cjs.map +1 -1
  57. package/dist/lib/mysql/schemas/content/content-contributions.js +1 -1
  58. package/dist/lib/mysql/schemas/content/content-resource-product.cjs.map +1 -1
  59. package/dist/lib/mysql/schemas/content/content-resource-product.js +1 -1
  60. package/dist/lib/mysql/schemas/content/content-resource-resource.cjs.map +1 -1
  61. package/dist/lib/mysql/schemas/content/content-resource-resource.js +1 -1
  62. package/dist/lib/mysql/schemas/content/content-resource.cjs.map +1 -1
  63. package/dist/lib/mysql/schemas/content/content-resource.js +1 -1
  64. package/dist/lib/utils.d.cts +1 -0
  65. package/dist/lib/utils.d.ts +1 -0
  66. package/package.json +4 -2
  67. package/src/index.ts +14 -4
  68. package/src/lib/mysql/index.ts +601 -182
  69. 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-CQNKTFXE.js";
10
+ } from "./chunk-DAP5KOAO.js";
11
11
  import {
12
12
  getUpgradableProductsRelationsSchema,
13
13
  getUpgradableProductsSchema
14
- } from "./chunk-BM5UKWXI.js";
14
+ } from "./chunk-7ISZNMPU.js";
15
15
  import {
16
16
  getRolePermissionsRelationsSchema,
17
17
  getRolePermissionsSchema
18
- } from "./chunk-O6JECJRY.js";
18
+ } from "./chunk-QPXUGIXO.js";
19
19
  import {
20
20
  getSessionRelationsSchema,
21
21
  getSessionsSchema
22
- } from "./chunk-TBM3AK3P.js";
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-QTGVGIRO.js";
29
+ } from "./chunk-UK6EHYS5.js";
30
30
  import {
31
31
  getDeviceVerificationRelationsSchema,
32
32
  getDeviceVerificationSchema
33
- } from "./chunk-JZQ666KH.js";
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-FRA4ZCRA.js";
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, isNotNull, isNull, not, or, sql } from "drizzle-orm";
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-YYIPQN6H.js
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-DGMGNBW7.js
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().optional().nullable(),
8240
+ description: z2.string().nullish(),
8216
8241
  slug: z2.string(),
8217
8242
  image: z2.object({
8218
- url: z2.string().url(),
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-VDB4YSMY.js
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
- bulkPurchaseId: z2.string().max(191).optional().nullable(),
8261
- bulkCouponPurchases: z2.any().optional().nullable()
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-OUYYSWMK.js
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-K6G2HAJT.js
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
- fields: z2.record(z2.any()).default({}),
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.bulkPurchase?.bulkCouponId);
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
- throw new Error(`already-purchased-${email}`);
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 await client.query.upgradableProducts.findMany({
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
- bulkPurchase: true,
8979
- bulkCouponPurchases: true
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
- bulkCouponPurchases: z.array(purchaseSchema),
8995
- bulkPurchase: purchaseSchema.nullable().optional()
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
- with: {
9116
- roles: {
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
- console.error("User not found", userIdOrEmail);
9132
- return {
9133
- completedLessons: [],
9134
- nextResource: null,
9135
- percentCompleted: 0,
9136
- completedLessonsCount: 0,
9137
- totalLessonsCount
9138
- };
9079
+ return null;
9139
9080
  }
9140
- const parsedUser = userSchema.safeParse(user);
9141
- if (!parsedUser.success) {
9142
- console.error("Error parsing user", parsedUser.error);
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 userProgress = await client.query.resourceProgress.findMany({
9152
- where: and(eq(resourceProgress.userId, parsedUser.data.id), isNotNull(resourceProgress.completedAt), inArray(resourceProgress.resourceId, progressResources.map((r) => r.id))),
9153
- orderBy: asc(resourceProgress.completedAt)
9154
- });
9155
- const nextResourceId = parsedResources.data.filter((r) => {
9156
- return COUNTABLE_MODULE_RESOURCE_TYPES.includes(r.type);
9157
- }).find((r) => !userProgress.find((p) => p.resourceId === r.id))?.id;
9158
- const nextResource = await client.query.contentResource.findFirst({
9159
- where: eq(contentResource.id, nextResourceId)
9160
- });
9161
- const parsedNextResource = ContentResourceSchema.nullable().optional().default(null).parse(nextResource);
9162
- const parsedProgress = z.array(resourceProgressSchema).safeParse(userProgress);
9163
- if (!parsedProgress.success) {
9164
- console.error("Error parsing user progress", parsedProgress.error);
9165
- return {
9166
- completedLessons: [],
9167
- nextResource: null,
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.round(parsedProgress.data.length / parsedResources.data.length * 100);
9157
+ const percentCompleted = totalLessonsCount > 0 ? Math.ceil(completedLessonsCount / totalLessonsCount * 100) : 0;
9174
9158
  return {
9175
- completedLessons: parsedProgress.data,
9176
- nextResource: parsedNextResource,
9159
+ completedLessons,
9160
+ nextResource,
9177
9161
  percentCompleted,
9178
- completedLessonsCount: parsedProgress.data.length,
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.error("Error parsing merchantCharge", mCharge);
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 getProduct(productId) {
9235
- return productSchema.nullable().parse(await client.query.products.findFirst({
9236
- where: eq(products.id, productId)
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("No charge found for purchase"));
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
- throw new Error("updatePurchaseStatusForCharge Method not implemented.");
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-Z245DYMP.js.map
10050
+ //# sourceMappingURL=chunk-VUS77FG3.js.map