@lodashventure/medusa-media-manager 0.1.1
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/src/admin/index.js +1376 -0
- package/.medusa/server/src/admin/index.mjs +1377 -0
- package/.medusa/server/src/api/admin/media/assets/[id]/route.js +50 -0
- package/.medusa/server/src/api/admin/media/assets/[id]/url/route.js +24 -0
- package/.medusa/server/src/api/admin/media/assets/route.js +53 -0
- package/.medusa/server/src/api/admin/media/assets/upload/route.js +67 -0
- package/.medusa/server/src/api/middlewares.js +53 -0
- package/.medusa/server/src/index.js +46 -0
- package/.medusa/server/src/modules/media-manager/index.js +13 -0
- package/.medusa/server/src/modules/media-manager/migrations/Migration20251104115419.js +83 -0
- package/.medusa/server/src/modules/media-manager/migrations/Migration20251104160000.js +15 -0
- package/.medusa/server/src/modules/media-manager/models/index.js +14 -0
- package/.medusa/server/src/modules/media-manager/models/media-models.js +201 -0
- package/.medusa/server/src/modules/media-manager/service.js +778 -0
- package/.medusa/server/src/providers/index.js +23 -0
- package/.medusa/server/src/providers/storage/azure.js +100 -0
- package/.medusa/server/src/providers/storage/factory.js +32 -0
- package/.medusa/server/src/providers/storage/gcs.js +91 -0
- package/.medusa/server/src/providers/storage/local.js +73 -0
- package/.medusa/server/src/providers/storage/s3.js +96 -0
- package/.medusa/server/src/providers/storage/types.js +3 -0
- package/.medusa/server/src/types/index.js +3 -0
- package/.medusa/server/src/workflows/index.js +4 -0
- package/README.md +85 -0
- package/package.json +82 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./storage/types"), exports);
|
|
18
|
+
__exportStar(require("./storage/local"), exports);
|
|
19
|
+
__exportStar(require("./storage/s3"), exports);
|
|
20
|
+
__exportStar(require("./storage/gcs"), exports);
|
|
21
|
+
__exportStar(require("./storage/azure"), exports);
|
|
22
|
+
__exportStar(require("./storage/factory"), exports);
|
|
23
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxrREFBZ0M7QUFDaEMsa0RBQWdDO0FBQ2hDLCtDQUE2QjtBQUM3QixnREFBOEI7QUFDOUIsa0RBQWdDO0FBQ2hDLG9EQUFrQyJ9
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AzureBlobStorageDriver = void 0;
|
|
4
|
+
const storage_blob_1 = require("@azure/storage-blob");
|
|
5
|
+
class AzureBlobStorageDriver {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.config = config;
|
|
8
|
+
if (!config.bucket) {
|
|
9
|
+
throw new Error("Azure storage driver requires a container name");
|
|
10
|
+
}
|
|
11
|
+
if (config.credentials?.connectionString) {
|
|
12
|
+
this.blobServiceClient = storage_blob_1.BlobServiceClient.fromConnectionString(config.credentials.connectionString);
|
|
13
|
+
}
|
|
14
|
+
else if (config.credentials?.accountName &&
|
|
15
|
+
config.credentials?.accountKey) {
|
|
16
|
+
const sharedKeyCredential = new storage_blob_1.StorageSharedKeyCredential(config.credentials.accountName, config.credentials.accountKey);
|
|
17
|
+
const url = `https://${config.credentials.accountName}.blob.core.windows.net`;
|
|
18
|
+
this.blobServiceClient = new storage_blob_1.BlobServiceClient(url, sharedKeyCredential);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
throw new Error("Azure storage driver requires either a connection string or accountName/accountKey credentials");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
get containerClient() {
|
|
25
|
+
return this.blobServiceClient.getContainerClient(this.config.bucket);
|
|
26
|
+
}
|
|
27
|
+
async ensureReady() {
|
|
28
|
+
await this.containerClient.createIfNotExists();
|
|
29
|
+
}
|
|
30
|
+
async upload(key, buffer, mimeType) {
|
|
31
|
+
await this.ensureReady();
|
|
32
|
+
const blockBlobClient = this.containerClient.getBlockBlobClient(key);
|
|
33
|
+
await blockBlobClient.uploadData(buffer, {
|
|
34
|
+
blobHTTPHeaders: {
|
|
35
|
+
blobContentType: mimeType,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
return {
|
|
39
|
+
key,
|
|
40
|
+
url: this.getPublicUrl(key),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
async delete(key) {
|
|
44
|
+
const blockBlobClient = this.containerClient.getBlockBlobClient(key);
|
|
45
|
+
await blockBlobClient.deleteIfExists();
|
|
46
|
+
}
|
|
47
|
+
async copy(sourceKey, targetKey) {
|
|
48
|
+
const sourceClient = this.containerClient.getBlockBlobClient(sourceKey);
|
|
49
|
+
const targetClient = this.containerClient.getBlockBlobClient(targetKey);
|
|
50
|
+
const sourceUrl = await this.getSignedUrl(sourceKey, {
|
|
51
|
+
expiresInSeconds: 900,
|
|
52
|
+
});
|
|
53
|
+
await targetClient.syncCopyFromURL(sourceUrl);
|
|
54
|
+
}
|
|
55
|
+
getPublicUrl(key) {
|
|
56
|
+
if (this.config.publicCdn) {
|
|
57
|
+
return `${this.config.publicCdn.replace(/\/+$/, "")}/${key}`;
|
|
58
|
+
}
|
|
59
|
+
if (this.config.baseUrl) {
|
|
60
|
+
return `${this.config.baseUrl.replace(/\/+$/, "")}/${key}`;
|
|
61
|
+
}
|
|
62
|
+
if (!this.config.credentials?.accountName || !this.config.bucket) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
return `https://${this.config.credentials.accountName}.blob.core.windows.net/${this.config.bucket}/${key}`;
|
|
66
|
+
}
|
|
67
|
+
async getSignedUrl(key, options) {
|
|
68
|
+
if (!this.config.signed?.enabled) {
|
|
69
|
+
const publicUrl = this.getPublicUrl(key);
|
|
70
|
+
if (!publicUrl) {
|
|
71
|
+
throw new Error("Signed URLs disabled and no public URL available for this asset");
|
|
72
|
+
}
|
|
73
|
+
return publicUrl;
|
|
74
|
+
}
|
|
75
|
+
if (!this.config.credentials?.accountName ||
|
|
76
|
+
!this.config.credentials?.accountKey) {
|
|
77
|
+
throw new Error("Signed URLs for Azure require accountName and accountKey credentials");
|
|
78
|
+
}
|
|
79
|
+
const sharedKeyCredential = new storage_blob_1.StorageSharedKeyCredential(this.config.credentials.accountName, this.config.credentials.accountKey);
|
|
80
|
+
const permissions = storage_blob_1.BlobSASPermissions.parse("r");
|
|
81
|
+
const expiresOn = new Date(Date.now() +
|
|
82
|
+
(options?.expiresInSeconds ?? this.config.signed.ttlSeconds ?? 3600) *
|
|
83
|
+
1000);
|
|
84
|
+
const sasToken = (0, storage_blob_1.generateBlobSASQueryParameters)({
|
|
85
|
+
containerName: this.config.bucket,
|
|
86
|
+
blobName: key,
|
|
87
|
+
permissions,
|
|
88
|
+
expiresOn,
|
|
89
|
+
protocol: storage_blob_1.SASProtocol.Https,
|
|
90
|
+
}, sharedKeyCredential).toString();
|
|
91
|
+
const baseUrl = this.getPublicUrl(key) ??
|
|
92
|
+
`https://${this.config.credentials.accountName}.blob.core.windows.net/${this.config.bucket}/${key}`;
|
|
93
|
+
return `${baseUrl}?${sasToken}`;
|
|
94
|
+
}
|
|
95
|
+
getConfig() {
|
|
96
|
+
return this.config;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.AzureBlobStorageDriver = AzureBlobStorageDriver;
|
|
100
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXp1cmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3N0b3JhZ2UvYXp1cmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsc0RBTTZCO0FBUTdCLE1BQWEsc0JBQXNCO0lBR2pDLFlBQTZCLE1BQWlDO1FBQWpDLFdBQU0sR0FBTixNQUFNLENBQTJCO1FBQzVELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDbkIsTUFBTSxJQUFJLEtBQUssQ0FBQyxnREFBZ0QsQ0FBQyxDQUFDO1FBQ3BFLENBQUM7UUFFRCxJQUFJLE1BQU0sQ0FBQyxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQztZQUN6QyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsZ0NBQWlCLENBQUMsb0JBQW9CLENBQzdELE1BQU0sQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLENBQ3BDLENBQUM7UUFDSixDQUFDO2FBQU0sSUFDTCxNQUFNLENBQUMsV0FBVyxFQUFFLFdBQVc7WUFDL0IsTUFBTSxDQUFDLFdBQVcsRUFBRSxVQUFVLEVBQzlCLENBQUM7WUFDRCxNQUFNLG1CQUFtQixHQUFHLElBQUkseUNBQTBCLENBQ3hELE1BQU0sQ0FBQyxXQUFXLENBQUMsV0FBVyxFQUM5QixNQUFNLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FDOUIsQ0FBQztZQUNGLE1BQU0sR0FBRyxHQUFHLFdBQVcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxXQUFXLHdCQUF3QixDQUFDO1lBQzlFLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLGdDQUFpQixDQUFDLEdBQUcsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO1FBQzNFLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxJQUFJLEtBQUssQ0FDYixnR0FBZ0csQ0FDakcsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQsSUFBWSxlQUFlO1FBQ3pCLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFD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
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createStorageDriver = createStorageDriver;
|
|
4
|
+
const azure_1 = require("./azure");
|
|
5
|
+
const gcs_1 = require("./gcs");
|
|
6
|
+
const local_1 = require("./local");
|
|
7
|
+
const s3_1 = require("./s3");
|
|
8
|
+
function createStorageDriver(config) {
|
|
9
|
+
switch (config.driver) {
|
|
10
|
+
case "local":
|
|
11
|
+
return new local_1.LocalStorageDriver(config);
|
|
12
|
+
case "s3":
|
|
13
|
+
return new s3_1.S3StorageDriver(config);
|
|
14
|
+
case "r2": {
|
|
15
|
+
const endpoint = config.endpoint ??
|
|
16
|
+
(config.region
|
|
17
|
+
? `https://${config.region}.r2.cloudflarestorage.com`
|
|
18
|
+
: undefined);
|
|
19
|
+
return new s3_1.S3StorageDriver({
|
|
20
|
+
...config,
|
|
21
|
+
endpoint,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
case "gcs":
|
|
25
|
+
return new gcs_1.GcsStorageDriver(config);
|
|
26
|
+
case "azure":
|
|
27
|
+
return new azure_1.AzureBlobStorageDriver(config);
|
|
28
|
+
default:
|
|
29
|
+
throw new Error(`Unsupported storage driver: ${config.driver}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9wcm92aWRlcnMvc3RvcmFnZS9mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBT0Esa0RBMEJDO0FBaENELG1DQUFpRDtBQUNqRCwrQkFBeUM7QUFDekMsbUNBQTZDO0FBQzdDLDZCQUF1QztBQUd2QyxTQUFnQixtQkFBbUIsQ0FDakMsTUFBaUM7SUFFakMsUUFBUSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDdEIsS0FBSyxPQUFPO1lBQ1YsT0FBTyxJQUFJLDBCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3hDLEtBQUssSUFBSTtZQUNQLE9BQU8sSUFBSSxvQkFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3JDLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNWLE1BQU0sUUFBUSxHQUNaLE1BQU0sQ0FBQyxRQUFRO2dCQUNmLENBQUMsTUFBTSxDQUFDLE1BQU07b0JBQ1osQ0FBQyxDQUFDLFdBQVcsTUFBTSxDQUFDLE1BQU0sMkJBQTJCO29CQUNyRCxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDakIsT0FBTyxJQUFJLG9CQUFlLENBQUM7Z0JBQ3pCLEdBQUcsTUFBTTtnQkFDVCxRQUFRO2FBQ1QsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUNELEtBQUssS0FBSztZQUNSLE9BQU8sSUFBSSxzQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN0QyxLQUFLLE9BQU87WUFDVixPQUFPLElBQUksOEJBQXNCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDNUM7WUFDRSxNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUNwRSxDQUFDO0FBQ0gsQ0FBQyJ9
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GcsStorageDriver = void 0;
|
|
4
|
+
const storage_1 = require("@google-cloud/storage");
|
|
5
|
+
class GcsStorageDriver {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.config = config;
|
|
8
|
+
if (!config.bucket) {
|
|
9
|
+
throw new Error("GCS storage driver requires a bucket");
|
|
10
|
+
}
|
|
11
|
+
this.storage = new storage_1.Storage({
|
|
12
|
+
projectId: config.region,
|
|
13
|
+
credentials: config.credentials
|
|
14
|
+
? {
|
|
15
|
+
client_email: config.credentials.clientEmail,
|
|
16
|
+
private_key: config.credentials.privateKey,
|
|
17
|
+
}
|
|
18
|
+
: undefined,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
async ensureReady() {
|
|
22
|
+
const [exists] = await this.storage.bucket(this.config.bucket).exists();
|
|
23
|
+
if (!exists) {
|
|
24
|
+
await this.storage.bucket(this.config.bucket).create();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
file(key) {
|
|
28
|
+
return this.storage.bucket(this.config.bucket).file(key);
|
|
29
|
+
}
|
|
30
|
+
async upload(key, buffer, mimeType) {
|
|
31
|
+
const file = this.file(key);
|
|
32
|
+
await file.save(buffer, {
|
|
33
|
+
contentType: mimeType,
|
|
34
|
+
resumable: false,
|
|
35
|
+
});
|
|
36
|
+
if (!this.config.signed?.enabled) {
|
|
37
|
+
try {
|
|
38
|
+
await file.makePublic();
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
if (err?.code !== 400) {
|
|
42
|
+
console.warn("medusa-media-manager: failed to make GCS object public:", err?.message ?? err);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
key,
|
|
48
|
+
url: this.getPublicUrl(key),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
async delete(key) {
|
|
52
|
+
await this.file(key).delete({ ignoreNotFound: true });
|
|
53
|
+
}
|
|
54
|
+
async copy(sourceKey, targetKey) {
|
|
55
|
+
await this.file(sourceKey).copy(this.file(targetKey));
|
|
56
|
+
}
|
|
57
|
+
getPublicUrl(key) {
|
|
58
|
+
if (this.config.publicCdn) {
|
|
59
|
+
return `${this.config.publicCdn.replace(/\/+$/, "")}/${key}`;
|
|
60
|
+
}
|
|
61
|
+
if (this.config.baseUrl) {
|
|
62
|
+
return `${this.config.baseUrl.replace(/\/+$/, "")}/${key}`;
|
|
63
|
+
}
|
|
64
|
+
if (!this.config.bucket) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return `https://storage.googleapis.com/${this.config.bucket}/${key}`;
|
|
68
|
+
}
|
|
69
|
+
async getSignedUrl(key, options) {
|
|
70
|
+
if (!this.config.signed?.enabled) {
|
|
71
|
+
const publicUrl = this.getPublicUrl(key);
|
|
72
|
+
if (!publicUrl) {
|
|
73
|
+
throw new Error("Signed URLs disabled and no public URL available for this asset");
|
|
74
|
+
}
|
|
75
|
+
return publicUrl;
|
|
76
|
+
}
|
|
77
|
+
const expires = Date.now() +
|
|
78
|
+
(options?.expiresInSeconds ?? this.config.signed.ttlSeconds ?? 3600) *
|
|
79
|
+
1000;
|
|
80
|
+
const [url] = await this.file(key).getSignedUrl({
|
|
81
|
+
action: "read",
|
|
82
|
+
expires,
|
|
83
|
+
});
|
|
84
|
+
return url;
|
|
85
|
+
}
|
|
86
|
+
getConfig() {
|
|
87
|
+
return this.config;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.GcsStorageDriver = GcsStorageDriver;
|
|
91
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2NzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy9zdG9yYWdlL2djcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxtREFBZ0Q7QUFRaEQsTUFBYSxnQkFBZ0I7SUFHM0IsWUFBNkIsTUFBaUM7UUFBakMsV0FBTSxHQUFOLE1BQU0sQ0FBMkI7UUFDNUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNuQixNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7UUFDMUQsQ0FBQztRQUVELElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxpQkFBTyxDQUFDO1lBQ3pCLFNBQVMsRUFBRSxNQUFNLENBQUMsTUFBTTtZQUN4QixXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQVc7Z0JBQzdCLENBQUMsQ0FBQztvQkFDRSxZQUFZLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxXQUFXO29CQUM1QyxXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxVQUFVO2lCQUMzQztnQkFDSCxDQUFDLENBQUMsU0FBUztTQUNkLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsV0FBVztRQUNmLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDekUsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ1osTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU8sQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzFELENBQUM7SUFDSCxDQUFDO0lBRU8sSUFBSSxDQUFDLEdBQVc7UUFDdEIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENB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
|
|
@@ -0,0 +1,73 @@
|
|
|
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.LocalStorageDriver = void 0;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
10
|
+
const DEFAULT_LOCAL_MEDIA_DIR = "uploads/media";
|
|
11
|
+
class LocalStorageDriver {
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.config = config;
|
|
14
|
+
const basePath = this.config.baseUrl ||
|
|
15
|
+
path_1.default.join(process.cwd(), DEFAULT_LOCAL_MEDIA_DIR);
|
|
16
|
+
this.rootPath = path_1.default.resolve(basePath);
|
|
17
|
+
}
|
|
18
|
+
async ensureReady() {
|
|
19
|
+
await fs_1.promises.mkdir(this.rootPath, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
resolveKey(key) {
|
|
22
|
+
const normalized = key.replace(/^\/*/, "");
|
|
23
|
+
return path_1.default.join(this.rootPath, normalized);
|
|
24
|
+
}
|
|
25
|
+
async upload(key, buffer, mimeType) {
|
|
26
|
+
await this.ensureReady();
|
|
27
|
+
const targetPath = this.resolveKey(key);
|
|
28
|
+
await fs_1.promises.mkdir(path_1.default.dirname(targetPath), { recursive: true });
|
|
29
|
+
await fs_1.promises.writeFile(targetPath, buffer);
|
|
30
|
+
const etag = crypto_1.default.createHash("md5").update(buffer).digest("hex");
|
|
31
|
+
return {
|
|
32
|
+
key,
|
|
33
|
+
etag,
|
|
34
|
+
url: this.getPublicUrl(key),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
async delete(key) {
|
|
38
|
+
const targetPath = this.resolveKey(key);
|
|
39
|
+
try {
|
|
40
|
+
await fs_1.promises.unlink(targetPath);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
if (err.code !== "ENOENT") {
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async copy(sourceKey, targetKey) {
|
|
49
|
+
await this.ensureReady();
|
|
50
|
+
const sourcePath = this.resolveKey(sourceKey);
|
|
51
|
+
const targetPath = this.resolveKey(targetKey);
|
|
52
|
+
await fs_1.promises.mkdir(path_1.default.dirname(targetPath), { recursive: true });
|
|
53
|
+
await fs_1.promises.copyFile(sourcePath, targetPath);
|
|
54
|
+
}
|
|
55
|
+
getPublicUrl(key) {
|
|
56
|
+
if (this.config.publicCdn) {
|
|
57
|
+
return `${this.config.publicCdn.replace(/\/+$/, "")}/${key}`;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
async getSignedUrl(key, _options) {
|
|
62
|
+
const publicUrl = this.getPublicUrl(key);
|
|
63
|
+
if (!publicUrl) {
|
|
64
|
+
throw new Error("Signed URLs are not available for local storage without a public CDN configuration");
|
|
65
|
+
}
|
|
66
|
+
return publicUrl;
|
|
67
|
+
}
|
|
68
|
+
getConfig() {
|
|
69
|
+
return this.config;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.LocalStorageDriver = LocalStorageDriver;
|
|
73
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9jYWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3N0b3JhZ2UvbG9jYWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsMkJBQW9DO0FBQ3BDLGdEQUF3QjtBQUN4QixvREFBNEI7QUFRNUIsTUFBTSx1QkFBdUIsR0FBRyxlQUFlLENBQUM7QUFFaEQsTUFBYSxrQkFBa0I7SUFHN0IsWUFBNkIsTUFBaUM7UUFBakMsV0FBTSxHQUFOLE1BQU0sQ0FBMkI7UUFDNUQsTUFBTSxRQUFRLEdBQ1osSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPO1lBQ25CLGNBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLHVCQUF1QixDQUFDLENBQUM7UUFDcEQsSUFBSSxDQUFDLFFBQVEsR0FBRyxjQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFRCxLQUFLLENBQUMsV0FBVztRQUNmLE1BQU0sYUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUVPLFVBQVUsQ0FBQyxHQUFXO1FBQzVCLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzNDLE9BQU8sY0FBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFFRCxLQUFLLENBQUMsTUFBTSxDQUNWLEdBQVcsRUFDWCxNQUFjLEVBQ2QsUUFBZ0I7UUFFaEIsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDekIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN4QyxNQUFNLGFBQUUsQ0FBQyxLQUFLLENBQUMsY0FBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzlELE1BQU0sYUFBRSxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDdkMsTUFBTSxJQUFJLEdBQUcsZ0JBQU0sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuRSxPQUFPO1lBQ0wsR0FBRztZQUNILElBQUk7WUFDSixHQUFHLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUM7U0FDNUIsQ0FBQztJQUNKLENBQUM7SUFFRCxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQVc7UUFDdEIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN4QyxJQUFJLENBQUM7WUFDSCxNQUFNLGFBQUUsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDOUIsQ0FBQztRQUFDLE9BQU8sR0FBUSxFQUFFLENBQUM7WUFDbEIsSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO2dCQUMxQixNQUFNLEdBQUcsQ0FBQztZQUNaLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBaUIsRUFBRSxTQUFpQjtRQUM3QyxNQUFNLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN6QixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzlDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDOUMsTUFBTSxhQUFFLENBQUMsS0FBSyxDQUFDLGNBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUM5RCxNQUFNLGFBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRCxZQUFZLENBQUMsR0FBVztRQUN0QixJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDMUIsT0FBTyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7UUFDL0QsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELEtBQUssQ0FBQyxZQUFZLENBQ2hCLEdBQVcsRUFDWCxRQUFrQztRQUVsQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNmLE1BQU0sSUFBSSxLQUFLLENBQ2Isb0ZBQW9GLENBQ3JGLENBQUM7UUFDSixDQUFDO1FBQ0QsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELFNBQVM7UUFDUCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDckIsQ0FBQztDQUNGO0FBOUVELGdEQThFQyJ9
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.S3StorageDriver = void 0;
|
|
4
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
5
|
+
const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
|
|
6
|
+
class S3StorageDriver {
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this.config = config;
|
|
9
|
+
const { region, credentials } = config;
|
|
10
|
+
if (!config.bucket) {
|
|
11
|
+
throw new Error("S3 storage driver requires a bucket");
|
|
12
|
+
}
|
|
13
|
+
const clientConfig = {
|
|
14
|
+
region: region ?? "us-east-1",
|
|
15
|
+
endpoint: config.endpoint,
|
|
16
|
+
forcePathStyle: Boolean(config.endpoint),
|
|
17
|
+
};
|
|
18
|
+
if (credentials?.accessKeyId &&
|
|
19
|
+
credentials?.secretAccessKey) {
|
|
20
|
+
clientConfig.credentials = {
|
|
21
|
+
accessKeyId: credentials.accessKeyId,
|
|
22
|
+
secretAccessKey: credentials.secretAccessKey,
|
|
23
|
+
...(credentials.sessionToken
|
|
24
|
+
? { sessionToken: credentials.sessionToken }
|
|
25
|
+
: {}),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
this.client = new client_s3_1.S3Client(clientConfig);
|
|
29
|
+
}
|
|
30
|
+
async ensureReady() {
|
|
31
|
+
// No-op: bucket is assumed to exist
|
|
32
|
+
}
|
|
33
|
+
async upload(key, buffer, mimeType) {
|
|
34
|
+
await this.client.send(new client_s3_1.PutObjectCommand({
|
|
35
|
+
Bucket: this.config.bucket,
|
|
36
|
+
Key: key,
|
|
37
|
+
Body: buffer,
|
|
38
|
+
ContentType: mimeType,
|
|
39
|
+
}));
|
|
40
|
+
return {
|
|
41
|
+
key,
|
|
42
|
+
url: this.getPublicUrl(key),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async delete(key) {
|
|
46
|
+
await this.client.send(new client_s3_1.DeleteObjectCommand({
|
|
47
|
+
Bucket: this.config.bucket,
|
|
48
|
+
Key: key,
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
async copy(sourceKey, targetKey) {
|
|
52
|
+
await this.client.send(new client_s3_1.CopyObjectCommand({
|
|
53
|
+
Bucket: this.config.bucket,
|
|
54
|
+
Key: targetKey,
|
|
55
|
+
CopySource: `${this.config.bucket}/${sourceKey}`,
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
getPublicUrl(key) {
|
|
59
|
+
if (this.config.publicCdn) {
|
|
60
|
+
return `${this.config.publicCdn.replace(/\/+$/, "")}/${key}`;
|
|
61
|
+
}
|
|
62
|
+
if (this.config.baseUrl) {
|
|
63
|
+
return `${this.config.baseUrl.replace(/\/+$/, "")}/${key}`;
|
|
64
|
+
}
|
|
65
|
+
if (this.config.endpoint) {
|
|
66
|
+
return `${this.config.endpoint.replace(/\/+$/, "")}/${this.config.bucket}/${key}`;
|
|
67
|
+
}
|
|
68
|
+
if (!this.config.bucket) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
const regionSegment = this.config.region
|
|
72
|
+
? `.${this.config.region}`
|
|
73
|
+
: "";
|
|
74
|
+
return `https://${this.config.bucket}.s3${regionSegment}.amazonaws.com/${key}`;
|
|
75
|
+
}
|
|
76
|
+
async getSignedUrl(key, options) {
|
|
77
|
+
if (!this.config.signed?.enabled) {
|
|
78
|
+
const publicUrl = this.getPublicUrl(key);
|
|
79
|
+
if (!publicUrl) {
|
|
80
|
+
throw new Error("Signed URLs disabled and no public URL available for this asset");
|
|
81
|
+
}
|
|
82
|
+
return publicUrl;
|
|
83
|
+
}
|
|
84
|
+
const command = new client_s3_1.GetObjectCommand({
|
|
85
|
+
Bucket: this.config.bucket,
|
|
86
|
+
Key: key,
|
|
87
|
+
});
|
|
88
|
+
const ttl = options?.expiresInSeconds ?? this.config.signed.ttlSeconds ?? 3600;
|
|
89
|
+
return (0, s3_request_presigner_1.getSignedUrl)(this.client, command, { expiresIn: ttl });
|
|
90
|
+
}
|
|
91
|
+
getConfig() {
|
|
92
|
+
return this.config;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.S3StorageDriver = S3StorageDriver;
|
|
96
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiczMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3N0b3JhZ2UvczMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsa0RBTTRCO0FBQzVCLHdFQUE2RDtBQVE3RCxNQUFhLGVBQWU7SUFHMUIsWUFBNkIsTUFBaUM7UUFBakMsV0FBTSxHQUFOLE1BQU0sQ0FBMkI7UUFDNUQsTUFBTSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsR0FBRyxNQUFNLENBQUM7UUFDdkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNuQixNQUFNLElBQUksS0FBSyxDQUFDLHFDQUFxQyxDQUFDLENBQUM7UUFDekQsQ0FBQztRQUVELE1BQU0sWUFBWSxHQUE0QjtZQUM1QyxNQUFNLEVBQUUsTUFBTSxJQUFJLFdBQVc7WUFDN0IsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRO1lBQ3pCLGNBQWMsRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQztTQUN6QyxDQUFDO1FBRUYsSUFDRSxXQUFXLEVBQUUsV0FBVztZQUN4QixXQUFXLEVBQUUsZUFBZSxFQUM1QixDQUFDO1lBQ0QsWUFBWSxDQUFDLFdBQVcsR0FBRztnQkFDekIsV0FBVyxFQUFFLFdBQVcsQ0FBQyxXQUFXO2dCQUNwQyxlQUFlLEVBQUUsV0FBVyxDQUFDLGVBQWU7Z0JBQzVDLEdBQUcsQ0FBQyxXQUFXLENBQUMsWUFBWTtvQkFDMUIsQ0FBQyxDQUFDLEVBQUUsWUFBWSxFQUFFLFdBQVcsQ0FBQyxZQUFZLEVBQUU7b0JBQzVDLENBQUMsQ0FBQyxFQUFFLENBQUM7YUFDUixDQUFDO1FBQ0osQ0FBQztRQUVELElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxvQkFBUSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFRCxLQUFLLENBQUMsV0FBVztRQUNmLG9DQUFvQztJQUN0QyxDQUFDO0lBRUQsS0FBSyxDQUFD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
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3N0b3JhZ2UvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdHlwZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// Workflows will be implemented in a future iteration.
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsdURBQXVEIn0=
|
package/README.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Medusa Media Manager Plugin
|
|
2
|
+
|
|
3
|
+
This experimental plugin adds a Strapi-inspired media management experience to Medusa v2.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Unified media library with assets, folders, tags, relations, and activity logs.
|
|
8
|
+
- Pluggable storage adapters (Local, S3/R2, GCS, Azure Blob) with signed URL support.
|
|
9
|
+
- Image processing pipeline powered by Sharp for responsive variants.
|
|
10
|
+
- RESTful admin endpoints for upload, metadata updates, relations, and deletion safeguards.
|
|
11
|
+
- Typed service API (`MEDIA_MANAGER_MODULE`) for workflows and module integrations.
|
|
12
|
+
|
|
13
|
+
## Getting Started
|
|
14
|
+
|
|
15
|
+
Install dependencies and build the plugin:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm install --prefer-offline
|
|
19
|
+
pnpm run build
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or with Yarn:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
yarn install --check-files
|
|
26
|
+
yarn build
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Configure
|
|
30
|
+
|
|
31
|
+
Add the plugin to `medusa-config.js`:
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
plugins: [
|
|
35
|
+
{
|
|
36
|
+
resolve: "medusa-media-manager",
|
|
37
|
+
options: {
|
|
38
|
+
storage: {
|
|
39
|
+
driver: "s3",
|
|
40
|
+
bucket: process.env.MEDIA_BUCKET,
|
|
41
|
+
region: process.env.MEDIA_REGION,
|
|
42
|
+
publicCdn: process.env.MEDIA_CDN,
|
|
43
|
+
signed: { enabled: true, ttlSeconds: 3600 },
|
|
44
|
+
},
|
|
45
|
+
presets: [
|
|
46
|
+
{ name: "thumbnail", width: 200, height: 200, fit: "cover" },
|
|
47
|
+
{ name: "small", width: 640 },
|
|
48
|
+
{ name: "medium", width: 1024 },
|
|
49
|
+
{ name: "large", width: 1600 },
|
|
50
|
+
],
|
|
51
|
+
generate: { mode: "eager" },
|
|
52
|
+
svg: { sanitize: true },
|
|
53
|
+
moderation: { enabled: true },
|
|
54
|
+
rbac: { deleteRequiresNoUsage: true },
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Admin UI & Endpoints
|
|
61
|
+
|
|
62
|
+
- Medusa Admin gains a dedicated **Media Library** page at `/media-library` with search, filtering, grid/list views, upload drawer, and detail inspector.
|
|
63
|
+
- Upload drawer supports drag & drop, visibility/status controls, and tag management.
|
|
64
|
+
- Detail view exposes variants with one-click URL copy, relation visibility, metadata editing, and file replacement.
|
|
65
|
+
|
|
66
|
+
REST endpoints backing the UI:
|
|
67
|
+
|
|
68
|
+
- `POST /admin/media/assets/upload` — Multipart upload (supports folder, tags, visibility).
|
|
69
|
+
- `GET /admin/media/assets` — Query/search assets with filters.
|
|
70
|
+
- `GET /admin/media/assets/:id` — Retrieve a single asset with relations.
|
|
71
|
+
- `PATCH /admin/media/assets/:id` — Update metadata, tags, folder, status, visibility.
|
|
72
|
+
- `POST /admin/media/assets/:id/replace` — Swap the binary while retaining relationships.
|
|
73
|
+
- `GET /admin/media/assets/:id/url` — Resolve public/signed URLs for originals or variants.
|
|
74
|
+
- `DELETE /admin/media/assets/:id` — Safe deletion with usage guards (force via `?force=true`).
|
|
75
|
+
|
|
76
|
+
Middleware automatically wires Multer for upload routes.
|
|
77
|
+
|
|
78
|
+
## Notes & Next Steps
|
|
79
|
+
|
|
80
|
+
- Additional admin widgets (pickers, entity integrations) remain to be added.
|
|
81
|
+
- Workflows/event subscribers are not yet implemented.
|
|
82
|
+
- Additional endpoints (folders, tags management, variant regeneration) are planned.
|
|
83
|
+
- `medusa plugin:build` may require access to `$HOME/.config/medusa`; set `XDG_CONFIG_HOME` if necessary.
|
|
84
|
+
|
|
85
|
+
Contributions and feedback welcome!
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lodashventure/medusa-media-manager",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Medusa v2 plugin providing a Strapi-inspired media manager with storage adapters, variants, and admin UI",
|
|
5
|
+
"author": "StandUpCode",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"files": [
|
|
8
|
+
".medusa/server"
|
|
9
|
+
],
|
|
10
|
+
"exports": {
|
|
11
|
+
"./package.json": "./package.json",
|
|
12
|
+
"./workflows": "./.medusa/server/src/workflows/index.js",
|
|
13
|
+
"./.medusa/server/src/modules/*": "./.medusa/server/src/modules/*/index.js",
|
|
14
|
+
"./modules/*": "./.medusa/server/src/modules/*/index.js",
|
|
15
|
+
"./providers/*": "./.medusa/server/src/providers/*/index.js",
|
|
16
|
+
"./admin": "./.medusa/server/src/admin/index.mjs",
|
|
17
|
+
"./*": "./.medusa/server/src/*.js"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"medusa",
|
|
21
|
+
"plugin",
|
|
22
|
+
"media",
|
|
23
|
+
"asset-management",
|
|
24
|
+
"dam",
|
|
25
|
+
"medusa-v2"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "medusa plugin:build",
|
|
29
|
+
"dev": "medusa plugin:develop",
|
|
30
|
+
"lint": "eslint \"src/**/*.{ts,tsx}\"",
|
|
31
|
+
"prepublishOnly": "medusa plugin:build"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@aws-sdk/client-s3": "^3.669.0",
|
|
35
|
+
"@aws-sdk/s3-request-presigner": "^3.669.0",
|
|
36
|
+
"@azure/storage-blob": "^12.24.0",
|
|
37
|
+
"@google-cloud/storage": "^7.10.0",
|
|
38
|
+
"@medusajs/framework": "2.11.2",
|
|
39
|
+
"@medusajs/medusa": "2.11.2",
|
|
40
|
+
"@smithy/node-http-handler": "^3.1.0",
|
|
41
|
+
"file-type": "^19.6.0",
|
|
42
|
+
"lodash": "^4.17.21",
|
|
43
|
+
"mime-types": "^2.1.35",
|
|
44
|
+
"multer": "^2.0.2",
|
|
45
|
+
"sanitize-html": "^2.13.0",
|
|
46
|
+
"sharp": "^0.33.3",
|
|
47
|
+
"tmp": "^0.2.3",
|
|
48
|
+
"ts-node": "^10.9.2",
|
|
49
|
+
"uuid": "^9.0.1",
|
|
50
|
+
"yalc": "1.0.0-pre.53"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@medusajs/admin-sdk": "2.11.2",
|
|
54
|
+
"@medusajs/admin-shared": "2.11.2",
|
|
55
|
+
"@medusajs/cli": "2.11.2",
|
|
56
|
+
"@medusajs/icons": "^2.11.2",
|
|
57
|
+
"@medusajs/ui": "4.0.4",
|
|
58
|
+
"@swc/core": "1.5.7",
|
|
59
|
+
"@tanstack/react-query": "^5.0.0",
|
|
60
|
+
"@types/lodash": "^4.17.12",
|
|
61
|
+
"@types/multer": "^1.4.12",
|
|
62
|
+
"@types/node": "^20.0.0",
|
|
63
|
+
"@types/react": "^18.2.0",
|
|
64
|
+
"@types/react-dom": "^18.2.0",
|
|
65
|
+
"@types/sanitize-html": "^2.11.0",
|
|
66
|
+
"@types/uuid": "^10.0.0",
|
|
67
|
+
"eslint": "^9.10.0",
|
|
68
|
+
"react": "^18.2.0",
|
|
69
|
+
"react-dom": "^18.2.0",
|
|
70
|
+
"typescript": "^5.6.2"
|
|
71
|
+
},
|
|
72
|
+
"peerDependencies": {
|
|
73
|
+
"@medusajs/admin-sdk": "2.11.2",
|
|
74
|
+
"@medusajs/framework": "2.11.2",
|
|
75
|
+
"@medusajs/icons": "^2.11.2",
|
|
76
|
+
"@medusajs/medusa": "2.11.2",
|
|
77
|
+
"@medusajs/ui": "^4.0.3"
|
|
78
|
+
},
|
|
79
|
+
"engines": {
|
|
80
|
+
"node": ">=20"
|
|
81
|
+
}
|
|
82
|
+
}
|