New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@deepkit/injector

Package Overview
Dependencies
Maintainers
1
Versions
105
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.56 to 1.0.1-alpha.57

4

dist/cjs/src/injector.d.ts

@@ -53,2 +53,3 @@ import { NormalizedProvider, ProviderWithScope, TagRegistry, Token } from './provider';

private setter?;
private instantiations?;
/**

@@ -58,2 +59,3 @@ * All unscoped provider instances. Scoped instances are attached to `Scope`.

private instances;
private instantiated;
constructor(module: InjectorModule, buildContext: BuildContext);

@@ -64,2 +66,3 @@ static from(providers: ProviderWithScope[], parent?: Injector): Injector;

set<T>(token: T, value: any, scope?: Scope): void;
instantiationCount<T>(token: any): number;
clear(): void;

@@ -109,2 +112,3 @@ protected build(buildContext: BuildContext): void;

get<T>(token: T | Token, module?: InjectorModule): ResolveToken<T>;
instantiationCount(token: Token, module?: InjectorModule): number;
set<T>(token: T, value: any, module?: InjectorModule): void;

@@ -111,0 +115,0 @@ static forProviders(providers: ProviderWithScope[]): InjectorContext;

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

this.instances = {};
this.instantiated = {};
module.injector = this;

@@ -128,2 +129,7 @@ this.build(buildContext);

}
instantiationCount(token) {
if (!this.instantiations)
throw new Error('Injector was not built');
return this.instantiations(token);
}
clear() {

@@ -142,2 +148,5 @@ this.instances = {};

const creating = [];
const instantiationCompiler = new core_1.CompilerContext();
instantiationCompiler.context.set('injector', this);
const instantiationLines = [];
const setterCompiler = new core_1.CompilerContext();

@@ -162,2 +171,5 @@ setterCompiler.context.set('injector', this);

setterLines.push(`case ${setterCompiler.reserveVariable('token', token)}: {
if (${accessor} === undefined) {
injector.instantiated.${name} = injector.instantiated.${name} ? injector.instantiated.${name} + 1 : 1;
}
${accessor} = value;

@@ -169,6 +181,11 @@ break;

lines.push(`
case token === ${resolverCompiler.reserveConst(token)}: {
return ${resolverCompiler.reserveConst(prepared.resolveFrom)}.injector.resolver(${resolverCompiler.reserveConst(token)}, scope);
case token === ${resolverCompiler.reserveConst(token, 'token')}: {
return ${resolverCompiler.reserveConst(prepared.resolveFrom, 'resolveFrom')}.injector.resolver(${resolverCompiler.reserveConst(token, 'token')}, scope);
}
`);
`);
instantiationLines.push(`
case ${instantiationCompiler.reserveConst(token, 'token')}: {
return ${instantiationCompiler.reserveConst(prepared.resolveFrom, 'resolveFrom')}.injector.instantiations(${instantiationCompiler.reserveConst(token, 'token')});
}
`);
}

@@ -178,11 +195,24 @@ else {

lines.push(this.buildProvider(buildContext, resolverCompiler, name, accessor, scope, provider, prepared.modules));
instantiationLines.push(`
case ${instantiationCompiler.reserveConst(token, 'token')}: {
return injector.instantiated.${name} || 0;
}
`);
}
}
}
const setter = setterCompiler.build(`
this.instantiations = instantiationCompiler.build(`
//for ${core_1.getClassName(this.module)}
switch (token) {
${instantiationLines.join('\n')}
}
`, 'token');
this.setter = setterCompiler.build(`
//for ${core_1.getClassName(this.module)}
switch (token) {
${setterLines.join('\n')}
}
`, 'token', 'value', 'scope');
const resolver = resolverCompiler.raw(`
this.resolver = resolverCompiler.raw(`
//for ${core_1.getClassName(this.module)}
${creating.join('\n')};

@@ -202,4 +232,2 @@

`);
this.setter = setter;
this.resolver = resolver;
}

@@ -306,3 +334,3 @@ buildProvider(buildContext, compiler, name, accessor, scope, provider, resolveDependenciesFrom) {

return `
//${tokenLabel(token)}
//${tokenLabel(token)}, from ${resolveDependenciesFrom.map(core_1.getClassName).join(', ')}
case token === ${tokenVar}${scopeCheck}: {

@@ -312,2 +340,3 @@ ${!transient ? `if (${accessor} !== undefined) return ${accessor};` : ''}

${circularDependencyCheckStart}
injector.instantiated.${name} = injector.instantiated.${name} ? injector.instantiated.${name} + 1 : 1;
${factory.code}

@@ -514,2 +543,5 @@ ${circularDependencyCheckEnd}

}
instantiationCount(token, module) {
return this.getInjector(module || this.rootModule).instantiationCount(token);
}
set(token, value, module) {

@@ -516,0 +548,0 @@ return this.getInjector(module || this.rootModule).set(token, value, this.scope);

6

dist/cjs/src/module.d.ts
import { ConfigDefinition } from './config';
import { NormalizedProvider, ProviderWithScope, Token } from './provider';
import { ClassType } from '@deepkit/core';
import { AbstractClassType, ClassType } from '@deepkit/core';
import { InjectorToken } from './decorator';

@@ -39,3 +39,3 @@ import { BuildContext, Injector, SetupProviderRegistry } from './injector';

export declare function findModuleForConfig(config: ConfigDefinition<any>, modules: InjectorModule[]): InjectorModule;
export declare type ExportType = ClassType | InjectorToken<any> | string | InjectorModule;
export declare type ExportType = AbstractClassType | InjectorToken<any> | string | symbol | InjectorModule;
export declare function isProvided(providers: ProviderWithScope[], token: any): boolean;

@@ -90,2 +90,3 @@ export declare function getScope(provider: ProviderWithScope): string;

addExport(...controller: ClassType[]): this;
isExported(token: Token): boolean;
isProvided(classType: ClassType): boolean;

@@ -132,2 +133,3 @@ addProvider(...provider: ProviderWithScope[]): this;

resolveToken(token: any): InjectorModule | undefined;
getBuiltPreparedProviders(): Map<any, PreparedProvider> | undefined;
/**

@@ -134,0 +136,0 @@ * Prepared the module for a injector tree build.

@@ -28,6 +28,11 @@ "use strict";

let moduleIds = 0;
function registerPreparedProvider(map, modules, providers) {
function registerPreparedProvider(map, modules, providers, replaceExistingScope = true) {
const token = providers[0].provide;
const preparedProvider = map.get(token);
if (preparedProvider) {
for (const m of modules) {
if (preparedProvider.modules.includes(m))
continue;
preparedProvider.modules.push(m);
}
for (const provider of providers) {

@@ -42,3 +47,3 @@ const scope = getScope(provider);

}
else {
else if (replaceExistingScope) {
//scope already known, replace it

@@ -59,3 +64,4 @@ preparedProvider.providers.splice(knownProvider, 1, provider);

}
throw new Error(`No module found for configuration ${config.schema.toString().replace(/\n/g, ' ').replace(/\s+/g, ' ')}. Did you attach the configuration to a module?`);
const searchedIn = modules.map(v => core_1.getClassName(v));
throw new Error(`No module found for configuration ${config.schema.toString().replace(/\n/g, ' ').replace(/\s+/g, ' ')}. Searched in ${searchedIn.join(', ')}. Did you attach the configuration to a module?`);
}

@@ -157,2 +163,5 @@ exports.findModuleForConfig = findModuleForConfig;

}
isExported(token) {
return this.exports.includes(token);
}
isProvided(classType) {

@@ -282,2 +291,5 @@ return isProvided(this.getProviders(), classType);

}
getBuiltPreparedProviders() {
return this.preparedProviders;
}
/**

@@ -354,3 +366,3 @@ * Prepared the module for a injector tree build.

//we add our module as additional source for potential dependencies
parentProvider.modules.push(this);
registerPreparedProvider(parentProviders, preparedProvider.modules, preparedProvider.providers, false);
}

@@ -388,3 +400,3 @@ else {

//we add our module as additional source for potential dependencies
parentProvider.modules.push(this);
registerPreparedProvider(parentProviders, preparedProvider.modules, preparedProvider.providers, false);
}

@@ -391,0 +403,0 @@ else {

@@ -774,2 +774,106 @@ "use strict";

});
globals_1.test('instantiatedCount singleton', () => {
class Service {
}
class Registry {
}
const module1 = new module_1.InjectorModule([Service]);
const module2 = new module_1.InjectorModule([Registry]).addExport(Registry);
const root = new module_1.InjectorModule([]).addImport(module1, module2);
const injector = new injector_1.InjectorContext(root);
{
globals_1.expect(injector.instantiationCount(Service, module1)).toBe(0);
injector.get(Service, module1);
globals_1.expect(injector.instantiationCount(Service, module1)).toBe(1);
injector.get(Service, module1);
globals_1.expect(injector.instantiationCount(Service, module1)).toBe(1);
}
{
globals_1.expect(injector.instantiationCount(Registry, module2)).toBe(0);
injector.get(Registry, module2);
globals_1.expect(injector.instantiationCount(Registry, module2)).toBe(1);
injector.get(Registry, module2);
globals_1.expect(injector.instantiationCount(Registry, module2)).toBe(1);
}
});
globals_1.test('instantiatedCount scope', () => {
class Request {
}
const module1 = new module_1.InjectorModule([{ provide: Request, scope: 'http' }]);
const root = new module_1.InjectorModule([]).addImport(module1);
const injector = new injector_1.InjectorContext(root);
{
globals_1.expect(injector.createChildScope('http').instantiationCount(Request, module1)).toBe(0);
injector.createChildScope('http').get(Request, module1);
globals_1.expect(injector.createChildScope('http').instantiationCount(Request, module1)).toBe(1);
injector.createChildScope('http').get(Request, module1);
globals_1.expect(injector.createChildScope('http').instantiationCount(Request, module1)).toBe(2);
}
});
globals_1.test('configuration work in deeply nested imports with overridden service', () => {
const brokerConfig = new config_1.ConfigDefinition(type_1.t.schema({
listen: type_1.t.string
}));
let BrokerServer = class BrokerServer {
constructor(listen) {
this.listen = listen;
}
};
BrokerServer = __decorate([
__param(0, decorator_1.inject(brokerConfig.token('listen'))),
__metadata("design:paramtypes", [String])
], BrokerServer);
class BrokerModule extends module_1.InjectorModule {
}
let ApplicationServer = class ApplicationServer {
constructor(broker) {
this.broker = broker;
}
};
ApplicationServer = __decorate([
decorator_1.injectable,
__metadata("design:paramtypes", [BrokerServer])
], ApplicationServer);
class FrameworkModule extends module_1.InjectorModule {
}
const brokerModule = new BrokerModule([BrokerServer], undefined, { listen: '0.0.0.0' }).addExport(BrokerServer).setConfigDefinition(brokerConfig);
const frameworkModule = new FrameworkModule([ApplicationServer]).addImport(brokerModule).addExport(BrokerModule, ApplicationServer);
class Broker {
constructor(server) {
this.server = server;
}
}
class BrokerMemoryServer extends BrokerServer {
}
const root = new module_1.InjectorModule([
{ provide: BrokerServer, useClass: BrokerMemoryServer }
]).addImport(frameworkModule);
const injector = new injector_1.InjectorContext(root);
const applicationServer = injector.get(ApplicationServer);
globals_1.expect(applicationServer.broker.listen).toBe('0.0.0.0');
globals_1.expect(applicationServer.broker).toBeInstanceOf(BrokerMemoryServer);
const brokerServer = injector.get(BrokerServer);
globals_1.expect(brokerServer).toBeInstanceOf(BrokerMemoryServer);
globals_1.expect(brokerServer.listen).toBe('0.0.0.0');
});
globals_1.test('exported scoped can be replaced for another scope', () => {
class HttpRequest {
}
class HttpModule extends module_1.InjectorModule {
}
const httpModule = new HttpModule([{ provide: HttpRequest, scope: 'http' }]).addExport(HttpRequest);
class FrameworkModule extends module_1.InjectorModule {
}
const frameworkModule = new FrameworkModule([{ provide: HttpRequest, scope: 'rpc' }]).addImport(httpModule).addExport(HttpModule, HttpRequest);
const root = new module_1.InjectorModule().addImport(frameworkModule);
const injector = new injector_1.InjectorContext(root);
globals_1.expect(() => injector.get(HttpRequest)).toThrow('not found');
const scopeHttp = injector.createChildScope('http');
const httpRequest1 = scopeHttp.get(HttpRequest);
globals_1.expect(httpRequest1).toBeInstanceOf(HttpRequest);
const scopeRpc = injector.createChildScope('rpc');
const httpRequest2 = scopeRpc.get(HttpRequest);
globals_1.expect(httpRequest2).toBeInstanceOf(HttpRequest);
globals_1.expect(httpRequest2 !== httpRequest1).toBe(true);
});
//# sourceMappingURL=injector2.spec.js.map

@@ -53,2 +53,3 @@ import { NormalizedProvider, ProviderWithScope, TagRegistry, Token } from './provider';

private setter?;
private instantiations?;
/**

@@ -58,2 +59,3 @@ * All unscoped provider instances. Scoped instances are attached to `Scope`.

private instances;
private instantiated;
constructor(module: InjectorModule, buildContext: BuildContext);

@@ -64,2 +66,3 @@ static from(providers: ProviderWithScope[], parent?: Injector): Injector;

set<T>(token: T, value: any, scope?: Scope): void;
instantiationCount<T>(token: any): number;
clear(): void;

@@ -109,2 +112,3 @@ protected build(buildContext: BuildContext): void;

get<T>(token: T | Token, module?: InjectorModule): ResolveToken<T>;
instantiationCount(token: Token, module?: InjectorModule): number;
set<T>(token: T, value: any, module?: InjectorModule): void;

@@ -111,0 +115,0 @@ static forProviders(providers: ProviderWithScope[]): InjectorContext;

@@ -99,2 +99,3 @@ import { isClassProvider, isExistingProvider, isFactoryProvider, isValueProvider, Tag, TagProvider, TagRegistry } from './provider';

this.instances = {};
this.instantiated = {};
module.injector = this;

@@ -119,2 +120,7 @@ this.build(buildContext);

}
instantiationCount(token) {
if (!this.instantiations)
throw new Error('Injector was not built');
return this.instantiations(token);
}
clear() {

@@ -133,2 +139,5 @@ this.instances = {};

const creating = [];
const instantiationCompiler = new CompilerContext();
instantiationCompiler.context.set('injector', this);
const instantiationLines = [];
const setterCompiler = new CompilerContext();

@@ -153,2 +162,5 @@ setterCompiler.context.set('injector', this);

setterLines.push(`case ${setterCompiler.reserveVariable('token', token)}: {
if (${accessor} === undefined) {
injector.instantiated.${name} = injector.instantiated.${name} ? injector.instantiated.${name} + 1 : 1;
}
${accessor} = value;

@@ -160,6 +172,11 @@ break;

lines.push(`
case token === ${resolverCompiler.reserveConst(token)}: {
return ${resolverCompiler.reserveConst(prepared.resolveFrom)}.injector.resolver(${resolverCompiler.reserveConst(token)}, scope);
case token === ${resolverCompiler.reserveConst(token, 'token')}: {
return ${resolverCompiler.reserveConst(prepared.resolveFrom, 'resolveFrom')}.injector.resolver(${resolverCompiler.reserveConst(token, 'token')}, scope);
}
`);
`);
instantiationLines.push(`
case ${instantiationCompiler.reserveConst(token, 'token')}: {
return ${instantiationCompiler.reserveConst(prepared.resolveFrom, 'resolveFrom')}.injector.instantiations(${instantiationCompiler.reserveConst(token, 'token')});
}
`);
}

@@ -169,11 +186,24 @@ else {

lines.push(this.buildProvider(buildContext, resolverCompiler, name, accessor, scope, provider, prepared.modules));
instantiationLines.push(`
case ${instantiationCompiler.reserveConst(token, 'token')}: {
return injector.instantiated.${name} || 0;
}
`);
}
}
}
const setter = setterCompiler.build(`
this.instantiations = instantiationCompiler.build(`
//for ${getClassName(this.module)}
switch (token) {
${instantiationLines.join('\n')}
}
`, 'token');
this.setter = setterCompiler.build(`
//for ${getClassName(this.module)}
switch (token) {
${setterLines.join('\n')}
}
`, 'token', 'value', 'scope');
const resolver = resolverCompiler.raw(`
this.resolver = resolverCompiler.raw(`
//for ${getClassName(this.module)}
${creating.join('\n')};

@@ -193,4 +223,2 @@

`);
this.setter = setter;
this.resolver = resolver;
}

@@ -297,3 +325,3 @@ buildProvider(buildContext, compiler, name, accessor, scope, provider, resolveDependenciesFrom) {

return `
//${tokenLabel(token)}
//${tokenLabel(token)}, from ${resolveDependenciesFrom.map(getClassName).join(', ')}
case token === ${tokenVar}${scopeCheck}: {

@@ -303,2 +331,3 @@ ${!transient ? `if (${accessor} !== undefined) return ${accessor};` : ''}

${circularDependencyCheckStart}
injector.instantiated.${name} = injector.instantiated.${name} ? injector.instantiated.${name} + 1 : 1;
${factory.code}

@@ -503,2 +532,5 @@ ${circularDependencyCheckEnd}

}
instantiationCount(token, module) {
return this.getInjector(module || this.rootModule).instantiationCount(token);
}
set(token, value, module) {

@@ -505,0 +537,0 @@ return this.getInjector(module || this.rootModule).set(token, value, this.scope);

import { ConfigDefinition } from './config';
import { NormalizedProvider, ProviderWithScope, Token } from './provider';
import { ClassType } from '@deepkit/core';
import { AbstractClassType, ClassType } from '@deepkit/core';
import { InjectorToken } from './decorator';

@@ -39,3 +39,3 @@ import { BuildContext, Injector, SetupProviderRegistry } from './injector';

export declare function findModuleForConfig(config: ConfigDefinition<any>, modules: InjectorModule[]): InjectorModule;
export declare type ExportType = ClassType | InjectorToken<any> | string | InjectorModule;
export declare type ExportType = AbstractClassType | InjectorToken<any> | string | symbol | InjectorModule;
export declare function isProvided(providers: ProviderWithScope[], token: any): boolean;

@@ -90,2 +90,3 @@ export declare function getScope(provider: ProviderWithScope): string;

addExport(...controller: ClassType[]): this;
isExported(token: Token): boolean;
isProvided(classType: ClassType): boolean;

@@ -132,2 +133,3 @@ addProvider(...provider: ProviderWithScope[]): this;

resolveToken(token: any): InjectorModule | undefined;
getBuiltPreparedProviders(): Map<any, PreparedProvider> | undefined;
/**

@@ -134,0 +136,0 @@ * Prepared the module for a injector tree build.

@@ -24,6 +24,11 @@ import { TagProvider } from './provider';

let moduleIds = 0;
function registerPreparedProvider(map, modules, providers) {
function registerPreparedProvider(map, modules, providers, replaceExistingScope = true) {
const token = providers[0].provide;
const preparedProvider = map.get(token);
if (preparedProvider) {
for (const m of modules) {
if (preparedProvider.modules.includes(m))
continue;
preparedProvider.modules.push(m);
}
for (const provider of providers) {

@@ -38,3 +43,3 @@ const scope = getScope(provider);

}
else {
else if (replaceExistingScope) {
//scope already known, replace it

@@ -55,3 +60,4 @@ preparedProvider.providers.splice(knownProvider, 1, provider);

}
throw new Error(`No module found for configuration ${config.schema.toString().replace(/\n/g, ' ').replace(/\s+/g, ' ')}. Did you attach the configuration to a module?`);
const searchedIn = modules.map(v => getClassName(v));
throw new Error(`No module found for configuration ${config.schema.toString().replace(/\n/g, ' ').replace(/\s+/g, ' ')}. Searched in ${searchedIn.join(', ')}. Did you attach the configuration to a module?`);
}

@@ -150,2 +156,5 @@ export function isProvided(providers, token) {

}
isExported(token) {
return this.exports.includes(token);
}
isProvided(classType) {

@@ -275,2 +284,5 @@ return isProvided(this.getProviders(), classType);

}
getBuiltPreparedProviders() {
return this.preparedProviders;
}
/**

@@ -347,3 +359,3 @@ * Prepared the module for a injector tree build.

//we add our module as additional source for potential dependencies
parentProvider.modules.push(this);
registerPreparedProvider(parentProviders, preparedProvider.modules, preparedProvider.providers, false);
}

@@ -381,3 +393,3 @@ else {

//we add our module as additional source for potential dependencies
parentProvider.modules.push(this);
registerPreparedProvider(parentProviders, preparedProvider.modules, preparedProvider.providers, false);
}

@@ -384,0 +396,0 @@ else {

@@ -772,2 +772,106 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

});
test('instantiatedCount singleton', () => {
class Service {
}
class Registry {
}
const module1 = new InjectorModule([Service]);
const module2 = new InjectorModule([Registry]).addExport(Registry);
const root = new InjectorModule([]).addImport(module1, module2);
const injector = new InjectorContext(root);
{
expect(injector.instantiationCount(Service, module1)).toBe(0);
injector.get(Service, module1);
expect(injector.instantiationCount(Service, module1)).toBe(1);
injector.get(Service, module1);
expect(injector.instantiationCount(Service, module1)).toBe(1);
}
{
expect(injector.instantiationCount(Registry, module2)).toBe(0);
injector.get(Registry, module2);
expect(injector.instantiationCount(Registry, module2)).toBe(1);
injector.get(Registry, module2);
expect(injector.instantiationCount(Registry, module2)).toBe(1);
}
});
test('instantiatedCount scope', () => {
class Request {
}
const module1 = new InjectorModule([{ provide: Request, scope: 'http' }]);
const root = new InjectorModule([]).addImport(module1);
const injector = new InjectorContext(root);
{
expect(injector.createChildScope('http').instantiationCount(Request, module1)).toBe(0);
injector.createChildScope('http').get(Request, module1);
expect(injector.createChildScope('http').instantiationCount(Request, module1)).toBe(1);
injector.createChildScope('http').get(Request, module1);
expect(injector.createChildScope('http').instantiationCount(Request, module1)).toBe(2);
}
});
test('configuration work in deeply nested imports with overridden service', () => {
const brokerConfig = new ConfigDefinition(t.schema({
listen: t.string
}));
let BrokerServer = class BrokerServer {
constructor(listen) {
this.listen = listen;
}
};
BrokerServer = __decorate([
__param(0, inject(brokerConfig.token('listen'))),
__metadata("design:paramtypes", [String])
], BrokerServer);
class BrokerModule extends InjectorModule {
}
let ApplicationServer = class ApplicationServer {
constructor(broker) {
this.broker = broker;
}
};
ApplicationServer = __decorate([
injectable,
__metadata("design:paramtypes", [BrokerServer])
], ApplicationServer);
class FrameworkModule extends InjectorModule {
}
const brokerModule = new BrokerModule([BrokerServer], undefined, { listen: '0.0.0.0' }).addExport(BrokerServer).setConfigDefinition(brokerConfig);
const frameworkModule = new FrameworkModule([ApplicationServer]).addImport(brokerModule).addExport(BrokerModule, ApplicationServer);
class Broker {
constructor(server) {
this.server = server;
}
}
class BrokerMemoryServer extends BrokerServer {
}
const root = new InjectorModule([
{ provide: BrokerServer, useClass: BrokerMemoryServer }
]).addImport(frameworkModule);
const injector = new InjectorContext(root);
const applicationServer = injector.get(ApplicationServer);
expect(applicationServer.broker.listen).toBe('0.0.0.0');
expect(applicationServer.broker).toBeInstanceOf(BrokerMemoryServer);
const brokerServer = injector.get(BrokerServer);
expect(brokerServer).toBeInstanceOf(BrokerMemoryServer);
expect(brokerServer.listen).toBe('0.0.0.0');
});
test('exported scoped can be replaced for another scope', () => {
class HttpRequest {
}
class HttpModule extends InjectorModule {
}
const httpModule = new HttpModule([{ provide: HttpRequest, scope: 'http' }]).addExport(HttpRequest);
class FrameworkModule extends InjectorModule {
}
const frameworkModule = new FrameworkModule([{ provide: HttpRequest, scope: 'rpc' }]).addImport(httpModule).addExport(HttpModule, HttpRequest);
const root = new InjectorModule().addImport(frameworkModule);
const injector = new InjectorContext(root);
expect(() => injector.get(HttpRequest)).toThrow('not found');
const scopeHttp = injector.createChildScope('http');
const httpRequest1 = scopeHttp.get(HttpRequest);
expect(httpRequest1).toBeInstanceOf(HttpRequest);
const scopeRpc = injector.createChildScope('rpc');
const httpRequest2 = scopeRpc.get(HttpRequest);
expect(httpRequest2).toBeInstanceOf(HttpRequest);
expect(httpRequest2 !== httpRequest1).toBe(true);
});
//# sourceMappingURL=injector2.spec.js.map
{
"name": "@deepkit/injector",
"version": "1.0.1-alpha.56",
"version": "1.0.1-alpha.57",
"description": "Deepkit Dependency Injection",

@@ -44,3 +44,3 @@ "type": "commonjs",

},
"gitHead": "36c230c2a70b9c5c4524d84bd8b458550765cb79"
"gitHead": "a903656191c8a60a581610b6150d524800f93b77"
}

@@ -129,2 +129,3 @@ import { isClassProvider, isExistingProvider, isFactoryProvider, isValueProvider, NormalizedProvider, ProviderWithScope, Tag, TagProvider, TagRegistry, Token } from './provider';

private setter?: (token: any, value: any, scope?: Scope) => any;
private instantiations?: (token: any) => number;

@@ -135,2 +136,3 @@ /**

private instances: { [name: string]: any } = {};
private instantiated: { [name: string]: number } = {};

@@ -163,2 +165,7 @@ constructor(

instantiationCount<T>(token: any): number {
if (!this.instantiations) throw new Error('Injector was not built');
return this.instantiations(token);
}
clear() {

@@ -180,2 +187,6 @@ this.instances = {};

const instantiationCompiler = new CompilerContext();
instantiationCompiler.context.set('injector', this);
const instantiationLines: string[] = [];
const setterCompiler = new CompilerContext();

@@ -201,2 +212,5 @@ setterCompiler.context.set('injector', this);

setterLines.push(`case ${setterCompiler.reserveVariable('token', token)}: {
if (${accessor} === undefined) {
injector.instantiated.${name} = injector.instantiated.${name} ? injector.instantiated.${name} + 1 : 1;
}
${accessor} = value;

@@ -209,10 +223,21 @@ break;

lines.push(`
case token === ${resolverCompiler.reserveConst(token)}: {
return ${resolverCompiler.reserveConst(prepared.resolveFrom)}.injector.resolver(${resolverCompiler.reserveConst(token)}, scope);
case token === ${resolverCompiler.reserveConst(token, 'token')}: {
return ${resolverCompiler.reserveConst(prepared.resolveFrom, 'resolveFrom')}.injector.resolver(${resolverCompiler.reserveConst(token, 'token')}, scope);
}
`);
`);
instantiationLines.push(`
case ${instantiationCompiler.reserveConst(token, 'token')}: {
return ${instantiationCompiler.reserveConst(prepared.resolveFrom, 'resolveFrom')}.injector.instantiations(${instantiationCompiler.reserveConst(token, 'token')});
}
`)
} else {
//we own and instantiate the service
lines.push(this.buildProvider(buildContext, resolverCompiler, name, accessor, scope, provider, prepared.modules));
instantiationLines.push(`
case ${instantiationCompiler.reserveConst(token, 'token')}: {
return injector.instantiated.${name} || 0;
}
`)
}

@@ -222,4 +247,12 @@ }

const setter = setterCompiler.build(`
this.instantiations = instantiationCompiler.build(`
//for ${getClassName(this.module)}
switch (token) {
${instantiationLines.join('\n')}
}
`, 'token');
this.setter = setterCompiler.build(`
//for ${getClassName(this.module)}
switch (token) {
${setterLines.join('\n')}

@@ -229,3 +262,4 @@ }

const resolver = resolverCompiler.raw(`
this.resolver = resolverCompiler.raw(`
//for ${getClassName(this.module)}
${creating.join('\n')};

@@ -245,5 +279,2 @@

`) as any;
this.setter = setter;
this.resolver = resolver;
}

@@ -366,3 +397,3 @@

return `
//${tokenLabel(token)}
//${tokenLabel(token)}, from ${resolveDependenciesFrom.map(getClassName).join(', ')}
case token === ${tokenVar}${scopeCheck}: {

@@ -372,2 +403,3 @@ ${!transient ? `if (${accessor} !== undefined) return ${accessor};` : ''}

${circularDependencyCheckStart}
injector.instantiated.${name} = injector.instantiated.${name} ? injector.instantiated.${name} + 1 : 1;
${factory.code}

@@ -598,2 +630,6 @@ ${circularDependencyCheckEnd}

instantiationCount(token: Token, module?: InjectorModule): number {
return this.getInjector(module || this.rootModule).instantiationCount(token);
}
set<T>(token: T, value: any, module?: InjectorModule): void {

@@ -600,0 +636,0 @@ return this.getInjector(module || this.rootModule).set(token, value, this.scope);

import { ConfigDefinition } from './config';
import { NormalizedProvider, ProviderWithScope, TagProvider, Token } from './provider';
import { arrayRemoveItem, ClassType, getClassName, isClass, isPrototypeOfBase } from '@deepkit/core';
import { AbstractClassType, arrayRemoveItem, ClassType, getClassName, isClass, isPrototypeOfBase } from '@deepkit/core';
import { InjectorToken } from './decorator';

@@ -59,6 +59,10 @@ import { BuildContext, Injector, SetupProviderRegistry } from './injector';

function registerPreparedProvider(map: Map<any, PreparedProvider>, modules: InjectorModule[], providers: NormalizedProvider[]) {
function registerPreparedProvider(map: Map<any, PreparedProvider>, modules: InjectorModule[], providers: NormalizedProvider[], replaceExistingScope: boolean = true) {
const token = providers[0].provide;
const preparedProvider = map.get(token);
if (preparedProvider) {
for (const m of modules) {
if (preparedProvider.modules.includes(m)) continue;
preparedProvider.modules.push(m);
}
for (const provider of providers) {

@@ -72,3 +76,3 @@ const scope = getScope(provider);

preparedProvider.providers.push(provider);
} else {
} else if (replaceExistingScope) {
//scope already known, replace it

@@ -89,6 +93,8 @@ preparedProvider.providers.splice(knownProvider, 1, provider);

throw new Error(`No module found for configuration ${config.schema.toString().replace(/\n/g, ' ').replace(/\s+/g, ' ')}. Did you attach the configuration to a module?`);
const searchedIn = modules.map(v => getClassName(v));
throw new Error(`No module found for configuration ${config.schema.toString().replace(/\n/g, ' ').replace(/\s+/g, ' ')}. Searched in ${searchedIn.join(', ')}. Did you attach the configuration to a module?`);
}
export type ExportType = ClassType | InjectorToken<any> | string | InjectorModule;
export type ExportType = AbstractClassType | InjectorToken<any> | string | symbol | InjectorModule;

@@ -208,2 +214,6 @@ export function isProvided(providers: ProviderWithScope[], token: any): boolean {

isExported(token: Token): boolean {
return this.exports.includes(token);
}
isProvided(classType: ClassType): boolean {

@@ -347,2 +357,6 @@ return isProvided(this.getProviders(), classType);

getBuiltPreparedProviders(): Map<any, PreparedProvider> | undefined {
return this.preparedProviders;
}
/**

@@ -424,3 +438,3 @@ * Prepared the module for a injector tree build.

//we add our module as additional source for potential dependencies
parentProvider.modules.push(this);
registerPreparedProvider(parentProviders, preparedProvider.modules, preparedProvider.providers, false);
} else {

@@ -460,3 +474,3 @@ parentProviders.set(token, { modules: [this], providers: preparedProvider.providers.slice() });

//we add our module as additional source for potential dependencies
parentProvider.modules.push(this);
registerPreparedProvider(parentProviders, preparedProvider.modules, preparedProvider.providers, false);
} else {

@@ -463,0 +477,0 @@ parentProviders.set(token, { modules: [this, ...preparedProvider.modules], providers: preparedProvider.providers.slice() });

@@ -918,1 +918,129 @@ import 'reflect-metadata';

});
test('instantiatedCount singleton', () => {
class Service {
}
class Registry {
}
const module1 = new InjectorModule([Service]);
const module2 = new InjectorModule([Registry]).addExport(Registry);
const root = new InjectorModule([]).addImport(module1, module2);
const injector = new InjectorContext(root);
{
expect(injector.instantiationCount(Service, module1)).toBe(0);
injector.get(Service, module1);
expect(injector.instantiationCount(Service, module1)).toBe(1);
injector.get(Service, module1);
expect(injector.instantiationCount(Service, module1)).toBe(1);
}
{
expect(injector.instantiationCount(Registry, module2)).toBe(0);
injector.get(Registry, module2);
expect(injector.instantiationCount(Registry, module2)).toBe(1);
injector.get(Registry, module2);
expect(injector.instantiationCount(Registry, module2)).toBe(1);
}
});
test('instantiatedCount scope', () => {
class Request {
}
const module1 = new InjectorModule([{ provide: Request, scope: 'http' }]);
const root = new InjectorModule([]).addImport(module1);
const injector = new InjectorContext(root);
{
expect(injector.createChildScope('http').instantiationCount(Request, module1)).toBe(0);
injector.createChildScope('http').get(Request, module1);
expect(injector.createChildScope('http').instantiationCount(Request, module1)).toBe(1);
injector.createChildScope('http').get(Request, module1);
expect(injector.createChildScope('http').instantiationCount(Request, module1)).toBe(2);
}
});
test('configuration work in deeply nested imports with overridden service', () => {
const brokerConfig = new ConfigDefinition(t.schema({
listen: t.string
}));
class BrokerServer {
constructor(@inject(brokerConfig.token('listen')) public listen: string) {
}
}
class BrokerModule extends InjectorModule {
}
@injectable
class ApplicationServer {
constructor(public broker: BrokerServer) {
}
}
class FrameworkModule extends InjectorModule {
}
const brokerModule = new BrokerModule([BrokerServer], undefined, { listen: '0.0.0.0' }).addExport(BrokerServer).setConfigDefinition(brokerConfig);
const frameworkModule = new FrameworkModule([ApplicationServer]).addImport(brokerModule).addExport(BrokerModule, ApplicationServer);
class Broker {
constructor(public server: BrokerServer) {
}
}
class BrokerMemoryServer extends BrokerServer {
}
const root = new InjectorModule([
{ provide: BrokerServer, useClass: BrokerMemoryServer }
]).addImport(frameworkModule);
const injector = new InjectorContext(root);
const applicationServer = injector.get(ApplicationServer);
expect(applicationServer.broker.listen).toBe('0.0.0.0');
expect(applicationServer.broker).toBeInstanceOf(BrokerMemoryServer);
const brokerServer = injector.get(BrokerServer);
expect(brokerServer).toBeInstanceOf(BrokerMemoryServer);
expect(brokerServer.listen).toBe('0.0.0.0');
});
test('exported scoped can be replaced for another scope', () => {
class HttpRequest {
}
class HttpModule extends InjectorModule {
}
const httpModule = new HttpModule([{ provide: HttpRequest, scope: 'http' }]).addExport(HttpRequest);
class FrameworkModule extends InjectorModule {
}
const frameworkModule = new FrameworkModule([{ provide: HttpRequest, scope: 'rpc' }]).addImport(httpModule).addExport(HttpModule, HttpRequest);
const root = new InjectorModule().addImport(frameworkModule);
const injector = new InjectorContext(root);
expect(() => injector.get(HttpRequest)).toThrow('not found');
const scopeHttp = injector.createChildScope('http');
const httpRequest1 = scopeHttp.get(HttpRequest);
expect(httpRequest1).toBeInstanceOf(HttpRequest);
const scopeRpc = injector.createChildScope('rpc');
const httpRequest2 = scopeRpc.get(HttpRequest);
expect(httpRequest2).toBeInstanceOf(HttpRequest);
expect(httpRequest2 !== httpRequest1).toBe(true);
});

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