@wendellhu/redi
Advanced tools
Comparing version 0.1.5 to 0.1.6
@@ -75,3 +75,3 @@ (function (global, factory) { | ||
function WithDependency(id, quantity, lookUp) { | ||
return function (_target) { | ||
return function () { | ||
return { | ||
@@ -105,2 +105,4 @@ get: function () { | ||
var childInjectorRef = React__namespace.useRef(null); | ||
// dispose the injector when the container Injector unmounts | ||
React__namespace.useEffect(function () { return function () { var _a; return (_a = childInjectorRef.current) === null || _a === void 0 ? void 0 : _a.dispose(); }; }, []); | ||
return (React__namespace.createElement(RediConsumer, null, function (context) { | ||
@@ -120,2 +122,8 @@ var childInjector; | ||
} | ||
/** | ||
* @deprecated | ||
* @param Comp | ||
* @param injector | ||
* @returns | ||
*/ | ||
function connectInjector(Comp, injector) { | ||
@@ -122,0 +130,0 @@ return function ComponentWithInjector(props) { |
107
dist/redi.js
@@ -9,3 +9,3 @@ (function (global, factory) { | ||
var __extends$5 = (undefined && undefined.__extends) || (function () { | ||
var __extends$4 = (undefined && undefined.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
@@ -32,3 +32,3 @@ extendStatics = Object.setPrototypeOf || | ||
var IdentifierUndefinedError = /** @class */ (function (_super) { | ||
__extends$5(IdentifierUndefinedError, _super); | ||
__extends$4(IdentifierUndefinedError, _super); | ||
function IdentifierUndefinedError(target, index) { | ||
@@ -43,3 +43,3 @@ var _this = this; | ||
var QuantityCheckError = /** @class */ (function (_super) { | ||
__extends$5(QuantityCheckError, _super); | ||
__extends$4(QuantityCheckError, _super); | ||
function QuantityCheckError(id, quantity, actual) { | ||
@@ -93,3 +93,3 @@ var _this = this; | ||
var __extends$4 = (undefined && undefined.__extends) || (function () { | ||
var __extends$3 = (undefined && undefined.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
@@ -112,3 +112,3 @@ extendStatics = Object.setPrototypeOf || | ||
var DependencyDescriptorNotFoundError = /** @class */ (function (_super) { | ||
__extends$4(DependencyDescriptorNotFoundError, _super); | ||
__extends$3(DependencyDescriptorNotFoundError, _super); | ||
function DependencyDescriptorNotFoundError(index, target) { | ||
@@ -208,3 +208,3 @@ var _this = this; | ||
var __extends$3 = (undefined && undefined.__extends) || (function () { | ||
var __extends$2 = (undefined && undefined.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
@@ -228,3 +228,3 @@ extendStatics = Object.setPrototypeOf || | ||
var DependencyNotFoundError = /** @class */ (function (_super) { | ||
__extends$3(DependencyNotFoundError, _super); | ||
__extends$2(DependencyNotFoundError, _super); | ||
function DependencyNotFoundError(id) { | ||
@@ -265,2 +265,3 @@ var _this = this; | ||
if (quantity === void 0) { quantity = exports.Quantity.REQUIRED; } | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
var ret = this.dependencyMap.get(id); | ||
@@ -378,24 +379,3 @@ checkQuantity(id, quantity, ret.length); | ||
var __extends$2 = (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 NotValidDependencyModifierError = /** @class */ (function (_super) { | ||
__extends$2(NotValidDependencyModifierError, _super); | ||
function NotValidDependencyModifierError() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
return NotValidDependencyModifierError; | ||
}(Error)); | ||
// class NotValidDependencyModifierError extends Error {} | ||
function normalizeFactoryDeps(deps) { | ||
@@ -549,2 +529,3 @@ if (!deps) { | ||
} | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
return this.value; | ||
@@ -626,6 +607,10 @@ }; | ||
}; | ||
var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
@@ -655,4 +640,4 @@ var MAX_RESOLUTIONS_QUEUED = 300; | ||
}(Error)); | ||
var DecoratorInjector = /** @class */ (function () { | ||
function DecoratorInjector(collectionOrDependencies, parent) { | ||
var Injector = /** @class */ (function () { | ||
function Injector(collectionOrDependencies, parent) { | ||
this.resolvedDependencyCollection = new ResolvedDependencyCollection(); | ||
@@ -673,7 +658,7 @@ this.children = []; | ||
} | ||
DecoratorInjector.prototype.createChild = function (dependencies) { | ||
Injector.prototype.createChild = function (dependencies) { | ||
this.ensureInjectorNotDisposed(); | ||
return new DecoratorInjector(dependencies, this); | ||
return new Injector(dependencies, this); | ||
}; | ||
DecoratorInjector.prototype.dispose = function () { | ||
Injector.prototype.dispose = function () { | ||
this.dependencyCollection.dispose(); | ||
@@ -683,3 +668,3 @@ this.resolvedDependencyCollection.dispose(); | ||
}; | ||
DecoratorInjector.prototype.add = function (idOrCtor, item) { | ||
Injector.prototype.add = function (idOrCtor, item) { | ||
if (typeof item !== 'undefined') { | ||
@@ -700,3 +685,3 @@ if (isAsyncDependencyItem(item) || | ||
}; | ||
DecoratorInjector.prototype.get = function (id, quantityOrLookup, lookUp) { | ||
Injector.prototype.get = function (id, quantityOrLookup, lookUp) { | ||
this.ensureInjectorNotDisposed(); | ||
@@ -729,3 +714,3 @@ var quantity = exports.Quantity.REQUIRED; | ||
*/ | ||
DecoratorInjector.prototype.getAsync = function (id) { | ||
Injector.prototype.getAsync = function (id) { | ||
this.ensureInjectorNotDisposed(); | ||
@@ -745,3 +730,3 @@ var cachedResult = this.getValue(id, exports.Quantity.REQUIRED); | ||
*/ | ||
DecoratorInjector.prototype.createInstance = function (ctor) { | ||
Injector.prototype.createInstance = function (ctor) { | ||
var customArgs = []; | ||
@@ -752,3 +737,3 @@ for (var _i = 1; _i < arguments.length; _i++) { | ||
this.ensureInjectorNotDisposed(); | ||
return this.resolveClass_.apply(this, __spreadArray([ctor], customArgs)); | ||
return this.resolveClass_.apply(this, __spreadArray([ctor], customArgs, false)); | ||
}; | ||
@@ -758,3 +743,3 @@ /** | ||
*/ | ||
DecoratorInjector.prototype.resolveDependency = function (id, item) { | ||
Injector.prototype.resolveDependency = function (id, item) { | ||
if (isInstanceDependencyItem(item)) { | ||
@@ -773,3 +758,3 @@ return this.resolveInstanceDependency(id, item); | ||
}; | ||
DecoratorInjector.prototype.resolveInstanceDependency = function (id, item) { | ||
Injector.prototype.resolveInstanceDependency = function (id, item) { | ||
var thing = item.useValue; | ||
@@ -779,3 +764,3 @@ this.resolvedDependencyCollection.add(id, thing); | ||
}; | ||
DecoratorInjector.prototype.resolveClass = function (id, item) { | ||
Injector.prototype.resolveClass = function (id, item) { | ||
var _this = this; | ||
@@ -819,3 +804,3 @@ var ctor = item.useClass; | ||
}; | ||
DecoratorInjector.prototype.resolveClass_ = function (ctor) { | ||
Injector.prototype.resolveClass_ = function (ctor) { | ||
var extraParams = []; | ||
@@ -835,3 +820,3 @@ for (var _i = 1; _i < arguments.length; _i++) { | ||
} | ||
var args = __spreadArray([], extraParams); | ||
var args = __spreadArray([], extraParams, true); | ||
var firstDependencyArgIndex = declaredDependencies.length > 0 | ||
@@ -844,3 +829,3 @@ ? declaredDependencies[0].paramIndex | ||
if (delta > 0) { | ||
args = __spreadArray(__spreadArray([], args), new Array(delta).fill(undefined)); | ||
args = __spreadArray(__spreadArray([], args, true), new Array(delta).fill(undefined), true); | ||
} | ||
@@ -851,7 +836,7 @@ else { | ||
} | ||
var thing = new (ctor.bind.apply(ctor, __spreadArray(__spreadArray([void 0], args), resolvedArgs)))(); | ||
var thing = new (ctor.bind.apply(ctor, __spreadArray(__spreadArray([void 0], args, false), resolvedArgs, false)))(); | ||
this.markResolutionCompleted(); | ||
return thing; | ||
}; | ||
DecoratorInjector.prototype.resolveFactory = function (id, item) { | ||
Injector.prototype.resolveFactory = function (id, item) { | ||
this.markNewResolution(); | ||
@@ -870,3 +855,3 @@ var declaredDependencies = normalizeFactoryDeps(item.deps); | ||
}; | ||
DecoratorInjector.prototype.resolveAsync = function (id, item) { | ||
Injector.prototype.resolveAsync = function (id, item) { | ||
var _this = this; | ||
@@ -878,3 +863,3 @@ var asyncLoader = { | ||
}; | ||
DecoratorInjector.prototype.resolveAsync_ = function (id, item) { | ||
Injector.prototype.resolveAsync_ = function (id, item) { | ||
var _this = this; | ||
@@ -911,3 +896,3 @@ return item.useAsync().then(function (thing) { | ||
*/ | ||
DecoratorInjector.prototype.getValue = function (id, quantity, lookUp) { | ||
Injector.prototype.getValue = function (id, quantity, lookUp) { | ||
var _this = this; | ||
@@ -945,3 +930,3 @@ if (quantity === void 0) { quantity = exports.Quantity.REQUIRED; } | ||
*/ | ||
DecoratorInjector.prototype.createAndCacheDependency = function (id, quantity, lookUp) { | ||
Injector.prototype.createAndCacheDependency = function (id, quantity, lookUp) { | ||
var _this = this; | ||
@@ -976,3 +961,3 @@ if (quantity === void 0) { quantity = exports.Quantity.REQUIRED; } | ||
} | ||
if (id === DecoratorInjector) { | ||
if (id === Injector) { | ||
return this; | ||
@@ -985,3 +970,3 @@ } | ||
}; | ||
DecoratorInjector.prototype.markNewResolution = function (id) { | ||
Injector.prototype.markNewResolution = function (id) { | ||
this.resolutionOngoing += 1; | ||
@@ -992,6 +977,6 @@ if (this.resolutionOngoing >= MAX_RESOLUTIONS_QUEUED) { | ||
}; | ||
DecoratorInjector.prototype.markResolutionCompleted = function () { | ||
Injector.prototype.markResolutionCompleted = function () { | ||
this.resolutionOngoing -= 1; | ||
}; | ||
DecoratorInjector.prototype.ensureInjectorNotDisposed = function () { | ||
Injector.prototype.ensureInjectorNotDisposed = function () { | ||
if (this.disposed) { | ||
@@ -1001,7 +986,7 @@ throw new InjectorAlreadyDisposedError(); | ||
}; | ||
return DecoratorInjector; | ||
return Injector; | ||
}()); | ||
exports.Inject = Inject; | ||
exports.Injector = DecoratorInjector; | ||
exports.Injector = Injector; | ||
exports.Many = Many; | ||
@@ -1008,0 +993,0 @@ exports.Optional = Optional; |
@@ -59,2 +59,3 @@ var __extends = (this && this.__extends) || (function () { | ||
if (quantity === void 0) { quantity = Quantity.REQUIRED; } | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
var ret = this.dependencyMap.get(id); | ||
@@ -61,0 +62,0 @@ checkQuantity(id, quantity, ret.length); |
@@ -1,25 +0,4 @@ | ||
var __extends = (this && this.__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 __()); | ||
}; | ||
})(); | ||
import { LookUp, Self, SkipSelf } from './dependencyLookUp'; | ||
import { Optional, Quantity } from './dependencyQuantity'; | ||
var NotValidDependencyModifierError = /** @class */ (function (_super) { | ||
__extends(NotValidDependencyModifierError, _super); | ||
function NotValidDependencyModifierError() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
return NotValidDependencyModifierError; | ||
}(Error)); | ||
// class NotValidDependencyModifierError extends Error {} | ||
export function normalizeFactoryDeps(deps) { | ||
@@ -26,0 +5,0 @@ if (!deps) { |
@@ -7,3 +7,3 @@ import { DependencyIdentifier, NormalizedDependencyIdentifier } from './dependencyIdentifier'; | ||
export declare function forwardRef<T>(wrapper: () => Ctor<T>): ForwardRef<T>; | ||
export declare function isForwardRef<T = any>(thing: any): thing is ForwardRef<T>; | ||
export declare function isForwardRef<T = any>(thing: unknown): thing is ForwardRef<T>; | ||
export declare function normalizeForwardRef<T>(id: DependencyIdentifier<T>): NormalizedDependencyIdentifier<T>; |
@@ -8,3 +8,3 @@ import { DependencyIdentifier } from './dependencyIdentifier'; | ||
} | ||
export declare function isCtor<T>(thing: any): thing is Ctor<T>; | ||
export declare function isCtor<T>(thing: unknown): thing is Ctor<T>; | ||
export interface ClassDependencyItem<T> { | ||
@@ -14,3 +14,3 @@ useClass: Ctor<T>; | ||
} | ||
export declare function isClassDependencyItem<T>(thing: any): thing is ClassDependencyItem<T>; | ||
export declare function isClassDependencyItem<T>(thing: unknown): thing is ClassDependencyItem<T>; | ||
export declare type FactoryDepModifier = typeof Self | typeof SkipSelf | typeof Optional | typeof Many; | ||
@@ -22,16 +22,16 @@ export declare type FactoryDep<T> = [...FactoryDepModifier[], DependencyIdentifier<T>] | DependencyIdentifier<T>; | ||
} | ||
export declare function isFactoryDependencyItem<T>(thing: any): thing is FactoryDependencyItem<T>; | ||
export declare function isFactoryDependencyItem<T>(thing: unknown): thing is FactoryDependencyItem<T>; | ||
export interface ValueDependencyItem<T> { | ||
useValue: T; | ||
} | ||
export declare function isInstanceDependencyItem<T>(thing: any): thing is ValueDependencyItem<T>; | ||
export declare function isInstanceDependencyItem<T>(thing: unknown): thing is ValueDependencyItem<T>; | ||
export interface AsyncDependencyItem<T> { | ||
useAsync: () => Promise<T | Ctor<T> | [DependencyIdentifier<T>, SyncDependencyItem<T>]>; | ||
} | ||
export declare function isAsyncDependencyItem<T>(thing: any): thing is AsyncDependencyItem<T>; | ||
export declare function isAsyncDependencyItem<T>(thing: unknown): thing is AsyncDependencyItem<T>; | ||
export interface AsyncHook<T> { | ||
whenReady(): Promise<T>; | ||
} | ||
export declare function isAsyncHook<T>(thing: any): thing is AsyncHook<T>; | ||
export declare function isAsyncHook<T>(thing: unknown): thing is AsyncHook<T>; | ||
export declare type SyncDependencyItem<T> = ClassDependencyItem<T> | FactoryDependencyItem<T> | ValueDependencyItem<T>; | ||
export declare type DependencyItem<T> = SyncDependencyItem<T> | AsyncDependencyItem<T>; |
export interface Disposable { | ||
dispose(): void; | ||
} | ||
export declare function isDisposable(thing: any): thing is Disposable; | ||
export declare function isDisposable(thing: unknown): thing is Disposable; |
@@ -76,2 +76,3 @@ /** | ||
} | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
return this.value; | ||
@@ -78,0 +79,0 @@ }; |
@@ -6,3 +6,3 @@ import { Dependency } from './dependencyCollection'; | ||
import { Quantity } from './dependencyQuantity'; | ||
export declare class DecoratorInjector { | ||
export declare class Injector { | ||
private readonly dependencyCollection; | ||
@@ -14,4 +14,4 @@ private readonly resolvedDependencyCollection; | ||
private disposed; | ||
constructor(collectionOrDependencies?: Dependency[], parent?: DecoratorInjector); | ||
createChild(dependencies?: Dependency[]): DecoratorInjector; | ||
constructor(collectionOrDependencies?: Dependency[], parent?: Injector); | ||
createChild(dependencies?: Dependency[]): Injector; | ||
dispose(): void; | ||
@@ -18,0 +18,0 @@ add<T>(ctor: Ctor<T>): void; |
@@ -27,6 +27,10 @@ var __extends = (this && this.__extends) || (function () { | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
@@ -65,4 +69,4 @@ import { getDependencies } from './decorators'; | ||
}(Error)); | ||
var DecoratorInjector = /** @class */ (function () { | ||
function DecoratorInjector(collectionOrDependencies, parent) { | ||
var Injector = /** @class */ (function () { | ||
function Injector(collectionOrDependencies, parent) { | ||
this.resolvedDependencyCollection = new ResolvedDependencyCollection(); | ||
@@ -83,7 +87,7 @@ this.children = []; | ||
} | ||
DecoratorInjector.prototype.createChild = function (dependencies) { | ||
Injector.prototype.createChild = function (dependencies) { | ||
this.ensureInjectorNotDisposed(); | ||
return new DecoratorInjector(dependencies, this); | ||
return new Injector(dependencies, this); | ||
}; | ||
DecoratorInjector.prototype.dispose = function () { | ||
Injector.prototype.dispose = function () { | ||
this.dependencyCollection.dispose(); | ||
@@ -93,3 +97,3 @@ this.resolvedDependencyCollection.dispose(); | ||
}; | ||
DecoratorInjector.prototype.add = function (idOrCtor, item) { | ||
Injector.prototype.add = function (idOrCtor, item) { | ||
if (typeof item !== 'undefined') { | ||
@@ -110,3 +114,3 @@ if (isAsyncDependencyItem(item) || | ||
}; | ||
DecoratorInjector.prototype.get = function (id, quantityOrLookup, lookUp) { | ||
Injector.prototype.get = function (id, quantityOrLookup, lookUp) { | ||
this.ensureInjectorNotDisposed(); | ||
@@ -139,3 +143,3 @@ var quantity = Quantity.REQUIRED; | ||
*/ | ||
DecoratorInjector.prototype.getAsync = function (id) { | ||
Injector.prototype.getAsync = function (id) { | ||
this.ensureInjectorNotDisposed(); | ||
@@ -155,3 +159,3 @@ var cachedResult = this.getValue(id, Quantity.REQUIRED); | ||
*/ | ||
DecoratorInjector.prototype.createInstance = function (ctor) { | ||
Injector.prototype.createInstance = function (ctor) { | ||
var customArgs = []; | ||
@@ -162,3 +166,3 @@ for (var _i = 1; _i < arguments.length; _i++) { | ||
this.ensureInjectorNotDisposed(); | ||
return this.resolveClass_.apply(this, __spreadArray([ctor], customArgs)); | ||
return this.resolveClass_.apply(this, __spreadArray([ctor], customArgs, false)); | ||
}; | ||
@@ -168,3 +172,3 @@ /** | ||
*/ | ||
DecoratorInjector.prototype.resolveDependency = function (id, item) { | ||
Injector.prototype.resolveDependency = function (id, item) { | ||
if (isInstanceDependencyItem(item)) { | ||
@@ -183,3 +187,3 @@ return this.resolveInstanceDependency(id, item); | ||
}; | ||
DecoratorInjector.prototype.resolveInstanceDependency = function (id, item) { | ||
Injector.prototype.resolveInstanceDependency = function (id, item) { | ||
var thing = item.useValue; | ||
@@ -189,3 +193,3 @@ this.resolvedDependencyCollection.add(id, thing); | ||
}; | ||
DecoratorInjector.prototype.resolveClass = function (id, item) { | ||
Injector.prototype.resolveClass = function (id, item) { | ||
var _this = this; | ||
@@ -229,3 +233,3 @@ var ctor = item.useClass; | ||
}; | ||
DecoratorInjector.prototype.resolveClass_ = function (ctor) { | ||
Injector.prototype.resolveClass_ = function (ctor) { | ||
var extraParams = []; | ||
@@ -245,3 +249,3 @@ for (var _i = 1; _i < arguments.length; _i++) { | ||
} | ||
var args = __spreadArray([], extraParams); | ||
var args = __spreadArray([], extraParams, true); | ||
var firstDependencyArgIndex = declaredDependencies.length > 0 | ||
@@ -254,3 +258,3 @@ ? declaredDependencies[0].paramIndex | ||
if (delta > 0) { | ||
args = __spreadArray(__spreadArray([], args), new Array(delta).fill(undefined)); | ||
args = __spreadArray(__spreadArray([], args, true), new Array(delta).fill(undefined), true); | ||
} | ||
@@ -261,7 +265,7 @@ else { | ||
} | ||
var thing = new (ctor.bind.apply(ctor, __spreadArray(__spreadArray([void 0], args), resolvedArgs)))(); | ||
var thing = new (ctor.bind.apply(ctor, __spreadArray(__spreadArray([void 0], args, false), resolvedArgs, false)))(); | ||
this.markResolutionCompleted(); | ||
return thing; | ||
}; | ||
DecoratorInjector.prototype.resolveFactory = function (id, item) { | ||
Injector.prototype.resolveFactory = function (id, item) { | ||
this.markNewResolution(); | ||
@@ -280,3 +284,3 @@ var declaredDependencies = normalizeFactoryDeps(item.deps); | ||
}; | ||
DecoratorInjector.prototype.resolveAsync = function (id, item) { | ||
Injector.prototype.resolveAsync = function (id, item) { | ||
var _this = this; | ||
@@ -288,3 +292,3 @@ var asyncLoader = { | ||
}; | ||
DecoratorInjector.prototype.resolveAsync_ = function (id, item) { | ||
Injector.prototype.resolveAsync_ = function (id, item) { | ||
var _this = this; | ||
@@ -321,3 +325,3 @@ return item.useAsync().then(function (thing) { | ||
*/ | ||
DecoratorInjector.prototype.getValue = function (id, quantity, lookUp) { | ||
Injector.prototype.getValue = function (id, quantity, lookUp) { | ||
var _this = this; | ||
@@ -355,3 +359,3 @@ if (quantity === void 0) { quantity = Quantity.REQUIRED; } | ||
*/ | ||
DecoratorInjector.prototype.createAndCacheDependency = function (id, quantity, lookUp) { | ||
Injector.prototype.createAndCacheDependency = function (id, quantity, lookUp) { | ||
var _this = this; | ||
@@ -386,3 +390,3 @@ if (quantity === void 0) { quantity = Quantity.REQUIRED; } | ||
} | ||
if (id === DecoratorInjector) { | ||
if (id === Injector) { | ||
return this; | ||
@@ -395,3 +399,3 @@ } | ||
}; | ||
DecoratorInjector.prototype.markNewResolution = function (id) { | ||
Injector.prototype.markNewResolution = function (id) { | ||
this.resolutionOngoing += 1; | ||
@@ -402,6 +406,6 @@ if (this.resolutionOngoing >= MAX_RESOLUTIONS_QUEUED) { | ||
}; | ||
DecoratorInjector.prototype.markResolutionCompleted = function () { | ||
Injector.prototype.markResolutionCompleted = function () { | ||
this.resolutionOngoing -= 1; | ||
}; | ||
DecoratorInjector.prototype.ensureInjectorNotDisposed = function () { | ||
Injector.prototype.ensureInjectorNotDisposed = function () { | ||
if (this.disposed) { | ||
@@ -411,5 +415,5 @@ throw new InjectorAlreadyDisposedError(); | ||
}; | ||
return DecoratorInjector; | ||
return Injector; | ||
}()); | ||
export { DecoratorInjector }; | ||
export { Injector }; | ||
//# sourceMappingURL=injector.js.map |
export { createIdentifier } from './decorators'; | ||
export { Many, Optional, Inject, Quantity } from './dependencyQuantity'; | ||
export { forwardRef } from './dependencyForwardRef'; | ||
export { DecoratorInjector as Injector } from './injector'; | ||
export { Injector } from './injector'; | ||
export { LookUp, SkipSelf, Self } from './dependencyLookUp'; | ||
@@ -6,0 +6,0 @@ export { DependencyPair, Dependency } from './dependencyCollection'; |
export { createIdentifier } from './decorators'; | ||
export { Many, Optional, Inject, Quantity } from './dependencyQuantity'; | ||
export { forwardRef } from './dependencyForwardRef'; | ||
export { DecoratorInjector as Injector } from './injector'; | ||
export { Injector } from './injector'; | ||
export { LookUp, SkipSelf, Self } from './dependencyLookUp'; | ||
export { registerSingleton } from './dependencySingletons'; | ||
//# sourceMappingURL=publicApi.js.map |
import * as React from 'react'; | ||
import { Injector, Dependency } from '@wendellhu/redi'; | ||
/** | ||
* @deprecated | ||
* @param Comp | ||
* @param injector | ||
* @returns | ||
*/ | ||
export declare function connectInjector<T>(Comp: React.ComponentType<T>, injector: Injector): React.ComponentType<T>; | ||
export declare function connectDependencies<T>(Comp: React.ComponentType<T>, dependencies: Dependency[]): React.ComponentType<T>; |
@@ -18,2 +18,4 @@ var __assign = (this && this.__assign) || function () { | ||
var childInjectorRef = React.useRef(null); | ||
// dispose the injector when the container Injector unmounts | ||
React.useEffect(function () { return function () { var _a; return (_a = childInjectorRef.current) === null || _a === void 0 ? void 0 : _a.dispose(); }; }, []); | ||
return (React.createElement(RediConsumer, null, function (context) { | ||
@@ -33,2 +35,8 @@ var childInjector; | ||
} | ||
/** | ||
* @deprecated | ||
* @param Comp | ||
* @param injector | ||
* @returns | ||
*/ | ||
export function connectInjector(Comp, injector) { | ||
@@ -35,0 +43,0 @@ return function ComponentWithInjector(props) { |
@@ -43,3 +43,3 @@ var __extends = (this && this.__extends) || (function () { | ||
export function WithDependency(id, quantity, lookUp) { | ||
return function (_target) { | ||
return function () { | ||
return { | ||
@@ -46,0 +46,0 @@ get: function () { |
@@ -50,3 +50,3 @@ import * as React from 'react'; | ||
function WithDependency(id, quantity, lookUp) { | ||
return function (_target) { | ||
return function () { | ||
return { | ||
@@ -80,2 +80,4 @@ get: function () { | ||
var childInjectorRef = React.useRef(null); | ||
// dispose the injector when the container Injector unmounts | ||
React.useEffect(function () { return function () { var _a; return (_a = childInjectorRef.current) === null || _a === void 0 ? void 0 : _a.dispose(); }; }, []); | ||
return (React.createElement(RediConsumer, null, function (context) { | ||
@@ -95,2 +97,8 @@ var childInjector; | ||
} | ||
/** | ||
* @deprecated | ||
* @param Comp | ||
* @param injector | ||
* @returns | ||
*/ | ||
function connectInjector(Comp, injector) { | ||
@@ -97,0 +105,0 @@ return function ComponentWithInjector(props) { |
107
fesm/redi.js
var IdentifierDecoratorSymbol = Symbol('$$IDENTIFIER_DECORATOR'); | ||
var __extends$5 = (undefined && undefined.__extends) || (function () { | ||
var __extends$4 = (undefined && undefined.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
@@ -25,3 +25,3 @@ extendStatics = Object.setPrototypeOf || | ||
var IdentifierUndefinedError = /** @class */ (function (_super) { | ||
__extends$5(IdentifierUndefinedError, _super); | ||
__extends$4(IdentifierUndefinedError, _super); | ||
function IdentifierUndefinedError(target, index) { | ||
@@ -36,3 +36,3 @@ var _this = this; | ||
var QuantityCheckError = /** @class */ (function (_super) { | ||
__extends$5(QuantityCheckError, _super); | ||
__extends$4(QuantityCheckError, _super); | ||
function QuantityCheckError(id, quantity, actual) { | ||
@@ -86,3 +86,3 @@ var _this = this; | ||
var __extends$4 = (undefined && undefined.__extends) || (function () { | ||
var __extends$3 = (undefined && undefined.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
@@ -105,3 +105,3 @@ extendStatics = Object.setPrototypeOf || | ||
var DependencyDescriptorNotFoundError = /** @class */ (function (_super) { | ||
__extends$4(DependencyDescriptorNotFoundError, _super); | ||
__extends$3(DependencyDescriptorNotFoundError, _super); | ||
function DependencyDescriptorNotFoundError(index, target) { | ||
@@ -201,3 +201,3 @@ var _this = this; | ||
var __extends$3 = (undefined && undefined.__extends) || (function () { | ||
var __extends$2 = (undefined && undefined.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
@@ -221,3 +221,3 @@ extendStatics = Object.setPrototypeOf || | ||
var DependencyNotFoundError = /** @class */ (function (_super) { | ||
__extends$3(DependencyNotFoundError, _super); | ||
__extends$2(DependencyNotFoundError, _super); | ||
function DependencyNotFoundError(id) { | ||
@@ -258,2 +258,3 @@ var _this = this; | ||
if (quantity === void 0) { quantity = Quantity.REQUIRED; } | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
var ret = this.dependencyMap.get(id); | ||
@@ -371,24 +372,3 @@ checkQuantity(id, quantity, ret.length); | ||
var __extends$2 = (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 NotValidDependencyModifierError = /** @class */ (function (_super) { | ||
__extends$2(NotValidDependencyModifierError, _super); | ||
function NotValidDependencyModifierError() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
return NotValidDependencyModifierError; | ||
}(Error)); | ||
// class NotValidDependencyModifierError extends Error {} | ||
function normalizeFactoryDeps(deps) { | ||
@@ -542,2 +522,3 @@ if (!deps) { | ||
} | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
return this.value; | ||
@@ -619,6 +600,10 @@ }; | ||
}; | ||
var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
@@ -648,4 +633,4 @@ var MAX_RESOLUTIONS_QUEUED = 300; | ||
}(Error)); | ||
var DecoratorInjector = /** @class */ (function () { | ||
function DecoratorInjector(collectionOrDependencies, parent) { | ||
var Injector = /** @class */ (function () { | ||
function Injector(collectionOrDependencies, parent) { | ||
this.resolvedDependencyCollection = new ResolvedDependencyCollection(); | ||
@@ -666,7 +651,7 @@ this.children = []; | ||
} | ||
DecoratorInjector.prototype.createChild = function (dependencies) { | ||
Injector.prototype.createChild = function (dependencies) { | ||
this.ensureInjectorNotDisposed(); | ||
return new DecoratorInjector(dependencies, this); | ||
return new Injector(dependencies, this); | ||
}; | ||
DecoratorInjector.prototype.dispose = function () { | ||
Injector.prototype.dispose = function () { | ||
this.dependencyCollection.dispose(); | ||
@@ -676,3 +661,3 @@ this.resolvedDependencyCollection.dispose(); | ||
}; | ||
DecoratorInjector.prototype.add = function (idOrCtor, item) { | ||
Injector.prototype.add = function (idOrCtor, item) { | ||
if (typeof item !== 'undefined') { | ||
@@ -693,3 +678,3 @@ if (isAsyncDependencyItem(item) || | ||
}; | ||
DecoratorInjector.prototype.get = function (id, quantityOrLookup, lookUp) { | ||
Injector.prototype.get = function (id, quantityOrLookup, lookUp) { | ||
this.ensureInjectorNotDisposed(); | ||
@@ -722,3 +707,3 @@ var quantity = Quantity.REQUIRED; | ||
*/ | ||
DecoratorInjector.prototype.getAsync = function (id) { | ||
Injector.prototype.getAsync = function (id) { | ||
this.ensureInjectorNotDisposed(); | ||
@@ -738,3 +723,3 @@ var cachedResult = this.getValue(id, Quantity.REQUIRED); | ||
*/ | ||
DecoratorInjector.prototype.createInstance = function (ctor) { | ||
Injector.prototype.createInstance = function (ctor) { | ||
var customArgs = []; | ||
@@ -745,3 +730,3 @@ for (var _i = 1; _i < arguments.length; _i++) { | ||
this.ensureInjectorNotDisposed(); | ||
return this.resolveClass_.apply(this, __spreadArray([ctor], customArgs)); | ||
return this.resolveClass_.apply(this, __spreadArray([ctor], customArgs, false)); | ||
}; | ||
@@ -751,3 +736,3 @@ /** | ||
*/ | ||
DecoratorInjector.prototype.resolveDependency = function (id, item) { | ||
Injector.prototype.resolveDependency = function (id, item) { | ||
if (isInstanceDependencyItem(item)) { | ||
@@ -766,3 +751,3 @@ return this.resolveInstanceDependency(id, item); | ||
}; | ||
DecoratorInjector.prototype.resolveInstanceDependency = function (id, item) { | ||
Injector.prototype.resolveInstanceDependency = function (id, item) { | ||
var thing = item.useValue; | ||
@@ -772,3 +757,3 @@ this.resolvedDependencyCollection.add(id, thing); | ||
}; | ||
DecoratorInjector.prototype.resolveClass = function (id, item) { | ||
Injector.prototype.resolveClass = function (id, item) { | ||
var _this = this; | ||
@@ -812,3 +797,3 @@ var ctor = item.useClass; | ||
}; | ||
DecoratorInjector.prototype.resolveClass_ = function (ctor) { | ||
Injector.prototype.resolveClass_ = function (ctor) { | ||
var extraParams = []; | ||
@@ -828,3 +813,3 @@ for (var _i = 1; _i < arguments.length; _i++) { | ||
} | ||
var args = __spreadArray([], extraParams); | ||
var args = __spreadArray([], extraParams, true); | ||
var firstDependencyArgIndex = declaredDependencies.length > 0 | ||
@@ -837,3 +822,3 @@ ? declaredDependencies[0].paramIndex | ||
if (delta > 0) { | ||
args = __spreadArray(__spreadArray([], args), new Array(delta).fill(undefined)); | ||
args = __spreadArray(__spreadArray([], args, true), new Array(delta).fill(undefined), true); | ||
} | ||
@@ -844,7 +829,7 @@ else { | ||
} | ||
var thing = new (ctor.bind.apply(ctor, __spreadArray(__spreadArray([void 0], args), resolvedArgs)))(); | ||
var thing = new (ctor.bind.apply(ctor, __spreadArray(__spreadArray([void 0], args, false), resolvedArgs, false)))(); | ||
this.markResolutionCompleted(); | ||
return thing; | ||
}; | ||
DecoratorInjector.prototype.resolveFactory = function (id, item) { | ||
Injector.prototype.resolveFactory = function (id, item) { | ||
this.markNewResolution(); | ||
@@ -863,3 +848,3 @@ var declaredDependencies = normalizeFactoryDeps(item.deps); | ||
}; | ||
DecoratorInjector.prototype.resolveAsync = function (id, item) { | ||
Injector.prototype.resolveAsync = function (id, item) { | ||
var _this = this; | ||
@@ -871,3 +856,3 @@ var asyncLoader = { | ||
}; | ||
DecoratorInjector.prototype.resolveAsync_ = function (id, item) { | ||
Injector.prototype.resolveAsync_ = function (id, item) { | ||
var _this = this; | ||
@@ -904,3 +889,3 @@ return item.useAsync().then(function (thing) { | ||
*/ | ||
DecoratorInjector.prototype.getValue = function (id, quantity, lookUp) { | ||
Injector.prototype.getValue = function (id, quantity, lookUp) { | ||
var _this = this; | ||
@@ -938,3 +923,3 @@ if (quantity === void 0) { quantity = Quantity.REQUIRED; } | ||
*/ | ||
DecoratorInjector.prototype.createAndCacheDependency = function (id, quantity, lookUp) { | ||
Injector.prototype.createAndCacheDependency = function (id, quantity, lookUp) { | ||
var _this = this; | ||
@@ -969,3 +954,3 @@ if (quantity === void 0) { quantity = Quantity.REQUIRED; } | ||
} | ||
if (id === DecoratorInjector) { | ||
if (id === Injector) { | ||
return this; | ||
@@ -978,3 +963,3 @@ } | ||
}; | ||
DecoratorInjector.prototype.markNewResolution = function (id) { | ||
Injector.prototype.markNewResolution = function (id) { | ||
this.resolutionOngoing += 1; | ||
@@ -985,6 +970,6 @@ if (this.resolutionOngoing >= MAX_RESOLUTIONS_QUEUED) { | ||
}; | ||
DecoratorInjector.prototype.markResolutionCompleted = function () { | ||
Injector.prototype.markResolutionCompleted = function () { | ||
this.resolutionOngoing -= 1; | ||
}; | ||
DecoratorInjector.prototype.ensureInjectorNotDisposed = function () { | ||
Injector.prototype.ensureInjectorNotDisposed = function () { | ||
if (this.disposed) { | ||
@@ -994,6 +979,6 @@ throw new InjectorAlreadyDisposedError(); | ||
}; | ||
return DecoratorInjector; | ||
return Injector; | ||
}()); | ||
export { Inject, DecoratorInjector as Injector, LookUp, Many, Optional, Quantity, Self, SkipSelf, createIdentifier, forwardRef, registerSingleton }; | ||
export { Inject, Injector, LookUp, Many, Optional, Quantity, Self, SkipSelf, createIdentifier, forwardRef, registerSingleton }; | ||
//# sourceMappingURL=redi.js.map |
{ | ||
"name": "@wendellhu/redi", | ||
"version": "0.1.5", | ||
"version": "0.1.6", | ||
"description": "A dependency library for TypeScript and JavaScript, along with a binding for React.", | ||
@@ -10,6 +10,6 @@ "author": "wendellhu95 <wendellhu95@gmail.com>", | ||
}, | ||
"main": "publish/dist/redi", | ||
"module": "./fesm/@wendellhu/redi.js", | ||
"main": "./dist/redi.js", | ||
"module": "./fesm/redi.js", | ||
"typings": "./esm/publicApi.d.ts", | ||
"sideEffects": false | ||
} |
433
README.md
# redi | ||
A dependency library for TypeScript and JavaScript, along with a binding for React. | ||
[Demo TodoMVC](https://wendellhu95.github.io/redi-todomvc/) | [Demo Repo](https://github.com/wendellhu95/redi-todomvc) | ||
[![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 | ||
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 { | ||
// your implementation here... | ||
} | ||
} | ||
+ import { Inject } from '@wendellhu/redi' | ||
class FileListService { | ||
- constructor() {} | ||
+ constructor(@Inject(AuthService) private readonly authService: AuthService) {} | ||
public getUserFiles(): Promise<Files> { | ||
- const currentUser = // ...AuthService.getCurrentUserInfo() | ||
+ const currentUser = this.authService.getCurrentUserInfo() | ||
// ... | ||
} | ||
} | ||
``` | ||
Then you need to include all things into an `Injector`. | ||
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. | ||
- Dependency 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 | ||
#### **`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
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
347057
437
62
3559