turash/bugulma/frontend/lib/organization-transformer.ts
Damir Mukimov 6347f42e20
Consolidate repositories: Remove nested frontend .git and merge into main repository
- Remove nested git repository from bugulma/frontend/.git
- Add all frontend files to main repository tracking
- Convert from separate frontend/backend repos to unified monorepo
- Preserve all frontend code and development history as tracked files
- Eliminate nested repository complexity for simpler development workflow

This creates a proper monorepo structure with frontend and backend
coexisting in the same repository for easier development and deployment.
2025-11-25 06:02:57 +01:00

107 lines
3.5 KiB
TypeScript

/**
* Organization data transformation utilities
* Handles business logic for transforming and validating organization data
* Separated from API services to maintain clean separation of concerns
*/
import { z } from 'zod';
import type { BackendOrganization } from '@/schemas/backend/organization';
/**
* Fallback schema for handling legacy/malformed organization data
* Used when strict validation fails
*/
const fallbackOrganizationSchema = z
.object({
ID: z.string().optional(),
id: z.string().optional(),
Name: z.string().optional(),
name: z.string().optional(),
Sector: z.string().optional(),
sector: z.string().optional(),
Description: z.string().optional(),
description: z.string().optional(),
LogoURL: z.string().optional(),
logoURL: z.string().optional(),
logoUrl: z.string().optional(),
Website: z.string().optional(),
website: z.string().optional(),
Address: z.string().optional(),
address: z.string().optional(),
Verified: z.boolean().optional(),
verified: z.boolean().optional(),
Subtype: z.string().optional(),
subtype: z.string().optional(),
Latitude: z.number().optional(),
latitude: z.number().optional(),
Longitude: z.number().optional(),
longitude: z.number().optional(),
CreatedAt: z.string().optional(),
createdAt: z.string().optional(),
UpdatedAt: z.string().optional(),
updatedAt: z.string().optional(),
})
.transform((org) => ({
ID: org.ID || org.id || '',
Name: org.Name || org.name || '',
Sector: org.Sector || org.sector || '',
Description: org.Description || org.description || '',
LogoURL: org.LogoURL || org.logoURL || org.logoUrl,
Website: org.Website || org.website,
Address: org.Address || org.address,
Verified: org.Verified ?? org.verified ?? false,
Subtype: org.Subtype || org.subtype,
Latitude: org.Latitude ?? org.latitude,
Longitude: org.Longitude ?? org.longitude,
CreatedAt: org.CreatedAt || org.createdAt,
UpdatedAt: org.UpdatedAt || org.updatedAt,
}));
/**
* Transform raw organization data with fallback logic
* Handles both strict validation and legacy data formats
*/
export function transformOrganizationData(data: unknown): BackendOrganization {
// First try strict validation
const strictSchema = z.object({
ID: z.string(),
Name: z.string(),
Sector: z.string(),
Description: z.string().optional(),
LogoURL: z.string().optional(),
Website: z.string().optional(),
Address: z.string().optional(),
Verified: z.boolean(),
Subtype: z.string().optional(),
Latitude: z.number().optional(),
Longitude: z.number().optional(),
CreatedAt: z.string().optional(),
UpdatedAt: z.string().optional(),
});
const strictResult = strictSchema.safeParse(data);
if (strictResult.success) {
return strictResult.data as BackendOrganization;
}
// Fall back to flexible transformation
const fallbackResult = fallbackOrganizationSchema.safeParse(data);
if (fallbackResult.success) {
return fallbackResult.data as BackendOrganization;
}
throw new Error('Unable to transform organization data');
}
/**
* Transform array of organization data with filtering
* Removes organizations with invalid IDs and applies transformations
*/
export function transformOrganizationsList(data: unknown[]): BackendOrganization[] {
if (!Array.isArray(data)) {
throw new Error('Expected array of organizations');
}
return data.map(transformOrganizationData).filter((org) => org.ID && org.ID.trim() !== '');
}