Skip to content

Commit

Permalink
feat: Introduce late registration
Browse files Browse the repository at this point in the history
  • Loading branch information
Iku-turso committed Mar 3, 2022
1 parent 91f7921 commit 5524f0e
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/injectable/ogre-tools-injectable.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ declare module '@ogre-tools/injectable' {
): TReturnAsPromise extends true
? Promise<TInjectionToken['template'][]>
: TInjectionToken['template'][];

register(injectable: NormalInjectable<any, any>): void;
register(injectable: InjectionTokenInjectable<any>): void;
}

type InferFromToken<T> = T extends InjectionToken<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,18 @@ export default (...listOfGetRequireContexts) => {
},

register: externalInjectable => {
if (setupsHaveBeenRan && !!externalInjectable.setup) {
throw new Error(
`Tried to register setuppable "${externalInjectable.id}" after setups have already ran.`,
);
}

if (setupsAreBeingRan && !!externalInjectable.setup) {
throw new Error(
`Tried to register setuppable "${externalInjectable.id}" during setup.`,
);
}

if (!externalInjectable.id) {
throw new Error('Tried to register injectable without ID.');
}
Expand Down Expand Up @@ -201,6 +213,8 @@ export default (...listOfGetRequireContexts) => {
},
]);
},

register: privateDi.register,
});

await pipeline(
Expand Down Expand Up @@ -347,6 +361,8 @@ const getInstance = ({
di.injectMany(alias, parameter, newContext),

context: newContext,

register: di.register,
};

const instanceKey = injectable.lifecycle.getInstanceKey(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import getDi from '../test-utils/getDiForUnitTesting';
import getInjectable from '../getInjectable/getInjectable';

describe('createContainer.late-registration', () => {
it('given injectable registered by another injectable during injection, when thus registered injectable is injected, injects', async () => {
const someInjectableForlateRegistration = getInjectable({
id: 'some-injectable-for-late-registration',

instantiate: di => {
di.register(someInjectableToBeRegisteredLate);
},
});

const someInjectableToBeRegisteredLate = getInjectable({
id: 'some-injectable-to-be-registered-late',

instantiate: () => 'some-instance',
});

const di = getDi(
someInjectableForlateRegistration,
// Notice: the injectable is not registered before late.
// someInjectableToBeRegisteredLate,
);

di.inject(someInjectableForlateRegistration);

const actual = di.inject(someInjectableToBeRegisteredLate);

expect(actual).toBe('some-instance');
});

it('given injectable registered by another injectable during setup, when thus registered injectable is injected, injects', async () => {
const someInjectableForlateRegistration = getInjectable({
id: 'some-injectable-for-late-registration',

setup: di => {
di.register(someInjectableToBeRegisteredLate);
},
});

const someInjectableToBeRegisteredLate = getInjectable({
id: 'some-injectable-to-be-registered-late',

instantiate: () => 'some-instance',
});

const di = getDi(
someInjectableForlateRegistration,
// Notice: the injectable is not registered before late.
// someInjectableToBeRegisteredLate,
);

await di.runSetups();

const actual = di.inject(someInjectableToBeRegisteredLate);

expect(actual).toBe('some-instance');
});

it('given setups are already ran, when registering a setuppable, throws', async () => {
const someSetuppableToBeRegisteredLate = getInjectable({
id: 'some-setuppable-to-be-registered-late',

setup: () => {},
});

const di = getDi();

await di.runSetups();

expect(() => {
di.register(someSetuppableToBeRegisteredLate);
}).toThrow(
'Tried to register setuppable "some-setuppable-to-be-registered-late" after setups have already ran.',
);
});

it('given setups are being ran, when a setuppable registers another setuppable, throws', async () => {
const someSetuppable = getInjectable({
id: 'some-setuppable',

setup: di => {
di.register(someSetuppableToBeRegisteredLate);
},
});

const someSetuppableToBeRegisteredLate = getInjectable({
id: 'some-setuppable-to-be-registered-late',

setup: () => {},
});

const di = getDi(someSetuppable);

return expect(di.runSetups()).rejects.toThrow(
'Tried to register setuppable "some-setuppable-to-be-registered-late" during setup.',
);
});
});

0 comments on commit 5524f0e

Please sign in to comment.