Files
chartdb/src/lib/domain/db-field.ts
2025-09-04 12:10:56 +03:00

119 lines
3.0 KiB
TypeScript

import { z } from 'zod';
import {
dataTypeSchema,
findDataTypeDataById,
type DataType,
} from '../data/data-types/data-types';
import type { DatabaseType } from './database-type';
export interface DBField {
id: string;
name: string;
type: DataType;
primaryKey: boolean;
unique: boolean;
nullable: boolean;
increment?: boolean | null;
createdAt: number;
characterMaximumLength?: string | null;
precision?: number | null;
scale?: number | null;
default?: string | null;
collation?: string | null;
comments?: string | null;
}
export const dbFieldSchema: z.ZodType<DBField> = z.object({
id: z.string(),
name: z.string(),
type: dataTypeSchema,
primaryKey: z.boolean(),
unique: z.boolean(),
nullable: z.boolean(),
increment: z.boolean().or(z.null()).optional(),
createdAt: z.number(),
characterMaximumLength: z.string().or(z.null()).optional(),
precision: z.number().or(z.null()).optional(),
scale: z.number().or(z.null()).optional(),
default: z.string().or(z.null()).optional(),
collation: z.string().or(z.null()).optional(),
comments: z.string().or(z.null()).optional(),
});
export const generateDBFieldSuffix = (
field: DBField,
{
databaseType,
forceExtended = false,
typeId,
}: {
databaseType?: DatabaseType;
forceExtended?: boolean;
typeId?: string;
} = {}
): string => {
if (databaseType && forceExtended && typeId) {
return generateExtendedSuffix(field, databaseType, typeId);
}
return generateStandardSuffix(field);
};
const generateExtendedSuffix = (
field: DBField,
databaseType: DatabaseType,
typeId: string
): string => {
const type = findDataTypeDataById(typeId, databaseType);
if (!type?.fieldAttributes) {
return '';
}
const { fieldAttributes } = type;
// Character maximum length types (e.g., VARCHAR)
if (fieldAttributes.hasCharMaxLength) {
const maxLength = field.characterMaximumLength ?? 'n';
return `(${maxLength})`;
}
// Precision and scale types (e.g., DECIMAL)
if (fieldAttributes.precision && fieldAttributes.scale) {
return formatPrecisionAndScale(field.precision, field.scale, '(p, s)');
}
// Precision only types (e.g., FLOAT)
if (fieldAttributes.precision) {
const precision = field.precision ?? 'p';
return `(${precision})`;
}
return '';
};
const generateStandardSuffix = (field: DBField): string => {
// Character maximum length
if (field.characterMaximumLength) {
return `(${field.characterMaximumLength})`;
}
return formatPrecisionAndScale(field.precision, field.scale, '');
};
const formatPrecisionAndScale = (
precision: number | null | undefined,
scale: number | null | undefined,
fallback: string
): string => {
if (precision && scale) {
return `(${precision}, ${scale})`;
}
if (precision) {
return `(${precision})`;
}
return fallback;
};