Created
November 19, 2024 08:05
-
-
Save Evanion/edee156e2e9423e67ee8edfec77dc730 to your computer and use it in GitHub Desktop.
Input decorator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'reflect-metadata'; | |
import { InputHTMLAttributes } from 'react'; | |
import { ClassConstructor } from 'class-transformer'; | |
export type InputOptions = Omit< | |
InputHTMLAttributes<HTMLInputElement>, | |
'name' | |
> & { | |
label?: string; | |
}; | |
const defaultOptions: InputOptions = { | |
type: 'text', | |
}; | |
/** | |
* Property decorator for input fields | |
* @param props | |
* @returns | |
*/ | |
export function Input(props: InputOptions): PropertyDecorator { | |
return (target: Object, propertyKey: string | symbol) => { | |
// First we need to register the property as a field on the class | |
// This is done by adding a metadata key to the class prototype | |
// The metadata key is `fields` and the value is an array of field names | |
const fields = Reflect.getMetadata('fields', target) || []; | |
Reflect.defineMetadata('fields', [...fields, propertyKey], target); | |
// Get the fieldType for the property | |
const propertyType = Reflect.getMetadata( | |
'design:type', | |
target, | |
propertyKey | |
); | |
if (!propertyType) { | |
console.warn( | |
`Property type metadata is undefined for ${String(propertyKey)}` | |
); | |
} | |
// Determine the type (string, number, boolean, etc.) | |
const dataType = typeof propertyType; | |
// set some default values | |
const defaultProps = { ...defaultOptions, dataType, ...props }; | |
// Next we need to store the field metadata on the property itself | |
Reflect.defineMetadata('field', defaultProps, target, propertyKey); | |
}; | |
} | |
export function getFields<Schema extends ClassConstructor<Object>>( | |
schema: Schema | |
) { | |
const fields = Reflect.getMetadata('fields', schema.prototype); | |
const fieldsData = fields.map((name: string) => { | |
const fieldData = Reflect.getMetadata('field', schema.prototype, name); | |
return { name, ...fieldData }; | |
}); | |
return fieldsData; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment