feat: normalize and validate component model structure

This commit is contained in:
MatthieuTD
2025-10-01 11:47:45 +02:00
parent f48e7aad30
commit 1a4cedb431
8 changed files with 383 additions and 25 deletions

View File

@@ -0,0 +1,109 @@
import type { ComponentModelStructure } from '../shared/types/inventory';
type InputValue = Record<string, unknown> | null | undefined;
const toArray = (value: unknown): unknown[] => {
if (Array.isArray(value)) {
return value;
}
if (value === undefined || value === null) {
return [];
}
return [value];
};
const sanitizeRole = (role: unknown): string | undefined => {
if (role === undefined || role === null) {
return undefined;
}
const stringValue = String(role).trim();
return stringValue ? stringValue : undefined;
};
const sanitizeAlias = (alias: unknown): string | undefined => {
if (alias === undefined || alias === null) {
return undefined;
}
const stringValue = String(alias).trim();
return stringValue ? stringValue : undefined;
};
const ensureString = (value: unknown): string => String(value ?? '');
export function normalizeComponentModelStructure(
input: unknown,
): ComponentModelStructure {
const structure = (input ?? {}) as InputValue;
const pieces = toArray((structure as any)?.pieces).map((piece) => {
const candidate = piece as Record<string, unknown> | null | undefined;
if (candidate?.familyCode) {
return {
familyCode: ensureString(candidate.familyCode).trim() || 'UNKNOWN',
role: sanitizeRole(candidate.role),
} as ComponentModelStructure['pieces'][number];
}
if (candidate?.typePieceId) {
return {
typePieceId: ensureString(candidate.typePieceId).trim() || 'UNKNOWN',
role: sanitizeRole(candidate.role),
} as ComponentModelStructure['pieces'][number];
}
return {
familyCode:
ensureString(
candidate?.familyCode ?? candidate?.name ?? candidate?.typePieceLabel ?? 'UNKNOWN',
).trim() || 'UNKNOWN',
role: sanitizeRole(candidate?.role),
} as ComponentModelStructure['pieces'][number];
});
const customFields = toArray((structure as any)?.customFields).map((field) => {
const candidate = field as Record<string, unknown> | null | undefined;
const key = ensureString(candidate?.key ?? candidate?.name ?? 'unknown').trim();
return {
key: key || 'unknown',
value: candidate?.value ?? null,
};
});
const rawSubcomponents = toArray(
(structure as any)?.subcomponents ?? (structure as any)?.subComponents,
);
const subcomponents = rawSubcomponents.map((subcomponent) => {
const candidate = subcomponent as Record<string, unknown> | null | undefined;
if (candidate?.modelId) {
return {
modelId: ensureString(candidate.modelId).trim() || 'UNKNOWN',
alias: sanitizeAlias(candidate?.alias ?? candidate?.name),
} as ComponentModelStructure['subcomponents'][number];
}
if (candidate?.familyCode) {
return {
familyCode: ensureString(candidate.familyCode).trim() || 'UNKNOWN',
alias: sanitizeAlias(candidate?.alias ?? candidate?.name),
} as ComponentModelStructure['subcomponents'][number];
}
if (candidate?.typeComposantId) {
return {
typeComposantId: ensureString(candidate.typeComposantId).trim() || 'UNKNOWN',
alias: sanitizeAlias(candidate?.alias ?? candidate?.name),
} as ComponentModelStructure['subcomponents'][number];
}
return {
familyCode: ensureString(candidate?.name ?? 'UNKNOWN').trim() || 'UNKNOWN',
alias: sanitizeAlias(candidate?.alias ?? candidate?.name),
} as ComponentModelStructure['subcomponents'][number];
});
return {
pieces,
customFields,
subcomponents,
};
}