Skip to content

Commit

Permalink
feat: 🎸 implement control value transformer metadata decorator
Browse files Browse the repository at this point in the history
  • Loading branch information
ZeevKatz committed Oct 19, 2020
1 parent 3b1ff49 commit 0e8a63a
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 0 deletions.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Interface that represents metadata related to control value transformer.
*/
export interface ControlValueTransformerMetadata {
/**
* Unique name for the control value transformer.
*/
name: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Class } from 'utility-types';

import { Transformer } from '../shared';

import { ControlValueTransformerMetadata } from './control-value-transformer-metadata.interface';

/**
* Unique symbol used as a key to define and read metadata related to control value transformers.
*/
const CONTROL_VALUE_TRANSFORMER_METADATA = Symbol('CONTROL_VALUE_TRANSFORMER_METADATA');

/**
* Asserts the given transformer class is decorated with {@link Transformer}.
* @param transformer - Instance of control value transformer that should be decorated.
*/
const assertTransformerIsDecorated = (transformer: Transformer) => {
const hasMetadata = Reflect.hasMetadata(CONTROL_VALUE_TRANSFORMER_METADATA, transformer.constructor);

if (!hasMetadata) {
throw new TypeError(`"${transformer.constructor}" is not decorated with ControlValueTransformer.`);
}
};

/**
* Returns metadata associate with the given control value transformer.
* @param transformer - Instance of control value transformer.
* @returns Control value transformer metadata.
*/
export const getControlValueTransformerMetadata = (transformer: Transformer): ControlValueTransformerMetadata => {
assertTransformerIsDecorated(transformer);

return Reflect.getMetadata(CONTROL_VALUE_TRANSFORMER_METADATA, transformer.constructor);
};

/**
* Defines metadata on the given control value transformer class.
* @param transformerClass - Class that implements {@link Transformer}.
* @param metadata - Control value transformer metadata.
*/
export const definedControlValueTransformerMetadata = (
transformerClass: Class<Transformer>,
metadata: ControlValueTransformerMetadata
) => {
return Reflect.defineMetadata(CONTROL_VALUE_TRANSFORMER_METADATA, metadata, transformerClass);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Class } from 'utility-types';

import { Transformer } from '../shared';

import { ControlValueTransformerMetadata } from './control-value-transformer-metadata.interface';
import { definedControlValueTransformerMetadata } from './control-value-transformer-metadata.utils';

/**
* Decorator used to define required metadata on control value transformers.
* @param metadata - Control value transformer metadata.
*/
export const ControlValueTransformer = (metadata: ControlValueTransformerMetadata) => <T extends Transformer>(
transformerClass: Class<T>
): Class<T> => {
definedControlValueTransformerMetadata(transformerClass, metadata);
return transformerClass;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export { ControlValueTransformer } from './control-value-transformer.decorator';
export { ControlValueTransformerMetadata } from './control-value-transformer-metadata.interface';
export {
definedControlValueTransformerMetadata,
getControlValueTransformerMetadata,
} from './control-value-transformer-metadata.utils';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Transformer } from './transformer.interface';
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Interface that represents value transformer.
* `S` - Source value type.
* `T` - Target value type.
*/
export interface Transformer<S = unknown, T = unknown> {
/**
* Transforms the given source value (`S`) to the target value type (`T`).
*/
toTarget: (sourceValue: S) => T;

/**
* Transforms the given target value (`T`) to the source value type (`S`).
*/
toSource: (targetValue: T, currentSourceValue: S) => S;
}
9 changes: 9 additions & 0 deletions projects/ngze/control-value-transformer/src/public-api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
/*
* Public API Surface of Control Value Transformer
*/

import 'reflect-metadata';

export {
ControlValueTransformer,
ControlValueTransformerMetadata,
getControlValueTransformerMetadata,
} from './lib/metadata';
export { Transformer } from './lib/shared';

0 comments on commit 0e8a63a

Please sign in to comment.