async-injection 2.2.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ReadMe.md +134 -194
- package/lib/async-factory-provider.d.ts +4 -4
- package/lib/bindable-provider.d.ts +4 -4
- package/lib/binding.d.ts +80 -0
- package/lib/cjs/async-factory-provider.js +5 -5
- package/lib/cjs/async-factory-provider.js.map +1 -1
- package/lib/cjs/bindable-provider.js +23 -36
- package/lib/cjs/bindable-provider.js.map +1 -1
- package/lib/cjs/{binder.js → binding.js} +1 -1
- package/lib/cjs/binding.js.map +1 -0
- package/lib/cjs/class-provider.js +168 -66
- package/lib/cjs/class-provider.js.map +1 -1
- package/lib/cjs/constant-provider.js +4 -4
- package/lib/cjs/constant-provider.js.map +1 -1
- package/lib/cjs/container.js +81 -45
- package/lib/cjs/container.js.map +1 -1
- package/lib/cjs/decorators.js +80 -40
- package/lib/cjs/decorators.js.map +1 -1
- package/lib/cjs/index.js +10 -10
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/injector.js +5 -5
- package/lib/cjs/injector.js.map +1 -1
- package/lib/cjs/provider.js +16 -11
- package/lib/cjs/provider.js.map +1 -1
- package/lib/cjs/state.js +2 -2
- package/lib/cjs/state.js.map +1 -1
- package/lib/cjs/sync-factory-provider.js +7 -7
- package/lib/cjs/sync-factory-provider.js.map +1 -1
- package/lib/cjs/utils.js +10 -13
- package/lib/cjs/utils.js.map +1 -1
- package/lib/class-provider.d.ts +20 -6
- package/lib/constant-provider.d.ts +2 -2
- package/lib/container.d.ts +45 -19
- package/lib/decorators.d.ts +16 -3
- package/lib/esm/async-factory-provider.js +1 -1
- package/lib/esm/async-factory-provider.js.map +1 -1
- package/lib/esm/bindable-provider.js +19 -32
- package/lib/esm/bindable-provider.js.map +1 -1
- package/lib/esm/binding.js +2 -0
- package/lib/esm/binding.js.map +1 -0
- package/lib/esm/class-provider.js +155 -53
- package/lib/esm/class-provider.js.map +1 -1
- package/lib/esm/constant-provider.js.map +1 -1
- package/lib/esm/container.js +63 -27
- package/lib/esm/container.js.map +1 -1
- package/lib/esm/decorators.js +61 -22
- package/lib/esm/decorators.js.map +1 -1
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/injector.js +5 -5
- package/lib/esm/injector.js.map +1 -1
- package/lib/esm/provider.js +14 -9
- package/lib/esm/provider.js.map +1 -1
- package/lib/esm/state.js.map +1 -1
- package/lib/esm/sync-factory-provider.js +1 -1
- package/lib/esm/sync-factory-provider.js.map +1 -1
- package/lib/esm/utils.js +6 -8
- package/lib/esm/utils.js.map +1 -1
- package/lib/index.d.ts +4 -3
- package/lib/injector.d.ts +1 -1
- package/lib/provider.d.ts +4 -4
- package/lib/state.d.ts +3 -3
- package/lib/sync-factory-provider.d.ts +5 -5
- package/package.json +7 -18
- package/lib/binder.d.ts +0 -106
- package/lib/cjs/binder.js.map +0 -1
- package/lib/esm/binder.js +0 -2
- package/lib/esm/binder.js.map +0 -1
package/lib/esm/provider.js
CHANGED
|
@@ -10,10 +10,10 @@ export class Provider {
|
|
|
10
10
|
* Base method to initialize the state of this Provider *if* (and only if) it has been configured as a Singleton.
|
|
11
11
|
* If this Provider has not been configured as a singleton, this method is essentially a noop that returns undefined.
|
|
12
12
|
*
|
|
13
|
-
* @param
|
|
13
|
+
* @param _asyncOnly This default implementation ignores this parameter.
|
|
14
14
|
* @returns A completion Promise if initialization requires asynchronicity, otherwise the return value is undefined.
|
|
15
15
|
*/
|
|
16
|
-
resolveIfSingleton(
|
|
16
|
+
resolveIfSingleton(_asyncOnly) {
|
|
17
17
|
if (this.singleton === null) {
|
|
18
18
|
const s = this.provideAsState();
|
|
19
19
|
if (s.pending)
|
|
@@ -38,13 +38,18 @@ export class Provider {
|
|
|
38
38
|
if (this.singleton) {
|
|
39
39
|
const s = this.provideAsState();
|
|
40
40
|
if (s.pending) {
|
|
41
|
-
return
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
return (async () => {
|
|
42
|
+
try {
|
|
43
|
+
const v = await s.promise;
|
|
44
|
+
this.singleton = null;
|
|
45
|
+
InvokeReleaseMethod(v);
|
|
46
|
+
return v;
|
|
47
|
+
}
|
|
48
|
+
catch (_a) {
|
|
49
|
+
this.singleton = null;
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
})();
|
|
48
53
|
}
|
|
49
54
|
else {
|
|
50
55
|
this.singleton = null;
|
package/lib/esm/provider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,mBAAmB,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,mBAAmB,EAAC,MAAM,SAAS,CAAC;AAG5C;;;GAGG;AACH,MAAM,OAAgB,QAAQ;IAC7B;IACA,CAAC;IAiBD;;;;;;OAMG;IACH,kBAAkB,CAAC,UAAmB;QACrC,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;YAChC,IAAI,CAAC,CAAC,OAAO;gBACZ,OAAO,CAAC,CAAC,OAAQ,CAAC;iBACd,IAAI,CAAC,CAAC,QAAQ;gBAClB,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;;;;;;;;;OAUG;IACH,kBAAkB;QACjB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;YAChC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,IAAI,EAAE;oBAClB,IAAI,CAAC;wBACJ,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,OAAQ,CAAC;wBAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;wBACtB,mBAAmB,CAAC,CAAC,CAAC,CAAC;wBACvB,OAAO,CAAC,CAAC;oBACV,CAAC;oBACD,WAAM,CAAC;wBACN,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;wBACtB,OAAO,IAAI,CAAC;oBACb,CAAC;gBACF,CAAC,CAAC,EAAE,CAAC;YACN,CAAC;iBACI,CAAC;gBACL,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;gBACtB,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;oBAClC,mBAAmB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;oBACjC,OAAO,CAAC,CAAC,SAAS,CAAC;gBACpB,CAAC;gBACD,OAAO,IAAI,CAAC;YACb,CAAC;QACF,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;CACD","sourcesContent":["import {State} from './state';\nimport {InvokeReleaseMethod} from './utils';\n\n\n/**\n * Internally all InjectableIds are mapped to an abstract Provider<T>.\n * A Provider may choose to return a singleton or a new value each time it is queried.\n */\nexport abstract class Provider<T = any> {\n\tprotected constructor() {\n\t}\n\n\t/**\n\t * If the provider is configured as a singleton, this property will be the state of that singleton.\n\t * This value will be defined for resolved/resolving Singletons, null for Singletons that have not yet been queried, and will remain undefined for non-Singleton Providers.\n\t * Default value is undefined (e.g. not a Singleton).\n\t */\n\tprotected singleton?: State<T> | null;\n\n\t/**\n\t * This is the workhorse method of the Provider, and is invoked directly or indirectly by both Injector.get and Injector.resolve.\n\t * This method returns the current State<T> if it is already known (which it might be for Singleton scenarios).\n\t * Otherwise it resolves the State<T>.\n\t * IF the Provider<T> is a Singleton, it's State<T> is updated before returning.\n\t */\n\tabstract provideAsState(): State<T>;\n\n\t/**\n\t * Base method to initialize the state of this Provider *if* (and only if) it has been configured as a Singleton.\n\t * If this Provider has not been configured as a singleton, this method is essentially a noop that returns undefined.\n\t *\n\t * @param _asyncOnly This default implementation ignores this parameter.\n\t * @returns A completion Promise if initialization requires asynchronicity, otherwise the return value is undefined.\n\t */\n\tresolveIfSingleton(_asyncOnly: boolean): Promise<T> | undefined {\n\t\tif (this.singleton === null) {\n\t\t\tconst s = this.provideAsState();\n\t\t\tif (s.pending)\n\t\t\t\treturn s.promise!;\n\t\t\telse if (s.rejected)\n\t\t\t\treturn Promise.reject(s.rejected);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * If (and only if) this Provider has been configured as a Singleton, and if it has been (or is being resolved), find and invoke the @Release decorated method (if there is one).\n\t * NOTE that if the singleton is actively being resolved when this method is called, this method waits for the resolution to complete and then invokes the @Release decorated method; But in any case this is a synchronous method and returns immediately to it's caller.\n\t * Also note that invoking this method does not release or invalidate the Provider;\n\t * Rather, it resets a Singleton Provider to a fresh (unresolved/unqueried) state (aka sets this.singleton to null).\n\t * It is assumed that the Singleton itself will no longer be used after this method returns.\n\t * If not a singleton, this method returns undefined.\n\t * If the singleton has been resolved, it is returned, otherwise null is returned.\n\t * If the singleton is pending resolution, a Promise for the singleton or for null is returned.\n\t * Note that if a singleton is returned, its Release method will already have been invoked.\n\t */\n\treleaseIfSingleton(): T | undefined | null | Promise<T | null> {\n\t\tif (this.singleton) {\n\t\t\tconst s = this.provideAsState();\n\t\t\tif (s.pending) {\n\t\t\t\treturn (async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst v = await s.promise!;\n\t\t\t\t\t\tthis.singleton = null;\n\t\t\t\t\t\tInvokeReleaseMethod(v);\n\t\t\t\t\t\treturn v;\n\t\t\t\t\t}\n\t\t\t\t\tcatch {\n\t\t\t\t\t\tthis.singleton = null;\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.singleton = null;\n\t\t\t\tif ((!s.rejected) && s.fulfilled) {\n\t\t\t\t\tInvokeReleaseMethod(s.fulfilled);\n\t\t\t\t\treturn s.fulfilled;\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n}\n"]}
|
package/lib/esm/state.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,SAAS,CAAC;AAElC;;GAEG;AACH,MAAM,OAAO,KAAK;IACjB,MAAM,CAAC,SAAS,CAAe,OAA+B,EAAE,QAAkB,EAAE,SAAkB;QACrG,MAAM,MAAM,GAAG,IAAI,KAAK,EAAU,CAAC;QACnC,IAAI,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC;YACvB,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAC7B,CAAC,CAAC,EAAE,EAAE;gBACL,MAAM,CAAC,UAAU,GAAG,CAAC,CAAC;gBACtB,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC;gBACxB,OAAO,CAAC,CAAC;YACV,CAAC,EACD,CAAC,CAAM,EAAE,EAAE;gBACV,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC;gBACrB,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC;gBACxB,MAAM,CAAC,CAAC;YACT,CAAC,CACD,CAAC;QACH,CAAC;aACI,CAAC;YACL,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC;YACxB,IAAI,QAAQ,EAAE,CAAC;gBACd,MAAM,CAAC,SAAS,GAAG,QAAQ,CAAC;YAC7B,CAAC;iBACI,CAAC;gBACL,MAAM,CAAC,UAAU,GAAG,SAAmB,CAAC;YACzC,CAAC;YACD,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC;QACxB,CAAC;QACD,OAAO,MAAM,CAAC;IACf,CAAC;IAED;IACA,CAAC;IAID,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAID,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAID,IAAI,SAAS;QACZ,OAAO,IAAI,CAAC,UAAU,CAAC;IACxB,CAAC;IAID,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;CACD","sourcesContent":["import {isPromise} from './utils';\n\n/**\n * Internal class that allows us to track the state of a promise (chain).\n */\nexport class State<T = any> {\n\tstatic MakeState<TState = any>(promise: Promise<TState> | null, rejected?: unknown, fulfilled?: TState): State<TState> {\n\t\tconst retVal = new State<TState>();\n\t\tif (isPromise(promise)) {\n\t\t\tretVal._pending = true;\n\t\t\tretVal._promise = promise.then(\n\t\t\t\t(v) => {\n\t\t\t\t\tretVal._fulfilled = v;\n\t\t\t\t\tretVal._pending = false;\n\t\t\t\t\treturn v;\n\t\t\t\t},\n\t\t\t\t(e: any) => {\n\t\t\t\t\tretVal._rejected = e;\n\t\t\t\t\tretVal._pending = false;\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t\telse {\n\t\t\tretVal._pending = false;\n\t\t\tif (rejected) {\n\t\t\t\tretVal._rejected = rejected;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tretVal._fulfilled = fulfilled as TState;\n\t\t\t}\n\t\t\tretVal._promise = null;\n\t\t}\n\t\treturn retVal;\n\t}\n\n\tprotected constructor() {\n\t}\n\n\tprotected _promise!: Promise<T> | null;\n\n\tget promise(): Promise<T> | null {\n\t\treturn this._promise;\n\t}\n\n\tprotected _pending!: boolean;\n\n\tget pending(): boolean {\n\t\treturn this._pending;\n\t}\n\n\tprotected _fulfilled!: T;\n\n\tget fulfilled(): T {\n\t\treturn this._fulfilled;\n\t}\n\n\tprotected _rejected: unknown;\n\n\tget rejected(): unknown {\n\t\treturn this._rejected;\n\t}\n}\n"]}
|
|
@@ -21,7 +21,7 @@ export class FactoryBasedProvider extends BindableProvider {
|
|
|
21
21
|
catch (err) {
|
|
22
22
|
// There was an error, give the errorHandler (if any) a crack at recovery.
|
|
23
23
|
try {
|
|
24
|
-
// queryErrorHandler will throw if it could not
|
|
24
|
+
// queryErrorHandler will throw if it could not get a substitute object.
|
|
25
25
|
retVal = State.MakeState(null, undefined, this.queryErrorHandler(err));
|
|
26
26
|
}
|
|
27
27
|
catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-factory-provider.js","sourceRoot":"","sources":["../../src/sync-factory-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"sync-factory-provider.js","sourceRoot":"","sources":["../../src/sync-factory-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAC;AAGrD,OAAO,EAAC,KAAK,EAAC,MAAM,SAAS,CAAC;AAE9B;;;GAGG;AACH,MAAM,OAAO,oBAAwB,SAAQ,gBAAmC;IAC/E,YAAY,QAAkB,EAAE,EAAmB,EAAE,KAAqB;QACzE,KAAK,CAAC,QAAQ,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED;;;OAGG;IACH,cAAc;QACb,IAAI,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;QAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,IAAI,CAAC;gBACJ,MAAM,GAAG,KAAK,CAAC,SAAS,CAAI,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YACzE,CAAC;YACD,OAAO,GAAG,EAAE,CAAC;gBACZ,0EAA0E;gBAC1E,IAAI,CAAC;oBACJ,wEAAwE;oBACxE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAI,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC3E,CAAC;gBACD,OAAO,CAAC,EAAE,CAAC;oBACV,0CAA0C;oBAC1C,MAAM,GAAG,KAAK,CAAC,SAAS,CAAI,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;gBACjD,CAAC;YACF,CAAC;QACF,CAAC;QACD,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI;YAC1B,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC;QACzB,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;;OAGG;IACH,kBAAkB,CAAC,SAAkB;QACpC,IAAI,SAAS;YACZ,OAAO,SAAS,CAAC;QAClB,OAAO,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;CACD","sourcesContent":["import {BindableProvider} from './bindable-provider';\nimport {SyncFactory} from './binding';\nimport {InjectableId, Injector} from './injector';\nimport {State} from './state';\n\n/**\n * @inheritDoc\n * This specialization simply invokes it's configured Factory and provides the result.\n */\nexport class FactoryBasedProvider<T> extends BindableProvider<T, SyncFactory<T>> {\n\tconstructor(injector: Injector, id: InjectableId<T>, maker: SyncFactory<T>) {\n\t\tsuper(injector, id, maker);\n\t}\n\n\t/**\n\t * @inheritDoc\n\t * This specialization invokes it's configured Factory and provides the result (or invokes the error handler if necessary).\n\t */\n\tprovideAsState(): State<T> {\n\t\tlet retVal = this.singleton;\n\t\tif (!retVal) {\n\t\t\ttry {\n\t\t\t\tretVal = State.MakeState<T>(null, undefined, this.maker(this.injector));\n\t\t\t}\n\t\t\tcatch (err) {\n\t\t\t\t// There was an error, give the errorHandler (if any) a crack at recovery.\n\t\t\t\ttry {\n\t\t\t\t\t// queryErrorHandler will throw if it could not get a substitute object.\n\t\t\t\t\tretVal = State.MakeState<T>(null, undefined, this.queryErrorHandler(err));\n\t\t\t\t}\n\t\t\t\tcatch (e) {\n\t\t\t\t\t// could not recover, propagate the error.\n\t\t\t\t\tretVal = State.MakeState<T>(null, e, undefined);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.singleton === null)\n\t\t\tthis.singleton = retVal;\n\t\treturn retVal;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t * This specialization returns undefined anytime 'asyncOnly' is true (since this Provider is by definition synchronous).\n\t */\n\tresolveIfSingleton(asyncOnly: boolean): Promise<T> | undefined {\n\t\tif (asyncOnly)\n\t\t\treturn undefined;\n\t\treturn super.resolveIfSingleton(false);\n\t}\n}\n"]}
|
package/lib/esm/utils.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/explicit-module-boundary-types */
|
|
2
1
|
import { RELEASE_METADATA_KEY } from './constants.js';
|
|
3
2
|
/**
|
|
4
3
|
* Returns true if the specified object looks like a JavaScript Error object.
|
|
@@ -8,7 +7,7 @@ export function isErrorObj(err) {
|
|
|
8
7
|
return false;
|
|
9
8
|
if (err instanceof Error)
|
|
10
9
|
return true;
|
|
11
|
-
return err && typeof err.message === 'string' && typeof err.stack === 'string';
|
|
10
|
+
return !!(err && typeof err.message === 'string' && typeof err.stack === 'string');
|
|
12
11
|
}
|
|
13
12
|
/**
|
|
14
13
|
* Returns true if the specified value is "thenable" (aka a Promise).
|
|
@@ -18,7 +17,7 @@ export function isPromise(value) {
|
|
|
18
17
|
return false;
|
|
19
18
|
if (value instanceof Promise)
|
|
20
19
|
return true;
|
|
21
|
-
return value && typeof value.then === 'function';
|
|
20
|
+
return !!(value && typeof value.then === 'function');
|
|
22
21
|
}
|
|
23
22
|
/**
|
|
24
23
|
* Simple helper function to find the @Release decorated method of an object (if any), and invoke it.
|
|
@@ -27,16 +26,15 @@ export function isPromise(value) {
|
|
|
27
26
|
*/
|
|
28
27
|
export function InvokeReleaseMethod(obj) {
|
|
29
28
|
var _a, _b;
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
if (releaseMethod &&
|
|
33
|
-
const releaseFn = (_b = (_a =
|
|
29
|
+
const o = obj;
|
|
30
|
+
const releaseMethod = Reflect.getMetadata(RELEASE_METADATA_KEY, o.constructor);
|
|
31
|
+
if (releaseMethod && o.constructor.prototype[releaseMethod] && typeof o.constructor.prototype[releaseMethod] === 'function') {
|
|
32
|
+
const releaseFn = (_b = (_a = o[releaseMethod]).bind) === null || _b === void 0 ? void 0 : _b.call(_a, o);
|
|
34
33
|
if (releaseFn) {
|
|
35
34
|
releaseFn();
|
|
36
35
|
return true;
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
|
-
/* eslint-enable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */
|
|
40
38
|
return false;
|
|
41
39
|
}
|
|
42
40
|
//# sourceMappingURL=utils.js.map
|
package/lib/esm/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,aAAa,CAAC;AAEjD;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,GAAQ;IAClC,IAAI,CAAC,GAAG;QACP,OAAO,KAAK,CAAC;IAEd,IAAI,GAAG,YAAY,KAAK;QACvB,OAAO,IAAI,CAAC;IAEb,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC;AACpF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAI,KAAU;IACtC,IAAI,CAAC,KAAK;QACT,OAAO,KAAK,CAAC;IAEd,IAAI,KAAK,YAAY,OAAO;QAC3B,OAAO,IAAI,CAAC;IAEb,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAc,GAAM;;IACtD,MAAM,CAAC,GAAG,GAAU,CAAC;IACrB,MAAM,aAAa,GAAW,OAAO,CAAC,WAAW,CAAC,oBAAoB,EAAE,CAAC,CAAC,WAAW,CAAW,CAAC;IACjG,IAAI,aAAa,IAAI,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,UAAU,EAAE,CAAC;QAC7H,MAAM,SAAS,GAAG,MAAA,MAAA,CAAC,CAAC,aAAa,CAAC,EAAC,IAAI,mDAAG,CAAC,CAAC,CAAC;QAC7C,IAAI,SAAS,EAAE,CAAC;YACf,SAAS,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC","sourcesContent":["import {RELEASE_METADATA_KEY} from './constants';\n\n/**\n * Returns true if the specified object looks like a JavaScript Error object.\n */\nexport function isErrorObj(err: any): err is Error {\n\tif (!err)\n\t\treturn false;\n\n\tif (err instanceof Error)\n\t\treturn true;\n\n\treturn !!(err && typeof err.message === 'string' && typeof err.stack === 'string');\n}\n\n/**\n * Returns true if the specified value is \"thenable\" (aka a Promise).\n */\nexport function isPromise<T>(value: any): value is Promise<T> {\n\tif (!value)\n\t\treturn false;\n\n\tif (value instanceof Promise)\n\t\treturn true;\n\n\treturn !!(value && typeof value.then === 'function');\n}\n\n/**\n * Simple helper function to find the @Release decorated method of an object (if any), and invoke it.\n * This is primarily an internal method as you probably know the exact method, and should invoke it yourself.\n * async-injection uses this helper to allow Singletons to clean up any non-garbage-collectable resources they may have allocated.\n */\nexport function InvokeReleaseMethod<T = unknown>(obj: T): boolean {\n\tconst o = obj as any;\n\tconst releaseMethod: string = Reflect.getMetadata(RELEASE_METADATA_KEY, o.constructor) as string;\n\tif (releaseMethod && o.constructor.prototype[releaseMethod] && typeof o.constructor.prototype[releaseMethod] === 'function') {\n\t\tconst releaseFn = o[releaseMethod].bind?.(o);\n\t\tif (releaseFn) {\n\t\t\treleaseFn();\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n"]}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export { Container } from './container
|
|
2
|
-
export { Inject, Injectable, Optional, PostConstruct, Release } from './decorators
|
|
3
|
-
export { ClassConstructor, InjectableId, InjectionToken, Injector } from './injector
|
|
1
|
+
export { Container } from './container';
|
|
2
|
+
export { Inject, Injectable, Optional, PostConstruct, Release } from './decorators';
|
|
3
|
+
export { ClassConstructor, InjectableId, InjectionToken, Injector } from './injector';
|
|
4
|
+
export { AsyncFactory, OnErrorCallback, OnSuccessCallback, RegisterDescriptor, SyncFactory } from './binding';
|
package/lib/injector.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export interface Injector {
|
|
|
31
31
|
/**
|
|
32
32
|
* Check to see if the existing InjectableId is known (aka has been bound).
|
|
33
33
|
* Error callbacks may wish to know if a particular InjectableId is available.
|
|
34
|
-
* Also the
|
|
34
|
+
* Also the Container's bindXXX calls always overwrite any previous bindings, so you may want to use this as a gate.
|
|
35
35
|
*
|
|
36
36
|
* @param id The id to check for.
|
|
37
37
|
* @param ascending If true, this will search up the chain of parent containers (if they exist). Default is false (only checks if the id is bound within this container).
|
package/lib/provider.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { State } from './state
|
|
1
|
+
import { State } from './state';
|
|
2
2
|
/**
|
|
3
3
|
* Internally all InjectableIds are mapped to an abstract Provider<T>.
|
|
4
4
|
* A Provider may choose to return a singleton or a new value each time it is queried.
|
|
@@ -10,7 +10,7 @@ export declare abstract class Provider<T = any> {
|
|
|
10
10
|
* This value will be defined for resolved/resolving Singletons, null for Singletons that have not yet been queried, and will remain undefined for non-Singleton Providers.
|
|
11
11
|
* Default value is undefined (e.g. not a Singleton).
|
|
12
12
|
*/
|
|
13
|
-
protected singleton?: State<T
|
|
13
|
+
protected singleton?: State<T> | null;
|
|
14
14
|
/**
|
|
15
15
|
* This is the workhorse method of the Provider, and is invoked directly or indirectly by both Injector.get and Injector.resolve.
|
|
16
16
|
* This method returns the current State<T> if it is already known (which it might be for Singleton scenarios).
|
|
@@ -22,10 +22,10 @@ export declare abstract class Provider<T = any> {
|
|
|
22
22
|
* Base method to initialize the state of this Provider *if* (and only if) it has been configured as a Singleton.
|
|
23
23
|
* If this Provider has not been configured as a singleton, this method is essentially a noop that returns undefined.
|
|
24
24
|
*
|
|
25
|
-
* @param
|
|
25
|
+
* @param _asyncOnly This default implementation ignores this parameter.
|
|
26
26
|
* @returns A completion Promise if initialization requires asynchronicity, otherwise the return value is undefined.
|
|
27
27
|
*/
|
|
28
|
-
resolveIfSingleton(
|
|
28
|
+
resolveIfSingleton(_asyncOnly: boolean): Promise<T> | undefined;
|
|
29
29
|
/**
|
|
30
30
|
* If (and only if) this Provider has been configured as a Singleton, and if it has been (or is being resolved), find and invoke the @Release decorated method (if there is one).
|
|
31
31
|
* NOTE that if the singleton is actively being resolved when this method is called, this method waits for the resolution to complete and then invokes the @Release decorated method; But in any case this is a synchronous method and returns immediately to it's caller.
|
package/lib/state.d.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* Internal class that allows us to track the state of a promise (chain).
|
|
3
3
|
*/
|
|
4
4
|
export declare class State<T = any> {
|
|
5
|
-
static MakeState<TState = any>(promise: Promise<TState
|
|
5
|
+
static MakeState<TState = any>(promise: Promise<TState> | null, rejected?: unknown, fulfilled?: TState): State<TState>;
|
|
6
6
|
protected constructor();
|
|
7
|
-
protected _promise: Promise<T
|
|
8
|
-
get promise(): Promise<T
|
|
7
|
+
protected _promise: Promise<T> | null;
|
|
8
|
+
get promise(): Promise<T> | null;
|
|
9
9
|
protected _pending: boolean;
|
|
10
10
|
get pending(): boolean;
|
|
11
11
|
protected _fulfilled: T;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { BindableProvider } from './bindable-provider
|
|
2
|
-
import { SyncFactory } from './
|
|
3
|
-
import { InjectableId, Injector } from './injector
|
|
4
|
-
import { State } from './state
|
|
1
|
+
import { BindableProvider } from './bindable-provider';
|
|
2
|
+
import { SyncFactory } from './binding';
|
|
3
|
+
import { InjectableId, Injector } from './injector';
|
|
4
|
+
import { State } from './state';
|
|
5
5
|
/**
|
|
6
6
|
* @inheritDoc
|
|
7
7
|
* This specialization simply invokes it's configured Factory and provides the result.
|
|
@@ -17,5 +17,5 @@ export declare class FactoryBasedProvider<T> extends BindableProvider<T, SyncFac
|
|
|
17
17
|
* @inheritDoc
|
|
18
18
|
* This specialization returns undefined anytime 'asyncOnly' is true (since this Provider is by definition synchronous).
|
|
19
19
|
*/
|
|
20
|
-
resolveIfSingleton(asyncOnly: boolean): Promise<T
|
|
20
|
+
resolveIfSingleton(asyncOnly: boolean): Promise<T> | undefined;
|
|
21
21
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "async-injection",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "A robust lightweight dependency injection library for TypeScript.",
|
|
5
5
|
"author": "Frank Stock",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,12 +43,10 @@
|
|
|
43
43
|
"scripts": {
|
|
44
44
|
"clean": "rimraf ./lib && rimraf ./.nyc_output && rimraf ./coverage",
|
|
45
45
|
"fullclean": "npm run clean && rimraf ./package-lock.json && rimraf ./node_modules",
|
|
46
|
-
"pretest": "npm run lint",
|
|
47
46
|
"test": "TS_NODE_PROJECT=./tsconfig-test.json node --require ts-node/register --require tsconfig-paths/register node_modules/jasmine/bin/jasmine.js --config=jasmine.json",
|
|
48
47
|
"coverage": "rimraf coverage && rimraf ./nyc_output && nyc -e .ts -x \"**/*.spec.ts\" -x \"tst/*\" --reporter=text-summary --reporter=lcov npm run test",
|
|
49
48
|
"build": "npm run clean && tsc -p tsconfig.base.json && tsc -p tsconfig.esm.json && tsc-esm-fix --target=lib/esm && tsc -p tsconfig.cjs.json && npm run _postbuild",
|
|
50
|
-
"_postbuild": "echo '{\"type\": \"module\"}' >lib/esm/package.json && echo '{\"type\": \"commonjs\"}' >lib/cjs/package.json"
|
|
51
|
-
"lint": "eslint 'src/**/*.ts'"
|
|
49
|
+
"_postbuild": "echo '{\"type\": \"module\"}' >lib/esm/package.json && echo '{\"type\": \"commonjs\"}' >lib/cjs/package.json"
|
|
52
50
|
},
|
|
53
51
|
"repository": {
|
|
54
52
|
"type": "git",
|
|
@@ -60,27 +58,18 @@
|
|
|
60
58
|
"devDependencies": {
|
|
61
59
|
"@istanbuljs/nyc-config-typescript": "~1.0.2",
|
|
62
60
|
"@types/jasmine": "~6.0.0",
|
|
63
|
-
"@types/node": "^
|
|
64
|
-
"
|
|
65
|
-
"@typescript-eslint/parser": "~5.62.0",
|
|
66
|
-
"eslint": "~8.57.1",
|
|
67
|
-
"eslint-plugin-import": "~2.32.0",
|
|
68
|
-
"eslint-plugin-jsdoc": "~39.9.1",
|
|
69
|
-
"eslint-plugin-prefer-arrow": "~1.2.3",
|
|
70
|
-
"jasmine": "~6.0.0",
|
|
61
|
+
"@types/node": "^20.19.37",
|
|
62
|
+
"jasmine": "~6.1.0",
|
|
71
63
|
"jasmine-console-reporter": "~3.1.0",
|
|
72
|
-
"nyc": "~
|
|
64
|
+
"nyc": "~18.0.0",
|
|
73
65
|
"reflect-metadata": "~0.2.2",
|
|
74
|
-
"rimraf": "~
|
|
66
|
+
"rimraf": "~6.1.3",
|
|
75
67
|
"source-map-support": "~0.5.21",
|
|
76
68
|
"ts-node": "~10.9.2",
|
|
77
69
|
"tsc-esm-fix": "~3.1.2",
|
|
78
70
|
"tsconfig-paths": "~4.2.0",
|
|
79
71
|
"tslib": "~2.8.1",
|
|
80
|
-
"typescript": "~
|
|
81
|
-
},
|
|
82
|
-
"overrides": {
|
|
83
|
-
"diff": "^8.0.3"
|
|
72
|
+
"typescript": "~5.9.3"
|
|
84
73
|
},
|
|
85
74
|
"nyc": {
|
|
86
75
|
"extends": "@istanbuljs/nyc-config-typescript",
|
package/lib/binder.d.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { AbstractConstructor, ClassConstructor, InjectableId, Injector } from './injector.js';
|
|
2
|
-
/**
|
|
3
|
-
* Type definition for functions that return a value.
|
|
4
|
-
* The function should return a valid value, but may throw an exception if it cannot.
|
|
5
|
-
*/
|
|
6
|
-
export type SyncFactory<T> = (injector: Injector) => T;
|
|
7
|
-
/**
|
|
8
|
-
* Type definition for functions that return a Promise for a value.
|
|
9
|
-
* The function *must* not throw and must return a valid Promise (e.g. pending, resolved, rejected).
|
|
10
|
-
*/
|
|
11
|
-
export type AsyncFactory<T> = (injector: Injector) => Promise<T>;
|
|
12
|
-
/**
|
|
13
|
-
* You may bind an error handler which will be invoked, if the bound InjectableId could not be put into service.
|
|
14
|
-
* An error handler *must* not throw, but may return an Error that will be propagated back up the call chain.
|
|
15
|
-
*
|
|
16
|
-
* @param binder The Binder that experienced the error.
|
|
17
|
-
* @param id The identifier for what was trying to be made.
|
|
18
|
-
* @param maker The thing that made (or tried to provideAsState). Will be one of type ClassConstructor, SyncFactory, or AsyncFactory, depending on how you registered the binding.
|
|
19
|
-
* @param error Identifies the problem that occurred.
|
|
20
|
-
* @param value If the 'maker' was able to create the thing, but it had an error during post construction, the made thing will be passed here.
|
|
21
|
-
* @returns one of 3 results...
|
|
22
|
-
* A substitute thing (kind of like a 'maker' do-over) which must be fully operational (e.g. any `@PostConstruct` will be ignored).
|
|
23
|
-
* An alternate Error which will be propagated back up the call chain.
|
|
24
|
-
* Undefined, which means the 'error' parameter will be propagated back up the call chain.
|
|
25
|
-
*/
|
|
26
|
-
export type OnErrorCallback<T, M> = (injector: Injector, id: InjectableId<T>, maker: M, error: unknown, value?: T) => T | Error | void;
|
|
27
|
-
/**
|
|
28
|
-
* You may bind a success handler which will be invoked just before the bound InjectableId is put into service.
|
|
29
|
-
* This is an alternative to the more preferred `@PostConstruct` decorator for scenarios when usage of that decorator is not feasible.
|
|
30
|
-
* WARNING:
|
|
31
|
-
* By registering a success handler, you override and nullify any `@PostConstruct` decorator on the class.
|
|
32
|
-
* In such a scenario, the success handler should perform whatever care and feeding the class expected from the `@PostConstruct` decorator.
|
|
33
|
-
* A success handler *must* not throw, but may return an Error that will be propagated back up the call chain.
|
|
34
|
-
*
|
|
35
|
-
* @param binder The Binder that performed the construction.
|
|
36
|
-
* @param id The identifier for what was made.
|
|
37
|
-
* @param maker The thing that made. Will be one of type ClassConstructor, SyncFactory, or AsyncFactory, depending on how you registered the binding.
|
|
38
|
-
* @param value The thing that was made.
|
|
39
|
-
* @returns one of 3 results...
|
|
40
|
-
* An Error which will be propagated back up the call chain.
|
|
41
|
-
* Undefined, which means the object is ready to be placed into service.
|
|
42
|
-
* A Promise that resolves to one of the above two values (undefined or Error).
|
|
43
|
-
*/
|
|
44
|
-
export type OnSuccessCallback<T, M> = (value: T, injector: Injector, id: InjectableId<T>, maker: M) => Promise<Error | void> | Error | void;
|
|
45
|
-
/**
|
|
46
|
-
* An interface allowing binding of an error handler.
|
|
47
|
-
*
|
|
48
|
-
* @see OnErrorCallback
|
|
49
|
-
*/
|
|
50
|
-
export interface BindErrHandler<T, M> {
|
|
51
|
-
onError(cb: OnErrorCallback<T, M>): void;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* An interface allowing binding of a post construction handler.
|
|
55
|
-
*
|
|
56
|
-
* @see OnSuccessCallback
|
|
57
|
-
*/
|
|
58
|
-
export interface BindHandler<T, M> extends BindErrHandler<T, M> {
|
|
59
|
-
onSuccess(cb: OnSuccessCallback<T, M>): BindErrHandler<T, M>;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* @inheritDoc
|
|
63
|
-
* This specialization also allows you to specify that the binding is 'Singleton' (e.g. only one in the system).
|
|
64
|
-
*/
|
|
65
|
-
export interface BindAs<T, M> extends BindHandler<T, M> {
|
|
66
|
-
asSingleton(): BindHandler<T, M>;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Bind Ids to producers.
|
|
70
|
-
*/
|
|
71
|
-
export interface Binder extends Injector {
|
|
72
|
-
/**
|
|
73
|
-
* Bind an InjectableId to a constant value.
|
|
74
|
-
* Constants are by their very nature singleton, and are assumed to be error proof.
|
|
75
|
-
*/
|
|
76
|
-
bindConstant<T>(id: InjectableId<T>, value: T): T;
|
|
77
|
-
/**
|
|
78
|
-
* Bind an InjectableId to a class (actually it's constructor).
|
|
79
|
-
* As a shortcut, you may use the class constructor as the 'id' (e.g. container.bindClass(A); ).
|
|
80
|
-
* The container will also invoke any `@PostConstruct` present on the class.
|
|
81
|
-
*/
|
|
82
|
-
bindClass<T>(id: ClassConstructor<T>, constructor?: ClassConstructor<T>): BindAs<T, ClassConstructor<T>>;
|
|
83
|
-
bindClass<T>(id: string | symbol | AbstractConstructor<T> | InjectableId<T>, constructor: ClassConstructor<T>): BindAs<T, ClassConstructor<T>>;
|
|
84
|
-
/**
|
|
85
|
-
* Bind an InjectableId to a synchronous factory that will be invoked on demand when the object is needed.
|
|
86
|
-
* The factory should produce the needed value
|
|
87
|
-
* NOTE: The container will not invoke any `@PostConstruct` present on the class, this is the responsibility of the factory.
|
|
88
|
-
*/
|
|
89
|
-
bindFactory<T>(id: InjectableId<T>, factory: SyncFactory<T>): BindAs<T, SyncFactory<T>>;
|
|
90
|
-
/**
|
|
91
|
-
* Bind an InjectableId to an asynchronous factory that will be invoked on demand when the object is needed.
|
|
92
|
-
* The factory should produce the needed value (asynchronously of course).
|
|
93
|
-
* NOTE: The container will not invoke any `@PostConstruct` present on the class, this is the responsibility of the factory.
|
|
94
|
-
* WARNING!!! The factory may not throw and must return a valid Promise (which can be pending, resolved, rejected, etc.).
|
|
95
|
-
*/
|
|
96
|
-
bindAsyncFactory<T>(id: InjectableId<T>, factory: AsyncFactory<T>): BindAs<T, AsyncFactory<T>>;
|
|
97
|
-
/**
|
|
98
|
-
* This essentially pre creates/loads all *singleton* InjectableIds currently known to the Binder.
|
|
99
|
-
* This *may* be helpful if you wish to use Injector.get on a dependency tree that has asynchronous singletons within the tree.
|
|
100
|
-
*
|
|
101
|
-
* @param asyncOnly Only resolve AsyncFactorys as well as any bound classes that have an asynchronous `@PostConstruct` decorator. WARNING: If true, SyncFactorys will *not* be resolved even if they are Singletons.
|
|
102
|
-
* @param parentRecursion If true and the the container has a parent, resolveIfSingleton will first be called for the parent
|
|
103
|
-
* @returns A Promise that resolves when all Singleton's have been resolved, OR rejects if one or more of the Singleton's failed to resolve. NOTE: Rejection does not occur until all Singleton resolutions have settled, and the rejection reason/err will be a Map<InjectableId, Error>
|
|
104
|
-
*/
|
|
105
|
-
resolveSingletons(asyncOnly?: boolean, parentRecursion?: boolean): Promise<this>;
|
|
106
|
-
}
|
package/lib/cjs/binder.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"binder.js","sourceRoot":"","sources":["../../src/binder.ts"],"names":[],"mappings":"","sourcesContent":["import {AbstractConstructor, ClassConstructor, InjectableId, Injector} from './injector.js';\n\n/**\n * Type definition for functions that return a value.\n * The function should return a valid value, but may throw an exception if it cannot.\n */\nexport type SyncFactory<T> = (injector: Injector) => T;\n\n/**\n * Type definition for functions that return a Promise for a value.\n * The function *must* not throw and must return a valid Promise (e.g. pending, resolved, rejected).\n */\nexport type AsyncFactory<T> = (injector: Injector) => Promise<T>;\n\n/**\n * You may bind an error handler which will be invoked, if the bound InjectableId could not be put into service.\n * An error handler *must* not throw, but may return an Error that will be propagated back up the call chain.\n *\n * @param binder The Binder that experienced the error.\n * @param id The identifier for what was trying to be made.\n * @param maker The thing that made (or tried to provideAsState). Will be one of type ClassConstructor, SyncFactory, or AsyncFactory, depending on how you registered the binding.\n * @param error Identifies the problem that occurred.\n * @param value If the 'maker' was able to create the thing, but it had an error during post construction, the made thing will be passed here.\n * @returns one of 3 results...\n * A substitute thing (kind of like a 'maker' do-over) which must be fully operational (e.g. any `@PostConstruct` will be ignored).\n * An alternate Error which will be propagated back up the call chain.\n * Undefined, which means the 'error' parameter will be propagated back up the call chain.\n */\nexport type OnErrorCallback<T, M> = (injector: Injector, id: InjectableId<T>, maker: M, error: unknown, value?: T) => T | Error | void;\n\n/**\n * You may bind a success handler which will be invoked just before the bound InjectableId is put into service.\n * This is an alternative to the more preferred `@PostConstruct` decorator for scenarios when usage of that decorator is not feasible.\n * WARNING:\n * By registering a success handler, you override and nullify any `@PostConstruct` decorator on the class.\n * In such a scenario, the success handler should perform whatever care and feeding the class expected from the `@PostConstruct` decorator.\n * A success handler *must* not throw, but may return an Error that will be propagated back up the call chain.\n *\n * @param binder The Binder that performed the construction.\n * @param id The identifier for what was made.\n * @param maker The thing that made. Will be one of type ClassConstructor, SyncFactory, or AsyncFactory, depending on how you registered the binding.\n * @param value The thing that was made.\n * @returns one of 3 results...\n * An Error which will be propagated back up the call chain.\n * Undefined, which means the object is ready to be placed into service.\n * A Promise that resolves to one of the above two values (undefined or Error).\n */\nexport type OnSuccessCallback<T, M> = (value: T, injector: Injector, id: InjectableId<T>, maker: M) => Promise<Error | void> | Error | void;\n\n/**\n * An interface allowing binding of an error handler.\n *\n * @see OnErrorCallback\n */\nexport interface BindErrHandler<T, M> {\n\tonError(cb: OnErrorCallback<T, M>): void;\n}\n\n/**\n * An interface allowing binding of a post construction handler.\n *\n * @see OnSuccessCallback\n */\nexport interface BindHandler<T, M> extends BindErrHandler<T, M> {\n\tonSuccess(cb: OnSuccessCallback<T, M>): BindErrHandler<T, M>;\n}\n\n/**\n * @inheritDoc\n * This specialization also allows you to specify that the binding is 'Singleton' (e.g. only one in the system).\n */\nexport interface BindAs<T, M> extends BindHandler<T, M> {\n\tasSingleton(): BindHandler<T, M>;\n}\n\n/**\n * Bind Ids to producers.\n */\nexport interface Binder extends Injector {\n\n\t/**\n\t * Bind an InjectableId to a constant value.\n\t * Constants are by their very nature singleton, and are assumed to be error proof.\n\t */\n\tbindConstant<T>(id: InjectableId<T>, value: T): T;\n\n\t/**\n\t * Bind an InjectableId to a class (actually it's constructor).\n\t * As a shortcut, you may use the class constructor as the 'id' (e.g. container.bindClass(A); ).\n\t * The container will also invoke any `@PostConstruct` present on the class.\n\t */\n\tbindClass<T>(id: ClassConstructor<T>, constructor?: ClassConstructor<T>): BindAs<T, ClassConstructor<T>>;\n\n\tbindClass<T>(id: string | symbol | AbstractConstructor<T> | InjectableId<T>, constructor: ClassConstructor<T>): BindAs<T, ClassConstructor<T>>;\n\n\t/**\n\t * Bind an InjectableId to a synchronous factory that will be invoked on demand when the object is needed.\n\t * The factory should produce the needed value\n\t * NOTE: The container will not invoke any `@PostConstruct` present on the class, this is the responsibility of the factory.\n\t */\n\tbindFactory<T>(id: InjectableId<T>, factory: SyncFactory<T>): BindAs<T, SyncFactory<T>>;\n\n\t/**\n\t * Bind an InjectableId to an asynchronous factory that will be invoked on demand when the object is needed.\n\t * The factory should produce the needed value (asynchronously of course).\n\t * NOTE: The container will not invoke any `@PostConstruct` present on the class, this is the responsibility of the factory.\n\t * WARNING!!! The factory may not throw and must return a valid Promise (which can be pending, resolved, rejected, etc.).\n\t */\n\tbindAsyncFactory<T>(id: InjectableId<T>, factory: AsyncFactory<T>): BindAs<T, AsyncFactory<T>>;\n\n\t/**\n\t * This essentially pre creates/loads all *singleton* InjectableIds currently known to the Binder.\n\t * This *may* be helpful if you wish to use Injector.get on a dependency tree that has asynchronous singletons within the tree.\n\t *\n\t * @param asyncOnly Only resolve AsyncFactorys as well as any bound classes that have an asynchronous `@PostConstruct` decorator. WARNING: If true, SyncFactorys will *not* be resolved even if they are Singletons.\n\t * @param parentRecursion If true and the the container has a parent, resolveIfSingleton will first be called for the parent\n\t * @returns A Promise that resolves when all Singleton's have been resolved, OR rejects if one or more of the Singleton's failed to resolve. NOTE: Rejection does not occur until all Singleton resolutions have settled, and the rejection reason/err will be a Map<InjectableId, Error>\n\t */\n\tresolveSingletons(asyncOnly?: boolean, parentRecursion?: boolean): Promise<this>;\n}\n"]}
|
package/lib/esm/binder.js
DELETED
package/lib/esm/binder.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"binder.js","sourceRoot":"","sources":["../../src/binder.ts"],"names":[],"mappings":"","sourcesContent":["import {AbstractConstructor, ClassConstructor, InjectableId, Injector} from './injector.js';\n\n/**\n * Type definition for functions that return a value.\n * The function should return a valid value, but may throw an exception if it cannot.\n */\nexport type SyncFactory<T> = (injector: Injector) => T;\n\n/**\n * Type definition for functions that return a Promise for a value.\n * The function *must* not throw and must return a valid Promise (e.g. pending, resolved, rejected).\n */\nexport type AsyncFactory<T> = (injector: Injector) => Promise<T>;\n\n/**\n * You may bind an error handler which will be invoked, if the bound InjectableId could not be put into service.\n * An error handler *must* not throw, but may return an Error that will be propagated back up the call chain.\n *\n * @param binder The Binder that experienced the error.\n * @param id The identifier for what was trying to be made.\n * @param maker The thing that made (or tried to provideAsState). Will be one of type ClassConstructor, SyncFactory, or AsyncFactory, depending on how you registered the binding.\n * @param error Identifies the problem that occurred.\n * @param value If the 'maker' was able to create the thing, but it had an error during post construction, the made thing will be passed here.\n * @returns one of 3 results...\n * A substitute thing (kind of like a 'maker' do-over) which must be fully operational (e.g. any `@PostConstruct` will be ignored).\n * An alternate Error which will be propagated back up the call chain.\n * Undefined, which means the 'error' parameter will be propagated back up the call chain.\n */\nexport type OnErrorCallback<T, M> = (injector: Injector, id: InjectableId<T>, maker: M, error: unknown, value?: T) => T | Error | void;\n\n/**\n * You may bind a success handler which will be invoked just before the bound InjectableId is put into service.\n * This is an alternative to the more preferred `@PostConstruct` decorator for scenarios when usage of that decorator is not feasible.\n * WARNING:\n * By registering a success handler, you override and nullify any `@PostConstruct` decorator on the class.\n * In such a scenario, the success handler should perform whatever care and feeding the class expected from the `@PostConstruct` decorator.\n * A success handler *must* not throw, but may return an Error that will be propagated back up the call chain.\n *\n * @param binder The Binder that performed the construction.\n * @param id The identifier for what was made.\n * @param maker The thing that made. Will be one of type ClassConstructor, SyncFactory, or AsyncFactory, depending on how you registered the binding.\n * @param value The thing that was made.\n * @returns one of 3 results...\n * An Error which will be propagated back up the call chain.\n * Undefined, which means the object is ready to be placed into service.\n * A Promise that resolves to one of the above two values (undefined or Error).\n */\nexport type OnSuccessCallback<T, M> = (value: T, injector: Injector, id: InjectableId<T>, maker: M) => Promise<Error | void> | Error | void;\n\n/**\n * An interface allowing binding of an error handler.\n *\n * @see OnErrorCallback\n */\nexport interface BindErrHandler<T, M> {\n\tonError(cb: OnErrorCallback<T, M>): void;\n}\n\n/**\n * An interface allowing binding of a post construction handler.\n *\n * @see OnSuccessCallback\n */\nexport interface BindHandler<T, M> extends BindErrHandler<T, M> {\n\tonSuccess(cb: OnSuccessCallback<T, M>): BindErrHandler<T, M>;\n}\n\n/**\n * @inheritDoc\n * This specialization also allows you to specify that the binding is 'Singleton' (e.g. only one in the system).\n */\nexport interface BindAs<T, M> extends BindHandler<T, M> {\n\tasSingleton(): BindHandler<T, M>;\n}\n\n/**\n * Bind Ids to producers.\n */\nexport interface Binder extends Injector {\n\n\t/**\n\t * Bind an InjectableId to a constant value.\n\t * Constants are by their very nature singleton, and are assumed to be error proof.\n\t */\n\tbindConstant<T>(id: InjectableId<T>, value: T): T;\n\n\t/**\n\t * Bind an InjectableId to a class (actually it's constructor).\n\t * As a shortcut, you may use the class constructor as the 'id' (e.g. container.bindClass(A); ).\n\t * The container will also invoke any `@PostConstruct` present on the class.\n\t */\n\tbindClass<T>(id: ClassConstructor<T>, constructor?: ClassConstructor<T>): BindAs<T, ClassConstructor<T>>;\n\n\tbindClass<T>(id: string | symbol | AbstractConstructor<T> | InjectableId<T>, constructor: ClassConstructor<T>): BindAs<T, ClassConstructor<T>>;\n\n\t/**\n\t * Bind an InjectableId to a synchronous factory that will be invoked on demand when the object is needed.\n\t * The factory should produce the needed value\n\t * NOTE: The container will not invoke any `@PostConstruct` present on the class, this is the responsibility of the factory.\n\t */\n\tbindFactory<T>(id: InjectableId<T>, factory: SyncFactory<T>): BindAs<T, SyncFactory<T>>;\n\n\t/**\n\t * Bind an InjectableId to an asynchronous factory that will be invoked on demand when the object is needed.\n\t * The factory should produce the needed value (asynchronously of course).\n\t * NOTE: The container will not invoke any `@PostConstruct` present on the class, this is the responsibility of the factory.\n\t * WARNING!!! The factory may not throw and must return a valid Promise (which can be pending, resolved, rejected, etc.).\n\t */\n\tbindAsyncFactory<T>(id: InjectableId<T>, factory: AsyncFactory<T>): BindAs<T, AsyncFactory<T>>;\n\n\t/**\n\t * This essentially pre creates/loads all *singleton* InjectableIds currently known to the Binder.\n\t * This *may* be helpful if you wish to use Injector.get on a dependency tree that has asynchronous singletons within the tree.\n\t *\n\t * @param asyncOnly Only resolve AsyncFactorys as well as any bound classes that have an asynchronous `@PostConstruct` decorator. WARNING: If true, SyncFactorys will *not* be resolved even if they are Singletons.\n\t * @param parentRecursion If true and the the container has a parent, resolveIfSingleton will first be called for the parent\n\t * @returns A Promise that resolves when all Singleton's have been resolved, OR rejects if one or more of the Singleton's failed to resolve. NOTE: Rejection does not occur until all Singleton resolutions have settled, and the rejection reason/err will be a Map<InjectableId, Error>\n\t */\n\tresolveSingletons(asyncOnly?: boolean, parentRecursion?: boolean): Promise<this>;\n}\n"]}
|