npm package: @nestling/context
Description: Context Module for NestJS
Author: Rob Halff
Latest version: 1.8.1

# Context module for NestJS

Conventional context module.

Use it to store context about the application.

## Setup

Global Context

```typescript
import { ContextModule } from '@nestling/context'

@Module({
  imports: [
    ContextModule
  ]
})
export class ApplicationModule {}

@Component()
export class MyMiddleware {
  constructor(
    private context: ContextService
  ) {}
  
  someMethod() {
    this.context.set('someGlobalContext', ...)
  }
}

@Component()
export class MyService {
  constructor(
    private context: ContextService
  ) {}
  
  someMethod() {
    if (this.context.has('someGlobalContext')) {
      this.context.get('someGlobalContext')
      ...
    }
  }
}
```

## Per Request / Response Context

First make sure the ContextModule is imported, it will automatically define a ContextModel
on each request / response pair, this is done internally by the ContextInterceptor.

The context is shared among request & response, representing the same context instance.

```typescript
imports: [
  ContextModule 
]
```

### Functions

The context can be retrieved from either the request or the response.

```
 request.context.set('prop', value')
 request.context.get('prop'')
 request.context.has('prop'')
 
 response.context.set('prop', value')
 response.context.get('prop'')
 response.context.has('prop'')
```

Convenience functions are also available:
```typescript
import {
  hasContext,
  getContext,
  setContext
} from '@nestling/context'

// sets .context on request
setContext('jwt', decoded, request)

// additional functions:
hasContext('jwt', request)
getContext<ExpectedType>('jwt', request) // ExpectedType or null
````

## @Context decorator

The `@Context` decorator can be used to retrieve context which was previously set on the request.

If `@Context()` is called with no arguments it will supply the whole context.

```
@Controller()
export class MyController {
  @Get()
  async getPosts(
    @Context('jwt') jwt,
    @Context('nested.path') nestedPath,
    @Context(['nested', 'path', 'also']) nestedPathAlso
    @Context() context
  ) {}
}
```

## Example Context Supplier

Note that although the context is set on the request, it will also be available on the response.

```typescript
import {
  CanActivate,
  Injectable,
  ExecutionContext
} from '@nestjs/common'
import { ErrorMessage } from '@nestling/errors'
import * as jwt from 'jsonwebtoken'
import { ConfigService } from '@nestling/config'
import { setContext } from '@nestling/context'

import { JWTConfig } from './types'

@Injectable()
class JsonWebtokenGuard implements CanActivate {
  constructor (
    private config: ConfigService
  ) {}

  async canActivate (executionContext: ExecutionContext): Promise<boolean> {
    const {
      jwt: {
        contextKey = 'jwt',
        secret,
        header = 'authorization'
      }
    }: JWTConfig = this.config as any

    const httpContext = executionContext.switchToHttp()
    const request = httpContext.getRequest()
    const { headers } = request

    if (typeof headers[header] === 'string') {
      const parts = headers[header].split(' ')

      if (parts[0] === 'Bearer') {
        const token = parts[1]
        const decoded: any = jwt.verify(token, secret)

        setContext(contextKey, decoded, request)

        return true
      }
    }

    throw new ErrorMessage('auth:unauthorized')
  }
}

```