# @showroomprive/azure-appconfig

A library to use Azure App Configuration in NestJS.

It will decompose Azure App Configuration Data into an interface.

# Table of Contents
- [@showroomprive/azure-appconfig](#showroompriveazure-appconfig)
- [Table of Contents](#table-of-contents)
  - [Requirements](#requirements)
  - [Dependencies](#dependencies)
    - [Dev Dependencies](#dev-dependencies)
    - [Peer Dependencies](#peer-dependencies)
  - [Data Description](#data-description)
  - [Installation](#installation)
  - [Configuration](#configuration)
    - [**app.module.ts**](#appmodulets)
  - [Usage](#usage)
  
## Requirements

To use this library, the following requirements need to be met :

| Library Name       | Version | Description                                                                 |
|--------------------|---------|-----------------------------------------------------------------------------|
| @nestjs/common     | ^10.4.8 | Common utilities used by NestJS applications.                                |
| @nestjs/core       | ^10.0.0 | The core package of the NestJS framework.                                    |
| rxjs               | ^7.8.1  | A library for reactive programming using Observables, to make it easier to compose asynchronous or callback-based code. |
| @nestjs/config     | ^3.3.0  | A module for managing application configuration in NestJS.                  |


## Dependencies

| Dependency                  | Version  |
|-----------------------------|----------|
| @nestjs/common              | ^11.0.11 |
| @azure/app-configuration    | ^1.8.0   |
| @azure/identity             | ^4.7.0   |
| @azure/keyvault-secrets     | ^4.9.0   |
| @nestjs/config              | ^4.0.1   |
| @nestjs/core                | ^11.0.11 |
| rxjs                        | ^7.8.2   |

### Dev Dependencies

| Dependency                  | Version  |
|-----------------------------|----------|
| @types/node                 | ^22.13.9 |
| typescript                  | ^5.8.2   |

### Peer Dependencies

| Dependency                  | Version  |
|-----------------------------|----------|
| @nestjs/common              | ^11.0.11 |
| @nestjs/core                | ^11.0.11 |
| rxjs                        | ^7.8.2   |
| @nestjs/config              | ^4.0.1   |


## Data Description

The data is described like this : 

```typescript
export interface ApplicationSettings<T> {
    [key: string]: T | GeneralSettings;
    General: GeneralSettings;
    Application: T;
}
```

`General` property will have all data that can be used by any application, his prefix in Azure App Configuration is : **SRP**.

`Application` property is a configuration that will be unique for each application, his prefix in Azure App Configuration is equals to the value of `APP_CONFIG_NAME` environnement variable.

## Installation

To install the package, run:

```sh
npm install @showroomprive/azure-appconfig
```

## Configuration
To use the library, several environment variables need to be provided in a `.env` file at the root:

| Variable Name     | Description                                      |
|-------------------|--------------------------------------------------|
| APP_CONFIG_URL    | The URL of the Azure App Configuration instance. |
| ENVIRONMENT       | The current environment (e.g., dev, prod, test, local). |
| APP_CONFIG_NAME   | The name of the Azure App Configuration prefix.         |

For local developpement, the variable `ENVIRONMENT` is mandatory, we won't reach the Azure App Configuration, we use a json file that is parsed instead.

The configuration is splitted in 2 parts :
- General part (prefix in Azure App Configuration : **SRP**)
- Application part (prefix in Azure App Configuration: value of `APP_CONFIG_NAME` environnement variable)

The local configuration should be at the root of the project (near `package.json` and `.env` files):  

The file should be named : **local.config.json** : 

```json
{
    "SampleSettings": {
        "SampleSetting1": "Value1",
        "SampleSetting2": "Value2"
    },
    "SRP": {
        "InternalBasePaths": {
            "BetaWebApp": "/beta/webapp"
        }
    }
}
```
> **Warning:** This file may contain sensitive information. Ensure it is not committed to version control and is kept local to your development environment.


### **app.module.ts**

We need imports 2 modules:
- ConfigModule (global way to share configuration through the whole application)
- AzureAppconfigModule 

We need to add one provider to access the data : 
- ApplicationSettingsService

So the changes will be like that : 
```typescript
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { ConfigModule } from '@nestjs/config';
import { ApplicationSettingsService, AzureAppconfigModule } from '@showroomprive/azure-appconfig';
import { azureAppconfigLoader } from "@showroomprive/azure-appconfig/dist/azure-appconfig-loader";

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true,
        load: [
          azureAppconfigLoader
        ],
     }),
    AzureAppconfigModule],
  controllers: [AppController],
  providers: [ ApplicationSettingsService],
})
export class AppModule {}
```

## Usage

To access the data we need to use Dependency injection for the ApplicationSettingsService and then we will be able to access the General and Application properties.

For example : 
```typescript
import { Controller, Get } from '@nestjs/common';
import { ApplicationSettingsService } from '@showroomprive/azure-appconfig';
import { SampleSettings } from './models/sample-settings';
import { GeneralSettings } from '@showroomprive/azure-appconfig/dist/models/general-settings';

@Controller()
export class AppController {

  constructor(private readonly azureAppConfiguration: ApplicationSettingsService<SampleSettings>) {
  }

  @Get("general")
  getGeneralSettings(): GeneralSettings | undefined {
    return this.azureAppConfiguration.General;
  }

  @Get("application")
  getApplicationSettings(): SampleSettings | undefined {
    return this.azureAppConfiguration.Application;
  }
}
```

Where SampleSettings is an interface :
```typescript
export interface SampleSettings {
    SampleSetting1: string;
    SampleSetting2: string;
}
```

The `ApplicationSettingsService<SampleSettings>` use `ConfigService` to get the configurations and configure 2 properties, General and Application :

these 2 get the values like this :
- General : `configService.get<SampleSettings>('General')`
- Application : `configService.get<SampleSettings>('Application')`

For factory, we can access the configuration on `ConfigService` from `@nestjs/config`

There is a sample of how to do it with knex :

```typescript
import { Global, Module } from '@nestjs/common';
import Knex from 'knex';
import { Model } from 'objection';
import { ConfigService } from '@nestjs/config';
import { SampleSettings } from 'src/models/sample-settings';

@Global()
@Module({
  providers: [   
    {
      provide: 'KnexConnection',
      useFactory: async (configService : ConfigService) => {
        const config = configService.get<SampleSettings>('Application');
        const knex = Knex({
          client: 'mssql',
          connection: {
            host: config.DatabaseSettings.Host,
            user: config.DatabaseSettings.User,
            password: config.DatabaseSettings.Password,
            database: config.DatabaseSettings.Name,
            port: Number(config.DatabaseSettings.Port),
          }
        });
        Model.knex(knex);
        return knex;
      },
      inject: [ConfigService],
    },
  ],
  exports: ['KnexConnection'],
})
export class DatabaseModule {}
```