@occupop/lib-container
TypeScript icon, indicating that this package has built-in type declarations

1.2.2 • Public • Published

Package @occupop/lib-container

This package is intended to use as a Container for Dependency Injection... making Inversion of Control: Easy, Fast, Clean and Typesafe.

This implementation wraps https://github.com/jeffijoe/awilix package! Check their docs for detailed/advanced usage.

NPM registry token required!

Install

# Yarn
yarn add @occupop/lib-container

# NPM
npm install @occupop/lib-container

# Bun
bun add @occupop/lib-container

Usage - Register

import { createTypedContainer } from '@occupop/lib-container'
//... all other imports omited... 

export const container = createTypedContainer({
    // Top-level
    graphqlServer: { asFunction: makeGraphqlServer, singleton: true },
    mongoClient: { asFunction: makeMongoClient, singleton: true },
    getMongoCollection: { asFunction: makeGetMongoCollection, singleton: true },
    // ... add .singleton() to top-level services to cache factory call 
    
    // Services
    fooService: { asFunction: makeFooService, scoped: true },
    barService: { asClass: BarService, scoped: true },
    // ... you can add .scoped() cache some lifecicle factory calls
    
    // Repositories
    fooRepository: { asFunction: makeFooRepository, singleton: true },
    barRepository: { asFunction: makeBarRepository, singleton: true },
    
    // Session scope (possible null)
    authUser: { asValue: null as AuthUser | null }, // for injecting AuthService.getUser()
    request: { asValue: null as Request | null }, // for injecting Express request
})

// typed dependencies to make inject easy...
type Deps = typeof container.cradle

Usage - Scoped register

In order to have a scoped container available in the request scope, we use to apply a context function to the server to intercept the request and create a scoped container createTypedContainerScope with request available and even the auth user ready to be used.

// context-function.ts
import { createTypedContainerScope } from '@occupop/lib-container'
//... all other imports omited... 

export function makeAuthContextFunction({ container, getAuthUser }: Deps) {
    return async (context) => {
        const authUser = await getAuthUser(context.req)
        const scopedContainer = createTypedContainerScope(container, {
            request: { asValue: context.req },
            authUser: { asValue: authUser },
        })
        return { ...context, container: scopedContainer }
    }
}

export type ScopedDeps = ReturnType<ReturnType<typeof makeAuthContextFunction>>['container']

NOTE: even having AuthUser available, NEVER require as a Service dependency! REMEMBER: all services should be able to be used from commands, queue, etc!

Usage - Creating Factories

// amazing-service.ts
import type { Deps } from '.container'

export function makeAmazingService({
   fooRepository,
   barRepository,
   randomDependencieHere,
    // ... dependencies will be type-hinted thanks to type Deps!
}: Deps) {
    return {
        foo: () => { /** ... nice and clean implementation ... */ },
        bar: () => { /** ... another clean implementation ... */ },
    }
}

Usage - Consuming

// server.ts
import { type Deps, container } from '.container'

container.build(async ({ logger, mongoClient, eventService }: Deps) => {
    await mongoClient.connect()
    logger.log('Mongo connected')
    eventService.consumer().start()
    logger.log('Worker ready!')
})

// OR ...

// server.ts
import { container } from '.container'

const { logger, mongoClient, eventService } = container.cradle
await mongoClient.connect()
logger.log('Mongo connected')
eventService.consumer().start()
logger.log('Worker ready!')

TODO

  • Improve later register to be made in the same format
  • Correct container self signature to inferred cradle type
  • Resolve circular reference from old version and keep awilix signature format

Dependencies (1)

Dev Dependencies (2)

Package Sidebar

Install

npm i @occupop/lib-container

Weekly Downloads

46

Version

1.2.2

License

none

Unpacked Size

7.76 kB

Total Files

4

Last publish

Collaborators

  • gera_occupop
  • dougoccupop
  • pauloccupop
  • lcidral
  • leonardoreiners
  • paulooccupop
  • matheus-occupop
  • kaueoccupop