Skip to content

Commit

Permalink
add allowServiceOverriding
Browse files Browse the repository at this point in the history
  • Loading branch information
Victor Mendele committed Oct 6, 2021
1 parent 96854fa commit b983322
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 5 deletions.
12 changes: 7 additions & 5 deletions packages/container/src/Implementation/Container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,20 @@ class ContainerBuilder implements ContainerBuilderInterface {
.set(LifeCycle.Singleton, new Map())
.set(LifeCycle.Transient, new Map())

private readonly allowServiceOverriding: boolean

constructor(options: CreateContainerBuilderOptions,
private readonly createProvider: (containerInterface: ContainerInterface) => SyncServiceProviderInterface = createSyncServiceProvider,
private readonly createAsyncProvider: (containerInterface: ContainerInterface) => AsyncServiceProviderInterface = createAsyncServiceProvider
) {
options.loaders.forEach(loader => loader(this))
options.loaders?.forEach(loader => loader(this))
this.allowServiceOverriding = options.allowServiceOverriding ?? false
}

addFactory<TService>(key: ServiceKey, factory: SyncServiceFactory<TService>, lifeCycle: LifeCycle): this {
if (this.isAlreadyRegistered(key))
if (this.isAlreadyRegistered(key) && !this.allowServiceOverriding)
throw new ServiceAlreadyRegisteredError(key)


this.syncFactories.get(lifeCycle)?.set(key, factory)
// this.syncFactories.set(key, {factory, lifeCycle})
return this
Expand All @@ -120,7 +122,7 @@ class ContainerBuilder implements ContainerBuilderInterface {
}

addAsyncFactory<TService>(key: ServiceKey, factory: AsyncServiceFactory<Promise<TService>>, lifeCycle: LifeCycle): this {
if (this.isAlreadyRegistered(key))
if (this.isAlreadyRegistered(key) && !this.allowServiceOverriding)
throw new ServiceAlreadyRegisteredError(key)

this.asyncFactories.get(lifeCycle)?.set(key, factory)
Expand All @@ -136,7 +138,7 @@ class ContainerBuilder implements ContainerBuilderInterface {
}
}

export type CreateContainerBuilderOptions = { loaders: ServiceLoaderInterface[] }
export type CreateContainerBuilderOptions = { loaders?: ServiceLoaderInterface[], allowServiceOverriding?: boolean }
const defaultOptions = { loaders: [] }

export const createContainerBuilder = (options: CreateContainerBuilderOptions = defaultOptions,
Expand Down
20 changes: 20 additions & 0 deletions packages/container/tests/Container.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,26 @@ it('should throw when overriding service', function () {
expect(shouldThrow4).toThrow(`Service with key "MyService" was already registered.`)
})

it('should not throw when overriding service if the allowServiceOverriding is true', async () => {
// Arrange
const builder = createContainerBuilder({ allowServiceOverriding: true })

// Act
const container = builder
.addFactory('MyService', () => 'hello', LifeCycle.Singleton)
.addFactory('MyService', () => 'world', LifeCycle.Singleton)
.addAsyncFactory('MyAsyncService', async () => 'hello', LifeCycle.Singleton)
.addAsyncFactory('MyAsyncService', async () => 'world', LifeCycle.Singleton)
.build()

const myService = container.get('MyService')
const myServiceAsync = await container.getAsync('MyAsyncService')

// Assert
expect(myService).toBe('world')
expect(myServiceAsync).toBe('world')
})

describe('services lifetime', function () {

it('should create singleton services', function () {
Expand Down

0 comments on commit b983322

Please sign in to comment.