npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@geckoai/class-mirror

v1.0.0

Published

Class mirror is typescript decorator framework.

Downloads

1

Readme

class-mirror

The @geckoai/class-mirror is typescript metadata decorator framework.

npm (scoped)

Installing

npm i reflect-metadata @geckoai/class-mirror
#or
yarn add reflect-metadata @geckoai/class-mirror

Example Usage

The following examples contain basic usage methods. For more high-level usage methods, please refer to the test directory.

Create class decorator

Create custom metadata file or use ClassMetadata, custom metadata must use the ClassMetadata extension. entity-metadata.ts

export class EntityMetadata<
  T = EntityMetadataOption
> extends ClassMetadata<T> {}

export interface EntityMetadataOption {
  readonly title?: string;
  readonly description?: string;
}

Create decorator file.

// import mirror
import { ClassMirror } from '@geckoai/class-mirror';
// import entity-metadata.ts
import { EntityMetadata } from './entity-metadata';

// The decorator can be used in two ways.
export function Entity<T extends Function>(target: T): T | void;
export function Entity(title: string, description: string): ClassDecorator;
export function Entity<T extends Function>(
  ...args: unknown[]
): T | void | ClassDecorator {
  if (args.length === 2) {
    const [title, description] = args as [string, string];
    return ClassMirror.createDecorator(
      new EntityMetadata({
        title,
        description,
      })
    );
  } else {
    return ClassMirror.createDecorator(new EntityMetadata(null))(args[0] as T);
  }
}

Create any class file, use @Entity or @Entity(...) decorator.

@Entity
class Foo {}

// or

@Entity({title: 'Bar', description: 'Class Bar'})
class Bar {}

Use ClassMirror.reflect get metadata.

import {ClassMirror} from "./index";

var reflect1 = ClassMirror.reflect(Foo);
var reflect2 = ClassMirror.reflect(Bar);

console.log(reflect1.metadata) // Set<EntityMetadata>
console.log(reflect2.metadata) // Set<EntityMetadata>

Create property decorator

Create custom metadata file or use PropertyMetadata, custom metadata must use the PropertyMetadata extension. exclude-metadata.ts

import { PropertyMetadata } from '@geckoai/class-mirror';

/**
 * @class ExcludeMetadata
 */
export class ExcludeMetadata<
  T = ExcludeMetadataOption
> extends PropertyMetadata<T> {}

export interface ExcludeMetadataOption {
  readonly toPlainOnly?: boolean;
  readonly toClassOnly?: boolean;
}

Create custom property decorator

use PropertyMirror.createDecorator create property decorator.

import { ExcludeMetadata, ExcludeMetadataOption } from './exclude-metadata';
import { PropertyMirror } from '@geckoai/class-mirror';

// The decorator can be used in two ways.
export function Exclude(target: Object, propertyKey: string | symbol): void;
export function Exclude(option: ExcludeMetadataOption): PropertyDecorator;
export function Exclude(...args: unknown[]): void | PropertyDecorator {
  if (args.length === 1) {
    return PropertyMirror.createDecorator(
      new ExcludeMetadata(args[0] as ExcludeMetadataOption)
    );
  } else {
    const [target, propertyKey] = args as [Object, string | symbol];
    return PropertyMirror.createDecorator(new ExcludeMetadata(null))(
      target,
      propertyKey
    );
  }
}

Create any class file, use @Exclude or @Exclude(...) decorator.

import {Exclude} from "your decoraror path"
class Foo {
    @Exclude
    public id: string;
    
    @Exclude({toPlainOnly: true})
    public name: string;

    @Exclude
    public static age: number;
}

Use PropertMirror.reflect or ClassMirror.reflect get metadata.

import {ClassMirror, PropertyMirror} from "./index";

// use ClassMirror get metadata.
const reflectClass = ClassMirror.reflect(Foo);
reflectClass.getMirror('id', false) // PropertyMirror<PropertyMetadata>
reflectClass.getMirror('age', false) //PropertyMirror<PropertyMetadata>

// use PropertyMirror get metadata.
const refect1 = PropertyMirror.reflect(Foo, 'id', false); // PropertyMirror<PropertyMetadata>
const refect2 = PropertyMirror.reflect(Foo, 'age', true); // PropertyMirror<PropertyMetadata>

console.log(refect1.metadata) // Set<ExcludeMetadata>
console.log(refect2.metadata) // Set<ExcludeMetadata>

// id: string
console.log(refect1.getDesignType()) // String
// age: number
console.log(refect2.getDesignType()) // Number

Create method decorator

Create custom metadata file or use MethodMetadata, custom metadata must use the MethodMetadata extension. request-metadata.ts

import { MethodMetadata } from '@geckoai/class-mirror';

/**
 * @class RequestMetadata
 */
export class RequestMetadata<T = MetadataOption> extends MethodMetadata<T> {}

export interface RequestMetadataOption {
    readonly path?: string;
    readonly method?: string;
}

Create custom method decorator

use MethodMirror.createDecorator create method decorator.

import { RequestMetadata, RequestMetadataOption } from './request-metadata';
import { MethodMirror } from '@geckoai/class-mirror';

// Unlike the previous case, the decorator has only one use,but it can also be used in two ways, You must add your own implementation logic.
export function Request(metadata: RequestMetadataOption): MethodDecorator {
    return MethodMirror.createDecorator(new RequestMetadata(metadata));
}

Create any class file, use@Request(...) decorator.

import {Request} from "your decoraror path"
class Foo {
    @Request({path: '/', method: 'post'})
    public zoo(): string {
        return 'zoo';
    }

    @Request({path: '/', method: 'post'})
    public static bar(): number {
        return 1;
    }
}

Use Method.reflect or ClassMirror.reflect get metadata.

import {ClassMirror, PropertyMirror} from "./index";

// use ClassMirror get metadata.
const reflectClass = ClassMirror.reflect(Foo);
reflectClass.getMirror('zoo', false) // MethodMirror<MethodMetadata>
reflectClass.getMirror('bar', false) // MethodMirror<MethodMetadata>

// use MethodMirror get metadata.
const refectMethod1 = MethodMirror.reflect(Foo, 'zoo', false); // MethodMirror<MethodMetadata>
const refectMethod2 = MethodMirror.reflect(Foo, 'bar', true); // MethodMirror<MethodMetadata>

// Use function reflect metadata
MethodMirror.reflect(Foo, Foo.bar, true); // MethodMirror<MethodMetadata>

// Instance use Function reflect metadata
const foo = new Foo();
MethodMirror.reflect(Foo, Foo.zoo, false); // MethodMirror<MethodMetadata>

// Get method parameter metadata mirrors.
console.log(refectMethod1.parameters); // Map<number, ParameterMirror>
console.log(refectMethod2.parameters); // Map<number, ParameterMirror>

//Get reflect medatadata.
console.log(refectMethod1.metadata); // Set<MethodMetadata>
console.log(refectMethod2.metadata); // Set<MethodMetadata>

// Get parameters type
console.log(refectMethod1.getDesignParamTypes()); // []
console.log(refectMethod2.getDesignParamTypes()); // []

// Get Return type
console.log(refectMethod1.getReturnType()); // String
console.log(refectMethod2.getReturnType()); // Number

Create parameter decorator

Create custom metadata file or use ParameterMetadata, custom metadata must use the ParameterMetadata extension. param-metadata.ts

import { ParameterMetadata } from '@geckoai/class-mirror';

/**
 * @class ParamMetadata
 */
export class ParamMetadata<T = MetadataOption> extends ParameterMetadata<T> {}

export interface ParamMetadataOption {
    readonly path: string;
}

Create custom parameter decorator

use ParameterMirror.createDecorator create parameter decorator.

