A lightweight, partial implementation of the TC39 Reflect Metadata proposal. This library provides reflection metadata functionality with a focus on performance and bundle size.
npm install @arcmantle/reflect-metadata
pnpm add @arcmantle/reflect-metadata
yarn add @arcmantle/reflect-metadata
Extend the global Reflect object with metadata APIs:
import { useReflectMetadata } from '@arcmantle/reflect-metadata';
// Extend the global Reflect with metadata APIs
const Reflect = useReflectMetadata();
// Now you can use Reflect metadata APIs (global Reflect is extended)
Reflect.defineMetadata('custom:key', 'value', target);
const value = Reflect.getMetadata('custom:key', target);
<script type="module">
import { useReflectMetadata } from '@arcmantle/reflect-metadata';
const Reflect = useReflectMetadata();
// Reflect metadata APIs are now available globally
</script>
This library implements the following Reflect metadata APIs:
Reflect.defineMetadata(key, value, target[, propertyKey])
Defines metadata for a target object or property.
const Reflect = useReflectMetadata();
Reflect.defineMetadata('custom:type', 'string', MyClass, 'propertyName');
Reflect.getMetadata(key, target[, propertyKey])
Retrieves metadata from a target object or property, including inherited metadata.
const Reflect = useReflectMetadata();
const type = Reflect.getMetadata('custom:type', MyClass, 'propertyName');
Reflect.getOwnMetadata(key, target[, propertyKey])
Retrieves own metadata from a target object or property (no inheritance).
const Reflect = useReflectMetadata();
const ownType = Reflect.getOwnMetadata('custom:type', MyClass, 'propertyName');
Reflect.hasMetadata(key, target[, propertyKey])
Checks if metadata exists for a target object or property (including inherited).
const Reflect = useReflectMetadata();
const hasType = Reflect.hasMetadata('custom:type', MyClass, 'propertyName');
Reflect.hasOwnMetadata(key, target[, propertyKey])
Checks if own metadata exists for a target object or property (no inheritance).
const Reflect = useReflectMetadata();
const hasOwnType = Reflect.hasOwnMetadata('custom:type', MyClass, 'propertyName');
Reflect.metadata(key, value)
Creates a metadata decorator function.
const Reflect = useReflectMetadata();
const Type = (type: string) => Reflect.metadata('custom:type', type);
class MyClass {
@Type('string')
propertyName: string;
}
Reflect.decorate(decorators, target[, propertyKey, descriptor])
Applies decorators to a target.
const Reflect = useReflectMetadata();
const decoratedClass = Reflect.decorate([MyDecorator], MyClass);
import { useReflectMetadata } from '@arcmantle/reflect-metadata';
const Reflect = useReflectMetadata();
class User {
name: string;
email: string;
}
// Store metadata
Reflect.defineMetadata('validation:required', true, User, 'name');
Reflect.defineMetadata('validation:email', true, User, 'email');
// Retrieve metadata
const isNameRequired = Reflect.getMetadata('validation:required', User, 'name');
const isEmailValidation = Reflect.getMetadata('validation:email', User, 'email');
import { useReflectMetadata } from '@arcmantle/reflect-metadata';
const Reflect = useReflectMetadata();
// Create a validation decorator
function Required(target: any, propertyKey: string) {
Reflect.defineMetadata('validation:required', true, target, propertyKey);
}
function Email(target: any, propertyKey: string) {
Reflect.defineMetadata('validation:email', true, target, propertyKey);
}
class User {
@Required
name: string;
@Required
@Email
email: string;
}
// Validation logic
function validate(instance: any) {
const constructor = instance.constructor;
for (const property of Object.keys(instance)) {
const isRequired = Reflect.getMetadata('validation:required', constructor, property);
const isEmail = Reflect.getMetadata('validation:email', constructor, property);
if (isRequired && !instance[property]) {
throw new Error(`${property} is required`);
}
if (isEmail && !instance[property].includes('@')) {
throw new Error(`${property} must be a valid email`);
}
}
}
useReflectMetadata()
return the same extended global ReflectContributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.