40 lines
1.3 KiB
TypeScript
40 lines
1.3 KiB
TypeScript
import { defineMetadata, getMetadata } from "muddle/metadata";
|
|
import type { FieldOptions } from "muddle/contracts/typegen/orm/field.ts";
|
|
import type { FieldDescriptor } from "muddle/contracts/typegen/orm/field.ts";
|
|
|
|
export const FIELD_METADATA_KEY = "muddle:orm:fields";
|
|
|
|
/** Converts a property name into the default column name. */
|
|
export function toColumnName(property: string): string {
|
|
return property
|
|
.replace(/([a-z0-9])([A-Z])/g, "$1_$2")
|
|
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2")
|
|
.toLowerCase();
|
|
}
|
|
|
|
/** Declares the column backing a property. */
|
|
export function Field<Value = any>(
|
|
options: FieldOptions<Value>,
|
|
): PropertyDecorator {
|
|
return (target, propertyKey) => {
|
|
const constructor = target.constructor as object;
|
|
const fields = getFields(constructor);
|
|
const property = String(propertyKey);
|
|
fields.set(property, {
|
|
property,
|
|
column: options.column ?? toColumnName(property),
|
|
options,
|
|
});
|
|
};
|
|
}
|
|
|
|
/** Reads the fields declared on a model class. */
|
|
export function getFields(target: object): Map<string, FieldDescriptor> {
|
|
const existing = getMetadata(FIELD_METADATA_KEY, target) as
|
|
| Map<string, FieldDescriptor>
|
|
| undefined;
|
|
if (existing) return existing;
|
|
const fields = new Map<string, FieldDescriptor>();
|
|
defineMetadata(FIELD_METADATA_KEY, fields, target);
|
|
return fields;
|
|
}
|