import { ParamMetadata, ParamMetadataOption } from './param-metadata';
import { ParameterMirror } from '@geckoai/class-mirror';

// The decorator can be used in two ways.
export function Param(target: Object, propertyKey: string | symbol, parameterIndex: number): void;
export function Param(option: MetadataOption): ParameterDecorator;
export function Param(...args: unknown[]): ParameterDecorator | void {
    if (args.length === 1) {
        const [option] = args as [MetadataOption];
        return ParameterMirror.createDecorator(new Metadata(option));
    } else {
        const [target, propertyKey, parameterIndex] = args as [
            Object,
                string | symbol,
            number
        ];
        return ParameterMirror.createDecorator(new Metadata(null))(
            target,
            propertyKey,
            parameterIndex
        );
    }
}

Create any class file, use @Param or @Param(...) decorator.

import {Exclude} from "your decoraror path";
import {Request} from "your decoraror path";

class Foo {
    public constructor(
        @Param({ path: 'constructor', method: 'post' }) public path: string,
        @Param public index: number
    ) {}
    
    @Request({path: '/', method: 'post'})
    public zoo(@Param test: Number, @Param({path: '/'}) path: string): string {
        return 'zoo';
    }
    
    public static bar(@Param test: Object, @Param({path: '/'}) path: string): number {
        return 1;
    }
}

Use ParameterMirror.reflect or ParameterMirror.reflect get metadata.

import {ClassMirror, MethodMirror, ParameterMirror} from "./index";

// use ClassMirror get metadata.
const reflectClass = ClassMirror.reflect(Foo);
reflectClass.getMirror('zoo', false) // MethodMirror<MethodMetadata>
reflectClass.getMirror('bar', false) // MethodMirror<MethodMetadata>

// use MethodMirror get metadata.
const refectMethod1 = MethodMirror.reflect(Foo, 'zoo', false); // MethodMirror<MethodMetadata>
const refectMethod2 = MethodMirror.reflect(Foo, 'bar', true); // MethodMirror<MethodMetadata>

// Get parameters type
console.log(refectMethod1.getDesignParamTypes()); // [Number, String]
console.log(refectMethod2.getDesignParamTypes()); // [Object, String]

// Get method parameter metadata mirrors, you can find metadata in parameters.
console.log(refectMethod1.parameters); // Map<number, ParameterMirror>
console.log(refectMethod2.parameters); // Map<number, ParameterMirror>

// Find 1st parameter metadata
const parameterMirror1 = refectMethod1.parameters.get(0); // ParameterMirror<ParameterMetadata>
// Find 2nd parameter metadata
const parameterMirror2 = refectMethod1.parameters.get(1); // ParameterMirror<ParameterMetadata>
// or
ParameterMirror.reflect(Foo, 'zoo', 0, false); // ParameterMirror<ParameterMetadata>
ParameterMirror.reflect(Foo, 'bar', 0, true); // ParameterMirror<ParameterMetadata>

parameterMirror1.getDesignParamType(); // Number
parameterMirror2.getDesignParamType(); // String

parameterMirror1.metadata // Set<ParameterMetadata>
parameterMirror2.metadata // Set<ParameterMetadata>

// If it is a parameter decorator of a constructor, you need to obtain metadata through the following methods
console.log(reflectClass.parameters); // Map<number, ParameterMirror>;
const parameterMirror3  = reflectClass.parameters.get(0) // ParameterMirror
const parameterMirror4  = reflectClass.parameters.get(1) // ParameterMirror

parameterMirror3.metadata // Set<ParameterMetadata>
parameterMirror4.metadata // Set<ParameterMetadata>

parameterMirror3.getDesignParamType(); // String
parameterMirror4.getDesignParamType(); // Number

Documentation

Issues

Create issues in this repository for anything related to the Class Decorator. When creating issues please search for existing issues to avoid duplicates.

License

Licensed under the MIT License.