Template
1
0

feat: initial boilerplate

This commit is contained in:
2025-08-11 20:45:41 +02:00
parent d98524254f
commit 1215a98afc
148 changed files with 6935 additions and 2060 deletions

View 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);
}

View 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;
};

View 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];

View File

@@ -0,0 +1,3 @@
export * from "./libraries/args.ts";
export * from "./libraries/environment.ts";
export * from "./libraries/parsers.ts";