@universal-packages/namespaced-decorators
v1.3.3
Published
Easily track and decide which and how decorators will transform your clases
Downloads
11,166
Readme
Namespaced Decorators
Easily track and decide which and how decorators will transform your classes. Decorators are still in stage: 3, so they are experimental either in Typescript and Babel.
Install
npm install @universal-packages/namespaced-decorators
Decorators
The base decorators are meant to be used to register decorations in a certain namespace, with a single decoration object to be passed to whoever is going to finally decorate the class depending on what is in that decoration object.
You shouldn't use these base decorators directly in your classes, instead you create a new decorator function that takes your custom arguments to be collected into a decoration object.
All decorators take a namespace as first argument to be grouped accordingly, and a decoration object with a required __type
property useful to know what to do with the decorated element.
ClassDecorator
Registers a class decorationAccessorDecorator
Registers an accessor decorationMethodDecorator
Registers a method decorationArgumentDecorator
Registers a method's argument decorationPropertyDecorator
Registers a property decoration, it also takes a third argument, aDescriptorGenerator
which is a function that returns a descriptor to describe the property, useful to make properties read only.
Example usage
import { ClassDecorator, PropertyDecorator, AccessorDecorator, MethodDecorator, ArgumentDecorator } from '@universal-packages/namespaced-decorators'
function Controller(path) {
return ClassDecorator('web', { __type: 'controller', path })
}
function RequestBody(parser) {
return PropertyDecorator('web', { __type: 'request-body', parser }, () => {
return { configurable: false }
})
}
function Globals() {
return AccessorDecorator('web', { __type: 'globals' })
}
function Endpoint(verb) {
return MethodDecorator('web', { __type: 'endpoint', verb })
}
function Param(key) {
return ArgumentDecorator('web', { __type: 'param', key })
}
@Controller('/')
export default class ApplicationController {
@RequestBody('json')
body
@Globals()
get globals(): string {
return this.setGlobals
}
@Endpoint('get')
async root(@Param('id') id) {
this.setGlobals = (user: { name: 'David' })
}
}
Global methods
getNamespace(namespace: string, location: string, [conventionPrefix: string])
getNamespace(namespace: string, sharedModules: ModuleRegistry[], [conventionPrefix: string])
Get the namespaced decorators registry as a useful structured decorations object. It can load a directory and import modules to trigger decorations, get class directory location and share imported modules that may have errors.
Optionally instead of providing a location to load you can pass an array of already loaded modules, this way the registry can be filled with the class directory location.
In order to get the location of a decorated class all imported modules should have that class as a default export.
import { loadModules } from '@universal-packages/module-loader'
import { getNamespace } from '@universal-packages/namespaced-decorators'
const namespaceRegistry = getNamespace('web', './src', 'controller')
// You can pass already loaded modules
const modules = loadModules('./lib')
const namespaceRegistry = getNamespace('web', modules)
NamespaceRegistry
The namespace registry is structured as follow:
name
String
The name of the namespaceclasses
ClassRegistry[]
An array of all classes decorated in order of activation. The class registry is structured as follow:name
String
The name of the classdecorations
Decoration[]
All the decorations are being applied to the class in order of activation.location
String
If a loading location object is provided when getting a namespace this property will be populated with the class src file path.target
ClassType
The actual reference to the decorated class.accessors
AccessorRegistry[]
An array of all the decorated accessors in this class. The Accessor Registry is structured as follow:propertyKey
String
The accessor namedecorations
Decoration[]
All the decorations being applied to the accessor in order of activation.
methods
MethodRegistry[]
An array of all the decorated methods in this class. The Method Registry is structured as follow:propertyKey
String
The accessor namedecorations
Decoration[]
All the decorations being applied to the method in order of activation.arguments
ArgumentRegistry[]
An array of all the decorated arguments in this method. The Argument Registry is structured as follow:index
number
The index of the method argument from left to right.decorations
Decoration[]
All the decorations being applied to the argument in order of activation.
properties
PropertyRegistry[]
An array of all the decorated properties in this class. The Property Registry is structured as follow:propertyKey
String
The accessor namedecorations
Decoration[]
All the decorations being applied to the property in order of activation.
importedModules
ModuleRegistry[]
All modules imported when loading namespace, useful to know if any module may have an error.
How does it look?
const namespace = {
name: 'web',
classes: [
{
name: 'ApplicationController',
decorations: [{ __type: 'controller', path: '/' }],
location: '/Users/david/project/src/Application.controller.ts',
target: ApplicationController,
accessors: [
{
decorations: [{ __type: 'globals' }],
propertyKey: 'globals'
}
],
methods: [
{
propertyKey: 'root',
decorations: [{ __type: 'endpoint', verb: 'get' }],
arguments: [
{
index: 0,
decorations: [{ __type: 'param', key: 'id' }]
}
]
}
],
properties: [
{
propertyKey: 'body',
decorations: [{ __type: 'request-body', parser: 'json' }]
}
]
}
],
importedModules: [
{
export: [ApplicationController],
location: '/Users/david/project/src/Application.controller.ts',
error: null
},
{
export: null,
location: '/Users/david/project/src/Users.controller.ts',
error: Error('Unexpected error')
}
]
}
Typescript
This library is developed in TypeScript and shipped fully typed.
Contributing
The development of this library happens in the open on GitHub, and we are grateful to the community for contributing bugfixes and improvements. Read below to learn how you can take part in improving this library.