Skip to content

Commit

Permalink
Merge pull request #208 from inversify/feat/add-container
Browse files Browse the repository at this point in the history
Add container
  • Loading branch information
notaphplover authored Dec 22, 2024
2 parents 4148040 + b974b17 commit 5d7bd31
Show file tree
Hide file tree
Showing 19 changed files with 1,693 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/green-beans-own.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@inversifyjs/container": minor
---

Added `Container`.
5 changes: 5 additions & 0 deletions .changeset/itchy-coins-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@inversifyjs/container": minor
---

Added `InversifyContainerError`.
5 changes: 5 additions & 0 deletions .changeset/rare-ghosts-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@inversifyjs/container": minor
---

Added `ContainerModule`.
5 changes: 5 additions & 0 deletions .changeset/witty-worms-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@inversifyjs/container": minor
---

Added `BindToFluentSyntax`.
5 changes: 4 additions & 1 deletion packages/container/libraries/container/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
"tslib": "2.8.1",
"typescript": "5.7.2"
},
"peerDependencies": {
"reflect-metadata": "~0.2.2"
},
"devEngines": {
"node": "^20.18.0",
"pnpm": "^9.12.1"
Expand Down Expand Up @@ -78,5 +81,5 @@
"test:unit:js": "pnpm run test:js --selectProjects Unit"
},
"sideEffects": false,
"version": "1.4.0"
"version": "1.0.0"
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { afterAll, beforeAll, describe, expect, it, jest } from '@jest/globals';

jest.mock('../../../binding/actions/getBindingId');
jest.mock('../actions/getBindingId');

