@lodashventure/medusa-collection-thumbnail 1.1.4 → 1.1.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.
Files changed (34) hide show
  1. package/.medusa/server/src/admin/index.js +2 -177
  2. package/.medusa/server/src/admin/index.mjs +4 -179
  3. package/.medusa/server/src/api/admin/collections/[id]/thumbnail/route.js +211 -0
  4. package/.medusa/server/{api → src/api}/middlewares.js +1 -1
  5. package/.medusa/server/src/api/store/collections/[id]/route.js +43 -0
  6. package/.medusa/server/src/api/store/collections/route.js +71 -0
  7. package/.medusa/server/src/index.js +15 -0
  8. package/.medusa/server/{modules → src/modules}/collection/index.js +1 -1
  9. package/.medusa/server/{modules/collection/migrations/Migration20250921062957.js → src/modules/collection/migrations/Migration20251108000000.js} +4 -4
  10. package/.medusa/server/{modules → src/modules}/collection/models/collection.js +1 -1
  11. package/.medusa/server/{modules → src/modules}/collection/service.js +1 -1
  12. package/.medusa/server/src/services/gcs-direct-upload.js +56 -0
  13. package/.medusa/server/src/workflows/upload-collection-thumbnail.js +59 -0
  14. package/README.md +32 -34
  15. package/package.json +16 -16
  16. package/.medusa/server/api/admin/collections/[id]/thumbnail/route.d.ts +0 -8
  17. package/.medusa/server/api/admin/collections/[id]/thumbnail/route.js +0 -211
  18. package/.medusa/server/api/middlewares.d.ts +0 -2
  19. package/.medusa/server/api/store/collections/[id]/route.d.ts +0 -2
  20. package/.medusa/server/api/store/collections/[id]/route.js +0 -46
  21. package/.medusa/server/api/store/collections/route.d.ts +0 -2
  22. package/.medusa/server/api/store/collections/route.js +0 -71
  23. package/.medusa/server/index.d.ts +0 -2
  24. package/.medusa/server/index.js +0 -8
  25. package/.medusa/server/links/collection-thumbnail.d.ts +0 -2
  26. package/.medusa/server/links/collection-thumbnail.js +0 -16
  27. package/.medusa/server/modules/collection/index.d.ts +0 -21
  28. package/.medusa/server/modules/collection/migrations/Migration20250921062957.d.ts +0 -5
  29. package/.medusa/server/modules/collection/models/collection.d.ts +0 -5
  30. package/.medusa/server/modules/collection/service.d.ts +0 -10
  31. package/.medusa/server/services/gcs-direct-upload.d.ts +0 -8
  32. package/.medusa/server/services/gcs-direct-upload.js +0 -59
  33. package/.medusa/server/workflows/upload-collection-thumbnail.d.ts +0 -13
  34. package/.medusa/server/workflows/upload-collection-thumbnail.js +0 -59
