Skip to content

Instantly share code, notes, and snippets.

@theoparis
Last active November 11, 2020 22:01
Show Gist options
  • Save theoparis/660114d3c1909151bb740296a63de598 to your computer and use it in GitHub Desktop.
Save theoparis/660114d3c1909151bb740296a63de598 to your computer and use it in GitHub Desktop.
test
import { Inject, Injectable, Optional } from "@nestjs/common";
import get from "lodash.get";
import {
CONFIGURATION_TOKEN,
VALIDATED_ENV_PROPNAME,
} from "./config.constants";
import { NoInferType } from "./types";
import Joi from "joi";
import { PrefixLogger } from "@toes/core";
import {
proxy,
ProxyStoreJSON,
ProxyStore,
} from "@sebastianspeitel/proxystore";
export abstract class ConfigService<
K extends Record<PropertyKey, unknown> = Record<PropertyKey, unknown>
> {
constructor(
protected validate: boolean,
protected internalConfig: ProxyStore<K>
) {
if (validate) {
const schema = this.getValidationSchema();
const res = schema.validate(this.internalConfig);
if (res.error)
new PrefixLogger("Config Validation").error(res.error.message);
else this.internalConfig = res.value;
}
}
abstract getValidationSchema(): Joi.ObjectSchema;
/**
* Get a configuration value (either custom configuration or process environment variable)
* based on property path (you can use dot notation to traverse nested object, e.g. "database.host").
* It returns a default value if the key does not exist.
* @param propertyPath
* @param defaultValue
*/
get<T = unknown>(propertyPath: keyof K, defaultValue?: T): T | undefined {
const splitPath = (propertyPath as string).split(".");
const processValue = get(process.env, propertyPath);
if (typeof processValue != "undefined")
return (processValue as unknown) as T;
const internalValue = this.internalConfig.get(
splitPath.splice(-1, 1),
splitPath[splitPath.length - 1]
);
return typeof internalValue === "undefined"
? defaultValue
: internalValue;
}
set<T = unknown>(propertyPath: keyof K, value: T): boolean {
const splitPath = (propertyPath as string).split(".");
return this.internalConfig.set(
splitPath.splice(-1, 1),
splitPath[splitPath.length - 1],
value
);
}
}
export interface ProxyByrdConfig {
DB_DEBUG: boolean;
DB_HOST: string;
DB_USER: string;
DB_PASS: string;
DB_NAME: string;
DB_PORT: string;
JWT_SECRET: string;
}
import { Inject, Injectable, Optional } from "@nestjs/common";
import Joi from "joi";
import {
ConfigService as NestConfigService,
Constants,
} from "@flowtr/nest-config";
import { KnexOptions, KnexOptionsFactory } from "@nestjsplus/knex";
import { join } from "path";
import { TypeOrmOptionsFactory, TypeOrmModuleOptions } from "@nestjs/typeorm";
import { User, Site, Route } from "../database/entities";
import { ProxyByrdConfig } from "../util";
import { proxy, ProxyStoreJSON } from "@sebastianspeitel/proxystore";
@Injectable()
export class ConfigService
extends NestConfigService<ProxyByrdConfig>
implements KnexOptionsFactory, TypeOrmOptionsFactory {
constructor(
@Optional()
@Inject(Constants.CONFIGURATION_TOKEN)
config: ProxyByrdConfig
) {
super(true, proxy(ProxyStoreJSON, {path: ""}));
}
// Our custom "schema"
// We supply it to the ConfigManager by extending the
// ConfigManager class and implementing the
// provideConfigSpec() method, which simply returns
// our custom schema
getValidationSchema() {
return Joi.object({
DB_HOST: {
validate: Joi.string(),
required: false,
default: "localhost",
},
DB_PORT: {
validate: Joi.number().min(1).max(65535),
required: false,
default: 27017,
},
DB_USER: {
validate: Joi.string(),
required: false,
default: "",
},
DB_PASS: {
validate: Joi.string(),
required: false,
default: "",
},
DB_NAME: {
validate: Joi.string(),
required: false,
default: "proxybyrd",
},
DB_DEBUG: {
validate: Joi.bool(),
required: false,
default: "false",
},
JWT_SECRET: {
validate: Joi.string(),
required: false,
default: "secret 1234",
},
});
}
/**
* Creates the knex database configuration
*/
createKnexOptions(): KnexOptions | Promise<KnexOptions> {
return {
client: "mongodb",
debug: this.get<boolean>("DB_DEBUG"),
connection: {
host: this.get<string>("DB_HOST"),
user: this.get<string>("DB_USER"),
password: this.get<string>("DB_PASS"),
database: this.get<string>("DB_NAME"),
port: this.get<number>("DB_PORT"),
debug: this.get<boolean>("DB_DEBUG"),
},
pool: {
min: 0,
max: 5,
},
migrations: {
directory: join(__dirname, "..", "database", "migrations"),
loadExtensions: [".js", ".ts"],
},
};
}
createTypeOrmOptions(): TypeOrmModuleOptions {
return {
type: "postgres",
host: this.get<string>("DB_HOST"),
username: this.get<string>("DB_USER"),
password: this.get<string>("DB_PASS"),
database: this.get<string>("DB_NAME"),
port: this.get<number>("DB_PORT"),
logging: this.get<boolean>("DB_DEBUG") ? ["error"] : false,
autoLoadEntities: true,
synchronize: true,
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment