@coursebuilder/adapter-drizzle 2.1.0 → 3.0.0-canary.0.0c9beb2ae
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-KIQLUFJX.js → chunk-2GW3BJE2.js} +2 -2
- package/dist/{chunk-M3WM5Q7W.js → chunk-33ZN7FN7.js} +2 -2
- package/dist/chunk-4VZJQAPV.js +74 -0
- package/dist/chunk-5FLS4ZBX.js +109 -0
- package/dist/chunk-5YR5M22S.js +147 -0
- package/dist/chunk-6XQ6C3IX.js +18 -0
- package/dist/chunk-AIDM2CH6.js +146 -0
- package/dist/chunk-ALTODDUX.js +173 -0
- package/dist/chunk-AZY2VRAE.js +63 -0
- package/dist/chunk-BS7T27VL.js +239 -0
- package/dist/chunk-CN3FCRLR.js +55 -0
- package/dist/chunk-EAXC4CQD.js +245 -0
- package/dist/chunk-EDDG2YFS.js +249 -0
- package/dist/chunk-EDKWCMA7.js +210 -0
- package/dist/{chunk-CFSRMUNC.js → chunk-EDM6DKA5.js} +2 -2
- package/dist/{chunk-EZEQQJNH.js → chunk-EIQBTF5J.js} +2 -2
- package/dist/chunk-FYT7RTVW.js +248 -0
- package/dist/{chunk-DUFH5L2F.js → chunk-INZTF6QV.js} +2 -2
- package/dist/{chunk-3AF6MZQ7.js → chunk-JVHX4JHA.js} +2 -2
- package/dist/chunk-LWEKWDLC.js +300 -0
- package/dist/chunk-OJPEBGGE.js +139 -0
- package/dist/chunk-QKOSV34V.js +16268 -0
- package/dist/chunk-QO3QE3LE.js +330 -0
- package/dist/chunk-QQKNNFFB.js +399 -0
- package/dist/chunk-RBHCV3UW.js +20 -0
- package/dist/chunk-TNH2C27F.js +252 -0
- package/dist/chunk-TNWNW666.js +133 -0
- package/dist/chunk-VBEXYQ6L.js +156 -0
- package/dist/chunk-W3ILNMLD.js +265 -0
- package/dist/chunk-WJ2ZUXL3.js +71 -0
- package/dist/{chunk-4SWTV7Z3.js → chunk-WUMDFFN3.js} +2 -2
- package/dist/{chunk-FJGNLVE4.js → chunk-X7DRYXB7.js} +2 -2
- package/dist/{chunk-PNPTKVJ4.js → chunk-XUBZKYH6.js} +24 -15
- package/dist/{chunk-MYG6PCE3.js → chunk-ZY4AFKUQ.js} +2 -2
- package/dist/index.d.ts +5 -11
- package/dist/index.js +42 -19
- package/dist/lib/mysql/cms-resource-actions.cjs +15932 -4129
- package/dist/lib/mysql/cms-resource-actions.cjs.map +1 -1
- package/dist/lib/mysql/cms-resource-actions.d.cts +10 -25
- package/dist/lib/mysql/cms-resource-actions.d.ts +10 -25
- package/dist/lib/mysql/cms-resource-actions.js +2 -1
- package/dist/lib/mysql/context.cjs +3380 -0
- package/dist/lib/mysql/context.cjs.map +1 -0
- package/dist/lib/mysql/context.d.cts +15 -0
- package/dist/lib/mysql/context.d.ts +15 -0
- package/dist/lib/mysql/context.js +34 -0
- package/dist/lib/mysql/context.js.map +1 -0
- package/dist/lib/mysql/index.cjs +21648 -15013
- package/dist/lib/mysql/index.cjs.map +1 -1
- package/dist/lib/mysql/index.d.cts +24 -14300
- package/dist/lib/mysql/index.d.ts +24 -14300
- package/dist/lib/mysql/index.js +47 -23
- package/dist/lib/mysql/ports/auth-storage.cjs +84 -0
- package/dist/lib/mysql/ports/auth-storage.cjs.map +1 -0
- package/dist/lib/mysql/ports/auth-storage.d.cts +22 -0
- package/dist/lib/mysql/ports/auth-storage.d.ts +22 -0
- package/dist/lib/mysql/ports/auth-storage.js +8 -0
- package/dist/lib/mysql/ports/auth-storage.js.map +1 -0
- package/dist/lib/mysql/ports/catalog.cjs +16688 -0
- package/dist/lib/mysql/ports/catalog.cjs.map +1 -0
- package/dist/lib/mysql/ports/catalog.d.cts +24 -0
- package/dist/lib/mysql/ports/catalog.d.ts +24 -0
- package/dist/lib/mysql/ports/catalog.js +9 -0
- package/dist/lib/mysql/ports/catalog.js.map +1 -0
- package/dist/lib/mysql/ports/content-resource.cjs +321 -0
- package/dist/lib/mysql/ports/content-resource.cjs.map +1 -0
- package/dist/lib/mysql/ports/content-resource.d.cts +23 -0
- package/dist/lib/mysql/ports/content-resource.d.ts +23 -0
- package/dist/lib/mysql/ports/content-resource.js +8 -0
- package/dist/lib/mysql/ports/content-resource.js.map +1 -0
- package/dist/lib/mysql/ports/coupon.cjs +16524 -0
- package/dist/lib/mysql/ports/coupon.cjs.map +1 -0
- package/dist/lib/mysql/ports/coupon.d.cts +22 -0
- package/dist/lib/mysql/ports/coupon.d.ts +22 -0
- package/dist/lib/mysql/ports/coupon.js +9 -0
- package/dist/lib/mysql/ports/coupon.js.map +1 -0
- package/dist/lib/mysql/ports/entitlement.cjs +16350 -0
- package/dist/lib/mysql/ports/entitlement.cjs.map +1 -0
- package/dist/lib/mysql/ports/entitlement.d.cts +22 -0
- package/dist/lib/mysql/ports/entitlement.d.ts +22 -0
- package/dist/lib/mysql/ports/entitlement.js +9 -0
- package/dist/lib/mysql/ports/entitlement.js.map +1 -0
- package/dist/lib/mysql/ports/identity.cjs +154 -0
- package/dist/lib/mysql/ports/identity.cjs.map +1 -0
- package/dist/lib/mysql/ports/identity.d.cts +22 -0
- package/dist/lib/mysql/ports/identity.d.ts +22 -0
- package/dist/lib/mysql/ports/identity.js +8 -0
- package/dist/lib/mysql/ports/identity.js.map +1 -0
- package/dist/lib/mysql/ports/merchant.cjs +194 -0
- package/dist/lib/mysql/ports/merchant.cjs.map +1 -0
- package/dist/lib/mysql/ports/merchant.d.cts +22 -0
- package/dist/lib/mysql/ports/merchant.d.ts +22 -0
- package/dist/lib/mysql/ports/merchant.js +8 -0
- package/dist/lib/mysql/ports/merchant.js.map +1 -0
- package/dist/lib/mysql/ports/organization.cjs +16426 -0
- package/dist/lib/mysql/ports/organization.cjs.map +1 -0
- package/dist/lib/mysql/ports/organization.d.cts +22 -0
- package/dist/lib/mysql/ports/organization.d.ts +22 -0
- package/dist/lib/mysql/ports/organization.js +9 -0
- package/dist/lib/mysql/ports/organization.js.map +1 -0
- package/dist/lib/mysql/ports/progress.cjs +16544 -0
- package/dist/lib/mysql/ports/progress.cjs.map +1 -0
- package/dist/lib/mysql/ports/progress.d.cts +22 -0
- package/dist/lib/mysql/ports/progress.d.ts +22 -0
- package/dist/lib/mysql/ports/progress.js +9 -0
- package/dist/lib/mysql/ports/progress.js.map +1 -0
- package/dist/lib/mysql/ports/purchase.cjs +16609 -0
- package/dist/lib/mysql/ports/purchase.cjs.map +1 -0
- package/dist/lib/mysql/ports/purchase.d.cts +23 -0
- package/dist/lib/mysql/ports/purchase.d.ts +23 -0
- package/dist/lib/mysql/ports/purchase.js +9 -0
- package/dist/lib/mysql/ports/purchase.js.map +1 -0
- package/dist/lib/mysql/ports/subscription.cjs +76 -0
- package/dist/lib/mysql/ports/subscription.cjs.map +1 -0
- package/dist/lib/mysql/ports/subscription.d.cts +22 -0
- package/dist/lib/mysql/ports/subscription.d.ts +22 -0
- package/dist/lib/mysql/ports/subscription.js +8 -0
- package/dist/lib/mysql/ports/subscription.js.map +1 -0
- package/dist/lib/mysql/schema.cjs +3373 -0
- package/dist/lib/mysql/schema.cjs.map +1 -0
- package/dist/lib/mysql/schema.d.cts +14385 -0
- package/dist/lib/mysql/schema.d.ts +14385 -0
- package/dist/lib/mysql/schema.js +35 -0
- package/dist/lib/mysql/schema.js.map +1 -0
- package/dist/lib/mysql/schemas/auth/accounts.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/accounts.js +6 -6
- package/dist/lib/mysql/schemas/auth/device-access-token.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/device-access-token.js +7 -7
- package/dist/lib/mysql/schemas/auth/device-verification.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/device-verification.js +7 -7
- package/dist/lib/mysql/schemas/auth/personal-access-token.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/personal-access-token.js +7 -7
- package/dist/lib/mysql/schemas/auth/profiles.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/profiles.js +6 -6
- package/dist/lib/mysql/schemas/auth/role-permissions.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/role-permissions.js +7 -7
- package/dist/lib/mysql/schemas/auth/roles.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/roles.js +6 -6
- package/dist/lib/mysql/schemas/auth/sessions.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/sessions.js +7 -7
- package/dist/lib/mysql/schemas/auth/user-permissions.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/user-permissions.js +6 -6
- package/dist/lib/mysql/schemas/auth/user-prefs.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/user-prefs.js +6 -6
- package/dist/lib/mysql/schemas/auth/user-roles.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/user-roles.js +6 -6
- package/dist/lib/mysql/schemas/auth/users.cjs +5 -1
- package/dist/lib/mysql/schemas/auth/users.cjs.map +1 -1
- package/dist/lib/mysql/schemas/auth/users.js +6 -6
- package/dist/lib/mysql/schemas/commerce/coupon.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/coupon.js +6 -6
- package/dist/lib/mysql/schemas/commerce/merchant-charge.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-charge.js +6 -6
- package/dist/lib/mysql/schemas/commerce/merchant-subscription.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/merchant-subscription.js +6 -6
- package/dist/lib/mysql/schemas/commerce/price.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/price.js +6 -6
- package/dist/lib/mysql/schemas/commerce/product.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/product.js +6 -6
- package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/purchase-user-transfer.js +7 -7
- package/dist/lib/mysql/schemas/commerce/purchase.cjs +11 -2
- package/dist/lib/mysql/schemas/commerce/purchase.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/purchase.js +6 -6
- package/dist/lib/mysql/schemas/commerce/subscription.cjs +6 -1
- package/dist/lib/mysql/schemas/commerce/subscription.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/subscription.js +6 -6
- package/dist/lib/mysql/schemas/commerce/upgradable-products.cjs.map +1 -1
- package/dist/lib/mysql/schemas/commerce/upgradable-products.js +7 -7
- package/dist/lib/mysql/schemas/communication/comment.cjs +5 -1
- package/dist/lib/mysql/schemas/communication/comment.cjs.map +1 -1
- package/dist/lib/mysql/schemas/communication/comment.js +6 -6
- package/dist/lib/mysql/schemas/communication/communication-preferences.cjs +5 -1
- package/dist/lib/mysql/schemas/communication/communication-preferences.cjs.map +1 -1
- package/dist/lib/mysql/schemas/communication/communication-preferences.js +6 -6
- package/dist/lib/mysql/schemas/communication/question-response.cjs.map +1 -1
- package/dist/lib/mysql/schemas/communication/question-response.js +7 -7
- package/dist/lib/mysql/schemas/content/content-contributions.cjs +5 -1
- package/dist/lib/mysql/schemas/content/content-contributions.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-contributions.js +6 -6
- package/dist/lib/mysql/schemas/content/content-resource-product.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-resource-product.js +6 -6
- package/dist/lib/mysql/schemas/content/content-resource-resource.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-resource-resource.js +6 -6
- package/dist/lib/mysql/schemas/content/content-resource-tag.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-resource-tag.js +6 -6
- package/dist/lib/mysql/schemas/content/content-resource-version.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-resource-version.js +6 -6
- package/dist/lib/mysql/schemas/content/content-resource.cjs +5 -1
- package/dist/lib/mysql/schemas/content/content-resource.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/content-resource.js +6 -6
- package/dist/lib/mysql/schemas/content/tag-tag.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/tag-tag.js +6 -6
- package/dist/lib/mysql/schemas/content/tag.cjs.map +1 -1
- package/dist/lib/mysql/schemas/content/tag.js +6 -6
- package/dist/lib/mysql/schemas/entitlements/entitlement.cjs +11 -2
- package/dist/lib/mysql/schemas/entitlements/entitlement.cjs.map +1 -1
- package/dist/lib/mysql/schemas/entitlements/entitlement.js +7 -7
- package/dist/lib/mysql/schemas/org/organization-membership-roles.cjs +11 -2
- package/dist/lib/mysql/schemas/org/organization-membership-roles.cjs.map +1 -1
- package/dist/lib/mysql/schemas/org/organization-membership-roles.js +6 -6
- package/dist/lib/mysql/schemas/org/organization-memberships.cjs +11 -2
- package/dist/lib/mysql/schemas/org/organization-memberships.cjs.map +1 -1
- package/dist/lib/mysql/schemas/org/organization-memberships.d.cts +16 -0
- package/dist/lib/mysql/schemas/org/organization-memberships.d.ts +16 -0
- package/dist/lib/mysql/schemas/org/organization-memberships.js +6 -6
- package/dist/lib/mysql/schemas/org/organizations.cjs +11 -2
- package/dist/lib/mysql/schemas/org/organizations.cjs.map +1 -1
- package/dist/lib/mysql/schemas/org/organizations.d.cts +16 -0
- package/dist/lib/mysql/schemas/org/organizations.d.ts +16 -0
- package/dist/lib/mysql/schemas/org/organizations.js +6 -6
- package/dist/lib/mysql/workflows/content-resource-workflow-utils.cjs +40 -0
- package/dist/lib/mysql/workflows/content-resource-workflow-utils.cjs.map +1 -0
- package/dist/lib/mysql/workflows/content-resource-workflow-utils.d.cts +4 -0
- package/dist/lib/mysql/workflows/content-resource-workflow-utils.d.ts +4 -0
- package/dist/lib/mysql/workflows/content-resource-workflow-utils.js +10 -0
- package/dist/lib/mysql/workflows/content-resource-workflow-utils.js.map +1 -0
- package/dist/lib/mysql/workflows/create-cohort.cjs +184 -0
- package/dist/lib/mysql/workflows/create-cohort.cjs.map +1 -0
- package/dist/lib/mysql/workflows/create-cohort.d.cts +24 -0
- package/dist/lib/mysql/workflows/create-cohort.d.ts +24 -0
- package/dist/lib/mysql/workflows/create-cohort.js +9 -0
- package/dist/lib/mysql/workflows/create-cohort.js.map +1 -0
- package/dist/lib/mysql/workflows/create-event-series.cjs +283 -0
- package/dist/lib/mysql/workflows/create-event-series.cjs.map +1 -0
- package/dist/lib/mysql/workflows/create-event-series.d.cts +24 -0
- package/dist/lib/mysql/workflows/create-event-series.d.ts +24 -0
- package/dist/lib/mysql/workflows/create-event-series.js +9 -0
- package/dist/lib/mysql/workflows/create-event-series.js.map +1 -0
- package/dist/lib/mysql/workflows/create-event.cjs +194 -0
- package/dist/lib/mysql/workflows/create-event.cjs.map +1 -0
- package/dist/lib/mysql/workflows/create-event.d.cts +24 -0
- package/dist/lib/mysql/workflows/create-event.d.ts +24 -0
- package/dist/lib/mysql/workflows/create-event.js +9 -0
- package/dist/lib/mysql/workflows/create-event.js.map +1 -0
- package/dist/lib/mysql/workflows/create-merchant-charge-and-purchase.cjs +231 -0
- package/dist/lib/mysql/workflows/create-merchant-charge-and-purchase.cjs.map +1 -0
- package/dist/lib/mysql/workflows/create-merchant-charge-and-purchase.d.cts +22 -0
- package/dist/lib/mysql/workflows/create-merchant-charge-and-purchase.d.ts +22 -0
- package/dist/lib/mysql/workflows/create-merchant-charge-and-purchase.js +8 -0
- package/dist/lib/mysql/workflows/create-merchant-charge-and-purchase.js.map +1 -0
- package/dist/lib/mysql/workflows/create-workshop.cjs +286 -0
- package/dist/lib/mysql/workflows/create-workshop.cjs.map +1 -0
- package/dist/lib/mysql/workflows/create-workshop.d.cts +24 -0
- package/dist/lib/mysql/workflows/create-workshop.d.ts +24 -0
- package/dist/lib/mysql/workflows/create-workshop.js +9 -0
- package/dist/lib/mysql/workflows/create-workshop.js.map +1 -0
- package/dist/lib/mysql/workflows/redeem-full-price-coupon.cjs +130 -0
- package/dist/lib/mysql/workflows/redeem-full-price-coupon.cjs.map +1 -0
- package/dist/lib/mysql/workflows/redeem-full-price-coupon.d.cts +24 -0
- package/dist/lib/mysql/workflows/redeem-full-price-coupon.d.ts +24 -0
- package/dist/lib/mysql/workflows/redeem-full-price-coupon.js +8 -0
- package/dist/lib/mysql/workflows/redeem-full-price-coupon.js.map +1 -0
- package/dist/lib/mysql/workflows/transfer-purchase-to-user.cjs +95 -0
- package/dist/lib/mysql/workflows/transfer-purchase-to-user.cjs.map +1 -0
- package/dist/lib/mysql/workflows/transfer-purchase-to-user.d.cts +30 -0
- package/dist/lib/mysql/workflows/transfer-purchase-to-user.d.ts +30 -0
- package/dist/lib/mysql/workflows/transfer-purchase-to-user.js +8 -0
- package/dist/lib/mysql/workflows/transfer-purchase-to-user.js.map +1 -0
- package/dist/lib/utils.d.cts +1 -10
- package/dist/lib/utils.d.ts +1 -10
- package/dist/types.d.ts +14 -0
- package/dist/types.js +1 -0
- package/package.json +9 -5
- package/src/index.ts +3 -2
- package/src/lib/mysql/cms-resource-actions.ts +37 -0
- package/src/lib/mysql/context.ts +20 -0
- package/src/lib/mysql/index.ts +118 -4872
- package/src/lib/mysql/ports/auth-storage.ts +139 -0
- package/src/lib/mysql/ports/catalog.ts +610 -0
- package/src/lib/mysql/ports/content-resource.ts +442 -0
- package/src/lib/mysql/ports/coupon.ts +387 -0
- package/src/lib/mysql/ports/entitlement.ts +96 -0
- package/src/lib/mysql/ports/identity.ts +160 -0
- package/src/lib/mysql/ports/merchant.ts +274 -0
- package/src/lib/mysql/ports/organization.ts +216 -0
- package/src/lib/mysql/ports/progress.ts +366 -0
- package/src/lib/mysql/ports/purchase.ts +517 -0
- package/src/lib/mysql/ports/subscription.ts +93 -0
- package/src/lib/mysql/schema.ts +374 -0
- package/src/lib/mysql/schemas/org/organization-memberships.ts +7 -0
- package/src/lib/mysql/schemas/org/organizations.ts +8 -0
- package/src/lib/mysql/workflows/content-resource-workflow-utils.ts +22 -0
- package/src/lib/mysql/workflows/create-cohort.ts +239 -0
- package/src/lib/mysql/workflows/create-event-series.ts +384 -0
- package/src/lib/mysql/workflows/create-event.ts +232 -0
- package/src/lib/mysql/workflows/create-merchant-charge-and-purchase.ts +365 -0
- package/src/lib/mysql/workflows/create-workshop.ts +372 -0
- package/src/lib/mysql/workflows/redeem-full-price-coupon.ts +179 -0
- package/src/lib/mysql/workflows/transfer-purchase-to-user.ts +142 -0
- package/src/types.ts +33 -0
- package/dist/authjs.d.ts +0 -27
- package/dist/authjs.js +0 -1
- package/dist/chunk-25RKHMRM.js +0 -8729
- package/dist/chunk-2AW5KYAK.js +0 -101
- package/dist/chunk-3EF5ZXLG.js +0 -101
- package/dist/chunk-7FBSP3VD.js +0 -78
- package/dist/chunk-AP5HBIV4.js +0 -112
- package/dist/chunk-F56AI52P.js +0 -49
- package/dist/chunk-HAQZSRJL.js +0 -4696
- package/dist/chunk-I2U5PTWN.js +0 -79
- package/dist/chunk-IBQGXFEX.js +0 -8729
- package/dist/chunk-PJORQUQP.js +0 -58
- package/dist/chunk-W6RPAAKG.js +0 -2144
- package/dist/chunk-WKJTU24D.js +0 -88
- package/dist/chunk-WWBSNLRC.js +0 -63
- package/src/authjs.ts +0 -34
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
|
|
31
|
+
// src/lib/mysql/workflows/create-workshop.ts
|
|
32
|
+
var create_workshop_exports = {};
|
|
33
|
+
__export(create_workshop_exports, {
|
|
34
|
+
createWorkshopWorkflow: () => createWorkshopWorkflow
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(create_workshop_exports);
|
|
37
|
+
var import_slugify = __toESM(require("@sindresorhus/slugify"), 1);
|
|
38
|
+
var import_drizzle_orm = require("drizzle-orm");
|
|
39
|
+
var import_content_resource_schema = require("@coursebuilder/core/schemas/content-resource-schema");
|
|
40
|
+
var import_logger = require("@coursebuilder/utils/logger");
|
|
41
|
+
|
|
42
|
+
// src/lib/mysql/workflows/content-resource-workflow-utils.ts
|
|
43
|
+
var import_nanoid = require("nanoid");
|
|
44
|
+
var guid = (0, import_nanoid.customAlphabet)("1234567890abcdefghijklmnopqrstuvwxyz", 5);
|
|
45
|
+
var normalizeExpirationDate = /* @__PURE__ */ __name((date) => {
|
|
46
|
+
if (!date)
|
|
47
|
+
return void 0;
|
|
48
|
+
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 23, 59, 59, 0));
|
|
49
|
+
}, "normalizeExpirationDate");
|
|
50
|
+
|
|
51
|
+
// src/lib/mysql/workflows/create-workshop.ts
|
|
52
|
+
var logger = import_logger.logger;
|
|
53
|
+
function createWorkshopWorkflow({ client, tables }, operations) {
|
|
54
|
+
const { contentResource, contentResourceResource, contentResourceProduct, contentResourceTag } = tables;
|
|
55
|
+
return {
|
|
56
|
+
async createWorkshop(input, userId) {
|
|
57
|
+
const hash = guid();
|
|
58
|
+
const workshopId = `workshop~${hash}`;
|
|
59
|
+
const result = await client.transaction(async (tx) => {
|
|
60
|
+
await tx.insert(contentResource).values({
|
|
61
|
+
id: workshopId,
|
|
62
|
+
type: "workshop",
|
|
63
|
+
createdById: userId,
|
|
64
|
+
fields: {
|
|
65
|
+
title: input.workshop.title,
|
|
66
|
+
description: input.workshop.description,
|
|
67
|
+
state: "draft",
|
|
68
|
+
visibility: "unlisted",
|
|
69
|
+
slug: (0, import_slugify.default)(`${input.workshop.title}~${hash}`)
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
const workshop = await tx.query.contentResource.findFirst({
|
|
73
|
+
where: (0, import_drizzle_orm.eq)(contentResource.id, workshopId),
|
|
74
|
+
with: {
|
|
75
|
+
resources: {
|
|
76
|
+
with: {
|
|
77
|
+
resource: {
|
|
78
|
+
with: {
|
|
79
|
+
resources: {
|
|
80
|
+
with: {
|
|
81
|
+
resource: true
|
|
82
|
+
},
|
|
83
|
+
orderBy: (0, import_drizzle_orm.asc)(contentResourceResource.position)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
orderBy: (0, import_drizzle_orm.asc)(contentResourceResource.position)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
if (!workshop) {
|
|
93
|
+
throw new Error("Failed to create workshop");
|
|
94
|
+
}
|
|
95
|
+
const parsedWorkshop = import_content_resource_schema.ContentResourceSchema.safeParse(workshop);
|
|
96
|
+
if (!parsedWorkshop.success) {
|
|
97
|
+
throw new Error("Invalid workshop data");
|
|
98
|
+
}
|
|
99
|
+
if (input.workshop.tagIds) {
|
|
100
|
+
await tx.insert(contentResourceTag).values(input.workshop.tagIds.map((tag) => ({
|
|
101
|
+
contentResourceId: workshopId,
|
|
102
|
+
tagId: tag.id,
|
|
103
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
104
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
105
|
+
position: 0
|
|
106
|
+
})));
|
|
107
|
+
}
|
|
108
|
+
const createdSections = [];
|
|
109
|
+
const createdLessons = [];
|
|
110
|
+
let position = 0;
|
|
111
|
+
for (const item of input.structure) {
|
|
112
|
+
if (item.type === "section") {
|
|
113
|
+
const sectionHash = guid();
|
|
114
|
+
const sectionId = `section~${sectionHash}`;
|
|
115
|
+
await tx.insert(contentResource).values({
|
|
116
|
+
id: sectionId,
|
|
117
|
+
type: "section",
|
|
118
|
+
createdById: userId,
|
|
119
|
+
fields: {
|
|
120
|
+
title: item.title,
|
|
121
|
+
state: "draft",
|
|
122
|
+
visibility: "unlisted",
|
|
123
|
+
slug: (0, import_slugify.default)(`${item.title}~${sectionHash}`)
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
await tx.insert(contentResourceResource).values({
|
|
127
|
+
resourceOfId: workshopId,
|
|
128
|
+
resourceId: sectionId,
|
|
129
|
+
position
|
|
130
|
+
});
|
|
131
|
+
const section = await tx.query.contentResource.findFirst({
|
|
132
|
+
where: (0, import_drizzle_orm.eq)(contentResource.id, sectionId)
|
|
133
|
+
});
|
|
134
|
+
if (section) {
|
|
135
|
+
createdSections.push(section);
|
|
136
|
+
}
|
|
137
|
+
let lessonPosition = 0;
|
|
138
|
+
for (const lessonData of item.lessons) {
|
|
139
|
+
const lessonHash = guid();
|
|
140
|
+
const lessonId = `lesson_${lessonHash}`;
|
|
141
|
+
await tx.insert(contentResource).values({
|
|
142
|
+
id: lessonId,
|
|
143
|
+
type: "lesson",
|
|
144
|
+
createdById: userId,
|
|
145
|
+
fields: {
|
|
146
|
+
title: lessonData.title,
|
|
147
|
+
state: "draft",
|
|
148
|
+
visibility: "unlisted",
|
|
149
|
+
slug: (0, import_slugify.default)(`${lessonData.title}~${lessonHash}`),
|
|
150
|
+
lessonType: "lesson"
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
if (lessonData.videoResourceId) {
|
|
154
|
+
await tx.insert(contentResourceResource).values({
|
|
155
|
+
resourceOfId: lessonId,
|
|
156
|
+
resourceId: lessonData.videoResourceId,
|
|
157
|
+
position: 0
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
await tx.insert(contentResourceResource).values({
|
|
161
|
+
resourceOfId: sectionId,
|
|
162
|
+
resourceId: lessonId,
|
|
163
|
+
position: lessonPosition
|
|
164
|
+
});
|
|
165
|
+
const lesson = await tx.query.contentResource.findFirst({
|
|
166
|
+
where: (0, import_drizzle_orm.eq)(contentResource.id, lessonId)
|
|
167
|
+
});
|
|
168
|
+
if (lesson) {
|
|
169
|
+
createdLessons.push(lesson);
|
|
170
|
+
}
|
|
171
|
+
lessonPosition++;
|
|
172
|
+
}
|
|
173
|
+
position++;
|
|
174
|
+
} else {
|
|
175
|
+
const lessonHash = guid();
|
|
176
|
+
const lessonId = `lesson_${lessonHash}`;
|
|
177
|
+
await tx.insert(contentResource).values({
|
|
178
|
+
id: lessonId,
|
|
179
|
+
type: "lesson",
|
|
180
|
+
createdById: userId,
|
|
181
|
+
fields: {
|
|
182
|
+
title: item.title,
|
|
183
|
+
state: "draft",
|
|
184
|
+
visibility: "unlisted",
|
|
185
|
+
slug: (0, import_slugify.default)(`${item.title}~${lessonHash}`),
|
|
186
|
+
lessonType: "lesson"
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
if (item.videoResourceId) {
|
|
190
|
+
await tx.insert(contentResourceResource).values({
|
|
191
|
+
resourceOfId: lessonId,
|
|
192
|
+
resourceId: item.videoResourceId,
|
|
193
|
+
position: 0
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
await tx.insert(contentResourceResource).values({
|
|
197
|
+
resourceOfId: workshopId,
|
|
198
|
+
resourceId: lessonId,
|
|
199
|
+
position
|
|
200
|
+
});
|
|
201
|
+
const lesson = await tx.query.contentResource.findFirst({
|
|
202
|
+
where: (0, import_drizzle_orm.eq)(contentResource.id, lessonId)
|
|
203
|
+
});
|
|
204
|
+
if (lesson) {
|
|
205
|
+
createdLessons.push(lesson);
|
|
206
|
+
}
|
|
207
|
+
position++;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
workshop: parsedWorkshop.data,
|
|
212
|
+
sections: createdSections,
|
|
213
|
+
lessons: createdLessons
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
let product = null;
|
|
217
|
+
if (input.createProduct && input.pricing.price && input.pricing.price > 0) {
|
|
218
|
+
try {
|
|
219
|
+
product = await operations.createProduct({
|
|
220
|
+
name: input.workshop.title,
|
|
221
|
+
price: input.pricing.price,
|
|
222
|
+
quantityAvailable: input.pricing.quantity ?? -1,
|
|
223
|
+
type: "self-paced",
|
|
224
|
+
state: "published",
|
|
225
|
+
visibility: "public"
|
|
226
|
+
});
|
|
227
|
+
if (product) {
|
|
228
|
+
await client.insert(contentResourceProduct).values({
|
|
229
|
+
resourceId: workshopId,
|
|
230
|
+
productId: product.id,
|
|
231
|
+
position: 0,
|
|
232
|
+
metadata: {
|
|
233
|
+
addedBy: userId
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
if (input.coupon?.enabled && input.coupon.percentageDiscount && input.coupon.expires) {
|
|
237
|
+
try {
|
|
238
|
+
const finalExpires = normalizeExpirationDate(input.coupon.expires);
|
|
239
|
+
await operations.createCoupon({
|
|
240
|
+
percentageDiscount: input.coupon.percentageDiscount,
|
|
241
|
+
expires: finalExpires || null,
|
|
242
|
+
restrictedToProductId: product.id,
|
|
243
|
+
default: true,
|
|
244
|
+
maxUses: -1,
|
|
245
|
+
quantity: "-1",
|
|
246
|
+
status: 1,
|
|
247
|
+
fields: {}
|
|
248
|
+
});
|
|
249
|
+
logger.debug("workshop.create.coupon.success", {
|
|
250
|
+
workshopId,
|
|
251
|
+
productId: product.id,
|
|
252
|
+
userId,
|
|
253
|
+
percentageDiscount: input.coupon.percentageDiscount
|
|
254
|
+
});
|
|
255
|
+
} catch (couponError) {
|
|
256
|
+
logger.error(new Error(`Failed to create coupon for workshop: ${couponError}`));
|
|
257
|
+
logger.debug("workshop.create.coupon.failed", {
|
|
258
|
+
workshopId,
|
|
259
|
+
productId: product.id,
|
|
260
|
+
userId
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
} catch (productError) {
|
|
266
|
+
logger.error(new Error(`Failed to create product for workshop: ${productError}`));
|
|
267
|
+
logger.debug("workshop.create.product.failed", {
|
|
268
|
+
workshopId,
|
|
269
|
+
userId,
|
|
270
|
+
price: input.pricing.price
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
...result,
|
|
276
|
+
product
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
__name(createWorkshopWorkflow, "createWorkshopWorkflow");
|
|
282
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
283
|
+
0 && (module.exports = {
|
|
284
|
+
createWorkshopWorkflow
|
|
285
|
+
});
|
|
286
|
+
//# sourceMappingURL=create-workshop.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/mysql/workflows/create-workshop.ts","../../../../src/lib/mysql/workflows/content-resource-workflow-utils.ts"],"sourcesContent":["import slugify from '@sindresorhus/slugify'\nimport { asc, eq } from 'drizzle-orm'\n\nimport type {\n\tCatalogPort,\n\tContentResourcePort,\n\tCouponPort,\n} from '@coursebuilder/core/ports'\nimport {\n\tContentResourceSchema,\n\ttype ContentResource,\n} from '@coursebuilder/core/schemas/content-resource-schema'\nimport { logger as baseLogger } from '@coursebuilder/utils/logger'\n\nimport type { MySqlContext } from '../context.js'\nimport {\n\tguid,\n\tnormalizeExpirationDate,\n} from './content-resource-workflow-utils.js'\n\nconst logger = baseLogger as unknown as {\n\tdebug: (message: string, attrs?: Record<string, unknown>) => void\n\terror: (error: Error, attrs?: Record<string, unknown>) => void\n}\n\ntype CreateWorkshopOperations = Pick<CatalogPort, 'createProduct'> &\n\tPick<CouponPort, 'createCoupon'>\n\n/**\n * Creates the private workshop creation workflow.\n *\n * @param context - The shared MySQL client and table set.\n * @param operations - Narrow catalog, coupon, and content resource operations.\n * @returns The content resource creation operation.\n *\n * @example\n * ```ts\n * const workflow = createWorkshopWorkflow(context, operations)\n * ```\n */\nexport function createWorkshopWorkflow(\n\t{ client, tables }: MySqlContext,\n\toperations: CreateWorkshopOperations,\n): Pick<ContentResourcePort, 'createWorkshop'> {\n\tconst {\n\t\tcontentResource,\n\t\tcontentResourceResource,\n\t\tcontentResourceProduct,\n\t\tcontentResourceTag,\n\t} = tables\n\n\treturn {\n\t\tasync createWorkshop(\n\t\t\tinput: {\n\t\t\t\tworkshop: {\n\t\t\t\t\ttitle: string\n\t\t\t\t\tdescription?: string\n\t\t\t\t\ttagIds?:\n\t\t\t\t\t\t| { id: string; fields: { label: string; name: string } }[]\n\t\t\t\t\t\t| null\n\t\t\t\t}\n\t\t\t\tcreateProduct?: boolean\n\t\t\t\tpricing: {\n\t\t\t\t\tprice?: number | null\n\t\t\t\t\tquantity?: number | null\n\t\t\t\t}\n\t\t\t\tcoupon?: {\n\t\t\t\t\tenabled: boolean\n\t\t\t\t\tpercentageDiscount?: string\n\t\t\t\t\texpires?: Date\n\t\t\t\t}\n\t\t\t\tstructure: Array<\n\t\t\t\t\t| {\n\t\t\t\t\t\t\ttype: 'section'\n\t\t\t\t\t\t\ttitle: string\n\t\t\t\t\t\t\tlessons: { title: string; videoResourceId?: string }[]\n\t\t\t\t\t }\n\t\t\t\t\t| { type: 'lesson'; title: string; videoResourceId?: string }\n\t\t\t\t>\n\t\t\t},\n\t\t\tuserId: string,\n\t\t) {\n\t\t\tconst hash = guid()\n\t\t\tconst workshopId = `workshop~${hash}`\n\n\t\t\t// Transaction only handles database operations\n\t\t\tconst result = await client.transaction(async (tx) => {\n\t\t\t\t// Create workshop content resource\n\t\t\t\tawait tx.insert(contentResource).values({\n\t\t\t\t\tid: workshopId,\n\t\t\t\t\ttype: 'workshop',\n\t\t\t\t\tcreatedById: userId,\n\t\t\t\t\tfields: {\n\t\t\t\t\t\ttitle: input.workshop.title,\n\t\t\t\t\t\tdescription: input.workshop.description,\n\t\t\t\t\t\tstate: 'draft',\n\t\t\t\t\t\tvisibility: 'unlisted',\n\t\t\t\t\t\tslug: slugify(`${input.workshop.title}~${hash}`),\n\t\t\t\t\t},\n\t\t\t\t})\n\n\t\t\t\t// Fetch created workshop\n\t\t\t\tconst workshop = await tx.query.contentResource.findFirst({\n\t\t\t\t\twhere: eq(contentResource.id, workshopId),\n\t\t\t\t\twith: {\n\t\t\t\t\t\tresources: {\n\t\t\t\t\t\t\twith: {\n\t\t\t\t\t\t\t\tresource: {\n\t\t\t\t\t\t\t\t\twith: {\n\t\t\t\t\t\t\t\t\t\tresources: {\n\t\t\t\t\t\t\t\t\t\t\twith: {\n\t\t\t\t\t\t\t\t\t\t\t\tresource: true,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\torderBy: asc(contentResourceResource.position),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\torderBy: asc(contentResourceResource.position),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t})\n\n\t\t\t\tif (!workshop) {\n\t\t\t\t\tthrow new Error('Failed to create workshop')\n\t\t\t\t}\n\n\t\t\t\tconst parsedWorkshop = ContentResourceSchema.safeParse(workshop)\n\t\t\t\tif (!parsedWorkshop.success) {\n\t\t\t\t\tthrow new Error('Invalid workshop data')\n\t\t\t\t}\n\n\t\t\t\t// Associate tags with workshop\n\t\t\t\tif (input.workshop.tagIds) {\n\t\t\t\t\tawait tx.insert(contentResourceTag).values(\n\t\t\t\t\t\tinput.workshop.tagIds.map((tag) => ({\n\t\t\t\t\t\t\tcontentResourceId: workshopId,\n\t\t\t\t\t\t\ttagId: tag.id,\n\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\tposition: 0,\n\t\t\t\t\t\t})),\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\t// Create sections and lessons\n\t\t\t\tconst createdSections: ContentResource[] = []\n\t\t\t\tconst createdLessons: ContentResource[] = []\n\t\t\t\tlet position = 0\n\n\t\t\t\tfor (const item of input.structure) {\n\t\t\t\t\tif (item.type === 'section') {\n\t\t\t\t\t\t// Create section\n\t\t\t\t\t\tconst sectionHash = guid()\n\t\t\t\t\t\tconst sectionId = `section~${sectionHash}`\n\n\t\t\t\t\t\tawait tx.insert(contentResource).values({\n\t\t\t\t\t\t\tid: sectionId,\n\t\t\t\t\t\t\ttype: 'section',\n\t\t\t\t\t\t\tcreatedById: userId,\n\t\t\t\t\t\t\tfields: {\n\t\t\t\t\t\t\t\ttitle: item.title,\n\t\t\t\t\t\t\t\tstate: 'draft',\n\t\t\t\t\t\t\t\tvisibility: 'unlisted',\n\t\t\t\t\t\t\t\tslug: slugify(`${item.title}~${sectionHash}`),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t// Link section to workshop\n\t\t\t\t\t\tawait tx.insert(contentResourceResource).values({\n\t\t\t\t\t\t\tresourceOfId: workshopId,\n\t\t\t\t\t\t\tresourceId: sectionId,\n\t\t\t\t\t\t\tposition,\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tconst section = await tx.query.contentResource.findFirst({\n\t\t\t\t\t\t\twhere: eq(contentResource.id, sectionId),\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tif (section) {\n\t\t\t\t\t\t\tcreatedSections.push(section as ContentResource)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Create lessons in section\n\t\t\t\t\t\tlet lessonPosition = 0\n\t\t\t\t\t\tfor (const lessonData of item.lessons) {\n\t\t\t\t\t\t\tconst lessonHash = guid()\n\t\t\t\t\t\t\tconst lessonId = `lesson_${lessonHash}`\n\n\t\t\t\t\t\t\tawait tx.insert(contentResource).values({\n\t\t\t\t\t\t\t\tid: lessonId,\n\t\t\t\t\t\t\t\ttype: 'lesson',\n\t\t\t\t\t\t\t\tcreatedById: userId,\n\t\t\t\t\t\t\t\tfields: {\n\t\t\t\t\t\t\t\t\ttitle: lessonData.title,\n\t\t\t\t\t\t\t\t\tstate: 'draft',\n\t\t\t\t\t\t\t\t\tvisibility: 'unlisted',\n\t\t\t\t\t\t\t\t\tslug: slugify(`${lessonData.title}~${lessonHash}`),\n\t\t\t\t\t\t\t\t\tlessonType: 'lesson',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t})\n\n\t\t\t\t\t\t\t// Link video if provided\n\t\t\t\t\t\t\tif (lessonData.videoResourceId) {\n\t\t\t\t\t\t\t\tawait tx.insert(contentResourceResource).values({\n\t\t\t\t\t\t\t\t\tresourceOfId: lessonId,\n\t\t\t\t\t\t\t\t\tresourceId: lessonData.videoResourceId,\n\t\t\t\t\t\t\t\t\tposition: 0,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Link lesson to section\n\t\t\t\t\t\t\tawait tx.insert(contentResourceResource).values({\n\t\t\t\t\t\t\t\tresourceOfId: sectionId,\n\t\t\t\t\t\t\t\tresourceId: lessonId,\n\t\t\t\t\t\t\t\tposition: lessonPosition,\n\t\t\t\t\t\t\t})\n\n\t\t\t\t\t\t\tconst lesson = await tx.query.contentResource.findFirst({\n\t\t\t\t\t\t\t\twhere: eq(contentResource.id, lessonId),\n\t\t\t\t\t\t\t})\n\n\t\t\t\t\t\t\tif (lesson) {\n\t\t\t\t\t\t\t\tcreatedLessons.push(lesson as ContentResource)\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tlessonPosition++\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tposition++\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Create top-level lesson\n\t\t\t\t\t\tconst lessonHash = guid()\n\t\t\t\t\t\tconst lessonId = `lesson_${lessonHash}`\n\n\t\t\t\t\t\tawait tx.insert(contentResource).values({\n\t\t\t\t\t\t\tid: lessonId,\n\t\t\t\t\t\t\ttype: 'lesson',\n\t\t\t\t\t\t\tcreatedById: userId,\n\t\t\t\t\t\t\tfields: {\n\t\t\t\t\t\t\t\ttitle: item.title,\n\t\t\t\t\t\t\t\tstate: 'draft',\n\t\t\t\t\t\t\t\tvisibility: 'unlisted',\n\t\t\t\t\t\t\t\tslug: slugify(`${item.title}~${lessonHash}`),\n\t\t\t\t\t\t\t\tlessonType: 'lesson',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t// Link video if provided\n\t\t\t\t\t\tif (item.videoResourceId) {\n\t\t\t\t\t\t\tawait tx.insert(contentResourceResource).values({\n\t\t\t\t\t\t\t\tresourceOfId: lessonId,\n\t\t\t\t\t\t\t\tresourceId: item.videoResourceId,\n\t\t\t\t\t\t\t\tposition: 0,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Link lesson to workshop\n\t\t\t\t\t\tawait tx.insert(contentResourceResource).values({\n\t\t\t\t\t\t\tresourceOfId: workshopId,\n\t\t\t\t\t\t\tresourceId: lessonId,\n\t\t\t\t\t\t\tposition,\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tconst lesson = await tx.query.contentResource.findFirst({\n\t\t\t\t\t\t\twhere: eq(contentResource.id, lessonId),\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tif (lesson) {\n\t\t\t\t\t\t\tcreatedLessons.push(lesson as ContentResource)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tposition++\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tworkshop: parsedWorkshop.data,\n\t\t\t\t\tsections: createdSections,\n\t\t\t\t\tlessons: createdLessons,\n\t\t\t\t}\n\t\t\t})\n\n\t\t\t// Handle product and coupon creation outside transaction\n\t\t\tlet product: any = null\n\t\t\tif (\n\t\t\t\tinput.createProduct &&\n\t\t\t\tinput.pricing.price &&\n\t\t\t\tinput.pricing.price > 0\n\t\t\t) {\n\t\t\t\ttry {\n\t\t\t\t\tproduct = await operations.createProduct({\n\t\t\t\t\t\tname: input.workshop.title,\n\t\t\t\t\t\tprice: input.pricing.price,\n\t\t\t\t\t\tquantityAvailable: input.pricing.quantity ?? -1,\n\t\t\t\t\t\ttype: 'self-paced',\n\t\t\t\t\t\tstate: 'published',\n\t\t\t\t\t\tvisibility: 'public',\n\t\t\t\t\t})\n\n\t\t\t\t\tif (product) {\n\t\t\t\t\t\t// Link product to workshop resource\n\t\t\t\t\t\tawait client.insert(contentResourceProduct).values({\n\t\t\t\t\t\t\tresourceId: workshopId,\n\t\t\t\t\t\t\tproductId: product.id,\n\t\t\t\t\t\t\tposition: 0,\n\t\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\t\taddedBy: userId,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t// Create coupon if enabled\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tinput.coupon?.enabled &&\n\t\t\t\t\t\t\tinput.coupon.percentageDiscount &&\n\t\t\t\t\t\t\tinput.coupon.expires\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst finalExpires = normalizeExpirationDate(\n\t\t\t\t\t\t\t\t\tinput.coupon.expires,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tawait operations.createCoupon({\n\t\t\t\t\t\t\t\t\tpercentageDiscount: input.coupon.percentageDiscount,\n\t\t\t\t\t\t\t\t\texpires: finalExpires || null,\n\t\t\t\t\t\t\t\t\trestrictedToProductId: product.id,\n\t\t\t\t\t\t\t\t\tdefault: true,\n\t\t\t\t\t\t\t\t\tmaxUses: -1,\n\t\t\t\t\t\t\t\t\tquantity: '-1',\n\t\t\t\t\t\t\t\t\tstatus: 1,\n\t\t\t\t\t\t\t\t\tfields: {},\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\tlogger.debug('workshop.create.coupon.success', {\n\t\t\t\t\t\t\t\t\tworkshopId,\n\t\t\t\t\t\t\t\t\tproductId: product.id,\n\t\t\t\t\t\t\t\t\tuserId,\n\t\t\t\t\t\t\t\t\tpercentageDiscount: input.coupon.percentageDiscount,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t} catch (couponError) {\n\t\t\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t\t\t`Failed to create coupon for workshop: ${couponError}`,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tlogger.debug('workshop.create.coupon.failed', {\n\t\t\t\t\t\t\t\t\tworkshopId,\n\t\t\t\t\t\t\t\t\tproductId: product.id,\n\t\t\t\t\t\t\t\t\tuserId,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t// Don't throw - workshop creation should succeed even if coupon fails\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (productError) {\n\t\t\t\t\tlogger.error(\n\t\t\t\t\t\tnew Error(`Failed to create product for workshop: ${productError}`),\n\t\t\t\t\t)\n\t\t\t\t\tlogger.debug('workshop.create.product.failed', {\n\t\t\t\t\t\tworkshopId,\n\t\t\t\t\t\tuserId,\n\t\t\t\t\t\tprice: input.pricing.price,\n\t\t\t\t\t})\n\t\t\t\t\t// Don't throw - workshop creation should succeed even if product fails\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\tproduct,\n\t\t\t}\n\t\t},\n\t}\n}\n","import { customAlphabet } from 'nanoid'\n\nexport const guid = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz', 5)\n\nexport const normalizeExpirationDate = (date: Date | undefined) => {\n\tif (!date) return undefined\n\n\t// Create a new Date object for 23:59:59 UTC on the date part of the input date\n\t// The input date should be a JS Date representing 00:00:00 LA time for the chosen day.\n\t// Its UTC date parts (getUTCFullYear, etc.) will give us the correct calendar day.\n\treturn new Date(\n\t\tDate.UTC(\n\t\t\tdate.getUTCFullYear(),\n\t\t\tdate.getUTCMonth(), // 0-indexed\n\t\t\tdate.getUTCDate(),\n\t\t\t23, // hours\n\t\t\t59, // minutes\n\t\t\t59, // seconds\n\t\t\t0, // milliseconds\n\t\t),\n\t)\n}\n"],"mappings":"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","names":["guid","customAlphabet","normalizeExpirationDate","date","undefined","Date","UTC","getUTCFullYear","getUTCMonth","getUTCDate","logger","baseLogger","createWorkshopWorkflow","client","tables","operations","contentResource","contentResourceResource","contentResourceProduct","contentResourceTag","createWorkshop","input","userId","hash","guid","workshopId","result","transaction","tx","insert","values","id","type","createdById","fields","title","workshop","description","state","visibility","slug","slugify","query","findFirst","where","eq","with","resources","resource","orderBy","asc","position","Error","parsedWorkshop","ContentResourceSchema","safeParse","success","tagIds","map","tag","contentResourceId","tagId","createdAt","Date","updatedAt","createdSections","createdLessons","item","structure","sectionHash","sectionId","resourceOfId","resourceId","section","push","lessonPosition","lessonData","lessons","lessonHash","lessonId","lessonType","videoResourceId","lesson","data","sections","product","createProduct","pricing","price","name","quantityAvailable","quantity","productId","metadata","addedBy","coupon","enabled","percentageDiscount","expires","finalExpires","normalizeExpirationDate","createCoupon","restrictedToProductId","default","maxUses","status","debug","couponError","error","productError"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CatalogPort, CouponPort, ContentResourcePort } from '@coursebuilder/core/ports';
|
|
2
|
+
import { MySqlContext } from '../context.cjs';
|
|
3
|
+
import 'drizzle-orm/mysql-core';
|
|
4
|
+
import '../schema.cjs';
|
|
5
|
+
import 'drizzle-orm';
|
|
6
|
+
import '@coursebuilder/core/auth';
|
|
7
|
+
import '../schemas/auth/users.cjs';
|
|
8
|
+
|
|
9
|
+
type CreateWorkshopOperations = Pick<CatalogPort, 'createProduct'> & Pick<CouponPort, 'createCoupon'>;
|
|
10
|
+
/**
|
|
11
|
+
* Creates the private workshop creation workflow.
|
|
12
|
+
*
|
|
13
|
+
* @param context - The shared MySQL client and table set.
|
|
14
|
+
* @param operations - Narrow catalog, coupon, and content resource operations.
|
|
15
|
+
* @returns The content resource creation operation.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const workflow = createWorkshopWorkflow(context, operations)
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
declare function createWorkshopWorkflow({ client, tables }: MySqlContext, operations: CreateWorkshopOperations): Pick<ContentResourcePort, 'createWorkshop'>;
|
|
23
|
+
|
|
24
|
+
export { createWorkshopWorkflow };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CatalogPort, CouponPort, ContentResourcePort } from '@coursebuilder/core/ports';
|
|
2
|
+
import { MySqlContext } from '../context.js';
|
|
3
|
+
import 'drizzle-orm/mysql-core';
|
|
4
|
+
import '../schema.js';
|
|
5
|
+
import 'drizzle-orm';
|
|
6
|
+
import '@coursebuilder/core/auth';
|
|
7
|
+
import '../schemas/auth/users.js';
|
|
8
|
+
|
|
9
|
+
type CreateWorkshopOperations = Pick<CatalogPort, 'createProduct'> & Pick<CouponPort, 'createCoupon'>;
|
|
10
|
+
/**
|
|
11
|
+
* Creates the private workshop creation workflow.
|
|
12
|
+
*
|
|
13
|
+
* @param context - The shared MySQL client and table set.
|
|
14
|
+
* @param operations - Narrow catalog, coupon, and content resource operations.
|
|
15
|
+
* @returns The content resource creation operation.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const workflow = createWorkshopWorkflow(context, operations)
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
declare function createWorkshopWorkflow({ client, tables }: MySqlContext, operations: CreateWorkshopOperations): Pick<ContentResourcePort, 'createWorkshop'>;
|
|
23
|
+
|
|
24
|
+
export { createWorkshopWorkflow };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/lib/mysql/workflows/redeem-full-price-coupon.ts
|
|
22
|
+
var redeem_full_price_coupon_exports = {};
|
|
23
|
+
__export(redeem_full_price_coupon_exports, {
|
|
24
|
+
createRedeemFullPriceCouponWorkflow: () => createRedeemFullPriceCouponWorkflow
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(redeem_full_price_coupon_exports);
|
|
27
|
+
var import_drizzle_orm = require("drizzle-orm");
|
|
28
|
+
var import_uuid = require("uuid");
|
|
29
|
+
var import_logger = require("@coursebuilder/utils/logger");
|
|
30
|
+
var import_validate_coupon = require("@coursebuilder/commerce/validate-coupon");
|
|
31
|
+
var normalizeLearnerEmail = /* @__PURE__ */ __name((email) => email.trim().toLowerCase().replace(/\s+/g, "+"), "normalizeLearnerEmail");
|
|
32
|
+
function createRedeemFullPriceCouponWorkflow({ client, tables }, operations) {
|
|
33
|
+
const { purchases: purchaseTable } = tables;
|
|
34
|
+
return {
|
|
35
|
+
async redeemFullPriceCoupon(options) {
|
|
36
|
+
const { email: baseEmail, couponId, productIds, currentUserId, redeemingProductId } = options;
|
|
37
|
+
const email = normalizeLearnerEmail(String(baseEmail));
|
|
38
|
+
const coupon = await operations.getCouponWithBulkPurchases(couponId);
|
|
39
|
+
const productId = coupon && coupon.restrictedToProductId || redeemingProductId;
|
|
40
|
+
if (!productId)
|
|
41
|
+
throw new Error(`unable-to-find-any-product-id`);
|
|
42
|
+
const couponValidation = (0, import_validate_coupon.validateCoupon)(coupon, productIds);
|
|
43
|
+
if (coupon && couponValidation.isRedeemable) {
|
|
44
|
+
const bulkCouponRedemption = Boolean(coupon.maxUses > 1);
|
|
45
|
+
const { user } = await operations.findOrCreateUser(email);
|
|
46
|
+
if (!user)
|
|
47
|
+
throw new Error(`unable-to-create-user-${email}`);
|
|
48
|
+
const currentUser = currentUserId ? await operations.getUserById(currentUserId) : null;
|
|
49
|
+
const redeemingForCurrentUser = currentUser?.id === user.id;
|
|
50
|
+
if (bulkCouponRedemption) {
|
|
51
|
+
const existingValidRedemption = await client.query.purchases.findFirst({
|
|
52
|
+
where: (0, import_drizzle_orm.and)((0, import_drizzle_orm.eq)(purchaseTable.redeemedBulkCouponId, coupon.id), (0, import_drizzle_orm.eq)(purchaseTable.userId, user.id), (0, import_drizzle_orm.eq)(purchaseTable.status, "Valid"))
|
|
53
|
+
});
|
|
54
|
+
if (existingValidRedemption) {
|
|
55
|
+
import_logger.logger.info("adapter.coupon.redeem.duplicate_team_seat", {
|
|
56
|
+
couponId: coupon.id,
|
|
57
|
+
currentUserId,
|
|
58
|
+
email,
|
|
59
|
+
productId,
|
|
60
|
+
purchaseId: existingValidRedemption.id,
|
|
61
|
+
userId: user.id
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
error: {
|
|
65
|
+
message: "team-seat-redemption-already-claimed"
|
|
66
|
+
},
|
|
67
|
+
redeemingForCurrentUser,
|
|
68
|
+
purchase: null
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const existingPurchases = await operations.getExistingNonBulkValidPurchasesOfProduct({
|
|
73
|
+
userId: user.id,
|
|
74
|
+
productId
|
|
75
|
+
});
|
|
76
|
+
if (existingPurchases.length > 0) {
|
|
77
|
+
const errorMessage = `already-purchased-${email}`;
|
|
78
|
+
import_logger.logger.info("adapter.coupon.redeem.already_purchased", {
|
|
79
|
+
couponId: coupon.id,
|
|
80
|
+
currentUserId,
|
|
81
|
+
email,
|
|
82
|
+
productId,
|
|
83
|
+
userId: user.id
|
|
84
|
+
});
|
|
85
|
+
return {
|
|
86
|
+
error: {
|
|
87
|
+
message: errorMessage
|
|
88
|
+
},
|
|
89
|
+
redeemingForCurrentUser,
|
|
90
|
+
purchase: null
|
|
91
|
+
};
|
|
92
|
+
throw new Error(errorMessage);
|
|
93
|
+
}
|
|
94
|
+
const purchaseId = `purchase-${(0, import_uuid.v4)()}`;
|
|
95
|
+
const userMemberships = await operations.getMembershipsForUser(user.id);
|
|
96
|
+
const organizationId = coupon.organizationId || userMemberships.find((m) => m.organization.name?.includes(user.email))?.organizationId;
|
|
97
|
+
await operations.createPurchase({
|
|
98
|
+
id: purchaseId,
|
|
99
|
+
userId: user.id,
|
|
100
|
+
couponId: bulkCouponRedemption ? null : coupon.id,
|
|
101
|
+
redeemedBulkCouponId: bulkCouponRedemption ? coupon.id : null,
|
|
102
|
+
productId,
|
|
103
|
+
totalAmount: "0",
|
|
104
|
+
organizationId,
|
|
105
|
+
metadata: {
|
|
106
|
+
couponUsedId: bulkCouponRedemption ? null : coupon.id
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
const newPurchase = await operations.getPurchase(purchaseId);
|
|
110
|
+
await operations.incrementCouponUsedCount(coupon.id);
|
|
111
|
+
await operations.createPurchaseTransfer({
|
|
112
|
+
sourceUserId: user.id,
|
|
113
|
+
purchaseId,
|
|
114
|
+
expiresAt: new Date(Date.now() + 1e3 * 60 * 60 * 24 * 7)
|
|
115
|
+
});
|
|
116
|
+
return {
|
|
117
|
+
purchase: newPurchase,
|
|
118
|
+
redeemingForCurrentUser
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
__name(createRedeemFullPriceCouponWorkflow, "createRedeemFullPriceCouponWorkflow");
|
|
126
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
127
|
+
0 && (module.exports = {
|
|
128
|
+
createRedeemFullPriceCouponWorkflow
|
|
129
|
+
});
|
|
130
|
+
//# sourceMappingURL=redeem-full-price-coupon.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/mysql/workflows/redeem-full-price-coupon.ts"],"sourcesContent":["import { and, eq } from 'drizzle-orm'\nimport { v4 } from 'uuid'\n\nimport type {\n\tCouponPort,\n\tIdentityPort,\n\tOrganizationPort,\n\tPurchasePort,\n} from '@coursebuilder/core/ports'\nimport { logger } from '@coursebuilder/utils/logger'\nimport { validateCoupon } from '@coursebuilder/commerce/validate-coupon'\n\nimport type { MySqlContext } from '../context.js'\n\ntype RedeemFullPriceCouponOperations = Pick<\n\tCouponPort,\n\t'getCouponWithBulkPurchases' | 'incrementCouponUsedCount'\n> &\n\tPick<IdentityPort, 'findOrCreateUser' | 'getUserById'> &\n\tPick<OrganizationPort, 'getMembershipsForUser'> &\n\tPick<\n\t\tPurchasePort,\n\t\t| 'createPurchase'\n\t\t| 'createPurchaseTransfer'\n\t\t| 'getExistingNonBulkValidPurchasesOfProduct'\n\t\t| 'getPurchase'\n\t>\n\nconst normalizeLearnerEmail = (email: string) =>\n\temail.trim().toLowerCase().replace(/\\s+/g, '+')\n\n/**\n * Creates the private full-price coupon redemption workflow.\n *\n * @param context - The shared MySQL client and table set.\n * @param operations - Narrow identity, organization, purchase, and coupon operations.\n * @returns The purchase-owned coupon redemption operation.\n *\n * @example\n * ```ts\n * const workflow = createRedeemFullPriceCouponWorkflow(context, operations)\n * ```\n */\nexport function createRedeemFullPriceCouponWorkflow(\n\t{ client, tables }: MySqlContext,\n\toperations: RedeemFullPriceCouponOperations,\n): Pick<PurchasePort, 'redeemFullPriceCoupon'> {\n\tconst { purchases: purchaseTable } = tables\n\n\treturn {\n\t\tasync redeemFullPriceCoupon(options) {\n\t\t\tconst {\n\t\t\t\temail: baseEmail,\n\t\t\t\tcouponId,\n\t\t\t\tproductIds,\n\t\t\t\tcurrentUserId,\n\t\t\t\tredeemingProductId,\n\t\t\t} = options\n\t\t\tconst email = normalizeLearnerEmail(String(baseEmail))\n\n\t\t\tconst coupon = await operations.getCouponWithBulkPurchases(couponId)\n\n\t\t\tconst productId =\n\t\t\t\t(coupon && (coupon.restrictedToProductId as string)) ||\n\t\t\t\tredeemingProductId\n\n\t\t\tif (!productId) throw new Error(`unable-to-find-any-product-id`)\n\n\t\t\tconst couponValidation = validateCoupon(coupon, productIds)\n\n\t\t\tif (coupon && couponValidation.isRedeemable) {\n\t\t\t\t// if the Coupon is the Bulk Coupon of a Bulk Purchase,\n\t\t\t\t// then a bulk coupon is being redeemed\n\t\t\t\tconst bulkCouponRedemption = Boolean(coupon.maxUses > 1)\n\n\t\t\t\tconst { user } = await operations.findOrCreateUser(email)\n\n\t\t\t\tif (!user) throw new Error(`unable-to-create-user-${email}`)\n\n\t\t\t\tconst currentUser = currentUserId\n\t\t\t\t\t? await operations.getUserById(currentUserId)\n\t\t\t\t\t: null\n\n\t\t\t\tconst redeemingForCurrentUser = currentUser?.id === user.id\n\n\t\t\t\tif (bulkCouponRedemption) {\n\t\t\t\t\tconst existingValidRedemption =\n\t\t\t\t\t\tawait client.query.purchases.findFirst({\n\t\t\t\t\t\t\twhere: and(\n\t\t\t\t\t\t\t\teq(purchaseTable.redeemedBulkCouponId, coupon.id),\n\t\t\t\t\t\t\t\teq(purchaseTable.userId, user.id),\n\t\t\t\t\t\t\t\teq(purchaseTable.status, 'Valid'),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t})\n\n\t\t\t\t\tif (existingValidRedemption) {\n\t\t\t\t\t\tlogger.info('adapter.coupon.redeem.duplicate_team_seat', {\n\t\t\t\t\t\t\tcouponId: coupon.id,\n\t\t\t\t\t\t\tcurrentUserId,\n\t\t\t\t\t\t\temail,\n\t\t\t\t\t\t\tproductId,\n\t\t\t\t\t\t\tpurchaseId: existingValidRedemption.id,\n\t\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t\t})\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\t\tmessage: 'team-seat-redemption-already-claimed',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tredeemingForCurrentUser,\n\t\t\t\t\t\t\tpurchase: null,\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// To prevent double-purchasing, check if this user already has a\n\t\t\t\t// Purchase record for this product that is valid and wasn't a bulk\n\t\t\t\t// coupon purchase.\n\t\t\t\tconst existingPurchases =\n\t\t\t\t\tawait operations.getExistingNonBulkValidPurchasesOfProduct({\n\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t\tproductId,\n\t\t\t\t\t})\n\n\t\t\t\tif (existingPurchases.length > 0) {\n\t\t\t\t\tconst errorMessage = `already-purchased-${email}`\n\t\t\t\t\tlogger.info('adapter.coupon.redeem.already_purchased', {\n\t\t\t\t\t\tcouponId: coupon.id,\n\t\t\t\t\t\tcurrentUserId,\n\t\t\t\t\t\temail,\n\t\t\t\t\t\tproductId,\n\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t})\n\t\t\t\t\treturn {\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: errorMessage,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tredeemingForCurrentUser,\n\t\t\t\t\t\tpurchase: null,\n\t\t\t\t\t}\n\t\t\t\t\tthrow new Error(errorMessage)\n\t\t\t\t}\n\n\t\t\t\tconst purchaseId = `purchase-${v4()}`\n\t\t\t\tconst userMemberships = await operations.getMembershipsForUser(user.id)\n\t\t\t\tconst organizationId =\n\t\t\t\t\tcoupon.organizationId ||\n\t\t\t\t\tuserMemberships.find((m) => m.organization.name?.includes(user.email))\n\t\t\t\t\t\t?.organizationId // safer way to make sure we are using personal organization\n\n\t\t\t\tawait operations.createPurchase({\n\t\t\t\t\tid: purchaseId,\n\t\t\t\t\tuserId: user.id,\n\t\t\t\t\tcouponId: bulkCouponRedemption ? null : coupon.id,\n\t\t\t\t\tredeemedBulkCouponId: bulkCouponRedemption ? coupon.id : null,\n\t\t\t\t\tproductId,\n\t\t\t\t\ttotalAmount: '0',\n\t\t\t\t\torganizationId,\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tcouponUsedId: bulkCouponRedemption ? null : coupon.id,\n\t\t\t\t\t},\n\t\t\t\t})\n\n\t\t\t\tconst newPurchase = await operations.getPurchase(purchaseId)\n\n\t\t\t\tawait operations.incrementCouponUsedCount(coupon.id)\n\n\t\t\t\tawait operations.createPurchaseTransfer({\n\t\t\t\t\tsourceUserId: user.id,\n\t\t\t\t\tpurchaseId: purchaseId,\n\t\t\t\t\texpiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7),\n\t\t\t\t})\n\n\t\t\t\treturn { purchase: newPurchase, redeemingForCurrentUser }\n\t\t\t}\n\n\t\t\treturn null\n\t\t},\n\t}\n}\n"],"mappings":"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","names":["normalizeLearnerEmail","email","trim","toLowerCase","replace","createRedeemFullPriceCouponWorkflow","client","tables","operations","purchases","purchaseTable","redeemFullPriceCoupon","options","baseEmail","couponId","productIds","currentUserId","redeemingProductId","String","coupon","getCouponWithBulkPurchases","productId","restrictedToProductId","Error","couponValidation","validateCoupon","isRedeemable","bulkCouponRedemption","Boolean","maxUses","user","findOrCreateUser","currentUser","getUserById","redeemingForCurrentUser","id","existingValidRedemption","query","findFirst","where","and","eq","redeemedBulkCouponId","userId","status","logger","info","purchaseId","error","message","purchase","existingPurchases","getExistingNonBulkValidPurchasesOfProduct","length","errorMessage","v4","userMemberships","getMembershipsForUser","organizationId","find","m","organization","name","includes","createPurchase","totalAmount","metadata","couponUsedId","newPurchase","getPurchase","incrementCouponUsedCount","createPurchaseTransfer","sourceUserId","expiresAt","Date","now"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CouponPort, IdentityPort, OrganizationPort, PurchasePort } from '@coursebuilder/core/ports';
|
|
2
|
+
import { MySqlContext } from '../context.cjs';
|
|
3
|
+
import 'drizzle-orm/mysql-core';
|
|
4
|
+
import '../schema.cjs';
|
|
5
|
+
import 'drizzle-orm';
|
|
6
|
+
import '@coursebuilder/core/auth';
|
|
7
|
+
import '../schemas/auth/users.cjs';
|
|
8
|
+
|
|
9
|
+
type RedeemFullPriceCouponOperations = Pick<CouponPort, 'getCouponWithBulkPurchases' | 'incrementCouponUsedCount'> & Pick<IdentityPort, 'findOrCreateUser' | 'getUserById'> & Pick<OrganizationPort, 'getMembershipsForUser'> & Pick<PurchasePort, 'createPurchase' | 'createPurchaseTransfer' | 'getExistingNonBulkValidPurchasesOfProduct' | 'getPurchase'>;
|
|
10
|
+
/**
|
|
11
|
+
* Creates the private full-price coupon redemption workflow.
|
|
12
|
+
*
|
|
13
|
+
* @param context - The shared MySQL client and table set.
|
|
14
|
+
* @param operations - Narrow identity, organization, purchase, and coupon operations.
|
|
15
|
+
* @returns The purchase-owned coupon redemption operation.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const workflow = createRedeemFullPriceCouponWorkflow(context, operations)
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
declare function createRedeemFullPriceCouponWorkflow({ client, tables }: MySqlContext, operations: RedeemFullPriceCouponOperations): Pick<PurchasePort, 'redeemFullPriceCoupon'>;
|
|
23
|
+
|
|
24
|
+
export { createRedeemFullPriceCouponWorkflow };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CouponPort, IdentityPort, OrganizationPort, PurchasePort } from '@coursebuilder/core/ports';
|
|
2
|
+
import { MySqlContext } from '../context.js';
|
|
3
|
+
import 'drizzle-orm/mysql-core';
|
|
4
|
+
import '../schema.js';
|
|
5
|
+
import 'drizzle-orm';
|
|
6
|
+
import '@coursebuilder/core/auth';
|
|
7
|
+
import '../schemas/auth/users.js';
|
|
8
|
+
|
|
9
|
+
type RedeemFullPriceCouponOperations = Pick<CouponPort, 'getCouponWithBulkPurchases' | 'incrementCouponUsedCount'> & Pick<IdentityPort, 'findOrCreateUser' | 'getUserById'> & Pick<OrganizationPort, 'getMembershipsForUser'> & Pick<PurchasePort, 'createPurchase' | 'createPurchaseTransfer' | 'getExistingNonBulkValidPurchasesOfProduct' | 'getPurchase'>;
|
|
10
|
+
/**
|
|
11
|
+
* Creates the private full-price coupon redemption workflow.
|
|
12
|
+
*
|
|
13
|
+
* @param context - The shared MySQL client and table set.
|
|
14
|
+
* @param operations - Narrow identity, organization, purchase, and coupon operations.
|
|
15
|
+
* @returns The purchase-owned coupon redemption operation.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const workflow = createRedeemFullPriceCouponWorkflow(context, operations)
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
declare function createRedeemFullPriceCouponWorkflow({ client, tables }: MySqlContext, operations: RedeemFullPriceCouponOperations): Pick<PurchasePort, 'redeemFullPriceCoupon'>;
|
|
23
|
+
|
|
24
|
+
export { createRedeemFullPriceCouponWorkflow };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|