Skip to content

Commit

Permalink
feat: Add decorator for deregistration of injectables
Browse files Browse the repository at this point in the history
  • Loading branch information
Iku-turso committed Apr 7, 2022
1 parent 8681a6e commit 1192484
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 18 deletions.
2 changes: 2 additions & 0 deletions packages/injectable/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import lifecycleEnum from './src/dependency-injection-container/lifecycleEnum';
import createContainer, {
injectionDecoratorToken,
registrationDecoratorToken,
deregistrationDecoratorToken,
} from './src/dependency-injection-container/createContainer';

export {
Expand All @@ -16,6 +17,7 @@ export {
getInjectionToken,
injectionDecoratorToken,
registrationDecoratorToken,
deregistrationDecoratorToken,
injectionTokenSymbol,
lifecycleEnum,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import getInjectable from '../getInjectable/getInjectable';
import { createContainer } from '../../index';
import { deregistrationDecoratorToken } from './createContainer';

describe('createContainer.decoration-of-deregistration', () => {
describe('given there is decorator for deregistration, when an injectable is deregistered, ', () => {
let someInjectable;
let di;
let deregisterDecoratorMock;

beforeEach(() => {
di = createContainer();

deregisterDecoratorMock = jest.fn();

const someDeregistrationDecorator = getInjectable({
id: 'some-deregistration-decorator',

instantiate: () => () => deregisterDecoratorMock,

injectionToken: deregistrationDecoratorToken,
});

someInjectable = getInjectable({
id: 'some-injectable',
instantiate: () => 'irrelevant',
});

di.register(someDeregistrationDecorator);
di.register(someInjectable);
});

it('when the injectable is deregistered, calls decorator with injectable', () => {
di.deregister(someInjectable);

expect(deregisterDecoratorMock).toHaveBeenCalledWith(someInjectable);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ export default () => {
nonDecoratedPrivateInjectMany,
);

const withDeregistrationDecorators = withDeregistrationDecoratorsFor(
nonDecoratedPrivateInjectMany,
);

const nonDecoratedRegister = (...externalInjectables) => {
externalInjectables.forEach(externalInjectable => {
if (!externalInjectable.id) {
Expand Down Expand Up @@ -131,31 +135,33 @@ export default () => {
injectableMap.get(injectable.id).clear();
};

const nonDecoratedDeregister = (...aliases) => {
aliases.forEach(alias => {
if (!injectableMap.has(alias.id)) {
throw new Error(
`Tried to deregister non-registered injectable "${alias.id}".`,
);
}

purgeInstances(alias);

injectables = pipeline(injectables, reject(isRelatedTo(alias)));

overridingInjectables = pipeline(
overridingInjectables,
reject(isRelatedTo(alias)),
);
});
};

const privateDi = {
inject: decoratedPrivateInject,

injectMany: decoratedPrivateInjectMany,

register: withRegistrationDecorators(nonDecoratedRegister),

deregister: (...aliases) => {
aliases.forEach(alias => {
if (!injectableMap.has(alias.id)) {
throw new Error(
`Tried to deregister non-registered injectable "${alias.id}".`,
);
}

purgeInstances(alias);

injectables = pipeline(injectables, reject(isRelatedTo(alias)));

overridingInjectables = pipeline(
overridingInjectables,
reject(isRelatedTo(alias)),
);
});
},
deregister: withDeregistrationDecorators(nonDecoratedDeregister),

override: (alias, instantiateStub) => {
const originalInjectable = pipeline(
Expand Down Expand Up @@ -312,6 +318,11 @@ export const registrationDecoratorToken = getInjectionToken({
decorable: false,
});

export const deregistrationDecoratorToken = getInjectionToken({
id: 'deregistration-decorator-token',
decorable: false,
});

export const instantiationDecoratorToken = getInjectionToken({
id: 'instantiate-decorator-token',
decorable: false,
Expand All @@ -331,6 +342,15 @@ const withRegistrationDecoratorsFor =
pipeline(toBeDecorated, ...decorators)(...injectables);
};

const withDeregistrationDecoratorsFor =
injectMany =>
toBeDecorated =>
(...injectables) => {
const decorators = injectMany(deregistrationDecoratorToken);

pipeline(toBeDecorated, ...decorators)(...injectables);
};

const withInstantiationDecoratorsFor = ({ injectMany, injectable }) => {
const isRelevantDecorator = isRelevantDecoratorFor(injectable);

Expand Down

0 comments on commit 1192484

Please sign in to comment.