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

@alterior/annotations

v3.11.1

Published

Create and interact with Typescript metadata decorators

Downloads

165

Readme

@alterior/annotations

Version

Provides a standardized way to define metadata on programmatic elements of a Typescript application by using classes and decorators. The data being attached is called an "annotation" and is represented as an instance of an Annotation class, and the functions which attach the metadata are called "decorators".

Annotations are stored directly on the object using Object.defineProperty to avoid annotations applied to superclasses from appearing on their subclasses.

Creating annotations

First, create a subclass of Annotation. You will need to assign the annotation a "metadata name", which should be of the form package-name:decorator-name as shown below. Omitting @MetadataName() is an error.

@MetadataName('@myorg/mypackage:Color')
export class ColorAnnotation extends Annotation {
    constructor(readonly color : string) {
        super();
    }
}

Next, export your new Annotation's decorator:

export const Color = ColorAnnotation.decorator();

Retrieving annotations

You can extract the annotations for a target by using the appropriate static method on your Annotation subclass. For instance, to get all ColorAnnotations on class Cat, use:

let annotations : ColorAnnotation[] = ColorAnnotation.getAllForClass(Cat);

If you are not expecting more than one of the same annotation, use getForClass() to get the first matching annotation:

let annotation : ColorAnnotation = ColorAnnotation.getForClass(Cat);

You can attach and retrieve annotations on classes, methods, properties, constructor parameters and method parameters.

Limiting the decorator's allowed targets

You can enforce that your annotation's decorator can only be used on the decoration targets you expect:

export const Color = ColorAnnotation.decorator({
    validTargets: [ 'class', 'method' ]
});

Valid targets are class, method, property, and parameter. Applying a decorator to an invalid target is typically detected at compile-time assuming Typescript can infer the values passed to validTargets, and at runtime throws AnnotationTargetError.

Limit decorator to a single use per target

Sometimes it is desirable to prevent users from applying your decorator to a target more than once. Typically doing this is not an error, and Alterior can return all the annotation instances created by multiple decorators on a given target. However, Alterior can generate an error if a decorator for an annotation is used when an annotation of that type is already attached to the target, using the allowMultiple: false option:

export const Color = ColorAnnotation.decorator({
    allowMultiple: false
});

By default allowMultiple is true and the library allows the annotation decorator to be used as many times as the user desires.

Decorator Factories

Sometimes you may want to add additional behavior to be run when the decorator is being applied. To do that, you can provide a factory option to your decorator:

export const Color = ColorAnnotation.decorator({
    factory(site : DecoratorTarget, name : string) {
        // do special stuff here before 
        // returning the annotation to be attached.
        return new ColorAnnotation(name);
    }
})

Multiple decorators for a single Annotation class

Sometimes you have multiple decorators that are storing the same type of metadata. For instance, perhaps many of your users use 'red' and 'blue' with your @Color() decorator, so you decide to make it so your users can use @Red() and @Blue() instead. One way you might accomplish this is:

    export const Color = ColorAnnotation.decorator();
    export const Red = () => Color('red');
    export const Blue = () => Color('red');