@@ -0,0 +1,43 @@
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 collection from Medusa's default service
11
+ const collection = await productModuleService.retrieveProductCollection(id);
12
+ if (!collection) {
13
+ return res.status(404).json({ error: "Collection not found" });
14
+ }
15
+ // Retrieve custom data (thumbnail)
16
+ const customData = await collectionCustomService
17
+ .listProductCollectionCustoms({
18
+ collection_id: id,
19
+ })
20
+ .then((result) => result[0]);
21
+ // Enrich collection with thumbnail
22
+ const enrichedCollection = {
23
+ id: collection.id,
24
+ title: collection.title,
25
+ handle: collection.handle,
26
+ thumbnail: customData?.thumbnail || null,
27
+ created_at: collection.created_at,
28
+ updated_at: collection.updated_at,
29
+ };
30
+ return res.json({
31
+ collection: enrichedCollection,
32
+ });
33
+ }
34
+ catch (error) {
35
+ console.error("Error fetching collection:", error);
36
+ return res.status(500).json({
37
+ error: "Failed to fetch collection",
38
+ message: error.message
39
+ });
40
+ }
41
+ };
42
+ exports.GET = GET;
43
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2NvbGxlY3Rpb25zL1tpZF0vcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUEscURBQW9EO0FBRzdDLE1BQU0sR0FBRyxHQUFHLEtBQUssRUFDdEIsR0FBa0IsRUFDbEIsR0FBbUIsRUFDbkIsRUFBRTtJQUNGLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDO0lBQzFCLE1BQU0sb0JBQW9CLEdBQTBCLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUNuRSxlQUFPLENBQUMsT0FBTyxDQUNoQixDQUFDO0lBQ0YsTUFBTSx1QkFBdUIsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBUSxDQUFDO0lBRTdFLElBQUksQ0FBQztRQUNILG9EQUFvRDtRQUNwRCxNQUFNLFVBQVUsR0FBRyxNQUFNLG9CQUFvQixDQUFDLHlCQUF5QixDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRTVFLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNoQixPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLHNCQUFzQixFQUFFLENBQUMsQ0FBQztRQUNqRSxDQUFDO1FBRUQsbUNBQW1DO1FBQ25DLE1BQU0sVUFBVSxHQUFHLE1BQU0sdUJBQXVCO2FBQzdDLDRCQUE0QixDQUFDO1lBQzVCLGFBQWEsRUFBRSxFQUFFO1NBQ2xCLENBQUM7YUFDRCxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRS9CLG1DQUFtQztRQUNuQyxNQUFNLGtCQUFrQixHQUFHO1lBQ3pCLEVBQUUsRUFBRSxVQUFVLENBQUMsRUFBRTtZQUNqQixLQUFLLEVBQUUsVUFBVSxDQUFDLEtBQUs7WUFDdkIsTUFBTSxFQUFFLFVBQVUsQ0FBQyxNQUFNO1lBQ3pCLFNBQVMsRUFBRSxVQUFVLEVBQUUsU0FBUyxJQUFJLElBQUk7WUFDeEMsVUFBVSxFQUFFLFVBQVUsQ0FBQyxVQUFVO1lBQ2pDLFVBQVUsRUFBRSxVQUFVLENBQUMsVUFBVTtTQUNsQyxDQUFDO1FBRUYsT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDO1lBQ2QsVUFBVSxFQUFFLGtCQUFrQjtTQUMvQixDQUFDLENBQUM7SUFDTCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsNEJBQTRCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDbkQsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUMxQixLQUFLLEVBQUUsNEJBQTRCO1lBQ25DLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTztTQUN2QixDQUFDLENBQUM7SUFDTCxDQUFDO0FBQ0gsQ0FBQyxDQUFDO0FBN0NXLFFBQUEsR0FBRyxPQTZDZCJ9
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2NvbGxlY3Rpb25zL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUlBLHFEQUFvRDtBQUc3QyxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQ3RCLEdBQWtCLEVBQ2xCLEdBQW1CLEVBQ25CLEVBQUU7SUFDRixNQUFNLG9CQUFvQixHQUEwQixHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FDbkUsZUFBTyxDQUFDLE9BQU8sQ0FDaEIsQ0FBQztJQUNGLE1BQU0sdUJBQXVCLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsa0JBQWtCLENBQVEsQ0FBQztJQUU3RSxJQUFJLENBQUM7UUFDSCx5QkFBeUI7UUFDekIsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBZSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3hELE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekQsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFnQixDQUFDO1FBQzFDLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsVUFBaUIsQ0FBQztRQUMvQyxNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLFVBQWlCLENBQUM7UUFFL0MsZ0NBQWdDO1FBQ2hDLE1BQU0sT0FBTyxHQUFRLEVBQUUsQ0FBQztRQUN4QixJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1gsT0FBTyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDMUIsQ0FBQztRQUNELElBQUksVUFBVSxFQUFFLENBQUM7WUFDZixPQUFPLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUNsQyxDQUFDO1FBQ0QsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQ2xDLENBQUM7UUFFRCxxREFBcUQ7UUFDckQsTUFBTSxDQUFDLFdBQVcsRUFBRSxLQUFLLENBQUMsR0FBRyxNQUFNLG9CQUFvQixDQUFDLDhCQUE4QixDQUNwRixPQUFPLEVBQ1A7WUFDRSxJQUFJLEVBQUUsTUFBTTtZQUNaLElBQUksRUFBRSxLQUFLO1lBQ1gsS0FBSyxFQUFFLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRTtTQUM5QixDQUNGLENBQUM7UUFFRix5QkFBeUI7UUFDekIsTUFBTSxhQUFhLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUVqRCx3REFBd0Q7UUFDeEQsSUFBSSxhQUFhLEdBQWtDLEVBQUUsQ0FBQztRQUN0RCxJQUFJLGFBQWEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDN0IsTUFBTSxVQUFVLEdBQUcsTUFBTSx1QkFBdUIsQ0FBQyw0QkFBNEIsQ0FBQztnQkFDNUUsYUFBYSxFQUFFLGFBQWE7YUFDN0IsQ0FBQyxDQUFDO1lBRUgsZ0NBQWdDO1lBQ2hDLGFBQWEsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFO2dCQUNoRCxHQUFHLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUM7Z0JBQzdDLE9BQU8sR0FBRyxDQUFDO1lBQ2IsQ0FBQyxFQUFFLEVBQW1DLENBQUMsQ0FBQztRQUMxQyxDQUFDO1FBRUQscUNBQXFDO1FBQ3JDLE1BQU0sbUJBQW1CLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDekQsRUFBRSxFQUFFLFVBQVUsQ0FBQyxFQUFFO1lBQ2pCLEtBQUssRUFBRSxVQUFVLENBQUMsS0FBSztZQUN2QixNQUFNLEVBQUUsVUFBVSxDQUFDLE1BQU07WUFDekIsU0FBUyxFQUFFLGFBQWEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSTtZQUMvQyxVQUFVLEVBQUUsVUFBVSxDQUFDLFVBQVU7WUFDakMsVUFBVSxFQUFFLFVBQVUsQ0FBQyxVQUFVO1NBQ2xDLENBQUMsQ0FBQyxDQUFDO1FBRUosT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDO1lBQ2QsV0FBVyxFQUFFLG1CQUFtQjtZQUNoQyxLQUFLO1lBQ0wsTUFBTTtZQUNOLEtBQUs7U0FDTixDQUFDLENBQUM7SUFDTCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsNkJBQTZCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDcEQsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUMxQixLQUFLLEVBQUUsNkJBQTZCO1lBQ3BDLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTztTQUN2QixDQUFDLENBQUM7SUFDTCxDQUFDO0FBQ0gsQ0FBQyxDQUFDO0FBL0VXLFFBQUEsR0FBRyxPQStFZCJ9
@@ -0,0 +1,15 @@
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 = exports.CollectionModule = void 0;
7
+ const collection_1 = __importDefault(require("./modules/collection"));
8
+ exports.CollectionModule = collection_1.default;
9
+ // Export the module so MedusaJS can load it
10
+ exports.default = {
11
+ modules: [collection_1.default],
12
+ };
13
+ var collection_2 = require("./modules/collection");
14
+ Object.defineProperty(exports, "COLLECTION_MODULE", { enumerable: true, get: function () { return collection_2.COLLECTION_MODULE; } });
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsc0VBQW9EO0FBUTNDLDJCQVJGLG9CQUFnQixDQVFFO0FBTnpCLDRDQUE0QztBQUM1QyxrQkFBZTtJQUNiLE9BQU8sRUFBRSxDQUFDLG9CQUFnQixDQUFDO0NBQzVCLENBQUM7QUFJRixtREFBeUQ7QUFBaEQsK0dBQUEsaUJBQWlCLE9BQUEifQ==
@@ -10,4 +10,4 @@ exports.COLLECTION_MODULE = "collectionCustom";
10
10
  exports.default = (0, utils_1.Module)(exports.COLLECTION_MODULE, {
11
11
  service: service_1.default,
12
12
  });
13
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9jb2xsZWN0aW9uL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHFEQUFtRDtBQUNuRCx3REFBZ0Q7QUFFbkMsUUFBQSxpQkFBaUIsR0FBRyxrQkFBa0IsQ0FBQztBQUVwRCxrQkFBZSxJQUFBLGNBQU0sRUFBQyx5QkFBaUIsRUFBRTtJQUN2QyxPQUFPLEVBQUUsaUJBQXVCO0NBQ2pDLENBQUMsQ0FBQyJ9
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9jb2xsZWN0aW9uL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHFEQUFtRDtBQUNuRCx3REFBZ0Q7QUFFbkMsUUFBQSxpQkFBaUIsR0FBRyxrQkFBa0IsQ0FBQztBQUVwRCxrQkFBZSxJQUFBLGNBQU0sRUFBQyx5QkFBaUIsRUFBRTtJQUN2QyxPQUFPLEVBQUUsaUJBQXVCO0NBQ2pDLENBQUMsQ0FBQyJ9
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Migration20250921062957 = void 0;
3
+ exports.Migration20251108000000 = void 0;
4
4
  const migrations_1 = require("@medusajs/framework/mikro-orm/migrations");
5
- class Migration20250921062957 extends migrations_1.Migration {
5
+ class Migration20251108000000 extends migrations_1.Migration {
6
6
  async up() {
7
7
  this.addSql(`alter table if exists "product_collection_custom" drop constraint if exists "product_collection_custom_collection_id_unique";`);
8
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"));`);
@@ -14,5 +14,5 @@ class Migration20250921062957 extends migrations_1.Migration {
14
14
  this.addSql(`drop table if exists "product_collection_custom" cascade;`);
15
15
  }
16
16
  }
17
- exports.Migration20250921062957 = Migration20250921062957;
18
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWlncmF0aW9uMjAyNTA5MjEwNjI5NTcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9jb2xsZWN0aW9uL21pZ3JhdGlvbnMvTWlncmF0aW9uMjAyNTA5MjEwNjI5NTcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEseUVBQXFFO0FBRXJFLE1BQWEsdUJBQXdCLFNBQVEsc0JBQVM7SUFFM0MsS0FBSyxDQUFDLEVBQUU7UUFDZixJQUFJLENBQUMsTUFBTSxDQUFDLCtIQUErSCxDQUFDLENBQUM7UUFDN0ksSUFBSSxDQUFDLE1BQU0sQ0FBQyxxVUFBcVUsQ0FBQyxDQUFDO1FBQ25WLElBQUksQ0FBQyxNQUFNLENBQUMsaUtBQWlLLENBQUMsQ0FBQztRQUMvSyxJQUFJLENBQUMsTUFBTSxDQUFDLDZJQUE2SSxDQUFDLENBQUM7UUFDM0osSUFBSSxDQUFDLE1BQU0sQ0FBQyxtSkFBbUosQ0FBQyxDQUFDO0lBQ25LLENBQUM7SUFFUSxLQUFLLENBQUMsSUFBSTtRQUNqQixJQUFJLENBQUMsTUFBTSxDQUFDLDJEQUEyRCxDQUFDLENBQUM7SUFDM0UsQ0FBQztDQUVGO0FBZEQsMERBY0MifQ==
17
+ exports.Migration20251108000000 = Migration20251108000000;
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWlncmF0aW9uMjAyNTExMDgwMDAwMDAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9jb2xsZWN0aW9uL21pZ3JhdGlvbnMvTWlncmF0aW9uMjAyNTExMDgwMDAwMDAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEseUVBQXFFO0FBRXJFLE1BQWEsdUJBQXdCLFNBQVEsc0JBQVM7SUFFM0MsS0FBSyxDQUFDLEVBQUU7UUFDZixJQUFJLENBQUMsTUFBTSxDQUFDLCtIQUErSCxDQUFDLENBQUM7UUFDN0ksSUFBSSxDQUFDLE1BQU0sQ0FBQyxxVUFBcVUsQ0FBQyxDQUFDO1FBQ25WLElBQUksQ0FBQyxNQUFNLENBQUMsaUtBQWlLLENBQUMsQ0FBQztRQUMvSyxJQUFJLENBQUMsTUFBTSxDQUFDLDZJQUE2SSxDQUFDLENBQUM7UUFDM0osSUFBSSxDQUFDLE1BQU0sQ0FBQyxtSkFBbUosQ0FBQyxDQUFDO0lBQ25LLENBQUM7SUFFUSxLQUFLLENBQUMsSUFBSTtRQUNqQixJQUFJLENBQUMsTUFBTSxDQUFDLDJEQUEyRCxDQUFDLENBQUM7SUFDM0UsQ0FBQztDQUVGO0FBZEQsMERBY0MifQ==
@@ -13,4 +13,4 @@ exports.ProductCollectionCustom = utils_1.model
13
13
  on: ["collection_id"],
14
14
  },
15
15
  ]);
