Want to take your software engineering career to the next level? Join the mailing list for career tips & advice Click here

aspect.js

Aspect-oriented programming library for the future generations...

Subscribe to updates I use aspect.js


Statistics on aspect.js

Number of watchers on Github 214
Number of open issues 0
Average time to close an issue 16 days
Main language TypeScript
Average time to merge a PR 6 days
Open pull requests 1+
Closed pull requests 0+
Last commit over 2 years ago
Repo Created about 5 years ago
Repo Last Updated over 2 years ago
Size 1.99 MB
Organization / Authormgechev
Contributors3
Page Updated
Do you use aspect.js? Leave a review!
View aspect.js activity
View on github
Fresh, new opensource launches 🚀🚀🚀
Software engineers: It's time to get promoted. Starting NOW! Subscribe to my mailing list and I will equip you with tools, tips and actionable advice to grow in your career.
Evaluating aspect.js for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)

Introduction

Build Status

Library for aspect-oriented programming with JavaScript, which takes advantage of ECMAScript 2016 decorators syntax.

For further reading on decorators, take a look at the spec.

Blog post, introduction to the AOP and the library could be found here.

Talk from AngularConnect.

Cutting Angular's Crosscuts

Sample usage

import {beforeMethod, Wove, Metadata} from 'aspect.js';

class LoggerAspect {
  @beforeMethod({
    classNamePattern: /^Article/,
    methodNamePattern: /^(get|set)/
  })
  invokeBeforeMethod(meta: Metadata) {
    // meta.woveMetadata == { bar: 42 }
    console.log(`Inside of the logger. Called ${meta.className}.${meta.method.name} with args: ${meta.method.args.join(', ')}.`);
  }
}

class Article {
  id: number;
  title: string;
  content: string;
}

@Wove({ bar: 42 })
class ArticleCollection {
  articles: Article[] = [];
  getArticle(id: number) {
    console.log(`Getting article with id: ${id}.`);
    return this.articles.filter(a => {
      return a.id === id;
    }).pop();
  }
  setArticle(article: Article) {
    console.log(`Setting article with id: ${article.id}.`);
    this.articles.push(article);
  }
}

new ArticleCollection().getArticle(1);

// Result:
// Inside of the logger. Called ArticleCollection.getArticle with args: 1.
// Getting article with id: 1.

In case you're using aspect.js in a browser environment the minifier may break the annotated code because of the performed mangling. In order to handle this problem you can use:

class LoggerAspect {
  @beforeMethod({
    classes: [ArticleCollection],
    methods: [ArticleCollection.prototype.getArticle, ArticleCollection.prototype.setArticle]
  })
  invokeBeforeMethod(meta: Metadata) {
    // meta.woveMetadata == { bar: 42 }
    console.log(`Inside of the logger. Called ${meta.className}.${meta.method.name} with args: ${meta.method.args.join(', ')}.`);
  }
}

class ArticleCollection {
  getArticle(id: number) {...}
  setArticle(article: Article) {...}
}

In this case you can omit the @Wove decorator.

This way, by explicitly listing the classes and methods which should be woven, you can prevent the unwanted effect of mangling.

Demo

git clone https://github.com/mgechev/aop.js --depth 1
npm install -g ts-node
ts-node demo/index.ts

API

The library offers the following combinations of advices and joint points:

Method calls

  • beforeMethod(MethodSelector) - invoked before method call
  • afterMethod(MethodSelector) - invoked after method call
  • aroundMethod(MethodSelector) - invoked around method call
  • onThrowOfMethod(MethodSelector) - invoked on throw of method call
  • asyncOnThrowOfMethod(MethodSelector) - invoked on throw of async method call

Static method calls

  • beforeStaticMethod(MethodSelector) - invoked before static method call
  • afterStaticMethod(MethodSelector) - invoked after static method call
  • aroundStaticMethod(MethodSelector) - invoked around static method call
  • onThrowOfStaticMethod(MethodSelector) - invoked on throw of static method call
  • asyncOnThrowOfStaticMethod(MethodSelector) - invoked on throw of async static method call

Accessors

  • beforeSetter(MemberSelector) - invoked before setter call
  • afterSetter(MemberSelector) - invoked after setter call
  • aroundSetter(MemberSelector) - invoked around setter call
  • onThrowOfSetter(MemberSelector) - invoked on throw of setter call
  • asyncOnThrowOfSetter(MemberSelector) - invoked on throw of async setter call
  • beforeGetter(MemberSelector) - invoked before getter call
  • afterGetter(MemberSelector) - invoked after getter call
  • aroundGetter(MemberSelector) - invoked around getter call
  • onThrowOfGetter(MemberSelector) - invoked on throw of getter call
  • asyncOnThrowOfGetter(MemberSelector) - invoked on throw of async getter call

MethodSelector

export interface MethodSelector {
  classNamePattern?: RegExp;
  methodNamePattern?: RegExp;
  classes?: Function[];
  methods?: Function[];
}

MemberSelector

export interface MemberSelector {
  classNamePattern?: RegExp;
  fieldNamePattern?: RegExp;
  classes?: Function[];
  methods?: PropertyDescriptor[];
}

Metadata

export class Metadata {
  public method: MethodMetadata;
  public className: string;
  public woveMetadata: any;
}

MethodMetadata

export class MethodMetadata {
  public proceed: boolean;
  public name: string;
  public args: any[];
  public context: any;
  public result: any;
  public exception: any;
  public invoke: (...args: any[]) => any;
}

Diagram

Here's a UML class diagram which shows the relations between the individual abstractions:

UML Diagram

Roadmap

  • [x] Tests
  • [x] Type annotations and DTS generation
  • [x] Aspect factories
    • [x] Generic aspects
  • [x] Implement the following advices:
    • [x] Before
    • [x] After
    • [x] Throwing
    • [x] Returning
    • [x] Around
  • [x] Implement the following joint points:
    • [x] Method execution
    • [x] Static method execution
    • [x] Filed get
    • [x] Field set

License

MIT

aspect.js open issues Ask a question     (View All Issues)
  • almost 4 years Extend MethodMetadata with `invoke` method
  • about 4 years Work with mangling
  • over 4 years Write documentation
aspect.js open pull requests (View All Pulls)
  • add editorconfig
aspect.js list of languages used
Other projects in TypeScript