import angular, { IComponentOptions } from 'angular' import 'reflect-metadata' export function Component(options: { selector: string } & IComponentOptions) { return function(target) { const bindings = Reflect.getMetadata('angular:bindings', target) || {} const injections = Reflect.getMetadata('angular:injections', target) || [] const controllerWithDI = injections.concat(target) const componentOptions = { controller: controllerWithDI, ...options, bindings } if (options.selector.indexOf('-') !== -1) { throw new Error(`The @Component selector "${options.selector}" must be camelCased.`) } angular.module('app').component(options.selector, componentOptions) target.$inject = injections return target } } export function Injectable(name: string) { return function(target) { const injections = Reflect.getMetadata('angular:injections', target) || [] Reflect.defineMetadata('angular:service', name, target) target.$inject = injections const serviceWithDI = injections.concat(target) angular.module('app').service(name, serviceWithDI) } } // In TypeScript 5, we need to account for the constructor param key being undefined. // We're on TypeScript 4 in this project, but this still causes a problem. // A TS 5 project that consumes code that consumes these decorators will fail regardless. // See: https://github.com/microsoft/TypeScript/issues/52435 export function Inject(dependency?: string) { return function(target, _propertyKey: string | undefined, _propertyIndex: number) { const injections: string[] = Reflect.getMetadata('angular:injections', target) || [] if (dependency) { injections[_propertyIndex] = (dependency) } Reflect.defineMetadata('angular:injections', injections, target) } } export function Input(binding: '<' | '=' | '=?' | '@' = '<') { return function(target, propertyKey: string) { const bindings = Reflect.getMetadata('angular:bindings', target.constructor) || {} bindings[propertyKey] = binding Reflect.defineMetadata('angular:bindings', bindings, target.constructor) } } export function Output(binding: '&' | '&?' = '&') { return function(target, propertyKey: string) { const bindings = Reflect.getMetadata('angular:bindings', target.constructor) || {} bindings[propertyKey] = binding Reflect.defineMetadata('angular:bindings', bindings, target.constructor) } }