diff --git a/package.json b/package.json index e861cf3..515f4ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@agape/metadata", - "version": "0.1.0", + "version": "0.2.0", "description": "Metadata annotations", "main": "./cjs/index.js", "module": "./es2020/index.js", @@ -33,8 +33,5 @@ "require": "./cjs/index.js", "import": "./es2020/index.js" } - }, - "dependencies": { - "@agape/string": "^2.0.0" } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 3ad0922..2953bea 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ export * from './lib/decorators/description.decorator'; export * from './lib/decorators/example.decorator'; export * from './lib/decorators/label.decorator'; +export * from './lib/decorators/name.decorator'; export * from './lib/decorators/noun.decorator'; export * from './lib/decorators/sensitive.decorator'; export * from './lib/decorators/token.decorator'; @@ -9,6 +10,7 @@ export * from './lib/functions/description'; export * from './lib/functions/example'; export * from './lib/functions/label'; export * from './lib/functions/labels'; +export * from './lib/functions/name'; export * from './lib/functions/noun'; export * from './lib/functions/nouns'; export * from './lib/functions/sensitive'; diff --git a/src/lib/decorators/description.decorator.ts b/src/lib/decorators/description.decorator.ts index 779845f..ac85710 100644 --- a/src/lib/decorators/description.decorator.ts +++ b/src/lib/decorators/description.decorator.ts @@ -8,8 +8,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * > This decorator sets the `description` property on the associated * {@link MetadataDescriptor}. * - * ## Usage - * + * @example * ### Class * ```ts * @Description('Represents a user profile with personal and contact information') @@ -19,6 +18,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Property * ```ts * class Profile { @@ -27,6 +27,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Method * ```ts * class ProfileService { @@ -37,6 +38,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Parameter * ```ts * class ProfileService { diff --git a/src/lib/decorators/example.decorator.ts b/src/lib/decorators/example.decorator.ts index 8f6e9f0..d7d7639 100644 --- a/src/lib/decorators/example.decorator.ts +++ b/src/lib/decorators/example.decorator.ts @@ -8,8 +8,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * > This decorator sets the `example` property on the associated * {@link MetadataDescriptor}. * - * ## Usage - * + * @example * ### Class * ```ts * @Example({ name: 'Wireless Mouse', price: 29.99 }) @@ -19,6 +18,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Property * ```ts * class Product { @@ -30,6 +30,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Method * ```ts * class ProductService { @@ -40,6 +41,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Parameter * ```ts * class ProductService { diff --git a/src/lib/decorators/label.decorator.ts b/src/lib/decorators/label.decorator.ts index 789341f..d88806e 100644 --- a/src/lib/decorators/label.decorator.ts +++ b/src/lib/decorators/label.decorator.ts @@ -11,8 +11,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * > This decorator sets the `label` and `labels` properties * on the associated {@link MetadataDescriptor}. * - * ## Usage - * + * @example * ### Class * ```ts * @Label('Product', 'Products') @@ -22,6 +21,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Property * ```ts * class Product { @@ -30,6 +30,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Method * ```ts * class ProductService { @@ -40,6 +41,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Parameter * ```ts * class ProductService { diff --git a/src/lib/decorators/name.decorator.spec.ts b/src/lib/decorators/name.decorator.spec.ts new file mode 100644 index 0000000..9341e8a --- /dev/null +++ b/src/lib/decorators/name.decorator.spec.ts @@ -0,0 +1,63 @@ +import { Name } from './name.decorator'; +import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; + +describe('Name', () => { + + it('should set name on class', () => { + @Name('Product') + class Product { + name!: string; + } + + const descriptor = MetadataDescriptor.for(Product); + expect(descriptor.name).toEqual('Product'); + }); + + it('should set name on property', () => { + class Product { + @Name('skuCode') + sku!: string; + } + + const descriptor = MetadataDescriptor.for(Product, 'sku'); + expect(descriptor.name).toEqual('skuCode'); + }); + + it('should set name on method', () => { + class ProductService { + @Name('createProduct') + create(): void { + // ... + } + } + + const descriptor = MetadataDescriptor.for(ProductService, 'create'); + expect(descriptor.name).toEqual('createProduct'); + }); + + it('should set name on parameter', () => { + class ProductService { + create(@Name('product') product: any): void { + // ... + } + } + + const descriptor = MetadataDescriptor.for(ProductService, 'create', 0); + expect(descriptor.name).toEqual('product'); + }); + + it('should override automatically set name', () => { + @Name('CustomProduct') + class Product { + @Name('customSku') + sku!: string; + } + + const classDescriptor = MetadataDescriptor.for(Product); + const propertyDescriptor = MetadataDescriptor.for(Product, 'sku'); + + expect(classDescriptor.name).toEqual('CustomProduct'); + expect(propertyDescriptor.name).toEqual('customSku'); + }); + +}); diff --git a/src/lib/decorators/name.decorator.ts b/src/lib/decorators/name.decorator.ts new file mode 100644 index 0000000..e539fba --- /dev/null +++ b/src/lib/decorators/name.decorator.ts @@ -0,0 +1,73 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Class } from '@agape/types'; +import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; + +/** + * Specifies a name for the decorated class, property, method, or parameter. + * + * Names are used to identify the decorated element and can be used for + * serialization, validation, and other metadata-driven operations. + * + * > This decorator sets the `name` property on the associated {@link MetadataDescriptor}. + * + * @example + * ### Class + * ```ts + * @Name('Product') + * class Product { + * name: string; + * price: number; + * } + * ``` + * + * @example + * ### Property + * ```ts + * class Product { + * @Name('skuCode') + * sku: string; + * } + * ``` + * + * @example + * ### Method + * ```ts + * class ProductService { + * @Name('createProduct') + * create(): void { + * // ... + * } + * } + * ``` + * + * @example + * ### Parameter + * ```ts + * class ProductService { + * create(@Name('product') product: Product): void { + * // ... + * } + * } + * ``` + * + * @decorator Class + * @decorator Property + * @decorator Method + * @decorator Parameter + * @decoratorKind Metadata + * @decoratorPropertyType string + */ +export function Name(name: string): (target: object | Class, name?: string, index?: TypedPropertyDescriptor | number) => void +export function Name(...args: any[]) { + + function Name(target: object | Class, name?: string, index?: TypedPropertyDescriptor | number) { + + const descriptor = index !== undefined && typeof index === "number" + ? MetadataDescriptor.for(target, name, index) + : MetadataDescriptor.for(target, name); + + descriptor.name = args[0]; + } + + return Name +} diff --git a/src/lib/decorators/noun.decorator.ts b/src/lib/decorators/noun.decorator.ts index 6f0602b..152ab58 100644 --- a/src/lib/decorators/noun.decorator.ts +++ b/src/lib/decorators/noun.decorator.ts @@ -10,8 +10,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * > This decorator sets the `noun` and `nouns` properties * on the associated {@link MetadataDescriptor}. * - * ## Usage - * + * @example * ### Class * ```ts * @Noun('product', 'products') @@ -21,6 +20,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Property * ```ts * class Product { @@ -29,6 +29,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Method * ```ts * class ProductService { @@ -39,6 +40,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Parameter * ```ts * class ProductService { diff --git a/src/lib/decorators/sensitive.decorator.ts b/src/lib/decorators/sensitive.decorator.ts index 148e0ce..d92e8c6 100644 --- a/src/lib/decorators/sensitive.decorator.ts +++ b/src/lib/decorators/sensitive.decorator.ts @@ -8,8 +8,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * > This decorator sets `sensitive` to `true` on the corresponding * {@link MetadataDescriptor} * - * ## Usage - * + * @example * ### Class * ```ts * @Sensitive @@ -19,6 +18,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Property * ```ts * class Employee { @@ -27,6 +27,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Method * ```ts * class AuthService { @@ -37,6 +38,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Parameter * ```ts * class AuthService { @@ -48,6 +50,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Explicitly disable sensitivity * ```ts * class Admin extends User { diff --git a/src/lib/decorators/token.decorator.ts b/src/lib/decorators/token.decorator.ts index b6e4430..e160066 100644 --- a/src/lib/decorators/token.decorator.ts +++ b/src/lib/decorators/token.decorator.ts @@ -13,8 +13,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * > This decorator sets the `token` and `tokens` properties * on the associated {@link MetadataDescriptor}. * - * ## Usage - * + * @example * ### Class * ```ts * @Token('product', 'products') @@ -24,6 +23,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Property * ```ts * class Product { @@ -32,6 +32,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Method * ```ts * class ProductService { @@ -42,6 +43,7 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * } * ``` * + * @example * ### Parameter * ```ts * class ProductService { diff --git a/src/lib/descriptors/metadata.descriptor.spec.ts b/src/lib/descriptors/metadata.descriptor.spec.ts index f3ed570..f9d156d 100644 --- a/src/lib/descriptors/metadata.descriptor.spec.ts +++ b/src/lib/descriptors/metadata.descriptor.spec.ts @@ -13,7 +13,7 @@ describe('MetadataDescriptor', () => { }) it('should set some properties', () => { - d = new MetadataDescriptor(); + d = new MetadataDescriptor('TestName'); d.label = 'Label'; d.labels = 'Labels'; d.noun = 'noun'; @@ -24,6 +24,7 @@ describe('MetadataDescriptor', () => { d.description = 'Description'; d.example = 'example'; + expect(d.name).toEqual('TestName'); expect(d.label).toEqual('Label'); expect(d.labels).toEqual('Labels'); expect(d.noun).toEqual('noun'); @@ -43,6 +44,27 @@ describe('MetadataDescriptor', () => { const e = MetadataDescriptor.for(Foo); expect(d).toBe(e) }) + it('should automatically set name for class', () => { + class Foo { } + d = MetadataDescriptor.for(Foo) + expect(d.name).toEqual('Foo') + }) + it('should automatically set name for property', () => { + class Foo { + bar!: string; + } + d = MetadataDescriptor.for(Foo, 'bar') + expect(d.name).toEqual('bar') + }) + it('should not set name for parameter', () => { + class Foo { + method(): void { + // Empty method for testing + } + } + d = MetadataDescriptor.for(Foo, 'method', 0) + expect(d.name).toBeUndefined() + }) it('should get the same descriptor for a class as it\'s prototype', () => { class Foo { } d = MetadataDescriptor.for(Foo) diff --git a/src/lib/descriptors/metadata.descriptor.ts b/src/lib/descriptors/metadata.descriptor.ts index 1e7ca94..b108570 100644 --- a/src/lib/descriptors/metadata.descriptor.ts +++ b/src/lib/descriptors/metadata.descriptor.ts @@ -3,28 +3,196 @@ import { Class } from '@agape/types'; import '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, labels, 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 + * ``` */ export class MetadataDescriptor { + /** + * The name of the decorated element. + * + * For classes, this is typically the class name. + * For properties, this is typically the property name. + * For parameters, this is usually undefined unless explicitly set. + */ + name?: string; + + /** + * A human-readable label for the decorated element. + * + * Labels are typically used in user interfaces such as form inputs, + * tables, and auto-generated documentation. + */ label?: string; - labels?: string + /** + * The plural form of the label. + * + * Used when displaying multiple instances of the decorated element, + * such as in table headers or list titles. + */ + labels?: string; + /** + * A noun that represents the decorated element. + * + * Nouns are used for grammatical purposes and can help with + * generating proper text in documentation or user interfaces. + */ noun?: string; + /** + * The plural form of the noun. + * + * Used when referring to multiple instances of the decorated element. + */ nouns?: string; + /** + * A token identifier for the decorated element. + * + * Tokens are typically used for internal identification and + * can be used for serialization or other programmatic operations. + */ token?: string; + /** + * The plural form of the token. + * + * Used when referring to multiple instances of the decorated element. + */ tokens?: string; + /** + * Indicates whether the decorated element contains sensitive information. + * + * When true, this element should be treated with special care in terms + * of logging, serialization, and display to ensure sensitive data + * is not inadvertently exposed. + */ sensitive?: boolean; + /** + * A detailed description of the decorated element. + * + * Descriptions provide additional context and information about + * the purpose and usage of the decorated element. + */ description?: string; + /** + * An example value for the decorated element. + * + * Examples can be used in documentation, validation messages, + * or as default values in user interfaces. + */ example?: any; + /** + * 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?: string) { + 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: Class | object, property?: string, index?: number): MetadataDescriptor { const prototype = typeof target === 'function' ? target.prototype : target; const token = index !== undefined ? `${property}:${index}` : property || ''; @@ -32,12 +200,53 @@ export class MetadataDescriptor { let descriptor = Reflect.getMetadata('agape:metadata', prototype, token); if (descriptor) return descriptor; - descriptor = new MetadataDescriptor() + let name: string | undefined; + + 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: Class | object, property?: string, index?: number): MetadataDescriptor | undefined { const prototype = typeof target === 'function' ? target.prototype : target; const token = index !== undefined ? `${property}:${index}` : property || ''; diff --git a/src/lib/functions/description.ts b/src/lib/functions/description.ts index a2766a4..0755dc1 100644 --- a/src/lib/functions/description.ts +++ b/src/lib/functions/description.ts @@ -8,20 +8,21 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * It supports metadata attached at the class level, property level, or parameter level depending * on which arguments are provided. * - * ## Usage - * + * @example * ### Class Level Description * * ```ts * const desc = description(MyClass); * ``` * + * @example * ### Property Level Description * * ```ts * const desc = description(MyClass, 'title'); * ``` * + * @example * ### Parameter Level Description * * ```ts diff --git a/src/lib/functions/example.ts b/src/lib/functions/example.ts index c9d34a5..3002499 100644 --- a/src/lib/functions/example.ts +++ b/src/lib/functions/example.ts @@ -9,20 +9,21 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * It supports metadata attached at the class level, property level, or parameter level depending * on which arguments are provided. * - * ## Usage - * + * @example * ### Class Level Example * * ```ts * const metadata = example(MyClass); * ``` * + * @example * ### Property Level Example * * ```ts * const metadata = example(MyClass, 'title'); * ``` * + * @example * ### Parameter Level Example * * ```ts diff --git a/src/lib/functions/label.ts b/src/lib/functions/label.ts index e53a613..3edd6ed 100644 --- a/src/lib/functions/label.ts +++ b/src/lib/functions/label.ts @@ -8,20 +8,21 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * It supports metadata attached at the class level, property level, or parameter level depending * on which arguments are provided. * - * ## Usage - * + * @example * ### Class Level Label * * ```ts * const metadata = label(MyClass); * ``` * + * @example * ### Property Level Label * * ```ts * const metadata = label(MyClass, 'title'); * ``` * + * @example * ### Parameter Level Label * * ```ts diff --git a/src/lib/functions/labels.ts b/src/lib/functions/labels.ts index 6c778b7..dac9087 100644 --- a/src/lib/functions/labels.ts +++ b/src/lib/functions/labels.ts @@ -8,20 +8,21 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * It supports metadata attached at the class level, property level, or parameter level depending * on which arguments are provided. * - * ## Usage - * + * @example * ### Class Level Labels * * ```ts * const metadata = labels(MyClass); * ``` * + * @example * ### Property Level Labels * * ```ts * const metadata = labels(MyClass, 'title'); * ``` * + * @example * ### Parameter Level Labels * * ```ts diff --git a/src/lib/functions/name.spec.ts b/src/lib/functions/name.spec.ts new file mode 100644 index 0000000..b4130df --- /dev/null +++ b/src/lib/functions/name.spec.ts @@ -0,0 +1,78 @@ +import { name } from './name'; +import { Name } from '../decorators/name.decorator'; +import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; + +describe('name', () => { + + it('should get name from class', () => { + @Name('Product') + class Product { + name!: string; + } + + const result = name(Product); + expect(result).toEqual('Product'); + }); + + it('should get name from property', () => { + class Product { + @Name('skuCode') + sku!: string; + } + + const result = name(Product, 'sku'); + expect(result).toEqual('skuCode'); + }); + + it('should get name from method', () => { + class ProductService { + @Name('createProduct') + create(): void { + // ... + } + } + + const result = name(ProductService, 'create'); + expect(result).toEqual('createProduct'); + }); + + it('should get name from parameter', () => { + class ProductService { + create(@Name('product') product: any): void { + // ... + } + } + + const result = name(ProductService, 'create', 0); + expect(result).toEqual('product'); + }); + + it('should return undefined when no name is set', () => { + class Product { + sku!: string; + } + + const classResult = name(Product); + const propertyResult = name(Product, 'sku'); + + expect(classResult).toBeUndefined(); + expect(propertyResult).toBeUndefined(); + }); + + it('should return automatically set name when no decorator is used', () => { + class Product { + sku!: string; + } + + // Get descriptors to trigger automatic name setting + MetadataDescriptor.for(Product); + MetadataDescriptor.for(Product, 'sku'); + + const classResult = name(Product); + const propertyResult = name(Product, 'sku'); + + expect(classResult).toEqual('Product'); + expect(propertyResult).toEqual('sku'); + }); + +}); diff --git a/src/lib/functions/name.ts b/src/lib/functions/name.ts new file mode 100644 index 0000000..bab5311 --- /dev/null +++ b/src/lib/functions/name.ts @@ -0,0 +1,39 @@ +import { Class } from '@agape/types'; +import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; + +/** + * Retrieves the name metadata associated with a class, property, or method parameter. + * + * This function is used to fetch the `name` value stored via metadata for the given target. + * It supports metadata attached at the class level, property level, or parameter level depending + * on which arguments are provided. + * + * @example + * ### Class Level Name + * + * ```ts + * const metadata = name(MyClass); + * ``` + * + * @example + * ### Property Level Name + * + * ```ts + * const metadata = name(MyClass, 'title'); + * ``` + * + * @example + * ### Parameter Level Name + * + * ```ts + * const metadata = name(MyClass, 'setTitle', 0); + * ``` + * + * @param target - The target class constructor to retrieve metadata from. + * @param property - The name of the property or method to retrieve metadata for. + * @param index - The index of the parameter if retrieving metadata for a method parameter. + * @returns The name metadata if found; otherwise, `undefined`. + */ +export function name(target: Class, property?: string, index?: number): string | undefined { + return MetadataDescriptor.get(target, property, index)?.name; +} diff --git a/src/lib/functions/noun.ts b/src/lib/functions/noun.ts index 5e437ca..db72acd 100644 --- a/src/lib/functions/noun.ts +++ b/src/lib/functions/noun.ts @@ -8,20 +8,21 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * It supports metadata attached at the class level, property level, or parameter level depending * on which arguments are provided. * - * ## Usage - * + * @example * ### Class Level Noun * * ```ts * const metadata = noun(MyClass); * ``` * + * @example * ### Property Level Noun * * ```ts * const metadata = noun(MyClass, 'title'); * ``` * + * @example * ### Parameter Level Noun * * ```ts diff --git a/src/lib/functions/nouns.ts b/src/lib/functions/nouns.ts index e270380..bd2e8fb 100644 --- a/src/lib/functions/nouns.ts +++ b/src/lib/functions/nouns.ts @@ -8,20 +8,21 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * It supports metadata attached at the class level, property level, or parameter level depending * on which arguments are provided. * - * ## Usage - * + * @example * ### Class Level Nouns * * ```ts * const metadata = nouns(MyClass); * ``` * + * @example * ### Property Level Nouns * * ```ts * const metadata = nouns(MyClass, 'title'); * ``` * + * @example * ### Parameter Level Nouns * * ```ts diff --git a/src/lib/functions/sensitive.ts b/src/lib/functions/sensitive.ts index 54358b1..326c883 100644 --- a/src/lib/functions/sensitive.ts +++ b/src/lib/functions/sensitive.ts @@ -8,20 +8,21 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * It supports metadata attached at the class level, property level, or parameter level depending * on which arguments are provided. * - * ## Usage - * + * @example * ### Class Level Sensitive * * ```ts * const metadata = sensitive(MyClass); * ``` * + * @example * ### Property Level Sensitive * * ```ts * const metadata = sensitive(MyClass, 'password'); * ``` * + * @example * ### Parameter Level Sensitive * * ```ts diff --git a/src/lib/functions/token.ts b/src/lib/functions/token.ts index 0634afe..4cf83cd 100644 --- a/src/lib/functions/token.ts +++ b/src/lib/functions/token.ts @@ -8,20 +8,21 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * It supports metadata attached at the class level, property level, or parameter level depending * on which arguments are provided. * - * ## Usage - * + * @example * ### Class Level Token * * ```ts * const metadata = token(MyClass); * ``` * + * @example * ### Property Level Token * * ```ts * const metadata = token(MyClass, 'title'); * ``` * + * @example * ### Parameter Level Token * * ```ts diff --git a/src/lib/functions/tokens.ts b/src/lib/functions/tokens.ts index b0a4e15..41c04a4 100644 --- a/src/lib/functions/tokens.ts +++ b/src/lib/functions/tokens.ts @@ -8,20 +8,21 @@ import { MetadataDescriptor } from '../descriptors/metadata.descriptor'; * It supports metadata attached at the class level, property level, or parameter level depending * on which arguments are provided. * - * ## Usage - * + * @example * ### Class Level Tokens * * ```ts * const metadata = tokens(MyClass); * ``` * + * @example * ### Property Level Tokens * * ```ts * const metadata = tokens(MyClass, 'title'); * ``` * + * @example * ### Parameter Level Tokens * * ```ts