Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@deepkit/injector

Package Overview
Dependencies
Maintainers
1
Versions
100
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@deepkit/injector - npm Package Compare versions

Comparing version 1.0.1-alpha.44 to 1.0.1-alpha.48

26

dist/cjs/src/injector.d.ts

@@ -48,2 +48,7 @@ import { ClassSchema, ExtractClassDefinition, PlainSchemaProps, PropertySchema } from '@deepkit/type';

readonly root: this;
readonly options: {
token: any;
optional: boolean;
root: boolean;
};
}

@@ -56,2 +61,3 @@ export declare type InjectOptions = {

declare type ForwardRef<T> = () => T;
export declare function isInjectDecorator(v: any): v is InjectDecorator;
export declare function inject(token?: any | ForwardRef<any>): InjectDecorator;

@@ -76,3 +82,3 @@ export declare class InjectToken {

get<T, R = T extends ClassType<infer R> ? R : T>(token: T, frontInjector?: BasicInjector): R;
getInjector(contextId: number): BasicInjector;
getInjectorForModule(module: InjectorModule): BasicInjector;
}

@@ -86,3 +92,3 @@ export declare class Injector implements BasicInjector {

protected contextResolver?: {
getInjector(contextId: number): BasicInjector;
getInjectorForModule(module: InjectorModule): BasicInjector;
} | undefined;

@@ -93,5 +99,5 @@ circularCheck: boolean;

constructor(providers?: Provider[], parents?: (BasicInjector | Injector)[], injectorContext?: InjectorContext, configuredProviderRegistry?: ConfiguredProviderRegistry | undefined, tagRegistry?: TagRegistry, contextResolver?: {
getInjector(contextId: number): BasicInjector;
getInjectorForModule(module: InjectorModule): BasicInjector;
} | undefined);
getInjector(contextId: number): BasicInjector;
getInjectorForModule(module: InjectorModule): BasicInjector;
/**

@@ -111,3 +117,12 @@ * Creates a clone of this instance, maintains the provider structure, but drops provider instances.

isRoot(): boolean;
protected createFactoryProperty(property: PropertySchema, compiler: CompilerContext, classTypeVar: string, argPosition: number, notFoundFunction: string): string;
protected createFactoryProperty(options: {
name: string | number;
token: any;
optional: boolean;
}, compiler: CompilerContext, ofName: string, argPosition: number, notFoundFunction: string): string;
protected optionsFromProperty(property: PropertySchema): {
token: any;
name: string | number;
optional: boolean;
};
protected createFactory(compiler: CompilerContext, classType: ClassType): string;

@@ -217,2 +232,3 @@ protected buildRetriever(): (injector: Injector, token: any, frontInjector?: Injector) => any;

static forProviders(providers: ProviderWithScope[]): InjectorContext;
getInjectorForModule(module: InjectorModule): Injector;
getInjector(contextId: number): Injector;

@@ -219,0 +235,0 @@ get<T, R = T extends ClassType<infer R> ? R : T>(token: T, frontInjector?: Injector): R;

98

dist/cjs/src/injector.js

@@ -12,3 +12,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.InjectorContext = exports.setupProvider = exports.ConfiguredProviderRegistry = exports.Context = exports.ScopedContextCache = exports.ScopedContextScopeCaches = exports.ContextRegistry = exports.MemoryInjector = exports.Injector = exports.tokenLabel = exports.DependenciesUnmetError = exports.TokenNotFoundError = exports.CircularDependencyError = exports.injectable = exports.InjectToken = exports.inject = exports.createConfig = exports.injectorReference = exports.InjectorReference = exports.ConfigDefinition = exports.ConfigSlice = exports.ConfigToken = void 0;
exports.InjectorContext = exports.setupProvider = exports.ConfiguredProviderRegistry = exports.Context = exports.ScopedContextCache = exports.ScopedContextScopeCaches = exports.ContextRegistry = exports.MemoryInjector = exports.Injector = exports.tokenLabel = exports.DependenciesUnmetError = exports.TokenNotFoundError = exports.CircularDependencyError = exports.injectable = exports.InjectToken = exports.inject = exports.isInjectDecorator = exports.createConfig = exports.injectorReference = exports.InjectorReference = exports.ConfigDefinition = exports.ConfigSlice = exports.ConfigToken = void 0;
const type_1 = require("@deepkit/type");

@@ -102,2 +102,7 @@ const provider_1 = require("./provider");

exports.createConfig = createConfig;
const injectSymbol = Symbol('inject');
function isInjectDecorator(v) {
return core_1.isFunction(v) && v.hasOwnProperty(injectSymbol);
}
exports.isInjectDecorator = isInjectDecorator;
function inject(token) {

@@ -115,2 +120,3 @@ const injectOptions = {

};
Object.defineProperty(fn, injectSymbol, { value: true, enumerable: false });
Object.defineProperty(fn, 'optional', {

@@ -122,2 +128,7 @@ get() {

});
Object.defineProperty(fn, 'options', {
get() {
return injectOptions;
}
});
Object.defineProperty(fn, 'root', {

@@ -195,4 +206,4 @@ get() {

}
getInjector(contextId) {
return this.contextResolver ? this.contextResolver.getInjector(contextId) : this;
getInjectorForModule(module) {
return this.contextResolver ? this.contextResolver.getInjectorForModule(module) : this;
}

@@ -223,9 +234,4 @@ /**

}
createFactoryProperty(property, compiler, classTypeVar, argPosition, notFoundFunction) {
const options = property.data['deepkit/inject'];
let token = property.resolveClassType;
const isOptional = options && options.optional;
if (options && options.token) {
token = core_1.isFunction(options.token) ? options.token() : options.token;
}
createFactoryProperty(options, compiler, ofName, argPosition, notFoundFunction) {
const token = options.token;
if (token instanceof ConfigDefinition) {

@@ -273,6 +279,16 @@ if (token.hasModule()) {

else {
if (token === undefined)
throw new Error(`Argument type of '${property.name}' at position ${argPosition} is undefined. Imported reflect-metadata correctly? For circular references use @inject(() => T) ${property.name}:T.`);
if (token === undefined) {
let of = `${ofName}.${options.name}`;
if (argPosition >= 0) {
const argsCheck = [];
for (let i = 0; i < argPosition; i++)
argsCheck.push('✓');
argsCheck.push('?');
of = `${ofName}(${argsCheck.join(', ')})`;
}
throw new DependenciesUnmetError(`Undefined dependency '${options.name}: undefined' of ${of}. Dependency '${options.name}' has no type. Imported reflect-metadata correctly? ` +
`Use '@inject(PROVIDER) ${options.name}: T' if T is an interface. For circular references use @inject(() => T) ${options.name}: T.`);
}
const tokenVar = compiler.reserveVariable('token', token);
const orThrow = isOptional ? '' : `?? ${notFoundFunction}(${classTypeVar}, ${JSON.stringify(property.name)}, ${argPosition}, ${tokenVar})`;
const orThrow = options.optional ? '' : `?? ${notFoundFunction}(${JSON.stringify(ofName)}, ${JSON.stringify(options.name)}, ${argPosition}, ${tokenVar})`;
return `(frontInjector.retriever ? frontInjector.retriever(frontInjector, ${tokenVar}, frontInjector) : frontInjector.get(${tokenVar}, frontInjector)) ${orThrow}`;

@@ -282,2 +298,10 @@ }

}
optionsFromProperty(property) {
const options = property.data['deepkit/inject'];
let token = property.resolveClassType;
if (options && options.token) {
token = core_1.isFunction(options.token) ? options.token() : options.token;
}
return { token, name: property.name, optional: !!options && options.optional };
}
createFactory(compiler, classType) {

@@ -291,3 +315,3 @@ if (!classType)

for (const property of schema.getMethodProperties('constructor')) {
args.push(this.createFactoryProperty(property, compiler, classTypeVar, args.length, 'constructorParameterNotFound'));
args.push(this.createFactoryProperty(this.optionsFromProperty(property), compiler, core_1.getClassName(classType), args.length, 'constructorParameterNotFound'));
}

@@ -299,3 +323,3 @@ for (const property of schema.getProperties()) {

continue;
propertyAssignment.push(`v.${property.name} = ${this.createFactoryProperty(property, compiler, classTypeVar, args.length, 'propertyParameterNotFound')};`);
propertyAssignment.push(`v.${property.name} = ${this.createFactoryProperty(this.optionsFromProperty(property), compiler, core_1.getClassName(classType), -1, 'propertyParameterNotFound')};`);
}

@@ -366,4 +390,21 @@ return `v = new ${classTypeVar}(${args.join(',')});\n${propertyAssignment.join('\n')}`;

token = provider.provide;
const deps = (provider.deps || []).map(v => `frontInjector.get(${compiler.reserveVariable('dep', v)}, frontInjector)`);
factory = `v = ${compiler.reserveVariable('factory', provider.useFactory)}(${deps.join(', ')});`;
const args = [];
let i = 0;
for (const dep of provider.deps || []) {
let optional = false;
let token = dep;
if (isInjectDecorator(dep)) {
optional = dep.options.optional;
token = dep.options.token;
}
if (!token) {
throw new Error(`No token defined for dependency ${i} in 'deps' of useFactory for ${tokenLabel(provider.provide)}`);
}
args.push(this.createFactoryProperty({
name: i++,
token,
optional,
}, compiler, 'useFactory', args.length, 'factoryDependencyNotFound'));
}
factory = `v = ${compiler.reserveVariable('factory', provider.useFactory)}(${args.join(', ')});`;
}

@@ -446,2 +487,3 @@ else if (core_1.isClass(provider)) {

compiler.context.set('constructorParameterNotFound', constructorParameterNotFound);
compiler.context.set('factoryDependencyNotFound', factoryDependencyNotFound);
compiler.context.set('propertyParameterNotFound', propertyParameterNotFound);

@@ -475,5 +517,5 @@ compiler.preCode = `

exports.Injector = Injector;
function constructorParameterNotFound(classType, name, position, token) {
function constructorParameterNotFound(ofName, name, position, token) {
const argsCheck = [];
for (let i = 0; i < position - 1; i++)
for (let i = 0; i < position; i++)
argsCheck.push('✓');

@@ -483,9 +525,18 @@ argsCheck.push('?');

reset();
throw new DependenciesUnmetError(`Unknown constructor argument ${name} of ${core_1.getClassName(classType)}(${argsCheck.join(', ')}). Make sure '${tokenLabel(token)}' is provided.`);
throw new DependenciesUnmetError(`Unknown constructor argument '${name}: ${tokenLabel(token)}' of ${ofName}(${argsCheck.join(', ')}). Make sure '${tokenLabel(token)}' is provided.`);
}
function propertyParameterNotFound(classType, name, position, token) {
function factoryDependencyNotFound(ofName, name, position, token) {
const argsCheck = [];
for (let i = 0; i < position; i++)
argsCheck.push('✓');
argsCheck.push('?');
for (const reset of CircularDetectorResets)
reset();
throw new DependenciesUnmetError(`Unknown property parameter ${name} of ${core_1.getClassName(classType)}. Make sure '${tokenLabel(token)}' is provided.`);
throw new DependenciesUnmetError(`Unknown factory dependency argument '${tokenLabel(token)}' of ${ofName}(${argsCheck.join(', ')}). Make sure '${tokenLabel(token)}' is provided.`);
}
function propertyParameterNotFound(ofName, name, position, token) {
for (const reset of CircularDetectorResets)
reset();
throw new DependenciesUnmetError(`Unknown property parameter ${name} of ${ofName}. Make sure '${tokenLabel(token)}' is provided.`);
}
function throwCircularDependency() {

@@ -661,2 +712,5 @@ const path = CircularDetector.map(tokenLabel).join(' -> ');

}
getInjectorForModule(module) {
return this.getInjector(module.contextId);
}
getInjector(contextId) {

@@ -663,0 +717,0 @@ let injector = this.injectors[contextId];

@@ -8,2 +8,3 @@ import { ClassType } from '@deepkit/core';

config: C;
contextId: number;
protected setupProviderRegistry: ConfiguredProviderRegistry;

@@ -10,0 +11,0 @@ constructor(name: N, config: C);

@@ -9,2 +9,3 @@ "use strict";

this.config = config;
this.contextId = 0;
this.setupProviderRegistry = new injector_1.ConfiguredProviderRegistry;

@@ -11,0 +12,0 @@ }

@@ -22,3 +22,3 @@ "use strict";

exports.a = 'asd';
globals_1.test('injector', () => {
globals_1.test('injector basics', () => {
class Connection {

@@ -40,2 +40,61 @@ }

});
globals_1.test('missing dep', () => {
class Connection {
}
class Missing {
}
let MyServer = class MyServer {
constructor(connection, missing) {
this.connection = connection;
this.missing = missing;
globals_1.expect(connection).toBeInstanceOf(Connection);
}
};
MyServer = __decorate([
injector_1.injectable(),
__metadata("design:paramtypes", [Connection, Missing])
], MyServer);
const injector = new injector_1.Injector([MyServer, Connection]);
globals_1.expect(() => injector.get(MyServer)).toThrow(`Unknown constructor argument 'missing: Missing' of MyServer(✓, ?). Make sure 'Missing' is provided.`);
});
globals_1.test('wrong dep 1', () => {
class Connection {
}
let MyServer = class MyServer {
constructor(connection, missing) {
this.connection = connection;
this.missing = missing;
globals_1.expect(connection).toBeInstanceOf(Connection);
}
};
MyServer = __decorate([
injector_1.injectable(),
__metadata("design:paramtypes", [Connection, Object])
], MyServer);
globals_1.expect(() => new injector_1.Injector([MyServer, Connection])).toThrow(`Undefined dependency 'missing: undefined' of MyServer(✓, ?).`);
});
globals_1.test('wrong dep 2', () => {
let MyServer = class MyServer {
constructor(missing) {
this.missing = missing;
}
};
MyServer = __decorate([
injector_1.injectable(),
__metadata("design:paramtypes", [Object])
], MyServer);
globals_1.expect(() => new injector_1.Injector([MyServer])).toThrow(`Undefined dependency 'missing: undefined' of MyServer(?).`);
});
globals_1.test('wrong dep 3', () => {
let MyServer = class MyServer {
};
__decorate([
injector_1.inject(),
__metadata("design:type", Object)
], MyServer.prototype, "missing", void 0);
MyServer = __decorate([
injector_1.injectable()
], MyServer);
globals_1.expect(() => new injector_1.Injector([MyServer])).toThrow(`Undefined dependency 'missing: undefined' of MyServer.missing.`);
});
globals_1.test('injector key', () => {

@@ -147,3 +206,3 @@ let MyServer = class MyServer {

globals_1.expect(() => injector.get(Connection)).toThrow('Could not resolve injector token Connection');
globals_1.expect(() => injector.get(MyServer)).toThrow(`Unknown constructor argument connection of MyServer(?). Make sure 'Connection' is provided`);
globals_1.expect(() => injector.get(MyServer)).toThrow(`Unknown constructor argument 'connection: Connection' of MyServer(?).`);
}

@@ -258,3 +317,3 @@ });

globals_1.expect(i3.get('level')).toBe(2);
globals_1.expect(() => i2.get('level2')).toThrow('Could not resolve injector token deep2');
globals_1.expect(() => i2.get('level2')).toThrow(`Unknown factory dependency argument 'deep2' of useFactory`);
globals_1.expect(i3.get('level2')).toBe(3);

@@ -271,3 +330,3 @@ });

globals_1.expect(i3.get('level')).toBe(2);
globals_1.expect(() => i2.get('level2')).toThrow('Could not resolve injector token deep2');
globals_1.expect(() => i2.get('level2')).toThrow(`Unknown factory dependency argument 'deep2' of useFactory`);
globals_1.expect(i3.get('level2')).toBe(3);

@@ -274,0 +333,0 @@ });

@@ -48,2 +48,7 @@ import { ClassSchema, ExtractClassDefinition, PlainSchemaProps, PropertySchema } from '@deepkit/type';

readonly root: this;
readonly options: {
token: any;
optional: boolean;
root: boolean;
};
}

@@ -56,2 +61,3 @@ export declare type InjectOptions = {

declare type ForwardRef<T> = () => T;
export declare function isInjectDecorator(v: any): v is InjectDecorator;
export declare function inject(token?: any | ForwardRef<any>): InjectDecorator;

@@ -76,3 +82,3 @@ export declare class InjectToken {

get<T, R = T extends ClassType<infer R> ? R : T>(token: T, frontInjector?: BasicInjector): R;
getInjector(contextId: number): BasicInjector;
getInjectorForModule(module: InjectorModule): BasicInjector;
}

@@ -86,3 +92,3 @@ export declare class Injector implements BasicInjector {

protected contextResolver?: {
getInjector(contextId: number): BasicInjector;
getInjectorForModule(module: InjectorModule): BasicInjector;
} | undefined;

@@ -93,5 +99,5 @@ circularCheck: boolean;

constructor(providers?: Provider[], parents?: (BasicInjector | Injector)[], injectorContext?: InjectorContext, configuredProviderRegistry?: ConfiguredProviderRegistry | undefined, tagRegistry?: TagRegistry, contextResolver?: {
getInjector(contextId: number): BasicInjector;
getInjectorForModule(module: InjectorModule): BasicInjector;
} | undefined);
getInjector(contextId: number): BasicInjector;
getInjectorForModule(module: InjectorModule): BasicInjector;
/**

@@ -111,3 +117,12 @@ * Creates a clone of this instance, maintains the provider structure, but drops provider instances.

isRoot(): boolean;
protected createFactoryProperty(property: PropertySchema, compiler: CompilerContext, classTypeVar: string, argPosition: number, notFoundFunction: string): string;
protected createFactoryProperty(options: {
name: string | number;
token: any;
optional: boolean;
}, compiler: CompilerContext, ofName: string, argPosition: number, notFoundFunction: string): string;
protected optionsFromProperty(property: PropertySchema): {
token: any;
name: string | number;
optional: boolean;
};
protected createFactory(compiler: CompilerContext, classType: ClassType): string;

@@ -217,2 +232,3 @@ protected buildRetriever(): (injector: Injector, token: any, frontInjector?: Injector) => any;

static forProviders(providers: ProviderWithScope[]): InjectorContext;
getInjectorForModule(module: InjectorModule): Injector;
getInjector(contextId: number): Injector;

@@ -219,0 +235,0 @@ get<T, R = T extends ClassType<infer R> ? R : T>(token: T, frontInjector?: Injector): R;

@@ -92,2 +92,6 @@ /*

}
const injectSymbol = Symbol('inject');
export function isInjectDecorator(v) {
return isFunction(v) && v.hasOwnProperty(injectSymbol);
}
export function inject(token) {

@@ -105,2 +109,3 @@ const injectOptions = {

};
Object.defineProperty(fn, injectSymbol, { value: true, enumerable: false });
Object.defineProperty(fn, 'optional', {

@@ -112,2 +117,7 @@ get() {

});
Object.defineProperty(fn, 'options', {
get() {
return injectOptions;
}
});
Object.defineProperty(fn, 'root', {

@@ -178,4 +188,4 @@ get() {

}
getInjector(contextId) {
return this.contextResolver ? this.contextResolver.getInjector(contextId) : this;
getInjectorForModule(module) {
return this.contextResolver ? this.contextResolver.getInjectorForModule(module) : this;
}

@@ -206,9 +216,4 @@ /**

}
createFactoryProperty(property, compiler, classTypeVar, argPosition, notFoundFunction) {
const options = property.data['deepkit/inject'];
let token = property.resolveClassType;
const isOptional = options && options.optional;
if (options && options.token) {
token = isFunction(options.token) ? options.token() : options.token;
}
createFactoryProperty(options, compiler, ofName, argPosition, notFoundFunction) {
const token = options.token;
if (token instanceof ConfigDefinition) {

@@ -256,6 +261,16 @@ if (token.hasModule()) {

else {
if (token === undefined)
throw new Error(`Argument type of '${property.name}' at position ${argPosition} is undefined. Imported reflect-metadata correctly? For circular references use @inject(() => T) ${property.name}:T.`);
if (token === undefined) {
let of = `${ofName}.${options.name}`;
if (argPosition >= 0) {
const argsCheck = [];
for (let i = 0; i < argPosition; i++)
argsCheck.push('✓');
argsCheck.push('?');
of = `${ofName}(${argsCheck.join(', ')})`;
}
throw new DependenciesUnmetError(`Undefined dependency '${options.name}: undefined' of ${of}. Dependency '${options.name}' has no type. Imported reflect-metadata correctly? ` +
`Use '@inject(PROVIDER) ${options.name}: T' if T is an interface. For circular references use @inject(() => T) ${options.name}: T.`);
}
const tokenVar = compiler.reserveVariable('token', token);
const orThrow = isOptional ? '' : `?? ${notFoundFunction}(${classTypeVar}, ${JSON.stringify(property.name)}, ${argPosition}, ${tokenVar})`;
const orThrow = options.optional ? '' : `?? ${notFoundFunction}(${JSON.stringify(ofName)}, ${JSON.stringify(options.name)}, ${argPosition}, ${tokenVar})`;
return `(frontInjector.retriever ? frontInjector.retriever(frontInjector, ${tokenVar}, frontInjector) : frontInjector.get(${tokenVar}, frontInjector)) ${orThrow}`;

@@ -265,2 +280,10 @@ }

}
optionsFromProperty(property) {
const options = property.data['deepkit/inject'];
let token = property.resolveClassType;
if (options && options.token) {
token = isFunction(options.token) ? options.token() : options.token;
}
return { token, name: property.name, optional: !!options && options.optional };
}
createFactory(compiler, classType) {

@@ -274,3 +297,3 @@ if (!classType)

for (const property of schema.getMethodProperties('constructor')) {
args.push(this.createFactoryProperty(property, compiler, classTypeVar, args.length, 'constructorParameterNotFound'));
args.push(this.createFactoryProperty(this.optionsFromProperty(property), compiler, getClassName(classType), args.length, 'constructorParameterNotFound'));
}

@@ -282,3 +305,3 @@ for (const property of schema.getProperties()) {

continue;
propertyAssignment.push(`v.${property.name} = ${this.createFactoryProperty(property, compiler, classTypeVar, args.length, 'propertyParameterNotFound')};`);
propertyAssignment.push(`v.${property.name} = ${this.createFactoryProperty(this.optionsFromProperty(property), compiler, getClassName(classType), -1, 'propertyParameterNotFound')};`);
}

@@ -349,4 +372,21 @@ return `v = new ${classTypeVar}(${args.join(',')});\n${propertyAssignment.join('\n')}`;

token = provider.provide;
const deps = (provider.deps || []).map(v => `frontInjector.get(${compiler.reserveVariable('dep', v)}, frontInjector)`);
factory = `v = ${compiler.reserveVariable('factory', provider.useFactory)}(${deps.join(', ')});`;
const args = [];
let i = 0;
for (const dep of provider.deps || []) {
let optional = false;
let token = dep;
if (isInjectDecorator(dep)) {
optional = dep.options.optional;
token = dep.options.token;
}
if (!token) {
throw new Error(`No token defined for dependency ${i} in 'deps' of useFactory for ${tokenLabel(provider.provide)}`);
}
args.push(this.createFactoryProperty({
name: i++,
token,
optional,
}, compiler, 'useFactory', args.length, 'factoryDependencyNotFound'));
}
factory = `v = ${compiler.reserveVariable('factory', provider.useFactory)}(${args.join(', ')});`;
}

@@ -429,2 +469,3 @@ else if (isClass(provider)) {

compiler.context.set('constructorParameterNotFound', constructorParameterNotFound);
compiler.context.set('factoryDependencyNotFound', factoryDependencyNotFound);
compiler.context.set('propertyParameterNotFound', propertyParameterNotFound);

@@ -457,5 +498,5 @@ compiler.preCode = `

}
function constructorParameterNotFound(classType, name, position, token) {
function constructorParameterNotFound(ofName, name, position, token) {
const argsCheck = [];
for (let i = 0; i < position - 1; i++)
for (let i = 0; i < position; i++)
argsCheck.push('✓');

@@ -465,9 +506,18 @@ argsCheck.push('?');

reset();
throw new DependenciesUnmetError(`Unknown constructor argument ${name} of ${getClassName(classType)}(${argsCheck.join(', ')}). Make sure '${tokenLabel(token)}' is provided.`);
throw new DependenciesUnmetError(`Unknown constructor argument '${name}: ${tokenLabel(token)}' of ${ofName}(${argsCheck.join(', ')}). Make sure '${tokenLabel(token)}' is provided.`);
}
function propertyParameterNotFound(classType, name, position, token) {
function factoryDependencyNotFound(ofName, name, position, token) {
const argsCheck = [];
for (let i = 0; i < position; i++)
argsCheck.push('✓');
argsCheck.push('?');
for (const reset of CircularDetectorResets)
reset();
throw new DependenciesUnmetError(`Unknown property parameter ${name} of ${getClassName(classType)}. Make sure '${tokenLabel(token)}' is provided.`);
throw new DependenciesUnmetError(`Unknown factory dependency argument '${tokenLabel(token)}' of ${ofName}(${argsCheck.join(', ')}). Make sure '${tokenLabel(token)}' is provided.`);
}
function propertyParameterNotFound(ofName, name, position, token) {
for (const reset of CircularDetectorResets)
reset();
throw new DependenciesUnmetError(`Unknown property parameter ${name} of ${ofName}. Make sure '${tokenLabel(token)}' is provided.`);
}
function throwCircularDependency() {

@@ -636,2 +686,5 @@ const path = CircularDetector.map(tokenLabel).join(' -> ');

}
getInjectorForModule(module) {
return this.getInjector(module.contextId);
}
getInjector(contextId) {

@@ -638,0 +691,0 @@ let injector = this.injectors[contextId];

@@ -8,2 +8,3 @@ import { ClassType } from '@deepkit/core';

config: C;
contextId: number;
protected setupProviderRegistry: ConfiguredProviderRegistry;

@@ -10,0 +11,0 @@ constructor(name: N, config: C);

@@ -6,2 +6,3 @@ import { ConfiguredProviderRegistry, setupProvider } from './injector';

this.config = config;
this.contextId = 0;
this.setupProviderRegistry = new ConfiguredProviderRegistry;

@@ -8,0 +9,0 @@ }

@@ -19,3 +19,3 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

export const a = 'asd';
test('injector', () => {
test('injector basics', () => {
class Connection {

@@ -37,2 +37,61 @@ }

});
test('missing dep', () => {
class Connection {
}
class Missing {
}
let MyServer = class MyServer {
constructor(connection, missing) {
this.connection = connection;
this.missing = missing;
expect(connection).toBeInstanceOf(Connection);
}
};
MyServer = __decorate([
injectable(),
__metadata("design:paramtypes", [Connection, Missing])
], MyServer);
const injector = new Injector([MyServer, Connection]);
expect(() => injector.get(MyServer)).toThrow(`Unknown constructor argument 'missing: Missing' of MyServer(✓, ?). Make sure 'Missing' is provided.`);
});
test('wrong dep 1', () => {
class Connection {
}
let MyServer = class MyServer {
constructor(connection, missing) {
this.connection = connection;
this.missing = missing;
expect(connection).toBeInstanceOf(Connection);
}
};
MyServer = __decorate([
injectable(),
__metadata("design:paramtypes", [Connection, Object])
], MyServer);
expect(() => new Injector([MyServer, Connection])).toThrow(`Undefined dependency 'missing: undefined' of MyServer(✓, ?).`);
});
test('wrong dep 2', () => {
let MyServer = class MyServer {
constructor(missing) {
this.missing = missing;
}
};
MyServer = __decorate([
injectable(),
__metadata("design:paramtypes", [Object])
], MyServer);
expect(() => new Injector([MyServer])).toThrow(`Undefined dependency 'missing: undefined' of MyServer(?).`);
});
test('wrong dep 3', () => {
let MyServer = class MyServer {
};
__decorate([
inject(),
__metadata("design:type", Object)
], MyServer.prototype, "missing", void 0);
MyServer = __decorate([
injectable()
], MyServer);
expect(() => new Injector([MyServer])).toThrow(`Undefined dependency 'missing: undefined' of MyServer.missing.`);
});
test('injector key', () => {

@@ -144,3 +203,3 @@ let MyServer = class MyServer {

expect(() => injector.get(Connection)).toThrow('Could not resolve injector token Connection');
expect(() => injector.get(MyServer)).toThrow(`Unknown constructor argument connection of MyServer(?). Make sure 'Connection' is provided`);
expect(() => injector.get(MyServer)).toThrow(`Unknown constructor argument 'connection: Connection' of MyServer(?).`);
}

@@ -255,3 +314,3 @@ });

expect(i3.get('level')).toBe(2);
expect(() => i2.get('level2')).toThrow('Could not resolve injector token deep2');
expect(() => i2.get('level2')).toThrow(`Unknown factory dependency argument 'deep2' of useFactory`);
expect(i3.get('level2')).toBe(3);

@@ -268,3 +327,3 @@ });

expect(i3.get('level')).toBe(2);
expect(() => i2.get('level2')).toThrow('Could not resolve injector token deep2');
expect(() => i2.get('level2')).toThrow(`Unknown factory dependency argument 'deep2' of useFactory`);
expect(i3.get('level2')).toBe(3);

@@ -271,0 +330,0 @@ });

{
"name": "@deepkit/injector",
"version": "1.0.1-alpha.44",
"version": "1.0.1-alpha.48",
"description": "Deepkit Dependency Injection",

@@ -30,4 +30,4 @@ "type": "commonjs",

"devDependencies": {
"@deepkit/core": "^1.0.1-alpha.43",
"@deepkit/type": "^1.0.1-alpha.44",
"@deepkit/core": "^1.0.1-alpha.48",
"@deepkit/type": "^1.0.1-alpha.48",
"reflect-metadata": "^0.1.13"

@@ -43,3 +43,3 @@ },

},
"gitHead": "76911a9d4d25918fde4fab70f132a1f46356df4d"
"gitHead": "8e7a12c811318244eb165e32b526a51cb50b95c1"
}

@@ -127,2 +127,4 @@ /*

readonly root: this;
readonly options: {token: any, optional: boolean, root: boolean};
}

@@ -138,2 +140,8 @@

const injectSymbol = Symbol('inject');
export function isInjectDecorator(v: any): v is InjectDecorator {
return isFunction(v) && v.hasOwnProperty(injectSymbol);
}
export function inject(token?: any | ForwardRef<any>): InjectDecorator {

@@ -153,2 +161,4 @@ const injectOptions: InjectOptions = {

Object.defineProperty(fn, injectSymbol, {value: true, enumerable: false});
Object.defineProperty(fn, 'optional', {

@@ -161,2 +171,8 @@ get() {

Object.defineProperty(fn, 'options', {
get() {
return injectOptions;
}
});
Object.defineProperty(fn, 'root', {

@@ -215,3 +231,3 @@ get() {

get<T, R = T extends ClassType<infer R> ? R : T>(token: T, frontInjector?: BasicInjector): R;
getInjector(contextId: number): BasicInjector;
getInjectorForModule(module: InjectorModule): BasicInjector;
}

@@ -238,3 +254,3 @@

protected tagRegistry: TagRegistry = new TagRegistry(),
protected contextResolver?: { getInjector(contextId: number): BasicInjector }
protected contextResolver?: { getInjectorForModule(module: InjectorModule): BasicInjector }
) {

@@ -245,4 +261,4 @@ if (!this.configuredProviderRegistry) this.configuredProviderRegistry = injectorContext.configuredProviderRegistry;

getInjector(contextId: number): BasicInjector {
return this.contextResolver ? this.contextResolver.getInjector(contextId) : this;
getInjectorForModule(module: InjectorModule): BasicInjector {
return this.contextResolver ? this.contextResolver.getInjectorForModule(module) : this;
}

@@ -277,11 +293,5 @@

protected createFactoryProperty(property: PropertySchema, compiler: CompilerContext, classTypeVar: string, argPosition: number, notFoundFunction: string) {
const options = property.data['deepkit/inject'] as InjectOptions | undefined;
let token: any = property.resolveClassType;
const isOptional = options && options.optional;
protected createFactoryProperty(options: {name: string | number, token: any, optional: boolean}, compiler: CompilerContext, ofName: string, argPosition: number, notFoundFunction: string) {
const token = options.token;
if (options && options.token) {
token = isFunction(options.token) ? options.token() : options.token;
}
if (token instanceof ConfigDefinition) {

@@ -321,5 +331,18 @@ if (token.hasModule()) {

} else {
if (token === undefined) throw new Error(`Argument type of '${property.name}' at position ${argPosition} is undefined. Imported reflect-metadata correctly? For circular references use @inject(() => T) ${property.name}:T.`);
if (token === undefined) {
let of = `${ofName}.${options.name}`;
if (argPosition >= 0) {
const argsCheck: string[] = [];
for (let i = 0; i < argPosition; i++) argsCheck.push('✓');
argsCheck.push('?');
of = `${ofName}(${argsCheck.join(', ')})`;
}
throw new DependenciesUnmetError(
`Undefined dependency '${options.name}: undefined' of ${of}. Dependency '${options.name}' has no type. Imported reflect-metadata correctly? `+
`Use '@inject(PROVIDER) ${options.name}: T' if T is an interface. For circular references use @inject(() => T) ${options.name}: T.`
);
}
const tokenVar = compiler.reserveVariable('token', token);
const orThrow = isOptional ? '' : `?? ${notFoundFunction}(${classTypeVar}, ${JSON.stringify(property.name)}, ${argPosition}, ${tokenVar})`;
const orThrow = options.optional ? '' : `?? ${notFoundFunction}(${JSON.stringify(ofName)}, ${JSON.stringify(options.name)}, ${argPosition}, ${tokenVar})`;

@@ -332,2 +355,13 @@ return `(frontInjector.retriever ? frontInjector.retriever(frontInjector, ${tokenVar}, frontInjector) : frontInjector.get(${tokenVar}, frontInjector)) ${orThrow}`;

protected optionsFromProperty(property: PropertySchema): {token: any, name: string|number, optional: boolean} {
const options = property.data['deepkit/inject'] as InjectOptions | undefined;
let token: any = property.resolveClassType;
if (options && options.token) {
token = isFunction(options.token) ? options.token() : options.token;
}
return {token, name: property.name, optional: !!options && options.optional};
}
protected createFactory(compiler: CompilerContext, classType: ClassType): string {

@@ -341,3 +375,3 @@ if (!classType) throw new Error('Can not create factory for undefined ClassType');

for (const property of schema.getMethodProperties('constructor')) {
args.push(this.createFactoryProperty(property, compiler, classTypeVar, args.length, 'constructorParameterNotFound'));
args.push(this.createFactoryProperty(this.optionsFromProperty(property), compiler, getClassName(classType), args.length, 'constructorParameterNotFound'));
}

@@ -348,3 +382,3 @@

if (property.methodName === 'constructor') continue;
propertyAssignment.push(`v.${property.name} = ${this.createFactoryProperty(property, compiler, classTypeVar, args.length, 'propertyParameterNotFound')};`);
propertyAssignment.push(`v.${property.name} = ${this.createFactoryProperty(this.optionsFromProperty(property), compiler, getClassName(classType), -1, 'propertyParameterNotFound')};`);
}

@@ -414,4 +448,25 @@

const deps: any[] = (provider.deps || []).map(v => `frontInjector.get(${compiler.reserveVariable('dep', v)}, frontInjector)`);
factory = `v = ${compiler.reserveVariable('factory', provider.useFactory)}(${deps.join(', ')});`;
const args: string[] = [];
let i = 0;
for (const dep of provider.deps || []) {
let optional = false
let token = dep;
if (isInjectDecorator(dep)) {
optional = dep.options.optional;
token = dep.options.token;
}
if (!token) {
throw new Error(`No token defined for dependency ${i} in 'deps' of useFactory for ${tokenLabel(provider.provide)}`);
}
args.push(this.createFactoryProperty({
name: i++,
token,
optional,
}, compiler, 'useFactory', args.length, 'factoryDependencyNotFound'));
}
factory = `v = ${compiler.reserveVariable('factory', provider.useFactory)}(${args.join(', ')});`;
} else if (isClass(provider)) {

@@ -497,2 +552,3 @@ token = provider;

compiler.context.set('constructorParameterNotFound', constructorParameterNotFound);
compiler.context.set('factoryDependencyNotFound', factoryDependencyNotFound);
compiler.context.set('propertyParameterNotFound', propertyParameterNotFound);

@@ -528,5 +584,5 @@

function constructorParameterNotFound(classType: ClassType, name: string, position: number, token: any) {
function constructorParameterNotFound(ofName: string, name: string, position: number, token: any) {
const argsCheck: string[] = [];
for (let i = 0; i < position - 1; i++) argsCheck.push('✓');
for (let i = 0; i < position; i++) argsCheck.push('✓');
argsCheck.push('?');

@@ -536,13 +592,24 @@

throw new DependenciesUnmetError(
`Unknown constructor argument ${name} of ${getClassName(classType)}(${argsCheck.join(', ')}). Make sure '${tokenLabel(token)}' is provided.`
`Unknown constructor argument '${name}: ${tokenLabel(token)}' of ${ofName}(${argsCheck.join(', ')}). Make sure '${tokenLabel(token)}' is provided.`
);
}
function propertyParameterNotFound(classType: ClassType, name: string, position: number, token: any) {
function factoryDependencyNotFound(ofName: string, name: string, position: number, token: any) {
const argsCheck: string[] = [];
for (let i = 0; i < position; i++) argsCheck.push('✓');
argsCheck.push('?');
for (const reset of CircularDetectorResets) reset();
throw new DependenciesUnmetError(
`Unknown property parameter ${name} of ${getClassName(classType)}. Make sure '${tokenLabel(token)}' is provided.`
`Unknown factory dependency argument '${tokenLabel(token)}' of ${ofName}(${argsCheck.join(', ')}). Make sure '${tokenLabel(token)}' is provided.`
);
}
function propertyParameterNotFound(ofName: string, name: string, position: number, token: any) {
for (const reset of CircularDetectorResets) reset();
throw new DependenciesUnmetError(
`Unknown property parameter ${name} of ${ofName}. Make sure '${tokenLabel(token)}' is provided.`
);
}
function throwCircularDependency() {

@@ -599,3 +666,2 @@ const path = CircularDetector.map(tokenLabel).join(' -> ');

getCache(scope: string): ScopedContextCache {

@@ -749,2 +815,6 @@ let cache = this.caches[scope];

public getInjectorForModule(module: InjectorModule): Injector {
return this.getInjector(module.contextId);
}
public getInjector(contextId: number): Injector {

@@ -751,0 +821,0 @@ let injector = this.injectors[contextId];

@@ -5,2 +5,4 @@ import { ClassType } from '@deepkit/core';

export class InjectorModule<N extends string = string, C extends { [name: string]: any } = any> {
public contextId: number = 0;
protected setupProviderRegistry = new ConfiguredProviderRegistry;

@@ -7,0 +9,0 @@

@@ -9,3 +9,3 @@ import { expect, test } from '@jest/globals';

test('injector', () => {
test('injector basics', () => {
class Connection {

@@ -26,2 +26,53 @@ }

test('missing dep', () => {
class Connection {
}
class Missing {
}
@injectable()
class MyServer {
constructor(private connection: Connection, private missing: Missing) {
expect(connection).toBeInstanceOf(Connection);
}
}
const injector = new Injector([MyServer, Connection]);
expect(() => injector.get(MyServer)).toThrow(`Unknown constructor argument 'missing: Missing' of MyServer(✓, ?). Make sure 'Missing' is provided.`);
});
test('wrong dep 1', () => {
class Connection {
}
@injectable()
class MyServer {
constructor(private connection: Connection, private missing: any) {
expect(connection).toBeInstanceOf(Connection);
}
}
expect(() => new Injector([MyServer, Connection])).toThrow(`Undefined dependency 'missing: undefined' of MyServer(✓, ?).`);
});
test('wrong dep 2', () => {
@injectable()
class MyServer {
constructor(private missing: any) {
}
}
expect(() => new Injector([MyServer])).toThrow(`Undefined dependency 'missing: undefined' of MyServer(?).`);
});
test('wrong dep 3', () => {
@injectable()
class MyServer {
@inject() private missing: any;
}
expect(() => new Injector([MyServer])).toThrow(`Undefined dependency 'missing: undefined' of MyServer.missing.`);
});
test('injector key', () => {

@@ -127,3 +178,3 @@ @injectable()

expect(() => injector.get(Connection)).toThrow('Could not resolve injector token Connection');
expect(() => injector.get(MyServer)).toThrow(`Unknown constructor argument connection of MyServer(?). Make sure 'Connection' is provided`);
expect(() => injector.get(MyServer)).toThrow(`Unknown constructor argument 'connection: Connection' of MyServer(?).`);
}

@@ -241,3 +292,3 @@ });

expect(() => i2.get('level2')).toThrow('Could not resolve injector token deep2');
expect(() => i2.get('level2')).toThrow(`Unknown factory dependency argument 'deep2' of useFactory`);
expect(i3.get('level2')).toBe(3);

@@ -258,3 +309,3 @@ });

expect(() => i2.get('level2')).toThrow('Could not resolve injector token deep2');
expect(() => i2.get('level2')).toThrow(`Unknown factory dependency argument 'deep2' of useFactory`);
expect(i3.get('level2')).toBe(3);

@@ -261,0 +312,0 @@ });

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc