feat: initial boilerplate
This commit is contained in:
21
api/libraries/config/libraries/args.ts
Normal file
21
api/libraries/config/libraries/args.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { parseArgs } from "@std/cli";
|
||||
|
||||
import { Parser, toString } from "./parsers.ts";
|
||||
|
||||
export function getArgsVariable(key: string, fallback?: string): string;
|
||||
export function getArgsVariable<T extends Parser>(key: string, parse: T, fallback?: string): ReturnType<T>;
|
||||
export function getArgsVariable<T extends Parser>(key: string, parse?: T, fallback?: string): ReturnType<T> {
|
||||
if (typeof parse === "string") {
|
||||
fallback = parse;
|
||||
parse = undefined;
|
||||
}
|
||||
const flags = parseArgs(Deno.args);
|
||||
const value = flags[key];
|
||||
if (value === undefined) {
|
||||
if (fallback !== undefined) {
|
||||
return parse ? parse(fallback) : fallback;
|
||||
}
|
||||
throw new Error(`Config Exception: Missing ${key} variable in arguments`);
|
||||
}
|
||||
return parse ? parse(value) : toString(value);
|
||||
}
|
||||
79
api/libraries/config/libraries/environment.ts
Normal file
79
api/libraries/config/libraries/environment.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { load } from "@std/dotenv";
|
||||
import type { z } from "zod";
|
||||
|
||||
import { Env, Parser, toServiceEnv, toString } from "./parsers.ts";
|
||||
|
||||
const env = await load();
|
||||
|
||||
/**
|
||||
* Get an environment variable and parse it to the desired type.
|
||||
*
|
||||
* @param key - Environment key to resolve.
|
||||
* @param parse - Parser function to convert the value to the desired type. Default: `string`.
|
||||
*/
|
||||
export function getEnvironmentVariable(key: string, fallback?: string): string;
|
||||
export function getEnvironmentVariable<T extends Parser>(key: string, parse: T, fallback?: string): ReturnType<T>;
|
||||
export function getEnvironmentVariable<T extends Parser>(key: string, parse?: T, fallback?: string): ReturnType<T> {
|
||||
if (typeof parse === "string") {
|
||||
fallback = parse;
|
||||
parse = undefined;
|
||||
}
|
||||
const value = env[key] ?? Deno.env.get(key);
|
||||
if (value === undefined) {
|
||||
if (fallback !== undefined) {
|
||||
return parse ? parse(fallback) : fallback;
|
||||
}
|
||||
throw new Error(`Config Exception: Missing ${key} variable in configuration`);
|
||||
}
|
||||
return parse ? parse(value) : toString(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an environment variable, select value based on ENV map and parse it to the desired type. Can be used with simple primitives or objects / arrays
|
||||
*
|
||||
* @export
|
||||
* @param {{
|
||||
* key: string;
|
||||
* envFallback?: FallbackEnvMap;
|
||||
* fallback: string;
|
||||
* validation: z.ZodTypeAny,
|
||||
* }} options
|
||||
* @param {string} options.key - the name of the env variable
|
||||
* @param {object} options.envFallback - map with env specific fallbacks that will be used if none value provided
|
||||
* @param {string} options.envFallback.local - example "local" SERVICE_ENV target fallback value
|
||||
* @param {string} options.fallback - string fallback that will be used if no env variable found
|
||||
* @param {z.ZodTypeAny} options.validation - Zod validation object or validation primitive
|
||||
* @returns {z.infer<typeof validation>} - Returns the inferred type of the validation provided
|
||||
*/
|
||||
export function validateEnvVariable({
|
||||
key,
|
||||
envFallback,
|
||||
fallback,
|
||||
validation,
|
||||
}: {
|
||||
key: string;
|
||||
validation: z.ZodTypeAny;
|
||||
envFallback?: FallbackEnvMap;
|
||||
fallback?: string;
|
||||
}): z.infer<typeof validation> {
|
||||
const serviceEnv = getEnvironmentVariable("SERVICE_ENV", toServiceEnv, "local");
|
||||
const providedValue = env[key] ?? Deno.env.get(key);
|
||||
const fallbackValue = typeof envFallback === "object" ? (envFallback[serviceEnv] ?? fallback) : fallback;
|
||||
const toBeUsed = providedValue ?? fallbackValue;
|
||||
try {
|
||||
if (typeof toBeUsed === "string" && (toBeUsed.trim().startsWith("{") || toBeUsed.trim().startsWith("["))) {
|
||||
return validation.parse(JSON.parse(toBeUsed));
|
||||
}
|
||||
return validation.parse(toBeUsed);
|
||||
} catch (e) {
|
||||
throw new Deno.errors.InvalidData(`Config Exception: Missing valid ${key} variable in configuration`, { cause: e });
|
||||
}
|
||||
}
|
||||
|
||||
type FallbackEnvMap = Partial<Record<Env, string>> & {
|
||||
testing?: string;
|
||||
local?: string;
|
||||
stg?: string;
|
||||
demo?: string;
|
||||
prod?: string;
|
||||
};
|
||||
98
api/libraries/config/libraries/parsers.ts
Normal file
98
api/libraries/config/libraries/parsers.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
const SERVICE_ENV = ["testing", "local", "stg", "demo", "prod"] as const;
|
||||
|
||||
/**
|
||||
* Convert an variable to a string.
|
||||
*
|
||||
* @param value - Value to convert.
|
||||
*/
|
||||
export function toString(value: unknown): string {
|
||||
if (typeof value === "string") {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "number") {
|
||||
return value.toString();
|
||||
}
|
||||
throw new Error(`Config Exception: Cannot convert ${value} to string`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an variable to a number.
|
||||
*
|
||||
* @param value - Value to convert.
|
||||
*/
|
||||
export function toNumber(value: unknown): number {
|
||||
if (typeof value === "number") {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
return parseInt(value);
|
||||
}
|
||||
throw new Error(`Config Exception: Cannot convert ${value} to number`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an variable to a boolean.
|
||||
*
|
||||
* @param value - Value to convert.
|
||||
*/
|
||||
export function toBoolean(value: unknown): boolean {
|
||||
if (typeof value === "boolean") {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
return value === "true" || value === "1";
|
||||
}
|
||||
throw new Error(`Config Exception: Cannot convert ${value} to boolean`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a variable to an array of strings.
|
||||
*
|
||||
* Expects a comma seprated, eg. foo,bar,foobar
|
||||
*
|
||||
* @param value - Value to convert.
|
||||
*/
|
||||
export function toArray(value: unknown): string[] {
|
||||
if (typeof value === "string") {
|
||||
if (value === "") {
|
||||
return [];
|
||||
}
|
||||
return value.split(",");
|
||||
}
|
||||
throw new Error(`Config Exception: Cannot convert ${value} to array`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the given value is a valid SERVICE_ENV variable.
|
||||
*
|
||||
* @param value - Value to validate.
|
||||
*/
|
||||
export function toServiceEnv(value: unknown): Env {
|
||||
assertServiceEnv(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------------
|
||||
| Assertions
|
||||
|--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
function assertServiceEnv(value: unknown): asserts value is Env {
|
||||
if (typeof value !== "string") {
|
||||
throw new Error(`Config Exception: Env ${value} is not a string`);
|
||||
}
|
||||
if ((SERVICE_ENV as unknown as string[]).includes(value) === false) {
|
||||
throw new Error(`Config Exception: Invalid env ${value} provided`);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------------
|
||||
| Types
|
||||
|--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
export type Parser = (value: unknown) => any;
|
||||
|
||||
export type Env = (typeof SERVICE_ENV)[number];
|
||||
3
api/libraries/config/mod.ts
Normal file
3
api/libraries/config/mod.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from "./libraries/args.ts";
|
||||
export * from "./libraries/environment.ts";
|
||||
export * from "./libraries/parsers.ts";
|
||||
Reference in New Issue
Block a user