42 lines
1.3 KiB
TypeScript
42 lines
1.3 KiB
TypeScript
import { defineMetadata, getMetadata } from "muddle/metadata";
|
|
|
|
export const HYDRATE_METADATA_KEY = "muddle:orm:hydrated";
|
|
|
|
export interface HydrateOptions<Value = any> {
|
|
/** Computes the value from the raw database row. */
|
|
decode?: (row: Record<string, unknown>) => Value;
|
|
/** Column the value is derived from, handed to `decode` as second argument. */
|
|
column?: string;
|
|
}
|
|
|
|
export interface HydrateDescriptor {
|
|
property: string;
|
|
options: HydrateOptions;
|
|
}
|
|
|
|
/** Declares a hydrated (computed) property. */
|
|
export function Hydrate<Value = any>(
|
|
options: HydrateOptions<Value> = {},
|
|
): PropertyDecorator {
|
|
return (target, propertyKey) => {
|
|
const constructor = target.constructor as object;
|
|
const hydrated = getHydratedProperties(constructor);
|
|
hydrated.set(String(propertyKey), {
|
|
property: String(propertyKey),
|
|
options: options as HydrateOptions,
|
|
});
|
|
};
|
|
}
|
|
|
|
/** Reads the hydrated properties declared on a model class. */
|
|
export function getHydratedProperties(
|
|
target: object,
|
|
): Map<string, HydrateDescriptor> {
|
|
const existing = getMetadata(HYDRATE_METADATA_KEY, target) as
|
|
| Map<string, HydrateDescriptor>
|
|
| undefined;
|
|
if (existing) return existing;
|
|
const hydrated = new Map<string, HydrateDescriptor>();
|
|
defineMetadata(HYDRATE_METADATA_KEY, hydrated, target);
|
|
return hydrated;
|
|
}
|