@lodashventure/medusa-wishlist 0.0.6

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.
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ const widgetModule = { widgets: [] };
3
+ const routeModule = {
4
+ routes: []
5
+ };
6
+ const menuItemModule = {
7
+ menuItems: []
8
+ };
9
+ const formModule = { customFields: {} };
10
+ const displayModule = {
11
+ displays: {}
12
+ };
13
+ const plugin = {
14
+ widgetModule,
15
+ routeModule,
16
+ menuItemModule,
17
+ formModule,
18
+ displayModule
19
+ };
20
+ module.exports = plugin;
@@ -0,0 +1,21 @@
1
+ const widgetModule = { widgets: [] };
2
+ const routeModule = {
3
+ routes: []
4
+ };
5
+ const menuItemModule = {
6
+ menuItems: []
7
+ };
8
+ const formModule = { customFields: {} };
9
+ const displayModule = {
10
+ displays: {}
11
+ };
12
+ const plugin = {
13
+ widgetModule,
14
+ routeModule,
15
+ menuItemModule,
16
+ formModule,
17
+ displayModule
18
+ };
19
+ export {
20
+ plugin as default
21
+ };
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const wishlist_1 = require("../../../../../../modules/wishlist");
6
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
7
+ /**
8
+ * POST /store/customers/me/wishlist/add-all-to-cart
9
+ * Add all items from wishlist to cart
10
+ */
11
+ const POST = async (req, res) => {
12
+ const logger = req.scope.resolve("logger");
13
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
14
+ // Get customer with wishlist
15
+ const { data: customerWithWishlist } = await query.graph({
16
+ entity: "customer",
17
+ fields: [
18
+ "wishlist.*",
19
+ "wishlist.items.*",
20
+ ],
21
+ filters: {
22
+ id: [req.auth_context.actor_id],
23
+ },
24
+ });
25
+ if (!customerWithWishlist || !customerWithWishlist.length) {
26
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.NOT_FOUND, "Customer not found");
27
+ }
28
+ if (!customerWithWishlist[0].wishlist) {
29
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.NOT_FOUND, "Wishlist not found for this customer");
30
+ }
31
+ const wishlistItems = customerWithWishlist[0].wishlist.items || [];
32
+ if (wishlistItems.length === 0) {
33
+ return res.json({
34
+ message: "Wishlist is empty",
35
+ cart: null,
36
+ added_count: 0
37
+ });
38
+ }
39
+ // Get or create cart for customer
40
+ const cartModuleService = req.scope.resolve(utils_1.Modules.CART);
41
+ let cart = await cartModuleService.listCarts({
42
+ customer_id: customerWithWishlist[0].id,
43
+ completed_at: null
44
+ });
45
+ let cartId;
46
+ if (cart && cart.length > 0) {
47
+ cartId = cart[0].id;
48
+ logger.debug(`Using existing cart ${cartId}`);
49
+ }
50
+ else {
51
+ const newCart = await cartModuleService.createCarts({
52
+ currency_code: "usd", // You might want to make this configurable
53
+ customer_id: customerWithWishlist[0].id,
54
+ region_id: req.body?.region_id || undefined,
55
+ });
56
+ cartId = newCart.id;
57
+ logger.info(`Created new cart ${cartId} for customer`);
58
+ }
59
+ // Prepare items for cart
60
+ const itemsToAdd = wishlistItems.map((item) => ({
61
+ variant_id: item.productVariantId,
62
+ quantity: item.quantity || 1,
63
+ }));
64
+ logger.debug(`Adding ${itemsToAdd.length} items from wishlist to cart ${cartId}`);
65
+ // Add all items to cart
66
+ await (0, core_flows_1.addToCartWorkflow)(req.scope).run({
67
+ input: {
68
+ items: itemsToAdd,
69
+ cart_id: cartId,
70
+ }
71
+ });
72
+ // Optionally remove all items from wishlist
73
+ if (req.body?.removeFromWishlist) {
74
+ const wishlistModuleService = req.scope.resolve(wishlist_1.WISHLIST_MODULE);
75
+ logger.debug(`Removing all items from wishlist after adding to cart`);
76
+ for (const item of wishlistItems) {
77
+ await wishlistModuleService.deleteItem(customerWithWishlist[0].wishlist.id, item.productId, item.productVariantId);
78
+ }
79
+ }
80
+ // Get updated cart
81
+ const updatedCart = await cartModuleService.retrieveCart(cartId, {
82
+ relations: ['items', 'items.variant', 'items.variant.product']
83
+ });
84
+ logger.info(`Successfully added ${itemsToAdd.length} items from wishlist to cart`);
85
+ return res.json({
86
+ cart: updatedCart,
87
+ message: `Successfully added ${itemsToAdd.length} items to cart`,
88
+ added_count: itemsToAdd.length
89
+ });
90
+ };
91
+ exports.POST = POST;
92
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2N1c3RvbWVycy9tZS93aXNobGlzdC9hZGQtYWxsLXRvLWNhcnQvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBS0EscURBQTZHO0FBRTdHLGlFQUFvRTtBQUNwRSw0REFBK0Q7QUFPL0Q7OztHQUdHO0FBQ0ksTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUN2QixHQUFrRCxFQUNsRCxHQUFtQixFQUNuQixFQUFFO0lBQ0YsTUFBTSxNQUFNLEdBQVcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDbEQsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsS0FBSyxDQUFDLENBQUE7SUFFaEUsNkJBQTZCO0lBQzdCLE1BQU0sRUFBRSxJQUFJLEVBQUUsb0JBQW9CLEVBQUUsR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFDdkQsTUFBTSxFQUFFLFVBQVU7UUFDbEIsTUFBTSxFQUFFO1lBQ04sWUFBWTtZQUNaLGtCQUFrQjtTQUNuQjtRQUNELE9BQU8sRUFBRTtZQUNQLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDO1NBQ2hDO0tBQ0YsQ0FBQyxDQUFBO0lBRUYsSUFBSSxDQUFDLG9CQUFvQixJQUFJLENBQUMsb0JBQW9CLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDMUQsTUFBTSxJQUFJLG1CQUFXLENBQ25CLHdCQUFnQixDQUFDLFNBQVMsRUFDMUIsb0JBQW9CLENBQ3JCLENBQUE7SUFDSCxDQUFDO0lBRUQsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3RDLE1BQU0sSUFBSSxtQkFBVyxDQUNuQix3QkFBZ0IsQ0FBQyxTQUFT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
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const wishlist_1 = require("../../../../../../modules/wishlist");
6
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
7
+ /**
8
+ * POST /store/customers/me/wishlist/add-to-cart
9
+ * Add a single item from wishlist to cart
10
+ */
11
+ const POST = async (req, res) => {
12
+ const logger = req.scope.resolve("logger");
13
+ if (!req.body?.productVariantId) {
14
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.INVALID_DATA, "productVariantId is required");
15
+ }
16
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
17
+ // Get customer with wishlist
18
+ const { data: customerWithWishlist } = await query.graph({
19
+ entity: "customer",
20
+ fields: [
21
+ "wishlist.*",
22
+ "wishlist.items.*",
23
+ ],
24
+ filters: {
25
+ id: [req.auth_context.actor_id],
26
+ },
27
+ });
28
+ if (!customerWithWishlist || !customerWithWishlist.length) {
29
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.NOT_FOUND, "Customer not found");
30
+ }
31
+ if (!customerWithWishlist[0].wishlist) {
32
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.NOT_FOUND, "Wishlist not found for this customer");
33
+ }
34
+ // Find the item in the wishlist
35
+ const wishlistItem = customerWithWishlist[0].wishlist.items?.find((item) => item.productVariantId === req.body.productVariantId);
36
+ if (!wishlistItem) {
37
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.NOT_FOUND, "Item not found in wishlist");
38
+ }
39
+ // Get or create cart for customer
40
+ const cartModuleService = req.scope.resolve(utils_1.Modules.CART);
41
+ let cart = await cartModuleService.listCarts({
42
+ customer_id: customerWithWishlist[0].id,
43
+ completed_at: null
44
+ });
45
+ let cartId;
46
+ if (cart && cart.length > 0) {
47
+ cartId = cart[0].id;
48
+ logger.debug(`Using existing cart ${cartId}`);
49
+ }
50
+ else {
51
+ const newCart = await cartModuleService.createCarts({
52
+ currency_code: "usd", // You might want to make this configurable
53
+ customer_id: customerWithWishlist[0].id,
54
+ region_id: req.body.region_id || undefined,
55
+ });
56
+ cartId = newCart.id;
57
+ logger.info(`Created new cart ${cartId} for customer`);
58
+ }
59
+ // Add item to cart using Medusa's workflow
60
+ logger.debug(`Adding item ${req.body.productVariantId} from wishlist to cart ${cartId}`);
61
+ await (0, core_flows_1.addToCartWorkflow)(req.scope).run({
62
+ input: {
63
+ items: [{
64
+ variant_id: req.body.productVariantId,
65
+ quantity: wishlistItem.quantity || 1,
66
+ }],
67
+ cart_id: cartId,
68
+ }
69
+ });
70
+ // Optionally remove from wishlist
71
+ if (req.body.removeFromWishlist) {
72
+ const wishlistModuleService = req.scope.resolve(wishlist_1.WISHLIST_MODULE);
73
+ logger.debug(`Removing item from wishlist after adding to cart`);
74
+ await wishlistModuleService.deleteItem(customerWithWishlist[0].wishlist.id, wishlistItem.productId, wishlistItem.productVariantId);
75
+ }
76
+ // Get updated cart
77
+ const updatedCart = await cartModuleService.retrieveCart(cartId, {
78
+ relations: ['items', 'items.variant', 'items.variant.product']
79
+ });
80
+ logger.info(`Successfully added item ${req.body.productVariantId} from wishlist to cart`);
81
+ return res.json({
82
+ cart: updatedCart,
83
+ message: "Item added to cart successfully"
84
+ });
85
+ };
86
+ exports.POST = POST;
87
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2N1c3RvbWVycy9tZS93aXNobGlzdC9hZGQtdG8tY2FydC9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFLQSxxREFBNkc7QUFFN0csaUVBQW9FO0FBQ3BFLDREQUErRDtBQWMvRDs7O0dBR0c7QUFDSSxNQUFNLElBQUksR0FBRyxLQUFLLEVBQ3ZCLEdBQTJELEVBQzNELEdBQW1CLEVBQ25CLEVBQUU7SUFDRixNQUFNLE1BQU0sR0FBVyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUVsRCxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxnQkFBZ0IsRUFBRSxDQUFDO1FBQ2hDLE1BQU0sSUFBSSxtQkFBVyxDQUNuQix3QkFBZ0IsQ0FBQyxZQUFZLEVBQzdCLDhCQUE4QixDQUMvQixDQUFBO0lBQ0gsQ0FBQztJQUVELE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFBO0lBRWhFLDZCQUE2QjtJQUM3QixNQUFNLEVBQUUsSUFBSSxFQUFFLG9CQUFvQixFQUFFLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDO1FBQ3ZELE1BQU0sRUFBRSxVQUFVO1FBQ2xCLE1BQU0sRUFBRTtZQUNOLFlBQVk7WUFDWixrQkFBa0I7U0FDbkI7UUFDRCxPQUFPLEVBQUU7WUFDUCxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQztTQUNoQztLQUNGLENBQUMsQ0FBQTtJQUVGLElBQUksQ0FBQyxvQkFBb0IsSUFBSSxDQUFDLG9CQUFvQixDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzFELE1BQU0sSUFBSSxtQkFBVyxDQUNuQix3QkFBZ0IsQ0FBQyxTQUFTLEVBQzFCLG9C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
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DELETE = exports.POST = void 0;
7
+ const utils_1 = require("@medusajs/framework/utils");
8
+ const wishlist_1 = require("../../../../../../modules/wishlist");
9
+ const assign_wishlist_to_customer_1 = __importDefault(require("../../../../../../workflows/assign-wishlist-to-customer"));
10
+ const POST = async (req, res) => {
11
+ const logger = req.scope.resolve("logger");
12
+ // Validate request body
13
+ if (!req.body?.productId || !req.body?.productVariantId) {
14
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.INVALID_DATA, "productId and productVariantId are required");
15
+ }
16
+ if (!req.body?.quantity || req.body.quantity <= 0) {
17
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.INVALID_DATA, "quantity must be a positive number");
18
+ }
19
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
20
+ const { data: customerWithWishlist } = await query.graph({
21
+ entity: "customer",
22
+ fields: [
23
+ "wishlist.*",
24
+ ],
25
+ filters: {
26
+ id: [req.auth_context.actor_id],
27
+ },
28
+ });
29
+ if (!customerWithWishlist || !customerWithWishlist.length) {
30
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.NOT_FOUND, "Customer not found");
31
+ }
32
+ const wishlistModuleService = req.scope.resolve(wishlist_1.WISHLIST_MODULE);
33
+ let wishlistId;
34
+ if (customerWithWishlist[0].wishlist) {
35
+ wishlistId = customerWithWishlist[0].wishlist.id;
36
+ }
37
+ else {
38
+ logger.debug(`Wishlist will be initialized for customer ${customerWithWishlist[0].id}`);
39
+ wishlistId = await wishlistModuleService.create();
40
+ await (0, assign_wishlist_to_customer_1.default)(req.scope)
41
+ .run({
42
+ input: {
43
+ customerId: customerWithWishlist[0].id,
44
+ wishlistId: wishlistId
45
+ }
46
+ });
47
+ logger.info(`Wishlist ${wishlistId} initialized for customer ${customerWithWishlist[0].id}`);
48
+ }
49
+ logger.debug(`Adding item to wishlist ${wishlistId}`);
50
+ await wishlistModuleService.addOrUpdateItem(wishlistId, req.body.productId, req.body.productVariantId, req.body.quantity);
51
+ const updatedWishlist = await wishlistModuleService.retrieveWishlist(wishlistId, {
52
+ relations: ['items']
53
+ });
54
+ logger.info(`Item ${req.body.productVariantId} added to wishlist ${wishlistId}`);
55
+ return res.json(updatedWishlist);
56
+ };
57
+ exports.POST = POST;
58
+ const DELETE = async (req, res) => {
59
+ const logger = req.scope.resolve("logger");
60
+ const productId = req.query.productId;
61
+ const productVariantId = req.query.productVariantId;
62
+ // Validate query parameters
63
+ if (!productId || !productVariantId) {
64
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.INVALID_DATA, "productId and productVariantId query parameters are required");
65
+ }
66
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
67
+ const { data: customerWithWishlist } = await query.graph({
68
+ entity: "customer",
69
+ fields: [
70
+ "wishlist.*",
71
+ ],
72
+ filters: {
73
+ id: [req.auth_context.actor_id],
74
+ },
75
+ });
76
+ if (!customerWithWishlist || !customerWithWishlist.length) {
77
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.NOT_FOUND, "Customer not found");
78
+ }
79
+ if (!customerWithWishlist[0].wishlist) {
80
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.NOT_FOUND, "Wishlist not found for this customer");
81
+ }
82
+ const wishlistModuleService = req.scope.resolve(wishlist_1.WISHLIST_MODULE);
83
+ const wishlistId = customerWithWishlist[0].wishlist.id;
84
+ logger.debug(`Removing item ${productVariantId} from wishlist ${wishlistId}`);
85
+ await wishlistModuleService.deleteItem(wishlistId, productId, productVariantId);
86
+ const updatedWishlist = await wishlistModuleService.retrieveWishlist(wishlistId, {
87
+ relations: ['items']
88
+ });
89
+ logger.info(`Item ${productVariantId} removed from wishlist ${wishlistId}`);
90
+ return res.json(updatedWishlist);
91
+ };
92
+ exports.DELETE = DELETE;
93
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2N1c3RvbWVycy9tZS93aXNobGlzdC9pdGVtcy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFLQSxxREFBb0c7QUFFcEcsaUVBQW9FO0FBQ3BFLDBIQUFzRztBQUcvRixNQUFNLElBQUksR0FBRyxLQUFLLEVBQ3ZCLEdBQXVELEVBQ3ZELEdBQW1CLEVBQ25CLEVBQUU7SUFDRixNQUFNLE1BQU0sR0FBVyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUVsRCx3QkFBd0I7SUFDeEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsU0FBUyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3hELE1BQU0sSUFBSSxtQkFBVyxDQUNuQix3QkFBZ0IsQ0FBQyxZQUFZLEVBQzdCLDZDQUE2QyxDQUM5QyxDQUFBO0lBQ0gsQ0FBQztJQUVELElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLFFBQVEsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUNsRCxNQUFNLElBQUksbUJBQVcsQ0FDbkIsd0JBQWdCLENBQUMsWUFBWSxFQUM3QixvQ0FBb0MsQ0FDckMsQ0FBQTtJQUNILENBQUM7SUFFRCxNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUVoRSxNQUFNLEVBQUUsSUFBSSxFQUFFLG9CQUFvQixFQUFFLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDO1FBQ3ZELE1BQU0sRUFBRSxVQUFVO1FBQ2xCLE1BQU0sRUFBRTtZQUNOLFlBQVk7U0FDYjtRQUNELE9BQU8sRUFBRTtZQUNQLEVB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
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PATCH = exports.GET = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const wishlist_1 = require("../../../../../modules/wishlist");
6
+ const GET = async (req, res) => {
7
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
8
+ const { data: [customer] } = await query.graph({
9
+ entity: "customer",
10
+ fields: [
11
+ "wishlist.*",
12
+ "wishlist.items.*",
13
+ ],
14
+ filters: {
15
+ id: [req.auth_context.actor_id],
16
+ },
17
+ });
18
+ res.json({
19
+ wishlist: customer.wishlist,
20
+ });
21
+ };
22
+ exports.GET = GET;
23
+ const PATCH = async (req, res) => {
24
+ const logger = req.scope.resolve("logger");
25
+ if (!req.body?.name && req.body?.description === undefined) {
26
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.INVALID_DATA, "At least one of name or description must be provided");
27
+ }
28
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
29
+ const { data: customerWithWishlist } = await query.graph({
30
+ entity: "customer",
31
+ fields: [
32
+ "wishlist.*",
33
+ ],
34
+ filters: {
35
+ id: [req.auth_context.actor_id],
36
+ },
37
+ });
38
+ if (!customerWithWishlist || !customerWithWishlist.length) {
39
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.NOT_FOUND, "Customer not found");
40
+ }
41
+ if (!customerWithWishlist[0].wishlist) {
42
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.NOT_FOUND, "Wishlist not found for this customer");
43
+ }
44
+ const wishlistModuleService = req.scope.resolve(wishlist_1.WISHLIST_MODULE);
45
+ const wishlistId = customerWithWishlist[0].wishlist.id;
46
+ logger.debug(`Updating wishlist ${wishlistId} info`);
47
+ await wishlistModuleService.updateWishlistInfo(wishlistId, req.body.name, req.body.description);
48
+ const updatedWishlist = await wishlistModuleService.retrieveWishlist(wishlistId, {
49
+ relations: ['items']
50
+ });
51
+ logger.info(`Wishlist ${wishlistId} info updated`);
52
+ return res.json({
53
+ wishlist: updatedWishlist
54
+ });
55
+ };
56
+ exports.PATCH = PATCH;
57
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2N1c3RvbWVycy9tZS93aXNobGlzdC9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFJQSxxREFBb0c7QUFFcEcsOERBQWlFO0FBUTFELE1BQU0sR0FBRyxHQUFHLEtBQUssRUFDdEIsR0FBK0IsRUFDL0IsR0FBbUIsRUFDbkIsRUFBRTtJQUNGLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFBO0lBRWhFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFBRSxHQUFHLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQztRQUM3QyxNQUFNLEVBQUUsVUFBVTtRQUNsQixNQUFNLEVBQUU7WUFDTixZQUFZO1lBQ1osa0JBQWtCO1NBQ25CO1FBQ0QsT0FBTyxFQUFFO1lBQ1AsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUM7U0FDaEM7S0FDRixDQUFDLENBQUE7SUFFRixHQUFHLENBQUMsSUFBSSxDQUFDO1FBQ1AsUUFBUSxFQUFFLFFBQVEsQ0FBQyxRQUFRO0tBQzVCLENBQUMsQ0FBQTtBQUNKLENBQUMsQ0FBQTtBQXBCWSxRQUFBLEdBQUcsT0FvQmY7QUFFTSxNQUFNLEtBQUssR0FBRyxLQUFLLEVBQ3hCLEdBQW9ELEVBQ3BELEdBQW1CLEVBQ25CLEVBQUU7SUFDRixNQUFNLE1BQU0sR0FBVyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUVsRCxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLElBQUksR0FBRyxDQUFDLElBQUksRUFBRSxXQUFXLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDM0QsTUFBTSxJQUFJLG1CQUFXLENBQ25CLHdCQUFnQixDQUFDLFlBQVksRUFDN0Isc0RBQXNELENBQ3ZELENBQUE7SUFDSCxDQUFDO0lBRUQsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsS0FBSyxDQUFDLENBQUE7SUFFaEUsTUFBTSxFQUFFLElBQUksRUFBRSxvQkFBb0IsRUFBRSxHQUFHLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQztRQUN2RCxNQUFNLEVBQUUsVUFBVTtRQUNsQixNQUFNLEVBQUU7WUFDTixZQUFZO1NBQ2I7UUFDRCxPQUFPLEVBQUU7WUFDUCxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQztTQUNoQztLQUNGLENBQUMsQ0FBQTtJQUVGLElBQUksQ0FBQyxvQkFBb0IsSUFBSSxDQUFDLG9CQUFvQixDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzFELE1BQU0sSUFBSSxtQkFBVyxDQUNuQix3QkFBZ0IsQ0FBQyxTQUFTLEVBQzFCLG9CQUFvQixDQUNyQixDQUFBO0lBQ0gsQ0FBQztJQUVELElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUN0QyxNQUFNLElBQUksbUJBQVcsQ0FDbkIsd0JBQWdCLENBQUMsU0FBUyxFQUMxQixzQ0FBc0MsQ0FDdkMsQ0FBQTtJQUNILENBQUM7SUFFRCxNQUFNLHFCQUFxQixHQUEwQixHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQywwQkFBZSxDQUFDLENBQUE7SUFDdkYsTUFBTSxVQUFVLEdBQUcsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQTtJQUV0RCxNQUFNLENBQUMsS0FBSyxDQUFDLHFCQUFxQixVQUFVLE9BQU8sQ0FBQyxDQUFBO0lBRXBELE1BQU0scUJBQXFCLENBQUMsa0JBQWtCLENBQzVDLFVBQVUsRUFDVixHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFDYixHQUFHLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FDckIsQ0FBQTtJQUVELE1BQU0sZUFBZSxHQUFHLE1BQU0scUJBQXFCLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxFQUFFO1FBQy9FLFNBQVMsRUFBRSxDQUFDLE9BQU8sQ0FBQztLQUNyQixDQUFDLENBQUE7SUFFRixNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksVUFBVSxlQUFlLENBQUMsQ0FBQTtJQUVsRCxPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDZCxRQUFRLEVBQUUsZUFBZTtLQUMxQixDQUFDLENBQUE7QUFDSixDQUFDLENBQUE7QUEzRFksUUFBQSxLQUFLLFNBMkRqQiJ9
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const wishlist_1 = require("../../../../../../modules/wishlist");
6
+ const POST = async (req, res) => {
7
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
8
+ const { data: customerWithWishlist } = await query.graph({
9
+ entity: "customer",
10
+ fields: [
11
+ "wishlist.*",
12
+ ],
13
+ filters: {
14
+ id: [req.auth_context.actor_id],
15
+ },
16
+ });
17
+ if (customerWithWishlist && customerWithWishlist.length) {
18
+ const wishlistModuleService = req.scope.resolve(wishlist_1.WISHLIST_MODULE);
19
+ if (customerWithWishlist[0].wishlist && customerWithWishlist[0].wishlist.id) {
20
+ const token = wishlistModuleService.getSharedToken(req.auth_context.actor_id);
21
+ return res.json({
22
+ shared_token: token
23
+ });
24
+ }
25
+ }
26
+ return res.json(422);
27
+ };
28
+ exports.POST = POST;
29
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2N1c3RvbWVycy9tZS93aXNobGlzdC9zaGFyZS10b2tlbi9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFLQSxxREFBcUU7QUFFckUsaUVBQW9FO0FBRTdELE1BQU0sSUFBSSxHQUFHLEtBQUssRUFDdkIsR0FBK0IsRUFDL0IsR0FBbUIsRUFDbkIsRUFBRTtJQUNGLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFBO0lBRWhFLE1BQU0sRUFBRSxJQUFJLEVBQUUsb0JBQW9CLEVBQUUsR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFDdkQsTUFBTSxFQUFFLFVBQVU7UUFDbEIsTUFBTSxFQUFFO1lBQ04sWUFBWTtTQUNiO1FBQ0QsT0FBTyxFQUFFO1lBQ1AsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUM7U0FDaEM7S0FDRixDQUFDLENBQUE7SUFFRixJQUFJLG9CQUFvQixJQUFJLG9CQUFvQixDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ3hELE1BQU0scUJBQXFCLEdBQTBCLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLDBCQUFlLENBQUMsQ0FBQTtRQUV2RixJQUFJLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsSUFBSSxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDNUUsTUFBTSxLQUFLLEdBQUcscUJBQXFCLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDOUUsT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDO2dCQUNkLFlBQVksRUFBRSxLQUFLO2FBQ3BCLENBQUMsQ0FBQTtRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3ZCLENBQUMsQ0FBQTtBQTVCWSxRQUFBLElBQUksUUE0QmhCIn0=
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const wishlist_1 = require("../../../modules/wishlist");
6
+ const GET = async (req, res) => {
7
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
8
+ const rawRequest = req;
9
+ const token = rawRequest.query.token;
10
+ if (token) {
11
+ const wishlistModuleService = req.scope.resolve(wishlist_1.WISHLIST_MODULE);
12
+ const customerId = wishlistModuleService.decodeToken(token);
13
+ if (customerId) {
14
+ const { data: [customer] } = await query.graph({
15
+ entity: "customer",
16
+ fields: [
17
+ "wishlist.*",
18
+ "wishlist.items.*",
19
+ ],
20
+ filters: {
21
+ id: [customerId],
22
+ },
23
+ });
24
+ return res.json({
25
+ wishlist: customer.wishlist,
26
+ });
27
+ }
28
+ }
29
+ return res.json(422);
30
+ };
31
+ exports.GET = GET;
32
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL3dpc2hsaXN0cy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFJQSxxREFBcUU7QUFFckUsd0RBQTJEO0FBRXBELE1BQU0sR0FBRyxHQUFHLEtBQUssRUFDdEIsR0FBa0IsRUFDbEIsR0FBbUIsRUFDbkIsRUFBRTtJQUNGLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFBO0lBRWhFLE1BQU0sVUFBVSxHQUFHLEdBQXFCLENBQUM7SUFDekMsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUM7SUFFckMsSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUNWLE1BQU0scUJBQXFCLEdBQTBCLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLDBCQUFlLENBQUMsQ0FBQTtRQUN2RixNQUFNLFVBQVUsR0FBRyxxQkFBcUIsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDNUQsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFBRSxHQUFHLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQztnQkFDN0MsTUFBTSxFQUFFLFVBQVU7Z0JBQ2xCLE1BQU0sRUFBRTtvQkFDTixZQUFZO29CQUNaLGtCQUFrQjtpQkFDbkI7Z0JBQ0QsT0FBTyxFQUFFO29CQUNQLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQztpQkFDakI7YUFDRixDQUFDLENBQUE7WUFFRixPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUM7Z0JBQ2QsUUFBUSxFQUFFLFFBQVEsQ0FBQyxRQUFRO2FBQzVCLENBQUMsQ0FBQTtRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3ZCLENBQUMsQ0FBQTtBQS9CWSxRQUFBLEdBQUcsT0ErQmYifQ==
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ const customer_1 = __importDefault(require("@medusajs/medusa/customer"));
8
+ const wishlist_1 = __importDefault(require("../modules/wishlist"));
9
+ exports.default = (0, utils_1.defineLink)(customer_1.default.linkable.customer, {
10
+ linkable: wishlist_1.default.linkable.wishlist,
11
+ deleteCascade: true,
12
+ });
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VzdG9tZXItd2lzaGxpc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGlua3MvY3VzdG9tZXItd2lzaGxpc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxREFBc0Q7QUFDdEQseUVBQXNEO0FBQ3RELG1FQUFnRDtBQUVoRCxrQkFBZSxJQUFBLGtCQUFVLEVBQ3ZCLGtCQUFjLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFDaEM7SUFDRSxRQUFRLEVBQUUsa0JBQWMsQ0FBQyxRQUFRLENBQUMsUUFBUTtJQUMxQyxhQUFhLEVBQUUsSUFBSTtDQUNwQixDQUNGLENBQUEifQ==
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WISHLIST_MODULE = void 0;
7
+ const service_1 = __importDefault(require("./service"));
8
+ const utils_1 = require("@medusajs/framework/utils");
9
+ exports.WISHLIST_MODULE = "wishlistModuleService";
10
+ exports.default = (0, utils_1.Module)(exports.WISHLIST_MODULE, {
11
+ service: service_1.default,
12
+ });
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy93aXNobGlzdC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSx3REFBNkM7QUFDN0MscURBQWtEO0FBRXJDLFFBQUEsZUFBZSxHQUFHLHVCQUF1QixDQUFBO0FBRXRELGtCQUFlLElBQUEsY0FBTSxFQUFDLHVCQUFlLEVBQUU7SUFDckMsT0FBTyxFQUFFLGlCQUFxQjtDQUMvQixDQUFDLENBQUEifQ==
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Migration20250224100856 = void 0;
4
+ const migrations_1 = require("@mikro-orm/migrations");
5
+ class Migration20250224100856 extends migrations_1.Migration {
6
+ async up() {
7
+ this.addSql(`create table if not exists "wishlist" ("id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "wishlist_pkey" primary key ("id"));`);
8
+ this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_wishlist_deleted_at" ON "wishlist" (deleted_at) WHERE deleted_at IS NULL;`);
9
+ this.addSql(`create table if not exists "wishlist_item" ("id" text not null, "quantity" integer not null, "productId" text not null, "productVariantId" text not null, "wishlist_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "wishlist_item_pkey" primary key ("id"));`);
10
+ this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_wishlist_item_wishlist_id" ON "wishlist_item" (wishlist_id) WHERE deleted_at IS NULL;`);
11
+ this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_wishlist_item_deleted_at" ON "wishlist_item" (deleted_at) WHERE deleted_at IS NULL;`);
12
+ this.addSql(`alter table if exists "wishlist_item" add constraint "wishlist_item_wishlist_id_foreign" foreign key ("wishlist_id") references "wishlist" ("id") on update cascade on delete cascade;`);
13
+ }
14
+ async down() {
15
+ this.addSql(`alter table if exists "wishlist_item" drop constraint if exists "wishlist_item_wishlist_id_foreign";`);
16
+ this.addSql(`drop table if exists "wishlist" cascade;`);
17
+ this.addSql(`drop table if exists "wishlist_item" cascade;`);
18
+ }
19
+ }
20
+ exports.Migration20250224100856 = Migration20250224100856;
21
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWlncmF0aW9uMjAyNTAyMjQxMDA4NTYuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy93aXNobGlzdC9taWdyYXRpb25zL01pZ3JhdGlvbjIwMjUwMjI0MTAwODU2LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHNEQUFrRDtBQUVsRCxNQUFhLHVCQUF3QixTQUFRLHNCQUFTO0lBRTNDLEtBQUssQ0FBQyxFQUFFO1FBQ2YsSUFBSSxDQUFDLE1BQU0sQ0FBQyw2T0FBNk8sQ0FBQyxDQUFDO1FBQzNQLElBQUksQ0FBQyxNQUFNLENBQUMsMkdBQTJHLENBQUMsQ0FBQztRQUV6SCxJQUFJLENBQUMsTUFBTSxDQUFDLDhXQUE4VyxDQUFDLENBQUM7UUFDNVgsSUFBSSxDQUFDLE1BQU0sQ0FBQyx1SEFBdUgsQ0FBQyxDQUFDO1FBQ3JJLElBQUksQ0FBQyxNQUFNLENBQUMscUhBQXFILENBQUMsQ0FBQztRQUVuSSxJQUFJLENBQUMsTUFBTSxDQUFDLHdMQUF3TCxDQUFDLENBQUM7SUFDeE0sQ0FBQztJQUVRLEtBQUssQ0FBQyxJQUFJO1FBQ2pCLElBQUksQ0FBQyxNQUFNLENBQUMsc0dBQXNHLENBQUMsQ0FBQztRQUVwSCxJQUFJLENBQUMsTUFBTSxDQUFDLDBDQUEwQyxDQUFDLENBQUM7UUFFeEQsSUFBSSxDQUFDLE1BQU0sQ0FBQywrQ0FBK0MsQ0FBQyxDQUFDO0lBQy9ELENBQUM7Q0FFRjtBQXJCRCwwREFxQkMifQ==
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Migration20250322000000 = void 0;
4
+ const migrations_1 = require("@mikro-orm/migrations");
5
+ class Migration20250322000000 extends migrations_1.Migration {
6
+ async up() {
7
+ this.addSql('alter table "wishlist" add column "name" text not null default \'My Wishlist\';');
8
+ this.addSql('alter table "wishlist" add column "description" text null;');
9
+ }
10
+ async down() {
11
+ this.addSql('alter table "wishlist" drop column "name";');
12
+ this.addSql('alter table "wishlist" drop column "description";');
13
+ }
14
+ }
15
+ exports.Migration20250322000000 = Migration20250322000000;
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWlncmF0aW9uMjAyNTAzMjIwMDAwMDAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy93aXNobGlzdC9taWdyYXRpb25zL01pZ3JhdGlvbjIwMjUwMzIyMDAwMDAwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHNEQUFrRDtBQUVsRCxNQUFhLHVCQUF3QixTQUFRLHNCQUFTO0lBRXBELEtBQUssQ0FBQyxFQUFFO1FBQ04sSUFBSSxDQUFDLE1BQU0sQ0FBQyxpRkFBaUYsQ0FBQyxDQUFDO1FBQy9GLElBQUksQ0FBQyxNQUFNLENBQUMsNERBQTRELENBQUMsQ0FBQztJQUM1RSxDQUFDO0lBRUQsS0FBSyxDQUFDLElBQUk7UUFDUixJQUFJLENBQUMsTUFBTSxDQUFDLDRDQUE0QyxDQUFDLENBQUM7UUFDMUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxtREFBbUQsQ0FBQyxDQUFDO0lBQ25FLENBQUM7Q0FFRjtBQVpELDBEQVlDIn0=
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ const wishlist_1 = __importDefault(require("./wishlist"));
8
+ const WishlistItem = utils_1.model.define("wishlist_item", {
9
+ id: utils_1.model.id().primaryKey(),
10
+ quantity: utils_1.model.number(),
11
+ productId: utils_1.model.text(),
12
+ productVariantId: utils_1.model.text(),
13
+ wishlist: utils_1.model.belongsTo(() => wishlist_1.default, {
14
+ mappedBy: "items"
15
+ })
16
+ });
17
+ exports.default = WishlistItem;
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2lzaGxpc3QtaXRlbS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL3dpc2hsaXN0L21vZGVscy93aXNobGlzdC1pdGVtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEscURBQWlEO0FBQ2pELDBEQUFpQztBQUVqQyxNQUFNLFlBQVksR0FBRyxhQUFLLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRTtJQUNqRCxFQUFFLEVBQUUsYUFBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsRUFBRTtJQUMzQixRQUFRLEVBQUUsYUFBSyxDQUFDLE1BQU0sRUFBRTtJQUN4QixTQUFTLEVBQUUsYUFBSyxDQUFDLElBQUksRUFBRTtJQUN2QixnQkFBZ0IsRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFO0lBQzlCLFFBQVEsRUFBRSxhQUFLLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLGtCQUFRLEVBQUU7UUFDeEMsUUFBUSxFQUFFLE9BQU87S0FDbEIsQ0FBQztDQUNILENBQUMsQ0FBQTtBQUVGLGtCQUFlLFlBQVksQ0FBQSJ9
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ const wishlist_item_1 = __importDefault(require("./wishlist-item"));
8
+ const Wishlist = utils_1.model.define("wishlist", {
9
+ id: utils_1.model.id().primaryKey(),
10
+ name: utils_1.model.text().default("My Wishlist"),
11
+ description: utils_1.model.text().nullable(),
12
+ items: utils_1.model.hasMany(() => wishlist_item_1.default, {
13
+ mappedBy: "wishlist"
14
+ })
15
+ }).cascades({
16
+ delete: ["items"],
17
+ });
18
+ exports.default = Wishlist;
19
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2lzaGxpc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy93aXNobGlzdC9tb2RlbHMvd2lzaGxpc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxREFBaUQ7QUFDakQsb0VBQTBDO0FBRTFDLE1BQU0sUUFBUSxHQUFHLGFBQUssQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFO0lBQ3hDLEVBQUUsRUFBRSxhQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsVUFBVSxFQUFFO0lBQzNCLElBQUksRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQztJQUN6QyxXQUFXLEVBQUUsYUFBSyxDQUFDLElBQUksRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUNwQyxLQUFLLEVBQUUsYUFBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyx1QkFBWSxFQUFFO1FBQ3ZDLFFBQVEsRUFBRSxVQUFVO0tBQ3JCLENBQUM7Q0FDSCxDQUFDLENBQUMsUUFBUSxDQUFDO0lBQ1YsTUFBTSxFQUFFLENBQUMsT0FBTyxDQUFDO0NBQ2xCLENBQUMsQ0FBQTtBQUVGLGtCQUFlLFFBQVEsQ0FBQSJ9
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ const wishlist_1 = __importDefault(require("./models/wishlist"));
8
+ const wishlist_item_1 = __importDefault(require("./models/wishlist-item"));
9
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
10
+ class WishlistModuleService extends (0, utils_1.MedusaService)({
11
+ Wishlist: wishlist_1.default,
12
+ WishlistItem: wishlist_item_1.default
13
+ }) {
14
+ constructor({}, options) {
15
+ super(...arguments);
16
+ this.options_ = {
17
+ jwtSecret: options && options.jwtSecret ? options.jwtSecret : '',
18
+ };
19
+ }
20
+ async deleteItem(wishlistId, productId, productVariantId) {
21
+ await this.deleteWishlistItems({
22
+ wishlist_id: wishlistId,
23
+ productId: productId,
24
+ productVariantId: productVariantId
25
+ });
26
+ }
27
+ async addOrUpdateItem(wishlistId, productId, productVariantId, quantity) {
28
+ const existingItem = await this.listAndCountWishlistItems({
29
+ productVariantId: productVariantId
30
+ });
31
+ if (existingItem[1]) {
32
+ const existingItem = await this.updateWishlistItems({
33
+ selector: {
34
+ productId: productId,
35
+ productVariantId: productVariantId
36
+ },
37
+ data: {
38
+ quantity: quantity
39
+ }
40
+ });
41
+ return existingItem;
42
+ }
43
+ else {
44
+ const newItem = await this.createWishlistItems({
45
+ quantity: quantity,
46
+ productId: productId,
47
+ productVariantId: productVariantId,
48
+ wishlist_id: wishlistId
49
+ });
50
+ return newItem;
51
+ }
52
+ }
53
+ async create(name, description) {
54
+ const wishlist = await this.createWishlists({
55
+ name: name || "My Wishlist",
56
+ description: description || null
57
+ });
58
+ return wishlist.id;
59
+ }
60
+ async updateWishlistInfo(wishlistId, name, description) {
61
+ const data = {};
62
+ if (name !== undefined)
63
+ data.name = name;
64
+ if (description !== undefined)
65
+ data.description = description;
66
+ const updatedWishlist = await this.updateWishlists({
67
+ selector: { id: wishlistId },
68
+ data
69
+ });
70
+ return updatedWishlist;
71
+ }
72
+ getSharedToken(customerId) {
73
+ return jsonwebtoken_1.default.sign({
74
+ customer_id: customerId
75
+ }, this.options_.jwtSecret);
76
+ }
77
+ decodeToken(token) {
78
+ try {
79
+ const decoded = jsonwebtoken_1.default.verify(token, this.options_.jwtSecret);
80
+ if (!decoded || !decoded.customer_id) {
81
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.UNAUTHORIZED, `Invalid token: missing customer_id`);
82
+ }
83
+ return decoded.customer_id;
84
+ }
85
+ catch (error) {
86
+ if (error instanceof jsonwebtoken_1.default.JsonWebTokenError) {
87
+ throw new utils_1.MedusaError(utils_1.MedusaErrorTypes.UNAUTHORIZED, `Invalid token: ${error.message}`);
88
+ }
89
+ throw error;
90
+ }
91
+ }
92
+ }
93
+ exports.default = WishlistModuleService;
94
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL3dpc2hsaXN0L3NlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxREFBd0Y7QUFDeEYsaUVBQXlDO0FBQ3pDLDJFQUFrRDtBQUNsRCxnRUFBOEI7QUFHOUIsTUFBTSxxQkFBc0IsU0FBUSxJQUFBLHFCQUFhLEVBQUM7SUFDaEQsUUFBUSxFQUFSLGtCQUFRO0lBQ1IsWUFBWSxFQUFaLHVCQUFZO0NBQ2IsQ0FBQztJQUlBLFlBQVksRUFBRSxFQUFFLE9BQXVCO1FBQ3JDLEtBQUssQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFBO1FBRW5CLElBQUksQ0FBQyxRQUFRLEdBQUc7WUFDZCxTQUFTLEVBQUUsT0FBTyxJQUFJLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUU7U0FDakUsQ0FBQTtJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsVUFBVSxDQUFDLFVBQWtCLEVBQUUsU0FBaUIsRUFBRSxnQkFBd0I7UUFDOUUsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUM7WUFDN0IsV0FBVyxFQUFFLFVBQVU7WUFDdkIsU0FBUyxFQUFFLFNBQVM7WUFDcEIsZ0JBQWdCLEVBQUUsZ0JBQWdCO1NBQ25DLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFFRCxLQUFLLENBQUMsZUFBZSxDQUFDLFVBQWtCLEVBQUUsU0FBaUIsRUFBRSxnQkFBd0IsRUFBRSxRQUFnQjtRQUNyRyxNQUFNLFlBQVksR0FBRyxNQUFNLElBQUksQ0FBQyx5QkFBeUIsQ0FBQztZQUN4RCxnQkFBZ0IsRUFBRSxnQkFBZ0I7U0FDbkMsQ0FBQyxDQUFBO1FBQ0YsSUFBSSxZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNwQixNQUFNLFlBQVksR0FBRyxNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FB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
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy93aXNobGlzdC90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIn0=
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
4
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ const wishlist_1 = require("../modules/wishlist");
7
+ const assignWishlistToCustomerWorkflow = (0, workflows_sdk_1.createWorkflow)("assign-wishlist-to-customer", function (input) {
8
+ (0, core_flows_1.createRemoteLinkStep)([{
9
+ [utils_1.Modules.CUSTOMER]: {
10
+ customer_id: input.customerId
11
+ },
12
+ [wishlist_1.WISHLIST_MODULE]: {
13
+ wishlist_id: input.wishlistId
14
+ }
15
+ }]);
16
+ return new workflows_sdk_1.WorkflowResponse({});
17
+ });
18
+ exports.default = assignWishlistToCustomerWorkflow;
19
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzaWduLXdpc2hsaXN0LXRvLWN1c3RvbWVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9hc3NpZ24td2lzaGxpc3QtdG8tY3VzdG9tZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxxRUFJMEM7QUFDMUMsNERBQW1FO0FBQ25FLHFEQUFvRDtBQUNwRCxrREFBc0Q7QUFPdEQsTUFBTSxnQ0FBZ0MsR0FBRyxJQUFBLDhCQUFjLEVBQ3JELDZCQUE2QixFQUM3QixVQUFVLEtBQW9DO0lBRTVDLElBQUEsaUNBQW9CLEVBQUMsQ0FBQztZQUNwQixDQUFDLGVBQU8sQ0FBQyxRQUFRLENBQUMsRUFBRTtnQkFDbEIsV0FBVyxFQUFFLEtBQUssQ0FBQyxVQUFVO2FBQzlCO1lBQ0QsQ0FBQywwQkFBZSxDQUFDLEVBQUU7Z0JBQ2pCLFdBQVcsRUFBRSxLQUFLLENBQUMsVUFBVTthQUM5QjtTQUNGLENBQUMsQ0FBQyxDQUFBO0lBRUgsT0FBTyxJQUFJLGdDQUFnQixDQUFDLEVBQUUsQ0FBQyxDQUFBO0FBQ2pDLENBQUMsQ0FDRixDQUFBO0FBRUQsa0JBQWUsZ0NBQWdDLENBQUEifQ==
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 RSC-Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,342 @@
1
+ # Medusa Wishlist (Enhanced)
2
+
3
+ A powerful wishlist plugin for Medusa v2 that allows customers to save products for later, share their wishlists with others, and seamlessly move items to cart.
4
+
5
+ ## ✨ Features
6
+
7
+ ### Core Features
8
+ - 🛍️ **Customer Wishlists** - Each customer gets their own wishlist, automatically created when they add their first item
9
+ - ➕ **Add/Update Items** - Customers can add products to their wishlist and update quantities
10
+ - 🗑️ **Remove Items** - Easy removal of items from the wishlist
11
+ - 🔗 **Share Wishlists** - Generate shareable links using secure JWT tokens
12
+ - 🌐 **Public Access** - Shared wishlists can be viewed without authentication
13
+
14
+ ### Enhanced Features ⭐
15
+ - 🛒 **Move to Cart** - Add individual or all wishlist items directly to cart
16
+ - 📝 **Named Wishlists** - Give your wishlist a custom name and description
17
+ - 🔒 **Enhanced Security** - Improved JWT verification with proper signature validation
18
+ - ✅ **Input Validation** - Comprehensive request validation with proper error messages
19
+ - 🎯 **TypeScript Support** - Fully typed API with proper type definitions
20
+ - 📊 **Better Logging** - Enhanced logging for debugging and monitoring
21
+ - ⚡ **Error Handling** - Robust error handling with meaningful error messages
22
+
23
+ ## Installation
24
+
25
+ ### Option 1: Install as NPM Package
26
+
27
+ 1. Install the plugin:
28
+
29
+ ```bash
30
+ npm install @rsc-labs/medusa-wishlist
31
+ # or
32
+ yarn add @rsc-labs/medusa-wishlist
33
+ ```
34
+
35
+ 2. Add the plugin to your `medusa-config.js`:
36
+
37
+ ```js
38
+ const plugins = [
39
+ // ... other plugins
40
+ {
41
+ resolve: "@rsc-labs/medusa-wishlist",
42
+ options: {
43
+ jwtSecret: process.env.JWT_SECRET || "supersecret"
44
+ }
45
+ }
46
+ ]
47
+ ```
48
+
49
+ Or simply:
50
+
51
+ ```js
52
+ const plugins = [
53
+ // ... other plugins
54
+ "@rsc-labs/medusa-wishlist"
55
+ ]
56
+ ```
57
+
58
+ 3. Run database migrations:
59
+
60
+ ```bash
61
+ npx medusa db:migrate
62
+ ```
63
+
64
+ ### Option 2: Copy Source Code
65
+
66
+ You can also copy the source code directly into your Medusa project:
67
+
68
+ 1. Copy the `/src` directory contents into your project
69
+ 2. Add the module to your `medusa-config.js`:
70
+
71
+ ```js
72
+ const modules = [
73
+ // ... other modules
74
+ {
75
+ resolve: "./src/modules/wishlist",
76
+ options: {
77
+ jwtSecret: process.env.JWT_SECRET || "supersecret"
78
+ }
79
+ }
80
+ ]
81
+ ```
82
+
83
+ 3. Install required dependencies:
84
+
85
+ ```bash
86
+ npm install jsonwebtoken
87
+ # or
88
+ yarn add jsonwebtoken
89
+ ```
90
+
91
+ 4. Run database migrations:
92
+
93
+ ```bash
94
+ npx medusa db:migrate
95
+ ```
96
+
97
+ ## Configuration
98
+
99
+ ### JWT Secret
100
+
101
+ The wishlist sharing feature uses JWT tokens. It's recommended to set a strong secret in your environment variables:
102
+
103
+ ```bash
104
+ # .env
105
+ JWT_SECRET=your-super-secret-key-here
106
+ ```
107
+
108
+ Then configure it in `medusa-config.js`:
109
+
110
+ ```js
111
+ {
112
+ resolve: "@rsc-labs/medusa-wishlist",
113
+ options: {
114
+ jwtSecret: process.env.JWT_SECRET
115
+ }
116
+ }
117
+ ```
118
+
119
+ ## API Endpoints
120
+
121
+ ### Authenticated Endpoints (Require Customer Token)
122
+
123
+ #### Get Customer's Wishlist
124
+ ```
125
+ GET /store/customers/me/wishlist
126
+ Authorization: Bearer {customer-token}
127
+ ```
128
+
129
+ #### Update Wishlist Info ⭐ NEW
130
+ ```
131
+ PATCH /store/customers/me/wishlist
132
+ Authorization: Bearer {customer-token}
133
+ Content-Type: application/json
134
+
135
+ {
136
+ "name": "My Birthday Wishlist",
137
+ "description": "Items I'd love for my birthday"
138
+ }
139
+ ```
140
+
141
+ #### Add or Update Item
142
+ ```
143
+ POST /store/customers/me/wishlist/items
144
+ Authorization: Bearer {customer-token}
145
+ Content-Type: application/json
146
+
147
+ {
148
+ "productId": "prod_01XXXXX",
149
+ "productVariantId": "variant_01XXXXX",
150
+ "quantity": 1
151
+ }
152
+ ```
153
+
154
+ #### Remove Item
155
+ ```
156
+ DELETE /store/customers/me/wishlist/items?productId={productId}&productVariantId={productVariantId}
157
+ Authorization: Bearer {customer-token}
158
+ ```
159
+
160
+ #### Add Item to Cart from Wishlist ⭐ NEW
161
+ ```
162
+ POST /store/customers/me/wishlist/add-to-cart
163
+ Authorization: Bearer {customer-token}
164
+ Content-Type: application/json
165
+
166
+ {
167
+ "productVariantId": "variant_01XXXXX",
168
+ "removeFromWishlist": true // Optional: remove from wishlist after adding to cart
169
+ }
170
+ ```
171
+
172
+ #### Add All Items to Cart ⭐ NEW
173
+ ```
174
+ POST /store/customers/me/wishlist/add-all-to-cart
175
+ Authorization: Bearer {customer-token}
176
+ Content-Type: application/json
177
+
178
+ {
179
+ "removeFromWishlist": true, // Optional: clear wishlist after adding to cart
180
+ "region_id": "region_01XXXXX" // Optional
181
+ }
182
+ ```
183
+
184
+ #### Generate Share Token
185
+ ```
186
+ POST /store/customers/me/wishlist/share-token
187
+ Authorization: Bearer {customer-token}
188
+
189
+ Response:
190
+ {
191
+ "shared_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
192
+ }
193
+ ```
194
+
195
+ ### Public Endpoints (No Authentication Required)
196
+
197
+ #### View Shared Wishlist
198
+ ```
199
+ GET /store/wishlists?token={shared-token}
200
+ ```
201
+
202
+ ## Usage Example
203
+
204
+ ### 1. Customer Login
205
+ ```bash
206
+ curl -X POST http://localhost:9000/store/auth/customer/emailpass \
207
+ -H "Content-Type: application/json" \
208
+ -d '{
209
+ "email": "customer@example.com",
210
+ "password": "password123"
211
+ }'
212
+ ```
213
+
214
+ ### 2. Add Item to Wishlist
215
+ ```bash
216
+ curl -X POST http://localhost:9000/store/customers/me/wishlist/items \
217
+ -H "Authorization: Bearer {token}" \
218
+ -H "Content-Type: application/json" \
219
+ -d '{
220
+ "productId": "prod_01XXXXX",
221
+ "productVariantId": "variant_01XXXXX",
222
+ "quantity": 1
223
+ }'
224
+ ```
225
+
226
+ ### 3. Get Wishlist
227
+ ```bash
228
+ curl -X GET http://localhost:9000/store/customers/me/wishlist \
229
+ -H "Authorization: Bearer {token}"
230
+ ```
231
+
232
+ ### 4. Generate Share Token
233
+ ```bash
234
+ curl -X POST http://localhost:9000/store/customers/me/wishlist/share-token \
235
+ -H "Authorization: Bearer {token}"
236
+ ```
237
+
238
+ ### 5. View Shared Wishlist (Public)
239
+ ```bash
240
+ curl -X GET "http://localhost:9000/store/wishlists?token={shared-token}"
241
+ ```
242
+
243
+ ## Database Schema
244
+
245
+ The plugin creates the following tables:
246
+
247
+ ### `wishlist`
248
+ - `id` - Primary key
249
+ - `name` - Wishlist name (default: "My Wishlist") ⭐ NEW
250
+ - `description` - Wishlist description (nullable) ⭐ NEW
251
+ - `created_at` - Timestamp
252
+ - `updated_at` - Timestamp
253
+
254
+ ### `wishlist_item`
255
+ - `id` - Primary key
256
+ - `wishlist_id` - Foreign key to wishlist
257
+ - `product_id` - Product identifier
258
+ - `product_variant_id` - Product variant identifier
259
+ - `quantity` - Item quantity
260
+ - `created_at` - Timestamp
261
+ - `updated_at` - Timestamp
262
+
263
+ ### `link_customer_wishlist`
264
+ - Links customers to their wishlists (1:1 relationship)
265
+
266
+ ## What's Been Improved
267
+
268
+ This enhanced version includes several critical improvements over the original:
269
+
270
+ ### 🔒 Security Improvements
271
+ - **Fixed Critical JWT Vulnerability**: The original plugin used `jwt.decode()` which doesn't verify token signatures. This has been replaced with `jwt.verify()` to properly validate tokens and prevent forgery attacks.
272
+ - **Proper Error Handling**: JWT verification errors are now properly caught and handled with appropriate error types.
273
+
274
+ ### ✅ Code Quality Improvements
275
+ - **TypeScript Type Safety**: Added comprehensive type definitions in `types.ts` for all request/response types
276
+ - **Input Validation**: All API endpoints now validate input data and return meaningful error messages
277
+ - **Better Error Messages**: Replaced generic HTTP status codes with proper Medusa error types and descriptive messages
278
+ - **Enhanced Logging**: Added detailed logging at debug and info levels for better monitoring and debugging
279
+
280
+ ### 🚀 New Features
281
+ 1. **Wishlist Naming**: Customers can now name and describe their wishlists
282
+ 2. **Move to Cart**: New endpoints to add individual or all wishlist items to cart
283
+ 3. **Smart Cart Management**: Automatically creates or uses existing cart when moving items
284
+ 4. **Optional Cleanup**: Option to remove items from wishlist after adding to cart
285
+
286
+ ### 🏗️ Architectural Improvements
287
+ - Removed unsafe type casting (`as unknown as any`)
288
+ - Proper use of Medusa's generic types for authenticated requests
289
+ - Better separation of concerns in service methods
290
+ - Consistent error handling patterns across all endpoints
291
+
292
+ ## How It Works
293
+
294
+ 1. **Automatic Creation**: When a customer adds their first item, a wishlist is automatically created and linked to their account
295
+ 2. **Item Management**: Customers can add, update quantities, or remove items from their wishlist
296
+ 3. **Sharing**: Customers can generate a JWT token to share their wishlist with others
297
+ 4. **Public Access**: Anyone with the share token can view the wishlist without authentication
298
+
299
+ ## API Documentation
300
+
301
+ For detailed API specifications, see the [OpenAPI documentation](./docs/api.yaml).
302
+
303
+ ## Development
304
+
305
+ ### Prerequisites
306
+ - Node.js 20+
307
+ - Medusa v2
308
+ - PostgreSQL
309
+
310
+ ### Local Setup
311
+ ```bash
312
+ # Install dependencies
313
+ npm install
314
+
315
+ # Run migrations
316
+ npx medusa db:migrate
317
+
318
+ # Start development server
319
+ npm run dev
320
+ ```
321
+
322
+ ## Contributing
323
+
324
+ Contributions are welcome! Please feel free to submit a Pull Request.
325
+
326
+ ## License
327
+
328
+ MIT License - see [LICENSE](./LICENSE) file for details.
329
+
330
+ ## Credits
331
+
332
+ Created by [RSC Labs](https://rsoftcon.com)
333
+
334
+ ## Support
335
+
336
+ For issues and questions:
337
+ - GitHub Issues: [medusa-wishlist/issues](https://github.com/RSC-Labs/medusa-wishlist/issues)
338
+ - Documentation: [docs.medusajs.com](https://docs.medusajs.com)
339
+
340
+ ---
341
+
342
+ **Built for Medusa v2** 🚀
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@lodashventure/medusa-wishlist",
3
+ "version": "0.0.6",
4
+ "description": "The plugin which provides wishlist functionality.",
5
+ "author": "RSC Labs (https://rsoftcon.com)",
6
+ "license": "MIT",
7
+ "files": [
8
+ ".medusa/server"
9
+ ],
10
+ "exports": {
11
+ "./package.json": "./package.json",
12
+ "./workflows": "./.medusa/server/src/workflows/index.js",
13
+ "./.medusa/server/src/modules/*": "./.medusa/server/src/modules/*/index.js",
14
+ "./modules/*": "./.medusa/server/src/modules/*/index.js",
15
+ "./providers/*": "./.medusa/server/src/providers/*/index.js",
16
+ "./*": "./.medusa/server/src/*.js"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/RSC-Labs/medusa-wishlist"
21
+ },
22
+ "keywords": [
23
+ "medusa-plugin",
24
+ "medusa-v2",
25
+ "wishlist",
26
+ "medusa-wishlist"
27
+ ],
28
+ "scripts": {
29
+ "build": "medusa plugin:build",
30
+ "dev": "medusa plugin:develop"
31
+ },
32
+ "devDependencies": {
33
+ "@medusajs/admin-sdk": "2.10.3",
34
+ "@medusajs/cli": "2.10.3",
35
+ "@medusajs/framework": "2.10.3",
36
+ "@medusajs/medusa": "2.10.3",
37
+ "@medusajs/test-utils": "2.10.3",
38
+ "@medusajs/ui": "4.0.3",
39
+ "@medusajs/icons": "2.4.0",
40
+ "@mikro-orm/cli": "6.4.3",
41
+ "@mikro-orm/core": "6.4.3",
42
+ "@mikro-orm/knex": "6.4.3",
43
+ "@mikro-orm/migrations": "6.4.3",
44
+ "@mikro-orm/postgresql": "6.4.3",
45
+ "@swc/core": "1.5.7",
46
+ "@types/node": "^20.0.0",
47
+ "@types/react": "^18.3.2",
48
+ "@types/react-dom": "^18.2.25",
49
+ "awilix": "^8.0.1",
50
+ "pg": "^8.13.0",
51
+ "prop-types": "^15.8.1",
52
+ "react": "^18.2.0",
53
+ "react-dom": "^18.2.0",
54
+ "ts-node": "^10.9.2",
55
+ "typescript": "^5.6.2",
56
+ "vite": "^5.2.11",
57
+ "yalc": "^1.0.0-pre.53"
58
+ },
59
+ "peerDependencies": {
60
+ "@medusajs/admin-sdk": "2.10.3",
61
+ "@medusajs/cli": "2.10.3",
62
+ "@medusajs/framework": "2.10.3",
63
+ "@medusajs/test-utils": "2.10.3",
64
+ "@medusajs/medusa": "2.10.3",
65
+ "@medusajs/ui": "4.0.3",
66
+ "@medusajs/icons": "2.4.0",
67
+ "@mikro-orm/cli": "6.4.3",
68
+ "@mikro-orm/core": "6.4.3",
69
+ "@mikro-orm/knex": "6.4.3",
70
+ "@mikro-orm/migrations": "6.4.3",
71
+ "@mikro-orm/postgresql": "6.4.3",
72
+ "awilix": "^8.0.1",
73
+ "pg": "^8.13.0"
74
+ },
75
+ "engines": {
76
+ "node": ">=20"
77
+ }
78
+ }