Skip to content

Commit

Permalink
Merge pull request #48 from inversify/poc/class-metadata-models
Browse files Browse the repository at this point in the history
Add Class metadata models
  • Loading branch information
notaphplover authored Oct 29, 2024
2 parents 2b16594 + f2e28fe commit c057878
Show file tree
Hide file tree
Showing 27 changed files with 1,214 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/nine-drinks-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@inversifyjs/core": minor
---

Added `ClassMetadata`.
5 changes: 5 additions & 0 deletions .changeset/sixty-emus-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@inversifyjs/core": minor
---

Added `getClassMetadata`.
4 changes: 4 additions & 0 deletions packages/container/libraries/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
"url": "https://github.com/inversify/monorepo/issues"
},
"description": "InversifyJs core package",
"dependencies": {
"@inversifyjs/common": "workspace:*",
"@inversifyjs/reflect-metadata-utils": "workspace:*"
},
"devDependencies": {
"@eslint/js": "9.13.0",
"@jest/globals": "29.7.0",
Expand Down
24 changes: 23 additions & 1 deletion packages/container/libraries/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,23 @@
export {};
import { getClassMetadata } from './metadata/calculations/getClassMetadata';
import { ClassElementMetadata } from './metadata/models/ClassElementMetadata';
import { ClassElementMetadataKind } from './metadata/models/ClassElementMetadataKind';
import { ClassMetadata } from './metadata/models/ClassMetadata';
import { ClassMetadataLifecycle } from './metadata/models/ClassMetadataLifecycle';
import { ManagedClassElementMetadata } from './metadata/models/ManagedClassElementMetadata';
import { MetadataName } from './metadata/models/MetadataName';
import { MetadataTag } from './metadata/models/MetadataTag';
import { MetadataTargetName } from './metadata/models/MetadataTargetName';
import { UnmanagedClassElementMetadata } from './metadata/models/UnmanagedClassElementMetadata';

export type {
ClassElementMetadata,
ClassMetadata,
ClassMetadataLifecycle,
ManagedClassElementMetadata,
MetadataName,
MetadataTag,
MetadataTargetName,
UnmanagedClassElementMetadata,
};

export { ClassElementMetadataKind, getClassMetadata };
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
import { beforeAll, describe, expect, it } from '@jest/globals';

import { ServiceIdentifier } from '@inversifyjs/common';

import {
INJECT_TAG,
MULTI_INJECT_TAG,
NAME_TAG,
NAMED_TAG,
OPTIONAL_TAG,
UNMANAGED_TAG,
} from '../../reflectMetadata/data/keys';
import { ClassElementMetadata } from '../models/ClassElementMetadata';
import { ClassElementMetadataKind } from '../models/ClassElementMetadataKind';
import { LegacyMetadata } from '../models/LegacyMetadata';
import { MetadataName } from '../models/MetadataName';
import { MetadataTag } from '../models/MetadataTag';
import { MetadataTargetName } from '../models/MetadataTargetName';
import { getClassElementMetadataFromLegacyMetadata } from './getClassElementMetadataFromLegacyMetadata';

describe(getClassElementMetadataFromLegacyMetadata.name, () => {
describe('having an empty metadata list', () => {
let metadataListFixture: LegacyMetadata[];

beforeAll(() => {
metadataListFixture = [];
});

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

beforeAll(() => {
try {
getClassElementMetadataFromLegacyMetadata(metadataListFixture);
} catch (error: unknown) {
result = error;
}
});

it('should throw an Error', () => {
const expectedErrorProperties: Partial<Error> = {
message: 'Expected @inject, @multiInject or @unmanaged metadata',
};

expect(result).toBeInstanceOf(Error);
expect(result).toStrictEqual(
expect.objectContaining(expectedErrorProperties),
);
});
});
});

describe('having a metadata list with unmanaged metadata', () => {
let metadataListFixture: LegacyMetadata[];

beforeAll(() => {
metadataListFixture = [
{
key: UNMANAGED_TAG,
value: true,
},
];
});

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

beforeAll(() => {
result = getClassElementMetadataFromLegacyMetadata(metadataListFixture);
});

it('should return ClassElementMetadata', () => {
const expectedClassElementMetadata: ClassElementMetadata = {
kind: ClassElementMetadataKind.unmanaged,
};

expect(result).toStrictEqual(expectedClassElementMetadata);
});
});
});

describe.each<[string, LegacyMetadata]>([
[
'inject',
{
key: INJECT_TAG,
value: Symbol(),
},
],
[
'multi inject',
{
key: MULTI_INJECT_TAG,
value: Symbol(),
},
],
])(
'having a metadata list with both unmanaged and %s metadata',
(_: string, metadata: LegacyMetadata) => {
let metadataListFixture: LegacyMetadata[];

beforeAll(() => {
metadataListFixture = [
{
key: UNMANAGED_TAG,
value: true,
},
metadata,
];
});

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

beforeAll(() => {
try {
getClassElementMetadataFromLegacyMetadata(metadataListFixture);
} catch (error: unknown) {
result = error;
}
});

it('should throw an Error', () => {
const expectedErrorProperties: Partial<Error> = {
message:
'Expected a single @inject, @multiInject or @unmanaged metadata',
};

expect(result).toBeInstanceOf(Error);
expect(result).toStrictEqual(
expect.objectContaining(expectedErrorProperties),
);
});
});
},
);

describe.each<[string, ClassElementMetadataKind, LegacyMetadata]>([
[
'inject',
ClassElementMetadataKind.singleInjection,
{
key: INJECT_TAG,
value: Symbol(),
},
],
[
'multi inject',
ClassElementMetadataKind.multipleInjection,
{
key: MULTI_INJECT_TAG,
value: Symbol(),
},
],
])(
'having a metadata list with % metadata',
(
_: string,
classElementMetadataKind: ClassElementMetadataKind,
metadata: LegacyMetadata,
) => {
let metadataListFixture: LegacyMetadata[];

beforeAll(() => {
metadataListFixture = [metadata];
});

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

beforeAll(() => {
result =
getClassElementMetadataFromLegacyMetadata(metadataListFixture);
});

it('should return ClassElementMetadata', () => {
const expectedClassElementMetadata: ClassElementMetadata = {
kind: classElementMetadataKind,
name: undefined,
optional: false,
tags: new Map(),
targetName: undefined,
value: metadata.value as ServiceIdentifier,
};

expect(result).toStrictEqual(expectedClassElementMetadata);
});
});
},
);

describe.each<[string, ClassElementMetadataKind, LegacyMetadata]>([
[
'inject',
ClassElementMetadataKind.singleInjection,
{
key: INJECT_TAG,
value: Symbol(),
},
],
[
'multi inject',
ClassElementMetadataKind.multipleInjection,
{
key: MULTI_INJECT_TAG,
value: Symbol(),
},
],
])(
'having a metadata list with % metadata',
(
_: string,
classElementMetadataKind: ClassElementMetadataKind,
metadata: LegacyMetadata,
) => {
let customTagMetadataFixture: LegacyMetadata;
let nameMetadataFixture: LegacyMetadata;
let optionalMetadataFixture: LegacyMetadata;
let targetNameMetadataFixture: LegacyMetadata;
let metadataListFixture: LegacyMetadata[];

beforeAll(() => {
customTagMetadataFixture = {
key: 'customTag',
value: 'customTagValue',
};
nameMetadataFixture = {
key: NAME_TAG,
value: 'name-fixture',
};
optionalMetadataFixture = {
key: OPTIONAL_TAG,
value: true,
};
targetNameMetadataFixture = {
key: NAMED_TAG,
value: 'target-name-fixture',
};
metadataListFixture = [
metadata,
customTagMetadataFixture,
nameMetadataFixture,
optionalMetadataFixture,
targetNameMetadataFixture,
];
});

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

beforeAll(() => {
result =
getClassElementMetadataFromLegacyMetadata(metadataListFixture);
});

it('should return ClassElementMetadata', () => {
const expectedClassElementMetadata: ClassElementMetadata = {
kind: classElementMetadataKind,
name: nameMetadataFixture.value as MetadataName,
optional: true,
tags: new Map<MetadataTag, unknown>([
[
customTagMetadataFixture.key as MetadataTag,
customTagMetadataFixture.value,
],
]),
targetName: targetNameMetadataFixture.value as MetadataTargetName,
value: metadata.value as ServiceIdentifier,
};

expect(result).toStrictEqual(expectedClassElementMetadata);
});
});
},
);
});
Loading

0 comments on commit c057878

Please sign in to comment.