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.
Files changed (67) hide show
  1. package/ReadMe.md +134 -194
  2. package/lib/async-factory-provider.d.ts +4 -4
  3. package/lib/bindable-provider.d.ts +4 -4
  4. package/lib/binding.d.ts +80 -0
  5. package/lib/cjs/async-factory-provider.js +5 -5
  6. package/lib/cjs/async-factory-provider.js.map +1 -1
  7. package/lib/cjs/bindable-provider.js +23 -36
  8. package/lib/cjs/bindable-provider.js.map +1 -1
  9. package/lib/cjs/{binder.js → binding.js} +1 -1
  10. package/lib/cjs/binding.js.map +1 -0
  11. package/lib/cjs/class-provider.js +168 -66
  12. package/lib/cjs/class-provider.js.map +1 -1
  13. package/lib/cjs/constant-provider.js +4 -4
  14. package/lib/cjs/constant-provider.js.map +1 -1
  15. package/lib/cjs/container.js +81 -45
  16. package/lib/cjs/container.js.map +1 -1
  17. package/lib/cjs/decorators.js +80 -40
  18. package/lib/cjs/decorators.js.map +1 -1
  19. package/lib/cjs/index.js +10 -10
  20. package/lib/cjs/index.js.map +1 -1
  21. package/lib/cjs/injector.js +5 -5
  22. package/lib/cjs/injector.js.map +1 -1
  23. package/lib/cjs/provider.js +16 -11
  24. package/lib/cjs/provider.js.map +1 -1
  25. package/lib/cjs/state.js +2 -2
  26. package/lib/cjs/state.js.map +1 -1
  27. package/lib/cjs/sync-factory-provider.js +7 -7
  28. package/lib/cjs/sync-factory-provider.js.map +1 -1
  29. package/lib/cjs/utils.js +10 -13
  30. package/lib/cjs/utils.js.map +1 -1
  31. package/lib/class-provider.d.ts +20 -6
  32. package/lib/constant-provider.d.ts +2 -2
  33. package/lib/container.d.ts +45 -19
  34. package/lib/decorators.d.ts +16 -3
  35. package/lib/esm/async-factory-provider.js +1 -1
  36. package/lib/esm/async-factory-provider.js.map +1 -1
  37. package/lib/esm/bindable-provider.js +19 -32
  38. package/lib/esm/bindable-provider.js.map +1 -1
  39. package/lib/esm/binding.js +2 -0
  40. package/lib/esm/binding.js.map +1 -0
  41. package/lib/esm/class-provider.js +155 -53
  42. package/lib/esm/class-provider.js.map +1 -1
  43. package/lib/esm/constant-provider.js.map +1 -1
  44. package/lib/esm/container.js +63 -27
  45. package/lib/esm/container.js.map +1 -1
  46. package/lib/esm/decorators.js +61 -22
  47. package/lib/esm/decorators.js.map +1 -1
  48. package/lib/esm/index.js.map +1 -1
  49. package/lib/esm/injector.js +5 -5
  50. package/lib/esm/injector.js.map +1 -1
  51. package/lib/esm/provider.js +14 -9
  52. package/lib/esm/provider.js.map +1 -1
  53. package/lib/esm/state.js.map +1 -1
  54. package/lib/esm/sync-factory-provider.js +1 -1
  55. package/lib/esm/sync-factory-provider.js.map +1 -1
  56. package/lib/esm/utils.js +6 -8
  57. package/lib/esm/utils.js.map +1 -1
  58. package/lib/index.d.ts +4 -3
  59. package/lib/injector.d.ts +1 -1
  60. package/lib/provider.d.ts +4 -4
  61. package/lib/state.d.ts +3 -3
  62. package/lib/sync-factory-provider.d.ts +5 -5
  63. package/package.json +7 -18
  64. package/lib/binder.d.ts +0 -106
  65. package/lib/cjs/binder.js.map +0 -1
  66. package/lib/esm/binder.js +0 -2
  67. package/lib/esm/binder.js.map +0 -1
@@ -1,12 +1,13 @@
1
- import { InjectableId } from './injector.js';
1
+ import { InjectableId } from './injector';
2
2
  /**
3
3
  * Placed just before the class declaration, this class decorator applies metadata to the class constructor indicating that the user intends to bind the class into the container.
4
4
  * This decorator will throw if not placed on a class declaration, or if placed more than once on a class declaration.
5
5
  */
6
6
  export declare function Injectable(): ClassDecorator;
7
7
  /**
8
- * Placed just before a constructor parameter, this parameter decorator allows for specificity and control over the type of the type of Object that will be injected into the parameter.
8
+ * Placed just before a constructor parameter, this parameter decorator allows for specificity and control over the type of Object that will be injected into the parameter.
9
9
  * In the absence of this decorator the container will use whatever is bound to a parameter's type (or throw an error if it is unable to recognize the type).
10
+ * This decorator may also be placed on a parameter of a method annotated with @PostConstruct, in which case the container will resolve and inject the value before invoking that method.
10
11
  *
11
12
  * @param id The identifier of the bound type that should be injected.
12
13
  */
@@ -19,8 +20,13 @@ export declare function Inject(id: InjectableId<any>): ParameterDecorator;
19
20
  * @see Inject
20
21
  */
21
22
  export declare function _getInjectedIdAt(target: Function, parameterIndex: number): InjectableId<any>;
23
+ /**
24
+ * Retrieve the @Inject metadata for a specifically indexed parameter of a named method.
25
+ */
26
+ export declare function _getInjectedIdForMethod(prototype: object, methodName: string | symbol, parameterIndex: number): InjectableId<any>;
22
27
  /**
23
28
  * Placed just before a constructor parameter, this parameter decorator signals the container that it should supply the 'alt' constant value (undefined by default) if for *any* reason it is unable to otherwise resolve the type of the parameter.
29
+ * This decorator may also be placed on a parameter of a method annotated with @PostConstruct.
24
30
  * WARNING! It is your responsibility to ensure that alt is of the appropriate type/value.
25
31
  */
26
32
  export declare function Optional(alt?: any): ParameterDecorator;
@@ -35,9 +41,16 @@ export declare function Optional(alt?: any): ParameterDecorator;
35
41
  export declare function _getOptionalDefaultAt(target: Function, parameterIndex: number): {
36
42
  value: any;
37
43
  };
44
+ /**
45
+ * Retrieve the @Optional metadata for a specifically indexed parameter of a named method.
46
+ */
47
+ export declare function _getOptionalDefaultForMethod(prototype: object, methodName: string | symbol, parameterIndex: number): {
48
+ value: any;
49
+ };
38
50
  /**
39
51
  * Placed just before a class method, this method decorator flags a method that should be called after an object has been instantiated by the container, but before it is put into service.
40
- * The method will be assumed to be synchronous unless the method signature explicitly declares it's return type to be ": Promise<something>"
52
+ * The method will be assumed to be synchronous unless the method signature explicitly declares its return type to be ": Promise<something>".
53
+ * Parameters will be resolved by the container just as they are for constructors.
41
54
  * This decorator will throw if placed on a non-method or a static method of a class, or if placed on a method more than once, or if placed on more than one method for a class.
42
55
  */
43
56
  export declare function PostConstruct(): MethodDecorator;
