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

macro-decorators

v0.1.2

Published

Decorators for property macros

Downloads

49,246

Readme

Macro Decorators

Build Status Open on Github

Sometimes, writing code for JavaScript getters and setters can get repetitive. Macro decorators allow you to DRY up your code by creating a decorator that can duplicate a getter/setter's functionality in multiple places!

Checkout the docs to get started, or continue reading for more information.

Installation

Using NPM:

npm install macro-decorators

Using Yarn:

yarn add macro-decorators

Usage

You can import the macro decorator from macro-decorators and use it to define macros:

import macro from 'macro-decorators';

function fullNameMacro() {
  return macro({
    get() {
      return `${this.firstName} ${this.lastName}`;
    },

    set(obj, key, value) {
      let [firstName, lastName] = value.split(' ');
      this.firstName = firstName;
      this.lastName = lastName;
    },
  });
}

class User {
  firstName;
  lastName;

  @fullNameMacro fullName;
}

class Admin {
  firstName;
  lastName;

  @fullNameMacro fullName;
}

let captainMarvel = new User();

captainMarvel.fullName = 'Carol Danvers';
console.log(captainMarvel.firstName); // 'Carol'
console.log(captainMarvel.lastName); // 'Danvers'
console.log(captainMarvel.fullName); // 'Carol Danvers'

You can also create dynamic macros which accept parameters, to make them more reusable and composable:

import macro, { filter, reads } from 'macro-decorators';

function percent(dividendName, divisorName) {
  return macro(function() {
    let divisor = this[divisorName];
    if (!divisor) {
      return null;
    }
    return (this[dividendName] / divisor) * 100;
  });
}

function formattedPercent(percentPropertyName) {
  return macro(function() {
    let value = this[percentPropertyName];
    if (!value) {
      return '--';
    }
    value = value.toFixed(2);
    return `${value}%`;
  });
}

class TestResultComponent {
  testResults = [];

  @filter('testResults', result => !result.finished)
  errorBuilds;

  @filter('testResults', result => result.finished && !result.succeeded))
  failedBuilds;

  @filter('testResults', result => result.finished && result.succeeded))
  passedBuilds;

  @reads('testResults.length') numberOfBuilds;
  @reads('errorBuilds.length') numberOfErrorBuilds;
  @reads('failedBuilds.length') numberOfFailedBuilds;
  @reads('passedBuilds.length') numberOfPassedBuilds;

  @percent('numberOfErrorBuilds', 'numberOfBuilds') percentOfErrorBuilds;
  @percent('numberOfFailedBuilds', 'numberOfBuilds') percentOfFailedBuilds;
  @percent('numberOfPassedBuilds', 'numberOfBuilds') percentOfPassedBuilds;

  @formattedPercent('percentOfErrorBuilds') formattedPercentOfErrorBuilds;
  @formattedPercent('percentOfFailedBuilds') formattedPercentOfFailedBuilds;
  @formattedPercent('percentOfPassedBuilds') formattedPercentOfPassedBuilds;
}

The macro-decorators library also ships with a number of predefined macros, including the @filter and @reads decorators from the last example. Check out the API doc for more information on these macros.

Macro Paths

Built in macros that receive a key to a different property as an argument can also receive a path of keys separated by periods:

import { reads } from 'macro-decorators';

class Person {
  friends = [];

  @reads('friends.length') numFriends;
}

Paths can be any length, but can only consist of string based property keys separated by periods. They cannot be dynamic.

Contributing

See the Contributing guide for details.

Compatibility

macro-decorators is built using TypeScript, and is compatible with both the TypeScript and Babel Legacy stage 1 decorators transforms. This is following the recommendation of the decorators proposal champions.

Future Upgrade Path

The decorators spec is still changing and not finalized at all, but this library intends to provide an upgrade path for the @macro decorator and all of the macros defined in it. This plan will be finalized when the decorators proposal is at least stage 3 and beginning to see wide adoption. Ideally, it will:

  1. Be partially codemoddable
  2. Not require users to rewrite too much existing code
  3. Allow users to import both the legacy decorators and the finalized decorators at the same time, in the same app, so users can convert one file at a time.

Whether or not these goals will be technically feasible will depend on the final spec and its implementation.

License

This project is licensed under the MIT License.