@zaamx/netme-bundle 0.0.2

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,152 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = GET;
4
+ exports.POST = POST;
5
+ const bundles_1 = require("../../../modules/bundles");
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ async function GET(req, res) {
8
+ try {
9
+ const query = req.scope.resolve("query");
10
+ const { data: bundles, metadata: { count, take, skip } = {} } = await query.graph({
11
+ entity: "bundle",
12
+ ...req.queryConfig
13
+ });
14
+ // Enrich bundles with product information
15
+ const productService = req.scope.resolve(utils_1.Modules.PRODUCT);
16
+ const enrichedBundles = await Promise.all(bundles.map(async (bundle) => {
17
+ try {
18
+ const product = await productService.retrieveProduct(bundle.id);
19
+ // Get child products details
20
+ const childProducts = bundle.child_products?.data || [];
21
+ const enrichedChildProducts = await Promise.all(childProducts.map(async (childConfig) => {
22
+ try {
23
+ const childProduct = await productService.retrieveProduct(childConfig.id);
24
+ return {
25
+ id: childConfig.id,
26
+ product: {
27
+ id: childProduct.id,
28
+ title: childProduct.title,
29
+ },
30
+ quantity: childConfig.default_quantity || 1,
31
+ min_quantity: childConfig.min_quantity,
32
+ max_quantity: childConfig.max_quantity,
33
+ optional: childConfig.optional,
34
+ separate_shipping: childConfig.separate_shipping,
35
+ individual_price: childConfig.individual_price,
36
+ };
37
+ }
38
+ catch (error) {
39
+ // If child product doesn't exist, return basic info
40
+ return {
41
+ id: childConfig.id,
42
+ product: {
43
+ id: childConfig.id,
44
+ title: "Product not found",
45
+ },
46
+ quantity: childConfig.default_quantity || 1,
47
+ min_quantity: childConfig.min_quantity,
48
+ max_quantity: childConfig.max_quantity,
49
+ optional: childConfig.optional,
50
+ separate_shipping: childConfig.separate_shipping,
51
+ individual_price: childConfig.individual_price,
52
+ };
53
+ }
54
+ }));
55
+ return {
56
+ id: bundle.id,
57
+ title: product.title,
58
+ product: {
59
+ id: product.id,
60
+ },
61
+ items: enrichedChildProducts,
62
+ bundle_meta: bundle.bundle_meta?.data || [],
63
+ is_bundle: bundle.is_bundle,
64
+ created_at: bundle.created_at,
65
+ updated_at: bundle.updated_at,
66
+ };
67
+ }
68
+ catch (error) {
69
+ // If main product doesn't exist, return basic bundle info
70
+ return {
71
+ id: bundle.id,
72
+ title: "Product not found",
73
+ product: {
74
+ id: bundle.id,
75
+ },
76
+ items: [],
77
+ bundle_meta: bundle.bundle_meta?.data || [],
78
+ is_bundle: bundle.is_bundle,
79
+ created_at: bundle.created_at,
80
+ updated_at: bundle.updated_at,
81
+ };
82
+ }
83
+ }));
84
+ res.json({
85
+ bundled_products: enrichedBundles,
86
+ count: count || 0,
87
+ limit: take || 15,
88
+ offset: skip || 0,
89
+ });
90
+ }
91
+ catch (error) {
92
+ res.status(500).json({
93
+ message: "Failed to retrieve bundled products",
94
+ error: error instanceof Error ? error.message : "Unknown error"
95
+ });
96
+ }
97
+ }
98
+ async function POST(req, res) {
99
+ try {
100
+ const { title, product, items } = req.body;
101
+ // Create the product first
102
+ const productService = req.scope.resolve(utils_1.Modules.PRODUCT);
103
+ const createdProducts = await productService.createProducts([product]);
104
+ const createdProduct = createdProducts[0];
105
+ // Create bundle configuration
106
+ const bundleService = req.scope.resolve(bundles_1.BUNDLE_MODULE);
107
+ const bundle = await bundleService.createBundles([{
108
+ id: createdProduct.id,
109
+ child_products: {
110
+ data: items.map((item) => ({
111
+ id: item.product_id,
112
+ min_quantity: 1,
113
+ max_quantity: 1,
114
+ default_quantity: item.quantity,
115
+ optional: false,
116
+ separate_shipping: false,
117
+ individual_price: false,
118
+ }))
119
+ },
120
+ bundle_meta: {
121
+ data: []
122
+ },
123
+ is_bundle: true,
124
+ }]);
125
+ res.json({
126
+ bundled_product: {
127
+ id: createdProduct.id,
128
+ title: createdProduct.title,
129
+ product: {
130
+ id: createdProduct.id,
131
+ },
132
+ items: items.map((item) => ({
133
+ id: item.product_id,
134
+ product: {
135
+ id: item.product_id,
136
+ title: "Product", // You might want to fetch the actual product title
137
+ },
138
+ quantity: item.quantity,
139
+ })),
140
+ created_at: bundle[0].created_at,
141
+ updated_at: bundle[0].updated_at,
142
+ }
143
+ });
144
+ }
145
+ catch (error) {
146
+ res.status(500).json({
147
+ message: "Failed to create bundled product",
148
+ error: error instanceof Error ? error.message : "Unknown error"
149
+ });
150
+ }
151
+ }
152
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2J1bmRsZWQtcHJvZHVjdHMvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFNQSxrQkFxR0M7QUFFRCxvQkE4REM7QUExS0Qsc0RBQXdEO0FBRXhELHFEQUFtRDtBQUc1QyxLQUFLLFVBQVUsR0FBRyxDQUN2QixHQUFrQixFQUNsQixHQUFtQjtJQUVuQixJQUFJLENBQUM7UUFDSCxNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUN4QyxNQUFNLEVBQ0osSUFBSSxFQUFFLE9BQU8sRUFDYixRQUFRLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsRUFDckMsR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUM7WUFDcEIsTUFBTSxFQUFFLFFBQVE7WUFDaEIsR0FBRyxHQUFHLENBQUMsV0FBVztTQUNuQixDQUFDLENBQUE7UUFFRiwwQ0FBMEM7UUFDMUMsTUFBTSxjQUFjLEdBQTBCLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUNoRixNQUFNLGVBQWUsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQ3RDLE9BQWlCLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUN0QyxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxPQUFPLEdBQUcsTUFBTSxjQUFjLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQTtnQkFFL0QsNkJBQTZCO2dCQUM3QixNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsY0FBYyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUE7Z0JBQ3ZELE1BQU0scUJBQXFCLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxD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
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = GET;
4
+ async function GET(req, res) {
5
+ res.sendStatus(200);
6
+ }
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3BsdWdpbi9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLGtCQUtDO0FBTE0sS0FBSyxVQUFVLEdBQUcsQ0FDdkIsR0FBa0IsRUFDbEIsR0FBbUI7SUFFbkIsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN0QixDQUFDIn0=
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = GET;
4
+ exports.POST = POST;
5
+ exports.DELETE = DELETE;
6
+ const update_product_bundle_1 = require("../../../../../workflows/update-product-bundle");
7
+ const delete_product_bundle_1 = require("../../../../../workflows/delete-product-bundle");
8
+ const bundles_1 = require("../../../../../modules/bundles");
9
+ const utils_1 = require("@medusajs/framework/utils");
10
+ async function GET(req, res) {
11
+ try {
12
+ const { id: productId } = req.params;
13
+ const bundleService = req.scope.resolve(bundles_1.BUNDLE_MODULE);
14
+ const productService = req.scope.resolve(utils_1.Modules.PRODUCT);
15
+ // Get bundle data
16
+ const bundles = await bundleService.listBundles({
17
+ id: [productId]
18
+ });
19
+ if (!bundles.length) {
20
+ res.json({ product: { bundle: null } });
21
+ return;
22
+ }
23
+ const bundle = bundles[0];
24
+ const product = await productService.retrieveProduct(productId);
25
+ res.json({
26
+ product: {
27
+ ...product,
28
+ bundle: bundle
29
+ }
30
+ });
31
+ }
32
+ catch (error) {
33
+ res.status(500).json({
34
+ message: "Failed to retrieve bundle information",
35
+ error: error instanceof Error ? error.message : "Unknown error"
36
+ });
37
+ }
38
+ }
39
+ async function POST(req, res) {
40
+ const { id: productId } = req.params;
41
+ const { child_product_ids, bundle_meta, is_bundle } = req.body;
42
+ // Always delete any existing bundle config for this product first
43
+ try {
44
+ await (0, delete_product_bundle_1.deleteProductBundleWorkflow)(req.scope).run({
45
+ input: { product_id: productId }
46
+ });
47
+ }
48
+ catch (error) {
49
+ // Ignore errors if no bundle exists to delete
50
+ }
51
+ // Then create a new bundle config
52
+ const { result: product } = await (0, update_product_bundle_1.updateProductBundleWorkflow)(req.scope).run({
53
+ input: {
54
+ product_id: productId,
55
+ child_product_ids,
56
+ bundle_meta,
57
+ is_bundle,
58
+ },
59
+ });
60
+ res.json({ product });
61
+ }
62
+ async function DELETE(req, res) {
63
+ const { id: productId } = req.params;
64
+ const { result: product } = await (0, delete_product_bundle_1.deleteProductBundleWorkflow)(req.scope).run({
65
+ input: {
66
+ product_id: productId,
67
+ },
68
+ });
69
+ res.json({ product });
70
+ }
71
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3Byb2R1Y3RzL1tpZF0vYnVuZGxlL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBYUEsa0JBa0NDO0FBRUQsb0JBMkNDO0FBRUQsd0JBYUM7QUExR0QsMEZBQXNIO0FBQ3RILDBGQUE0RjtBQUM1Riw0REFBOEQ7QUFFOUQscURBQW1EO0FBUTVDLEtBQUssVUFBVSxHQUFHLENBQ3ZCLEdBQWtCLEVBQ2xCLEdBQW1CO0lBRW5CLElBQUksQ0FBQztRQUNILE1BQU0sRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQTtRQUNwQyxNQUFNLGFBQWEsR0FBa0IsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsdUJBQWEsQ0FBQyxDQUFBO1FBQ3JFLE1BQU0sY0FBYyxHQUEwQixHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxlQUFPLENBQUMsT0FBTyxDQUFDLENBQUE7UUFFaEYsa0JBQWtCO1FBQ2xCLE1BQU0sT0FBTyxHQUFHLE1BQU0sYUFBYSxDQUFDLFdBQVcsQ0FBQztZQUM5QyxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUM7U0FDaEIsQ0FBQyxDQUFBO1FBRUYsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNwQixHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQTtZQUN2QyxPQUFNO1FBQ1IsQ0FBQztRQUVELE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUN6QixNQUFNLE9BQU8sR0FBRyxNQUFNLGNBQWMsQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLENBQUE7UUFFL0QsR0FBRyxDQUFDLElBQUksQ0FBQztZQUNQLE9BQU8sRUFBRTtnQkFDUCxHQUFHLE9BQU87Z0JBQ1YsTUFBTSxFQUFFLE1BQU07YUFDZjtTQUNGLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFDbkIsT0FBTyxFQUFFLHVDQUF1QztZQUNoRCxLQUFLLEVBQUUsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsZUFBZTtTQUNoRSxDQUFDLENBQUE7SUFDSixDQUFDO0FBQ0gsQ0FBQztBQUVNLEtBQUssVUFBVSxJQUFJLENBQ3hCLEdBQWtCLEVBQ2xCLEdBQW1CO0lBRW5CLE1BQU0sRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQTtJQUNwQyxNQUFNLEVBQ0osaUJBQWlCLEVBQ2pCLFdBQVcsRUFDWCxTQUFTLEVBQ1YsR0FBRyxHQUFHLENBQUMsSUFZUCxDQUFBO0lBRUQsa0VBQWtFO0lBQ2xFLElBQUksQ0FBQztRQUNILE1BQU0sSUFBQSxtREFBMkIsRUFBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDO1lBQy9DLEtBQUssRUFBRSxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUU7U0FDakMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZiw4Q0FBOEM7SUFDaEQsQ0FBQztJQUVELGtDQUFrQztJQUNsQyxNQUFNLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLE1BQU0sSUFBQSxtREFBMkIsRUFBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDO1FBQzNFLEtBQUssRUFBRTtZQUNMLFVBQVUsRUFBRSxTQUFTO1lBQ3JCLGlCQUFpQjtZQUNqQixXQUFXO1lBQ1gsU0FBUztTQUN5QjtLQUNyQyxDQUFDLENBQUE7SUFFRixHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQTtBQUN2QixDQUFDO0FBRU0sS0FBSyxVQUFVLE1BQU0sQ0FDMUIsR0FBa0IsRUFDbEIsR0FBbUI7SUFFbkIsTUFBTSxFQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFBO0lBRXBDLE1BQU0sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsTUFBTSxJQUFBLG1EQUEyQixFQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDM0UsS0FBSyxFQUFFO1lBQ0wsVUFBVSxFQUFFLFNBQVM7U0FDdEI7S0FDRixDQUFDLENBQUE7SUFFRixHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQTtBQUN2QixDQUFDIn0=
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = POST;
4
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
5
+ /**
6
+ * priceRules its a method the price of a item in funcion of the metadata keys, there can be different rules for different items
7
+ * The rules are:
8
+ * 0. Item can be a simple item so we dont compute the price
9
+ * 1. Item can be a child item item.metadata?.bundled_by then price is 0.001
10
+ * {"items":[{"variant_id":"variant_01JPP0AYM96MX45KV7Z7NPC9KS","quantity":14,"metadata":{"bundled_by":"e7cc4dc7-cc95-4cd1-9236-f04f21aeaa56"}}]}
11
+ * 2. Item can have a computed price item.metadata?.bundle_sticks_price so price is nuevoPrecioPaquete
12
+ * {"items":[{"variant_id":"variant_01JPNRAA9VSCJM0HTYPK8H087Y","quantity":1,"metadata":{"bundle_id":"e7cc4dc7-cc95-4cd1-9236-f04f21aeaa56","bundle_sticky_price":{"nuevoPrecioPaquete":32441.46,"aumentoTotal":1638.46,"porcentajeExtra":-1.3407,"ajustePorUnidad":117.03,"precioUnitarioPromedio":2200.21}}}]}
13
+ * 3. Item can have a computed price item.metadata?.price_rules so price is price_rules.nuevoPrecio
14
+ * * {"items":[{"variant_id":"variant_01JPNRAA9VSCJM0HTYPK8H087Y","quantity":1,"metadata":{"bundle_id":"e7cc4dc7-cc95-4cd1-9236-f04f21aeaa56","bundle_sticky_price":{"nuevoPrecio":32441.46,"aumentoTotal":1638.46,"porcentajeExtra":-1.3407,"ajustePorUnidad":117.03,"precioUnitarioPromedio":2200.21}}}]}
15
+ */
16
+ const priceRules = (item) => {
17
+ if (item.metadata?.bundled_by) {
18
+ return 0.001;
19
+ }
20
+ if (item.metadata?.bundle_sticks_price) {
21
+ return item.metadata?.bundle_sticks_price?.nuevoPrecioPaquete;
22
+ }
23
+ if (item.metadata?.price_rules) {
24
+ return item.metadata?.price_rules?.nuevoPrecio;
25
+ }
26
+ return undefined;
27
+ };
28
+ async function POST(req, res) {
29
+ const { id: cartId } = req.params;
30
+ const { items } = req.body;
31
+ const query = req.scope.resolve("query");
32
+ // Simplify to match example format
33
+ const itemsWithDynamicPrice = items.map(item => {
34
+ const price = priceRules(item);
35
+ return {
36
+ ...item,
37
+ ...(price !== undefined && { unit_price: price })
38
+ };
39
+ });
40
+ // console.log('Items with prices --', itemsWithDynamicPrice)
41
+ const workflowInput = {
42
+ items: itemsWithDynamicPrice,
43
+ cart_id: cartId,
44
+ };
45
+ // console.log('Workflow input --', workflowInput)
46
+ await (0, core_flows_1.addToCartWorkflow)(req.scope).run({
47
+ input: workflowInput,
48
+ });
49
+ const updatedCart = await query.graph({
50
+ entity: "cart",
51
+ filters: { id: cartId },
52
+ fields: ["id", "items.*", "items.unit_price"],
53
+ });
54
+ // console.log('Updated cart --', updatedCart)
55
+ res.status(200).json({ cart: updatedCart });
56
+ }
57
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2NhcnRzL1tpZF0vYnVuZGxlLWxpbmUtaXRlbXMvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUF3Q0Esb0JBd0NDO0FBL0VELDREQUErRDtBQWMvRDs7Ozs7Ozs7OztHQVVHO0FBRUgsTUFBTSxVQUFVLEdBQUcsQ0FBQyxJQUF1QixFQUFFLEVBQUU7SUFDN0MsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLFVBQVUsRUFBRSxDQUFDO1FBQzlCLE9BQU8sS0FBSyxDQUFBO0lBQ2QsQ0FBQztJQUNELElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxtQkFBbUIsRUFBRSxDQUFDO1FBQ3ZDLE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxtQkFBbUIsRUFBRSxrQkFBa0IsQ0FBQTtJQUMvRCxDQUFDO0lBQ0QsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLFdBQVcsRUFBRSxDQUFDO1FBQy9CLE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxXQUFXLEVBQUUsV0FBVyxDQUFBO0lBQ2hELENBQUM7SUFDRCxPQUFPLFNBQVMsQ0FBQTtBQUNsQixDQUFDLENBQUE7QUFFTSxLQUFLLFVBQVUsSUFBSSxDQUN4QixHQUFrQixFQUNsQixHQUFtQjtJQUVuQixNQUFNLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUE7SUFDakMsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLEdBQUcsQ0FBQyxJQUFzQyxDQUFBO0lBRTVELE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBR3hDLG1DQUFtQztJQUNuQyxNQUFNLHFCQUFxQixHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUU7UUFDN0MsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQzlCLE9BQU87WUFDTCxHQUFHLElBQUk7WUFDUCxHQUFHLENBQUMsS0FBSyxLQUFLLFNBQVMsSUFBSSxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsQ0FBQztTQUNsRCxDQUFBO0lBQ0gsQ0FBQyxDQUFDLENBQUE7SUFFRiw2REFBNkQ7SUFFN0QsTUFBTSxhQUFhLEdBQUc7UUFDcEIsS0FBSyxFQUFFLHFCQUFxQjtRQUM1QixPQUFPLEVBQUUsTUFBTTtLQUNoQixDQUFBO0lBRUQsa0RBQWtEO0lBRWxELE1BQU0sSUFBQSw4QkFBaUIsRUFBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDO1FBQ3JDLEtBQUssRUFBRSxhQUFhO0tBQ3JCLENBQUMsQ0FBQTtJQUVGLE1BQU0sV0FBVyxHQUFHLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQztRQUNwQyxNQUFNLEVBQUUsTUFBTTtRQUNkLE9BQU8sRUFBRSxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUU7UUFDdkIsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRSxrQkFBa0IsQ0FBQztLQUM5QyxDQUFDLENBQUE7SUFFRiw4Q0FBOEM7SUFDOUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQTtBQUM3QyxDQUFDIn0=
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = GET;
4
+ async function GET(req, res) {
5
+ res.sendStatus(200);
6
+ }
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL3BsdWdpbi9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLGtCQUtDO0FBTE0sS0FBSyxVQUFVLEdBQUcsQ0FDdkIsR0FBa0IsRUFDbEIsR0FBbUI7SUFFbkIsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN0QixDQUFDIn0=
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = GET;
4
+ const bundles_1 = require("../../../../../modules/bundles");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ async function GET(req, res) {
7
+ try {
8
+ const { id: productId } = req.params;
9
+ const bundleService = req.scope.resolve(bundles_1.BUNDLE_MODULE);
10
+ const productService = req.scope.resolve(utils_1.Modules.PRODUCT);
11
+ // Get bundle data
12
+ const bundles = await bundleService.listBundles({
13
+ id: [productId]
14
+ });
15
+ if (!bundles.length) {
16
+ res.json({ bundle: null });
17
+ return;
18
+ }
19
+ const bundle = bundles[0];
20
+ // Validate bundle data structure
21
+ if (!bundle.child_products?.data) {
22
+ res.json({ bundle });
23
+ return;
24
+ }
25
+ // Get child products details
26
+ const childProductIds = bundle.child_products?.data;
27
+ if (!childProductIds) {
28
+ res.json({ bundle });
29
+ return;
30
+ }
31
+ // Merge bundle configuration with product details
32
+ const enrichedBundle = {
33
+ ...bundle
34
+ };
35
+ res.json({ bundle: enrichedBundle });
36
+ }
37
+ catch (error) {
38
+ res.status(400).json({
39
+ message: "Failed to retrieve bundle information",
40
+ error: error instanceof Error ? error.message : "Unknown error"
41
+ });
42
+ }
43
+ }
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL3Byb2R1Y3RzL1tpZF0vYnVuZGxlL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBTUEsa0JBK0NDO0FBcERELDREQUE4RDtBQUU5RCxxREFBbUQ7QUFHNUMsS0FBSyxVQUFVLEdBQUcsQ0FDdkIsR0FBa0IsRUFDbEIsR0FBbUI7SUFFbkIsSUFBSSxDQUFDO1FBQ0gsTUFBTSxFQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFBO1FBQ3BDLE1BQU0sYUFBYSxHQUFrQixHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyx1QkFBYSxDQUFDLENBQUE7UUFDckUsTUFBTSxjQUFjLEdBQTBCLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUVoRixrQkFBa0I7UUFDbEIsTUFBTSxPQUFPLEdBQUcsTUFBTSxhQUFhLENBQUMsV0FBVyxDQUFDO1lBQzlDLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQztTQUNoQixDQUFDLENBQUE7UUFFRixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3BCLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtZQUMxQixPQUFNO1FBQ1IsQ0FBQztRQUVELE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUV6QixpQ0FBaUM7UUFDakMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsSUFBSSxFQUFFLENBQUM7WUFDakMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUE7WUFDcEIsT0FBTTtRQUNSLENBQUM7UUFFRCw2QkFBNkI7UUFDN0IsTUFBTSxlQUFlLEdBQUcsTUFBTSxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUE7UUFDbkQsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3JCLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFBO1lBQ3BCLE9BQU07UUFDUixDQUFDO1FBR0Qsa0RBQWtEO1FBQ2xELE1BQU0sY0FBYyxHQUFHO1lBQ3JCLEdBQUcsTUFBTTtTQUNWLENBQUE7UUFFRCxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxDQUFDLENBQUE7SUFDdEMsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUNuQixPQUFPLEVBQUUsdUNBQXVDO1lBQ2hELEtBQUssRUFBRSxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxlQUFlO1NBQ2hFLENBQUMsQ0FBQTtJQUNKLENBQUM7QUFDSCxDQUFDIn0=
@@ -0,0 +1,10 @@
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 bundles_1 = __importDefault(require("../modules/bundles"));
8
+ const product_1 = __importDefault(require("@medusajs/medusa/product"));
9
+ exports.default = (0, utils_1.defineLink)(product_1.default.linkable.product, bundles_1.default.linkable.bundle);
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZHVjdC1idW5kbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGlua3MvcHJvZHVjdC1idW5kbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxREFBc0Q7QUFDdEQsaUVBQTZDO0FBQzdDLHVFQUFvRDtBQUVwRCxrQkFBZSxJQUFBLGtCQUFVLEVBQ3JCLGlCQUFhLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFDOUIsaUJBQVksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUMvQixDQUFBIn0=
@@ -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.BUNDLE_MODULE = void 0;
7
+ const service_1 = __importDefault(require("./service"));
8
+ const utils_1 = require("@medusajs/framework/utils");
9
+ exports.BUNDLE_MODULE = "bundle";
10
+ exports.default = (0, utils_1.Module)(exports.BUNDLE_MODULE, {
11
+ service: service_1.default,
12
+ });
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9idW5kbGVzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHdEQUFxQztBQUNyQyxxREFBa0Q7QUFFckMsUUFBQSxhQUFhLEdBQUcsUUFBUSxDQUFBO0FBRXJDLGtCQUFlLElBQUEsY0FBTSxFQUFDLHFCQUFhLEVBQUU7SUFDbkMsT0FBTyxFQUFFLGlCQUFhO0NBQ3ZCLENBQUMsQ0FBQSJ9
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Migration20241229065751 = void 0;
4
+ const migrations_1 = require("@mikro-orm/migrations");
5
+ class Migration20241229065751 extends migrations_1.Migration {
6
+ async up() {
7
+ this.addSql('create table if not exists "bundle" ("id" text not null, "child_products" jsonb not null default \'{"data":[]}\', "bundle_meta" jsonb not null default \'{"data":[]}\', "is_bundle" boolean not null default false, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "bundle_pkey" primary key ("id"));');
8
+ this.addSql('CREATE INDEX IF NOT EXISTS "IDX_bundle_deleted_at" ON "bundle" (deleted_at) WHERE deleted_at IS NULL;');
9
+ }
10
+ async down() {
11
+ this.addSql('drop table if exists "bundle" cascade;');
12
+ }
13
+ }
14
+ exports.Migration20241229065751 = Migration20241229065751;
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWlncmF0aW9uMjAyNDEyMjkwNjU3NTEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9idW5kbGVzL21pZ3JhdGlvbnMvTWlncmF0aW9uMjAyNDEyMjkwNjU3NTEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsc0RBQWtEO0FBRWxELE1BQWEsdUJBQXdCLFNBQVEsc0JBQVM7SUFFcEQsS0FBSyxDQUFDLEVBQUU7UUFDTixJQUFJLENBQUMsTUFBTSxDQUFDLG9ZQUFvWSxDQUFDLENBQUM7UUFDbFosSUFBSSxDQUFDLE1BQU0sQ0FBQyx1R0FBdUcsQ0FBQyxDQUFDO0lBQ3ZILENBQUM7SUFFRCxLQUFLLENBQUMsSUFBSTtRQUNSLElBQUksQ0FBQyxNQUFNLENBQUMsd0NBQXdDLENBQUMsQ0FBQztJQUN4RCxDQUFDO0NBRUY7QUFYRCwwREFXQyJ9
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Bundle = void 0;
4
+ /**
5
+ * This model is used to store the bundle meta data for a product.
6
+ * It is used to store the child products that are part of the bundle.
7
+ *
8
+ * The bundle_meta field is an array of objects that contain the child product id and the quantity.
9
+ * The is_bundle field is a boolean that indicates if the product is a bundle.
10
+ * npx medusa db:generate
11
+ * npx medusa db:sync-links
12
+ * npx medusa db:migrate
13
+ */
14
+ const utils_1 = require("@medusajs/framework/utils");
15
+ exports.Bundle = utils_1.model.define("bundle", {
16
+ id: utils_1.model.id().primaryKey(), // This will match the product ID
17
+ child_products: utils_1.model.json().default({ data: [] }), // Store as JSON object
18
+ bundle_meta: utils_1.model.json().default({ data: [] }), // Store as JSON object
19
+ is_bundle: utils_1.model.boolean().default(false),
20
+ });
21
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVuZGxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL21vZHVsZXMvYnVuZGxlcy9tb2RlbHMvYnVuZGxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBOzs7Ozs7Ozs7R0FTRztBQUNILHFEQUFpRDtBQUVwQyxRQUFBLE1BQU0sR0FBRyxhQUFLLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRTtJQUMzQyxFQUFFLEVBQUUsYUFBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsRUFBRSxFQUFFLGlDQUFpQztJQUM5RCxjQUFjLEVBQUUsYUFBSyxDQUFDLElBQUksRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFHLHVCQUF1QjtJQUM1RSxXQUFXLEVBQUUsYUFBSyxDQUFDLElBQUksRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFNLHVCQUF1QjtJQUM1RSxTQUFTLEVBQUUsYUFBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUM7Q0FDMUMsQ0FBQyxDQUFBIn0=
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("@medusajs/framework/utils");
4
+ const bundle_1 = require("./models/bundle");
5
+ class BundleService extends (0, utils_1.MedusaService)({
6
+ Bundle: bundle_1.Bundle,
7
+ }) {
8
+ async attachBundleToProduct(productId) {
9
+ const bundle = await this.listBundles({
10
+ id: [productId],
11
+ relations: ['childProducts']
12
+ });
13
+ return bundle[0] || null;
14
+ }
15
+ }
16
+ exports.default = BundleService;
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2J1bmRsZXMvc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHFEQUF5RDtBQUN6RCw0Q0FBd0M7QUFFeEMsTUFBTSxhQUFjLFNBQVEsSUFBQSxxQkFBYSxFQUFDO0lBQ3RDLE1BQU0sRUFBTixlQUFNO0NBQ1QsQ0FBQztJQUNFLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxTQUFpQjtRQUN6QyxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUM7WUFDbEMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDO1lBQ2YsU0FBUyxFQUFFLENBQUMsZUFBZSxDQUFDO1NBQy9CLENBQUMsQ0FBQTtRQUVGLE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQTtJQUM1QixDQUFDO0NBQ0o7QUFFRCxrQkFBZSxhQUFhLENBQUEifQ==
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteProductBundleWorkflow = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const bundles_1 = require("../modules/bundles");
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ const deleteProductBundleStep = (0, workflows_sdk_1.createStep)("delete-product-bundle", async (input, { container }) => {
8
+ const bundleService = container.resolve(bundles_1.BUNDLE_MODULE);
9
+ const productService = container.resolve(utils_1.Modules.PRODUCT);
10
+ // Find bundle
11
+ const bundles = await bundleService.listBundles({
12
+ id: [input.product_id]
13
+ });
14
+ if (bundles.length) {
15
+ // Delete bundle
16
+ await bundleService.deleteBundles([input.product_id]);
17
+ }
18
+ // Get updated product
19
+ const product = await productService.retrieveProduct(input.product_id);
20
+ return new workflows_sdk_1.StepResponse(product, bundles[0]);
21
+ });
22
+ exports.deleteProductBundleWorkflow = (0, workflows_sdk_1.createWorkflow)("delete-product-bundle", (input) => {
23
+ const product = deleteProductBundleStep(input);
24
+ return new workflows_sdk_1.WorkflowResponse(product);
25
+ });
26
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVsZXRlLXByb2R1Y3QtYnVuZGxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9kZWxldGUtcHJvZHVjdC1idW5kbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBSzBDO0FBQzFDLGdEQUFrRDtBQUNsRCxxREFBbUQ7QUFRbkQsTUFBTSx1QkFBdUIsR0FBRyxJQUFBLDBCQUFVLEVBQ3hDLHVCQUF1QixFQUN2QixLQUFLLEVBQUUsS0FBK0IsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDdkQsTUFBTSxhQUFhLEdBQWtCLFNBQVMsQ0FBQyxPQUFPLENBQUMsdUJBQWEsQ0FBQyxDQUFBO0lBQ3JFLE1BQU0sY0FBYyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsZUFBTyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBRXpELGNBQWM7SUFDZCxNQUFNLE9BQU8sR0FBRyxNQUFNLGFBQWEsQ0FBQyxXQUFXLENBQUM7UUFDNUMsRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQztLQUN6QixDQUFDLENBQUE7SUFFRixJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNuQixnQkFBZ0I7UUFDaEIsTUFBTSxhQUFhLENBQUMsYUFBYSxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUE7SUFDdkQsQ0FBQztJQUVELHNCQUFzQjtJQUN0QixNQUFNLE9BQU8sR0FBRyxNQUFNLGNBQWMsQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBZSxDQUFBO0lBRXBGLE9BQU8sSUFBSSw0QkFBWSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtBQUM5QyxDQUFDLENBQ0YsQ0FBQTtBQUVZLFFBQUEsMkJBQTJCLEdBQUcsSUFBQSw4QkFBYyxFQUN2RCx1QkFBdUIsRUFDdkIsQ0FBQyxLQUErQixFQUFFLEVBQUU7SUFDbEMsTUFBTSxPQUFPLEdBQUcsdUJBQXVCLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDOUMsT0FBTyxJQUFJLGdDQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFBO0FBQ3RDLENBQUMsQ0FDRixDQUFBIn0=
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updateProductBundleWorkflow = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const bundles_1 = require("../modules/bundles");
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ const updateProductBundleStep = (0, workflows_sdk_1.createStep)("update-product-bundle", async (input, { container }) => {
8
+ const bundleService = container.resolve(bundles_1.BUNDLE_MODULE);
9
+ const productService = container.resolve(utils_1.Modules.PRODUCT);
10
+ let bundle = await bundleService.listBundles({
11
+ id: [input.product_id]
12
+ });
13
+ if (!bundle.length && input.is_bundle) {
14
+ bundle = await bundleService.createBundles([{
15
+ id: input.product_id,
16
+ child_products: {
17
+ data: input.child_product_ids?.map(child => ({
18
+ id: child.id,
19
+ min_quantity: child.min_quantity ?? 1,
20
+ max_quantity: child.max_quantity ?? 1,
21
+ default_quantity: child.default_quantity ?? 1,
22
+ optional: child.optional ?? false,
23
+ separate_shipping: child.separate_shipping ?? false,
24
+ individual_price: child.individual_price ?? false,
25
+ })) || []
26
+ },
27
+ bundle_meta: {
28
+ data: input.bundle_meta || []
29
+ },
30
+ is_bundle: input.is_bundle,
31
+ }]);
32
+ }
33
+ else if (bundle.length) {
34
+ bundle = await bundleService.updateBundles([{
35
+ id: input.product_id,
36
+ child_products: {
37
+ data: input.child_product_ids?.map(child => ({
38
+ id: child.id,
39
+ min_quantity: child.min_quantity ?? 1,
40
+ max_quantity: child.max_quantity ?? 1,
41
+ default_quantity: child.default_quantity ?? 1,
42
+ optional: child.optional ?? false,
43
+ separate_shipping: child.separate_shipping ?? false,
44
+ individual_price: child.individual_price ?? false,
45
+ })) || []
46
+ },
47
+ bundle_meta: {
48
+ data: input.bundle_meta || []
49
+ },
50
+ is_bundle: input.is_bundle,
51
+ }]);
52
+ }
53
+ const product = await productService.retrieveProduct(input.product_id);
54
+ return new workflows_sdk_1.StepResponse({
55
+ ...product,
56
+ bundle: bundle[0] || null
57
+ });
58
+ });
59
+ exports.updateProductBundleWorkflow = (0, workflows_sdk_1.createWorkflow)("update-product-bundle", (input) => {
60
+ const product = updateProductBundleStep(input);
61
+ return new workflows_sdk_1.WorkflowResponse(product);
62
+ });
63
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBkYXRlLXByb2R1Y3QtYnVuZGxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy91cGRhdGUtcHJvZHVjdC1idW5kbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBSzBDO0FBQzFDLGdEQUFrRDtBQUNsRCxxREFBbUQ7QUFtQm5ELE1BQU0sdUJBQXVCLEdBQUcsSUFBQSwwQkFBVSxFQUN4Qyx1QkFBdUIsRUFDdkIsS0FBSyxFQUFFLEtBQStCLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO0lBQ3ZELE1BQU0sYUFBYSxHQUFrQixTQUFTLENBQUMsT0FBTyxDQUFDLHVCQUFhLENBQUMsQ0FBQTtJQUNyRSxNQUFNLGNBQWMsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQTtJQUV6RCxJQUFJLE1BQU0sR0FBRyxNQUFNLGFBQWEsQ0FBQyxXQUFXLENBQUM7UUFDM0MsRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQztLQUN2QixDQUFDLENBQUE7SUFFRixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sSUFBSSxLQUFLLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDdEMsTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUMxQyxFQUFFLEVBQUUsS0FBSyxDQUFDLFVBQVU7Z0JBQ3BCLGNBQWMsRUFBRTtvQkFDZCxJQUFJLEVBQUUsS0FBSyxDQUFDLGlCQUFpQixFQUFFLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7d0JBQzNDLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRTt3QkFDWixZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVksSUFBSSxDQUFDO3dCQUNyQyxZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVksSUFBSSxDQUFDO3dCQUNyQyxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsZ0JBQWdCLElBQUksQ0FBQzt3QkFDN0MsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRLElBQUksS0FBSzt3QkFDakMsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGlCQUFpQixJQUFJLEtBQUs7d0JBQ25ELGdCQUFnQixFQUFFLEtBQUssQ0FBQyxnQkFBZ0IsSUFBSSxLQUFLO3FCQUNsRCxDQUFDLENBQUMsSUFBSSxFQUFFO2lCQUNWO2dCQUNELFdBQVcsRUFBRTtvQkFDWCxJQUFJLEVBQUUsS0FBSyxDQUFDLFdBQVcsSUFBSSxFQUFFO2lCQUM5QjtnQkFDRCxTQUFTLEVBQUUsS0FBSyxDQUFDLFNBQVM7YUFDM0IsQ0FBQyxDQUFDLENBQUE7SUFDTCxDQUFDO1NBQU0sSUFBSSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDekIsTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUMxQyxFQUFFLEVBQUUsS0FBSyxDQUFDLFVBQVU7Z0JBQ3BCLGNBQWMsRUFBRTtvQkFDZCxJQUFJLEVBQUUsS0FBSyxDQUFDLGlCQUFpQixFQUFFLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7d0JBQzNDLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRTt3QkFDWixZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVksSUFBSSxDQUFDO3dCQUNyQyxZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVksSUFBSSxDQUFDO3dCQUNyQyxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsZ0JBQWdCLElBQUksQ0FBQzt3QkFDN0MsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRLElBQUksS0FBSzt3QkFDakMsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGlCQUFpQixJQUFJLEtBQUs7d0JBQ25ELGdCQUFnQixFQUFFLEtBQUssQ0FBQyxnQkFBZ0IsSUFBSSxLQUFLO3FCQUNsRCxDQUFDLENBQUMsSUFBSSxFQUFFO2lCQUNWO2dCQUNELFdBQVcsRUFBRTtvQkFDWCxJQUFJLEVBQUUsS0FBSyxDQUFDLFdBQVcsSUFBSSxFQUFFO2lCQUM5QjtnQkFDRCxTQUFTLEVBQUUsS0FBSyxDQUFDLFNBQVM7YUFDM0IsQ0FBQyxDQUFDLENBQUE7SUFDTCxDQUFDO0lBRUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxjQUFjLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQWUsQ0FBQTtJQUVwRixPQUFPLElBQUksNEJBQVksQ0FBQztRQUN0QixHQUFHLE9BQU87UUFDVixNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUk7S0FDMUIsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUNGLENBQUE7QUFFWSxRQUFBLDJCQUEyQixHQUFHLElBQUEsOEJBQWMsRUFDdkQsdUJBQXVCLEVBQ3ZCLENBQUMsS0FBK0IsRUFBRSxFQUFFO0lBQ2xDLE1BQU0sT0FBTyxHQUFHLHVCQUF1QixDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQzlDLE9BQU8sSUFBSSxnQ0FBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQTtBQUN0QyxDQUFDLENBQ0YsQ0FBQSJ9
package/README.md ADDED
@@ -0,0 +1,64 @@
1
+ <p align="center">
2
+ <a href="https://www.medusajs.com">
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/59018053/229103275-b5e482bb-4601-46e6-8142-244f531cebdb.svg">
5
+ <source media="(prefers-color-scheme: light)" srcset="https://user-images.githubusercontent.com/59018053/229103726-e5b529a3-9b3f-4970-8a1f-c6af37f087bf.svg">
6
+ <img alt="Medusa logo" src="https://user-images.githubusercontent.com/59018053/229103726-e5b529a3-9b3f-4970-8a1f-c6af37f087bf.svg">
7
+ </picture>
8
+ </a>
9
+ </p>
10
+ <h1 align="center">
11
+ Medusa Plugin Starter
12
+ </h1>
13
+
14
+ <h4 align="center">
15
+ <a href="https://docs.medusajs.com">Documentation</a> |
16
+ <a href="https://www.medusajs.com">Website</a>
17
+ </h4>
18
+
19
+ <p align="center">
20
+ Building blocks for digital commerce
21
+ </p>
22
+ <p align="center">
23
+ <a href="https://github.com/medusajs/medusa/blob/master/CONTRIBUTING.md">
24
+ <img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" alt="PRs welcome!" />
25
+ </a>
26
+ <a href="https://www.producthunt.com/posts/medusa"><img src="https://img.shields.io/badge/Product%20Hunt-%231%20Product%20of%20the%20Day-%23DA552E" alt="Product Hunt"></a>
27
+ <a href="https://discord.gg/xpCwq3Kfn8">
28
+ <img src="https://img.shields.io/badge/chat-on%20discord-7289DA.svg" alt="Discord Chat" />
29
+ </a>
30
+ <a href="https://twitter.com/intent/follow?screen_name=medusajs">
31
+ <img src="https://img.shields.io/twitter/follow/medusajs.svg?label=Follow%20@medusajs" alt="Follow @medusajs" />
32
+ </a>
33
+ </p>
34
+
35
+ ## Compatibility
36
+
37
+ This starter is compatible with versions >= 2.4.0 of `@medusajs/medusa`.
38
+
39
+ ## Getting Started
40
+
41
+ Visit the [Quickstart Guide](https://docs.medusajs.com/learn/installation) to set up a server.
42
+
43
+ Visit the [Plugins documentation](https://docs.medusajs.com/learn/fundamentals/plugins) to learn more about plugins and how to create them.
44
+
45
+ Visit the [Docs](https://docs.medusajs.com/learn/installation#get-started) to learn more about our system requirements.
46
+
47
+ ## What is Medusa
48
+
49
+ Medusa is a set of commerce modules and tools that allow you to build rich, reliable, and performant commerce applications without reinventing core commerce logic. The modules can be customized and used to build advanced ecommerce stores, marketplaces, or any product that needs foundational commerce primitives. All modules are open-source and freely available on npm.
50
+
51
+ Learn more about [Medusa’s architecture](https://docs.medusajs.com/learn/introduction/architecture) and [commerce modules](https://docs.medusajs.com/learn/fundamentals/modules/commerce-modules) in the Docs.
52
+
53
+ ## Community & Contributions
54
+
55
+ The community and core team are available in [GitHub Discussions](https://github.com/medusajs/medusa/discussions), where you can ask for support, discuss roadmap, and share ideas.
56
+
57
+ Join our [Discord server](https://discord.com/invite/medusajs) to meet other community members.
58
+
59
+ ## Other channels
60
+
61
+ - [GitHub Issues](https://github.com/medusajs/medusa/issues)
62
+ - [Twitter](https://twitter.com/medusajs)
63
+ - [LinkedIn](https://www.linkedin.com/company/medusajs)
64
+ - [Medusa Blog](https://medusajs.com/blog/)