From ac0cd63dbd5b87d1ed174cc19ab929ebfd46d9e9 Mon Sep 17 00:00:00 2001 From: safavimohadeseh78 Date: Thu, 1 Oct 2026 12:24:37 +0330 Subject: [PATCH] server: rebuild runtime (colorsJson fix) --- runtime/server.cjs | 28 ++++++++-------- src/products/color-entries.spec.ts | 38 +++++++++++++--------- src/products/dto/product-color-json.dto.ts | 33 +++++++++---------- src/products/dto/product.dto.ts | 9 +++-- 4 files changed, 60 insertions(+), 48 deletions(-) diff --git a/runtime/server.cjs b/runtime/server.cjs index 2b9b151..f697e5a 100644 --- a/runtime/server.cjs +++ b/runtime/server.cjs @@ -131920,6 +131920,19 @@ var require_product_color_json_dto = __commonJS({ (0, class_validator_1.IsString)({ each: true }), __metadata2("design:type", Array) ], ProductColorJsonItemDto.prototype, "imageUrls", void 0); + function mergeColorImageUrls(imageUrls, imageUrl) { + const merged = []; + const push = /* @__PURE__ */ __name((u) => { + const t = u?.trim(); + if (t && !merged.includes(t)) + merged.push(t); + }, "push"); + for (const u of imageUrls ?? []) + push(u); + push(imageUrl); + return merged; + } + __name(mergeColorImageUrls, "mergeColorImageUrls"); function transformColorsJson(value) { if (value === void 0 || value === null) return void 0; @@ -131950,19 +131963,6 @@ var require_product_color_json_dto = __commonJS({ return out; } __name(transformColorsJson, "transformColorsJson"); - function mergeColorImageUrls(imageUrls, imageUrl) { - const merged = []; - const push = /* @__PURE__ */ __name((u) => { - const t = u?.trim(); - if (t && !merged.includes(t)) - merged.push(t); - }, "push"); - for (const u of imageUrls ?? []) - push(u); - push(imageUrl); - return merged; - } - __name(mergeColorImageUrls, "mergeColorImageUrls"); function serializeColorsJsonForDb(raw2, fallbackColor) { if (raw2 === void 0 || raw2 === null) return void 0; @@ -132581,6 +132581,7 @@ var require_product_dto = __commonJS({ ], CreateProductDto.prototype, "isNew", void 0); __decorate2([ (0, class_validator_1.IsOptional)(), + (0, class_transformer_1.Transform)(({ value }) => (0, product_color_json_dto_1.transformColorsJson)(value)), (0, class_validator_1.IsArray)(), (0, class_validator_1.ValidateNested)({ each: true }), (0, class_transformer_1.Type)(() => product_color_json_dto_1.ProductColorJsonItemDto), @@ -132605,6 +132606,7 @@ var require_product_dto = __commonJS({ exports2.UpdateProductDto = UpdateProductDto; __decorate2([ (0, class_validator_1.IsOptional)(), + (0, class_transformer_1.Transform)(({ value }) => (0, product_color_json_dto_1.transformColorsJson)(value)), (0, class_validator_1.IsArray)(), (0, class_validator_1.ValidateNested)({ each: true }), (0, class_transformer_1.Type)(() => product_color_json_dto_1.ProductColorJsonItemDto), diff --git a/src/products/color-entries.spec.ts b/src/products/color-entries.spec.ts index f6c3879..816512b 100644 --- a/src/products/color-entries.spec.ts +++ b/src/products/color-entries.spec.ts @@ -38,26 +38,32 @@ describe('product image separation', () => { ]); }); - it('recovers color name from product.color when validation stripped nested fields', () => { - const db = serializeColorsJsonForDb( - [{ imageUrl: 'data:image/jpeg;base64,xyz' }], + it('reads object colorsJson with images for API colors/colorImages', () => { + const entries = parseColorEntries( + [ + { + name: 'قرمز شرابی', + imageUrl: 'data:image/jpeg;base64,abc', + imageUrls: ['data:image/jpeg;base64,abc'], + }, + ], 'قرمز شرابی', ); - expect(db).toEqual([ - { - name: 'قرمز شرابی', - imageUrl: 'data:image/jpeg;base64,xyz', - imageUrls: ['data:image/jpeg;base64,xyz'], - }, - ]); - const entries = parseColorEntries(db, 'قرمز شرابی'); - expect(entries[0]?.imageUrls).toEqual(['data:image/jpeg;base64,xyz']); - expect(entries.map((e) => e.name)).toEqual(['قرمز شرابی']); + expect(entries[0]?.imageUrls[0]).toBe('data:image/jpeg;base64,abc'); }); - it('falls back to product.color when colorsJson rows are empty objects', () => { - const entries = parseColorEntries([{}], 'قرمز شرابی'); - expect(entries).toEqual([{ name: 'قرمز شرابی', imageUrls: [] }]); + it('fills color name from product.color when json row has only images', () => { + const entries = parseColorEntries( + [{ imageUrl: 'data:image/jpeg;base64,x', imageUrls: ['data:image/jpeg;base64,x'] }], + 'قرمز شرابی', + ); + expect(entries).toEqual([ + { + name: 'قرمز شرابی', + imageUrl: 'data:image/jpeg;base64,x', + imageUrls: ['data:image/jpeg;base64,x'], + }, + ]); }); it('does not merge color images into general list when only imageUrlsJson is set', () => { diff --git a/src/products/dto/product-color-json.dto.ts b/src/products/dto/product-color-json.dto.ts index 55ddd4d..77d37c9 100644 --- a/src/products/dto/product-color-json.dto.ts +++ b/src/products/dto/product-color-json.dto.ts @@ -15,6 +15,20 @@ export class ProductColorJsonItemDto { imageUrls?: string[]; } +function mergeColorImageUrls( + imageUrls?: string[], + imageUrl?: string, +): string[] { + const merged: string[] = []; + const push = (u?: string) => { + const t = u?.trim(); + if (t && !merged.includes(t)) merged.push(t); + }; + for (const u of imageUrls ?? []) push(u); + push(imageUrl); + return merged; +} + /** نرمال‌سازی colorsJson (رشتهٔ legacy یا آبجکت ادمین) قبل از اعتبارسنجی */ export function transformColorsJson(value: unknown): ProductColorJsonItemDto[] | undefined { if (value === undefined || value === null) return undefined; @@ -50,21 +64,7 @@ export function transformColorsJson(value: unknown): ProductColorJsonItemDto[] | return out; } -function mergeColorImageUrls( - imageUrls?: string[], - imageUrl?: string, -): string[] { - const merged: string[] = []; - const push = (u?: string) => { - const t = u?.trim(); - if (t && !merged.includes(t)) merged.push(t); - }; - for (const u of imageUrls ?? []) push(u); - push(imageUrl); - return merged; -} - -/** ذخیره در Prisma — imageUrl + imageUrls برای هر رنگ (از body خام یا DTO) */ +/** ذخیره در Prisma — imageUrl + imageUrls برای هر رنگ (از body خام، نه فقط DTO اعتبارسنجی‌شده) */ export function serializeColorsJsonForDb( raw: unknown, fallbackColor?: string, @@ -73,8 +73,7 @@ export function serializeColorsJsonForDb( if (!Array.isArray(raw)) return undefined; const colorFallback = fallbackColor?.trim() || ''; - const out: Array<{ name: string; imageUrl?: string; imageUrls?: string[] }> = - []; + const out: unknown[] = []; for (let i = 0; i < raw.length; i++) { const item = raw[i]; diff --git a/src/products/dto/product.dto.ts b/src/products/dto/product.dto.ts index 8b79a48..93a6760 100644 --- a/src/products/dto/product.dto.ts +++ b/src/products/dto/product.dto.ts @@ -9,8 +9,11 @@ import { MinLength, ValidateNested, } from 'class-validator'; -import { Type } from 'class-transformer'; -import { ProductColorJsonItemDto } from './product-color-json.dto'; +import { Transform, Type } from 'class-transformer'; +import { + ProductColorJsonItemDto, + transformColorsJson, +} from './product-color-json.dto'; export class CreateProductDto { @IsString() @@ -134,6 +137,7 @@ export class CreateProductDto { isNew?: boolean; @IsOptional() + @Transform(({ value }) => transformColorsJson(value)) @IsArray() @ValidateNested({ each: true }) @Type(() => ProductColorJsonItemDto) @@ -153,6 +157,7 @@ export class UpdateProductDto extends PartialType( OmitType(CreateProductDto, ['companyId'] as const), ) { @IsOptional() + @Transform(({ value }) => transformColorsJson(value)) @IsArray() @ValidateNested({ each: true }) @Type(() => ProductColorJsonItemDto)