import { type PropertyType } from './decorators/primitive.ts' import { type Condition, ConditionSymbol } from './decorators/condition.ts' import { type Controller, ControllerSymbol } from './decorators/controller.ts' import { type Transformer, TransformerSymbol } from './decorators/transformer.ts' import { type Validator, ValidatorSymbol } from './decorators/validator.ts' import { type BitField, BitFieldSymbol } from './decorators/bitfield.ts' import { type Ctx, CtxSymbol } from './decorators/context.ts' import { type PrePost, PreFunctionSymbol, PostFunctionSymbol, PreClassFunctionSymbol, PostClassFunctionSymbol, PrePostSymbols, PrePostClass } from './decorators/prepost.ts' import { type DecoratorMetadataObject } from './types.ts' import './symbol-polyfill.ts' type MetadataSymbol = typeof BitFieldSymbol | typeof PreClassFunctionSymbol | typeof PreFunctionSymbol | typeof ConditionSymbol | typeof ControllerSymbol | typeof TransformerSymbol | typeof ValidatorSymbol | typeof CtxSymbol | typeof PostFunctionSymbol | typeof PostClassFunctionSymbol function getClassMetadata ( metadata: DecoratorMetadataObject, metadataKey: MetadataSymbol, ): T[] { if (metadata[metadataKey] === undefined) { metadata[metadataKey] = [] } const meta = metadata[metadataKey] return Array.isArray(meta) ? meta : [] } function removeClassMetadata ( metadata: DecoratorMetadataObject, metadataKey: MetadataSymbol, rmValue: any, ): T[] { const metas = getClassMetadata(metadata, metadataKey) const newMetas = metas.filter((x: any) => x.id !== rmValue.id) metadata[metadataKey] = newMetas return metadata[metadataKey] } function setClassMetadata ( metadata: DecoratorMetadataObject, metadataKey: MetadataSymbol, newValue: any, reverse = false, ): T[] { const metas = getClassMetadata(metadata, metadataKey) const newMetas = reverse ? [newValue, ...metas] : [...metas, newValue] metadata[metadataKey] = newMetas return newMetas } function getMetadata ( metadata: DecoratorMetadataObject, propertyKey: string | number | symbol, metadataKey: MetadataSymbol, reverse = false, ): T[] { // TODO Can be optionnal since its set on the set metadata if (metadata[metadataKey] === undefined) { metadata[metadataKey] = {} } const meta = (metadata[metadataKey][propertyKey] || []).slice() return reverse ? meta.reverse() : meta } function removeMetadata ( metadata: DecoratorMetadataObject, propertyKey: string | symbol | number, metadataKey: MetadataSymbol, rmValue: any, ): T[] { const metas = getMetadata(metadata, propertyKey, metadataKey) const newMetas = metas.filter((x: any) => x.id !== rmValue.id) metadata[metadataKey][propertyKey] = newMetas return metadata[metadataKey][propertyKey] } function setMetadata ( metadata: DecoratorMetadataObject, propertyKey: string | symbol | number, metadataKey: MetadataSymbol, newValue: any, reverse = false, ): T[] { const metas = getMetadata(metadata, propertyKey, metadataKey) const newMetas = reverse ? [newValue, ...metas] : [...metas, newValue] metadata[metadataKey][propertyKey] = newMetas return newMetas } const FieldSymbol = Symbol('field-symbol') function getFields (metadata: DecoratorMetadataObject): Array> { const fields = metadata[FieldSymbol] return Array.isArray(fields) ? fields : [] } function getField (metadata: DecoratorMetadataObject, propertyKey: keyof This): PropertyType | undefined { const fields = getFields(metadata) return fields.find(x => x.propertyName === propertyKey) } function setField ( metadata: DecoratorMetadataObject, field: PropertyType, ): Array> { const fields = [...getFields(metadata), field] metadata[FieldSymbol] = fields return fields } function removeField ( metadata: DecoratorMetadataObject, propertyKey: keyof This ): Array> { const fields = getFields(metadata).filter(x => x.propertyName !== propertyKey) metadata[FieldSymbol] = fields return fields } function isFieldDecorated (metadata: DecoratorMetadataObject, propertyKey: keyof This): boolean { return getField(metadata, propertyKey) !== undefined } function getClassPre (metadata: DecoratorMetadataObject): Array> { return getClassMetadata( metadata, PreClassFunctionSymbol, ) } function getPre (metadata: DecoratorMetadataObject, propertyKey: keyof This): Array> { return getMetadata( metadata, propertyKey, PreFunctionSymbol, ) } function getConditions (metadata: DecoratorMetadataObject, propertyKey: keyof This): Array> { return getMetadata( metadata, propertyKey, ConditionSymbol, ) } function setCondition ( metadata: DecoratorMetadataObject, propertyKey: keyof This, condition: Condition, ): Array> { return setMetadata(metadata, propertyKey, ConditionSymbol, condition, true) } function getControllers (metadata: DecoratorMetadataObject, propertyKey: keyof This): Array> { return getMetadata( metadata, propertyKey, ControllerSymbol, ) } function setController ( metadata: DecoratorMetadataObject, propertyKey: keyof This, controller: Controller, ): Array> { return setMetadata(metadata, propertyKey, ControllerSymbol, controller) } function getTransformers (metadata: DecoratorMetadataObject, propertyKey: keyof This, reverse = false): Array> { return getMetadata( metadata, propertyKey, TransformerSymbol, reverse ) } function setTransformer ( metadata: DecoratorMetadataObject, propertyKey: string | symbol, transformer: Transformer, ): Array> { return setMetadata(metadata, propertyKey, TransformerSymbol, transformer) } function getValidators (metadata: DecoratorMetadataObject, propertyKey: keyof This): Array> { return getMetadata( metadata, propertyKey, ValidatorSymbol, ) } function setValidator ( metadata: DecoratorMetadataObject, propertyKey: string | symbol, validator: Validator, ): Array> { return setMetadata(metadata, propertyKey, ValidatorSymbol, validator) } function getPost (metadata: DecoratorMetadataObject, propertyKey: keyof This): Array> { return getMetadata( metadata, propertyKey, PostFunctionSymbol, ) } function getClassPost (metadata: DecoratorMetadataObject): Array> { return getClassMetadata( metadata, PostClassFunctionSymbol, ) } function setPrePost ( metadata: DecoratorMetadataObject, sym: PrePostSymbols, prepost: PrePost | PrePostClass, propertyKey?: keyof This, ): Array> { if ((sym === PreClassFunctionSymbol) || (sym === PostClassFunctionSymbol)) { return setClassMetadata(metadata, sym, prepost) } else if (((sym === PreFunctionSymbol) || (sym === PostFunctionSymbol)) && (propertyKey !== undefined)) { return setMetadata(metadata, propertyKey, sym, prepost) } else { throw new Error() } } function removePrePost ( metadata: DecoratorMetadataObject, sym: PrePostSymbols, prepost: PrePost | PrePostClass, propertyKey?: keyof This, ): Array> { if ((sym === PreClassFunctionSymbol) || (sym === PostClassFunctionSymbol)) { return removeClassMetadata(metadata, sym, prepost) } else if (((sym === PreFunctionSymbol) || (sym === PostFunctionSymbol)) && (propertyKey !== undefined)) { return removeMetadata(metadata, propertyKey, sym, prepost) } else { throw new Error() } } function getBitField (metadata: DecoratorMetadataObject, propertyKey: keyof This): BitField | undefined { const bitfields = getBitFields(metadata) return bitfields.find(x => x.propertyName === propertyKey) } function getBitFields (metadata: DecoratorMetadataObject): Array> { if (metadata[BitFieldSymbol] === undefined) { metadata[BitFieldSymbol] = [] } const bitfields = metadata[BitFieldSymbol] return Array.isArray(bitfields) ? bitfields : [] } function setBitField ( metadata: DecoratorMetadataObject, bitfield: BitField, ): Array> { const bitfields = [...getBitFields(metadata), bitfield] metadata[BitFieldSymbol] = bitfields return bitfields } function getContext (metadata: DecoratorMetadataObject, propertyKey: keyof This): Array> { return getMetadata( metadata, propertyKey, CtxSymbol, ) } function setContext ( metadata: DecoratorMetadataObject, propertyKey: keyof This, ctx: Ctx, ): Array> { return setMetadata(metadata, propertyKey, CtxSymbol, ctx) } export default { getMetadata, setMetadata, getField, getFields, setField, removeField, isFieldDecorated, getClassPre, getPre, getConditions, setCondition, getControllers, setController, getTransformers, setTransformer, getValidators, setValidator, getPost, getClassPost, setPrePost, removePrePost, getBitField, getBitFields, setBitField, getContext, setContext, }