16
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2NvbGxlY3Rpb24vbW9kZWxzL2NvbGxlY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscURBQWtEO0FBRXJDLFFBQUEsdUJBQXVCLEdBQUcsYUFBSztLQUN6QyxNQUFNLENBQUMsMkJBQTJCLEVBQUU7SUFDbkMsRUFBRSxFQUFFLGFBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxVQUFVLEVBQUU7SUFDM0IsYUFBYSxFQUFFLGFBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxNQUFNLEVBQUU7SUFDcEMsU0FBUyxFQUFFLGFBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxRQUFRLEVBQUU7Q0FDbkMsQ0FBQztLQUNELE9BQU8sQ0FBQztJQUNQO1FBQ0UsRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDO0tBQ3RCO0NBQ0YsQ0FBQyxDQUFDIn0=
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2NvbGxlY3Rpb24vbW9kZWxzL2NvbGxlY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscURBQWtEO0FBRXJDLFFBQUEsdUJBQXVCLEdBQUcsYUFBSztLQUN6QyxNQUFNLENBQUMsMkJBQTJCLEVBQUU7SUFDbkMsRUFBRSxFQUFFLGFBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxVQUFVLEVBQUU7SUFDM0IsYUFBYSxFQUFFLGFBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxNQUFNLEVBQUU7SUFDcEMsU0FBUyxFQUFFLGFBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxRQUFRLEVBQUU7Q0FDbkMsQ0FBQztLQUNELE9BQU8sQ0FBQztJQUNQO1FBQ0UsRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDO0tBQ3RCO0NBQ0YsQ0FBQyxDQUFDIn0=
@@ -7,4 +7,4 @@ class CollectionModuleService extends (0, utils_1.MedusaService)({
7
7
  }) {
8
8
  }
9
9
  exports.default = CollectionModuleService;
10
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2NvbGxlY3Rpb24vc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHFEQUEwRDtBQUMxRCxvREFBOEQ7QUFFOUQsTUFBcUIsdUJBQXdCLFNBQVEsSUFBQSxxQkFBYSxFQUFDO0lBQ2pFLHVCQUF1QixFQUF2QixvQ0FBdUI7Q0FDeEIsQ0FBQztDQUFHO0FBRkwsMENBRUsifQ==
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2NvbGxlY3Rpb24vc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHFEQUEwRDtBQUMxRCxvREFBOEQ7QUFFOUQsTUFBcUIsdUJBQXdCLFNBQVEsSUFBQSxxQkFBYSxFQUFDO0lBQ2pFLHVCQUF1QixFQUF2QixvQ0FBdUI7Q0FDeEIsQ0FBQztDQUFHO0FBRkwsMENBRUsifQ==
@@ -0,0 +1,56 @@
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
+ constructor() {
7
+ // Initialize GCS client with credentials from env
8
+ this.storage = new storage_1.Storage({
9
+ credentials: {
10
+ client_email: process.env.CLIENT_EMAIL,
11
+ private_key: process.env.PRIVATE_KEY.replace(/\\n/g, '\n'),
12
+ },
13
+ });
14
+ this.bucketName = process.env.BUCKET_NAME || 'sangaroon';
15
+ this.baseUrl = (process.env.GCP_STORAGE_BASE_PUBLIC_URL || 'https://storage.cloud.google.com').replace(/\/+$/, '');
16
+ }
17
+ async uploadFile(filename, buffer, mimeType) {
18
+ try {
19
+ const bucket = this.storage.bucket(this.bucketName);
20
+ const file = bucket.file(filename);
21
+ await file.save(buffer, {
22
+ metadata: {
23
+ contentType: mimeType,
24
+ },
25
+ public: true,
26
+ resumable: false,
27
+ });
28
+ // Return the public URL
29
+ const sanitizedFilename = filename.replace(/^\/+/, '');
30
+ const baseWithBucket = this.baseUrl.endsWith(`/${this.bucketName}`)
31
+ ? this.baseUrl
32
+ : `${this.baseUrl}/${this.bucketName}`;
33
+ return `${baseWithBucket}/${sanitizedFilename}`;
34
+ }
35
+ catch (error) {
36
+ console.error('Error uploading to GCS:', error);
37
+ throw new Error(`Failed to upload file to GCS: ${error.message}`);
38
+ }
39
+ }
40
+ async deleteFile(filename) {
41
+ try {
42
+ const bucket = this.storage.bucket(this.bucketName);
43
+ const file = bucket.file(filename);
44
+ const [exists] = await file.exists();
45
+ if (exists) {
46
+ await file.delete();
47
+ }
48
+ }
49
+ catch (error) {
50
+ console.error('Error deleting from GCS:', error);
51
+ // Don't throw on delete errors
52
+ }
53
+ }
54
+ }
55
+ exports.GcsDirectUploadService = GcsDirectUploadService;
56
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2NzLWRpcmVjdC11cGxvYWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc2VydmljZXMvZ2NzLWRpcmVjdC11cGxvYWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbURBQWdEO0FBRWhELE1BQWEsc0JBQXNCO0lBS2pDO1FBQ0Usa0RBQWtEO1FBQ2xELElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxpQkFBTyxDQUFDO1lBQ3pCLFdBQVcsRUFBRTtnQkFDWCxZQUFZLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFhO2dCQUN2QyxXQUFXLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFZLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUM7YUFDNUQ7U0FDRixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxJQUFJLFdBQVcsQ0FBQztRQUN6RCxJQUFJLENBQUMsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQywyQkFBMkIsSUFBSSxrQ0FBa0MsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDckgsQ0FBQztJQUVELEtBQUssQ0FBQyxVQUFVLENBQUMsUUFBZ0IsRUFBRSxNQUFjLEVBQUUsUUFBZ0I7UUFDakUsSUFBSSxDQUFDO1lBQ0gsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3BELE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFFbkMsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDdEIsUUFBUSxFQUFFO29CQUNSLFdBQVcsRUFBRSxRQUFRO2lCQUN0QjtnQkFDRCxNQUFNLEVBQUUsSUFBSTtnQkFDWixTQUFTLEVBQUUsS0FBSzthQUNqQixDQUFDLENBQUM7WUFFSCx3QkFBd0I7WUFDeEIsTUFBTSxpQkFBaUIsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztZQUN2RCxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDakUsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPO2dCQUNkLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3pDLE9BQU8sR0FBRyxjQUFjLElBQUksaUJBQWlCLEVBQUUsQ0FBQztRQUNsRCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMseUJBQXlCLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDaEQsTUFBTSxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDcEUsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsVUFBVSxDQUFDLFFBQWdCO1FBQy9CLElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNwRCxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBRW5DLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNyQyxJQUFJLE1BQU0sRUFBRSxDQUFDO2dCQUNYLE1BQU0sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3RCLENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsMEJBQTBCLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDakQsK0JBQStCO1FBQ2pDLENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUF6REQsd0RBeURDIn0=
@@ -0,0 +1,59 @@
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
+ const isGcsUrl = oldUrl.includes("storage.googleapis.com") ||
26
+ oldUrl.includes("storage.cloud.google.com");
27
+ if (isGcsUrl) {
28
+ const parts = oldUrl.split('/');
29
+ const bucketIndex = parts.indexOf('sangaroon');
30
+ if (bucketIndex !== -1 && bucketIndex < parts.length - 1) {
31
+ const oldFilename = parts.slice(bucketIndex + 1).join('/');
32
+ await gcsUploadService.deleteFile(oldFilename);
33
+ }
34
+ }
35
+ }
36
+ catch (error) {
37
+ console.error('Failed to delete old thumbnail:', error);
38
+ // Continue even if deletion fails
39
+ }
40
+ }
41
+ if (existingCustom) {
42
+ await collectionCustomService.updateProductCollectionCustoms([{ id: existingCustom.id, thumbnail: publicUrl }]);
43
+ }
44
+ else {
45
+ await collectionCustomService.createProductCollectionCustoms([{
46
+ collection_id: collectionId,
47
+ thumbnail: publicUrl,
48
+ }]);
49
+ }
50
+ return new workflows_sdk_1.StepResponse({
51
+ collectionId,
52
+ thumbnailUrl: publicUrl,
53
+ });
54
+ });
55
+ exports.uploadCollectionThumbnailWorkflow = (0, workflows_sdk_1.createWorkflow)("upload-collection-thumbnail", (input) => {
56
+ const result = uploadThumbnailStep(input);
57
+ return new workflows_sdk_1.WorkflowResponse(result);
58
+ });
59
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkLWNvbGxlY3Rpb24tdGh1bWJuYWlsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy91cGxvYWQtY29sbGVjdGlvbi10aHVtYm5haWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBTTJDO0FBQzNDLHFFQUF1RTtBQVd2RSxNQUFNLG1CQUFtQixHQUFHLElBQUEsMEJBQVUsRUFDcEMsdUJBQXVCLEVBQ3ZCLEtBQUssRUFBRSxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQXdCLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO0lBQ3hFLE1BQU0sdUJBQXVCLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBUSxDQUFDO0lBQzdFLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSwwQ0FBc0IsRUFBRSxDQUFDO0lBRXRELCtEQUErRDtJQUMvRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDN0IsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksS0FBSyxDQUFDO0lBQ3hELE1BQU0sUUFBUSxHQUFHLHlCQUF5QixZQUFZLElBQUksU0FBUyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBRTdFLDJCQUEyQjtJQUMzQixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFFdkQsNkNBQTZDO0lBQzdDLE1BQU0sU0FBUyxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRXpGLE1BQU0sY0FBYyxHQUFHLE1BQU0sdUJBQXVCO1NBQ2pELDRCQUE0QixDQUFDLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxDQUFDO1NBQzdELElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFL0Isb0NBQW9DO0lBQ3BDLElBQUksY0FBYyxFQUFFLFNBQVMsRUFBRSxDQUFDO1FBQzlCLElBQUksQ0FBQztZQUNILGdDQUFnQztZQUNoQyxNQUFNLE1BQU0sR0FBRyxjQUFjLENBQUMsU0FBUyxDQUFDO1lBQ3hDLE1BQU0sUUFBUSxHQUNaLE1BQU0sQ0FBQyxRQUFRLENBQUMsd0JBQXdCLENBQUM7Z0JBQ3pDLE1BQU0sQ0FBQyxRQUFRLENBQUMsMEJBQTBCLENBQUMsQ0FBQztZQUM5QyxJQUFJLFFBQVEsRUFBRSxDQUFDO2dCQUNiLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ2hDLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQy9DLElBQUksV0FBVyxLQUFLLENBQUMsQ0FBQyxJQUFJLFdBQVcsR0FBRyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUN6RCxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQzNELE1BQU0sZ0JBQWdCLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO2dCQUNqRCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsT0FBTyxDQUFDLEtBQUssQ0FBQyxpQ0FBaUMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN4RCxrQ0FBa0M7UUFDcEMsQ0FBQztJQUNILENBQUM7SUFFRCxJQUFJLGNBQWMsRUFBRSxDQUFDO1FBQ25CLE1BQU0sdUJBQXVCLENBQUMsOEJBQThCLENBQzFELENBQUMsRUFBRSxFQUFFLEVBQUUsY0FBYyxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FDbEQsQ0FBQztJQUNKLENBQUM7U0FBTSxDQUFDO1FBQ04sTUFBTSx1QkFBdUIsQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO2dCQUM1RCxhQUFhLEVBQUUsWUFBWTtnQkFDM0IsU0FBUyxFQUFFLFNBQVM7YUFDckIsQ0FBQyxDQUFDLENBQUM7SUFDTixDQUFDO0lBRUQsT0FBTyxJQUFJLDRCQUFZLENBQUM7UUFDdEIsWUFBWTtRQUNaLFlBQVksRUFBRSxTQUFTO0tBQ3hCLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FDRixDQUFDO0FBRVcsUUFBQSxpQ0FBaUMsR0FBRyxJQUFBLDhCQUFjLEVBQzdELDZCQUE2QixFQUM3QixDQUFDLEtBQXlDLEVBQUUsRUFBRTtJQUM1QyxNQUFNLE1BQU0sR0FBRyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMxQyxPQUFPLElBQUksZ0NBQWdCLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDdEMsQ0FBQyxDQUNGLENBQUMifQ==
package/README.md CHANGED
@@ -1,71 +1,69 @@
1
1
  # Medusa Collection Thumbnail Plugin
2
2
 
3
- Collection thumbnail management plugin for Medusa v2.
3
+ Collection thumbnail management plugin for Medusa v2
4
4
 
5
5
  ## Features
6
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
7
+ - Upload, replace, and delete collection thumbnails
8
+ - Google Cloud Storage integration
9
+ - Admin UI widget with drag-and-drop upload
10
+ - Store API endpoints for fetching collections with thumbnails
11
+ - Automatic cleanup of old thumbnails
12
+ - ✅ File validation (5MB limit, images only)
12
13
 
13
14
  ## Installation
14
15
 
15
16
  ```bash
16
17
  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
18
  ```
22
19
 
23
20
  ## Configuration
24
21
 
25
- Add to your `medusa-config.ts`:
22
+ Add the plugin to your `medusa-config.js`:
26
23
 
27
- ```typescript
28
- plugins: [
24
+ ```javascript
25
+ const plugins = [
26
+ // ... other plugins
29
27
  {
30
28
  resolve: "@lodashventure/medusa-collection-thumbnail",
31
29
  options: {},
32
30
  },
33
- ]
34
-
35
- modules: [
36
- {
37
- resolve: "@lodashventure/medusa-collection-thumbnail/modules/collection",
38
- options: {},
39
- },
40
- ]
31
+ ];
41
32
  ```
42
33
 
43
- ### Environment Variables
34
+ ## Environment Variables
35
+
36
+ Required environment variables for Google Cloud Storage:
44
37
 
45
38
  ```env
