@lodashventure/medusa-brand 1.1.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/README.md +95 -0
- package/dist/admin/components/brand-form.d.ts +19 -0
- package/dist/admin/components/brand-form.js +182 -0
- package/dist/admin/components/brand-image-uploader.d.ts +14 -0
- package/dist/admin/components/brand-image-uploader.js +217 -0
- package/dist/admin/lib/sdk.d.ts +1 -0
- package/dist/admin/lib/sdk.js +14 -0
- package/dist/admin/routes/brands/page.d.ts +4 -0
- package/dist/admin/routes/brands/page.js +253 -0
- package/dist/admin/widgets/product-brand-widget.d.ts +8 -0
- package/dist/admin/widgets/product-brand-widget.js +207 -0
- package/dist/api/admin/brands/[id]/image/route.d.ts +5 -0
- package/dist/api/admin/brands/[id]/image/route.js +118 -0
- package/dist/api/admin/brands/[id]/logo/route.d.ts +5 -0
- package/dist/api/admin/brands/[id]/logo/route.js +118 -0
- package/dist/api/admin/brands/[id]/products/route.d.ts +2 -0
- package/dist/api/admin/brands/[id]/products/route.js +51 -0
- package/dist/api/admin/brands/[id]/route.d.ts +5 -0
- package/dist/api/admin/brands/[id]/route.js +111 -0
- package/dist/api/admin/brands/route.d.ts +4 -0
- package/dist/api/admin/brands/route.js +75 -0
- package/dist/api/admin/products/[id]/brand/route.d.ts +5 -0
- package/dist/api/admin/products/[id]/brand/route.js +116 -0
- package/dist/api/middlewares/attach-brand-to-products.d.ts +2 -0
- package/dist/api/middlewares/attach-brand-to-products.js +104 -0
- package/dist/api/middlewares.d.ts +6 -0
- package/dist/api/middlewares.js +26 -0
- package/dist/api/store/brands/route.d.ts +2 -0
- package/dist/api/store/brands/route.js +50 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -0
- package/dist/modules/brand/index.d.ts +35 -0
- package/dist/modules/brand/index.js +12 -0
- package/dist/modules/brand/migrations/Migration20251021070648.d.ts +5 -0
- package/dist/modules/brand/migrations/Migration20251021070648.js +27 -0
- package/dist/modules/brand/models/brand.d.ts +16 -0
- package/dist/modules/brand/models/brand.js +42 -0
- package/dist/modules/brand/service.d.ts +21 -0
- package/dist/modules/brand/service.js +10 -0
- package/dist/services/gcs-direct-upload.d.ts +8 -0
- package/dist/services/gcs-direct-upload.js +54 -0
- package/dist/workflows/upload-brand-image.d.ts +15 -0
- package/dist/workflows/upload-brand-image.js +56 -0
- package/package.json +58 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GET = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
// GET - List all active brands for store
|
|
6
|
+
const GET = async (req, res) => {
|
|
7
|
+
const brandService = req.scope.resolve("brandCustom");
|
|
8
|
+
const logger = req.scope.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
9
|
+
try {
|
|
10
|
+
const { q, limit = 20, offset = 0, order = "name", } = req.query;
|
|
11
|
+
const filters = {
|
|
12
|
+
is_active: true, // Only show active brands in store
|
|
13
|
+
};
|
|
14
|
+
if (q) {
|
|
15
|
+
filters.$or = [
|
|
16
|
+
{ name: { $ilike: `%${q}%` } },
|
|
17
|
+
{ description: { $ilike: `%${q}%` } },
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
const [brands, count] = await Promise.all([
|
|
21
|
+
brandService.listBrands(filters, {
|
|
22
|
+
limit: Number(limit),
|
|
23
|
+
offset: Number(offset),
|
|
24
|
+
order,
|
|
25
|
+
select: [
|
|
26
|
+
"id",
|
|
27
|
+
"name",
|
|
28
|
+
"slug",
|
|
29
|
+
"description",
|
|
30
|
+
"image",
|
|
31
|
+
"logo",
|
|
32
|
+
"website",
|
|
33
|
+
"metadata"
|
|
34
|
+
],
|
|
35
|
+
}),
|
|
36
|
+
brandService.listBrands(filters).then((result) => result.length)
|
|
37
|
+
]);
|
|
38
|
+
return res.json({
|
|
39
|
+
brands,
|
|
40
|
+
count,
|
|
41
|
+
offset: Number(offset),
|
|
42
|
+
limit: Number(limit),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
logger.error("Error listing brands for store:", error);
|
|
47
|
+
return res.status(500).json({ error: "Failed to list brands" });
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
exports.GET = GET;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BRAND_MODULE } from "./modules/brand";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BRAND_MODULE = void 0;
|
|
4
|
+
// Export the module name for use in medusa-config
|
|
5
|
+
var brand_1 = require("./modules/brand");
|
|
6
|
+
Object.defineProperty(exports, "BRAND_MODULE", { enumerable: true, get: function () { return brand_1.BRAND_MODULE; } });
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import BrandModuleService from "./service";
|
|
2
|
+
export declare const BRAND_MODULE = "brandCustom";
|
|
3
|
+
declare const _default: import("@medusajs/types").ModuleExports<typeof BrandModuleService> & {
|
|
4
|
+
linkable: {
|
|
5
|
+
readonly brand: {
|
|
6
|
+
id: {
|
|
7
|
+
serviceName: "brandCustom";
|
|
8
|
+
field: "brand";
|
|
9
|
+
linkable: "brand_id";
|
|
10
|
+
primaryKey: "id";
|
|
11
|
+
};
|
|
12
|
+
toJSON: () => {
|
|
13
|
+
serviceName: "brandCustom";
|
|
14
|
+
field: "brand";
|
|
15
|
+
linkable: "brand_id";
|
|
16
|
+
primaryKey: "id";
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
readonly productBrand: {
|
|
20
|
+
id: {
|
|
21
|
+
serviceName: "brandCustom";
|
|
22
|
+
field: "productBrand";
|
|
23
|
+
linkable: "product_brand_id";
|
|
24
|
+
primaryKey: "id";
|
|
25
|
+
};
|
|
26
|
+
toJSON: () => {
|
|
27
|
+
serviceName: "brandCustom";
|
|
28
|
+
field: "productBrand";
|
|
29
|
+
linkable: "product_brand_id";
|
|
30
|
+
primaryKey: "id";
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export default _default;
|
|
@@ -0,0 +1,12 @@
|
|
|
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.BRAND_MODULE = void 0;
|
|
7
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
8
|
+
const service_1 = __importDefault(require("./service"));
|
|
9
|
+
exports.BRAND_MODULE = "brandCustom";
|
|
10
|
+
exports.default = (0, utils_1.Module)(exports.BRAND_MODULE, {
|
|
11
|
+
service: service_1.default,
|
|
12
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Migration20251021070648 = void 0;
|
|
4
|
+
const migrations_1 = require("@medusajs/framework/mikro-orm/migrations");
|
|
5
|
+
class Migration20251021070648 extends migrations_1.Migration {
|
|
6
|
+
async up() {
|
|
7
|
+
this.addSql(`alter table if exists "product_brand" drop constraint if exists "product_brand_product_id_brand_id_unique";`);
|
|
8
|
+
this.addSql(`alter table if exists "brand" drop constraint if exists "brand_slug_unique";`);
|
|
9
|
+
this.addSql(`alter table if exists "brand" drop constraint if exists "brand_name_unique";`);
|
|
10
|
+
this.addSql(`create table if not exists "brand" ("id" text not null, "name" text not null, "slug" text not null, "description" text null, "image" text null, "logo" text null, "website" text null, "is_active" boolean not null default true, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "brand_pkey" primary key ("id"));`);
|
|
11
|
+
this.addSql(`CREATE UNIQUE INDEX IF NOT EXISTS "IDX_brand_name_unique" ON "brand" (name) WHERE deleted_at IS NULL;`);
|
|
12
|
+
this.addSql(`CREATE UNIQUE INDEX IF NOT EXISTS "IDX_brand_slug_unique" ON "brand" (slug) WHERE deleted_at IS NULL;`);
|
|
13
|
+
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_brand_deleted_at" ON "brand" (deleted_at) WHERE deleted_at IS NULL;`);
|
|
14
|
+
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_brand_slug" ON "brand" (slug) WHERE deleted_at IS NULL;`);
|
|
15
|
+
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_brand_is_active" ON "brand" (is_active) WHERE deleted_at IS NULL;`);
|
|
16
|
+
this.addSql(`create table if not exists "product_brand" ("id" text not null, "product_id" text not null, "brand_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_brand_pkey" primary key ("id"));`);
|
|
17
|
+
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_product_brand_deleted_at" ON "product_brand" (deleted_at) WHERE deleted_at IS NULL;`);
|
|
18
|
+
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_product_brand_product_id" ON "product_brand" (product_id) WHERE deleted_at IS NULL;`);
|
|
19
|
+
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_product_brand_brand_id" ON "product_brand" (brand_id) WHERE deleted_at IS NULL;`);
|
|
20
|
+
this.addSql(`CREATE UNIQUE INDEX IF NOT EXISTS "IDX_product_brand_product_id_brand_id_unique" ON "product_brand" (product_id, brand_id) WHERE deleted_at IS NULL;`);
|
|
21
|
+
}
|
|
22
|
+
async down() {
|
|
23
|
+
this.addSql(`drop table if exists "brand" cascade;`);
|
|
24
|
+
this.addSql(`drop table if exists "product_brand" cascade;`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.Migration20251021070648 = Migration20251021070648;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const Brand: import("@medusajs/framework/utils").DmlEntity<import("@medusajs/framework/utils").DMLEntitySchemaBuilder<{
|
|
2
|
+
id: import("@medusajs/framework/utils").PrimaryKeyModifier<string, import("@medusajs/framework/utils").IdProperty>;
|
|
3
|
+
name: import("@medusajs/framework/utils").TextProperty;
|
|
4
|
+
slug: import("@medusajs/framework/utils").TextProperty;
|
|
5
|
+
description: import("@medusajs/framework/utils").NullableModifier<string, import("@medusajs/framework/utils").TextProperty>;
|
|
6
|
+
image: import("@medusajs/framework/utils").NullableModifier<string, import("@medusajs/framework/utils").TextProperty>;
|
|
7
|
+
logo: import("@medusajs/framework/utils").NullableModifier<string, import("@medusajs/framework/utils").TextProperty>;
|
|
8
|
+
website: import("@medusajs/framework/utils").NullableModifier<string, import("@medusajs/framework/utils").TextProperty>;
|
|
9
|
+
is_active: import("@medusajs/framework/utils").BooleanProperty;
|
|
10
|
+
metadata: import("@medusajs/framework/utils").NullableModifier<Record<string, unknown>, import("@medusajs/framework/utils").JSONProperty>;
|
|
11
|
+
}>, "brand">;
|
|
12
|
+
export declare const ProductBrand: import("@medusajs/framework/utils").DmlEntity<import("@medusajs/framework/utils").DMLEntitySchemaBuilder<{
|
|
13
|
+
id: import("@medusajs/framework/utils").PrimaryKeyModifier<string, import("@medusajs/framework/utils").IdProperty>;
|
|
14
|
+
product_id: import("@medusajs/framework/utils").TextProperty;
|
|
15
|
+
brand_id: import("@medusajs/framework/utils").TextProperty;
|
|
16
|
+
}>, "product_brand">;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProductBrand = exports.Brand = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
exports.Brand = utils_1.model
|
|
6
|
+
.define("brand", {
|
|
7
|
+
id: utils_1.model.id().primaryKey(),
|
|
8
|
+
name: utils_1.model.text().unique(),
|
|
9
|
+
slug: utils_1.model.text().unique(),
|
|
10
|
+
description: utils_1.model.text().nullable(),
|
|
11
|
+
image: utils_1.model.text().nullable(),
|
|
12
|
+
logo: utils_1.model.text().nullable(),
|
|
13
|
+
website: utils_1.model.text().nullable(),
|
|
14
|
+
is_active: utils_1.model.boolean().default(true),
|
|
15
|
+
metadata: utils_1.model.json().nullable(),
|
|
16
|
+
})
|
|
17
|
+
.indexes([
|
|
18
|
+
{
|
|
19
|
+
on: ["slug"],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
on: ["is_active"],
|
|
23
|
+
},
|
|
24
|
+
]);
|
|
25
|
+
exports.ProductBrand = utils_1.model
|
|
26
|
+
.define("product_brand", {
|
|
27
|
+
id: utils_1.model.id().primaryKey(),
|
|
28
|
+
product_id: utils_1.model.text(),
|
|
29
|
+
brand_id: utils_1.model.text(),
|
|
30
|
+
})
|
|
31
|
+
.indexes([
|
|
32
|
+
{
|
|
33
|
+
on: ["product_id"],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
on: ["brand_id"],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
on: ["product_id", "brand_id"],
|
|
40
|
+
unique: true,
|
|
41
|
+
},
|
|
42
|
+
]);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
declare const BrandModuleService_base: import("@medusajs/framework/utils").MedusaServiceReturnType<import("@medusajs/framework/utils").ModelConfigurationsToConfigTemplate<{
|
|
2
|
+
readonly Brand: import("@medusajs/framework/utils").DmlEntity<import("@medusajs/framework/utils").DMLEntitySchemaBuilder<{
|
|
3
|
+
id: import("@medusajs/framework/utils").PrimaryKeyModifier<string, import("@medusajs/framework/utils").IdProperty>;
|
|
4
|
+
name: import("@medusajs/framework/utils").TextProperty;
|
|
5
|
+
slug: import("@medusajs/framework/utils").TextProperty;
|
|
6
|
+
description: import("@medusajs/framework/utils").NullableModifier<string, import("@medusajs/framework/utils").TextProperty>;
|
|
7
|
+
image: import("@medusajs/framework/utils").NullableModifier<string, import("@medusajs/framework/utils").TextProperty>;
|
|
8
|
+
logo: import("@medusajs/framework/utils").NullableModifier<string, import("@medusajs/framework/utils").TextProperty>;
|
|
9
|
+
website: import("@medusajs/framework/utils").NullableModifier<string, import("@medusajs/framework/utils").TextProperty>;
|
|
10
|
+
is_active: import("@medusajs/framework/utils").BooleanProperty;
|
|
11
|
+
metadata: import("@medusajs/framework/utils").NullableModifier<Record<string, unknown>, import("@medusajs/framework/utils").JSONProperty>;
|
|
12
|
+
}>, "brand">;
|
|
13
|
+
readonly ProductBrand: import("@medusajs/framework/utils").DmlEntity<import("@medusajs/framework/utils").DMLEntitySchemaBuilder<{
|
|
14
|
+
id: import("@medusajs/framework/utils").PrimaryKeyModifier<string, import("@medusajs/framework/utils").IdProperty>;
|
|
15
|
+
product_id: import("@medusajs/framework/utils").TextProperty;
|
|
16
|
+
brand_id: import("@medusajs/framework/utils").TextProperty;
|
|
17
|
+
}>, "product_brand">;
|
|
18
|
+
}>>;
|
|
19
|
+
export default class BrandModuleService extends BrandModuleService_base {
|
|
20
|
+
}
|
|
21
|
+
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 brand_1 = require("./models/brand");
|
|
5
|
+
class BrandModuleService extends (0, utils_1.MedusaService)({
|
|
6
|
+
Brand: brand_1.Brand,
|
|
7
|
+
ProductBrand: brand_1.ProductBrand,
|
|
8
|
+
}) {
|
|
9
|
+
}
|
|
10
|
+
exports.default = BrandModuleService;
|
|
@@ -0,0 +1,54 @@
|
|
|
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;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface UploadBrandImageInput {
|
|
2
|
+
brandId: string;
|
|
3
|
+
imageType: "image" | "logo";
|
|
4
|
+
fileData: {
|
|
5
|
+
filename: string;
|
|
6
|
+
mimeType: string;
|
|
7
|
+
content: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export declare const uploadBrandImageWorkflow: import("@medusajs/framework/workflows-sdk").ReturnWorkflow<UploadBrandImageInput, {
|
|
11
|
+
brandId: string;
|
|
12
|
+
imageType: "image" | "logo";
|
|
13
|
+
imageUrl: string;
|
|
14
|
+
}, []>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uploadBrandImageWorkflow = 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 uploadBrandImageStep = (0, workflows_sdk_1.createStep)("upload-brand-image-step", async ({ brandId, imageType, fileData }, { container }) => {
|
|
7
|
+
const brandService = container.resolve("brandCustom");
|
|
8
|
+
const gcsUploadService = new gcs_direct_upload_1.GcsDirectUploadService();
|
|
9
|
+
// Generate unique filename for direct upload
|
|
10
|
+
const timestamp = Date.now();
|
|
11
|
+
const ext = fileData.filename.split('.').pop() || 'jpg';
|
|
12
|
+
const filename = `brands/${imageType}-${brandId}-${timestamp}.${ext}`;
|
|
13
|
+
// Convert base64 to buffer
|
|
14
|
+
const buffer = Buffer.from(fileData.content, "base64");
|
|
15
|
+
// Upload directly to GCS
|
|
16
|
+
const publicUrl = await gcsUploadService.uploadFile(filename, buffer, fileData.mimeType);
|
|
17
|
+
// Retrieve existing brand
|
|
18
|
+
const brand = await brandService.retrieveBrand(brandId);
|
|
19
|
+
if (!brand) {
|
|
20
|
+
throw new Error(`Brand with id ${brandId} not found`);
|
|
21
|
+
}
|
|
22
|
+
// Delete old image if it exists
|
|
23
|
+
const oldImageUrl = brand[imageType];
|
|
24
|
+
if (oldImageUrl) {
|
|
25
|
+
try {
|
|
26
|
+
if (oldImageUrl.includes('storage.googleapis.com')) {
|
|
27
|
+
const parts = oldImageUrl.split('/');
|
|
28
|
+
const bucketIndex = parts.indexOf('sangaroon');
|
|
29
|
+
if (bucketIndex !== -1 && bucketIndex < parts.length - 1) {
|
|
30
|
+
const oldFilename = parts.slice(bucketIndex + 1).join('/');
|
|
31
|
+
await gcsUploadService.deleteFile(oldFilename);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
console.error(`Failed to delete old ${imageType}:`, error);
|
|
37
|
+
// Continue even if deletion fails
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Update brand with new image URL
|
|
41
|
+
const updateData = {};
|
|
42
|
+
updateData[imageType] = publicUrl;
|
|
43
|
+
await brandService.updateBrands([{
|
|
44
|
+
id: brandId,
|
|
45
|
+
...updateData
|
|
46
|
+
}]);
|
|
47
|
+
return new workflows_sdk_1.StepResponse({
|
|
48
|
+
brandId,
|
|
49
|
+
imageType,
|
|
50
|
+
imageUrl: publicUrl,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
exports.uploadBrandImageWorkflow = (0, workflows_sdk_1.createWorkflow)("upload-brand-image", (input) => {
|
|
54
|
+
const result = uploadBrandImageStep(input);
|
|
55
|
+
return new workflows_sdk_1.WorkflowResponse(result);
|
|
56
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lodashventure/medusa-brand",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Brand management plugin for Medusa v2",
|
|
5
|
+
"author": "Lodashventure",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"medusa",
|
|
9
|
+
"medusa-plugin",
|
|
10
|
+
"brand",
|
|
11
|
+
"ecommerce"
|
|
12
|
+
],
|
|
13
|
+
"main": "dist/index.js",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": "./dist/index.js",
|
|
16
|
+
"./modules/brand": "./dist/modules/brand/index.js",
|
|
17
|
+
"./package.json": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/lodashventure/medusa-brand"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"admin"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc --build",
|
|
29
|
+
"watch": "tsc --watch",
|
|
30
|
+
"dev": "tsc --watch"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@google-cloud/storage": "^7.17.2",
|
|
34
|
+
"@medusajs/admin-sdk": "*",
|
|
35
|
+
"@medusajs/framework": "*",
|
|
36
|
+
"@medusajs/icons": "*",
|
|
37
|
+
"@medusajs/ui": "*"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@medusajs/admin-sdk": "*",
|
|
41
|
+
"@medusajs/framework": "*",
|
|
42
|
+
"@medusajs/icons": "*",
|
|
43
|
+
"@medusajs/medusa": "*",
|
|
44
|
+
"@medusajs/ui": "*",
|
|
45
|
+
"react": "^18.0.0",
|
|
46
|
+
"react-dom": "^18.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@medusajs/types": "*",
|
|
50
|
+
"@types/multer": "^2.0.0",
|
|
51
|
+
"@types/node": "^20.19.23",
|
|
52
|
+
"@types/react": "^18.3.2",
|
|
53
|
+
"@types/react-dom": "^18.2.25",
|
|
54
|
+
"ts-node": "^10.9.2",
|
|
55
|
+
"typescript": "^5.6.2",
|
|
56
|
+
"yalc": "1.0.0-pre.53"
|
|
57
|
+
}
|
|
58
|
+
}
|