@lodashventure/medusa-brand 1.2.19 → 1.2.23
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 +1191 -556
- package/.medusa/server/src/admin/index.mjs +1165 -530
- package/.medusa/server/src/api/admin/brands/[id]/image/route.js +178 -0
- package/.medusa/server/src/api/admin/brands/[id]/logo/route.js +179 -0
- package/.medusa/server/src/api/admin/brands/[id]/products/route.js +55 -0
- package/.medusa/server/src/api/admin/brands/[id]/route.js +251 -0
- package/.medusa/server/src/api/admin/brands/route.js +276 -0
- package/.medusa/server/src/api/admin/products/[id]/brand/route.js +117 -0
- package/.medusa/server/src/api/middlewares/attach-brand-to-products.js +110 -0
- package/.medusa/server/src/api/middlewares.js +53 -0
- package/.medusa/server/src/api/store/brands/[id]/route.js +31 -0
- package/.medusa/server/src/api/store/brands/route.js +99 -0
- package/.medusa/server/{index.js → src/index.js} +1 -1
- package/.medusa/server/{modules → src/modules}/brand/index.js +1 -1
- package/.medusa/server/src/modules/brand/models/brand.js +40 -0
- package/.medusa/server/{modules → src/modules}/brand/service.js +1 -1
- package/.medusa/server/src/services/gcs-direct-upload.js +93 -0
- package/.medusa/server/src/workflows/upload-brand-image.js +66 -0
- package/package.json +11 -10
- package/.medusa/server/api/admin/brands/[id]/image/route.d.ts +0 -5
- package/.medusa/server/api/admin/brands/[id]/image/route.js +0 -119
- package/.medusa/server/api/admin/brands/[id]/logo/route.d.ts +0 -5
- package/.medusa/server/api/admin/brands/[id]/logo/route.js +0 -119
- package/.medusa/server/api/admin/brands/[id]/products/route.d.ts +0 -2
- package/.medusa/server/api/admin/brands/[id]/products/route.js +0 -52
- package/.medusa/server/api/admin/brands/[id]/route.d.ts +0 -5
- package/.medusa/server/api/admin/brands/[id]/route.js +0 -112
- package/.medusa/server/api/admin/brands/route.d.ts +0 -4
- package/.medusa/server/api/admin/brands/route.js +0 -76
- package/.medusa/server/api/admin/products/[id]/brand/route.d.ts +0 -5
- package/.medusa/server/api/admin/products/[id]/brand/route.js +0 -117
- package/.medusa/server/api/middlewares/attach-brand-to-products.d.ts +0 -2
- package/.medusa/server/api/middlewares/attach-brand-to-products.js +0 -105
- package/.medusa/server/api/middlewares.d.ts +0 -6
- package/.medusa/server/api/middlewares.js +0 -27
- package/.medusa/server/api/store/brands/route.d.ts +0 -2
- package/.medusa/server/api/store/brands/route.js +0 -53
- package/.medusa/server/index.d.ts +0 -1
- package/.medusa/server/modules/brand/index.d.ts +0 -35
- package/.medusa/server/modules/brand/migrations/Migration20251021070648.d.ts +0 -5
- package/.medusa/server/modules/brand/migrations/Migration20251021070648.js +0 -28
- package/.medusa/server/modules/brand/models/brand.d.ts +0 -16
- package/.medusa/server/modules/brand/models/brand.js +0 -43
- package/.medusa/server/modules/brand/service.d.ts +0 -21
- package/.medusa/server/services/gcs-direct-upload.d.ts +0 -8
- package/.medusa/server/services/gcs-direct-upload.js +0 -55
- package/.medusa/server/workflows/upload-brand-image.d.ts +0 -15
- package/.medusa/server/workflows/upload-brand-image.js +0 -57
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GET = GET;
|
|
4
|
+
exports.PUT = PUT;
|
|
5
|
+
exports.DELETE = DELETE;
|
|
6
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
7
|
+
const BRAND_MODULE = "brandCustom";
|
|
8
|
+
const SLUG_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
9
|
+
const sanitizeSlug = (value) => value
|
|
10
|
+
.toLowerCase()
|
|
11
|
+
.trim()
|
|
12
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
13
|
+
.replace(/^-+|-+$/g, "");
|
|
14
|
+
const ensureMetadataObject = (metadata) => {
|
|
15
|
+
if (metadata === undefined) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
if (metadata === null) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
if (typeof metadata === "object" && !Array.isArray(metadata)) {
|
|
22
|
+
return metadata;
|
|
23
|
+
}
|
|
24
|
+
throw new Error("Metadata must be a valid JSON object.");
|
|
25
|
+
};
|
|
26
|
+
const validateWebsite = (website) => {
|
|
27
|
+
if (website === undefined || website === null || !website.trim()) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (!/^https?:\/\/.+/i.test(website.trim())) {
|
|
31
|
+
throw new Error("Website must be a valid URL starting with http:// or https://");
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const normalizeBooleanInput = (value) => {
|
|
35
|
+
if (value === undefined) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
if (typeof value === "boolean") {
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
if (typeof value === "string") {
|
|
42
|
+
const normalized = value.toLowerCase().trim();
|
|
43
|
+
if (["true", "1"].includes(normalized)) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
if (["false", "0"].includes(normalized)) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
throw new Error("is_active must be a boolean value");
|
|
51
|
+
};
|
|
52
|
+
// GET - Get a specific brand by ID
|
|
53
|
+
async function GET(req, res) {
|
|
54
|
+
const { id } = req.params;
|
|
55
|
+
const container = req.scope;
|
|
56
|
+
const brandService = container.resolve(BRAND_MODULE);
|
|
57
|
+
const logger = container.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
58
|
+
try {
|
|
59
|
+
const [brand] = await brandService.listBrands({ id });
|
|
60
|
+
if (!brand) {
|
|
61
|
+
return res.status(404).json({ error: "Brand not found" });
|
|
62
|
+
}
|
|
63
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
64
|
+
res.json({ brand });
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
logger.error(`Error retrieving brand ${id}:`, error);
|
|
68
|
+
res.status(500).json({ error: "Failed to retrieve brand" });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// PUT - Update a brand
|
|
72
|
+
async function PUT(req, res) {
|
|
73
|
+
const { id } = req.params;
|
|
74
|
+
const container = req.scope;
|
|
75
|
+
const brandService = container.resolve(BRAND_MODULE);
|
|
76
|
+
const logger = container.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
77
|
+
try {
|
|
78
|
+
// Verify brand exists
|
|
79
|
+
const [brand] = await brandService.listBrands({ id });
|
|
80
|
+
if (!brand) {
|
|
81
|
+
return res.status(404).json({ error: "Brand not found" });
|
|
82
|
+
}
|
|
83
|
+
const payload = req.body ?? {};
|
|
84
|
+
const { name, slug, description, website, is_active, metadata } = payload;
|
|
85
|
+
if (name !== undefined) {
|
|
86
|
+
if (typeof name !== "string" || !name.trim()) {
|
|
87
|
+
return res.status(400).json({
|
|
88
|
+
error: "Name must be a non-empty string",
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
const trimmedName = name.trim();
|
|
92
|
+
if (trimmedName !== brand.name) {
|
|
93
|
+
const existingName = await brandService
|
|
94
|
+
.listBrands({
|
|
95
|
+
name: { $ilike: trimmedName },
|
|
96
|
+
deleted_at: null,
|
|
97
|
+
})
|
|
98
|
+
.then((result) => result[0]);
|
|
99
|
+
if (existingName && existingName.id !== id) {
|
|
100
|
+
return res.status(400).json({
|
|
101
|
+
error: "Brand with this name already exists",
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
let normalizedSlug;
|
|
107
|
+
if (slug !== undefined) {
|
|
108
|
+
if (typeof slug !== "string" || !slug.trim()) {
|
|
109
|
+
return res.status(400).json({
|
|
110
|
+
error: "Slug must be a non-empty string",
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
normalizedSlug = sanitizeSlug(slug);
|
|
114
|
+
if (!SLUG_REGEX.test(normalizedSlug)) {
|
|
115
|
+
return res.status(400).json({
|
|
116
|
+
error: "Slug must contain only lowercase letters, numbers, and hyphens",
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
if (normalizedSlug !== brand.slug) {
|
|
120
|
+
const existingSlug = await brandService
|
|
121
|
+
.listBrands({
|
|
122
|
+
slug: normalizedSlug,
|
|
123
|
+
deleted_at: null,
|
|
124
|
+
})
|
|
125
|
+
.then((result) => result[0]);
|
|
126
|
+
if (existingSlug && existingSlug.id !== id) {
|
|
127
|
+
return res.status(400).json({
|
|
128
|
+
error: "Brand with this slug already exists",
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (website !== undefined &&
|
|
134
|
+
website !== null &&
|
|
135
|
+
typeof website !== "string") {
|
|
136
|
+
return res.status(400).json({
|
|
137
|
+
error: "Website must be a string value",
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (typeof website === "string") {
|
|
141
|
+
try {
|
|
142
|
+
validateWebsite(website);
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
return res.status(400).json({
|
|
146
|
+
error: error.message,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
let parsedMetadata;
|
|
151
|
+
try {
|
|
152
|
+
parsedMetadata = ensureMetadataObject(metadata);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
return res.status(400).json({
|
|
156
|
+
error: error.message,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
let normalizedIsActive;
|
|
160
|
+
try {
|
|
161
|
+
normalizedIsActive = normalizeBooleanInput(is_active);
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
return res.status(400).json({
|
|
165
|
+
error: error.message,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
// Build update payload
|
|
169
|
+
const updateData = { id };
|
|
170
|
+
if (name !== undefined)
|
|
171
|
+
updateData.name = name.trim();
|
|
172
|
+
if (normalizedSlug !== undefined)
|
|
173
|
+
updateData.slug = normalizedSlug;
|
|
174
|
+
if (description !== undefined) {
|
|
175
|
+
if (description === null) {
|
|
176
|
+
updateData.description = null;
|
|
177
|
+
}
|
|
178
|
+
else if (typeof description === "string") {
|
|
179
|
+
updateData.description = description.trim() || null;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
return res.status(400).json({
|
|
183
|
+
error: "Description must be a string value",
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (website !== undefined) {
|
|
188
|
+
if (website === null) {
|
|
189
|
+
updateData.website = null;
|
|
190
|
+
}
|
|
191
|
+
else if (typeof website === "string") {
|
|
192
|
+
updateData.website = website.trim() || null;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (normalizedIsActive !== undefined) {
|
|
196
|
+
updateData.is_active = normalizedIsActive;
|
|
197
|
+
}
|
|
198
|
+
if (parsedMetadata !== undefined)
|
|
199
|
+
updateData.metadata = parsedMetadata;
|
|
200
|
+
// Update brand
|
|
201
|
+
const [updatedBrand] = await brandService.updateBrands([updateData]);
|
|
202
|
+
logger.info(`Brand updated: ${updatedBrand.id} - ${updatedBrand.name}`);
|
|
203
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
204
|
+
res.json({ brand: updatedBrand });
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
logger.error(`Error updating brand ${id}:`, error);
|
|
208
|
+
res.status(500).json({ error: "Failed to update brand" });
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// DELETE - Delete a brand (single)
|
|
212
|
+
async function DELETE(req, res) {
|
|
213
|
+
const { id } = req.params;
|
|
214
|
+
const container = req.scope;
|
|
215
|
+
const brandService = container.resolve(BRAND_MODULE);
|
|
216
|
+
const logger = container.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
217
|
+
try {
|
|
218
|
+
// Verify brand exists
|
|
219
|
+
const [brand] = await brandService.listBrands({ id });
|
|
220
|
+
if (!brand) {
|
|
221
|
+
return res.status(404).json({ error: "Brand not found" });
|
|
222
|
+
}
|
|
223
|
+
// Delete product-brand associations first
|
|
224
|
+
try {
|
|
225
|
+
const productBrands = await brandService.listProductBrands({
|
|
226
|
+
brand_id: id,
|
|
227
|
+
});
|
|
228
|
+
if (productBrands.length > 0) {
|
|
229
|
+
await brandService.deleteProductBrands(productBrands.map((pb) => pb.id));
|
|
230
|
+
logger.info(`Deleted ${productBrands.length} product associations for brand ${id}`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
logger.warn(`Error deleting product associations for brand ${id}: ${error.message}`);
|
|
235
|
+
// Continue with brand deletion
|
|
236
|
+
}
|
|
237
|
+
// Delete the brand
|
|
238
|
+
await brandService.deleteBrands([id]);
|
|
239
|
+
logger.info(`Brand deleted: ${id}`);
|
|
240
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
241
|
+
res.json({
|
|
242
|
+
message: "Brand deleted successfully",
|
|
243
|
+
deletedId: id,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
logger.error(`Error deleting brand ${id}:`, error);
|
|
248
|
+
res.status(500).json({ error: "Failed to delete brand" });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2JyYW5kcy9baWRdL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBNEVBLGtCQXNCQztBQUdELGtCQTJKQztBQUdELHdCQWtEQztBQWpURCxxREFBc0U7QUFFdEUsTUFBTSxZQUFZLEdBQUcsYUFBYSxDQUFDO0FBQ25DLE1BQU0sVUFBVSxHQUFHLDRCQUE0QixDQUFDO0FBRWhELE1BQU0sWUFBWSxHQUFHLENBQUMsS0FBYSxFQUFFLEVBQUUsQ0FDckMsS0FBSztLQUNGLFdBQVcsRUFBRTtLQUNiLElBQUksRUFBRTtLQUNOLE9BQU8sQ0FBQyxhQUFhLEVBQUUsR0FBRyxDQUFDO0tBQzNCLE9BQU8sQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFFN0IsTUFBTSxvQkFBb0IsR0FBRyxDQUFDLFFBQWlCLEVBQUUsRUFBRTtJQUNqRCxJQUFJLFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUMzQixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQsSUFBSSxRQUFRLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDdEIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsSUFBSSxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFDN0QsT0FBTyxRQUErQixDQUFDO0lBQ3pDLENBQUM7SUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxDQUFDLENBQUM7QUFDM0QsQ0FBQyxDQUFDO0FBRUYsTUFBTSxlQUFlLEdBQUcsQ0FBQyxPQUEyQixFQUFFLEVBQUU7SUFDdEQsSUFBSSxPQUFPLEtBQUssU0FBUyxJQUFJLE9BQU8sS0FBSyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztRQUNqRSxPQUFPO0lBQ1QsQ0FBQztJQUVELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUM1QyxNQUFNLElBQUksS0FBSyxDQUNiLCtEQUErRCxDQUNoRSxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxLQUFjLEVBQUUsRUFBRTtJQUMvQyxJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUN4QixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQsSUFBSSxPQUFPLEtBQUssS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUMvQixPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzlCLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM5QyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQ3ZDLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUNELElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDeEMsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsbUNBQW1DLENBQUMsQ0FBQztBQUN2RCxDQUFDLENBQUM7QUFXRixtQ0FBbUM7QUFDNUIsS0FBSyxVQUFVLEdBQUcsQ0FDdkIsR0FBK0IsRUFDL0IsR0FBbUI7SUFFbkIsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUM7SUFDMUIsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQztJQUM1QixNQUFNLFlBQVksR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBUSxDQUFDO0lBQzVELE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFFbkUsSUFBSSxDQUFDO1FBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLE1BQU0sWUFBWSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFdEQsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxDQUFDLENBQUM7UUFDNUQsQ0FBQztRQUVELEdBQUcsQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLGlDQUFpQyxDQUFDLENBQUM7UUFDakUsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDdEIsQ0FBQztJQUFDLE9BQU8sS0FBVSxFQUFFLENBQUM7UUFDcEIsTUFBTSxDQUFDLEtBQUssQ0FBQywwQkFBMEIsRUFBRSxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDckQsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsMEJBQTBCLEVBQUUsQ0FBQyxDQUFDO0lBQzlELENBQUM7QUFDSCxDQUFDO0FBRUQsdUJBQXVCO0FBQ2hCLEtBQUssVUFBVSxHQUFHLENBQ3ZCLEdBQWlELEVBQ2pELEdBQW1CO0lBRW5CLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDO0lBQzFCLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUM7SUFDNUIsTUFBTSxZQUFZLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQVEsQ0FBQztJQUM1RCxNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRW5FLElBQUksQ0FBQztRQUNILHNCQUFzQjtRQUN0QixNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsTUFBTSxZQUFZLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN0RCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDWCxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLGlCQUFpQixFQUFFLENBQUMsQ0FBQztRQUM1RCxDQUFDO1FBRUQsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUM7UUFDL0IsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEdBQUcsT0FBTyxDQUFDO1FBRTFFLElBQUksSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3ZCLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7Z0JBQzdDLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7b0JBQzFCLEtBQUssRUFBRSxpQ0FBaUM7aUJBQ3pDLENBQUMsQ0FBQztZQUNMLENBQUM7WUFFRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFFaEMsSUFBSSxXQUFXLEtBQUssS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUMvQixNQUFNLFlBQVksR0FBRyxNQUFNLFlBQVk7cUJBQ3BDLFVBQVUsQ0FBQztvQkFDVixJQUFJLEVBQUUsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFO29CQUM3QixVQUFVLEVBQUUsSUFBSTtpQkFDakIsQ0FBQztxQkFDRCxJQUFJLENBQUMsQ0FBQyxNQUFhLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUV0QyxJQUFJLFlBQVksSUFBSSxZQUFZLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDO29CQUMzQyxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO3dCQUMxQixLQUFLLEVBQUUscUNBQXFDO3FCQUM3QyxDQUFDLENBQUM7Z0JBQ0wsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxjQUFrQyxDQUFDO1FBQ3ZDLElBQUksSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3ZCLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7Z0JBQzdDLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7b0JBQzFCLEtBQUssRUFBRSxpQ0FBaUM7aUJBQ3pDLENBQUMsQ0FBQztZQUNMLENBQUM7WUFFRCxjQUFjLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRXBDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7Z0JBQ3JDLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7b0JBQzFCLEtBQUssRUFDSCxnRUFBZ0U7aUJBQ25FLENBQUMsQ0FBQztZQUNMLENBQUM7WUFFRCxJQUFJLGNBQWMsS0FBSyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ2xDLE1BQU0sWUFBWSxHQUFHLE1BQU0sWUFBWTtxQkFDcEMsVUFBVSxDQUFDO29CQUNWLElBQUksRUFBRSxjQUFjO29CQUNwQixVQUFVLEVBQUUsSUFBSTtpQkFDakIsQ0FBQztxQkFDRCxJQUFJLENBQUMsQ0FBQyxNQUFhLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUV0QyxJQUFJLFlBQVksSUFBSSxZQUFZLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDO29CQUMzQyxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO3dCQUMxQixLQUFLLEVBQUUscUNBQXFDO3FCQUM3QyxDQUFDLENBQUM7Z0JBQ0wsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBRUQsSUFDRSxPQUFPLEtBQUssU0FBUztZQUNyQixPQUFPLEtBQUssSUFBSTtZQUNoQixPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQzNCLENBQUM7WUFDRCxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUMxQixLQUFLLEVBQUUsZ0NBQWdDO2FBQ3hDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQztnQkFDSCxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDM0IsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztvQkFDMUIsS0FBSyxFQUFHLEtBQWUsQ0FBQyxPQUFPO2lCQUNoQyxDQUFDLENBQUM7WUFDTCxDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksY0FBc0QsQ0FBQztRQUMzRCxJQUFJLENBQUM7WUFDSCxjQUFjLEdBQUcsb0JBQW9CLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDbEQsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUMxQixLQUFLLEVBQUcsS0FBZSxDQUFDLE9BQU87YUFDaEMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELElBQUksa0JBQXVDLENBQUM7UUFDNUMsSUFBSSxDQUFDO1lBQ0gsa0JBQWtCLEdBQUcscUJBQXFCLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDeEQsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUMxQixLQUFLLEVBQUcsS0FBZSxDQUFDLE9BQU87YUFDaEMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELHVCQUF1QjtRQUN2QixNQUFNLFVBQVUsR0FBUSxFQUFFLEVBQUUsRUFBRSxDQUFDO1FBRS9CLElBQUksSUFBSSxLQUFLLFNBQVM7WUFBRSxVQUFVLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN0RCxJQUFJLGNBQWMsS0FBSyxTQUFTO1lBQUUsVUFBVSxDQUFDLElBQUksR0FBRyxjQUFjLENBQUM7UUFDbkUsSUFBSSxXQUFXLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDOUIsSUFBSSxXQUFXLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBQ3pCLFVBQVUsQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO1lBQ2hDLENBQUM7aUJBQU0sSUFBSSxPQUFPLFdBQVcsS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDM0MsVUFBVSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUMsSUFBSSxFQUFFLElBQUksSUFBSSxDQUFDO1lBQ3RELENBQUM7aUJBQU0sQ0FBQztnQkFDTixPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO29CQUMxQixLQUFLLEVBQUUsb0NBQW9DO2lCQUM1QyxDQUFDLENBQUM7WUFDTCxDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksT0FBTyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzFCLElBQUksT0FBTyxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUNyQixVQUFVLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztZQUM1QixDQUFDO2lCQUFNLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ3ZDLFVBQVUsQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLElBQUksQ0FBQztZQUM5QyxDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksa0JBQWtCLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDckMsVUFBVSxDQUFDLFNBQVMsR0FBRyxrQkFBa0IsQ0FBQztRQUM1QyxDQUFDO1FBQ0QsSUFBSSxjQUFjLEtBQUssU0FBUztZQUFFLFVBQVUsQ0FBQyxRQUFRLEdBQUcsY0FBYyxDQUFDO1FBRXZFLGVBQWU7UUFDZixNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsTUFBTSxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztRQUVyRSxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixZQUFZLENBQUMsRUFBRSxNQUFNLFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRXhFLEdBQUcsQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLGlDQUFpQyxDQUFDLENBQUM7UUFDakUsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFBQyxPQUFPLEtBQVUsRUFBRSxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxLQUFLLENBQUMsd0JBQXdCLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ25ELEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLHdCQUF3QixFQUFFLENBQUMsQ0FBQztJQUM1RCxDQUFDO0FBQ0gsQ0FBQztBQUVELG1DQUFtQztBQUM1QixLQUFLLFVBQVUsTUFBTSxDQUMxQixHQUErQixFQUMvQixHQUFtQjtJQUVuQixNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQztJQUMxQixNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDO0lBQzVCLE1BQU0sWUFBWSxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFRLENBQUM7SUFDNUQsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUVuRSxJQUFJLENBQUM7UUFDSCxzQkFBc0I7UUFDdEIsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLE1BQU0sWUFBWSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDdEQsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxDQUFDLENBQUM7UUFDNUQsQ0FBQztRQUVELDBDQUEwQztRQUMxQyxJQUFJLENBQUM7WUFDSCxNQUFNLGFBQWEsR0FBRyxNQUFNLFlBQVksQ0FBQyxpQkFBaUIsQ0FBQztnQkFDekQsUUFBUSxFQUFFLEVBQUU7YUFDYixDQUFDLENBQUM7WUFDSCxJQUFJLGFBQWEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQzdCLE1BQU0sWUFBWSxDQUFDLG1CQUFtQixDQUNwQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBTyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQ3RDLENBQUM7Z0JBQ0YsTUFBTSxDQUFDLElBQUksQ0FDVCxXQUFXLGFBQWEsQ0FBQyxNQUFNLG1DQUFtQyxFQUFFLEVBQUUsQ0FDdkUsQ0FBQztZQUNKLENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztZQUNwQixNQUFNLENBQUMsSUFBSSxDQUNULGlEQUFpRCxFQUFFLEtBQUssS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUN4RSxDQUFDO1lBQ0YsK0JBQStCO1FBQ2pDLENBQUM7UUFFRCxtQkFBbUI7UUFDbkIsTUFBTSxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUV0QyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRXBDLEdBQUcsQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLGlDQUFpQyxDQUFDLENBQUM7UUFDakUsR0FBRyxDQUFDLElBQUksQ0FBQztZQUNQLE9BQU8sRUFBRSw0QkFBNEI7WUFDckMsU0FBUyxFQUFFLEVBQUU7U0FDZCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztRQUNwQixNQUFNLENBQUMsS0FBSyxDQUFDLHdCQUF3QixFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNuRCxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSx3QkFBd0IsRUFBRSxDQUFDLENBQUM7SUFDNUQsQ0FBQztBQUNILENBQUMifQ==
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.POST = exports.GET = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const SLUG_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
6
|
+
const SORTABLE_FIELDS = new Set(["name", "created_at", "updated_at"]);
|
|
7
|
+
const sanitizeSlug = (value) => value
|
|
8
|
+
.toLowerCase()
|
|
9
|
+
.trim()
|
|
10
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
11
|
+
.replace(/^-+|-+$/g, "");
|
|
12
|
+
const ensureSingleValue = (value) => {
|
|
13
|
+
if (Array.isArray(value)) {
|
|
14
|
+
return ensureSingleValue(value[0]);
|
|
15
|
+
}
|
|
16
|
+
return typeof value === "string" ? value : undefined;
|
|
17
|
+
};
|
|
18
|
+
const parseNumber = (value, fallback) => {
|
|
19
|
+
if (!value) {
|
|
20
|
+
return fallback;
|
|
21
|
+
}
|
|
22
|
+
const parsed = Number(value);
|
|
23
|
+
if (Number.isFinite(parsed)) {
|
|
24
|
+
return parsed;
|
|
25
|
+
}
|
|
26
|
+
return fallback;
|
|
27
|
+
};
|
|
28
|
+
const normalizeMetadata = (metadata) => {
|
|
29
|
+
if (metadata === undefined || metadata === null) {
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
if (typeof metadata === "object" && !Array.isArray(metadata)) {
|
|
33
|
+
return metadata;
|
|
34
|
+
}
|
|
35
|
+
throw new Error("Metadata must be a valid JSON object");
|
|
36
|
+
};
|
|
37
|
+
const validateWebsite = (website) => {
|
|
38
|
+
if (!website) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const trimmed = website.trim();
|
|
42
|
+
if (!trimmed) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (!/^https?:\/\/.+/i.test(trimmed)) {
|
|
46
|
+
throw new Error("Website must be a valid URL starting with http:// or https://");
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const normalizeBoolean = (value, fallback) => {
|
|
50
|
+
if (value === undefined || value === null) {
|
|
51
|
+
return fallback;
|
|
52
|
+
}
|
|
53
|
+
if (typeof value === "boolean") {
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
if (typeof value === "string") {
|
|
57
|
+
const normalized = value.toLowerCase().trim();
|
|
58
|
+
if (["true", "1"].includes(normalized)) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
if (["false", "0"].includes(normalized)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
throw new Error("is_active must be a boolean value");
|
|
66
|
+
};
|
|
67
|
+
const GET = async (req, res) => {
|
|
68
|
+
const brandService = req.scope.resolve("brandCustom");
|
|
69
|
+
const logger = req.scope.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
70
|
+
try {
|
|
71
|
+
const searchTerm = ensureSingleValue(req.query.q);
|
|
72
|
+
const status = ensureSingleValue(req.query.status);
|
|
73
|
+
const sortByQuery = ensureSingleValue(req.query.sort_by);
|
|
74
|
+
const sortOrderQuery = ensureSingleValue(req.query.sort_order);
|
|
75
|
+
const slugQueryRaw = ensureSingleValue(req.query.slug);
|
|
76
|
+
const slugQuery = slugQueryRaw ? sanitizeSlug(slugQueryRaw) : undefined;
|
|
77
|
+
const limit = Math.min(Math.max(parseNumber(ensureSingleValue(req.query.limit), 10), 1), 100);
|
|
78
|
+
const offset = Math.max(parseNumber(ensureSingleValue(req.query.offset), 0), 0);
|
|
79
|
+
const filters = {};
|
|
80
|
+
if (status === "active") {
|
|
81
|
+
filters.is_active = true;
|
|
82
|
+
}
|
|
83
|
+
else if (status === "inactive") {
|
|
84
|
+
filters.is_active = false;
|
|
85
|
+
}
|
|
86
|
+
if (slugQuery) {
|
|
87
|
+
filters.slug = slugQuery;
|
|
88
|
+
}
|
|
89
|
+
if (searchTerm) {
|
|
90
|
+
filters.$or = [
|
|
91
|
+
{ name: { $ilike: `%${searchTerm}%` } },
|
|
92
|
+
{ slug: { $ilike: `%${searchTerm}%` } },
|
|
93
|
+
{ description: { $ilike: `%${searchTerm}%` } },
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
const orderField = SORTABLE_FIELDS.has(sortByQuery || "")
|
|
97
|
+
? sortByQuery
|
|
98
|
+
: "created_at";
|
|
99
|
+
const orderDirection = sortOrderQuery && sortOrderQuery.toLowerCase() === "asc" ? "ASC" : "DESC";
|
|
100
|
+
if (typeof brandService.listAndCountBrands === "function") {
|
|
101
|
+
const [brands, count] = await brandService.listAndCountBrands(filters, {
|
|
102
|
+
limit,
|
|
103
|
+
offset,
|
|
104
|
+
order: { [orderField]: orderDirection },
|
|
105
|
+
});
|
|
106
|
+
return res.json({
|
|
107
|
+
brands,
|
|
108
|
+
count,
|
|
109
|
+
offset,
|
|
110
|
+
limit,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const [brands, count] = await Promise.all([
|
|
114
|
+
brandService.listBrands(filters, {
|
|
115
|
+
limit,
|
|
116
|
+
offset,
|
|
117
|
+
order: { [orderField]: orderDirection },
|
|
118
|
+
}),
|
|
119
|
+
typeof brandService.countBrands === "function"
|
|
120
|
+
? brandService.countBrands(filters)
|
|
121
|
+
: brandService
|
|
122
|
+
.listBrands(filters)
|
|
123
|
+
.then((result) => result.length),
|
|
124
|
+
]);
|
|
125
|
+
return res.json({
|
|
126
|
+
brands,
|
|
127
|
+
count,
|
|
128
|
+
offset,
|
|
129
|
+
limit,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
logger.error("Error listing brands:", error);
|
|
134
|
+
return res.status(500).json({
|
|
135
|
+
message: "Failed to list brands",
|
|
136
|
+
error: "Failed to list brands",
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
exports.GET = GET;
|
|
141
|
+
const POST = async (req, res) => {
|
|
142
|
+
const brandService = req.scope.resolve("brandCustom");
|
|
143
|
+
const logger = req.scope.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
144
|
+
try {
|
|
145
|
+
let rawBody = req.body;
|
|
146
|
+
if (Buffer.isBuffer(rawBody)) {
|
|
147
|
+
rawBody = rawBody.toString("utf8");
|
|
148
|
+
}
|
|
149
|
+
if (typeof rawBody === "string") {
|
|
150
|
+
try {
|
|
151
|
+
rawBody = JSON.parse(rawBody);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
logger.error("Error parsing brand payload:", error);
|
|
155
|
+
return res.status(400).json({
|
|
156
|
+
message: "Request body must be valid JSON",
|
|
157
|
+
error: "Request body must be valid JSON",
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (!rawBody || typeof rawBody !== "object") {
|
|
162
|
+
return res.status(400).json({
|
|
163
|
+
message: "Request body must be a JSON object",
|
|
164
|
+
error: "Request body must be a JSON object",
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
const { name, slug, description, website, is_active, metadata } = rawBody;
|
|
168
|
+
if (!name || typeof name !== "string" || !name.trim()) {
|
|
169
|
+
return res.status(400).json({
|
|
170
|
+
message: "Name is required",
|
|
171
|
+
error: "Name is required",
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
if (description !== undefined &&
|
|
175
|
+
description !== null &&
|
|
176
|
+
typeof description !== "string") {
|
|
177
|
+
return res.status(400).json({
|
|
178
|
+
message: "Description must be a string value",
|
|
179
|
+
error: "Description must be a string value",
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
if (website !== undefined &&
|
|
183
|
+
website !== null &&
|
|
184
|
+
typeof website !== "string") {
|
|
185
|
+
return res.status(400).json({
|
|
186
|
+
message: "Website must be a string value",
|
|
187
|
+
error: "Website must be a string value",
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
const normalizedSlug = sanitizeSlug(slug ?? name);
|
|
191
|
+
if (!normalizedSlug || !SLUG_REGEX.test(normalizedSlug)) {
|
|
192
|
+
return res.status(400).json({
|
|
193
|
+
message: "Slug must contain only lowercase letters, numbers, and hyphens",
|
|
194
|
+
error: "Slug must contain only lowercase letters, numbers, and hyphens",
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
let parsedMetadata = {};
|
|
198
|
+
try {
|
|
199
|
+
parsedMetadata = normalizeMetadata(metadata);
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
return res.status(400).json({
|
|
203
|
+
message: error.message,
|
|
204
|
+
error: error.message,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
let normalizedIsActive;
|
|
208
|
+
try {
|
|
209
|
+
normalizedIsActive = normalizeBoolean(is_active, true);
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
return res.status(400).json({
|
|
213
|
+
message: error.message,
|
|
214
|
+
error: error.message,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
try {
|
|
218
|
+
validateWebsite(website);
|
|
219
|
+
}
|
|
220
|
+
catch (validationError) {
|
|
221
|
+
return res.status(400).json({
|
|
222
|
+
message: validationError.message,
|
|
223
|
+
error: validationError.message,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
const trimmedName = name.trim();
|
|
227
|
+
const trimmedWebsite = website?.trim() || null;
|
|
228
|
+
const trimmedDescription = description?.trim() || null;
|
|
229
|
+
const existingSlug = await brandService
|
|
230
|
+
.listBrands({
|
|
231
|
+
slug: normalizedSlug,
|
|
232
|
+
deleted_at: null,
|
|
233
|
+
})
|
|
234
|
+
.then((result) => result[0]);
|
|
235
|
+
if (existingSlug) {
|
|
236
|
+
return res.status(400).json({
|
|
237
|
+
message: "Brand with this slug already exists",
|
|
238
|
+
error: "Brand with this slug already exists",
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
const existingName = await brandService
|
|
242
|
+
.listBrands({
|
|
243
|
+
name: { $ilike: trimmedName },
|
|
244
|
+
deleted_at: null,
|
|
245
|
+
})
|
|
246
|
+
.then((result) => result[0]);
|
|
247
|
+
if (existingName) {
|
|
248
|
+
return res.status(400).json({
|
|
249
|
+
message: "Brand with this name already exists",
|
|
250
|
+
error: "Brand with this name already exists",
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
const brand = await brandService
|
|
254
|
+
.createBrands([
|
|
255
|
+
{
|
|
256
|
+
name: trimmedName,
|
|
257
|
+
slug: normalizedSlug,
|
|
258
|
+
description: trimmedDescription,
|
|
259
|
+
website: trimmedWebsite,
|
|
260
|
+
is_active: normalizedIsActive,
|
|
261
|
+
metadata: parsedMetadata,
|
|
262
|
+
},
|
|
263
|
+
])
|
|
264
|
+
.then((result) => result[0]);
|
|
265
|
+
return res.status(201).json({ brand });
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
logger.error("Error creating brand:", error);
|
|
269
|
+
return res.status(500).json({
|
|
270
|
+
message: "Failed to create brand",
|
|
271
|
+
error: "Failed to create brand",
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
exports.POST = POST;
|
|
276
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2JyYW5kcy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxxREFBc0U7QUFXdEUsTUFBTSxVQUFVLEdBQUcsNEJBQTRCLENBQUM7QUFDaEQsTUFBTSxlQUFlLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7QUFFdEUsTUFBTSxZQUFZLEdBQUcsQ0FBQyxLQUFhLEVBQUUsRUFBRSxDQUNyQyxLQUFLO0tBQ0YsV0FBVyxFQUFFO0tBQ2IsSUFBSSxFQUFFO0tBQ04sT0FBTyxDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUM7S0FDM0IsT0FBTyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUU3QixNQUFNLGlCQUFpQixHQUFHLENBQUMsS0FBYyxFQUFzQixFQUFFO0lBQy9ELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3pCLE9BQU8saUJBQWlCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVELE9BQU8sT0FBTyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUN2RCxDQUFDLENBQUM7QUFFRixNQUFNLFdBQVcsR0FBRyxDQUFDLEtBQXlCLEVBQUUsUUFBZ0IsRUFBRSxFQUFFO0lBQ2xFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNYLE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDN0IsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDNUIsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVELE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUMsQ0FBQztBQUVGLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxRQUFpQixFQUFFLEVBQUU7SUFDOUMsSUFBSSxRQUFRLEtBQUssU0FBUyxJQUFJLFFBQVEsS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUNoRCxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFFRCxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUM3RCxPQUFPLFFBQW1DLENBQUM7SUFDN0MsQ0FBQztJQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztBQUMxRCxDQUFDLENBQUM7QUFFRixNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQWtDLEVBQUUsRUFBRTtJQUM3RCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDYixPQUFPO0lBQ1QsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUMvQixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDYixPQUFPO0lBQ1QsQ0FBQztJQUVELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNyQyxNQUFNLElBQUksS0FBSyxDQUNiLCtEQUErRCxDQUNoRSxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxLQUFjLEVBQUUsUUFBaUIsRUFBRSxFQUFFO0lBQzdELElBQUksS0FBSyxLQUFLLFNBQVMsSUFBSSxLQUFLLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDMUMsT0FBTyxRQUFRLENBQUM7SUFDbEIsQ0FBQztJQUVELElBQUksT0FBTyxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDL0IsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUM5QixNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDOUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztZQUN2QyxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQ3hDLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztJQUNILENBQUM7SUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLG1DQUFtQyxDQUFDLENBQUM7QUFDdkQsQ0FBQyxDQUFDO0FBRUssTUFBTSxHQUFHLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ25FLE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBUSxDQUFDO0lBQzdELE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRW5FLElBQUksQ0FBQztRQUNILE1BQU0sVUFBVSxHQUFHLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbEQsTUFBTSxNQUFNLEdBQUcsaUJBQWlCLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNuRCxNQUFNLFdBQVcsR0FBRyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3pELE1BQU0sY0FBYyxHQUFHLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDL0QsTUFBTSxZQUFZLEdBQUcsaUJBQWlCLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2RCxNQUFNLFNBQVMsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBRXhFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQ3BCLElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQ2hFLEdBQUcsQ0FDSixDQUFDO1FBQ0YsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FDckIsV0FBVyxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQ25ELENBQUMsQ0FDRixDQUFDO1FBRUYsTUFBTSxPQUFPLEdBQTRCLEVBQUUsQ0FBQztRQUU1QyxJQUFJLE1BQU0sS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN4QixPQUFPLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUMzQixDQUFDO2FBQU0sSUFBSSxNQUFNLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDakMsT0FBTyxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDNUIsQ0FBQztRQUVELElBQUksU0FBUyxFQUFFLENBQUM7WUFDZCxPQUFPLENBQUMsSUFBSSxHQUFHLFNBQVMsQ0FBQztRQUMzQixDQUFDO1FBRUQsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxHQUFHLEdBQUc7Z0JBQ1osRUFBRSxJQUFJLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxVQUFVLEdBQUcsRUFBRSxFQUFFO2dCQUN2QyxFQUFFLElBQUksRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLFVBQVUsR0FBRyxFQUFFLEVBQUU7Z0JBQ3ZDLEVBQUUsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksVUFBVSxHQUFHLEVBQUUsRUFBRTthQUMvQyxDQUFDO1FBQ0osQ0FBQztRQUVELE1BQU0sVUFBVSxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUMsV0FBVyxJQUFJLEVBQUUsQ0FBQztZQUN2RCxDQUFDLENBQUUsV0FBb0Q7WUFDdkQsQ0FBQyxDQUFDLFlBQVksQ0FBQztRQUNqQixNQUFNLGNBQWMsR0FDbEIsY0FBYyxJQUFJLGNBQWMsQ0FBQyxXQUFXLEVBQUUsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO1FBRTVFLElBQUksT0FBTyxZQUFZLENBQUMsa0JBQWtCLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDMUQsTUFBTSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsR0FBRyxNQUFNLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUU7Z0JBQ3JFLEtBQUs7Z0JBQ0wsTUFBTTtnQkFDTixLQUFLLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLGNBQWMsRUFBRTthQUN4QyxDQUFDLENBQUM7WUFFSCxPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUM7Z0JBQ2QsTUFBTTtnQkFDTixLQUFLO2dCQUNMLE1BQU07Z0JBQ04sS0FBSzthQUNOLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxNQUFNLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztZQUN4QyxZQUFZLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRTtnQkFDL0IsS0FBSztnQkFDTCxNQUFNO2dCQUNOLEtBQUssRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsY0FBYyxFQUFFO2FBQ3hDLENBQUM7WUFDRixPQUFPLFlBQVksQ0FBQyxXQUFXLEtBQUssVUFBVTtnQkFDNUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDO2dCQUNuQyxDQUFDLENBQUMsWUFBWTtxQkFDVCxVQUFVLENBQUMsT0FBTyxDQUFDO3FCQUNuQixJQUFJLENBQUMsQ0FBQyxNQUFpQixFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO1NBQ2xELENBQUMsQ0FBQztRQUVILE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQztZQUNkLE1BQU07WUFDTixLQUFLO1lBQ0wsTUFBTTtZQUNOLEtBQUs7U0FDTixDQUFDLENBQUM7SUFDTCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE1BQU0sQ0FBQyxLQUFLLENBQUMsdUJBQXVCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDN0MsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUMxQixPQUFPLEVBQUUsdUJBQXVCO1lBQ2hDLEtBQUssRUFBRSx1QkFBdUI7U0FDL0IsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztBQUNILENBQUMsQ0FBQztBQXhGVyxRQUFBLEdBQUcsT0F3RmQ7QUFFSyxNQUFNLElBQUksR0FBRyxLQUFLLEVBQ3ZCLEdBQXNDLEVBQ3RDLEdBQW1CLEVBQ25CLEVBQUU7SUFDRixNQUFNLFlBQVksR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQVEsQ0FBQztJQUM3RCxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUVuRSxJQUFJLENBQUM7UUFDSCxJQUFJLE9BQU8sR0FBWSxHQUFHLENBQUMsSUFBSSxDQUFDO1FBRWhDLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQzdCLE9BQU8sR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3JDLENBQUM7UUFFRCxJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQztnQkFDSCxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQXVCLENBQUM7WUFDdEQsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsTUFBTSxDQUFDLEtBQUssQ0FBQyw4QkFBOEIsRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDcEQsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztvQkFDMUIsT0FBTyxFQUFFLGlDQUFpQztvQkFDMUMsS0FBSyxFQUFFLGlDQUFpQztpQkFDekMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztRQUNILENBQUM7UUFFRCxJQUFJLENBQUMsT0FBTyxJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzVDLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQzFCLE9BQU8sRUFBRSxvQ0FBb0M7Z0JBQzdDLEtBQUssRUFBRSxvQ0FBb0M7YUFDNUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxHQUM3RCxPQUE2QixDQUFDO1FBRWhDLElBQUksQ0FBQyxJQUFJLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7WUFDdEQsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDMUIsT0FBTyxFQUFFLGtCQUFrQjtnQkFDM0IsS0FBSyxFQUFFLGtCQUFrQjthQUMxQixDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsSUFDRSxXQUFXLEtBQUssU0FBUztZQUN6QixXQUFXLEtBQUssSUFBSTtZQUNwQixPQUFPLFdBQVcsS0FBSyxRQUFRLEVBQy9CLENBQUM7WUFDRCxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUMxQixPQUFPLEVBQUUsb0NBQW9DO2dCQUM3QyxLQUFLLEVBQUUsb0NBQW9DO2FBQzVDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxJQUNFLE9BQU8sS0FBSyxTQUFTO1lBQ3JCLE9BQU8sS0FBSyxJQUFJO1lBQ2hCLE9BQU8sT0FBTyxLQUFLLFFBQVEsRUFDM0IsQ0FBQztZQUNELE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQzFCLE9BQU8sRUFBRSxnQ0FBZ0M7Z0JBQ3pDLEtBQUssRUFBRSxnQ0FBZ0M7YUFDeEMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE1BQU0sY0FBYyxHQUFHLFlBQVksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLGNBQWMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQztZQUN4RCxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUMxQixPQUFPLEVBQ0wsZ0VBQWdFO2dCQUNsRSxLQUFLLEVBQUUsZ0VBQWdFO2FBQ3hFLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxJQUFJLGNBQWMsR0FBNEIsRUFBRSxDQUFDO1FBQ2pELElBQUksQ0FBQztZQUNILGNBQWMsR0FBRyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMvQyxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQzFCLE9BQU8sRUFBRyxLQUFlLENBQUMsT0FBTztnQkFDakMsS0FBSyxFQUFHLEtBQWUsQ0FBQyxPQUFPO2FBQ2hDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxJQUFJLGtCQUEyQixDQUFDO1FBQ2hDLElBQUksQ0FBQztZQUNILGtCQUFrQixHQUFHLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUN6RCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQzFCLE9BQU8sRUFBRyxLQUFlLENBQUMsT0FBTztnQkFDakMsS0FBSyxFQUFHLEtBQWUsQ0FBQyxPQUFPO2FBQ2hDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxJQUFJLENBQUM7WUFDSCxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDM0IsQ0FBQztRQUFDLE9BQU8sZUFBZSxFQUFFLENBQUM7WUFDekIsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDMUIsT0FBTyxFQUFHLGVBQXlCLENBQUMsT0FBTztnQkFDM0MsS0FBSyxFQUFHLGVBQXlCLENBQUMsT0FBTzthQUMxQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2hDLE1BQU0sY0FBYyxHQUFHLE9BQU8sRUFBRSxJQUFJLEVBQUUsSUFBSSxJQUFJLENBQUM7UUFDL0MsTUFBTSxrQkFBa0IsR0FBRyxXQUFXLEVBQUUsSUFBSSxFQUFFLElBQUksSUFBSSxDQUFDO1FBRXZELE1BQU0sWUFBWSxHQUFHLE1BQU0sWUFBWTthQUNwQyxVQUFVLENBQUM7WUFDVixJQUFJLEVBQUUsY0FBYztZQUNwQixVQUFVLEVBQUUsSUFBSTtTQUNqQixDQUFDO2FBQ0QsSUFBSSxDQUFDLENBQUMsTUFBYSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUV0QyxJQUFJLFlBQVksRUFBRSxDQUFDO1lBQ2pCLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQzFCLE9BQU8sRUFBRSxxQ0FBcUM7Z0JBQzlDLEtBQUssRUFBRSxxQ0FBcUM7YUFDN0MsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE1BQU0sWUFBWSxHQUFHLE1BQU0sWUFBWTthQUNwQyxVQUFVLENBQUM7WUFDVixJQUFJLEVBQUUsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFO1lBQzdCLFVBQVUsRUFBRSxJQUFJO1NBQ2pCLENBQUM7YUFDRCxJQUFJLENBQUMsQ0FBQyxNQUFhLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRXRDLElBQUksWUFBWSxFQUFFLENBQUM7WUFDakIsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDMUIsT0FBTyxFQUFFLHFDQUFxQztnQkFDOUMsS0FBSyxFQUFFLHFDQUFxQzthQUM3QyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsTUFBTSxLQUFLLEdBQUcsTUFBTSxZQUFZO2FBQzdCLFlBQVksQ0FBQztZQUNaO2dCQUNFLElBQUksRUFBRSxXQUFXO2dCQUNqQixJQUFJLEVBQUUsY0FBYztnQkFDcEIsV0FBVyxFQUFFLGtCQUFrQjtnQkFDL0IsT0FBTyxFQUFFLGNBQWM7Z0JBQ3ZCLFNBQVMsRUFBRSxrQkFBa0I7Z0JBQzdCLFFBQVEsRUFBRSxjQUFjO2FBQ3pCO1NBQ0YsQ0FBQzthQUNELElBQUksQ0FBQyxDQUFDLE1BQWEsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFdEMsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixNQUFNLENBQUMsS0FBSyxDQUFDLHVCQUF1QixFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzdDLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFDMUIsT0FBTyxFQUFFLHdCQUF3QjtZQUNqQyxLQUFLLEVBQUUsd0JBQXdCO1NBQ2hDLENBQUMsQ0FBQztJQUNMLENBQUM7QUFDSCxDQUFDLENBQUM7QUE1SlcsUUFBQSxJQUFJLFFBNEpmIn0=
|