Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/bak/config.ts

Raw
import type { SettingDeclaration } from "./src/pi-ext-settings.ts";

export interface S3Config {
	endpoint: string;
	bucket: string;
	region: string;
	accessKeyId: string;
	secretAccessKey: string;
}

export interface S3ConfigResolution {
	config?: S3Config;
	missing: string[];
}

/** Non-secret S3 location; credentials stay env-only. */
export interface S3Location {
	endpoint?: string;
	bucket: string;
	region: string;
}

const DEFAULT_BUCKET = "pi-bak";
const DEFAULT_REGION = "auto";

function parseLocation(raw: unknown): string {
	const value = typeof raw === "string" ? raw.trim() : "";
	if (!value) throw new Error("expected a non-empty string");
	return value;
}

export const LOCATION_SETTINGS: {
	[K in keyof S3Location]-?: SettingDeclaration<S3Location[K]>;
} = {
	endpoint: {
		key: "bak.s3.endpoint",
		env: "PI_BAK_S3_ENDPOINT",
		parse: parseLocation,
		default: undefined,
	},
	bucket: {
		key: "bak.s3.bucket",
		env: "PI_BAK_S3_BUCKET",
		parse: parseLocation,
		default: DEFAULT_BUCKET,
	},
	region: {
		key: "bak.s3.region",
		env: "PI_BAK_S3_REGION",
		parse: parseLocation,
		default: DEFAULT_REGION,
	},
};

export function s3Config(
	env: NodeJS.ProcessEnv = process.env,
	location: S3Location = {
		endpoint: env.PI_BAK_S3_ENDPOINT?.trim(),
		bucket: env.PI_BAK_S3_BUCKET?.trim() || DEFAULT_BUCKET,
		region: env.PI_BAK_S3_REGION?.trim() || DEFAULT_REGION,
	},
): S3ConfigResolution {
	const { endpoint } = location;
	const missing = [
		...(endpoint ? [] : ["PI_BAK_S3_ENDPOINT"]),
		...(
			["PI_BAK_S3_ACCESS_KEY_ID", "PI_BAK_S3_SECRET_ACCESS_KEY"] as const
		).filter((name) => !env[name]?.trim()),
	];
	if (!endpoint || missing.length > 0) return { missing };
	return {
		missing: [],
		config: {
			...location,
			endpoint,
			accessKeyId: env.PI_BAK_S3_ACCESS_KEY_ID?.trim() ?? "",
			secretAccessKey: env.PI_BAK_S3_SECRET_ACCESS_KEY?.trim() ?? "",
		},
	};
}