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

@wendellhu/redi

Package Overview
Dependencies
Maintainers
1
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@wendellhu/redi - npm Package Compare versions

Comparing version 0.2.4 to 0.2.6

esm/types.d.ts

173

dist/redi.js

@@ -46,2 +46,14 @@ (function (global, factory) {

exports.Quantity = void 0;
(function (Quantity) {
Quantity["MANY"] = "many";
Quantity["OPTIONAL"] = "optional";
Quantity["REQUIRED"] = "required";
})(exports.Quantity || (exports.Quantity = {}));
exports.LookUp = void 0;
(function (LookUp) {
LookUp["SELF"] = "self";
LookUp["SKIP_SELF"] = "skipSelf";
})(exports.LookUp || (exports.LookUp = {}));
var __extends$5 = (undefined && undefined.__extends) || (function () {

@@ -85,86 +97,6 @@ var extendStatics = function (d, b) {

})();
exports.Quantity = void 0;
(function (Quantity) {
Quantity["MANY"] = "many";
Quantity["OPTIONAL"] = "optional";
Quantity["REQUIRED"] = "required";
})(exports.Quantity || (exports.Quantity = {}));
var IdentifierUndefinedError = /** @class */ (function (_super) {
__extends$4(IdentifierUndefinedError, _super);
function IdentifierUndefinedError(target, index) {
var _this = this;
var msg = "It seems that you register \"undefined\" as dependency on the " + (index + 1) + " parameter of \"" + prettyPrintIdentifier(target) + "\".";
_this = _super.call(this, msg) || this;
return _this;
}
return IdentifierUndefinedError;
}(RediError));
var QuantityCheckError = /** @class */ (function (_super) {
__extends$4(QuantityCheckError, _super);
function QuantityCheckError(id, quantity, actual) {
var _this = this;
var msg = "Expect \"" + quantity + "\" dependency items for id \"" + prettyPrintIdentifier(id) + "\" but get " + actual + ".";
_this = _super.call(this, msg) || this;
return _this;
}
return QuantityCheckError;
}(RediError));
function checkQuantity(id, quantity, length) {
if ((quantity === exports.Quantity.OPTIONAL && length > 1) || (quantity === exports.Quantity.REQUIRED && length !== 1)) {
throw new QuantityCheckError(id, quantity, length);
}
}
function retrieveQuantity(quantity, arr) {
if (quantity === exports.Quantity.MANY) {
return arr;
}
else {
return arr[0];
}
}
function changeQuantity(target, index, quantity) {
var descriptor = getDependencyByIndex(target, index);
descriptor.quantity = quantity;
}
function quantifyDecoratorFactoryProducer(quantity) {
return function decoratorFactory(id) {
if (this instanceof decoratorFactory) {
return this;
}
return function (registerTarget, _key, index) {
if (id) {
setDependency(registerTarget, id, index, quantity);
}
else {
if (quantity === exports.Quantity.REQUIRED) {
throw new IdentifierUndefinedError(registerTarget, index);
}
changeQuantity(registerTarget, index, quantity);
}
};
};
}
var Many = quantifyDecoratorFactoryProducer(exports.Quantity.MANY);
var Optional = quantifyDecoratorFactoryProducer(exports.Quantity.OPTIONAL);
var Inject = quantifyDecoratorFactoryProducer(exports.Quantity.REQUIRED);
var __extends$3 = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var TARGET = Symbol('$$TARGET');
var DEPENDENCIES = Symbol('$$DEPENDENCIES');
var DependencyDescriptorNotFoundError = /** @class */ (function (_super) {
__extends$3(DependencyDescriptorNotFoundError, _super);
__extends$4(DependencyDescriptorNotFoundError, _super);
function DependencyDescriptorNotFoundError(index, target) {

@@ -245,2 +177,76 @@ var _this = this;

var __extends$3 = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var IdentifierUndefinedError = /** @class */ (function (_super) {
__extends$3(IdentifierUndefinedError, _super);
function IdentifierUndefinedError(target, index) {
var _this = this;
var msg = "It seems that you register \"undefined\" as dependency on the " + (index + 1) + " parameter of \"" + prettyPrintIdentifier(target) + "\".";
_this = _super.call(this, msg) || this;
return _this;
}
return IdentifierUndefinedError;
}(RediError));
var QuantityCheckError = /** @class */ (function (_super) {
__extends$3(QuantityCheckError, _super);
function QuantityCheckError(id, quantity, actual) {
var _this = this;
var msg = "Expect \"" + quantity + "\" dependency items for id \"" + prettyPrintIdentifier(id) + "\" but get " + actual + ".";
_this = _super.call(this, msg) || this;
return _this;
}
return QuantityCheckError;
}(RediError));
function checkQuantity(id, quantity, length) {
if ((quantity === exports.Quantity.OPTIONAL && length > 1) || (quantity === exports.Quantity.REQUIRED && length !== 1)) {
throw new QuantityCheckError(id, quantity, length);
}
}
function retrieveQuantity(quantity, arr) {
if (quantity === exports.Quantity.MANY) {
return arr;
}
else {
return arr[0];
}
}
function changeQuantity(target, index, quantity) {
var descriptor = getDependencyByIndex(target, index);
descriptor.quantity = quantity;
}
function quantifyDecoratorFactoryProducer(quantity) {
return function decoratorFactory(id) {
if (this instanceof decoratorFactory) {
return this;
}
return function (registerTarget, _key, index) {
if (id) {
setDependency(registerTarget, id, index, quantity);
}
else {
if (quantity === exports.Quantity.REQUIRED) {
throw new IdentifierUndefinedError(registerTarget, index);
}
changeQuantity(registerTarget, index, quantity);
}
};
};
}
var Many = quantifyDecoratorFactoryProducer(exports.Quantity.MANY);
var Optional = quantifyDecoratorFactoryProducer(exports.Quantity.OPTIONAL);
var Inject = quantifyDecoratorFactoryProducer(exports.Quantity.REQUIRED);
function forwardRef(wrapper) {

@@ -401,7 +407,2 @@ return {

exports.LookUp = void 0;
(function (LookUp) {
LookUp["SELF"] = "self";
LookUp["SKIP_SELF"] = "skipSelf";
})(exports.LookUp || (exports.LookUp = {}));
function changeLookup(target, index, lookUp) {

@@ -408,0 +409,0 @@ var descriptor = getDependencyByIndex(target, index);

import { DependencyDescriptor } from './dependencyDescriptor';
import { DependencyIdentifier, IdentifierDecorator } from './dependencyIdentifier';
import { Ctor } from './dependencyItem';
import { Quantity } from './dependencyQuantity';
import { Quantity } from './types';
export declare const TARGET: unique symbol;

@@ -6,0 +6,0 @@ export declare const DEPENDENCIES: unique symbol;

@@ -18,3 +18,3 @@ var __extends = (this && this.__extends) || (function () {

import { prettyPrintIdentifier } from './dependencyItem';
import { Quantity } from './dependencyQuantity';
import { Quantity } from './types';
import { RediError } from './error';

@@ -21,0 +21,0 @@ export var TARGET = Symbol('$$TARGET');

import { DependencyIdentifier } from './dependencyIdentifier';
import { Ctor, DependencyItem } from './dependencyItem';
import { Quantity } from './dependencyQuantity';
import { Disposable } from './dispose';
import { Quantity } from './types';
import { RediError } from './error';

@@ -6,0 +6,0 @@ export declare type DependencyPair<T> = [DependencyIdentifier<T>, DependencyItem<T>];

@@ -17,4 +17,5 @@ var __extends = (this && this.__extends) || (function () {

import { prettyPrintIdentifier } from './dependencyItem';
import { checkQuantity, Quantity, retrieveQuantity } from './dependencyQuantity';
import { checkQuantity, retrieveQuantity } from './dependencyQuantity';
import { isDisposable } from './dispose';
import { Quantity } from './types';
import { RediError } from './error';

@@ -21,0 +22,0 @@ export function isBareClassDependency(thing) {

import { DependencyIdentifier } from './dependencyIdentifier';
import { FactoryDep } from './dependencyItem';
import { LookUp } from './dependencyLookUp';
import { Quantity } from './dependencyQuantity';
import { LookUp, Quantity } from './types';
export interface DependencyDescriptor<T> {

@@ -6,0 +5,0 @@ paramIndex: number;

@@ -1,3 +0,4 @@

import { LookUp, Self, SkipSelf } from './dependencyLookUp';
import { Optional, Quantity } from './dependencyQuantity';
import { Self, SkipSelf } from './dependencyLookUp';
import { Optional } from './dependencyQuantity';
import { LookUp, Quantity } from './types';
export function normalizeFactoryDeps(deps) {

@@ -4,0 +5,0 @@ if (!deps) {

@@ -1,5 +0,1 @@

export declare enum LookUp {
SELF = "self",
SKIP_SELF = "skipSelf"
}
interface SkipSelfDecorator {

@@ -6,0 +2,0 @@ (): any;

import { getDependencyByIndex } from './decorators';
export var LookUp;
(function (LookUp) {
LookUp["SELF"] = "self";
LookUp["SKIP_SELF"] = "skipSelf";
})(LookUp || (LookUp = {}));
import { LookUp } from './types';
function changeLookup(target, index, lookUp) {

@@ -8,0 +4,0 @@ var descriptor = getDependencyByIndex(target, index);

import { DependencyIdentifier } from './dependencyIdentifier';
export declare enum Quantity {
MANY = "many",
OPTIONAL = "optional",
REQUIRED = "required"
}
import { Quantity } from './types';
export declare function checkQuantity(id: DependencyIdentifier<any>, quantity: Quantity, length: number): void;

@@ -8,0 +4,0 @@ export declare function retrieveQuantity<T>(quantity: Quantity, arr: T[]): T[] | T;

@@ -19,8 +19,3 @@ var __extends = (this && this.__extends) || (function () {

import { RediError } from './error';
export var Quantity;
(function (Quantity) {
Quantity["MANY"] = "many";
Quantity["OPTIONAL"] = "optional";
Quantity["REQUIRED"] = "required";
})(Quantity || (Quantity = {}));
import { Quantity } from './types';
var IdentifierUndefinedError = /** @class */ (function (_super) {

@@ -27,0 +22,0 @@ __extends(IdentifierUndefinedError, _super);

import { Dependency, DependencyPair } from './dependencyCollection';
import { DependencyIdentifier } from './dependencyIdentifier';
import { Ctor, DependencyItem, AsyncHook } from './dependencyItem';
import { LookUp } from './dependencyLookUp';
import { Quantity } from './dependencyQuantity';
import { Quantity, LookUp } from './types';
export declare class Injector {

@@ -7,0 +6,0 @@ private readonly dependencyCollection;

@@ -40,4 +40,2 @@ var __extends = (this && this.__extends) || (function () {

import { isClassDependencyItem, isFactoryDependencyItem, isInstanceDependencyItem, isAsyncDependencyItem, isAsyncHook, isCtor, prettyPrintIdentifier, } from './dependencyItem';
import { LookUp } from './dependencyLookUp';
import { Quantity } from './dependencyQuantity';
import { normalizeForwardRef } from './dependencyForwardRef';

@@ -47,2 +45,3 @@ import { IdleValue } from './idleValue';

import { RediError } from './error';
import { Quantity, LookUp } from './types';
var MAX_RESOLUTIONS_QUEUED = 300;

@@ -49,0 +48,0 @@ var NotInstantiatedSymbol = Symbol('$$NOT_INSTANTIATED_SYMBOL');

export { createIdentifier } from './decorators';
export { Many, Optional, Inject, Quantity } from './dependencyQuantity';
export { Quantity, LookUp } from './types';
export { Many, Optional, Inject } from './dependencyQuantity';
export { forwardRef } from './dependencyForwardRef';
export { Injector } from './injector';
export { LookUp, SkipSelf, Self } from './dependencyLookUp';
export { SkipSelf, Self } from './dependencyLookUp';
export { DependencyPair, Dependency } from './dependencyCollection';

@@ -7,0 +8,0 @@ export { DependencyIdentifier } from './dependencyIdentifier';

export { createIdentifier } from './decorators';
export { Many, Optional, Inject, Quantity } from './dependencyQuantity';
export { Quantity, LookUp } from './types';
export { Many, Optional, Inject } from './dependencyQuantity';
export { forwardRef } from './dependencyForwardRef';
export { Injector } from './injector';
export { LookUp, SkipSelf, Self } from './dependencyLookUp';
export { SkipSelf, Self } from './dependencyLookUp';
export { registerSingleton } from './dependencySingletons';
export { RediError } from './error';
//# sourceMappingURL=publicApi.js.map

@@ -40,2 +40,14 @@ var IdentifierDecoratorSymbol = Symbol('$$IDENTIFIER_DECORATOR');

var Quantity;
(function (Quantity) {
Quantity["MANY"] = "many";
Quantity["OPTIONAL"] = "optional";
Quantity["REQUIRED"] = "required";
})(Quantity || (Quantity = {}));
var LookUp;
(function (LookUp) {
LookUp["SELF"] = "self";
LookUp["SKIP_SELF"] = "skipSelf";
})(LookUp || (LookUp = {}));
var __extends$5 = (undefined && undefined.__extends) || (function () {

@@ -79,86 +91,6 @@ var extendStatics = function (d, b) {

})();
var Quantity;
(function (Quantity) {
Quantity["MANY"] = "many";
Quantity["OPTIONAL"] = "optional";
Quantity["REQUIRED"] = "required";
})(Quantity || (Quantity = {}));
var IdentifierUndefinedError = /** @class */ (function (_super) {
__extends$4(IdentifierUndefinedError, _super);
function IdentifierUndefinedError(target, index) {
var _this = this;
var msg = "It seems that you register \"undefined\" as dependency on the " + (index + 1) + " parameter of \"" + prettyPrintIdentifier(target) + "\".";
_this = _super.call(this, msg) || this;
return _this;
}
return IdentifierUndefinedError;
}(RediError));
var QuantityCheckError = /** @class */ (function (_super) {
__extends$4(QuantityCheckError, _super);
function QuantityCheckError(id, quantity, actual) {
var _this = this;
var msg = "Expect \"" + quantity + "\" dependency items for id \"" + prettyPrintIdentifier(id) + "\" but get " + actual + ".";
_this = _super.call(this, msg) || this;
return _this;
}
return QuantityCheckError;
}(RediError));
function checkQuantity(id, quantity, length) {
if ((quantity === Quantity.OPTIONAL && length > 1) || (quantity === Quantity.REQUIRED && length !== 1)) {
throw new QuantityCheckError(id, quantity, length);
}
}
function retrieveQuantity(quantity, arr) {
if (quantity === Quantity.MANY) {
return arr;
}
else {
return arr[0];
}
}
function changeQuantity(target, index, quantity) {
var descriptor = getDependencyByIndex(target, index);
descriptor.quantity = quantity;
}
function quantifyDecoratorFactoryProducer(quantity) {
return function decoratorFactory(id) {
if (this instanceof decoratorFactory) {
return this;
}
return function (registerTarget, _key, index) {
if (id) {
setDependency(registerTarget, id, index, quantity);
}
else {
if (quantity === Quantity.REQUIRED) {
throw new IdentifierUndefinedError(registerTarget, index);
}
changeQuantity(registerTarget, index, quantity);
}
};
};
}
var Many = quantifyDecoratorFactoryProducer(Quantity.MANY);
var Optional = quantifyDecoratorFactoryProducer(Quantity.OPTIONAL);
var Inject = quantifyDecoratorFactoryProducer(Quantity.REQUIRED);
var __extends$3 = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var TARGET = Symbol('$$TARGET');
var DEPENDENCIES = Symbol('$$DEPENDENCIES');
var DependencyDescriptorNotFoundError = /** @class */ (function (_super) {
__extends$3(DependencyDescriptorNotFoundError, _super);
__extends$4(DependencyDescriptorNotFoundError, _super);
function DependencyDescriptorNotFoundError(index, target) {

@@ -239,2 +171,76 @@ var _this = this;

var __extends$3 = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var IdentifierUndefinedError = /** @class */ (function (_super) {
__extends$3(IdentifierUndefinedError, _super);
function IdentifierUndefinedError(target, index) {
var _this = this;
var msg = "It seems that you register \"undefined\" as dependency on the " + (index + 1) + " parameter of \"" + prettyPrintIdentifier(target) + "\".";
_this = _super.call(this, msg) || this;
return _this;
}
return IdentifierUndefinedError;
}(RediError));
var QuantityCheckError = /** @class */ (function (_super) {
__extends$3(QuantityCheckError, _super);
function QuantityCheckError(id, quantity, actual) {
var _this = this;
var msg = "Expect \"" + quantity + "\" dependency items for id \"" + prettyPrintIdentifier(id) + "\" but get " + actual + ".";
_this = _super.call(this, msg) || this;
return _this;
}
return QuantityCheckError;
}(RediError));
function checkQuantity(id, quantity, length) {
if ((quantity === Quantity.OPTIONAL && length > 1) || (quantity === Quantity.REQUIRED && length !== 1)) {
throw new QuantityCheckError(id, quantity, length);
}
}
function retrieveQuantity(quantity, arr) {
if (quantity === Quantity.MANY) {
return arr;
}
else {
return arr[0];
}
}
function changeQuantity(target, index, quantity) {
var descriptor = getDependencyByIndex(target, index);
descriptor.quantity = quantity;
}
function quantifyDecoratorFactoryProducer(quantity) {
return function decoratorFactory(id) {
if (this instanceof decoratorFactory) {
return this;
}
return function (registerTarget, _key, index) {
if (id) {
setDependency(registerTarget, id, index, quantity);
}
else {
if (quantity === Quantity.REQUIRED) {
throw new IdentifierUndefinedError(registerTarget, index);
}
changeQuantity(registerTarget, index, quantity);
}
};
};
}
var Many = quantifyDecoratorFactoryProducer(Quantity.MANY);
var Optional = quantifyDecoratorFactoryProducer(Quantity.OPTIONAL);
var Inject = quantifyDecoratorFactoryProducer(Quantity.REQUIRED);
function forwardRef(wrapper) {

@@ -395,7 +401,2 @@ return {

var LookUp;
(function (LookUp) {
LookUp["SELF"] = "self";
LookUp["SKIP_SELF"] = "skipSelf";
})(LookUp || (LookUp = {}));
function changeLookup(target, index, lookUp) {

@@ -402,0 +403,0 @@ var descriptor = getDependencyByIndex(target, index);

{
"$schema": "https://raw.githubusercontent.com/wendellhu95/squirrel/master/src/schema/package.schema.json",
"name": "@wendellhu/redi",
"version": "0.2.4",
"version": "0.2.6",
"description": "A dependency library for TypeScript and JavaScript, along with a binding for React.",
"exports": {
"./react-bindings": {
"import": "./fesm/react-bindings.js",
"require": "./dist/react-bindings.js",
"types": "./esm/react-bindings/publicApi.d.ts"
},
"./package.json": "./package.json",
".": {
"import": "./fesm/redi.js",
"require": "./dist/redi.js",
"types": "./esm/publicApi.d.ts"
}
},
"author": "wendellhu95 <wendellhu95@gmail.com>",

@@ -7,0 +20,0 @@ "license": "MIT",

# redi
![Stars](https://badgen.net/github/stars/wendellhu95/redi)
![Downloads](https://badgen.net/npm/dt/@wendellhu/redi)
![Codecov](https://badgen.net/github/license/wendellhu95/redi)
[![Codecov](https://img.shields.io/codecov/c/github/wendellhu95/redi.svg)](https://codecov.io/gh/wendellhu95/redi)
A dependency library for TypeScript and JavaScript, along with a binding for React.
no
[Demo TodoMVC](https://wendellhu95.github.io/redi-todomvc/) | [Demo Repo](https://github.com/wendellhu95/redi-todomvc)
## Overview
[![Codecov](https://img.shields.io/codecov/c/github/wendellhu95/redi.svg?style=flat-square)](https://codecov.io/gh/wendellhu95/redi)
## Features
**redi** (pronounced 'ready') is a dependency injection library for TypeScript (& JavaScript with some babel config). It also provides a set of bindings to let you adopt the pattern in your React applications.
- **Completely opt-in**. Unlike Angular, redi let you decide when and where to use dependency injection.
- **Hierarchical dependency tree.**
- Supports **multi kinds of dependency items**, including
- classes
- instances
- factories
- async items
- Supports **n-ary dependencies**
- Required
- Optional
- Many
- **Constructor dependencies.**
- **Forward ref**, to resolve problems rising from cyclic dependency of JavaScript files.
- **Lazy instantiation**, instantiate a dependency only when they are accessed to boost up performance.
## Getting Started
### Installation
```sh
npm install @wendellhu/redi
```
After installation you need to enable `experimentalDecorators` in your tsconfig.json file.
```diff
{
"compilerOptions": {
+ "experimentalDecorators": true
}
}
```
### Basics
Let's get started with a real-word example:
```typescript
import { Inject } from '@wendellhu/redi'
class AuthService {
static public getCurrentUserInfo(): UserInfo {
// your implementation here...
}
}
class FileListService {
constructor() {}
public getUserFiles(): Promise<Files> {
const currentUser = // ...AuthService.getCurrentUserInfo()
// ...
}
}
```
It is clearly that `FileListServices` dependents on `AuthService`, so you just need to declare it on the constructor of `FileListService`.
Step 1. Declare dependency relationship.
```diff
class AuthService {
public getCurrentUserInfo(): UserInfo {

@@ -77,365 +20,17 @@ // your implementation here...

}
+ import { Inject } from '@wendellhu/redi'
class FileListService {
- constructor() {}
+ constructor(@Inject(AuthService) private readonly authService: AuthService) {}
constructor(@Inject(AuthService) private readonly authService: AuthService) {}
public getUserFiles(): Promise<Files> {
- const currentUser = // ...AuthService.getCurrentUserInfo()
+ const currentUser = this.authService.getCurrentUserInfo()
const currentUser = this.authService.getCurrentUserInfo()
// ...
}
}
const injector = new Injector([[AuthService], [FileListService]])
injector.get(AuthService)
```
Then you need to include all things into an `Injector`.
**View full documentation and examples on [redi.wendell.fun](https://redi.wendell.fun/).**
Step 2. Provide dependencies.
```typescript
import { Injector } from '@wendellhu/redi'
const injector = new Injector([[FileListService], [AuthService]])
```
You don't instantiate a `FileListService` by yourself. You get a `FileListService` from the injector just created.
Step 3. Wire up!
```typescript
const fileListService = injector.get(FileListService)
```
That's it!
### React Bindings
redi provides a set of React bindings in it's secondary entry point `@wendellhu/redi/react-bindings` that can help you use it in your React application easily.
```tsx
import { withDependencies } from '@wendellhu/redi/react-bindings'
const App = withDependencies(
function AppImpl() {
const injector = useInjector()
const fileListService = injector.get(FileListService)
// ...
},
[[FileListService], [AuthService]]
)
```
## Concepts
- The **injector** holds a set of bindings and resolves dependencies.
- A **binding** maps a **token** to a **dependency item**.
- Token works as an identifier. It differentiate a dependency from another. It could be
- the return value of `createIdentifier`
- or a class
- A dependency item could be
- a class
- an instance or value
- a factory function
- an async item, which would be resoled to an other kind of dependency later
- Dependency could declare its own dependencies, and contains extra information on how its dependencies should be injected, and contains extra information on how its dependencies should be injected.
## API
### Decorators
**`createIdentifier`**
```ts
function createIdentifier<T>(id: string): IdentifierDecorator<T>
```
Create a token that could identify a dependency. The token could be used as an decorator to declare dependencies.
```ts
import { createIdentifier } from '@wendellhu/redi'
interface IPlatformService {
copy(): Promise<boolean>
}
const IPlatformService = createIdentifier<IPlatformService>()
class Editor {
constructor(@IPlatformService private readonly ipfs: IPlatformService) {}
}
```
**`Inject Many Optional`**
- `Inject` marks the parameter as being a required dependency. By default, token returned from `createIdentifier` marks the parameter as required as well.
- `Many` marks the parameter and being a n-ary dependency.
- `Optional` marks the parameter as being an optional dependency.
```ts
class MobileEditor {
constructor(
@Inject(SoftKeyboard) private readonly softKeyboard: SoftKeyboard,
@Many(Menu) private readonly menus: Menu[],
@Optional(IPlatformService) private readonly ipfs?: IPlatformService
) {}
}
```
**`Self SkipSelf`**
- `Self` marks that the parameter should only be resolved by the current injector.
- `SkipSelf` marks that parameter should be resolved from the current injector's parent.
```ts
import { Self, SkipSelf } from '@wendellhu/redi'
class Person {
constructor() {
@Self() @Inject(forwardRef(() => Father)) private readonly father: Father,
@SkipSelf() @Inject(forwardRef(() => Father)) private readonly grandfather: Father
}
}
class Father extends Person {}
```
### Dependency Items
You can provide different kinds of dependency items, including class items, factory items, value items and async items.
#### **`ClassItem`**
```ts
interface ClassDependencyItem<T> {
useClass: Ctor<T>
lazy?: boolean
}
```
- `useClass` the class
- `lazy` enable lazy instantiation. The dependency would be instantiated only when CPU is idle or its properties or methods are actually accessed.
#### **`ValueDependencyItem`**
```ts
export interface ValueDependencyItem<T> {
useValue: T
}
```
#### **`FactoryDependencyItem`**
```ts
export interface FactoryDependencyItem<T> {
useFactory: (...deps: any[]) => T
deps?: FactoryDep<any>[]
}
```
#### **`AsyncDependencyItem`**
```ts
export type SyncDependencyItem<T> =
| ClassDependencyItem<T>
| FactoryDependencyItem<T>
| ValueDependencyItem<T>
interface AsyncDependencyItem<T> {
useAsync: () => Promise<
T | Ctor<T> | [DependencyIdentifier<T>, SyncDependencyItem<T>]
>
}
```
### Injector
```typescript
class Injector {
constructor(collectionOrDependencies?: Dependency[], parent?: Injector) {}
}
```
Create an injector with a bunch of bindings.
You can pass in another `Injector` as its parent injector.
```ts
class Injector {
public createChild(dependencies?: Dependency[]): Injector
}
```
Create a child injector. When a child injector could not resolve a dependency, it would delegate to its parent injector.
```ts
class Injector {
public dispose(): void
}
```
Dispose an injector, its child injectors and all _disposable_ dependencies in the injector tree.
```ts
class Injector {
public add<T>(ctor: Ctor<T>): void
public add<T>(
id: DependencyIdentifier<T>,
item: DependencyItem<T> | T
): void
public add<T>(
idOrCtor: Ctor<T> | DependencyIdentifier<T>,
item?: DependencyItem<T> | T
): void
}
```
Add a dependency or a value into the injector.
```ts
class Injector {
public get<T>(id: DependencyIdentifier<T>, lookUp?: LookUp): T
public get<T>(
id: DependencyIdentifier<T>,
quantity: Quantity.MANY,
lookUp?: LookUp
): T[]
public get<T>(
id: DependencyIdentifier<T>,
quantity: Quantity.OPTIONAL,
lookUp?: LookUp
): T | null
public get<T>(
id: DependencyIdentifier<T>,
quantity: Quantity.REQUIRED,
lookUp?: LookUp
): T
public get<T>(
id: DependencyIdentifier<T>,
quantity: Quantity,
lookUp?: LookUp
): T
public get<T>(
id: DependencyIdentifier<T>,
quantityOrLookup?: Quantity | LookUp,
lookUp?: LookUp
): T[] | T | null
}
```
Get a dependency from the injector.
```ts
class Injector {
public getAsync<T>(id: DependencyIdentifier<T>): Promise<T>
}
```
Get an async dependency.
```ts
class Injector {
public createInstance<T extends unknown[], U extends unknown[], C>(
ctor: new (...args: [...T, ...U]) => C,
...customArgs: T
): C
}
```
Instantiate a class-type dependency with extra parameters.
### `forwardRef`
In the example above, `Person` is declared before `Father`, but it depends on `Father`. In this case, you need to use `forwardRef` to wrap `Father`. Otherwise, `Father` is evaluated to `undefined` in dependency relationship resolution.
```ts
import { Self, SkipSelf } from '@wendellhu/redi'
class Person {
constructor() {
@Self() @Inject(forwardRef(() => Father)) private readonly father: Father,
@SkipSelf() @Inject(forwardRef(() => Father)) private readonly grandfather: Father
}
}
class Father extends Person {}
```
### Singletons
Sometimes you want some dependencies to be singletons. In that case, you don't have to add them to the root injector manually. Instead, you can just use `registerSingleton`.
```ts
export function registerSingleton<T>(
id: DependencyIdentifier<T>,
item: DependencyItem<T>
): void
```
Singletons would be fetched by the root injectors (in another word, injectors that don't have a parent injector) automatically.
In avoidance of unexpected error, it is strongly recommended to have only one root injector in your application.
### React Bindings
#### `connectDependencies`
```ts
export function connectDependencies<T>(
Comp: React.ComponentType<T>,
dependencies: Dependency[]
): React.ComponentType<T>
```
Bind dependencies into a React component. The dependencies would be instantiated when they are used in the React component tree. When you wrap a connected React component inside another, the injectors will hook up as well.
#### React Context
```ts
export const RediProvider = RediContext.Provider
export const RediConsumer = RediContext.Consumer
```
React context to consume or provide an `Injector`. In most cases you don't have to use them.
#### Hooks
```ts
export function useInjector(): Injector
```
Get the nearest `Injector`.
#### Decorators
```ts
export function WithDependency<T>(
id: DependencyIdentifier<T>,
quantity?: Quantity,
lookUp?: LookUp
): any
```
A decorator to be used on Class Component to get a dependency from the nearest `Injector`. An example:
```tsx
class AppImpl extends React.Component<{}> {
static contextType = RediContext
@WithDependency(IPlatformDependency)
private readonly platform!: IPlatformDependency
render() {
return <div>{this.a.key}</div>
}
}
```
## JavaScript
Redi could also be used in your JavaScript projects, provided that you use Babel to transpile your source files. Just add [this babel plugin](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy) to your babel config.
## License
MIT. Copyright 2021 Wendell Hu.

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

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