JSPM

  • Created
  • Published
  • Downloads 33
  • Score
    100M100P100Q70106F
  • License MIT

Tiny helper for TS/JS decorator building

Package Exports

  • @qiwi/decorator-utils

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@qiwi/decorator-utils) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

decorator-utils

Build Status Maintainability Test Coverage dependencyStatus Greenkeeper badge js-standard-style

Motivation

  1. — Decorator, what's that?
    — It's just a proposal "aspect" syntax for JS.
  2. — How does it work?
    Addy Osmany's answer
  3. — Is there any ready solution?
    — There're many awesome things around. Look at core-decorators and lodash-decorators.
  4. — Do I need this lib?
    — You should try this one before: decorator-utils by Luke Horvat
  5. — ...
    Just give a chance to Google
  6. — ...
    — How about writing your own? Netanel Basal's practical tips may be very helpful.
  7. — ...
    Yes, go ahead.
NOTE

There's no right way to support both decorator types: with @parentheses() and @plain. Holy War Thread: https://github.com/wycats/javascript-decorators/issues/23

Install

yarn add @qiwi/decorator-utils

Usage

Method

 const decorator = constructDecorator((targetType, target, param) => {
          if (targetType === METHOD) {
            return value => param || 'qux'
          }
        })

        class Foo {
          @decorator()
          foo () { return 'bar' }
          @decorator('BAZ')
          baz () { return 'baz' }
        }

Class

const decorator = constructDecorator((targetType, target) => {
          if (targetType === CLASS) {
            return class Bar extends target {
              constructor (name, age) {
                super(name)
                this.age = age
              }
            }
          }
        })

        @decorator()
        class Foo {
          constructor (name) {
            this.name = name
          }
          foo () { return 'bar' }
        }

Field & Param

    import {createDecorator, FIELD, PARAM} from '@qiwi/decorator-utils'
    
    const meta: any = {}
    const decorator = constructDecorator(({
        propName,
        paramIndex,
        targetType,
        target,
        args: [param]
    }: IDecoratorHandlerContext) => {
      if (targetType === PARAM) {
        if (propName && typeof paramIndex === 'number') {
          meta[propName] = meta[propName] || {}
          meta[propName][paramIndex] = target
        }
      }

      if (targetType === FIELD) {
        if (propName) {
          meta[propName] = param
        }
      }

    })

    class Foo {
      @decorator('arg')
      foo = 'bar'

      bar(one: any, @decorator() two: any) {
        return 'bar'
      }
    }

/**
    Now `meta` is smth like:
    {
      foo: 'arg',
      bar: {
        1: Foo.prototype.bar,
      },
    }
*/

Also you may apply decorator to the class, but decorate its methods:

const decorator = constructDecorator((targetType, target) => {
      if (targetType === METHOD) {
        return () => {
          return target().toUpperCase()
        }
      }
    })

    @decorator()
    class Foo {
      foo () { return 'bar' }
      baz () { return 'baz' }
    }