Skip to content

A lightweight, partial implementation of the [TC39 Reflect Metadata proposal](https://github.com/tc39/proposal-reflect-metadata). This library provides reflection metadata functionality with a focus on performance and bundle size.

Notifications You must be signed in to change notification settings

arcmantle/reflect-metadata

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

9 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

@arcmantle/reflect-metadata

License TypeScript

A lightweight, partial implementation of the TC39 Reflect Metadata proposal. This library provides reflection metadata functionality with a focus on performance and bundle size.

✨ Features

  • πŸͺΆ Lightweight: Only ~3.2KB unminified, 1.7KB minified, 0.7KB gzipped
  • πŸš€ Performance optimized: WeakMap-based storage for optimal memory usage
  • πŸ”§ Function-activated: Extends the global Reflect object with metadata APIs
  • πŸ›‘οΈ Safe: Won't override existing reflect-metadata implementations
  • πŸ“¦ ESM native: Built for modern JavaScript environments
  • 🎯 TypeScript ready: Full type definitions included

πŸ“¦ Installation

npm install @arcmantle/reflect-metadata
pnpm add @arcmantle/reflect-metadata
yarn add @arcmantle/reflect-metadata

πŸš€ Quick Start

Extend Global Reflect

Extend the global Reflect object with metadata APIs:

TypeScript/JavaScript

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);

HTML

<script type="module">
 import { useReflectMetadata } from '@arcmantle/reflect-metadata';

 const Reflect = useReflectMetadata();
 // Reflect metadata APIs are now available globally
</script>

πŸ“š API Reference

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);

πŸ”§ Usage Examples

Basic Metadata Storage

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');

Custom Decorators

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`);
  }
 }
}

⚠️ Important Notes

  • Safe activation: Multiple calls to useReflectMetadata() return the same extended global Reflect
  • Non-destructive: Won't override existing reflect-metadata implementations
  • Global extension: Extends the global Reflect object with metadata methods
  • ESM only: This package is ESM-only and requires Node.js 14+ or modern browsers
  • Partial implementation: Only implements the most commonly used metadata APIs

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

πŸ“„ License

This project is licensed under the Apache 2.0 License - see the LICENSE file for details.

πŸ”— Related Projects


About

A lightweight, partial implementation of the [TC39 Reflect Metadata proposal](https://github.com/tc39/proposal-reflect-metadata). This library provides reflection metadata functionality with a focus on performance and bundle size.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published