46
- CLIENT_EMAIL=your-gcs-client-email
47
- PRIVATE_KEY=your-gcs-private-key
39
+ CLIENT_EMAIL=your-service-account@project.iam.gserviceaccount.com
40
+ PRIVATE_KEY=your-private-key
48
41
  BUCKET_NAME=your-bucket-name
49
42
  GCP_STORAGE_BASE_PUBLIC_URL=https://storage.cloud.google.com
50
43
  ```
51
44
 
52
- ## API Routes
45
+ ## API Endpoints
53
46
 
54
- ### Admin Routes
47
+ ### Admin Endpoints
55
48
 
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
49
+ - `GET /admin/collections/:id/thumbnail` - Fetch thumbnail for a collection
50
+ - `POST /admin/collections/:id/thumbnail` - Upload thumbnail (multipart or base64)
51
+ - `DELETE /admin/collections/:id/thumbnail` - Delete thumbnail
59
52
 
60
- ### Store Routes
53
+ ### Store Endpoints
61
54
 
62
55
  - `GET /store/collections` - List collections with thumbnails
63
- - `GET /store/collections/:id` - Get collection with thumbnail
56
+ - `GET /store/collections/:id` - Get single collection with thumbnail
57
+
58
+ ## Development
64
59
 
65
- ## Admin UI
60
+ ```bash
61
+ # Build the plugin
62
+ npm run build
66
63
 
