fontcolor_theme
Deepkit App

Konfiguration

In Deepkit-Anwendungen können Module und Ihre Anwendung Konfigurationsoptionen haben. Eine Konfiguration kann z. B. aus Datenbank-URLs, Passwörtern, IPs usw. bestehen. Services, HTTP/RPC/CLI-Controller und Template-Funktionen können diese Konfigurationsoptionen über Dependency Injection auslesen.

Eine Konfiguration kann definiert werden, indem eine Class mit Properties definiert wird. Dies ist eine typesafe Möglichkeit, eine Konfiguration für Ihre gesamte Anwendung zu definieren, und ihre Werte werden automatisch serialisiert und validiert.

Beispiel

import { MinLength } from '@deepkit/type';
import { App } from '@deepkit/app';

class Config {
    pageTitle: string & MinLength<2> = 'Cool site';
    domain: string = 'example.com';
    debug: boolean = false;
}

const app = new App({
    config: Config
});


app.command('print-config', (config: Config) => {
    console.log('config', config);
})

app.run();
$ curl http://localhost:8080/
Hello from Cool site via example.com

Wenn kein Konfigurations-Loader verwendet wird, werden die Default-Werte verwendet. Um die Konfiguration zu ändern, können Sie entweder die app.configure({domain: 'localhost'}) Method verwenden oder einen Environment Configuration Loader benutzen.

Konfigurationswerte setzen

Standardmäßig werden keine Werte überschrieben, daher werden Default-Werte verwendet. Es gibt mehrere Möglichkeiten, Konfigurationswerte zu setzen.

  • Über app.configure({})
  • Umgebungsvariablen für jede Option
  • Umgebungsvariable via JSON
  • dotenv-Dateien

Sie können mehrere Methoden gleichzeitig verwenden, um die Konfiguration zu laden. Die Reihenfolge, in der sie aufgerufen werden, ist wichtig.

Umgebungsvariablen

Um jede Konfigurationsoption über ihre eigene Umgebungsvariable setzen zu können, verwenden Sie loadConfigFromEnv. Der Default-Prefix ist APP_, kann aber geändert werden. Außerdem lädt es automatisch .env-Dateien. Standardmäßig wird eine Uppercase-Naming-Strategie verwendet, die Sie ebenfalls ändern können.

Für Konfigurationsoptionen wie pageTitle oben können Sie APP_PAGE_TITLE="Other Title" verwenden, um den Wert zu ändern.

new App({
    config: config,
    controllers: [MyWebsite],
})
    .loadConfigFromEnv({prefix: 'APP_'})
    .run();
APP_PAGE_TITLE="Other title" ts-node app.ts server:start

JSON-Umgebungsvariable

Um mehrere Konfigurationsoptionen über eine einzelne Umgebungsvariable zu ändern, verwenden Sie loadConfigFromEnvVariable. Das erste Argument ist der Name der Umgebungsvariablen.

new App({
    config: config,
    controllers: [MyWebsite],
})
    .loadConfigFromEnvVariable('APP_CONFIG')
    .run();
APP_CONFIG='{"pageTitle": "Other title"}' ts-node app.ts server:start

DotEnv-Dateien

Um mehrere Konfigurationsoptionen über eine dotenv-Datei zu ändern, verwenden Sie loadConfigFromEnv. Das erste Argument ist entweder ein Pfad zu einer dotenv (relativ zu cwd) oder mehrere Pfade. Handelt es sich um ein Array, wird jeder Pfad ausprobiert, bis eine existierende Datei gefunden wird.

new App({
    config: config,
    controllers: [MyWebsite],
})
    .loadConfigFromEnv({envFilePath: ['production.dotenv', 'dotenv']})
    .run();
$ cat dotenv
APP_PAGE_TITLE=Other title
$ ts-node app.ts server:start

Modulkonfiguration

Jedes importierte Modul kann einen Modulnamen haben. Dieser Name wird für die oben verwendeten Konfigurationspfade benutzt.

Zum Beispiel ist beim Konfigurieren per Umgebungsvariablen der Pfad für die Option port des FrameworkModule FRAMEWORK_PORT. Alle Namen werden standardmäßig in Großbuchstaben geschrieben. Wird ein Prefix APP_ verwendet, kann der Port wie folgt geändert werden:

$ APP_FRAMEWORK_PORT=9999 ts-node app.ts server:start
2021-06-12T18:59:26.363Z [LOG] Start HTTP server, using 1 workers.
2021-06-12T18:59:26.365Z [LOG] HTTP MyWebsite
2021-06-12T18:59:26.366Z [LOG]     GET / helloWorld
2021-06-12T18:59:26.366Z [LOG] HTTP listening at http://localhost:9999/

In dotenv-Dateien wäre es ebenfalls APP_FRAMEWORK_PORT=9999.

In JSON-Umgebungsvariablen über loadConfigFromEnvVariable('APP_CONFIG') hingegen entspricht es der Struktur der eigentlichen Konfigurations-Class. framework wird zu einem Object.

$ APP_CONFIG='{"framework": {"port": 9999}}' ts-node app.ts server:start

Das funktioniert für alle Module gleich. Für die Konfigurationsoption Ihrer Anwendung (new App) ist kein Modul-Prefix erforderlich.

Konfigurationsklasse

import { MinLength } from '@deepkit/type';

export class Config {
    title!: string & MinLength<2>; //dadurch wird es erforderlich und muss angegeben werden
    host?: string;

    debug: boolean = false; //Default-Werte werden ebenfalls unterstützt
}
import { createModuleClass } from '@deepkit/app';
import { Config } from './module.config.ts';

export class MyModule extends createModuleClass({
  config: Config
}) {
}

Die Werte für die Konfigurationsoptionen können entweder im Konstruktor des Moduls, mit der .configure() Method, oder über Configuration Loader bereitgestellt werden (z. B. Environment Variable Loader).

import { MyModule } from './module.ts';

new App({
   imports: [new MyModule({title: 'Hello World'})],
}).run();

Um die Konfigurationsoptionen eines importierten Moduls dynamisch zu ändern, können Sie den process Hook verwenden. Dies ist ein guter Ort, um entweder Konfigurationsoptionen weiterzureichen oder ein importiertes Modul abhängig von der aktuellen Modulkonfiguration oder anderen Modulinstanz-Informationen einzurichten.

import { MyModule } from './module.ts';

export class MainModule extends createModuleClass({
}) {
    process() {
        this.getImportedModuleByClass(MyModule).configure({title: 'Changed'});
    }
}

Auf Anwendungsebene funktioniert es ein wenig anders:

new App({
    imports: [new MyModule({title: 'Hello World'}],
})
    .setup((module, config) => {
        module.getImportedModuleByClass(MyModule).configure({title: 'Changed'});
    })
    .run();

Wenn das Root-Anwendungsmodul aus einem regulären Modul erstellt wird, funktioniert es ähnlich wie bei regulären Modulen.

class AppModule extends createModuleClass({
}) {
    process() {
        this.getImportedModuleByClass(MyModule).configure({title: 'Changed'});
    }
}

App.fromModule(new AppModule()).run();

Konfigurationswerte lesen

Um eine Konfigurationsoption in einem Service zu verwenden, können Sie normale Dependency Injection nutzen. Es ist möglich, entweder das gesamte Konfigurations-Object, einen einzelnen Wert oder einen Teil der Konfiguration zu injizieren.

Teilmenge

Um nur eine Teilmenge der Konfigurationswerte zu injizieren, verwenden Sie den Pick Type.

import { Config } from './module.config';

export class MyService {
     constructor(private config: Pick<Config, 'title' | 'host'}) {
     }

     getTitle() {
         return this.config.title;
     }
}


//In Unit-Tests kann es wie folgt instanziiert werden
new MyService({title: 'Hello', host: '0.0.0.0'});

//oder Sie verwenden Type Aliases
type MyServiceConfig = Pick<Config, 'title' | 'host'};
export class MyService {
     constructor(private config: MyServiceConfig) {
     }
}

Einzelner Wert

Um nur einen einzelnen Wert zu injizieren, verwenden Sie den Indexzugriffsoperator.

import { Config } from './module.config';

export class MyService {
     constructor(private title: Config['title']) {
     }

     getTitle() {
         return this.title;
     }
}

Alle

Um alle Config-Werte zu injizieren, verwenden Sie die Class als Dependency.

import { Config } from './module.config';

export class MyService {
     constructor(private config: Config) {
     }

     getTitle() {
         return this.config.title;
     }
}
English中文 (Chinese)한국어 (Korean)日本語 (Japanese)Deutsch (German)