On this page

Scopes

Scopes — GraphQL Modules documentation.

Scope defines a life cycle of Providers and InjectionToken. There are two kinds of scopes, Singleton and Operation, former is used by default.

Singleton

As mentioned before, Singleton scope is the default choice in GraphQL Modules. Every Service and Token is created even before the first incoming GraphQL operation and never gets destroyed (only when Node process is terminated).

import { Injectable, createModule } from 'graphql-modules'

@Injectable()
class Data {}

export const myModule = createModule({
  id: 'my-module',
  providers: [Data]
  // ...
})
import { Injectable, InjectionToken, createModule } from 'graphql-modules'

const Env = new InjectionToken<'production' | 'development'>('environment')

export const myModule = createModule({
  id: 'my-module',
  providers: [
    {
      provide: Env,
      useFactory() {
        return process.env.NODE_ENV === 'production'
          ? 'production'
          : 'development'
      }
    }
  ]
  // ...
})

Operation

All classes and values are created within the context of execution, meaning every incoming GraphQL Operation.

The Data class defined below gets instantiated for every new GraphQL operation and disposed once the operation is resolved. Operation Scope doesn’t overlap for incoming requests, so for 3 requests at a time, 3 instances of Data are created, one per each request.

To improve the performance a bit, GraphQL Modules instantiate services on demand. When Data is not called anywhere directly or indirectly by resolvers, the service is not created.

All services and tokens are destroyed right after the GraphQL execution phase.

import { Injectable, Scope, createModule } from 'graphql-modules'

@Injectable({
  scope: Scope.Operation // <- here
})
class Data {}

export const myModule = createModule({
  id: 'my-module',
  providers: [Data]
  // ...
})
import {
  Injectable,
  Scope,
  InjectionToken,
  createModule
} from 'graphql-modules'

const Env = new InjectionToken<'production' | 'development'>('environment')

export const myModule = createModule({
  id: 'my-module',
  providers: [
    {
      provide: Env,
      scope: Scope.Operation, // <- here
      useFactory() {
        return process.env.NODE_ENV === 'production'
          ? 'production'
          : 'development'
      }
    }
  ]
  // ...
})

Using Both

Directly accessing a Singleton service in an Operation scoped service is possible, but not the other way around.

With @ExecutionContext decorator, your Singleton services will be able to indirectly access Operation scoped Tokens and Services.