diff --git a/.changeset/bright-houses-enjoy.md b/.changeset/bright-houses-enjoy.md new file mode 100644 index 00000000..dfe767a8 --- /dev/null +++ b/.changeset/bright-houses-enjoy.md @@ -0,0 +1,5 @@ +--- +"@inversifyjs/core": patch +--- + +Updated `OneToManyMapStar` to fix an issue involving a deletion use case diff --git a/.changeset/eight-papayas-hide.md b/.changeset/eight-papayas-hide.md new file mode 100644 index 00000000..9ae8228e --- /dev/null +++ b/.changeset/eight-papayas-hide.md @@ -0,0 +1,5 @@ +--- +"@inversifyjs/container": patch +--- + +Updated `ActivationService` and `DeactivationService` to fix an issue involving a service deactivation edge case diff --git a/packages/container/libraries/core/src/common/models/OneToManyMapStar.spec.ts b/packages/container/libraries/core/src/common/models/OneToManyMapStar.spec.ts index a083a262..586c07d2 100644 --- a/packages/container/libraries/core/src/common/models/OneToManyMapStar.spec.ts +++ b/packages/container/libraries/core/src/common/models/OneToManyMapStar.spec.ts @@ -342,7 +342,6 @@ describe(OneToManyMapStar.name, () => { let modelFixture: unknown; let firstRelationFixture: Required; let secondRelationFixture: Required; - let oneToManyMapStar: OneToManyMapStar; beforeAll(() => { modelFixture = Symbol(); @@ -354,21 +353,24 @@ describe(OneToManyMapStar.name, () => { bar: 4, foo: firstRelationFixture[RelationKey.foo], }; - oneToManyMapStar = new OneToManyMapStar({ - bar: { - isOptional: true, - }, - foo: { - isOptional: false, - }, - }); - - oneToManyMapStar.add(modelFixture, firstRelationFixture); - oneToManyMapStar.add(modelFixture, secondRelationFixture); }); - describe('when called', () => { + describe('when called, with a value asociated to a single model', () => { + let oneToManyMapStar: OneToManyMapStar; + beforeAll(() => { + oneToManyMapStar = new OneToManyMapStar({ + bar: { + isOptional: true, + }, + foo: { + isOptional: false, + }, + }); + + oneToManyMapStar.add(modelFixture, firstRelationFixture); + oneToManyMapStar.add(modelFixture, secondRelationFixture); + oneToManyMapStar.removeByRelation( RelationKey.bar, firstRelationFixture[RelationKey.bar], @@ -409,6 +411,127 @@ describe(OneToManyMapStar.name, () => { }); }); }); + + describe('when called, with a value asociated to both models', () => { + let oneToManyMapStar: OneToManyMapStar; + + beforeAll(() => { + oneToManyMapStar = new OneToManyMapStar({ + bar: { + isOptional: true, + }, + foo: { + isOptional: false, + }, + }); + + oneToManyMapStar.add(modelFixture, firstRelationFixture); + oneToManyMapStar.add(modelFixture, secondRelationFixture); + + oneToManyMapStar.removeByRelation( + RelationKey.foo, + firstRelationFixture[RelationKey.foo], + ); + }); + + describe('when called .get()', () => { + let results: { + [TKey in RelationKey]-?: Iterable | undefined; + }; + + beforeAll(() => { + results = { + [RelationKey.bar]: oneToManyMapStar.get( + RelationKey.bar, + firstRelationFixture[RelationKey.bar], + ), + [RelationKey.foo]: oneToManyMapStar.get( + RelationKey.foo, + firstRelationFixture[RelationKey.foo], + ), + }; + }); + + it('should return expected results', () => { + const expectedResults: { + [TKey in RelationKey]-?: Iterable | undefined; + } = { + [RelationKey.bar]: undefined, + [RelationKey.foo]: undefined, + }; + + expect(results).toStrictEqual(expectedResults); + }); + }); + }); + }); + + describe('having a OneToManyMapStart with two models with the same relation', () => { + let firstModelFixture: unknown; + let secondModelFixture: unknown; + let relationFixture: Required; + + beforeAll(() => { + firstModelFixture = Symbol(); + secondModelFixture = Symbol(); + relationFixture = { + bar: 3, + foo: 'foo', + }; + }); + + describe('when called', () => { + let oneToManyMapStar: OneToManyMapStar; + + beforeAll(() => { + oneToManyMapStar = new OneToManyMapStar({ + bar: { + isOptional: true, + }, + foo: { + isOptional: false, + }, + }); + + oneToManyMapStar.add(firstModelFixture, relationFixture); + oneToManyMapStar.add(secondModelFixture, relationFixture); + + oneToManyMapStar.removeByRelation( + RelationKey.bar, + relationFixture[RelationKey.bar], + ); + }); + + describe('when called .get()', () => { + let results: { + [TKey in RelationKey]-?: Iterable | undefined; + }; + + beforeAll(() => { + results = { + [RelationKey.bar]: oneToManyMapStar.get( + RelationKey.bar, + relationFixture[RelationKey.bar], + ), + [RelationKey.foo]: oneToManyMapStar.get( + RelationKey.foo, + relationFixture[RelationKey.foo], + ), + }; + }); + + it('should return expected results', () => { + const expectedResults: { + [TKey in RelationKey]-?: Iterable | undefined; + } = { + [RelationKey.bar]: undefined, + [RelationKey.foo]: undefined, + }; + + expect(results).toStrictEqual(expectedResults); + }); + }); + }); }); }); diff --git a/packages/container/libraries/core/src/common/models/OneToManyMapStar.ts b/packages/container/libraries/core/src/common/models/OneToManyMapStar.ts index 4a8f3eaf..b6d5f874 100644 --- a/packages/container/libraries/core/src/common/models/OneToManyMapStar.ts +++ b/packages/container/libraries/core/src/common/models/OneToManyMapStar.ts @@ -40,7 +40,7 @@ export class OneToManyMapStar for (const relationKey of Reflect.ownKeys( relation, ) as (keyof TRelation)[]) { - this.#buildOrGetRelationModelSet(relationKey, relation[relationKey]).push( + this.#buildOrGetRelationModels(relationKey, relation[relationKey]).push( model, ); } @@ -93,7 +93,9 @@ export class OneToManyMapStar return; } - for (const model of models) { + const uniqueModelsSet: Set = new Set(models); + + for (const model of uniqueModelsSet) { const relations: TRelation[] | undefined = this.#modelToRelationMap.get(model); @@ -124,20 +126,20 @@ export class OneToManyMapStar return relations; } - #buildOrGetRelationModelSet( + #buildOrGetRelationModels( relationKey: TKey, relationValue: TRelation[TKey], ): TModel[] { - let modelSet: TModel[] | undefined = + let models: TModel[] | undefined = this.#relationToModelsMaps[relationKey].get(relationValue); - if (modelSet === undefined) { - modelSet = []; + if (models === undefined) { + models = []; - this.#relationToModelsMaps[relationKey].set(relationValue, modelSet); + this.#relationToModelsMaps[relationKey].set(relationValue, models); } - return modelSet; + return models; } #pushEntriesIntoMap( @@ -166,17 +168,17 @@ export class OneToManyMapStar relationKey: TKey, relationValue: TRelation[TKey], ): void { - const modelSet: TModel[] | undefined = + const relationModels: TModel[] | undefined = this.#relationToModelsMaps[relationKey].get(relationValue); - if (modelSet !== undefined) { - const index: number = modelSet.indexOf(model); + if (relationModels !== undefined) { + const index: number = relationModels.indexOf(model); if (index !== NOT_FOUND_INDEX) { - modelSet.splice(index, 1); + relationModels.splice(index, 1); } - if (modelSet.length === 0) { + if (relationModels.length === 0) { this.#relationToModelsMaps[relationKey].delete(relationValue); } }