@lodashventure/medusa-collection-thumbnail 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.medusa/server/api/admin/collections/[id]/thumbnail/route.d.ts +4 -0
- package/.medusa/server/api/admin/collections/[id]/thumbnail/route.js +101 -0
- package/.medusa/server/api/middlewares.d.ts +2 -0
- package/.medusa/server/api/middlewares.js +31 -0
- package/.medusa/server/api/store/collections/[id]/route.d.ts +2 -0
- package/.medusa/server/api/store/collections/[id]/route.js +46 -0
- package/.medusa/server/api/store/collections/route.d.ts +2 -0
- package/.medusa/server/api/store/collections/route.js +71 -0
- package/.medusa/server/index.d.ts +2 -0
- package/.medusa/server/index.js +8 -0
- package/.medusa/server/links/collection-thumbnail.d.ts +2 -0
- package/.medusa/server/links/collection-thumbnail.js +16 -0
- package/.medusa/server/modules/collection/index.d.ts +21 -0
- package/.medusa/server/modules/collection/index.js +13 -0
- package/.medusa/server/modules/collection/migrations/Migration20250921062957.d.ts +5 -0
- package/.medusa/server/modules/collection/migrations/Migration20250921062957.js +18 -0
- package/.medusa/server/modules/collection/models/collection.d.ts +5 -0
- package/.medusa/server/modules/collection/models/collection.js +16 -0
- package/.medusa/server/modules/collection/service.d.ts +10 -0
- package/.medusa/server/modules/collection/service.js +10 -0
- package/.medusa/server/services/gcs-direct-upload.d.ts +8 -0
- package/.medusa/server/services/gcs-direct-upload.js +55 -0
- package/.medusa/server/workflows/upload-collection-thumbnail.d.ts +13 -0
- package/.medusa/server/workflows/upload-collection-thumbnail.js +57 -0
- package/README.md +72 -0
- package/package.json +58 -0
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http";
|
|
2
|
+
export declare const GET: (req: MedusaRequest, res: MedusaResponse) => Promise<MedusaResponse>;
|
|
3
|
+
export declare const POST: (req: MedusaRequest, res: MedusaResponse) => Promise<MedusaResponse>;
|
|
4
|
+
export declare const DELETE: (req: MedusaRequest, res: MedusaResponse) => Promise<MedusaResponse>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DELETE = exports.POST = exports.GET = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const upload_collection_thumbnail_1 = require("../../../../../workflows/upload-collection-thumbnail");
|
|
6
|
+
const gcs_direct_upload_1 = require("../../../../../services/gcs-direct-upload");
|
|
7
|
+
const GET = async (req, res) => {
|
|
8
|
+
const { id } = req.params;
|
|
9
|
+
const collectionCustomService = req.scope.resolve("collectionCustom");
|
|
10
|
+
try {
|
|
11
|
+
const customData = await collectionCustomService
|
|
12
|
+
.listProductCollectionCustoms({ collection_id: id })
|
|
13
|
+
.then((result) => result[0]);
|
|
14
|
+
return res.json({
|
|
15
|
+
thumbnail: customData?.thumbnail || null,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
console.error("Error fetching thumbnail:", error);
|
|
20
|
+
return res.status(500).json({ error: "Failed to fetch thumbnail" });
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
exports.GET = GET;
|
|
24
|
+
const POST = async (req, res) => {
|
|
25
|
+
const { id } = req.params;
|
|
26
|
+
const productModuleService = req.scope.resolve(utils_1.Modules.PRODUCT);
|
|
27
|
+
const logger = req.scope.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
28
|
+
try {
|
|
29
|
+
const collection = await productModuleService.retrieveProductCollection(id);
|
|
30
|
+
if (!collection) {
|
|
31
|
+
return res.status(404).json({ error: "Collection not found" });
|
|
32
|
+
}
|
|
33
|
+
const file = req.file;
|
|
34
|
+
if (!file) {
|
|
35
|
+
return res.status(400).json({ error: "No file uploaded" });
|
|
36
|
+
}
|
|
37
|
+
const result = await (0, upload_collection_thumbnail_1.uploadCollectionThumbnailWorkflow)(req.scope).run({
|
|
38
|
+
input: {
|
|
39
|
+
collectionId: id,
|
|
40
|
+
fileData: {
|
|
41
|
+
filename: file.originalname,
|
|
42
|
+
mimeType: file.mimetype,
|
|
43
|
+
content: file.buffer.toString("base64"),
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
return res.json({
|
|
48
|
+
collection: {
|
|
49
|
+
id,
|
|
50
|
+
thumbnail: result.result.thumbnailUrl,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
logger.error("Error uploading collection thumbnail:", error);
|
|
56
|
+
return res.status(500).json({ error: "Failed to upload thumbnail" });
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
exports.POST = POST;
|
|
60
|
+
const DELETE = async (req, res) => {
|
|
61
|
+
const { id } = req.params;
|
|
62
|
+
const collectionCustomService = req.scope.resolve("collectionCustom");
|
|
63
|
+
const logger = req.scope.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
64
|
+
const gcsUploadService = new gcs_direct_upload_1.GcsDirectUploadService();
|
|
65
|
+
try {
|
|
66
|
+
const existingCustom = await collectionCustomService
|
|
67
|
+
.listProductCollectionCustoms({ collection_id: id })
|
|
68
|
+
.then((result) => result[0]);
|
|
69
|
+
if (!existingCustom || !existingCustom.thumbnail) {
|
|
70
|
+
return res.status(404).json({ error: "No thumbnail found for this collection" });
|
|
71
|
+
}
|
|
72
|
+
// Delete the file from GCS
|
|
73
|
+
if (existingCustom.thumbnail) {
|
|
74
|
+
try {
|
|
75
|
+
const url = existingCustom.thumbnail;
|
|
76
|
+
if (url.includes('storage.googleapis.com')) {
|
|
77
|
+
const parts = url.split('/');
|
|
78
|
+
const bucketIndex = parts.indexOf('sangaroon');
|
|
79
|
+
if (bucketIndex !== -1 && bucketIndex < parts.length - 1) {
|
|
80
|
+
const filename = parts.slice(bucketIndex + 1).join('/');
|
|
81
|
+
await gcsUploadService.deleteFile(filename);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (deleteError) {
|
|
86
|
+
logger.error("Error deleting file from GCS:", deleteError);
|
|
87
|
+
// Continue even if file deletion fails
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
await collectionCustomService.updateProductCollectionCustoms([{ id: existingCustom.id, thumbnail: null }]);
|
|
91
|
+
return res.json({
|
|
92
|
+
message: "Thumbnail deleted successfully",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
logger.error("Error deleting collection thumbnail:", error);
|
|
97
|
+
return res.status(500).json({ error: "Failed to delete thumbnail" });
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
exports.DELETE = DELETE;
|
|
101
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2NvbGxlY3Rpb25zL1tpZF0vdGh1bWJuYWlsL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUlBLHFEQUErRTtBQUUvRSxzR0FBeUc7QUFDekcsaUZBQW1GO0FBRTVFLE1BQU0sR0FBRyxHQUFHLEtBQUssRUFDdEIsR0FBa0IsRUFDbEIsR0FBbUIsRUFDbkIsRUFBRTtJQUNGLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDO0lBQzFCLE1BQU0sdUJBQXVCLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsa0JBQWtCLENBQVEsQ0FBQztJQUU3RSxJQUFJLENBQUM7UUFDSCxNQUFNLFVBQVUsR0FBRyxNQUFNLHVCQUF1QjthQUM3Qyw0QkFBNEIsQ0FBQyxFQUFFLGFBQWEsRUFBRSxFQUFFLEVBQUUsQ0FBQzthQUNuRCxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRS9CLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQztZQUNkLFNBQVMsRUFBRSxVQUFVLEVBQUUsU0FBUyxJQUFJLElBQUk7U0FDekMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixPQUFPLENBQUMsS0FBSyxDQUFDLDJCQUEyQixFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ2xELE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsMkJBQTJCLEVBQUUsQ0FBQyxDQUFDO0lBQ3RFLENBQUM7QUFDSCxDQUFDLENBQUM7QUFuQlcsUUFBQSxHQUFHLE9BbUJkO0FBRUssTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUN2QixHQUFrQixFQUNs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
|
|
@@ -0,0 +1,31 @@
|
|
|
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 medusa_1 = require("@medusajs/medusa");
|
|
7
|
+
const multer_1 = __importDefault(require("multer"));
|
|
8
|
+
const upload = (0, multer_1.default)({
|
|
9
|
+
storage: multer_1.default.memoryStorage(),
|
|
10
|
+
limits: {
|
|
11
|
+
fileSize: 5 * 1024 * 1024,
|
|
12
|
+
},
|
|
13
|
+
fileFilter: (req, file, cb) => {
|
|
14
|
+
const allowedMimeTypes = ["image/jpeg", "image/png", "image/gif", "image/webp"];
|
|
15
|
+
if (allowedMimeTypes.includes(file.mimetype)) {
|
|
16
|
+
cb(null, true);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
cb(new Error("Invalid file type. Only JPEG, PNG, GIF, and WebP are allowed."));
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
exports.default = (0, medusa_1.defineMiddlewares)({
|
|
24
|
+
routes: [
|
|
25
|
+
{
|
|
26
|
+
matcher: "/admin/collections/:id/thumbnail",
|
|
27
|
+
middlewares: [upload.single("thumbnail")],
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL21pZGRsZXdhcmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsNkNBQXFEO0FBQ3JELG9EQUE0QjtBQUU1QixNQUFNLE1BQU0sR0FBRyxJQUFBLGdCQUFNLEVBQUM7SUFDcEIsT0FBTyxFQUFFLGdCQUFNLENBQUMsYUFBYSxFQUFFO0lBQy9CLE1BQU0sRUFBRTtRQUNOLFFBQVEsRUFBRSxDQUFDLEdBQUcsSUFBSSxHQUFHLElBQUk7S0FDMUI7SUFDRCxVQUFVLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxFQUFFO1FBQzVCLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxZQUFZLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUNoRixJQUFJLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztZQUM3QyxFQUFFLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2pCLENBQUM7YUFBTSxDQUFDO1lBQ04sRUFBRSxDQUFDLElBQUksS0FBSyxDQUFDLCtEQUErRCxDQUFDLENBQUMsQ0FBQztRQUNqRixDQUFDO0lBQ0gsQ0FBQztDQUNGLENBQUMsQ0FBQztBQUVILGtCQUFlLElBQUEsMEJBQWlCLEVBQUM7SUFDL0IsTUFBTSxFQUFFO1FBQ047WUFDRSxPQUFPLEVBQUUsa0NBQWtDO1lBQzNDLFdBQVcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFRLENBQUM7U0FDakQ7S0FDRjtDQUNGLENBQUMsQ0FBQyJ9
|
|
@@ -0,0 +1,46 @@
|
|
|
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 GET = async (req, res) => {
|
|
6
|
+
const { id } = req.params;
|
|
7
|
+
const productModuleService = req.scope.resolve(utils_1.Modules.PRODUCT);
|
|
8
|
+
const collectionCustomService = req.scope.resolve("collectionCustom");
|
|
9
|
+
try {
|
|
10
|
+
// Retrieve the collection from Medusa's default service
|
|
11
|
+
const collection = await productModuleService.retrieveProductCollection(id, {
|
|
12
|
+
relations: ["products"],
|
|
13
|
+
});
|
|
14
|
+
if (!collection) {
|
|
15
|
+
return res.status(404).json({
|
|
16
|
+
error: "Collection not found"
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
// Retrieve custom data (thumbnail) for this collection
|
|
20
|
+
const customData = await collectionCustomService
|
|
21
|
+
.listProductCollectionCustoms({ collection_id: id })
|
|
22
|
+
.then(result => result[0]);
|
|
23
|
+
// Enrich collection with thumbnail
|
|
24
|
+
const enrichedCollection = {
|
|
25
|
+
id: collection.id,
|
|
26
|
+
title: collection.title,
|
|
27
|
+
handle: collection.handle,
|
|
28
|
+
thumbnail: customData?.thumbnail || null,
|
|
29
|
+
created_at: collection.created_at,
|
|
30
|
+
updated_at: collection.updated_at,
|
|
31
|
+
products: collection.products,
|
|
32
|
+
};
|
|
33
|
+
return res.json({
|
|
34
|
+
collection: enrichedCollection,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error("Error fetching collection:", error);
|
|
39
|
+
return res.status(500).json({
|
|
40
|
+
error: "Failed to fetch collection",
|
|
41
|
+
message: error.message
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
exports.GET = GET;
|
|
46
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2NvbGxlY3Rpb25zL1tpZF0vcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUEscURBQW9EO0FBRzdDLE1BQU0sR0FBRyxHQUFHLEtBQUssRUFDdEIsR0FBa0IsRUFDbEIsR0FBbUIsRUFDbkIsRUFBRTtJQUNGLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDO0lBQzFCLE1BQU0sb0JBQW9CLEdBQTBCLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUNuRSxlQUFPLENBQUMsT0FBTyxDQUNoQixDQUFDO0lBQ0YsTUFBTSx1QkFBdUIsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBUSxDQUFDO0lBRTdFLElBQUksQ0FBQztRQUNILHdEQUF3RDtRQUN4RCxNQUFNLFVBQVUsR0FBRyxNQUFNLG9CQUFvQixDQUFDLHlCQUF5QixDQUFDLEVBQUUsRUFBRTtZQUMxRSxTQUFTLEVBQUUsQ0FBQyxVQUFVLENBQUM7U0FDeEIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ2hCLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQzFCLEtBQUssRUFBRSxzQkFBc0I7YUFDOUIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELHVEQUF1RDtRQUN2RCxNQUFNLFVBQVUsR0FBRyxNQUFNLHVCQUF1QjthQUM3Qyw0QkFBNEIsQ0FBQyxFQUFFLGFBQWEsRUFBRSxFQUFFLEVBQUUsQ0FBQzthQUNuRCxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUU3QixtQ0FBbUM7UUFDbkMsTUFBTSxrQkFBa0IsR0FBRztZQUN6QixFQUFFLEVBQUUsVUFBVSxDQUFDLEVBQUU7WUFDakIsS0FBSyxFQUFFLFVBQVUsQ0FBQyxLQUFLO1lBQ3ZCLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTTtZQUN6QixTQUFTLEVBQUUsVUFBVSxFQUFFLFNBQVMsSUFBSSxJQUFJO1lBQ3hDLFVBQVUsRUFBRSxVQUFVLENBQUMsVUFBVTtZQUNqQyxVQUFVLEVBQUUsVUFBVSxDQUFDLFVBQVU7WUFDakMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxRQUFRO1NBQzlCLENBQUM7UUFFRixPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUM7WUFDZCxVQUFVLEVBQUUsa0JBQWtCO1NBQy9CLENBQUMsQ0FBQztJQUNMLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsT0FBTyxDQUFDLEtBQUssQ0FBQyw0QkFBNEIsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNuRCxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQzFCLEtBQUssRUFBRSw0QkFBNEI7WUFDbkMsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1NBQ3ZCLENBQUMsQ0FBQztJQUNMLENBQUM7QUFDSCxDQUFDLENBQUM7QUFoRFcsUUFBQSxHQUFHLE9BZ0RkIn0=
|
|
@@ -0,0 +1,71 @@
|
|
|
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 GET = async (req, res) => {
|
|
6
|
+
const productModuleService = req.scope.resolve(utils_1.Modules.PRODUCT);
|
|
7
|
+
const collectionCustomService = req.scope.resolve("collectionCustom");
|
|
8
|
+
try {
|
|
9
|
+
// Parse query parameters
|
|
10
|
+
const limit = parseInt(req.query.limit) || 10;
|
|
11
|
+
const offset = parseInt(req.query.offset) || 0;
|
|
12
|
+
const handle = req.query.handle;
|
|
13
|
+
const created_at = req.query.created_at;
|
|
14
|
+
const updated_at = req.query.updated_at;
|
|
15
|
+
// Build filters for collections
|
|
16
|
+
const filters = {};
|
|
17
|
+
if (handle) {
|
|
18
|
+
filters.handle = handle;
|
|
19
|
+
}
|
|
20
|
+
if (created_at) {
|
|
21
|
+
filters.created_at = created_at;
|
|
22
|
+
}
|
|
23
|
+
if (updated_at) {
|
|
24
|
+
filters.updated_at = updated_at;
|
|
25
|
+
}
|
|
26
|
+
// Retrieve collections from Medusa's default service
|
|
27
|
+
const [collections, count] = await productModuleService.listAndCountProductCollections(filters, {
|
|
28
|
+
skip: offset,
|
|
29
|
+
take: limit,
|
|
30
|
+
order: { created_at: "DESC" },
|
|
31
|
+
});
|
|
32
|
+
// Get all collection IDs
|
|
33
|
+
const collectionIds = collections.map(c => c.id);
|
|
34
|
+
// Retrieve custom data (thumbnails) for all collections
|
|
35
|
+
let customDataMap = {};
|
|
36
|
+
if (collectionIds.length > 0) {
|
|
37
|
+
const customData = await collectionCustomService.listProductCollectionCustoms({
|
|
38
|
+
collection_id: collectionIds,
|
|
39
|
+
});
|
|
40
|
+
// Create a map for quick lookup
|
|
41
|
+
customDataMap = customData.reduce((acc, custom) => {
|
|
42
|
+
acc[custom.collection_id] = custom.thumbnail;
|
|
43
|
+
return acc;
|
|
44
|
+
}, {});
|
|
45
|
+
}
|
|
46
|
+
// Enrich collections with thumbnails
|
|
47
|
+
const enrichedCollections = collections.map(collection => ({
|
|
48
|
+
id: collection.id,
|
|
49
|
+
title: collection.title,
|
|
50
|
+
handle: collection.handle,
|
|
51
|
+
thumbnail: customDataMap[collection.id] || null,
|
|
52
|
+
created_at: collection.created_at,
|
|
53
|
+
updated_at: collection.updated_at,
|
|
54
|
+
}));
|
|
55
|
+
return res.json({
|
|
56
|
+
collections: enrichedCollections,
|
|
57
|
+
count,
|
|
58
|
+
offset,
|
|
59
|
+
limit,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error("Error fetching collections:", error);
|
|
64
|
+
return res.status(500).json({
|
|
65
|
+
error: "Failed to fetch collections",
|
|
66
|
+
message: error.message
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
exports.GET = GET;
|
|
71
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2NvbGxlY3Rpb25zL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUlBLHFEQUFvRDtBQUc3QyxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQ3RCLEdBQWtCLEVBQ2xCLEdBQW1CLEVBQ25CLEVBQUU7SUFDRixNQUFNLG9CQUFvQixHQUEwQixHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FDbkUsZUFBTyxDQUFDLE9BQU8sQ0FDaEIsQ0FBQztJQUNGLE1BQU0sdUJBQXVCLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsa0JBQWtCLENBQVEsQ0FBQztJQUU3RSxJQUFJLENBQUM7UUFDSCx5QkFBeUI7UUFDekIsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBZSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3hELE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekQsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFnQixDQUFDO1FBQzFDLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsVUFBaUIsQ0FBQztRQUMvQyxNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLFVBQWlCLENBQUM7UUFFL0MsZ0NBQWdDO1FBQ2hDLE1BQU0sT0FBTyxHQUFRLEVBQUUsQ0FBQztRQUN4QixJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1gsT0FBTyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDMUIsQ0FBQztRQUNELElBQUksVUFBVSxFQUFFLENBQUM7WUFDZixPQUFPLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUNsQyxDQUFDO1FBQ0QsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQ2xDLENBQUM7UUFFRCxxREFBcUQ7UUFDckQsTUFBTSxDQUFDLFdBQVcsRUFBRSxLQUFLLENBQUMsR0FBRyxNQUFNLG9CQUFvQixDQUFDLDhCQUE4QixDQUNwRixPQUFPLEVBQ1A7WUFDRSxJQUFJLEVBQUUsTUFBTTtZQUNaLElBQUksRUFBRSxLQUFLO1lBQ1gsS0FBSyxFQUFFLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRTtTQUM5QixDQUNGLENBQUM7UUFFRix5QkFBeUI7UUFDekIsTUFBTSxhQUFhLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUVqRCx3REFBd0Q7UUFDeEQsSUFBSSxhQUFhLEdBQWtDLEVBQUUsQ0FBQztRQUN0RCxJQUFJLGFBQWEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDN0IsTUFBTSxVQUFVLEdBQUcsTUFBTSx1QkFBdUIsQ0FBQyw0QkFBNEIsQ0FBQztnQkFDNUUsYUFBYSxFQUFFLGFBQWE7YUFDN0IsQ0FBQyxDQUFDO1lBRUgsZ0NBQWdDO1lBQ2hDLGFBQWEsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFO2dCQUNoRCxHQUFHLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUM7Z0JBQzdDLE9BQU8sR0FBRyxDQUFDO1lBQ2IsQ0FBQyxFQUFFLEVBQW1DLENBQUMsQ0FBQztRQUMxQyxDQUFDO1FBRUQscUNBQXFDO1FBQ3JDLE1BQU0sbUJBQW1CLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDekQsRUFBRSxFQUFFLFVBQVUsQ0FBQyxFQUFFO1lBQ2pCLEtBQUssRUFBRSxVQUFVLENBQUMsS0FBSztZQUN2QixNQUFNLEVBQUUsVUFBVSxDQUFDLE1BQU07WUFDekIsU0FBUyxFQUFFLGFBQWEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSTtZQUMvQyxVQUFVLEVBQUUsVUFBVSxDQUFDLFVBQVU7WUFDakMsVUFBVSxFQUFFLFVBQVUsQ0FBQyxVQUFVO1NBQ2xDLENBQUMsQ0FBQyxDQUFDO1FBRUosT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDO1lBQ2QsV0FBVyxFQUFFLG1CQUFtQjtZQUNoQyxLQUFLO1lBQ0wsTUFBTTtZQUNOLEtBQUs7U0FDTixDQUFDLENBQUM7SUFDTCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsNkJBQTZCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDcEQsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUMxQixLQUFLLEVBQUUsNkJBQTZCO1lBQ3BDLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTztTQUN2QixDQUFDLENBQUM7SUFDTCxDQUFDO0FBQ0gsQ0FBQyxDQUFDO0FBL0VXLFFBQUEsR0FBRyxPQStFZCJ9
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = collectionThumbnailPlugin;
|
|
4
|
+
async function collectionThumbnailPlugin(container, options) {
|
|
5
|
+
// Plugin initialization logic
|
|
6
|
+
console.log("Collection Thumbnail Plugin loaded");
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFFQSw0Q0FNQztBQU5jLEtBQUssVUFBVSx5QkFBeUIsQ0FDckQsU0FBMEIsRUFDMUIsT0FBZ0M7SUFFaEMsOEJBQThCO0lBQzlCLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0NBQW9DLENBQUMsQ0FBQztBQUNwRCxDQUFDIn0=
|
|
@@ -0,0 +1,16 @@
|
|
|
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 product_1 = __importDefault(require("@medusajs/medusa/product"));
|
|
8
|
+
const collection_1 = __importDefault(require("../modules/collection"));
|
|
9
|
+
exports.default = (0, utils_1.defineLink)({
|
|
10
|
+
linkable: product_1.default.linkable.productCollection,
|
|
11
|
+
deleteCascade: true,
|
|
12
|
+
}, {
|
|
13
|
+
linkable: collection_1.default.linkable.productCollectionCustom,
|
|
14
|
+
deleteCascade: true,
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi10aHVtYm5haWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGlua3MvY29sbGVjdGlvbi10aHVtYm5haWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxREFBdUQ7QUFDdkQsdUVBQXFEO0FBQ3JELHVFQUFxRDtBQUVyRCxrQkFBZSxJQUFBLGtCQUFVLEVBQ3ZCO0lBQ0UsUUFBUSxFQUFFLGlCQUFhLENBQUMsUUFBUSxDQUFDLGlCQUFpQjtJQUNsRCxhQUFhLEVBQUUsSUFBSTtDQUNwQixFQUNEO0lBQ0UsUUFBUSxFQUFFLG9CQUFnQixDQUFDLFFBQVEsQ0FBQyx1QkFBdUI7SUFDM0QsYUFBYSxFQUFFLElBQUk7Q0FDcEIsQ0FDRixDQUFDIn0=
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import CollectionModuleService from "./service";
|
|
2
|
+
export declare const COLLECTION_MODULE = "collectionCustom";
|
|
3
|
+
declare const _default: import("@medusajs/types").ModuleExports<typeof CollectionModuleService> & {
|
|
4
|
+
linkable: {
|
|
5
|
+
readonly productCollectionCustom: {
|
|
6
|
+
id: {
|
|
7
|
+
serviceName: "collectionCustom";
|
|
8
|
+
field: "productCollectionCustom";
|
|
9
|
+
linkable: "product_collection_custom_id";
|
|
10
|
+
primaryKey: "id";
|
|
11
|
+
};
|
|
12
|
+
toJSON: () => {
|
|
13
|
+
serviceName: "collectionCustom";
|
|
14
|
+
field: "productCollectionCustom";
|
|
15
|
+
linkable: "product_collection_custom_id";
|
|
16
|
+
primaryKey: "id";
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export default _default;
|
|
@@ -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.COLLECTION_MODULE = void 0;
|
|
7
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
8
|
+
const service_1 = __importDefault(require("./service"));
|
|
9
|
+
exports.COLLECTION_MODULE = "collectionCustom";
|
|
10
|
+
exports.default = (0, utils_1.Module)(exports.COLLECTION_MODULE, {
|
|
11
|
+
service: service_1.default,
|
|
12
|
+
});
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9jb2xsZWN0aW9uL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHFEQUFtRDtBQUNuRCx3REFBZ0Q7QUFFbkMsUUFBQSxpQkFBaUIsR0FBRyxrQkFBa0IsQ0FBQztBQUVwRCxrQkFBZSxJQUFBLGNBQU0sRUFBQyx5QkFBaUIsRUFBRTtJQUN2QyxPQUFPLEVBQUUsaUJBQXVCO0NBQ2pDLENBQUMsQ0FBQyJ9
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Migration20250921062957 = void 0;
|
|
4
|
+
const migrations_1 = require("@medusajs/framework/mikro-orm/migrations");
|
|
5
|
+
class Migration20250921062957 extends migrations_1.Migration {
|
|
6
|
+
async up() {
|
|
7
|
+
this.addSql(`alter table if exists "product_collection_custom" drop constraint if exists "product_collection_custom_collection_id_unique";`);
|
|
8
|
+
this.addSql(`create table if not exists "product_collection_custom" ("id" text not null, "collection_id" text not null, "thumbnail" text null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_collection_custom_pkey" primary key ("id"));`);
|
|
9
|
+
this.addSql(`CREATE UNIQUE INDEX IF NOT EXISTS "IDX_product_collection_custom_collection_id_unique" ON "product_collection_custom" (collection_id) WHERE deleted_at IS NULL;`);
|
|
10
|
+
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_product_collection_custom_deleted_at" ON "product_collection_custom" (deleted_at) WHERE deleted_at IS NULL;`);
|
|
11
|
+
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_product_collection_custom_collection_id" ON "product_collection_custom" (collection_id) WHERE deleted_at IS NULL;`);
|
|
12
|
+
}
|
|
13
|
+
async down() {
|
|
14
|
+
this.addSql(`drop table if exists "product_collection_custom" cascade;`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.Migration20250921062957 = Migration20250921062957;
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWlncmF0aW9uMjAyNTA5MjEwNjI5NTcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9jb2xsZWN0aW9uL21pZ3JhdGlvbnMvTWlncmF0aW9uMjAyNTA5MjEwNjI5NTcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEseUVBQXFFO0FBRXJFLE1BQWEsdUJBQXdCLFNBQVEsc0JBQVM7SUFFM0MsS0FBSyxDQUFDLEVBQUU7UUFDZixJQUFJLENBQUMsTUFBTSxDQUFDLCtIQUErSCxDQUFDLENBQUM7UUFDN0ksSUFBSSxDQUFDLE1BQU0sQ0FBQyxxVUFBcVUsQ0FBQyxDQUFDO1FBQ25WLElBQUksQ0FBQyxNQUFNLENBQUMsaUtBQWlLLENBQUMsQ0FBQztRQUMvSyxJQUFJLENBQUMsTUFBTSxDQUFDLDZJQUE2SSxDQUFDLENBQUM7UUFDM0osSUFBSSxDQUFDLE1BQU0sQ0FBQyxtSkFBbUosQ0FBQyxDQUFDO0lBQ25LLENBQUM7SUFFUSxLQUFLLENBQUMsSUFBSTtRQUNqQixJQUFJLENBQUMsTUFBTSxDQUFDLDJEQUEyRCxDQUFDLENBQUM7SUFDM0UsQ0FBQztDQUVGO0FBZEQsMERBY0MifQ==
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const ProductCollectionCustom: import("@medusajs/framework/utils").DmlEntity<import("@medusajs/framework/utils").DMLEntitySchemaBuilder<{
|
|
2
|
+
id: import("@medusajs/framework/utils").PrimaryKeyModifier<string, import("@medusajs/framework/utils").IdProperty>;
|
|
3
|
+
collection_id: import("@medusajs/framework/utils").TextProperty;
|
|
4
|
+
thumbnail: import("@medusajs/framework/utils").NullableModifier<string, import("@medusajs/framework/utils").TextProperty>;
|
|
5
|
+
}>, "product_collection_custom">;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProductCollectionCustom = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
exports.ProductCollectionCustom = utils_1.model
|
|
6
|
+
.define("product_collection_custom", {
|
|
7
|
+
id: utils_1.model.id().primaryKey(),
|
|
8
|
+
collection_id: utils_1.model.text().unique(),
|
|
9
|
+
thumbnail: utils_1.model.text().nullable(),
|
|
10
|
+
})
|
|
11
|
+
.indexes([
|
|
12
|
+
{
|
|
13
|
+
on: ["collection_id"],
|
|
14
|
+
},
|
|
15
|
+
]);
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2NvbGxlY3Rpb24vbW9kZWxzL2NvbGxlY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscURBQWtEO0FBRXJDLFFBQUEsdUJBQXVCLEdBQUcsYUFBSztLQUN6QyxNQUFNLENBQUMsMkJBQTJCLEVBQUU7SUFDbkMsRUFBRSxFQUFFLGFBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxVQUFVLEVBQUU7SUFDM0IsYUFBYSxFQUFFLGFBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxNQUFNLEVBQUU7SUFDcEMsU0FBUyxFQUFFLGFBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxRQUFRLEVBQUU7Q0FDbkMsQ0FBQztLQUNELE9BQU8sQ0FBQztJQUNQO1FBQ0UsRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDO0tBQ3RCO0NBQ0YsQ0FBQyxDQUFDIn0=
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
declare const CollectionModuleService_base: import("@medusajs/framework/utils").MedusaServiceReturnType<import("@medusajs/framework/utils").ModelConfigurationsToConfigTemplate<{
|
|
2
|
+
readonly ProductCollectionCustom: import("@medusajs/framework/utils").DmlEntity<import("@medusajs/framework/utils").DMLEntitySchemaBuilder<{
|
|
3
|
+
id: import("@medusajs/framework/utils").PrimaryKeyModifier<string, import("@medusajs/framework/utils").IdProperty>;
|
|
4
|
+
collection_id: import("@medusajs/framework/utils").TextProperty;
|
|
5
|
+
thumbnail: import("@medusajs/framework/utils").NullableModifier<string, import("@medusajs/framework/utils").TextProperty>;
|
|
6
|
+
}>, "product_collection_custom">;
|
|
7
|
+
}>>;
|
|
8
|
+
export default class CollectionModuleService extends CollectionModuleService_base {
|
|
9
|
+
}
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
4
|
+
const collection_1 = require("./models/collection");
|
|
5
|
+
class CollectionModuleService extends (0, utils_1.MedusaService)({
|
|
6
|
+
ProductCollectionCustom: collection_1.ProductCollectionCustom,
|
|
7
|
+
}) {
|
|
8
|
+
}
|
|
9
|
+
exports.default = CollectionModuleService;
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2NvbGxlY3Rpb24vc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHFEQUEwRDtBQUMxRCxvREFBOEQ7QUFFOUQsTUFBcUIsdUJBQXdCLFNBQVEsSUFBQSxxQkFBYSxFQUFDO0lBQ2pFLHVCQUF1QixFQUF2QixvQ0FBdUI7Q0FDeEIsQ0FBQztDQUFHO0FBRkwsMENBRUsifQ==
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GcsDirectUploadService = void 0;
|
|
4
|
+
const storage_1 = require("@google-cloud/storage");
|
|
5
|
+
class GcsDirectUploadService {
|
|
6
|
+
storage;
|
|
7
|
+
bucketName;
|
|
8
|
+
baseUrl;
|
|
9
|
+
constructor() {
|
|
10
|
+
// Initialize GCS client with credentials from env
|
|
11
|
+
this.storage = new storage_1.Storage({
|
|
12
|
+
credentials: {
|
|
13
|
+
client_email: process.env.CLIENT_EMAIL,
|
|
14
|
+
private_key: process.env.PRIVATE_KEY.replace(/\\n/g, '\n'),
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
this.bucketName = process.env.BUCKET_NAME || 'sangaroon';
|
|
18
|
+
this.baseUrl = process.env.GCP_STORAGE_BASE_PUBLIC_URL || 'https://storage.googleapis.com';
|
|
19
|
+
}
|
|
20
|
+
async uploadFile(filename, buffer, mimeType) {
|
|
21
|
+
try {
|
|
22
|
+
const bucket = this.storage.bucket(this.bucketName);
|
|
23
|
+
const file = bucket.file(filename);
|
|
24
|
+
await file.save(buffer, {
|
|
25
|
+
metadata: {
|
|
26
|
+
contentType: mimeType,
|
|
27
|
+
},
|
|
28
|
+
public: true,
|
|
29
|
+
resumable: false,
|
|
30
|
+
});
|
|
31
|
+
// Return the public URL
|
|
32
|
+
return `${this.baseUrl}/${this.bucketName}/${filename}`;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.error('Error uploading to GCS:', error);
|
|
36
|
+
throw new Error(`Failed to upload file to GCS: ${error.message}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async deleteFile(filename) {
|
|
40
|
+
try {
|
|
41
|
+
const bucket = this.storage.bucket(this.bucketName);
|
|
42
|
+
const file = bucket.file(filename);
|
|
43
|
+
const [exists] = await file.exists();
|
|
44
|
+
if (exists) {
|
|
45
|
+
await file.delete();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error('Error deleting from GCS:', error);
|
|
50
|
+
// Don't throw on delete errors
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.GcsDirectUploadService = GcsDirectUploadService;
|
|
55
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2NzLWRpcmVjdC11cGxvYWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvZ2NzLWRpcmVjdC11cGxvYWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbURBQWdEO0FBRWhELE1BQWEsc0JBQXNCO0lBQ3pCLE9BQU8sQ0FBVTtJQUNqQixVQUFVLENBQVM7SUFDbkIsT0FBTyxDQUFTO0lBRXhCO1FBQ0Usa0RBQWtEO1FBQ2xELElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxpQkFBTyxDQUFDO1lBQ3pCLFdBQVcsRUFBRTtnQkFDWCxZQUFZLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFhO2dCQUN2QyxXQUFXLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFZLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUM7YUFDNUQ7U0FDRixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxJQUFJLFdBQVcsQ0FBQztRQUN6RCxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLElBQUksZ0NBQWdDLENBQUM7SUFDN0YsQ0FBQztJQUVELEtBQUssQ0FBQyxVQUFVLENBQUMsUUFBZ0IsRUFBRSxNQUFjLEVBQUUsUUFBZ0I7UUFDakUsSUFBSSxDQUFDO1lBQ0gsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3BELE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFFbkMsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDdEIsUUFBUSxFQUFFO29CQUNSLFdBQVcsRUFBRSxRQUFRO2lCQUN0QjtnQkFDRCxNQUFNLEVBQUUsSUFBSTtnQkFDWixTQUFTLEVBQUUsS0FBSzthQUNqQixDQUFDLENBQUM7WUFFSCx3QkFBd0I7WUFDeEIsT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLFVBQVUsSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUMxRCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMseUJBQXlCLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDaEQsTUFBTSxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDcEUsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsVUFBVSxDQUFDLFFBQWdCO1FBQy9CLElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNwRCxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBRW5DLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNyQyxJQUFJLE1BQU0sRUFBRSxDQUFDO2dCQUNYLE1BQU0sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3RCLENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsMEJBQTBCLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDakQsK0JBQStCO1FBQ2pDLENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUFyREQsd0RBcURDIn0=
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface UploadThumbnailInput {
|
|
2
|
+
collectionId: string;
|
|
3
|
+
fileData: {
|
|
4
|
+
filename: string;
|
|
5
|
+
mimeType: string;
|
|
6
|
+
content: string;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export declare const uploadCollectionThumbnailWorkflow: import("@medusajs/framework/workflows-sdk").ReturnWorkflow<UploadThumbnailInput, {
|
|
10
|
+
collectionId: string;
|
|
11
|
+
thumbnailUrl: string;
|
|
12
|
+
}, []>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uploadCollectionThumbnailWorkflow = void 0;
|
|
4
|
+
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
|
|
5
|
+
const gcs_direct_upload_1 = require("../services/gcs-direct-upload");
|
|
6
|
+
const uploadThumbnailStep = (0, workflows_sdk_1.createStep)("upload-thumbnail-step", async ({ collectionId, fileData }, { container }) => {
|
|
7
|
+
const collectionCustomService = container.resolve("collectionCustom");
|
|
8
|
+
const gcsUploadService = new gcs_direct_upload_1.GcsDirectUploadService();
|
|
9
|
+
// Generate unique filename for direct upload (no UUID folders)
|
|
10
|
+
const timestamp = Date.now();
|
|
11
|
+
const ext = fileData.filename.split('.').pop() || 'jpg';
|
|
12
|
+
const filename = `collections/thumbnail-${collectionId}-${timestamp}.${ext}`;
|
|
13
|
+
// Convert base64 to buffer
|
|
14
|
+
const buffer = Buffer.from(fileData.content, "base64");
|
|
15
|
+
// Upload directly to GCS without UUID folder
|
|
16
|
+
const publicUrl = await gcsUploadService.uploadFile(filename, buffer, fileData.mimeType);
|
|
17
|
+
const existingCustom = await collectionCustomService
|
|
18
|
+
.listProductCollectionCustoms({ collection_id: collectionId })
|
|
19
|
+
.then((result) => result[0]);
|
|
20
|
+
// Delete old thumbnail if it exists
|
|
21
|
+
if (existingCustom?.thumbnail) {
|
|
22
|
+
try {
|
|
23
|
+
// Extract filename from the URL
|
|
24
|
+
const oldUrl = existingCustom.thumbnail;
|
|
25
|
+
if (oldUrl.includes('storage.googleapis.com')) {
|
|
26
|
+
const parts = oldUrl.split('/');
|
|
27
|
+
const bucketIndex = parts.indexOf('sangaroon');
|
|
28
|
+
if (bucketIndex !== -1 && bucketIndex < parts.length - 1) {
|
|
29
|
+
const oldFilename = parts.slice(bucketIndex + 1).join('/');
|
|
30
|
+
await gcsUploadService.deleteFile(oldFilename);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.error('Failed to delete old thumbnail:', error);
|
|
36
|
+
// Continue even if deletion fails
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (existingCustom) {
|
|
40
|
+
await collectionCustomService.updateProductCollectionCustoms([{ id: existingCustom.id, thumbnail: publicUrl }]);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
await collectionCustomService.createProductCollectionCustoms([{
|
|
44
|
+
collection_id: collectionId,
|
|
45
|
+
thumbnail: publicUrl,
|
|
46
|
+
}]);
|
|
47
|
+
}
|
|
48
|
+
return new workflows_sdk_1.StepResponse({
|
|
49
|
+
collectionId,
|
|
50
|
+
thumbnailUrl: publicUrl,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
exports.uploadCollectionThumbnailWorkflow = (0, workflows_sdk_1.createWorkflow)("upload-collection-thumbnail", (input) => {
|
|
54
|
+
const result = uploadThumbnailStep(input);
|
|
55
|
+
return new workflows_sdk_1.WorkflowResponse(result);
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkLWNvbGxlY3Rpb24tdGh1bWJuYWlsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3dvcmtmbG93cy91cGxvYWQtY29sbGVjdGlvbi10aHVtYm5haWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBTTJDO0FBQzNDLHFFQUF1RTtBQVd2RSxNQUFNLG1CQUFtQixHQUFHLElBQUEsMEJBQVUsRUFDcEMsdUJBQXVCLEVBQ3ZCLEtBQUssRUFBRSxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQXdCLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO0lBQ3hFLE1BQU0sdUJBQXVCLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBUSxDQUFDO0lBQzdFLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSwwQ0FBc0IsRUFBRSxDQUFDO0lBRXRELCtEQUErRDtJQUMvRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDN0IsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksS0FBSyxDQUFDO0lBQ3hELE1BQU0sUUFBUSxHQUFHLHlCQUF5QixZQUFZLElBQUksU0FBUyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBRTdFLDJCQUEyQjtJQUMzQixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFFdkQsNkNBQTZDO0lBQzdDLE1BQU0sU0FBUyxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRXpGLE1BQU0sY0FBYyxHQUFHLE1BQU0sdUJBQXVCO1NBQ2pELDRCQUE0QixDQUFDLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxDQUFDO1NBQzdELElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFL0Isb0NBQW9DO0lBQ3BDLElBQUksY0FBYyxFQUFFLFNBQVMsRUFBRSxDQUFDO1FBQzlCLElBQUksQ0FBQztZQUNILGdDQUFnQztZQUNoQyxNQUFNLE1BQU0sR0FBRyxjQUFjLENBQUMsU0FBUyxDQUFDO1lBQ3hDLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyx3QkFBd0IsQ0FBQyxFQUFFLENBQUM7Z0JBQzlDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ2hDLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQy9DLElBQUksV0FBVyxLQUFLLENBQUMsQ0FBQyxJQUFJLFdBQVcsR0FBRyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUN6RCxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQzNELE1BQU0sZ0JBQWdCLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO2dCQUNqRCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsT0FBTyxDQUFDLEtBQUssQ0FBQyxpQ0FBaUMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN4RCxrQ0FBa0M7UUFDcEMsQ0FBQztJQUNILENBQUM7SUFFRCxJQUFJLGNBQWMsRUFBRSxDQUFDO1FBQ25CLE1BQU0sdUJBQXVCLENBQUMsOEJBQThCLENBQzFELENBQUMsRUFBRSxFQUFFLEVBQUUsY0FBYyxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FDbEQsQ0FBQztJQUNKLENBQUM7U0FBTSxDQUFDO1FBQ04sTUFBTSx1QkFBdUIsQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO2dCQUM1RCxhQUFhLEVBQUUsWUFBWTtnQkFDM0IsU0FBUyxFQUFFLFNBQVM7YUFDckIsQ0FBQyxDQUFDLENBQUM7SUFDTixDQUFDO0lBRUQsT0FBTyxJQUFJLDRCQUFZLENBQUM7UUFDdEIsWUFBWTtRQUNaLFlBQVksRUFBRSxTQUFTO0tBQ3hCLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FDRixDQUFDO0FBRVcsUUFBQSxpQ0FBaUMsR0FBRyxJQUFBLDhCQUFjLEVBQzdELDZCQUE2QixFQUM3QixDQUFDLEtBQXlDLEVBQUUsRUFBRTtJQUM1QyxNQUFNLE1BQU0sR0FBRyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMxQyxPQUFPLElBQUksZ0NBQWdCLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDdEMsQ0FBQyxDQUNGLENBQUMifQ==
|
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Medusa Collection Thumbnail Plugin
|
|
2
|
+
|
|
3
|
+
Collection thumbnail management plugin for Medusa v2.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Add custom thumbnail images to product collections
|
|
8
|
+
- Upload, update, and delete thumbnails
|
|
9
|
+
- GCS (Google Cloud Storage) integration
|
|
10
|
+
- Admin UI for managing collection thumbnails
|
|
11
|
+
- Widget integration on collection detail pages
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @lodashventure/medusa-collection-thumbnail
|
|
17
|
+
# or
|
|
18
|
+
yarn add @lodashventure/medusa-collection-thumbnail
|
|
19
|
+
# or
|
|
20
|
+
pnpm add @lodashventure/medusa-collection-thumbnail
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Configuration
|
|
24
|
+
|
|
25
|
+
Add to your `medusa-config.ts`:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
plugins: [
|
|
29
|
+
{
|
|
30
|
+
resolve: "@lodashventure/medusa-collection-thumbnail",
|
|
31
|
+
options: {},
|
|
32
|
+
},
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
modules: [
|
|
36
|
+
{
|
|
37
|
+
resolve: "@lodashventure/medusa-collection-thumbnail/modules/collection",
|
|
38
|
+
options: {},
|
|
39
|
+
},
|
|
40
|
+
]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Environment Variables
|
|
44
|
+
|
|
45
|
+
```env
|
|
46
|
+
CLIENT_EMAIL=your-gcs-client-email
|
|
47
|
+
PRIVATE_KEY=your-gcs-private-key
|
|
48
|
+
BUCKET_NAME=your-bucket-name
|
|
49
|
+
GCP_STORAGE_BASE_PUBLIC_URL=https://storage.googleapis.com
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## API Routes
|
|
53
|
+
|
|
54
|
+
### Admin Routes
|
|
55
|
+
|
|
56
|
+
- `GET /admin/collections/:id/thumbnail` - Get collection thumbnail
|
|
57
|
+
- `POST /admin/collections/:id/thumbnail` - Upload collection thumbnail
|
|
58
|
+
- `DELETE /admin/collections/:id/thumbnail` - Delete collection thumbnail
|
|
59
|
+
|
|
60
|
+
### Store Routes
|
|
61
|
+
|
|
62
|
+
- `GET /store/collections` - List collections with thumbnails
|
|
63
|
+
- `GET /store/collections/:id` - Get collection with thumbnail
|
|
64
|
+
|
|
65
|
+
## Admin UI
|
|
66
|
+
|
|
67
|
+
- Navigate to Collections to see thumbnail management
|
|
68
|
+
- Collection detail pages include a thumbnail widget
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lodashventure/medusa-collection-thumbnail",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Collection thumbnail management plugin for Medusa v2",
|
|
5
|
+
"author": "Lodashventure",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"medusa",
|
|
9
|
+
"medusa-plugin",
|
|
10
|
+
"collection",
|
|
11
|
+
"thumbnail",
|
|
12
|
+
"ecommerce"
|
|
13
|
+
],
|
|
14
|
+
"files": [
|
|
15
|
+
".medusa/server"
|
|
16
|
+
],
|
|
17
|
+
"exports": {
|
|
18
|
+
"./package.json": "./package.json",
|
|
19
|
+
"./workflows": "./.medusa/server/workflows/index.js",
|
|
20
|
+
"./.medusa/server/src/modules/*": "./.medusa/server/modules/*/index.js",
|
|
21
|
+
"./modules/*": "./.medusa/server/modules/*/index.js",
|
|
22
|
+
"./admin": "./.medusa/server/src/admin/index.mjs",
|
|
23
|
+
"./*": "./.medusa/server/*.js"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/lodashventure/medusa-collection-thumbnail"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "medusa plugin:build",
|
|
31
|
+
"dev": "medusa plugin:develop"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@google-cloud/storage": "^7.17.2",
|
|
35
|
+
"@medusajs/admin-sdk": "2.11.1",
|
|
36
|
+
"@medusajs/framework": "2.11.1",
|
|
37
|
+
"@medusajs/icons": "2.11.1",
|
|
38
|
+
"@medusajs/ui": "*"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@medusajs/admin-sdk": "2.11.1",
|
|
42
|
+
"@medusajs/framework": "2.11.1",
|
|
43
|
+
"@medusajs/icons": "2.11.1",
|
|
44
|
+
"@medusajs/medusa": "2.11.1",
|
|
45
|
+
"@medusajs/ui": "*",
|
|
46
|
+
"react": "^18.0.0",
|
|
47
|
+
"react-dom": "^18.0.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@medusajs/types": "2.11.1",
|
|
51
|
+
"@types/multer": "^2.0.0",
|
|
52
|
+
"@types/node": "^20.19.23",
|
|
53
|
+
"@types/react": "^18.3.2",
|
|
54
|
+
"@types/react-dom": "^18.2.25",
|
|
55
|
+
"ts-node": "^10.9.2",
|
|
56
|
+
"typescript": "^5.6.2"
|
|
57
|
+
}
|
|
58
|
+
}
|