import { ServiceIdentifier } from '@inversifyjs/common';
import {
Expand All @@ -22,8 +22,8 @@ import {
ServiceRedirectionBinding,
} from '@inversifyjs/core';

import { getBindingId } from '../../../binding/actions/getBindingId';
import { Writable } from '../../../common/models/Writable';
import { Writable } from '../../common/models/Writable';
import { getBindingId } from '../actions/getBindingId';
import {
BindInFluentSyntaxImplementation,
BindInWhenOnFluentSyntaxImplementation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import {
ServiceRedirectionBinding,
} from '@inversifyjs/core';

import { getBindingId } from '../../../binding/actions/getBindingId';
import { Writable } from '../../../common/models/Writable';
import { BindingConstraintUtils } from '../utils/BindingConstraintUtils';
import { Writable } from '../../common/models/Writable';
import { BindingConstraintUtils } from '../../container/binding/utils/BindingConstraintUtils';
import { getBindingId } from '../actions/getBindingId';
import {
BindInFluentSyntax,
BindInWhenOnFluentSyntax,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { afterAll, beforeAll, describe, expect, it, jest } from '@jest/globals';

jest.mock('@inversifyjs/reflect-metadata-utils');

import {
getReflectMetadata,
setReflectMetadata,
updateReflectMetadata,
} from '@inversifyjs/reflect-metadata-utils';

import { getContainerModuleId } from './getContainerModuleId';

describe(getContainerModuleId.name, () => {
describe('when called, and getReflectMetadata() returns undefined', () => {
let result: unknown;

beforeAll(() => {
(
getReflectMetadata as jest.Mock<typeof getReflectMetadata>
).mockReturnValueOnce(0);

result = getContainerModuleId();
});

afterAll(() => {
jest.clearAllMocks();
});

it('should call getReflectMetadata()', () => {
expect(getReflectMetadata).toHaveBeenCalledTimes(1);
expect(getReflectMetadata).toHaveBeenCalledWith(
Object,
'@inversifyjs/container/bindingId',
);
});

it('should call updateReflectMetadata()', () => {
expect(updateReflectMetadata).toHaveBeenCalledTimes(1);
expect(updateReflectMetadata).toHaveBeenCalledWith(
Object,
'@inversifyjs/container/bindingId',
expect.any(Function),
expect.any(Function),
);
});

it('should return default id', () => {
expect(result).toBe(0);
});
});

describe('when called, and getReflectMetadata() returns Number.MAX_SAFE_INTEGER', () => {
let result: unknown;

beforeAll(() => {
(
getReflectMetadata as jest.Mock<typeof getReflectMetadata>
).mockReturnValueOnce(Number.MAX_SAFE_INTEGER);

result = getContainerModuleId();
});

afterAll(() => {
jest.clearAllMocks();
});

it('should call getReflectMetadata()', () => {
expect(getReflectMetadata).toHaveBeenCalledTimes(1);
expect(getReflectMetadata).toHaveBeenCalledWith(
Object,
'@inversifyjs/container/bindingId',
);
});

it('should call setReflectMetadata()', () => {
expect(setReflectMetadata).toHaveBeenCalledTimes(1);
expect(setReflectMetadata).toHaveBeenCalledWith(
Object,
'@inversifyjs/container/bindingId',
Number.MIN_SAFE_INTEGER,
);
});

it('should return expected result', () => {
expect(result).toBe(Number.MAX_SAFE_INTEGER);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {
getReflectMetadata,
setReflectMetadata,
updateReflectMetadata,
} from '@inversifyjs/reflect-metadata-utils';

const ID_METADATA: string = '@inversifyjs/container/bindingId';

export function getContainerModuleId(): number {
const bindingId: number =
getReflectMetadata<number>(Object, ID_METADATA) ?? 0;

if (bindingId === Number.MAX_SAFE_INTEGER) {
setReflectMetadata(Object, ID_METADATA, Number.MIN_SAFE_INTEGER);
} else {
updateReflectMetadata(
Object,
ID_METADATA,
() => bindingId,
(id: number) => id + 1,
);
}

return bindingId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { beforeAll, describe, expect, it, jest } from '@jest/globals';

jest.mock('../actions/getContainerModuleId');

import { getContainerModuleId } from '../actions/getContainerModuleId';
import { ContainerModule, ContainerModuleLoadOptions } from './ContainerModule';

describe(ContainerModule.name, () => {
let containerModuleIdfixture: number;
let loadMock: jest.Mock<
(options: ContainerModuleLoadOptions) => Promise<void>
>;

beforeAll(() => {
containerModuleIdfixture = 1;
loadMock = jest.fn();

(
getContainerModuleId as jest.Mock<typeof getContainerModuleId>
).mockReturnValue(containerModuleIdfixture);
});

describe('.id', () => {
describe('when called', () => {
let result: unknown;

beforeAll(() => {
result = new ContainerModule(loadMock).id;
});

it('should return expected value', () => {
expect(result).toBe(containerModuleIdfixture);
});
});
});

describe('.load', () => {
describe('when called', () => {
let result: unknown;

beforeAll(() => {
result = new ContainerModule(loadMock).load;
});

it('should return expected value', () => {
expect(result).toBe(loadMock);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { ServiceIdentifier } from '@inversifyjs/common';
import { BindingActivation, BindingDeactivation } from '@inversifyjs/core';

import { BindToFluentSyntax } from '../../binding/models/BindingFluentSyntax';
import { getContainerModuleId } from '../actions/getContainerModuleId';
import { IsBoundOptions } from './isBoundOptions';

export interface ContainerModuleLoadOptions {
bind<T>(serviceIdentifier: ServiceIdentifier<T>): BindToFluentSyntax<T>;
isBound(
serviceIdentifier: ServiceIdentifier,
options?: IsBoundOptions,
): boolean;
onActivation<T>(
serviceIdentifier: ServiceIdentifier<T>,
activation: BindingActivation<T>,
): void;
onDeactivation<T>(
serviceIdentifier: ServiceIdentifier<T>,
deactivation: BindingDeactivation<T>,
): void;
unbind(serviceIdentifier: ServiceIdentifier): Promise<void>;
}

export class ContainerModule {
readonly #id: number;
readonly #load: (options: ContainerModuleLoadOptions) => Promise<void>;

constructor(load: (options: ContainerModuleLoadOptions) => Promise<void>) {
this.#id = getContainerModuleId();
this.#load = load;
}

public get id(): number {
return this.#id;
}

public get load(): (options: ContainerModuleLoadOptions) => Promise<void> {
return this.#load;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { GetOptionsTagConstraint, MetadataName } from '@inversifyjs/core';

export interface IsBoundOptions {
name?: MetadataName;
tag?: GetOptionsTagConstraint;
}
Loading

0 comments on commit 5d7bd31

Please sign in to comment.