@travetto/di
Advanced tools
Comparing version 0.0.7 to 0.0.8
@@ -22,3 +22,3 @@ { | ||
}, | ||
"version": "0.0.7" | ||
"version": "0.0.8" | ||
} |
@@ -1,1 +0,1 @@ | ||
export * from './injectable'; | ||
export * from './injectable'; |
import { InjectableConfig, Dependency } from '../types'; | ||
import { DependencyRegistry, DEFAULT_INSTANCE } from '../service'; | ||
import { Class } from '@travetto/registry'; | ||
import { InjectableFactoryConfig } from '..'; | ||
@@ -24,9 +25,17 @@ export function Injectable(config: Partial<InjectableConfig<any>> = {}): ClassDecorator { | ||
export function Inject(config?: InjectConfig): PropertyDecorator { | ||
return (target: any, propertyKey: string | symbol) => { | ||
DependencyRegistry.registerProperty( | ||
target.constructor, | ||
propertyKey as string, | ||
config as any as Dependency); | ||
export function Inject(config?: InjectConfig) { | ||
return (target: any, propertyKey: string | symbol, idx?: number) => { | ||
if (typeof idx !== 'number') { // Only register if on property | ||
DependencyRegistry.registerProperty( | ||
target.constructor, | ||
propertyKey as string, | ||
config as any as Dependency); | ||
} | ||
}; | ||
} | ||
export function InjectableFactory(config: InjectableFactoryConfig<any>): MethodDecorator { | ||
return (target: any, property: string | symbol, descriptor: TypedPropertyDescriptor<any>) => { | ||
DependencyRegistry.registerFactory({ ...config, fn: descriptor.value, id: `${target.__id}#${property}` }); | ||
}; | ||
} |
@@ -1,2 +0,2 @@ | ||
import { Dependency, InjectableConfig, ClassTarget } from '../types'; | ||
import { Dependency, InjectableConfig, ClassTarget, InjectableFactoryConfig } from '../types'; | ||
import { InjectionError } from './error'; | ||
@@ -111,3 +111,5 @@ import { MetadataRegistry, Class, RootRegistry, ChangeEvent } from '@travetto/registry'; | ||
const inst = new managed.class(...consValues); | ||
const inst = managed.factory ? | ||
managed.factory(...consValues) : | ||
new managed.class(...consValues); | ||
@@ -211,2 +213,5 @@ for (let i = 0; i < fieldKeys.length; i++) { | ||
if (pconfig.factory) { | ||
config.factory = pconfig.factory; | ||
} | ||
if (pconfig.qualifier) { | ||
@@ -224,4 +229,34 @@ config.qualifier = pconfig.qualifier; | ||
} | ||
if (pconfig.dependencies) { | ||
config.dependencies = { fields: {}, ...pconfig.dependencies }; | ||
} | ||
} | ||
registerFactory(config: InjectableFactoryConfig<any> & { fn: (...args: any[]) => any, id?: string }) { | ||
const finalConfig: InjectableConfig<any> = {} as any; | ||
if (typeof config.autoCreate === 'boolean') { | ||
finalConfig.autoCreate = { create: config.autoCreate } as any; | ||
} | ||
finalConfig.factory = config.fn; | ||
finalConfig.target = config.class; | ||
if (config.qualifier) { | ||
finalConfig.qualifier = config.qualifier; | ||
} | ||
if (config.dependencies) { | ||
finalConfig.dependencies = { | ||
cons: config.dependencies, | ||
fields: {} | ||
} | ||
} | ||
// Create mock cls for DI purposes | ||
const cls = { __id: config.id || `${config.class.__id}#${config.fn.name}` } as any; | ||
finalConfig.class = cls; | ||
this.registerClass(cls, finalConfig); | ||
} | ||
onInstallFinalize<T>(cls: Class<T>) { | ||
@@ -238,5 +273,6 @@ const classId = cls.__id; | ||
if (parentConfig) { | ||
config.dependencies.fields = Object.assign({}, | ||
parentConfig.dependencies!.fields, | ||
config.dependencies.fields); | ||
config.dependencies.fields = { | ||
...parentConfig.dependencies!.fields, | ||
...config.dependencies.fields | ||
}; | ||
@@ -243,0 +279,0 @@ // Inherit cons deps if no constructor defined |
@@ -5,3 +5,5 @@ import * as ts from 'typescript'; | ||
let INJECTABLES = TransformUtil.buildImportAliasMap({ | ||
ConfigLoader.initialize(); // Initialize config as we need it here | ||
const INJECTABLES = TransformUtil.buildImportAliasMap({ | ||
...ConfigLoader.get('registry.injectable'), | ||
@@ -33,3 +35,3 @@ '@travetto/di': 'Injectable' | ||
optional, | ||
name: TransformUtil.getObjectValue(injectConfig, 'name') | ||
qualifier: TransformUtil.getObjectValue(injectConfig, 'qualifier') | ||
}); | ||
@@ -63,5 +65,5 @@ } | ||
const foundDec = TransformUtil.findAnyDecorator(node, INJECTABLES, state); | ||
let decls = node.decorators; | ||
if (foundDec) { | ||
if (foundDec) { // Constructor | ||
let decls = node.decorators; | ||
@@ -87,3 +89,3 @@ node = ts.visitEachChild(node, c => visitNode(context, c, state), context); | ||
// Add injectable to if not there | ||
// Add injectable decorator if not there (for aliased decorators) | ||
let injectable = TransformUtil.findAnyDecorator(node, { Injectable: new Set(['@travetto/di']) }, state); | ||
@@ -96,16 +98,15 @@ if (!injectable) { | ||
decls = ts.createNodeArray(declTemp); | ||
const cNode = node as any as ts.ClassDeclaration; | ||
const ret = ts.updateClassDeclaration(cNode, | ||
decls, | ||
cNode.modifiers, | ||
cNode.name, | ||
cNode.typeParameters, | ||
ts.createNodeArray(cNode.heritageClauses), | ||
cNode.members | ||
) as any; | ||
return ret; | ||
} | ||
const cNode = node as any as ts.ClassDeclaration; | ||
const out = ts.updateClassDeclaration(cNode, | ||
decls, | ||
cNode.modifiers, | ||
cNode.name, | ||
cNode.typeParameters, | ||
ts.createNodeArray(cNode.heritageClauses), | ||
cNode.members | ||
) as any; | ||
return out; | ||
} if (ts.isPropertyDeclaration(node)) { | ||
} else if (ts.isPropertyDeclaration(node)) { // Property | ||
const expr = processDeclaration(state, node); | ||
@@ -133,2 +134,53 @@ | ||
} | ||
} else if (ts.isMethodDeclaration(node) && (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Static) > 0) { // tslint:disable-line no-bitwise | ||
// Factory for static methods | ||
const foundDec = TransformUtil.findAnyDecorator(node, { InjectableFactory: new Set(['@travetto/di']) }, state); | ||
const decls = node.decorators; | ||
if (foundDec) { // Constructor | ||
const declTemp = (node.decorators || []).slice(0); | ||
let injectArgs: object[] = []; | ||
try { | ||
injectArgs = node.parameters.map(x => processDeclaration(state, x)!); | ||
} catch (e) { | ||
// If error, skip | ||
if (e.message !== 'Type information not found') { | ||
throw e; | ||
} | ||
} | ||
if (injectArgs.length) { | ||
const foundExpr = (foundDec.expression as ts.CallExpression); | ||
const args = TransformUtil.extendObjectLiteral({ | ||
dependencies: injectArgs | ||
}, foundExpr.arguments[0] as ts.ObjectLiteralExpression); | ||
node = ts.createMethod( | ||
decls!.filter(x => x !== foundDec).concat([ | ||
ts.createDecorator( | ||
ts.createCall( | ||
foundExpr.expression, | ||
foundExpr.typeArguments, | ||
ts.createNodeArray([args]) | ||
) | ||
) | ||
]), | ||
node.modifiers, | ||
node.asteriskToken, | ||
node.name, | ||
node.questionToken, | ||
node.typeParameters, | ||
node.parameters, | ||
node.type, | ||
node.body | ||
) as any; | ||
} | ||
return node; | ||
} else { | ||
return node; | ||
} | ||
} | ||
@@ -138,3 +190,2 @@ return ts.visitEachChild(node, c => visitNode(context, c, state), context); | ||
export const InjectableTransformer = { | ||
@@ -141,0 +192,0 @@ transformer: TransformUtil.importingVisitor<DiState>(() => ({ |
@@ -7,2 +7,3 @@ import { Class } from '@travetto/registry'; | ||
class: Class<T>; | ||
factory: (...args: any[]) => T; | ||
dependencies: { | ||
@@ -19,2 +20,9 @@ cons?: Dependency<any>[], | ||
optional?: boolean; | ||
} | ||
export interface InjectableFactoryConfig<T> { | ||
class: Class<T>; | ||
qualifier?: symbol; | ||
dependencies?: Dependency<any>[] | ||
autoCreate?: boolean | ||
} |
@@ -1,2 +0,2 @@ | ||
import { Injectable, Inject } from '../src'; | ||
import { Injectable, Inject, InjectableFactory } from '../src'; | ||
import { DbConfig, AltConfig } from './config'; | ||
@@ -6,4 +6,4 @@ | ||
export class Database { | ||
@Inject() dbConfig!: DbConfig<any, any>; | ||
@Inject({ optional: true }) altConfig!: AltConfig; | ||
@Inject() dbConfig: DbConfig<any, any>; | ||
@Inject({ optional: true }) altConfig: AltConfig; | ||
@@ -45,2 +45,11 @@ postConstruct() { | ||
age = 31; | ||
} | ||
} | ||
export const CUSTOM_SERVICE_INHERIT = Symbol('Custom'); | ||
class TestConfig { | ||
@InjectableFactory({ class: ServiceInherit, qualifier: CUSTOM_SERVICE_INHERIT }) | ||
static getObject(@Inject({ qualifier: SERVICE_INHERIT_2 }) svc: ServiceInherit) { | ||
return new ServiceInherit2(svc.db); | ||
} | ||
} |
import { DependencyRegistry } from '../src/service'; | ||
import { ServiceInherit, SERVICE_INHERIT_2 } from './deps'; | ||
import { ServiceInherit, SERVICE_INHERIT_2, CUSTOM_SERVICE_INHERIT } from './deps'; | ||
import { Suite, Test } from '@travetto/test'; | ||
@@ -46,3 +46,2 @@ import * as assert from 'assert'; | ||
@Test('run') | ||
@@ -72,2 +71,11 @@ async run() { | ||
} | ||
@Test('factory') | ||
async factory() { | ||
await DependencyRegistry.init(); | ||
const inst = await DependencyRegistry.getInstance(ServiceInherit, CUSTOM_SERVICE_INHERIT); | ||
assert(inst); | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23822
644