@@ -16,7 +16,7 @@ export class AsyncFactoryBasedProvider extends BindableProvider {
16
16
  let retVal = this.singleton;
17
17
  if (!retVal) {
18
18
  // Wrap the async factory's Promise in an errorHandler aware Promise.
19
- // Our contract is that an AsyncFactory may not throw and must return a valid Promise (e.g. pending, resolved, rejected, etc).
19
+ // Our contract is that an AsyncFactory may not throw and must return a valid Promise (e.g., pending, resolved, rejected, etc).
20
20
  retVal = State.MakeState(this.makePromiseForObj(this.maker(this.injector), obj => obj));
21
21
  }
22
22
  if (this.singleton === null)
@@ -1 +1 @@
1
- {"version":3,"file":"async-factory-provider.js","sourceRoot":"","sources":["../../src/async-factory-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,wBAAwB,CAAC;AAGxD,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAEjC;;;GAGG;AACH,MAAM,OAAO,yBAA6B,SAAQ,gBAAoC;IACrF,YAAY,QAAkB,EAAE,EAAmB,EAAE,KAAsB;QAC1E,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;YACZ,qEAAqE;YACrE,8HAA8H;YAC9H,MAAM,GAAG,KAAK,CAAC,SAAS,CAAI,IAAI,CAAC,iBAAiB,CAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;SAC9F;QACD,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI;YAC1B,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC;QACzB,OAAO,MAAM,CAAC;IACf,CAAC;CACD","sourcesContent":["import {BindableProvider} from './bindable-provider.js';\nimport {AsyncFactory} from './binder.js';\nimport {InjectableId, Injector} from './injector.js';\nimport {State} from './state.js';\n\n/**\n * @inheritDoc\n * This specialization invokes it's configured Factory asynchronously and waits until it can provide the result.\n */\nexport class AsyncFactoryBasedProvider<T> extends BindableProvider<T, AsyncFactory<T>> {\n\tconstructor(injector: Injector, id: InjectableId<T>, maker: AsyncFactory<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\t// Wrap the async factory's Promise in an errorHandler aware Promise.\n\t\t\t// Our contract is that an AsyncFactory may not throw and must return a valid Promise (e.g. pending, resolved, rejected, etc).\n\t\t\tretVal = State.MakeState<T>(this.makePromiseForObj<T>(this.maker(this.injector), obj => obj));\n\t\t}\n\t\tif (this.singleton === null)\n\t\t\tthis.singleton = retVal;\n\t\treturn retVal;\n\t}\n}\n"]}
1
+ {"version":3,"file":"async-factory-provider.js","sourceRoot":"","sources":["../../src/async-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,yBAA6B,SAAQ,gBAAoC;IACrF,YAAY,QAAkB,EAAE,EAAmB,EAAE,KAAsB;QAC1E,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,qEAAqE;YACrE,+HAA+H;YAC/H,MAAM,GAAG,KAAK,CAAC,SAAS,CAAI,IAAI,CAAC,iBAAiB,CAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/F,CAAC;QACD,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI;YAC1B,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC;QACzB,OAAO,MAAM,CAAC;IACf,CAAC;CACD","sourcesContent":["import {BindableProvider} from './bindable-provider';\nimport {AsyncFactory} from './binding';\nimport {InjectableId, Injector} from './injector';\nimport {State} from './state';\n\n/**\n * @inheritDoc\n * This specialization invokes it's configured Factory asynchronously and waits until it can provide the result.\n */\nexport class AsyncFactoryBasedProvider<T> extends BindableProvider<T, AsyncFactory<T>> {\n\tconstructor(injector: Injector, id: InjectableId<T>, maker: AsyncFactory<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\t// Wrap the async factory's Promise in an errorHandler aware Promise.\n\t\t\t// Our contract is that an AsyncFactory may not throw and must return a valid Promise (e.g., pending, resolved, rejected, etc).\n\t\t\tretVal = State.MakeState<T>(this.makePromiseForObj<T>(this.maker(this.injector), obj => obj));\n\t\t}\n\t\tif (this.singleton === null)\n\t\t\tthis.singleton = retVal;\n\t\treturn retVal;\n\t}\n}\n"]}
@@ -12,7 +12,7 @@ export class BindableProvider extends Provider {
12
12
  this.maker = maker;
13
13
  }
14
14
  /**
15
- * Invoked by the Binder to create chain-able configuration
15
+ * Invoked by the Container to create chain-able configuration
16
16
  *
17
17
  * @see BindAs
18
18
  */
@@ -46,13 +46,13 @@ export class BindableProvider extends Provider {
46
46
  // Error handler wants us to propagate an error.
47
47
  if (isErrorObj(handlerResult))
48
48
  throw handlerResult;
49
- // Error handler has no opinion, so provideAsState a state that reflects the error we just caught.
49
+ // Error handler has no opinion, so propagate the error we just caught.
50
50
  if (typeof handlerResult === 'undefined')
51
51
  throw err;
52
52
  // Error handler provided a valid (fully resolved) replacement.
53
53
  return handlerResult;
54
54
  }
55
- // No error handler, provideAsState a state that reflects the error we just caught.
55
+ // No error handler, propagate the error we just caught.
56
56
  throw err;
57
57
  }
58
58
  /**
@@ -63,35 +63,22 @@ export class BindableProvider extends Provider {
63
63
  * @param waitFor The supplied Promise.
64
64
  * @param cb Callback to be invoked if the supplied Promise resolves.
65
65
  */
66
- makePromiseForObj(waitFor, cb) {
67
- return new Promise((resolve, reject) => {
68
- const errHandlerFn = (err, objValue) => {
69
- // There was an error during async post construction, see if an error handler was provided, and if so, see what it wants to do.
70
- if (this.errorHandler) {
71
- const handlerResult = this.errorHandler(this.injector, this.id, this.maker, err, objValue);
72
- // Error handler wants us to propagate an alternative error.
73
- if (isErrorObj(handlerResult))
74
- err = handlerResult; // Fall thru
75
- else if (typeof handlerResult !== 'undefined') {
76
- resolve(handlerResult); // Error handler provided a replacement, so change the State that we returned from pending to resolved.
77
- return;
78
- }
79
- }
80
- // This will change the State that we returned from pending to rejected.
81
- reject(err);
82
- };
83
- waitFor.then((result) => {
84
- // This will change the State that we returned from pending to resolved.
85
- try {
86
- resolve(cb(result));
87
- }
88
- catch (err) {
89
- errHandlerFn(err, cb(result));
90
- }
91
- }).catch((err) => {
92
- errHandlerFn(err, cb(undefined));
93
- });
94
- });
66
+ async makePromiseForObj(waitFor, cb) {
67
+ let result;
68
+ try {
69
+ result = await waitFor;
70
+ }
71
+ catch (err) {
72
+ // waitFor rejected — ask the error handler for recovery, passing cb(undefined) as the partial object value.
73
+ return this.queryErrorHandler(err, cb(undefined));
74
+ }
75
+ try {
76
+ return cb(result);
77
+ }
78
+ catch (err) {
79
+ // cb threw after a successful resolution — ask the error handler for recovery.
80
+ return this.queryErrorHandler(err, cb(result));
81
+ }
95
82
  }
96
83
  }
97
84
  //# sourceMappingURL=bindable-provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bindable-provider.js","sourceRoot":"","sources":["../../src/bindable-provider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AACvC,OAAO,EAAC,UAAU,EAAC,MAAM,YAAY,CAAC;AAEtC;;;GAGG;AACH,MAAM,OAAgB,gBAAgF,SAAQ,QAAW;IACxH,YAAgC,QAAkB,EAAY,EAAmB,EAAY,KAAQ;QACpG,KAAK,EAAE,CAAC;QADuB,aAAQ,GAAR,QAAQ,CAAU;QAAY,OAAE,GAAF,EAAE,CAAiB;QAAY,UAAK,GAAL,KAAK,CAAG;IAErG,CAAC;IAcD;;;;OAIG;IACH,UAAU;QACT,MAAM,MAAM,GAAiB;YAC5B,OAAO,EAAE,CAAC,EAAyB,EAAE,EAAE;gBACtC,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;YACxB,CAAC;YACD,SAAS,EAAE,CAAC,EAA2B,EAAE,EAAE;gBAC1C,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;gBACzB,OAAO,MAAM,CAAC;YACf,CAAC;YACD,WAAW,EAAE,GAAG,EAAE;gBACjB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,qCAAqC;gBAC5D,OAAO,MAAM,CAAC;YACf,CAAC;SACD,CAAC;QACF,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;;;;;OAMG;IACO,iBAAiB,CAAC,GAAY,EAAE,GAAO;QAChD,oHAAoH;QACpH,IAAI,IAAI,CAAC,YAAY,EAAE;YACtB,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACtF,gDAAgD;YAChD,IAAI,UAAU,CAAC,aAAa,CAAC;gBAC5B,MAAM,aAAa,CAAC;YACrB,kGAAkG;YAClG,IAAI,OAAO,aAAa,KAAK,WAAW;gBACvC,MAAM,GAAG,CAAC;YACX,+DAA+D;YAC/D,OAAO,aAAa,CAAC;SACrB;QACD,mFAAmF;QACnF,MAAM,GAAG,CAAC;IACX,CAAC;IAED;;;;;;;OAOG;IACO,iBAAiB,CAAI,OAAmB,EAAE,EAAoB;QACvE,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACzC,MAAM,YAAY,GAAG,CAAC,GAAQ,EAAE,QAAY,EAAE,EAAE;gBAC/C,+HAA+H;gBAC/H,IAAI,IAAI,CAAC,YAAY,EAAE;oBACtB,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;oBAC3F,4DAA4D;oBAC5D,IAAI,UAAU,CAAC,aAAa,CAAC;wBAC5B,GAAG,GAAG,aAAa,CAAC,CAAG,YAAY;yBAC/B,IAAI,OAAO,aAAa,KAAK,WAAW,EAAE;wBAC9C,OAAO,CAAC,aAAa,CAAC,CAAC,CAAI,uGAAuG;wBAClI,OAAO;qBACP;iBACD;gBACD,wEAAwE;gBACxE,MAAM,CAAC,GAAG,CAAC,CAAC;YACb,CAAC,CAAC;YACF,OAAO,CAAC,IAAI,CACX,CAAC,MAAM,EAAE,EAAE;gBACV,wEAAwE;gBACxE,IAAI;oBACH,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;iBACpB;gBACD,OAAO,GAAG,EAAE;oBACX,YAAY,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;iBAC9B;YACF,CAAC,CACD,CAAC,KAAK,CACN,CAAC,GAAG,EAAE,EAAE;gBACP,YAAY,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;YAClC,CAAC,CACD,CAAC;QACH,CAAC,CAAC,CAAC;IACJ,CAAC;CACD","sourcesContent":["import {AsyncFactory, BindAs, OnErrorCallback, OnSuccessCallback, SyncFactory} from './binder.js';\nimport {ClassConstructor, InjectableId, Injector} from './injector.js';\nimport {Provider} from './provider.js';\nimport {isErrorObj} from './utils.js';\n\n/**\n * @inheritDoc\n * This abstraction is for Providers that can be additionally configured as Singletons and/or configured with error and/or success handling callback(s).\n */\nexport abstract class BindableProvider<T, M = ClassConstructor<T> | SyncFactory<T> | AsyncFactory<T>> extends Provider<T> {\n\tprotected constructor(protected injector: Injector, protected id: InjectableId<T>, protected maker: M) {\n\t\tsuper();\n\t}\n\n\t/**\n\t * A user supplied success handling function.\n\t * Default value is undefined.\n\t */\n\tprotected successHandler?: OnSuccessCallback<T, any>;\n\n\t/**\n\t * A user supplied error handling function.\n\t * Default value is undefined.\n\t */\n\tprotected errorHandler?: OnErrorCallback<T, any>;\n\n\t/**\n\t * Invoked by the Binder to create chain-able configuration\n\t *\n\t * @see BindAs\n\t */\n\tmakeBindAs(): BindAs<T, M> {\n\t\tconst retVal: BindAs<T, M> = {\n\t\t\tonError: (cb: OnErrorCallback<T, M>) => {\n\t\t\t\tthis.errorHandler = cb;\n\t\t\t},\n\t\t\tonSuccess: (cb: OnSuccessCallback<T, M>) => {\n\t\t\t\tthis.successHandler = cb;\n\t\t\t\treturn retVal;\n\t\t\t},\n\t\t\tasSingleton: () => {\n\t\t\t\tthis.singleton = null; // Flag state as no longer undefined.\n\t\t\t\treturn retVal;\n\t\t\t}\n\t\t};\n\t\treturn retVal;\n\t}\n\n\t/**\n\t * Encapsulate the logic of invoking any configured error handler, and processing it's result.\n\t *\n\t * @see OnErrorCallback\n\t *\n\t * @returns The object substituted by the callback (otherwise this method throws the appropriate error).\n\t */\n\tprotected queryErrorHandler(err: unknown, obj?: T): T {\n\t\t// There was an error during construction, see if an error handler was provided, and if so, see what it wants to do.\n\t\tif (this.errorHandler) {\n\t\t\tconst handlerResult = this.errorHandler(this.injector, this.id, this.maker, err, obj);\n\t\t\t// Error handler wants us to propagate an error.\n\t\t\tif (isErrorObj(handlerResult))\n\t\t\t\tthrow handlerResult;\n\t\t\t// Error handler has no opinion, so provideAsState a state that reflects the error we just caught.\n\t\t\tif (typeof handlerResult === 'undefined')\n\t\t\t\tthrow err;\n\t\t\t// Error handler provided a valid (fully resolved) replacement.\n\t\t\treturn handlerResult;\n\t\t}\n\t\t// No error handler, provideAsState a state that reflects the error we just caught.\n\t\tthrow err;\n\t}\n\n\t/**\n\t * This is like a retry mechanism that uses the Provider's errorHandler (if any) to attempt recovery whenever the supplied Promise rejects.\n\t * This method returns a Promise that rejects if recovery was not possible.\n\t * If the supplied Promise resolves, then this method passes the result to the callback, and then resolve as whatever that callback returns.\n\t *\n\t * @param waitFor The supplied Promise.\n\t * @param cb Callback to be invoked if the supplied Promise resolves.\n\t */\n\tprotected makePromiseForObj<R>(waitFor: Promise<R>, cb: (result: R) => T): Promise<T> {\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst errHandlerFn = (err: any, objValue?: T) => {\n\t\t\t\t// There was an error during async post construction, see if an error handler was provided, and if so, see what it wants to do.\n\t\t\t\tif (this.errorHandler) {\n\t\t\t\t\tconst handlerResult = this.errorHandler(this.injector, this.id, this.maker, err, objValue);\n\t\t\t\t\t// Error handler wants us to propagate an alternative error.\n\t\t\t\t\tif (isErrorObj(handlerResult))\n\t\t\t\t\t\terr = handlerResult; // Fall thru\n\t\t\t\t\telse if (typeof handlerResult !== 'undefined') {\n\t\t\t\t\t\tresolve(handlerResult); // Error handler provided a replacement, so change the State that we returned from pending to resolved.\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// This will change the State that we returned from pending to rejected.\n\t\t\t\treject(err);\n\t\t\t};\n\t\t\twaitFor.then(\n\t\t\t\t(result) => {\n\t\t\t\t\t// This will change the State that we returned from pending to resolved.\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresolve(cb(result));\n\t\t\t\t\t}\n\t\t\t\t\tcatch (err) {\n\t\t\t\t\t\terrHandlerFn(err, cb(result));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t).catch(\n\t\t\t\t(err) => {\n\t\t\t\t\terrHandlerFn(err, cb(undefined));\n\t\t\t\t}\n\t\t\t);\n\t\t});\n\t}\n}\n"]}
1
+ {"version":3,"file":"bindable-provider.js","sourceRoot":"","sources":["../../src/bindable-provider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AACpC,OAAO,EAAC,UAAU,EAAC,MAAM,SAAS,CAAC;AAEnC;;;GAGG;AACH,MAAM,OAAgB,gBAAgF,SAAQ,QAAW;IACxH,YAAgC,QAAkB,EAAY,EAAmB,EAAY,KAAQ;QACpG,KAAK,EAAE,CAAC;QADuB,aAAQ,GAAR,QAAQ,CAAU;QAAY,OAAE,GAAF,EAAE,CAAiB;QAAY,UAAK,GAAL,KAAK,CAAG;IAErG,CAAC;IAcD;;;;OAIG;IACH,UAAU;QACT,MAAM,MAAM,GAAiB;YAC5B,OAAO,EAAE,CAAC,EAAyB,EAAE,EAAE;gBACtC,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;YACxB,CAAC;YACD,SAAS,EAAE,CAAC,EAA2B,EAAE,EAAE;gBAC1C,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;gBACzB,OAAO,MAAM,CAAC;YACf,CAAC;YACD,WAAW,EAAE,GAAG,EAAE;gBACjB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,qCAAqC;gBAC5D,OAAO,MAAM,CAAC;YACf,CAAC;SACD,CAAC;QACF,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;;;;;OAMG;IACO,iBAAiB,CAAC,GAAY,EAAE,GAAO;QAChD,oHAAoH;QACpH,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACtF,gDAAgD;YAChD,IAAI,UAAU,CAAC,aAAa,CAAC;gBAC5B,MAAM,aAAa,CAAC;YACrB,uEAAuE;YACvE,IAAI,OAAO,aAAa,KAAK,WAAW;gBACvC,MAAM,GAAG,CAAC;YACX,+DAA+D;YAC/D,OAAO,aAAa,CAAC;QACtB,CAAC;QACD,wDAAwD;QACxD,MAAM,GAAG,CAAC;IACX,CAAC;IAED;;;;;;;OAOG;IACO,KAAK,CAAC,iBAAiB,CAAI,OAAmB,EAAE,EAAoB;QAC7E,IAAI,MAAS,CAAC;QACd,IAAI,CAAC;YACJ,MAAM,GAAG,MAAM,OAAO,CAAC;QACxB,CAAC;QACD,OAAO,GAAG,EAAE,CAAC;YACZ,4GAA4G;YAC5G,OAAO,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,EAAE,CAAC,SAAyB,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,CAAC;YACJ,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC;QACD,OAAO,GAAG,EAAE,CAAC;YACZ,+EAA+E;YAC/E,OAAO,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,EAAE,CAAC,MAAW,CAAC,CAAC,CAAC;QACrD,CAAC;IACF,CAAC;CACD","sourcesContent":["import {AsyncFactory, BindAs, OnErrorCallback, OnSuccessCallback, SyncFactory} from './binding';\nimport {ClassConstructor, InjectableId, Injector} from './injector';\nimport {Provider} from './provider';\nimport {isErrorObj} from './utils';\n\n/**\n * @inheritDoc\n * This abstraction is for Providers that can be additionally configured as Singletons and/or configured with error and/or success handling callback(s).\n */\nexport abstract class BindableProvider<T, M = ClassConstructor<T> | SyncFactory<T> | AsyncFactory<T>> extends Provider<T> {\n\tprotected constructor(protected injector: Injector, protected id: InjectableId<T>, protected maker: M) {\n\t\tsuper();\n\t}\n\n\t/**\n\t * A user supplied success handling function.\n\t * Default value is undefined.\n\t */\n\tprotected successHandler?: OnSuccessCallback<T, any>;\n\n\t/**\n\t * A user supplied error handling function.\n\t * Default value is undefined.\n\t */\n\tprotected errorHandler?: OnErrorCallback<T, any>;\n\n\t/**\n\t * Invoked by the Container to create chain-able configuration\n\t *\n\t * @see BindAs\n\t */\n\tmakeBindAs(): BindAs<T, M> {\n\t\tconst retVal: BindAs<T, M> = {\n\t\t\tonError: (cb: OnErrorCallback<T, M>) => {\n\t\t\t\tthis.errorHandler = cb;\n\t\t\t},\n\t\t\tonSuccess: (cb: OnSuccessCallback<T, M>) => {\n\t\t\t\tthis.successHandler = cb;\n\t\t\t\treturn retVal;\n\t\t\t},\n\t\t\tasSingleton: () => {\n\t\t\t\tthis.singleton = null; // Flag state as no longer undefined.\n\t\t\t\treturn retVal;\n\t\t\t}\n\t\t};\n\t\treturn retVal;\n\t}\n\n\t/**\n\t * Encapsulate the logic of invoking any configured error handler, and processing it's result.\n\t *\n\t * @see OnErrorCallback\n\t *\n\t * @returns The object substituted by the callback (otherwise this method throws the appropriate error).\n\t */\n\tprotected queryErrorHandler(err: unknown, obj?: T): T {\n\t\t// There was an error during construction, see if an error handler was provided, and if so, see what it wants to do.\n\t\tif (this.errorHandler) {\n\t\t\tconst handlerResult = this.errorHandler(this.injector, this.id, this.maker, err, obj);\n\t\t\t// Error handler wants us to propagate an error.\n\t\t\tif (isErrorObj(handlerResult))\n\t\t\t\tthrow handlerResult;\n\t\t\t// Error handler has no opinion, so propagate the error we just caught.\n\t\t\tif (typeof handlerResult === 'undefined')\n\t\t\t\tthrow err;\n\t\t\t// Error handler provided a valid (fully resolved) replacement.\n\t\t\treturn handlerResult;\n\t\t}\n\t\t// No error handler, propagate the error we just caught.\n\t\tthrow err;\n\t}\n\n\t/**\n\t * This is like a retry mechanism that uses the Provider's errorHandler (if any) to attempt recovery whenever the supplied Promise rejects.\n\t * This method returns a Promise that rejects if recovery was not possible.\n\t * If the supplied Promise resolves, then this method passes the result to the callback, and then resolve as whatever that callback returns.\n\t *\n\t * @param waitFor The supplied Promise.\n\t * @param cb Callback to be invoked if the supplied Promise resolves.\n\t */\n\tprotected async makePromiseForObj<R>(waitFor: Promise<R>, cb: (result: R) => T): Promise<T> {\n\t\tlet result: R;\n\t\ttry {\n\t\t\tresult = await waitFor;\n\t\t}\n\t\tcatch (err) {\n\t\t\t// waitFor rejected ask the error handler for recovery, passing cb(undefined) as the partial object value.\n\t\t\treturn this.queryErrorHandler(err, cb(undefined as unknown as R));\n\t\t}\n\t\ttry {\n\t\t\treturn cb(result);\n\t\t}\n\t\tcatch (err) {\n\t\t\t// cb threw after a successful resolution ask the error handler for recovery.\n\t\t\treturn this.queryErrorHandler(err, cb(result as R));\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=binding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding.js","sourceRoot":"","sources":["../../src/binding.ts"],"names":[],"mappings":"","sourcesContent":["import {ClassConstructor, InjectableId, Injector} from './injector';\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 injector The Injector 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 make) the value. 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 = unknown> = (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 value The thing that was made.\n * @param injector The Injector 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 * @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 = unknown> = (value: T, injector: Injector, id: InjectableId<T>, maker: M) => Promise<Error | void> | Error | void;\n\n/**\n * Descriptor object used with {@link Container.register} to specify how an id should be bound.\n * Mirrors the TSyringe registration API.\n */\nexport type RegisterDescriptor<T> =\n\t| { useClass: ClassConstructor<T> }\n\t| { useValue: T }\n\t| { useFactory: SyncFactory<T> }\n\t| { useAsyncFactory: AsyncFactory<T> };\n\n/**\n * An interface allowing binding of an error handler.\n *\n * @see OnErrorCallback\n */\nexport interface BindErrHandler<T, M = unknown> {\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 = unknown> 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 = unknown> extends BindHandler<T, M> {\n\tasSingleton(): BindHandler<T, M>;\n}\n\n"]}
@@ -1,6 +1,6 @@
1
1
  import { BindableProvider } from './bindable-provider.js';
2
2
  import { POSTCONSTRUCT_ASYNC_METADATA_KEY, POSTCONSTRUCT_SYNC_METADATA_KEY, REFLECT_PARAMS } from './constants.js';
3
- import { _getInjectedIdAt, _getOptionalDefaultAt } from './decorators.js';
3
+ import { _getInjectedIdAt, _getInjectedIdForMethod, _getOptionalDefaultAt, _getOptionalDefaultForMethod } from './decorators.js';
4
4
  import { State } from './state.js';
5
5
  import { isPromise } from './utils.js';
6
6
  /**
@@ -27,66 +27,167 @@ export class ClassBasedProvider extends BindableProvider {
27
27
  }
28
28
  /**
29
29
  * @inheritDoc
30
- * This specialization returns undefined if 'asyncOnly' is true and there is no asynchronous PostConstruct annotation (since class constructors can never by asynchronous).
30
+ * This specialization returns undefined if 'asyncOnly' is true **and** there is no asynchronous PostConstruct annotation (since class constructors can never by asynchronous),
31
+ * **unless** the @PostConstruct method has injectable parameters, which may themselves require async resolution.
31
32
  */
32
33
  resolveIfSingleton(asyncOnly) {
33
- if ((!asyncOnly) || Reflect.getMetadata(POSTCONSTRUCT_ASYNC_METADATA_KEY, this.maker))
34
+ if (!asyncOnly || Reflect.getMetadata(POSTCONSTRUCT_ASYNC_METADATA_KEY, this.maker) || this.postConstructHasParams())
34
35
  return super.resolveIfSingleton(false);
35
36
  return undefined;
36
37
  }
37
38
  /**
38
- * Make a resolved or pending State that reflects any @PostConstruct annotations.
39
+ * Returns true if the @PostConstruct method (if any) has at least one parameter.
40
+ * Any parameter may require async resolution, so this class must participate in resolveSingletons.
41
+ */
42
+ postConstructHasParams() {
43
+ var _a;
44
+ const pcMethod = (_a = Reflect.getMetadata(POSTCONSTRUCT_SYNC_METADATA_KEY, this.maker)) !== null && _a !== void 0 ? _a : Reflect.getMetadata(POSTCONSTRUCT_ASYNC_METADATA_KEY, this.maker);
45
+ if (!pcMethod)
46
+ return false;
47
+ const paramTypes = Reflect.getMetadata(REFLECT_PARAMS, this.maker.prototype, pcMethod);
48
+ return Array.isArray(paramTypes) && paramTypes.length > 0;
49
+ }
50
+ /**
51
+ * Make a resolved or pending State that reflects any @PostConstruct annotations and/or onSuccess handler.
52
+ * Any @PostConstruct method (with any injected parameters) runs first; the onSuccess handler runs after.
39
53
  */
40
54
  makePostConstructState(obj) {
41
- var _a, _b;
42
- if (typeof obj === 'object' && (!Array.isArray(obj)) && obj.constructor) {
43
- let maybeAsync = false;
44
- let pcFn;
45
- if (typeof this.successHandler === 'function') {
46
- maybeAsync = true;
47
- pcFn = () => {
48
- return this.successHandler(obj, this.injector, this.id, this.maker);
49
- };
55
+ if (obj === null || typeof obj !== 'object' || Array.isArray(obj) || !obj.constructor) {
56
+ return State.MakeState(null, undefined, obj);
57
+ }
58
+ const ctor = obj.constructor;
59
+ // Look up the @PostConstruct method name (sync or async).
60
+ let pcMaybeAsync = false;
61
+ let pcMethodName = Reflect.getMetadata(POSTCONSTRUCT_SYNC_METADATA_KEY, ctor);
62
+ if (!pcMethodName) {
63
+ pcMethodName = Reflect.getMetadata(POSTCONSTRUCT_ASYNC_METADATA_KEY, ctor);
64
+ pcMaybeAsync = !!pcMethodName;
65
+ }
66
+ const pcValid = !!(pcMethodName && typeof ctor.prototype[pcMethodName] === 'function');
67
+ const hasSuccess = typeof this.successHandler === 'function';
68
+ if (!pcValid && !hasSuccess) {
69
+ return State.MakeState(null, undefined, obj);
70
+ }
71
+ // Resolve any injectable parameters declared on the @PostConstruct method.
72
+ const paramStates = pcValid ? this.getMethodParameterStates(ctor, pcMethodName) : [];
73
+ // A synchronously rejected param (with no @Optional fallback) is treated as a PostConstruct error.
74
+ const firstRejected = paramStates.find(p => !p.pending && p.rejected);
75
+ if (firstRejected) {
76
+ try {
77
+ obj = this.queryErrorHandler(firstRejected.rejected, obj);
78
+ return State.MakeState(null, undefined, obj);
50
79
  }
51
- else {
52
- /* eslint-disable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */
53
- // Check to see if there is a @PostConstruct annotation on a method of the class.
54
- let postConstruct = Reflect.getMetadata(POSTCONSTRUCT_SYNC_METADATA_KEY, obj.constructor);
55
- if (!postConstruct) {
56
- maybeAsync = true;
57
- postConstruct = Reflect.getMetadata(POSTCONSTRUCT_ASYNC_METADATA_KEY, obj.constructor);
58
- }
59
- if (postConstruct && obj.constructor.prototype[postConstruct] && typeof obj.constructor.prototype[postConstruct] === 'function')
60
- pcFn = (_b = (_a = obj[postConstruct]).bind) === null || _b === void 0 ? void 0 : _b.call(_a, obj);
61
- /* eslint-enable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */
80
+ catch (e) {
81
+ return State.MakeState(null, e, undefined);
62
82
  }
63
- if (pcFn) {
64
- let result;
83
+ }
84
+ if (paramStates.some(p => p.pending)) {
85
+ // One or more params require async resolution — wait for them, then invoke.
86
+ const paramsPromise = Promise.all(paramStates.map(async (p, idx) => {
87
+ if (p.pending) {
88
+ try {
89
+ return await p.promise;
90
+ }
91
+ catch (err) {
92
+ const md = _getOptionalDefaultForMethod(ctor.prototype, pcMethodName, idx);
93
+ if (!md)
94
+ throw err;
95
+ return md.value;
96
+ }
97
+ }
98
+ return p.fulfilled;
99
+ }));
100
+ return State.MakeState((async () => {
101
+ let args;
65
102
  try {
66
- result = pcFn();
103
+ args = await paramsPromise;
67
104
  }
68
105
  catch (err) {
69
- // The post construction method threw while executing, give the errorHandler (if any) a crack at recovery.
70
- try {
71
- obj = this.queryErrorHandler(err, obj); // The returned obj is unlikely to be the original obj.
72
- return State.MakeState(null, undefined, obj);
73
- }
74
- catch (e) {
75
- // could not recover, propagate the error.
76
- return State.MakeState(null, e, undefined);
106
+ return this.queryErrorHandler(err, obj);
107
+ }
108
+ try {
109
+ const pcResult = obj[pcMethodName](...args);
110
+ if (pcResult && (pcResult instanceof Promise || (pcMaybeAsync && isPromise(pcResult))))
111
+ await pcResult;
112
+ if (hasSuccess) {
113
+ const sResult = this.successHandler(obj, this.injector, this.id, this.maker);
114
+ if (sResult && isPromise(sResult))
115
+ await sResult;
77
116
  }
117
+ return obj;
118
+ }
119
+ catch (err) {
120
+ return this.queryErrorHandler(err, obj);
78
121
  }
79
- // The post construction method says it will let us know when it's finished.
80
- if (result && (result instanceof Promise || (maybeAsync && isPromise(result)))) {
81
- // Return a State that is pending (the other return statements in this method return a State which is resolved or rejected).
82
- /* eslint-disable @typescript-eslint/no-unsafe-argument */
83
- return State.MakeState(this.makePromiseForObj(result, () => obj));
122
+ })());
123
+ }
124
+ // All params are synchronously available (or there are no params).
125
+ const pcArgs = paramStates.map(p => p.fulfilled);
126
+ const maybeAsync = pcMaybeAsync || hasSuccess;
127
+ // Build a single function that calls PostConstruct (with resolved args) then onSuccess.
128
+ let pcFn;
129
+ if (pcValid) {
130
+ pcFn = () => {
131
+ const pcResult = obj[pcMethodName](...pcArgs);
132
+ if (pcResult && (pcResult instanceof Promise || (pcMaybeAsync && isPromise(pcResult)))) {
133
+ // PostConstruct is async — chain onSuccess after it resolves.
134
+ return hasSuccess
135
+ ? pcResult.then(() => this.successHandler(obj, this.injector, this.id, this.maker))
136
+ : pcResult;
84
137
  }
138
+ // PostConstruct is sync — call onSuccess immediately.
139
+ if (hasSuccess)
140
+ return this.successHandler(obj, this.injector, this.id, this.maker);
141
+ return pcResult;
142
+ };
143
+ }
144
+ else {
145
+ // No PostConstruct — just call onSuccess.
146
+ pcFn = () => this.successHandler(obj, this.injector, this.id, this.maker);
147
+ }
148
+ let result;
149
+ try {
150
+ result = pcFn();
151
+ }
152
+ catch (err) {
153
+ try {
154
+ obj = this.queryErrorHandler(err, obj);
155
+ return State.MakeState(null, undefined, obj);
156
+ }
157
+ catch (e) {
158
+ return State.MakeState(null, e, undefined);
85
159
  }
86
160
  }
87
- // No PostConstruct, just return a resolved State
161
+ if (result && (result instanceof Promise || (maybeAsync && isPromise(result)))) {
162
+ return State.MakeState(this.makePromiseForObj(result, () => obj));
163
+ }
88
164
  return State.MakeState(null, undefined, obj);
89
165
  }
166
+ /**
167
+ * Collects the resolved States for all injectable parameters of a @PostConstruct method.
168
+ * Uses the same resolution rules as constructor parameters: the reflected type (or an explicit @Inject token) is used to look up the binding, and an error is thrown if the type cannot be determined.
169
+ * Use @Optional() on a parameter to supply a fallback when no binding is found.
170
+ * Returns an empty array if the method has no parameters.
171
+ */
172
+ getMethodParameterStates(ctor, methodName) {
173
+ const argTypes = Reflect.getMetadata(REFLECT_PARAMS, ctor.prototype, methodName);
174
+ if (!Array.isArray(argTypes) || argTypes.length === 0)
175
+ return [];
176
+ return argTypes.map((argType, index) => {
177
+ const overrideToken = _getInjectedIdForMethod(ctor.prototype, methodName, index);
178
+ const actualToken = overrideToken !== undefined ? overrideToken : argType;
179
+ if (actualToken == null) {
180
+ throw new Error(`Injection error. Unable to determine parameter ${index} type/value of ${ctor.name}.${methodName}`);
181
+ }
182
+ let param = this.injector.resolveState(actualToken);
183
+ if (!param.pending && param.rejected) {
184
+ const optionalDefault = _getOptionalDefaultForMethod(ctor.prototype, methodName, index);
185
+ if (optionalDefault)
186
+ param = State.MakeState(null, undefined, optionalDefault.value);
187
+ }
188
+ return param;
189
+ });
190
+ }
90
191
  /**
91
192
  * This method collects the States of all the constructor parameters for our target class.
92
193
  */
@@ -107,7 +208,6 @@ export class ClassBasedProvider extends BindableProvider {
107
208
  throw new Error(`Injection error. Unable to determine parameter ${index} type/value of ${this.maker.toString()} constructor`);
108
209
  }
109
210
  // Ask our container to resolve the parameter.
110
- /* eslint-disable @typescript-eslint/no-unsafe-argument */
111
211
  let param = this.injector.resolveState(actualToken);
112
212
  // If the parameter could not be resolved, see if there is an @Optional annotation
113
213
  if ((!param.pending) && param.rejected) {
@@ -134,41 +234,43 @@ export class ClassBasedProvider extends BindableProvider {
134
234
  // We do this by mapping each param to a Promise (pending or not), and then awaiting them all.
135
235
  // This might create some unnecessary (but immediately resolved) Promise objects,
136
236
  // BUT, it allows us to chain for failure *and* substitute the Optional (if one exists).
137
- const objPromise = this.makePromiseForObj(Promise.all(params.map((p, idx) => {
237
+ const objPromise = this.makePromiseForObj(Promise.all(params.map(async (p, idx) => {
138
238
  if (p.pending) {
139
- return p.promise.catch(err => {
239
+ try {
240
+ return await p.promise;
241
+ }
242
+ catch (err) {
140
243
  // This was a promised param that failed to resolve.
141
244
  // If there is an Optional decorator, use that, otherwise, failure is failure.
142
245
  const md = _getOptionalDefaultAt(this.maker, idx);
143
246
  if (!md)
144
247
  throw err;
145
248
  return md.value;
146
- });
249
+ }
147
250
  }
148
- if (p.rejected)
149
- return Promise.reject(p.rejected);
150
- return Promise.resolve(p.fulfilled);
251
+ return p.fulfilled;
151
252
  })), (values) => {
152
253
  if (values) {
153
254
  // All the parameters are now available, instantiate the class.
154
255
  // If this throws, it will be handled by our caller.
155
256
  return Reflect.construct(this.maker, values);
156
257
  }
258
+ return undefined;
157
259
  });
158
260
  // Once the obj is resolved, then we need to check for PostConstruct and if it was async, wait for that too.
159
- return State.MakeState(objPromise.then((obj) => {
261
+ return State.MakeState((async () => {
262
+ const obj = await objPromise;
160
263
  const state = this.makePostConstructState(obj);
161
264
  if (state.pending) {
162
- return state.promise; // chain (aka wait some more).
265
+ return await state.promise; // chain (aka wait some more).
163
266
  }
164
267
  else if (state.rejected) {
165
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
166
- return state.rejected; // error
268
+ throw state.rejected; // error
167
269
  }
168
270
  else {
169
271
  return state.fulfilled; // value (aka obj).
170
272
  }
171
- }));
273
+ })());
172
274
  }
173
275
  else {
174
276
  // All parameters needed for construction are available, instantiate the object.
@@ -1 +1 @@
1
- {"version":3,"file":"class-provider.js","sourceRoot":"","sources":["../../src/class-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import {BindableProvider} from './bindable-provider.js';\nimport {POSTCONSTRUCT_ASYNC_METADATA_KEY, POSTCONSTRUCT_SYNC_METADATA_KEY, REFLECT_PARAMS} from './constants.js';\nimport {_getInjectedIdAt, _getOptionalDefaultAt} from './decorators.js';\nimport {ClassConstructor, InjectableId, Injector} from './injector.js';\nimport {State} from './state.js';\nimport {isPromise} from './utils.js';\n\n/*\n * This is a bit of a hack, but it avoids a ton of alternative hacks.\n * Note that in the Container, resolveState is a protected method.\n * Injector was never meant to publicly expose State.\n * Gotta love JS!\n */\ninterface StateResolvingInjector extends Injector {\n\tresolveState<T>(id: InjectableId<T>): State<T>;\n}\n\n/**\n * @inheritDoc\n * This specialization invokes it's configured class constructor synchronously and then scans for (and invokes) any @PostConstruct (which may be synchronous or asynchronous).\n */\nexport class ClassBasedProvider<T> extends BindableProvider<T, ClassConstructor<T>> {\n\tconstructor(injector: StateResolvingInjector, id: InjectableId<T>, maker: ClassConstructor<T>) {\n\t\tsuper(injector, id, maker);\n\t}\n\n\t/**\n\t * @inheritDoc\n\t * @see the class description for this Provider.\n\t * This method is just a singleton guard, the real work is done by provideAsStateImpl.\n\t */\n\tprovideAsState(): State<T> {\n\t\tlet retVal = this.singleton;\n\t\tif (!retVal) {\n\t\t\tretVal = this.provideAsStateImpl();\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 if 'asyncOnly' is true and there is no asynchronous PostConstruct annotation (since class constructors can never by asynchronous).\n\t */\n\tresolveIfSingleton(asyncOnly: boolean): Promise<T> {\n\t\tif ((!asyncOnly) || Reflect.getMetadata(POSTCONSTRUCT_ASYNC_METADATA_KEY, this.maker))\n\t\t\treturn super.resolveIfSingleton(false);\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Make a resolved or pending State that reflects any @PostConstruct annotations.\n\t */\n\tprotected makePostConstructState(obj: T): State<T> {\n\t\tif (typeof obj === 'object' && (!Array.isArray(obj)) && obj.constructor) {\n\t\t\tlet maybeAsync = false;\n\t\t\tlet pcFn: () => void | Error | Promise<void | Error>;\n\t\t\tif (typeof this.successHandler === 'function') {\n\t\t\t\tmaybeAsync = true;\n\t\t\t\tpcFn = () => {\n\t\t\t\t\treturn this.successHandler(obj, this.injector, this.id, this.maker);\n\t\t\t\t};\n\t\t\t}\n\t\t\telse {\n\t\t\t\t/* eslint-disable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */\n\t\t\t\t// Check to see if there is a @PostConstruct annotation on a method of the class.\n\t\t\t\tlet postConstruct: string = Reflect.getMetadata(POSTCONSTRUCT_SYNC_METADATA_KEY, obj.constructor);\n\t\t\t\tif (!postConstruct) {\n\t\t\t\t\tmaybeAsync = true;\n\t\t\t\t\tpostConstruct = Reflect.getMetadata(POSTCONSTRUCT_ASYNC_METADATA_KEY, obj.constructor);\n\t\t\t\t}\n\t\t\t\tif (postConstruct && obj.constructor.prototype[postConstruct] && typeof obj.constructor.prototype[postConstruct] === 'function')\n\t\t\t\t\tpcFn = obj[postConstruct].bind?.(obj);\n\n\t\t\t\t/* eslint-enable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */\n\t\t\t}\n\t\t\tif (pcFn) {\n\t\t\t\tlet result: any;\n\t\t\t\ttry {\n\t\t\t\t\tresult = pcFn();\n\t\t\t\t}\n\t\t\t\tcatch (err) {\n\t\t\t\t\t// The post construction method threw while executing, give the errorHandler (if any) a crack at recovery.\n\t\t\t\t\ttry {\n\t\t\t\t\t\tobj = this.queryErrorHandler(err, obj); // The returned obj is unlikely to be the original obj.\n\t\t\t\t\t\treturn State.MakeState<T>(null, undefined, obj);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (e) {\n\t\t\t\t\t\t// could not recover, propagate the error.\n\t\t\t\t\t\treturn State.MakeState<T>(null, e, undefined);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// The post construction method says it will let us know when it's finished.\n\t\t\t\tif (result && (result instanceof Promise || (maybeAsync && isPromise<void>(result)))) {\n\t\t\t\t\t// Return a State that is pending (the other return statements in this method return a State which is resolved or rejected).\n\t\t\t\t\t/* eslint-disable @typescript-eslint/no-unsafe-argument */\n\t\t\t\t\treturn State.MakeState<T>(this.makePromiseForObj<T>(result, () => obj));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// No PostConstruct, just return a resolved State\n\t\treturn State.MakeState<T>(null, undefined, obj);\n\t}\n\n\t/**\n\t * This method collects the States of all the constructor parameters for our target class.\n\t */\n\tprotected getConstructorParameterStates(): State[] {\n\t\tconst argTypes = Reflect.getMetadata(REFLECT_PARAMS, this.maker);\n\t\tif (argTypes === undefined || !Array.isArray(argTypes)) {\n\t\t\treturn [];\n\t\t}\n\t\treturn argTypes.map((argType, index) => {\n\t\t\t// The reflect-metadata API fails on circular dependencies returning undefined instead.\n\t\t\t// Additionally, it cannot return generic types (no runtime type info).\n\t\t\t// If an Inject annotation precedes the parameter, then that is what should get injected.\n\t\t\tconst overrideToken = _getInjectedIdAt(this.maker, index);\n\t\t\t// If there was no Inject annotation, we might still be able to determine what to inject using the 'argType' (aka Reflect design:paramtypes).\n\t\t\tconst actualToken = overrideToken === undefined ? argType : overrideToken;\n\t\t\tif (actualToken === undefined) {\n\t\t\t\t// No Inject annotation, and the type is not known.\n\t\t\t\tthrow new Error(`Injection error. Unable to determine parameter ${index} type/value of ${this.maker.toString()} constructor`);\n\t\t\t}\n\t\t\t// Ask our container to resolve the parameter.\n\t\t\t/* eslint-disable @typescript-eslint/no-unsafe-argument */\n\t\t\tlet param = (this.injector as StateResolvingInjector).resolveState(actualToken);\n\t\t\t// If the parameter could not be resolved, see if there is an @Optional annotation\n\t\t\tif ((!param.pending) && param.rejected) {\n\t\t\t\tconst md = _getOptionalDefaultAt(this.maker, index);\n\t\t\t\tif (md)\n\t\t\t\t\tparam = State.MakeState<any>(null, undefined, md.value);\n\t\t\t}\n\t\t\treturn param;\n\t\t});\n\t}\n\n\t/**\n\t * Gather the needed constructor parameters, invoke the constructor, and figure out what post construction needs done.\n\t */\n\tprivate provideAsStateImpl(): State<T> {\n\t\tconst params = this.getConstructorParameterStates();\n\n\t\t// If any of the params are in a rejected state, we cannot construct.\n\t\tconst firstRejectedParam = params.find((p) => {\n\t\t\treturn (!p.pending) && p.rejected;\n\t\t});\n\t\tif (firstRejectedParam)\n\t\t\treturn firstRejectedParam as State<T>;\n\t\tif (params.some(p => p.pending)) {\n\t\t\t// Some of the parameters needed for construction are not yet available, wait for them and then attempt construction.\n\t\t\t// We do this by mapping each param to a Promise (pending or not), and then awaiting them all.\n\t\t\t// This might create some unnecessary (but immediately resolved) Promise objects,\n\t\t\t// BUT, it allows us to chain for failure *and* substitute the Optional (if one exists).\n\t\t\tconst objPromise = this.makePromiseForObj<any[]>(Promise.all(params.map((p, idx) => {\n\t\t\t\tif (p.pending) {\n\t\t\t\t\treturn p.promise.catch(err => {\n\t\t\t\t\t\t// This was a promised param that failed to resolve.\n\t\t\t\t\t\t// If there is an Optional decorator, use that, otherwise, failure is failure.\n\t\t\t\t\t\tconst md = _getOptionalDefaultAt(this.maker, idx);\n\t\t\t\t\t\tif (!md)\n\t\t\t\t\t\t\tthrow err;\n\t\t\t\t\t\treturn md.value as unknown;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (p.rejected)\n\t\t\t\t\treturn Promise.reject(p.rejected);\n\t\t\t\treturn Promise.resolve(p.fulfilled);\n\t\t\t})), (values) => {\n\t\t\t\tif (values) {\n\t\t\t\t\t// All the parameters are now available, instantiate the class.\n\t\t\t\t\t// If this throws, it will be handled by our caller.\n\t\t\t\t\treturn Reflect.construct(this.maker, values);\n\t\t\t\t}\n\t\t\t});\n\t\t\t// Once the obj is resolved, then we need to check for PostConstruct and if it was async, wait for that too.\n\t\t\treturn State.MakeState<T>(objPromise.then((obj) => {\n\t\t\t\tconst state = this.makePostConstructState(obj);\n\t\t\t\tif (state.pending) {\n\t\t\t\t\treturn state.promise; // chain (aka wait some more).\n\t\t\t\t}\n\t\t\t\telse if (state.rejected) {\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\t\t\t\t\treturn state.rejected as any; // error\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\treturn state.fulfilled; // value (aka obj).\n\t\t\t\t}\n\t\t\t}));\n\t\t}\n\t\telse {\n\t\t\t// All parameters needed for construction are available, instantiate the object.\n\t\t\ttry {\n\t\t\t\tconst newObj = Reflect.construct(this.maker, params.map((p) => p.fulfilled as unknown));\n\t\t\t\treturn this.makePostConstructState(newObj);\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\treturn 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\treturn State.MakeState<T>(null, e, undefined);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"class-provider.js","sourceRoot":"","sources":["../../src/class-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import {BindableProvider} from './bindable-provider';\nimport {POSTCONSTRUCT_ASYNC_METADATA_KEY, POSTCONSTRUCT_SYNC_METADATA_KEY, REFLECT_PARAMS} from './constants';\nimport {_getInjectedIdAt, _getInjectedIdForMethod, _getOptionalDefaultAt, _getOptionalDefaultForMethod} from './decorators';\nimport {ClassConstructor, InjectableId, Injector} from './injector';\nimport {State} from './state';\nimport {isPromise} from './utils';\n\n/*\n * This is a bit of a hack, but it avoids a ton of alternative hacks.\n * Note that in the Container, resolveState is a protected method.\n * Injector was never meant to publicly expose State.\n * Gotta love JS!\n */\ninterface StateResolvingInjector extends Injector {\n\tresolveState<T>(id: InjectableId<T>): State<T>;\n}\n\n/**\n * @inheritDoc\n * This specialization invokes it's configured class constructor synchronously and then scans for (and invokes) any @PostConstruct (which may be synchronous or asynchronous).\n */\nexport class ClassBasedProvider<T> extends BindableProvider<T, ClassConstructor<T>> {\n\tconstructor(injector: StateResolvingInjector, id: InjectableId<T>, maker: ClassConstructor<T>) {\n\t\tsuper(injector, id, maker);\n\t}\n\n\t/**\n\t * @inheritDoc\n\t * @see the class description for this Provider.\n\t * This method is just a singleton guard, the real work is done by provideAsStateImpl.\n\t */\n\tprovideAsState(): State<T> {\n\t\tlet retVal = this.singleton;\n\t\tif (!retVal) {\n\t\t\tretVal = this.provideAsStateImpl();\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 if 'asyncOnly' is true **and** there is no asynchronous PostConstruct annotation (since class constructors can never by asynchronous),\n\t * **unless** the @PostConstruct method has injectable parameters, which may themselves require async resolution.\n\t */\n\tresolveIfSingleton(asyncOnly: boolean): Promise<T> | undefined {\n\t\tif (!asyncOnly || Reflect.getMetadata(POSTCONSTRUCT_ASYNC_METADATA_KEY, this.maker) || this.postConstructHasParams())\n\t\t\treturn super.resolveIfSingleton(false);\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Returns true if the @PostConstruct method (if any) has at least one parameter.\n\t * Any parameter may require async resolution, so this class must participate in resolveSingletons.\n\t */\n\tprivate postConstructHasParams(): boolean {\n\t\tconst pcMethod =\n\t\t\t(Reflect.getMetadata(POSTCONSTRUCT_SYNC_METADATA_KEY, this.maker) as string | undefined) ??\n\t\t\t(Reflect.getMetadata(POSTCONSTRUCT_ASYNC_METADATA_KEY, this.maker) as string | undefined);\n\t\tif (!pcMethod)\n\t\t\treturn false;\n\t\tconst paramTypes = Reflect.getMetadata(REFLECT_PARAMS, this.maker.prototype, pcMethod) as unknown[] | undefined;\n\t\treturn Array.isArray(paramTypes) && paramTypes.length > 0;\n\t}\n\n\t/**\n\t * Make a resolved or pending State that reflects any @PostConstruct annotations and/or onSuccess handler.\n\t * Any @PostConstruct method (with any injected parameters) runs first; the onSuccess handler runs after.\n\t */\n\tprotected makePostConstructState(obj: T): State<T> {\n\t\tif (obj === null || typeof obj !== 'object' || Array.isArray(obj) || !(obj as any).constructor) {\n\t\t\treturn State.MakeState<T>(null, undefined, obj);\n\t\t}\n\t\tconst ctor = (obj as any).constructor;\n\n\t\t// Look up the @PostConstruct method name (sync or async).\n\t\tlet pcMaybeAsync = false;\n\t\tlet pcMethodName: string | undefined = Reflect.getMetadata(POSTCONSTRUCT_SYNC_METADATA_KEY, ctor) as string | undefined;\n\t\tif (!pcMethodName) {\n\t\t\tpcMethodName = Reflect.getMetadata(POSTCONSTRUCT_ASYNC_METADATA_KEY, ctor) as string | undefined;\n\t\t\tpcMaybeAsync = !!pcMethodName;\n\t\t}\n\t\tconst pcValid = !!(pcMethodName && typeof ctor.prototype[pcMethodName] === 'function');\n\t\tconst hasSuccess = typeof this.successHandler === 'function';\n\n\t\tif (!pcValid && !hasSuccess) {\n\t\t\treturn State.MakeState<T>(null, undefined, obj);\n\t\t}\n\n\t\t// Resolve any injectable parameters declared on the @PostConstruct method.\n\t\tconst paramStates = pcValid ? this.getMethodParameterStates(ctor, pcMethodName!) : [];\n\n\t\t// A synchronously rejected param (with no @Optional fallback) is treated as a PostConstruct error.\n\t\tconst firstRejected = paramStates.find(p => !p.pending && p.rejected);\n\t\tif (firstRejected) {\n\t\t\ttry {\n\t\t\t\tobj = this.queryErrorHandler(firstRejected.rejected, obj);\n\t\t\t\treturn State.MakeState<T>(null, undefined, obj);\n\t\t\t}\n\t\t\tcatch (e) {\n\t\t\t\treturn State.MakeState<T>(null, e, undefined);\n\t\t\t}\n\t\t}\n\n\t\tif (paramStates.some(p => p.pending)) {\n\t\t\t// One or more params require async resolution — wait for them, then invoke.\n\t\t\tconst paramsPromise = Promise.all(paramStates.map(async (p, idx) => {\n\t\t\t\tif (p.pending) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn await p.promise!;\n\t\t\t\t\t}\n\t\t\t\t\tcatch (err) {\n\t\t\t\t\t\tconst md = _getOptionalDefaultForMethod(ctor.prototype, pcMethodName!, idx);\n\t\t\t\t\t\tif (!md) throw err;\n\t\t\t\t\t\treturn md.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn p.fulfilled;\n\t\t\t}));\n\t\t\treturn State.MakeState<T>((async () => {\n\t\t\t\tlet args: any[];\n\t\t\t\ttry {\n\t\t\t\t\targs = await paramsPromise;\n\t\t\t\t}\n\t\t\t\tcatch (err) {\n\t\t\t\t\treturn this.queryErrorHandler(err, obj);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst pcResult = (obj as any)[pcMethodName!](...args);\n\t\t\t\t\tif (pcResult && (pcResult instanceof Promise || (pcMaybeAsync && isPromise(pcResult))))\n\t\t\t\t\t\tawait pcResult;\n\t\t\t\t\tif (hasSuccess) {\n\t\t\t\t\t\tconst sResult = this.successHandler!(obj, this.injector, this.id, this.maker);\n\t\t\t\t\t\tif (sResult && isPromise(sResult)) await sResult;\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t\tcatch (err) {\n\t\t\t\t\treturn this.queryErrorHandler(err, obj);\n\t\t\t\t}\n\t\t\t})());\n\t\t}\n\n\t\t// All params are synchronously available (or there are no params).\n\t\tconst pcArgs = paramStates.map(p => p.fulfilled);\n\t\tconst maybeAsync = pcMaybeAsync || hasSuccess;\n\n\t\t// Build a single function that calls PostConstruct (with resolved args) then onSuccess.\n\t\tlet pcFn: (() => void | Error | Promise<void | Error>) | undefined;\n\t\tif (pcValid) {\n\t\t\tpcFn = () => {\n\t\t\t\tconst pcResult = (obj as any)[pcMethodName!](...pcArgs);\n\t\t\t\tif (pcResult && (pcResult instanceof Promise || (pcMaybeAsync && isPromise<void>(pcResult)))) {\n\t\t\t\t\t// PostConstruct is async — chain onSuccess after it resolves.\n\t\t\t\t\treturn hasSuccess\n\t\t\t\t\t\t? (pcResult as Promise<void>).then(() => this.successHandler!(obj, this.injector, this.id, this.maker))\n\t\t\t\t\t\t: pcResult as Promise<void>;\n\t\t\t\t}\n\t\t\t\t// PostConstruct is sync — call onSuccess immediately.\n\t\t\t\tif (hasSuccess)\n\t\t\t\t\treturn this.successHandler!(obj, this.injector, this.id, this.maker) as void | Error | Promise<void | Error>;\n\t\t\t\treturn pcResult;\n\t\t\t};\n\t\t}\n\t\telse {\n\t\t\t// No PostConstruct — just call onSuccess.\n\t\t\tpcFn = () => this.successHandler!(obj, this.injector, this.id, this.maker) as void | Error | Promise<void | Error>;\n\t\t}\n\n\t\tlet result: any;\n\t\ttry {\n\t\t\tresult = pcFn();\n\t\t}\n\t\tcatch (err) {\n\t\t\ttry {\n\t\t\t\tobj = this.queryErrorHandler(err, obj);\n\t\t\t\treturn State.MakeState<T>(null, undefined, obj);\n\t\t\t}\n\t\t\tcatch (e) {\n\t\t\t\treturn State.MakeState<T>(null, e, undefined);\n\t\t\t}\n\t\t}\n\t\tif (result && (result instanceof Promise || (maybeAsync && isPromise<void>(result)))) {\n\t\t\treturn State.MakeState<T>(this.makePromiseForObj<T>(result, () => obj));\n\t\t}\n\t\treturn State.MakeState<T>(null, undefined, obj);\n\t}\n\n\t/**\n\t * Collects the resolved States for all injectable parameters of a @PostConstruct method.\n\t * Uses the same resolution rules as constructor parameters: the reflected type (or an explicit @Inject token) is used to look up the binding, and an error is thrown if the type cannot be determined.\n\t * Use @Optional() on a parameter to supply a fallback when no binding is found.\n\t * Returns an empty array if the method has no parameters.\n\t */\n\tprotected getMethodParameterStates(ctor: Function, methodName: string): State[] {\n\t\tconst argTypes = Reflect.getMetadata(REFLECT_PARAMS, ctor.prototype, methodName) as unknown[] | undefined;\n\t\tif (!Array.isArray(argTypes) || argTypes.length === 0)\n\t\t\treturn [];\n\t\treturn argTypes.map((argType, index) => {\n\t\t\tconst overrideToken = _getInjectedIdForMethod(ctor.prototype, methodName, index);\n\t\t\tconst actualToken = overrideToken !== undefined ? overrideToken : argType;\n\t\t\tif (actualToken == null) {\n\t\t\t\tthrow new Error(`Injection error. Unable to determine parameter ${index} type/value of ${(ctor as any).name}.${methodName}`);\n\t\t\t}\n\t\t\tlet param = (this.injector as StateResolvingInjector).resolveState(actualToken as InjectableId<unknown>);\n\t\t\tif (!param.pending && param.rejected) {\n\t\t\t\tconst optionalDefault = _getOptionalDefaultForMethod(ctor.prototype, methodName, index);\n\t\t\t\tif (optionalDefault)\n\t\t\t\t\tparam = State.MakeState<any>(null, undefined, optionalDefault.value);\n\t\t\t}\n\t\t\treturn param;\n\t\t});\n\t}\n\n\t/**\n\t * This method collects the States of all the constructor parameters for our target class.\n\t */\n\tprotected getConstructorParameterStates(): State[] {\n\t\tconst argTypes = Reflect.getMetadata(REFLECT_PARAMS, this.maker);\n\t\tif (argTypes === undefined || !Array.isArray(argTypes)) {\n\t\t\treturn [];\n\t\t}\n\t\treturn argTypes.map((argType, index) => {\n\t\t\t// The reflect-metadata API fails on circular dependencies returning undefined instead.\n\t\t\t// Additionally, it cannot return generic types (no runtime type info).\n\t\t\t// If an Inject annotation precedes the parameter, then that is what should get injected.\n\t\t\tconst overrideToken = _getInjectedIdAt(this.maker, index);\n\t\t\t// If there was no Inject annotation, we might still be able to determine what to inject using the 'argType' (aka Reflect design:paramtypes).\n\t\t\tconst actualToken = overrideToken === undefined ? argType : overrideToken;\n\t\t\tif (actualToken === undefined) {\n\t\t\t\t// No Inject annotation, and the type is not known.\n\t\t\t\tthrow new Error(`Injection error. Unable to determine parameter ${index} type/value of ${this.maker.toString()} constructor`);\n\t\t\t}\n\t\t\t// Ask our container to resolve the parameter.\n\t\t\tlet param = (this.injector as StateResolvingInjector).resolveState(actualToken);\n\t\t\t// If the parameter could not be resolved, see if there is an @Optional annotation\n\t\t\tif ((!param.pending) && param.rejected) {\n\t\t\t\tconst md = _getOptionalDefaultAt(this.maker, index);\n\t\t\t\tif (md)\n\t\t\t\t\tparam = State.MakeState<any>(null, undefined, md.value);\n\t\t\t}\n\t\t\treturn param;\n\t\t});\n\t}\n\n\t/**\n\t * Gather the needed constructor parameters, invoke the constructor, and figure out what post construction needs done.\n\t */\n\tprivate provideAsStateImpl(): State<T> {\n\t\tconst params = this.getConstructorParameterStates();\n\n\t\t// If any of the params are in a rejected state, we cannot construct.\n\t\tconst firstRejectedParam = params.find((p) => {\n\t\t\treturn (!p.pending) && p.rejected;\n\t\t});\n\t\tif (firstRejectedParam)\n\t\t\treturn firstRejectedParam as State<T>;\n\t\tif (params.some(p => p.pending)) {\n\t\t\t// Some of the parameters needed for construction are not yet available, wait for them and then attempt construction.\n\t\t\t// We do this by mapping each param to a Promise (pending or not), and then awaiting them all.\n\t\t\t// This might create some unnecessary (but immediately resolved) Promise objects,\n\t\t\t// BUT, it allows us to chain for failure *and* substitute the Optional (if one exists).\n\t\t\tconst objPromise = this.makePromiseForObj<any[]>(Promise.all(params.map(async (p, idx) => {\n\t\t\t\tif (p.pending) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn await p.promise!;\n\t\t\t\t\t}\n\t\t\t\t\tcatch (err) {\n\t\t\t\t\t\t// This was a promised param that failed to resolve.\n\t\t\t\t\t\t// If there is an Optional decorator, use that, otherwise, failure is failure.\n\t\t\t\t\t\tconst md = _getOptionalDefaultAt(this.maker, idx);\n\t\t\t\t\t\tif (!md)\n\t\t\t\t\t\t\tthrow err;\n\t\t\t\t\t\treturn md.value as unknown;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn p.fulfilled;\n\t\t\t})), (values) => {\n\t\t\t\tif (values) {\n\t\t\t\t\t// All the parameters are now available, instantiate the class.\n\t\t\t\t\t// If this throws, it will be handled by our caller.\n\t\t\t\t\treturn Reflect.construct(this.maker, values);\n\t\t\t\t}\n\t\t\t\treturn undefined as unknown as T;\n\t\t\t});\n\t\t\t// Once the obj is resolved, then we need to check for PostConstruct and if it was async, wait for that too.\n\t\t\treturn State.MakeState<T>((async () => {\n\t\t\t\tconst obj = await objPromise;\n\t\t\t\tconst state = this.makePostConstructState(obj);\n\t\t\t\tif (state.pending) {\n\t\t\t\t\treturn await state.promise!; // chain (aka wait some more).\n\t\t\t\t}\n\t\t\t\telse if (state.rejected) {\n\t\t\t\t\tthrow state.rejected; // error\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\treturn state.fulfilled!; // value (aka obj).\n\t\t\t\t}\n\t\t\t})());\n\t\t}\n\t\telse {\n\t\t\t// All parameters needed for construction are available, instantiate the object.\n\t\t\ttry {\n\t\t\t\tconst newObj = Reflect.construct(this.maker, params.map((p) => p.fulfilled as unknown));\n\t\t\t\treturn this.makePostConstructState(newObj);\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\treturn 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\treturn State.MakeState<T>(null, e, undefined);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"constant-provider.js","sourceRoot":"","sources":["../../src/constant-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AACvC,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAEjC;;;GAGG;AACH,MAAM,OAAO,gBAAoB,SAAQ,QAAW;IACnD,YAAY,QAAW;QACtB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAI,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAChE,CAAC;IAED,cAAc;QACb,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;CACD","sourcesContent":["import {Provider} from './provider.js';\nimport {State} from './state.js';\n\n/**\n * @inheritDoc\n * This specialization is always a Singleton.\n */\nexport class ConstantProvider<T> extends Provider<T> {\n\tconstructor(constant: T) {\n\t\tsuper();\n\t\tthis.singleton = State.MakeState<T>(null, undefined, constant);\n\t}\n\n\tprovideAsState(): State<T> {\n\t\treturn this.singleton;\n\t}\n}\n"]}
1
+ {"version":3,"file":"constant-provider.js","sourceRoot":"","sources":["../../src/constant-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AACpC,OAAO,EAAC,KAAK,EAAC,MAAM,SAAS,CAAC;AAE9B;;;GAGG;AACH,MAAM,OAAO,gBAAoB,SAAQ,QAAW;IACnD,YAAY,QAAW;QACtB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAI,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAChE,CAAC;IAED,cAAc;QACb,OAAO,IAAI,CAAC,SAAU,CAAC;IACxB,CAAC;CACD","sourcesContent":["import {Provider} from './provider';\nimport {State} from './state';\n\n/**\n * @inheritDoc\n * This specialization is always a Singleton.\n */\nexport class ConstantProvider<T> extends Provider<T> {\n\tconstructor(constant: T) {\n\t\tsuper();\n\t\tthis.singleton = State.MakeState<T>(null, undefined, constant);\n\t}\n\n\tprovideAsState(): State<T> {\n\t\treturn this.singleton!;\n\t}\n}\n"]}