Skip to content

Commit

Permalink
feat: Introduce decorator for registration to later permit reactive i…
Browse files Browse the repository at this point in the history
…njectMany
  • Loading branch information
Iku-turso committed Apr 6, 2022
1 parent 1cd0b12 commit 34d2667
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 21 deletions.
2 changes: 2 additions & 0 deletions packages/injectable/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import lifecycleEnum from './src/dependency-injection-container/lifecycleEnum';

import createContainer, {
injectionDecoratorToken,
registrationDecoratorToken,
} from './src/dependency-injection-container/createContainer';

export {
createContainer,
getInjectable,
getInjectionToken,
injectionDecoratorToken,
registrationDecoratorToken,
injectionTokenSymbol,
lifecycleEnum,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import getInjectable from '../getInjectable/getInjectable';
import { createContainer } from '../../index';
import { registrationDecoratorToken } from './createContainer';

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

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

const someRegistrationDecorator = getInjectable({
id: 'some-registration-decorator',

instantiate:
() =>
toBeDecorated =>
(injectable, ...args) =>
toBeDecorated(
{
...injectable,
instantiate: () => 'some-instance-from-decorator',
},

...args,
),

injectionToken: registrationDecoratorToken,
});

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

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

it('when the injectable is injected, injects instance using decorated registration', () => {
const actualInstance = di.inject(someInjectable);

expect(actualInstance).toBe('some-instance-from-decorator');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -96,34 +96,40 @@ export default (...listOfGetRequireContexts) => {
nonDecoratedPrivateInjectMany,
);

const privateDi = {
inject: decoratedPrivateInject,
const withRegistrationDecorators = withRegistrationDecoratorsFor(
nonDecoratedPrivateInjectMany,
);

injectMany: decoratedPrivateInjectMany,
const nonDecoratedRegister = externalInjectable => {
if (!externalInjectable.id) {
throw new Error('Tried to register injectable without ID.');
}

register: externalInjectable => {
if (!externalInjectable.id) {
throw new Error('Tried to register injectable without ID.');
}
if (injectables.find(matches({ id: externalInjectable.id }))) {
throw new Error(
`Tried to register multiple injectables for ID "${externalInjectable.id}"`,
);
}

if (injectables.find(matches({ id: externalInjectable.id }))) {
throw new Error(
`Tried to register multiple injectables for ID "${externalInjectable.id}"`,
);
}
const internalInjectable = {
...externalInjectable,

permitSideEffects: function () {
this.causesSideEffects = false;
},
};

const internalInjectable = {
...externalInjectable,
injectables.push(internalInjectable);

permitSideEffects: function () {
this.causesSideEffects = false;
},
};
injectableMap.set(internalInjectable.id, new Map());
};

injectables.push(internalInjectable);
const privateDi = {
inject: decoratedPrivateInject,

injectableMap.set(internalInjectable.id, new Map());
},
injectMany: decoratedPrivateInjectMany,

register: withRegistrationDecorators(nonDecoratedRegister),

override: (alias, instantiateStub) => {
const originalInjectable = pipeline(
Expand Down Expand Up @@ -295,6 +301,11 @@ const getInstance = ({
return newInstance;
};

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

export const instantiationDecoratorToken = getInjectionToken({
id: 'instantiate-decorator-token',
decorable: false,
Expand All @@ -305,6 +316,19 @@ export const injectionDecoratorToken = getInjectionToken({
decorable: false,
});

const withRegistrationDecoratorsFor =
injectMany =>
toBeDecorated =>
(injectable, ...args) => {
if (injectable.decorable === false) {
return toBeDecorated(injectable, ...args);
}

const decorators = injectMany(registrationDecoratorToken);

pipeline(toBeDecorated, ...decorators)(injectable, ...args);
};

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

Expand Down

0 comments on commit 34d2667

Please sign in to comment.