67
- - Navigate to Collections to see thumbnail management
68
- - Collection detail pages include a thumbnail widget
64
+ # Watch mode for development
65
+ npm run dev
66
+ ```
69
67
 
70
68
  ## License
71
69
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodashventure/medusa-collection-thumbnail",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "Collection thumbnail management plugin for Medusa v2",
5
5
  "author": "Lodashventure",
6
6
  "license": "MIT",
@@ -32,11 +32,11 @@
32
32
  "prepublishOnly": "medusa plugin:build"
33
33
  },
34
34
  "dependencies": {
35
- "@google-cloud/storage": "^7.17.2",
36
- "@medusajs/admin-sdk": "2.11.2",
37
- "@medusajs/framework": "2.11.2",
38
- "@medusajs/icons": "2.11.2",
39
- "@medusajs/ui": "*",
35
+ "@google-cloud/storage": "^7.17.3",
36
+ "@medusajs/admin-sdk": "2.11.3",
37
+ "@medusajs/framework": "2.11.3",
38
+ "@medusajs/icons": "2.11.3",
39
+ "@medusajs/ui": "^4.0.27",
40
40
  "yalc": "1.0.0-pre.53"
41
41
  },
42
42
  "peerDependencies": {
@@ -49,17 +49,17 @@
49
49
  "react-dom": "^18.0.0"
50
50
  },
51
51
  "devDependencies": {
52
- "@medusajs/admin-shared": "2.11.2",
53
- "@medusajs/cli": "2.11.2",
54
- "@medusajs/medusa": "2.11.2",
55
- "@medusajs/types": "2.11.2",
56
- "@swc/core": "^1.5.7",
52
+ "@medusajs/admin-shared": "2.11.3",
53
+ "@medusajs/cli": "2.11.3",
54
+ "@medusajs/medusa": "2.11.3",
55
+ "@medusajs/types": "2.11.3",
56
+ "@swc/core": "^1.15.0",
57
57
  "@types/multer": "^2.0.0",
58
- "@types/node": "^20.19.23",
59
- "@types/react": "^18.3.2",
60
- "@types/react-dom": "^18.2.25",
58
+ "@types/node": "^24.10.0",
59
+ "@types/react": "^19.2.2",
60
+ "@types/react-dom": "^19.2.2",
61
61
  "ts-node": "^10.9.2",
62
- "typescript": "^5.6.2",
63
- "vite": "^5.2.11"
62
+ "typescript": "^5.9.3",
63
+ "vite": "^7.2.2"
64
64
  }
65
65
  }
@@ -1,8 +0,0 @@
1
- import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http";
2
- type MedusaRequestWithFile<TBody = unknown> = MedusaRequest<TBody> & {
3
- file?: Express.Multer.File;
4
- };
5
- export declare const GET: (req: MedusaRequest, res: MedusaResponse) => Promise<MedusaResponse>;
6
- export declare const POST: (req: MedusaRequestWithFile, res: MedusaResponse) => Promise<MedusaResponse>;
7
- export declare const DELETE: (req: MedusaRequest, res: MedusaResponse) => Promise<MedusaResponse>;
8
- export {};