@aspectjs/core

Aspect Oriented Programming based on decorators, for browser & node

Usage no npm install needed!

<script type="module">
  import aspectjsCore from 'https://cdn.skypack.dev/@aspectjs/core';
</script>

README

AspectJS

The AOP framework for Javascript and Typescript

logo

ci-status Commitizen friendly

Abstract

Inspired by the AspectJ java framework, AspectJS Leverages ES Decorators to bring aspect-oriented programming to Javascript and Typescript.

For more details & usage, please read the documentation

Installation:

yarn add @aspectjs/core
## install polyfills if needed
yarn add reflect-metadata

Or with npm:

npm install --save @aspectjs/core
## install polyfills if needed
npm install --save reflect-metadata

Example

import { AnnotationFactory, BeforeContext, on, AnnotationType } from '@aspectjs/core/commons';
import { Aspect, Before, Order } from '@aspectjs/core/annotations';
import { WEAVER_CONTEXT } from '@aspectjs/core';

// Define the annotation
const Deprecated = new AnnotationFactory('my-lib').create(function Deprecated(message?: string): any {
    // Annotation stub returns any, so typescript accepts the annotation
    // above both classes, properties, methods & parameters
    return;
});

// Create an aspect to enhance the @Deprecated annotation
@Aspect()
class DeprecatedAspect {
    tags = {};

    @Before(on.method.withAnnotations(Deprecated)) // before @Deprecated methods
    @Before(on.parameter.withAnnotations(Deprecated)) // before methods with @Deprecated parameters
    @Order(1) // optional: give the execution order
    logWarning(context) {
        // context gets injected with some data relative to the current advice
        // get the unique target reference (ie: where the annotation is)
        const targetRef = context.target.ref;
        // if log warning not already raised for this target
        if (!this.tags[targetRef]) {
            if (
                // log any deprecated method call
                context.target.type === AnnotationType.METHOD ||
                // log any method call with a non-undefined deprecated parameter.
                context.args[context.target.parameterIndex] !== undefined
            ) {
                // get the message provided to @Deprecated, if any
                const message = context.annotations.onSelf(Deprecated)[0].args[0];
                // log a warning with either the provided message or a default one
                console.warn(message || `${context.target.label} is deprecated`);
                // warning raised, don't produce further warnings for this target
                this.tags[context.target.ref] = true;
            }
        }
    }
}

// Enable DeprecatedAspect
WEAVER_CONTEXT.getWeaver().enable(new DeprecatedAspect());

// Use the aspect
(function main() {
    class Greetings {
        sayHello(@Deprecarted('parameter name is deprecated') name) {
            console.log('Hello world');
        }
        @Deprecated()
        sayGoodbye() {
            console.log('Goodbye world');
        }
    }

    const g = new Greetings();
    g.sayHello('WORLD'); // will raise one warning
    g.sayGoodbye(); // will raise one warning
})();

Projects of the AspectJS family:

MIT Licensed