@travetto/di
Advanced tools
Comparing version 3.1.0-rc.3 to 3.1.0-rc.4
{ | ||
"name": "@travetto/di", | ||
"version": "3.1.0-rc.3", | ||
"version": "3.1.0-rc.4", | ||
"description": "Dependency registration/management and injection support.", | ||
@@ -33,3 +33,3 @@ "keywords": [ | ||
"peerDependencies": { | ||
"@travetto/transformer": "^3.1.0-rc.3" | ||
"@travetto/transformer": "^3.1.0-rc.4" | ||
}, | ||
@@ -36,0 +36,0 @@ "peerDependenciesMeta": { |
@@ -198,2 +198,41 @@ <!-- This file was generated by @travetto/doc and should not be modified directly --> | ||
## Non-Framework Dependencies | ||
The module is built around the framework's management of class registration, and being able to decorate the code with [@Injectable](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L31) decorators. There may also be a desire to leverage external code and pull it into the dependency injection framework. This could easily be achieved using a wrapper class that is owned by the framework. | ||
It is also possible to directly reference external types, and they will be converted into unique symbols. These symbols cannot be used manually, but can be leveraged using [@Inject](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L31) decorators. | ||
**Code: Example External Dependencies** | ||
```typescript | ||
import { EventEmitter } from 'events'; | ||
import { Writable } from 'stream'; | ||
import { Inject, Injectable, InjectableFactory } from '@travetto/di'; | ||
class Source { | ||
@InjectableFactory() | ||
static emitter(): EventEmitter { | ||
return new EventEmitter(); | ||
} | ||
@InjectableFactory(Symbol.for('custom-1')) | ||
static writable(): Writable { | ||
return {} as Writable; | ||
} | ||
@InjectableFactory(Symbol.for('custom-2')) | ||
static writableAlt(): Writable { | ||
return {} as Writable; | ||
} | ||
} | ||
@Injectable() | ||
class Service { | ||
@Inject() | ||
emitter: EventEmitter; | ||
@Inject(Symbol.for('custom-2')) | ||
writable: Writable; | ||
} | ||
``` | ||
## Manual Invocation | ||
@@ -200,0 +239,0 @@ Some times you will need to lookup a dependency dynamically, or you want to control the injection process at a more granular level. To achieve that you will need to directly access the [DependencyRegistry](https://github.com/travetto/travetto/tree/main/module/di/src/registry.ts#L1). The registry allows for requesting a dependency by class reference: |
@@ -6,2 +6,3 @@ import ts from 'typescript'; | ||
} from '@travetto/transformer'; | ||
import { ForeignType } from '@travetto/transformer/src/resolver/types'; | ||
@@ -15,2 +16,8 @@ const INJECTABLE_MOD = '@travetto/di/src/decorator'; | ||
static foreignTarget(state: TransformerState, ret: ForeignType): ts.Expression { | ||
return state.fromLiteral({ | ||
Ⲑid: `${ret.source.split('node_modules')[1]}+${ret.name}` | ||
}); | ||
} | ||
/** | ||
@@ -30,11 +37,23 @@ * Handle a specific declaration param/property | ||
let optional: ts.Expression | undefined = undefined; | ||
if (optional === undefined && !!param.questionToken) { | ||
optional = state.fromLiteral(true); | ||
const payload: { target?: unknown, qualifier?: unknown, optional?: boolean } = {}; | ||
if (!!param.questionToken) { | ||
payload.optional = true; | ||
} | ||
const keyParam = ts.isSetAccessorDeclaration(param) ? param.parameters[0] : param; | ||
const target = state.getOrImport(state.resolveExternalType(keyParam)); | ||
args.unshift(state.fromLiteral({ target, optional })); | ||
const type = state.resolveType(keyParam); | ||
if (type.key === 'managed') { | ||
payload.target = state.getOrImport(type); | ||
} else if (type.key === 'foreign') { | ||
payload.target = this.foreignTarget(state, type); | ||
} else { | ||
const file = param.getSourceFile().fileName; | ||
const src = state.getFileImportName(file); | ||
throw new Error(`Unable to import non-external type: ${param.getText()} ${type.key}: ${src}`); | ||
} | ||
args.unshift(state.fromLiteral(payload)); | ||
return args; | ||
@@ -58,3 +77,3 @@ } | ||
const resolvedType = state.resolveType(typeExpression); | ||
if (resolvedType.key === 'external') { | ||
if (resolvedType.key === 'managed') { | ||
const resolved = state.getOrImport(resolvedType); | ||
@@ -141,6 +160,12 @@ interfaces.push(resolved); | ||
// Read target from config or resolve | ||
let target; | ||
const config: { dependencies: unknown[], target?: unknown, qualifier?: unknown, src?: unknown } = { | ||
dependencies, | ||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions | ||
src: (node.parent as ts.ClassDeclaration).name, | ||
}; | ||
const ret = state.resolveReturnType(node); | ||
if (ret.key === 'external') { | ||
target = state.getOrImport(ret); | ||
if (ret.key === 'managed') { | ||
config.target = state.getOrImport(ret); | ||
} else if (ret.key === 'foreign') { | ||
config.target = this.foreignTarget(state, ret); | ||
} | ||
@@ -151,8 +176,3 @@ | ||
args.unshift(state.extendObjectLiteral({ | ||
dependencies, | ||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions | ||
src: (node.parent as ts.ClassDeclaration).name, | ||
target | ||
})); | ||
args.unshift(state.extendObjectLiteral(config)); | ||
@@ -159,0 +179,0 @@ // Replace decorator |
47719
922
290