//#region src/config.ts
var ConfigError = class extends Error {
	key;
	code;
	constructor(key, code) {
		super(`Configuration ${code}: ${key}`);
		this.name = "ConfigError";
		this.key = key;
		this.code = code;
	}
};
function defineConfig(schema) {
	return schema;
}
function readConfig(schema, env) {
	const output = {};
	for (const [key, field] of Object.entries(schema)) {
		const raw = env[key];
		if (raw === void 0 || raw === "") {
			if (Object.prototype.hasOwnProperty.call(field, "default")) {
				output[key] = field.default;
				continue;
			}
			if (field.optional) {
				output[key] = void 0;
				continue;
			}
			throw new ConfigError(key, "missing");
		}
		try {
			output[key] = field.parse(raw);
		} catch {
			throw new ConfigError(key, "invalid");
		}
	}
	return output;
}
function field(parse, options) {
	return {
		parse,
		...options ?? {}
	};
}
const configField = {
	string(options) {
		return field((raw) => raw, options);
	},
	number(options) {
		return field((raw) => {
			const value = Number(raw);
			if (!Number.isFinite(value)) throw new TypeError("Expected a finite number");
			return value;
		}, options);
	},
	boolean(options) {
		return field((raw) => {
			if (raw === "true") return true;
			if (raw === "false") return false;
			throw new TypeError("Expected exactly 'true' or 'false'");
		}, options);
	},
	url(options) {
		return field((raw) => new URL(raw).toString(), options);
	}
};
//#endregion
export { ConfigError, configField, defineConfig, readConfig };
