x
This commit is contained in:
1 parent
fb776f778f
commit
8f64d89f6f
13 files changed
+779
-295
No files matched your search
+230
@@ -0,0 +1,230 @@
|
||||
import re
|
||||
|
||||
filePath = 'apps/backend/src/routes/pages.ts'
|
||||
with open(filePath, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# 1. Update imports
|
||||
old_imports = """import {
|
||||
LocalizedStringSchema,
|
||||
HeroSectionPayloadSchema,
|
||||
CategoriesSectionPayloadSchema,
|
||||
ProductsSectionPayloadSchema,
|
||||
BannerSectionPayloadSchema,
|
||||
TextSectionPayloadSchema,
|
||||
AnnouncementBarSectionPayloadSchema,
|
||||
NewsletterSectionPayloadSchema,
|
||||
EditorialTileSectionPayloadSchema,
|
||||
EditorialCarouselSectionPayloadSchema,
|
||||
HeroArticlePayloadSchema,
|
||||
RichTextPayloadSchema,
|
||||
ScentNotesBreakdownPayloadSchema,
|
||||
QuoteCalloutPayloadSchema,
|
||||
ProductCarouselPayloadSchema,
|
||||
AccordionSectionPayloadSchema,
|
||||
ContactInfoSectionPayloadSchema,
|
||||
ContactFormSectionPayloadSchema
|
||||
} from "@homaroma/types";"""
|
||||
|
||||
new_imports = """import {
|
||||
LocalizedStringSchema,
|
||||
HeroSectionPayloadSchema,
|
||||
CategoriesSectionPayloadSchema,
|
||||
ProductsSectionPayloadSchema,
|
||||
BannerSectionPayloadSchema,
|
||||
TextSectionPayloadSchema,
|
||||
AnnouncementBarSectionPayloadSchema,
|
||||
NewsletterSectionPayloadSchema,
|
||||
EditorialTileSectionPayloadSchema,
|
||||
EditorialCarouselSectionPayloadSchema,
|
||||
HeroArticleSectionPayloadSchema,
|
||||
RichTextSectionPayloadSchema,
|
||||
ScentNotesBreakdownSectionPayloadSchema,
|
||||
QuoteCalloutSectionPayloadSchema,
|
||||
ProductCarouselSectionPayloadSchema,
|
||||
AccordionSectionPayloadSchema,
|
||||
ContactInfoSectionPayloadSchema,
|
||||
ContactFormSectionPayloadSchema
|
||||
} from "@homaroma/types";
|
||||
import { z } from "zod";"""
|
||||
|
||||
content = content.replace(old_imports, new_imports)
|
||||
|
||||
# 2. Remove manual validation functions
|
||||
# From 'function isLocalizedStringValue' up to 'const RESERVED_SLUGS'
|
||||
start_idx = content.find('function isLocalizedStringValue')
|
||||
end_idx = content.find('const RESERVED_SLUGS')
|
||||
|
||||
if start_idx != -1 and end_idx != -1:
|
||||
content = content[:start_idx] + content[end_idx:]
|
||||
|
||||
# 3. Refactor validateSectionPayload
|
||||
old_validate_func = """function validateSectionPayload(type: string, payload: any): string | null {
|
||||
if (!payload || typeof payload !== 'object') {
|
||||
return "Payload must be a JSON object";
|
||||
}
|
||||
|
||||
switch (type.toUpperCase()) {
|
||||
case 'HERO': {
|
||||
const res = HeroSectionPayloadSchema.safeParse(payload);
|
||||
if (!res.success) return res.error.issues.map((e: any) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
||||
break;
|
||||
}
|
||||
case 'CATEGORIES': {
|
||||
const res = CategoriesSectionPayloadSchema.safeParse(payload);
|
||||
if (!res.success) return res.error.issues.map((e: any) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
||||
break;
|
||||
}
|
||||
case 'PRODUCTS': {
|
||||
const res = ProductsSectionPayloadSchema.safeParse(payload);
|
||||
if (!res.success) return res.error.issues.map((e: any) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
||||
break;
|
||||
}
|
||||
case 'BANNER': {
|
||||
const res = BannerSectionPayloadSchema.safeParse(payload);
|
||||
if (!res.success) return res.error.issues.map((e: any) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
||||
break;
|
||||
}
|
||||
case 'TEXT': {
|
||||
const res = TextSectionPayloadSchema.safeParse(payload);
|
||||
if (!res.success) return res.error.issues.map((e: any) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
||||
break;
|
||||
}
|
||||
case 'ANNOUNCEMENT_BAR': {
|
||||
const res = AnnouncementBarSectionPayloadSchema.safeParse(payload);
|
||||
if (!res.success) return res.error.issues.map((e: any) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
||||
break;
|
||||
}
|
||||
case 'NEWSLETTER': {
|
||||
const res = NewsletterSectionPayloadSchema.safeParse(payload);
|
||||
if (!res.success) return res.error.issues.map((e: any) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
||||
break;
|
||||
}
|
||||
case 'EDITORIAL_TILE': {
|
||||
const res = EditorialTileSectionPayloadSchema.safeParse(payload);
|
||||
if (!res.success) return res.error.issues.map((e: any) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
||||
break;
|
||||
}
|
||||
case 'EDITORIAL_CAROUSEL': {
|
||||
const res = EditorialCarouselSectionPayloadSchema.safeParse(payload);
|
||||
if (!res.success) return res.error.issues.map((e: any) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
||||
break;
|
||||
}
|
||||
case 'HERO_ARTICLE': {
|
||||
const error = validateHeroArticlePayload(payload);
|
||||
if (error) return error;
|
||||
break;
|
||||
}
|
||||
case 'RICH_TEXT': {
|
||||
const error = validateRichTextPayload(payload);
|
||||
if (error) return error;
|
||||
break;
|
||||
}
|
||||
case 'SCENT_NOTES_BREAKDOWN': {
|
||||
const error = validateScentNotesBreakdownPayload(payload);
|
||||
if (error) return error;
|
||||
break;
|
||||
}
|
||||
case 'QUOTE_CALLOUT': {
|
||||
const error = validateQuoteCalloutPayload(payload);
|
||||
if (error) return error;
|
||||
break;
|
||||
}
|
||||
case 'PRODUCT_CAROUSEL': {
|
||||
const error = validateProductCarouselPayload(payload);
|
||||
if (error) return error;
|
||||
break;
|
||||
}
|
||||
case 'ACCORDION': {
|
||||
const error = validateAccordionPayload(payload);
|
||||
if (error) return error;
|
||||
break;
|
||||
}
|
||||
case 'CONTACT_INFO': {
|
||||
const error = validateContactInfoPayload(payload);
|
||||
if (error) return error;
|
||||
break;
|
||||
}
|
||||
case 'CONTACT_FORM': {
|
||||
const error = validateContactFormPayload(payload);
|
||||
if (error) return error;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return `Unknown section type: ${type}`;
|
||||
}
|
||||
|
||||
return null;
|
||||
}"""
|
||||
|
||||
new_validate_func = """function validateSectionPayload(type: string, payload: any): { success: boolean; issues?: z.ZodIssue[] } {
|
||||
if (!payload || typeof payload !== 'object') {
|
||||
return { success: false, issues: [{ code: 'custom', message: "Payload must be a JSON object", path: [] }] as z.ZodIssue[] };
|
||||
}
|
||||
|
||||
let schema: z.ZodTypeAny;
|
||||
|
||||
switch (type.toUpperCase()) {
|
||||
case 'HERO': schema = HeroSectionPayloadSchema; break;
|
||||
case 'CATEGORIES': schema = CategoriesSectionPayloadSchema; break;
|
||||
case 'PRODUCTS': schema = ProductsSectionPayloadSchema; break;
|
||||
case 'BANNER': schema = BannerSectionPayloadSchema; break;
|
||||
case 'TEXT': schema = TextSectionPayloadSchema; break;
|
||||
case 'ANNOUNCEMENT_BAR': schema = AnnouncementBarSectionPayloadSchema; break;
|
||||
case 'NEWSLETTER': schema = NewsletterSectionPayloadSchema; break;
|
||||
case 'EDITORIAL_TILE': schema = EditorialTileSectionPayloadSchema; break;
|
||||
case 'EDITORIAL_CAROUSEL': schema = EditorialCarouselSectionPayloadSchema; break;
|
||||
case 'HERO_ARTICLE': schema = HeroArticleSectionPayloadSchema; break;
|
||||
case 'RICH_TEXT': schema = RichTextSectionPayloadSchema; break;
|
||||
case 'SCENT_NOTES_BREAKDOWN': schema = ScentNotesBreakdownSectionPayloadSchema; break;
|
||||
case 'QUOTE_CALLOUT': schema = QuoteCalloutSectionPayloadSchema; break;
|
||||
case 'PRODUCT_CAROUSEL': schema = ProductCarouselSectionPayloadSchema; break;
|
||||
case 'ACCORDION': schema = AccordionSectionPayloadSchema; break;
|
||||
case 'CONTACT_INFO': schema = ContactInfoSectionPayloadSchema; break;
|
||||
case 'CONTACT_FORM': schema = ContactFormSectionPayloadSchema; break;
|
||||
default:
|
||||
return { success: false, issues: [{ code: 'custom', message: `Unknown section type: ${type}`, path: [] }] as z.ZodIssue[] };
|
||||
}
|
||||
|
||||
const res = schema.safeParse(payload);
|
||||
if (!res.success) {
|
||||
return { success: false, issues: res.error.issues };
|
||||
}
|
||||
return { success: true };
|
||||
}"""
|
||||
|
||||
# I need to use re.sub for validateSectionPayload in case of slight whitespace differences, but a simple find+replace is safer if exact.
|
||||
# Let's just use re.sub with a regex that captures everything from `function validateSectionPayload(type: string, payload: any): string | null {` to the end of the file.
|
||||
pattern = r'function validateSectionPayload\(type: string, payload: any\): string \| null \{[\s\S]*'
|
||||
content = re.sub(pattern, new_validate_func, content)
|
||||
|
||||
|
||||
# 4. Update error handling in POST and PUT
|
||||
# POST
|
||||
old_post_err = """ const validationError = validateSectionPayload(type, payload);
|
||||
if (validationError) {
|
||||
set.status = 400;
|
||||
return { error: validationError };
|
||||
}"""
|
||||
new_post_err = """ const validationResult = validateSectionPayload(type, payload);
|
||||
if (!validationResult.success) {
|
||||
set.status = 400;
|
||||
return { error: "Validation failed", details: validationResult.issues };
|
||||
}"""
|
||||
content = content.replace(old_post_err, new_post_err)
|
||||
|
||||
# PUT
|
||||
old_put_err = """ const validationError = validateSectionPayload(validationType, payload);
|
||||
if (validationError) {
|
||||
set.status = 400;
|
||||
return { error: validationError };
|
||||
}"""
|
||||
new_put_err = """ const validationResult = validateSectionPayload(validationType, payload);
|
||||
if (!validationResult.success) {
|
||||
set.status = 400;
|
||||
return { error: "Validation failed", details: validationResult.issues };
|
||||
}"""
|
||||
content = content.replace(old_put_err, new_put_err)
|
||||
|
||||
with open(filePath, 'w') as f:
|
||||
f.write(content)
|
||||
Reference in new issue
Block a user