Socket
Socket
Sign inDemoInstall

tsyringe

Package Overview
Dependencies
1
Maintainers
2
Versions
24
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 4.1.0 to 4.2.0

dist/cjs/lazy-helpers.js

20

dist/cjs/dependency-container.js

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

const error_helpers_1 = require("./error-helpers");
const lazy_helpers_1 = require("./lazy-helpers");
exports.typeInfo = new Map();

@@ -80,3 +81,6 @@ class InternalDependencyContainer {

}
return this.construct(token, context);
if (injection_token_1.isConstructorToken(token)) {
return this.construct(token, context);
}
throw new Error("Attempted to construct an undefined constructor. Could mean a circular dependency problem. Try using `delay` function.");
}

@@ -137,2 +141,12 @@ resolveRegistration(registration, context) {

}
clearInstances() {
for (const [token, registrations] of this._registry.entries()) {
this._registry.setAll(token, registrations
.filter(registration => !providers_1.isValueProvider(registration.provider))
.map(registration => {
registration.instance = undefined;
return registration;
}));
}
}
createChildContainer() {

@@ -174,4 +188,4 @@ const childContainer = new InternalDependencyContainer(this);

construct(ctor, context) {
if (typeof ctor === "undefined") {
throw new Error("Attempted to construct an undefined constructor. Could mean a circular dependency problem.");
if (ctor instanceof lazy_helpers_1.DelayedConstructor) {
return ctor.createProxy((target) => this.resolve(target, context));
}

@@ -178,0 +192,0 @@ if (ctor.length === 0) {

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

tslib_1.__exportStar(require("./providers"), exports);
var lazy_helpers_1 = require("./lazy-helpers");
exports.delay = lazy_helpers_1.delay;
var dependency_container_1 = require("./dependency-container");
exports.container = dependency_container_1.instance;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const lazy_helpers_1 = require("../lazy-helpers");
function isNormalToken(token) {

@@ -13,1 +14,5 @@ return typeof token === "string" || typeof token === "symbol";

exports.isTokenDescriptor = isTokenDescriptor;
function isConstructorToken(token) {
return typeof token === "function" || token instanceof lazy_helpers_1.DelayedConstructor;
}
exports.isConstructorToken = isConstructorToken;
import { isClassProvider, isFactoryProvider, isNormalToken, isTokenProvider, isValueProvider } from "./providers";
import { isProvider } from "./providers/provider";
import { isTokenDescriptor } from "./providers/injection-token";
import { isConstructorToken, isTokenDescriptor } from "./providers/injection-token";
import Registry from "./registry";

@@ -8,2 +8,3 @@ import Lifecycle from "./types/lifecycle";

import { formatErrorCtor } from "./error-helpers";
import { DelayedConstructor } from "./lazy-helpers";
export const typeInfo = new Map();

@@ -78,3 +79,6 @@ class InternalDependencyContainer {

}
return this.construct(token, context);
if (isConstructorToken(token)) {
return this.construct(token, context);
}
throw new Error("Attempted to construct an undefined constructor. Could mean a circular dependency problem. Try using `delay` function.");
}

@@ -135,2 +139,12 @@ resolveRegistration(registration, context) {

}
clearInstances() {
for (const [token, registrations] of this._registry.entries()) {
this._registry.setAll(token, registrations
.filter(registration => !isValueProvider(registration.provider))
.map(registration => {
registration.instance = undefined;
return registration;
}));
}
}
createChildContainer() {

@@ -172,4 +186,4 @@ const childContainer = new InternalDependencyContainer(this);

construct(ctor, context) {
if (typeof ctor === "undefined") {
throw new Error("Attempted to construct an undefined constructor. Could mean a circular dependency problem.");
if (ctor instanceof DelayedConstructor) {
return ctor.createProxy((target) => this.resolve(target, context));
}

@@ -176,0 +190,0 @@ if (ctor.length === 0) {

@@ -8,2 +8,3 @@ if (typeof Reflect === "undefined" || !Reflect.getMetadata) {

export * from "./providers";
export { delay } from "./lazy-helpers";
export { instance as container } from "./dependency-container";

@@ -0,1 +1,2 @@

import { DelayedConstructor } from "../lazy-helpers";
export function isNormalToken(token) {

@@ -9,1 +10,4 @@ return typeof token === "string" || typeof token === "symbol";

}
export function isConstructorToken(token) {
return typeof token === "function" || token instanceof DelayedConstructor;
}
import { __read, __spread, __values } from "tslib";
import { isClassProvider, isFactoryProvider, isNormalToken, isTokenProvider, isValueProvider } from "./providers";
import { isProvider } from "./providers/provider";
import { isTokenDescriptor } from "./providers/injection-token";
import { isConstructorToken, isTokenDescriptor } from "./providers/injection-token";
import Registry from "./registry";

@@ -9,2 +9,3 @@ import Lifecycle from "./types/lifecycle";

import { formatErrorCtor } from "./error-helpers";
import { DelayedConstructor } from "./lazy-helpers";
export var typeInfo = new Map();

@@ -81,3 +82,6 @@ var InternalDependencyContainer = (function () {

}
return this.construct(token, context);
if (isConstructorToken(token)) {
return this.construct(token, context);
}
throw new Error("Attempted to construct an undefined constructor. Could mean a circular dependency problem. Try using `delay` function.");
};

@@ -143,4 +147,25 @@ InternalDependencyContainer.prototype.resolveRegistration = function (registration, context) {

};
InternalDependencyContainer.prototype.clearInstances = function () {
var e_1, _a;
try {
for (var _b = __values(this._registry.entries()), _c = _b.next(); !_c.done; _c = _b.next()) {
var _d = __read(_c.value, 2), token = _d[0], registrations = _d[1];
this._registry.setAll(token, registrations
.filter(function (registration) { return !isValueProvider(registration.provider); })
.map(function (registration) {
registration.instance = undefined;
return registration;
}));
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
};
InternalDependencyContainer.prototype.createChildContainer = function () {
var e_1, _a;
var e_2, _a;
var childContainer = new InternalDependencyContainer(this);

@@ -166,3 +191,3 @@ try {

}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {

@@ -172,3 +197,3 @@ try {

}
finally { if (e_1) throw e_1.error; }
finally { if (e_2) throw e_2.error; }
}

@@ -196,4 +221,7 @@ return childContainer;

InternalDependencyContainer.prototype.construct = function (ctor, context) {
if (typeof ctor === "undefined") {
throw new Error("Attempted to construct an undefined constructor. Could mean a circular dependency problem.");
var _this = this;
if (ctor instanceof DelayedConstructor) {
return ctor.createProxy(function (target) {
return _this.resolve(target, context);
});
}

@@ -200,0 +228,0 @@ if (ctor.length === 0) {

@@ -8,2 +8,3 @@ if (typeof Reflect === "undefined" || !Reflect.getMetadata) {

export * from "./providers";
export { delay } from "./lazy-helpers";
export { instance as container } from "./dependency-container";

@@ -0,1 +1,2 @@

import { DelayedConstructor } from "../lazy-helpers";
export function isNormalToken(token) {

@@ -9,1 +10,4 @@ return typeof token === "string" || typeof token === "symbol";

}
export function isConstructorToken(token) {
return typeof token === "function" || token instanceof DelayedConstructor;
}

@@ -5,2 +5,3 @@ export { DependencyContainer, Lifecycle, RegistrationOptions } from "./types";

export * from "./providers";
export { delay } from "./lazy-helpers";
export { instance as container } from "./dependency-container";

3

dist/typings/providers/class-provider.d.ts
import constructor from "../types/constructor";
import Provider from "./provider";
import { DelayedConstructor } from "../lazy-helpers";
export default interface ClassProvider<T> {
useClass: constructor<T>;
useClass: constructor<T> | DelayedConstructor<T>;
}
export declare function isClassProvider<T>(provider: Provider<T>): provider is ClassProvider<any>;
import constructor from "../types/constructor";
declare type InjectionToken<T = any> = constructor<T> | string | symbol;
import { DelayedConstructor } from "../lazy-helpers";
declare type InjectionToken<T = any> = constructor<T> | string | symbol | DelayedConstructor<T>;
export declare function isNormalToken(token?: InjectionToken<any>): token is string | symbol;
export declare function isTokenDescriptor(descriptor: any): descriptor is TokenDescriptor;
export declare function isConstructorToken(token?: InjectionToken<any>): token is constructor<any> | DelayedConstructor<any>;
export interface TokenDescriptor {

@@ -6,0 +8,0 @@ token: InjectionToken<any>;

@@ -38,3 +38,4 @@ import FactoryProvider from "../providers/factory-provider";

reset(): void;
clearInstances(): void;
createChildContainer(): DependencyContainer;
}
{
"name": "tsyringe",
"version": "4.1.0",
"version": "4.2.0",
"description": "Lightweight dependency injection container for JavaScript/TypeScript",

@@ -5,0 +5,0 @@ "main": "dist/cjs/index.js",

@@ -29,2 +29,6 @@ [![Travis](https://img.shields.io/travis/Microsoft/tsyringe.svg)](https://travis-ci.org/Microsoft/tsyringe/)

- [Child Containers](#child-containers)
- [Clearing Instances](#clearing-instances)
- [Circular dependencies](#circular-dependencies)
- [The `delay` helper function](#the-delay-helper-function)
- [Interfaces and circular dependencies](#interfaces-and-circular-dependencies)
- [Full examples](#full-examples)

@@ -229,6 +233,6 @@ - [Example without interfaces](#example-without-interfaces)

A token may be either a string, a symbol, or a class constructor.
A token may be either a string, a symbol, a class constructor, or a instance of [`DelayedConstructor`](#circular-dependencies).
```typescript
type InjectionToken<T = any> = constructor<T> | string | symbol;
type InjectionToken<T = any> = constructor<T> | DelayedConstructor<T> | string | symbol;
```

@@ -346,9 +350,7 @@

```TypeScript
@injectable()
@registry([
Foo,
Bar,
{
token: "IFoobar",
useClass: MockFoobar
{ token: Foobar, useClass: Foobar },
{ token: "theirClass", useFactory: (c) => {
return new TheirClass( "arg" )
},
}

@@ -359,5 +361,8 @@ ])

This is useful when you don't control the entry point for your code (e.g. being instantiated by a framework), and need
an opportunity to do registration. Otherwise, it's preferable to use `.register()`. **Note** the `@injectable()` decorator
must precede the `@registry()` decorator, since TypeScript executes decorators inside out.
This is useful when you want to [register multiple classes for the same token](#register).
You can also use it to register and declare objects that wouldn't be imported by anything else,
such as more classes annotated with `@registry` or that are otherwise responsible for registering objects.
Lastly you might choose to use this to register 3rd party instances instead of the `container.register(...)` method.
note: if you want this class to be `@injectable` you must put the decorator before `@registry`, this annotation is not
required though.

@@ -394,5 +399,7 @@ ### Resolution

```
### Child Containers
If you need to have multiple containers that have disparate sets of registrations, you can create child containers
If you need to have multiple containers that have disparate sets of registrations, you can create child containers:
```typescript

@@ -403,4 +410,130 @@ const childContainer1 = container.createChildContainer();

```
Each of the child containers will have independent registrations, but if a registration is absent in the child container at resolution, the token will be resolved from the parent. This allows for a set of common services to be registered at the root, with specialized services registered on the child. This can be useful, for example, if you wish to create per-request containers that use common stateless services from the root container.
### Clearing Instances
The `container.clearInstances()` method allows you to clear all previously created and registered instances:
```typescript
class Foo {}
@singleton()
class Bar {}
const myFoo = new Foo();
container.registerInstance("Test", myFoo);
const myBar = container.resolve(Bar);
container.clearInstances();
container.resolve("Test"); // throws error
const myBar2 = container.resolve(Bar); // myBar !== myBar2
const myBar3 = container.resolve(Bar); // myBar2 === myBar3
```
Unlike with `container.reset()`, the registrations themselves are not cleared.
This is especially useful for testing:
```typescript
@singleton()
class Foo {}
beforeEach(() => {
container.clearInstances();
});
test("something", () => {
container.resolve(Foo); // will be a new singleton instance in every test
});
```
# Circular dependencies
Sometimes you need to inject services that have cyclic dependencies between them. As an example:
```typescript
@injectable()
export class Foo {
constructor(public bar: Bar) {}
}
@injectable()
export class Bar {
constructor(public foo: Foo) {}
}
```
Trying to resolve one of the services will end in an error because always one of the constructor will not be fully defined to construct the other one.
```typescript
container.resolve(Foo)
```
```
Error: Cannot inject the dependency at position #0 of "Foo" constructor. Reason:
Attempted to construct an undefined constructor. Could mean a circular dependency problem. Try using `delay` function.
```
### The `delay` helper function
The best way to deal with this situation is to do some kind of refactor to avoid the cyclic dependencies. Usually this implies introducing additional services to cut the cycles.
But when refactor is not an option you can use the `delay` function helper. The `delay` function wraps the constructor in an instance of `DelayedConstructor`.
The *delayed constructor* is a kind of special `InjectionToken` that will eventually be evaluated to construct an intermediate proxy object wrapping a factory for the real object.
When the proxy object is used for the first time it will construct a real object using this factory and any usage will be forwarded to the real object.
```typescript
@injectable()
export class Foo {
constructor(@inject(delay(Bar)) public bar: Bar) {}
}
@injectable()
export class Bar {
constructor(@inject(delay(Foo)) public foo: Foo) {}
}
// construction of foo is possible
const foo = container.resolve(Foo);
// property bar will hold a proxy that looks and acts as a real Bar instance.
foo.bar instanceof Bar; // true
```
### Interfaces and circular dependencies
We can rest in the fact that a `DelayedConstructor` could be used in the same contexts that a constructor and will be handled transparently by tsyringe. Such idea is used in the next example involving interfaces:
```typescript
export interface IFoo {}
@injectable()
@registry([
{
token: "IBar",
// `DelayedConstructor` of Bar will be the token
useToken: delay(Bar)
}
])
export class Foo implements IFoo {
constructor(@inject("IBar") public bar: IBar) {}
}
export interface IBar {}
@injectable()
@registry([
{
token: "IFoo",
useToken: delay(Foo)
}
])
export class Bar implements IBar {
constructor(@inject("IFoo") public foo: IFoo) {}
}
```
# Full examples

@@ -407,0 +540,0 @@

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc