Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promise (Lazy) Support + Global onActivation/onDeactivation #1132

Merged
merged 77 commits into from
Apr 30, 2021
Merged
Show file tree
Hide file tree
Changes from 70 commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
e6fc8de
potential appveyor fix
parisholley Aug 22, 2019
64cec27
fix for Microsoft/TSJS-lib-generator#559
parisholley Aug 22, 2019
4fc0636
Merge branch 'appveyor' into TimerHandlerFix
parisholley Aug 22, 2019
44c314d
full promise/async support, global onActivation/onDeactivation, bindi…
parisholley Aug 22, 2019
3e5b70e
appveyor works again?
parisholley Aug 22, 2019
2e14955
latest versions of FF require latest launcher to not hang
parisholley Aug 23, 2019
72949c0
Merge branch 'appveyor-fix' into async-v2
parisholley Aug 23, 2019
b1e4ff8
chore(package): update publish-please to version 5.5.0
greenkeeper[bot] Jun 30, 2019
c1f887d
fix for Microsoft/TSJS-lib-generator#559
parisholley Aug 22, 2019
2d7d794
latest versions of FF require latest launcher to not hang
parisholley Aug 23, 2019
f1971a4
context bug
parisholley Aug 23, 2019
4bde848
merged with master
parisholley Aug 24, 2019
29e6448
merged with latest
parisholley Aug 24, 2019
40a7951
support promise retying
parisholley Sep 12, 2019
cfe6661
change promise checks to thenable checks
parisholley Sep 15, 2019
1f97c3a
fix dangling promise
parisholley Sep 15, 2019
3ac344d
take advantage of type narrowing
parisholley Sep 16, 2019
cafe1eb
Merge branch 'master' into async-v2
parisholley Sep 16, 2019
a11d135
export predestroy
parisholley Sep 26, 2019
5995443
fix when promises are rejected and null values end up in the cache
parisholley Dec 6, 2019
54fa585
Merge branch 'master' into async-v2
dcavanagh Dec 16, 2020
7f9171c
Merge remote-tracking branch 'origin' into pr/parisholley/1132
PodaruDragos Mar 3, 2021
97207c3
fix failing ci
PodaruDragos Mar 3, 2021
9d745ca
test(resolution): remove additional spaces
notaphplover Apr 6, 2021
01941fd
Bump elliptic from 6.5.3 to 6.5.4 (#1298)
dependabot[bot] Mar 10, 2021
525007b
constant value / function binding activated when resolved (#1122)
notaphplover Apr 12, 2021
a67b3a7
Apply middleware when Container.resolve - fixes 1128 (#1129)
tonyhallett Mar 30, 2021
c1e7376
Setter injection without cast (#1152)
tonyhallett Mar 30, 2021
80e91bd
feat: refactor Container extracting logic to _preDestroyBinding and …
notaphplover Apr 8, 2021
8e77c51
refactor: updated several modules to pass codeclimate's analysis.
notaphplover Apr 8, 2021
1c5d462
Merge branch 'master' of https://github.com/inversify/InversifyJS int…
notaphplover Apr 12, 2021
b74cfd4
Merge remote-tracking branch 'upstream/master' into async-v2
notaphplover Apr 13, 2021
08ad622
refactor: update error messages to not to receive any type parameters
notaphplover Apr 14, 2021
b792336
refactor: update instantiation with better typings
notaphplover Apr 14, 2021
a3b7c9d
refactor: update Lookup.clone to use a Typeguard
notaphplover Apr 14, 2021
f94f125
refactor: update error msg with non any parameters
notaphplover Apr 14, 2021
3fef493
Merge branch 'master' of https://github.com/inversify/InversifyJS int…
notaphplover Apr 16, 2021
bcf0880
fix: update onActivation test to use a binding with a transient scope…
notaphplover Apr 16, 2021
161d0b2
Merge branch 'master' of https://github.com/inversify/InversifyJS int…
notaphplover Apr 18, 2021
f7a064e
feat: update container._propagateDeactivation to not to _triggerOnDea…
notaphplover Apr 19, 2021
9f40b2e
style: make it name shorter
notaphplover Apr 19, 2021
f75be4d
docs: added get async docs
notaphplover Apr 20, 2021
9f17834
docs: update container docs
notaphplover Apr 21, 2021
b2d8e61
docs: add activation handler and pre destroy docs
notaphplover Apr 21, 2021
292bab9
add missing types and refactor types to use BindingActivation and Bin…
notaphplover Apr 21, 2021
28c5d4e
add deactivation_handler docs
notaphplover Apr 21, 2021
06e66e3
fix async multi inject and property inject
tonyhallett Apr 22, 2021
8854c42
Container get all async methods to Promise<T[]>. singular async to as…
tonyhallett Apr 22, 2021
62390ba
container resolution type correction and improve lazy in sync test
tonyhallett Apr 22, 2021
1cc0df4
add typings at resolver and compact boolean logic at container._getBu…
notaphplover Apr 22, 2021
53a739c
add isPromiseOrContainsPromise
notaphplover Apr 22, 2021
b5421a0
update isPromise to receive unknown and a generic type
notaphplover Apr 22, 2021
b7a1845
refactor _createInstance
tonyhallett Apr 23, 2021
74e07a4
refactor _resolveRequests with array reduce
tonyhallett Apr 23, 2021
c7f97df
type to interface
tonyhallett Apr 23, 2021
ad07f4b
test coverage
tonyhallett Apr 23, 2021
6e58b9a
correct spelling in tests and correct expect in handler
tonyhallett Apr 23, 2021
455a48d
deactivate refactor and name changes
tonyhallett Apr 23, 2021
4df7e91
refactor activation and deactivation
tonyhallett Apr 23, 2021
e7c7943
update wikis and dynamic value typing
tonyhallett Apr 24, 2021
70be077
rebindAsync, missing module functionality and wiki updates
tonyhallett Apr 25, 2021
6b1d44d
Merge branch 'master' of https://github.com/inversify/InversifyJS int…
notaphplover Apr 25, 2021
004dc56
Merge branch 'master' into async-v2
tonyhallett Apr 26, 2021
f707594
review changes - type name change and missing snapshot moduleActivati…
tonyhallett Apr 26, 2021
00a1678
last code climate refactor
tonyhallett Apr 26, 2021
b118ab0
docs: update changelog
notaphplover Apr 27, 2021
6d525a2
feat: add lookup.removeIntersection
notaphplover Apr 27, 2021
e2f0099
test: add test for lookup.removeIntersection
notaphplover Apr 28, 2021
530eb86
test: improve module_activation_store tests
notaphplover Apr 28, 2021
748492e
test: add test to ensure unbind async throws an error when no binding…
notaphplover Apr 28, 2021
d2751a7
100% coverage
tonyhallett Apr 29, 2021
63a8679
correct test to match description
tonyhallett Apr 29, 2021
3ad854f
wiki grammar correction
tonyhallett Apr 29, 2021
dcf96ee
make container unload methods explicit that applies equally to async
tonyhallett Apr 29, 2021
36cfea6
type changes
tonyhallett Apr 29, 2021
f76a933
wiki changes
tonyhallett Apr 29, 2021
d06d0b0
update interfaces.Container.createChild to avoid receiving parameters
notaphplover Apr 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ test/**/*.js.map
src/**/*.js.map
src/*.js.map
type_definitions/**/*.js
.DS_store
.idea

.nyc_output
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ All notable changes to this project from 5.0.0 forward will be documented in thi
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- Async bindings #1132
- Async binding resolution (getAllAsync, getAllNamedAsync, getAllTaggedAsync, getAsync, getNamedAsync, getTaggedAsync, rebindAsync, unbindAsync, unbindAllAsync, unloadAsync) #1132
- Global onActivation / onDeactivation #1132
- Parent/Child onActivation / onDeactivation #1132
- Module onActivation / onDeactivation #1132
- Added @preDestroy decorator #1132

### Changed
- @postConstruct can target an asyncronous function #1132

## [5.1.1] - 2021-04-25
-Fix pre-publish for build artifacts

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ Let's take a look to the InversifyJS features!
- [Auto factory](https://github.com/inversify/InversifyJS/blob/master/wiki/auto_factory.md)
- [Injecting a Provider (asynchronous Factory)](https://github.com/inversify/InversifyJS/blob/master/wiki/provider_injection.md)
- [Activation handler](https://github.com/inversify/InversifyJS/blob/master/wiki/activation_handler.md)
- [Deactivation handler](https://github.com/inversify/InversifyJS/blob/master/wiki/deactivation_handler.md)
- [Post Construct decorator](https://github.com/inversify/InversifyJS/blob/master/wiki/post_construct.md)
- [Middleware](https://github.com/inversify/InversifyJS/blob/master/wiki/middleware.md)
- [Multi-injection](https://github.com/inversify/InversifyJS/blob/master/wiki/multi_injection.md)
Expand Down
16 changes: 5 additions & 11 deletions src/annotation/post_construct.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
import * as ERRORS_MSGS from "../constants/error_msgs";
import * as METADATA_KEY from "../constants/metadata_keys";
import { Metadata } from "../planning/metadata";
import { propertyEventDecorator } from "./property_event_decorator";

function postConstruct() {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const metadata = new Metadata(METADATA_KEY.POST_CONSTRUCT, propertyKey);

if (Reflect.hasOwnMetadata(METADATA_KEY.POST_CONSTRUCT, target.constructor)) {
throw new Error(ERRORS_MSGS.MULTIPLE_POST_CONSTRUCT_METHODS);
}
Reflect.defineMetadata(METADATA_KEY.POST_CONSTRUCT, metadata, target.constructor);
};
}
const postConstruct = propertyEventDecorator(
METADATA_KEY.POST_CONSTRUCT,
ERRORS_MSGS.MULTIPLE_POST_CONSTRUCT_METHODS,
);

export { postConstruct };
10 changes: 10 additions & 0 deletions src/annotation/pre_destroy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as ERRORS_MSGS from "../constants/error_msgs";
import * as METADATA_KEY from "../constants/metadata_keys";
import { propertyEventDecorator } from "./property_event_decorator";

const preDestroy = propertyEventDecorator(
METADATA_KEY.PRE_DESTROY,
ERRORS_MSGS.MULTIPLE_PRE_DESTROY_METHODS,
);

export { preDestroy };
16 changes: 16 additions & 0 deletions src/annotation/property_event_decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Metadata } from "../planning/metadata";

function propertyEventDecorator(eventKey: string, errorMessage: string) {
return () => {
return (target: any, propertyKey: string) => {
const metadata = new Metadata(eventKey, propertyKey);

if (Reflect.hasOwnMetadata(eventKey, target.constructor)) {
throw new Error(errorMessage);
}
Reflect.defineMetadata(eventKey, metadata, target.constructor);
}
}
}

export { propertyEventDecorator }
11 changes: 8 additions & 3 deletions src/bindings/binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { id } from "../utils/id";
class Binding<T> implements interfaces.Binding<T> {

public id: number;
public moduleId: string;
tonyhallett marked this conversation as resolved.
Show resolved Hide resolved
public moduleId: interfaces.ContainerModuleBase["id"];

// Determines weather the bindings has been already activated
// The activation action takes place when an instance is resolved
Expand All @@ -22,7 +22,7 @@ class Binding<T> implements interfaces.Binding<T> {
public cache: T | null;

// Cache used to allow BindingType.DynamicValue bindings
public dynamicValue: ((context: interfaces.Context) => T) | null;
public dynamicValue: interfaces.DynamicValue<T> | null;

// The scope mode to be used
public scope: interfaces.BindingScope;
Expand All @@ -40,7 +40,10 @@ class Binding<T> implements interfaces.Binding<T> {
public constraint: (request: interfaces.Request) => boolean;

// On activation handler (invoked just before an instance is added to cache and injected)
public onActivation: ((context: interfaces.Context, injectable: T) => T) | null;
public onActivation: interfaces.BindingActivation<T> | null;

// On deactivation handler (invoked just before an instance is unbinded and removed from container)
public onDeactivation: interfaces.BindingDeactivation<T> | null;

public constructor(serviceIdentifier: interfaces.ServiceIdentifier<T>, scope: interfaces.BindingScope) {
this.id = id();
Expand All @@ -54,6 +57,7 @@ class Binding<T> implements interfaces.Binding<T> {
this.factory = null;
this.provider = null;
this.onActivation = null;
this.onDeactivation = null;
this.dynamicValue = null;
}

Expand All @@ -68,6 +72,7 @@ class Binding<T> implements interfaces.Binding<T> {
clone.provider = this.provider;
clone.constraint = this.constraint;
clone.onActivation = this.onActivation;
clone.onDeactivation = this.onDeactivation;
clone.cache = this.cache;
return clone;
}
Expand Down
16 changes: 11 additions & 5 deletions src/constants/error_msgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export const INVALID_BINDING_TYPE = "Invalid binding type:";
export const NO_MORE_SNAPSHOTS_AVAILABLE = "No snapshot available to restore.";
export const INVALID_MIDDLEWARE_RETURN = "Invalid return type in middleware. Middleware must return!";
export const INVALID_FUNCTION_BINDING = "Value provided to function binding must be a function!";
export const LAZY_IN_SYNC = (key: unknown) => `You are attempting to construct '${key}' in a synchronous way
but it has asynchronous dependencies.`;

export const INVALID_TO_SELF_VALUE = "The toSelf function can only be applied when a constructor is " +
"used as service identifier";
Expand All @@ -39,11 +41,15 @@ export const CONTAINER_OPTIONS_INVALID_AUTO_BIND_INJECTABLE = "Invalid Container
export const CONTAINER_OPTIONS_INVALID_SKIP_BASE_CHECK = "Invalid Container option. Skip base check must " +
"be a boolean";

export const MULTIPLE_PRE_DESTROY_METHODS = "Cannot apply @preDestroy decorator multiple times in the same class";
export const MULTIPLE_POST_CONSTRUCT_METHODS = "Cannot apply @postConstruct decorator multiple times in the same class";
export const POST_CONSTRUCT_ERROR = (...values: any[]) => `@postConstruct error in class ${values[0]}: ${values[1]}`;

export const CIRCULAR_DEPENDENCY_IN_FACTORY = (...values: any[]) => "It looks like there is a circular dependency " +
`in one of the '${values[0]}' bindings. Please investigate bindings with` +
`service identifier '${values[1]}'.`;
export const ASYNC_UNBIND_REQUIRED = "Attempting to unbind dependency with asynchronous destruction (@preDestroy or onDeactivation)";
export const POST_CONSTRUCT_ERROR = (clazz: string, errorMessage: string) => `@postConstruct error in class ${clazz}: ${errorMessage}`;
export const PRE_DESTROY_ERROR = (clazz: string, errorMessage: string) => `@preDestroy error in class ${clazz}: ${errorMessage}`;
export const ON_DEACTIVATION_ERROR = (clazz: string, errorMessage: string) => `onDeactivation() error in class ${clazz}: ${errorMessage}`;

export const CIRCULAR_DEPENDENCY_IN_FACTORY = (factoryType: string, serviceIdentifier: string) =>
`It looks like there is a circular dependency in one of the '${factoryType}' bindings. Please investigate bindings with` +
`service identifier '${serviceIdentifier}'.`;

export const STACK_OVERFLOW = "Maximum call stack size exceeded";
3 changes: 3 additions & 0 deletions src/constants/metadata_keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ export const DESIGN_PARAM_TYPES = "design:paramtypes";
// used to identify postConstruct functions
export const POST_CONSTRUCT = "post_construct";

// used to identify preDestroy functions
export const PRE_DESTROY = "pre_destroy";

function getNonCustomTagKeys(): string[] {
return [
INJECT_TAG,
Expand Down
Loading