@agape/metadata
Version:
Metadata annotations
172 lines • 6.42 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MetadataDescriptor = void 0;
require("reflect-metadata");
/**
* A descriptor that holds metadata information for classes, properties, methods, and parameters.
*
* The `MetadataDescriptor` class is used to store and retrieve metadata associated with various
* elements in your codebase. It supports storing information like names, labelPlural, descriptions,
* and other metadata that can be used for serialization, validation, documentation generation,
* and other metadata-driven operations.
*
* @example
* ### Creating a Descriptor
*
* ```ts
* // create a get descriptor for a class
* const descriptor = MetaDataDescriptor.for(MyClass);
*
* // create or get a descriptor for a property or method
* const descriptor = MetaDataDescriptor.for(MyClass, 'myProperty');
*
* // create or get adescriptor for a method parameter
* const descriptor = MetaDataDescriptor.for(MyClass, 'myMethod', 0);
* ```
* @example
* ### Retrieving and Existing Descriptor
*
* ```ts
* // get descriptor for a class
* const descriptor = MetaDataDescriptor.get(MyClass);
*
* // get descriptor for a property or method
* const descriptor = MetaDataDescriptor.get(MyClass, 'myProperty');
*
* // get descriptor for a method parameter
* const descriptor = MetaDataDescriptor.get(MyClass, 'myMethod', 0);
* ```
*
* @example
* ### Example
*
* ```ts
* class User {
* @Label('Email address')
* @Description('The user\'s email address')
* @Sensitive()
* email: string;
*
* @Label('Full name')
* fullName: string;
* }
*
* // Get metadata for the class
* const classDescriptor = MetadataDescriptor.for(User);
* console.log(classDescriptor.name); // 'User'
*
* // Get metadata for the email property
* const emailDescriptor = MetadataDescriptor.for(User, 'email');
* console.log(emailDescriptor.label); // 'Email Address'
* console.log(emailDescriptor.sensitive); // true
* ```
*/
class MetadataDescriptor {
/**
* Creates a new MetadataDescriptor instance.
*
* @param name - Optional name for the decorated element. If not provided,
* the name can be set later or will be automatically determined
* when using the `for()` method.
*/
constructor(name) {
this.name = name;
}
/**
* Gets or creates a MetadataDescriptor for the specified target.
*
* This method retrieves an existing metadata descriptor or creates a new one
* if none exists. The name property is automatically set based on the context:
* - For classes: uses the class name
* - For properties: uses the property name
* - For parameters: no name is set (undefined)
*
* @param target - The target class constructor or object to get metadata for.
* @param property - Optional property name when getting metadata for a property or method.
* @param index - Optional parameter index when getting metadata for a method parameter.
* @returns The MetadataDescriptor for the specified target. If no descriptor exists,
* a new one is created and returned.
*
* @example
* ```ts
* class Product {
* name: string;
* price: number;
*
* calculateTotal(tax: number): number {
* return this.price * (1 + tax);
* }
* }
*
* // Get descriptor for the class
* const classDescriptor = MetadataDescriptor.for(Product);
* console.log(classDescriptor.name); // 'Product'
*
* // Get descriptor for a property
* const nameDescriptor = MetadataDescriptor.for(Product, 'name');
* console.log(nameDescriptor.name); // 'name'
*
* // Get descriptor for a method parameter
* const paramDescriptor = MetadataDescriptor.for(Product, 'calculateTotal', 0);
* console.log(paramDescriptor.name); // undefined
* ```
*/
static for(target, property, index) {
const prototype = typeof target === 'function' ? target.prototype : target;
const token = index !== undefined ? `${property}:${index}` : property || '';
let descriptor = Reflect.getMetadata('agape:metadata', prototype, token);
if (descriptor)
return descriptor;
let name;
if (index !== undefined) {
name = undefined;
}
else if (property) {
name = property;
}
else if (typeof target === 'function') {
name = target.name;
}
descriptor = new MetadataDescriptor(name);
Reflect.defineMetadata('agape:metadata', descriptor, prototype, token);
return descriptor;
}
/**
* Retrieves an existing MetadataDescriptor for the specified target.
*
* This method only retrieves existing metadata descriptors and does not
* create new ones. If no descriptor exists, it returns undefined.
*
* @param target - The target class constructor or object to get metadata for.
* @param property - Optional property name when getting metadata for a property or method.
* @param index - Optional parameter index when getting metadata for a method parameter.
* @returns The existing MetadataDescriptor if found, otherwise undefined.
*
* @example
* ```ts
* class Product {
* @Label('Product Name')
* name: string;
* }
*
* // Get existing descriptor for the class
* const classDescriptor = MetadataDescriptor.get(Product);
* console.log(classDescriptor?.name); // 'Product' (if descriptor exists)
*
* // Get existing descriptor for a property
* const nameDescriptor = MetadataDescriptor.get(Product, 'name');
* console.log(nameDescriptor?.label); // 'Product Name' (if descriptor exists)
*
* // Try to get non-existent descriptor
* const nonExistent = MetadataDescriptor.get(Product, 'nonExistent');
* console.log(nonExistent); // undefined
* ```
*/
static get(target, property, index) {
const prototype = typeof target === 'function' ? target.prototype : target;
const token = index !== undefined ? `${property}:${index}` : property || '';
return Reflect.getMetadata('agape:metadata', prototype, token);
}
}
exports.MetadataDescriptor = MetadataDescriptor;
//# sourceMappingURL=metadata.descriptor.js.map