@julr/vite-plugin-validate-env
Version:
✅ Vite plugin for validating your environment variables
170 lines (166 loc) • 5.64 kB
JavaScript
// src/index.ts
import path from "path";
import { cwd } from "process";
import { createConfigLoader as createLoader } from "unconfig";
// src/ui.ts
import { cliui } from "@poppinss/cliui";
function initUi() {
return cliui({ mode: process.env.NODE_ENV === "testing" ? "raw" : "normal" });
}
// src/validators/builtin/index.ts
function errorReporter(ui, errors) {
let finalMessage = ui.colors.red("Failed to validate environment variables : \n");
for (const error of errors) {
const errorKey = `[${ui.colors.magenta(error.key)}]`;
finalMessage += `
${errorKey}:
`;
const message = error.err.message.replace(`${error.err.code}: `, "");
finalMessage += ` ${ui.colors.yellow(message)}
`;
}
return finalMessage;
}
function builtinValidation(ui, env, schema2) {
const errors = [];
const variables = [];
for (const [key, validator] of Object.entries(schema2)) {
try {
const res = validator(key, env[key]);
if (typeof res === "undefined") continue;
variables.push({ key, value: res });
} catch (err) {
errors.push({ key, err });
}
}
if (errors.length) {
throw new Error(errorReporter(ui, errors));
}
return variables;
}
// src/validators/standard/index.ts
function errorReporter2(ui, errors) {
let finalMessage = ui.colors.red("Failed to validate environment variables : \n");
for (const error of errors) {
const errorKey = `[${ui.colors.magenta(error.key)}]`;
finalMessage += `
${errorKey}:
`;
const message = `Invalid value for "${error.key}" : ${error.err.issues[0].message}`;
finalMessage += ` ${ui.colors.yellow(message)}
`;
}
return finalMessage;
}
async function standardValidation(ui, env, schema2) {
const errors = [];
const variables = [];
for (const [key, validator] of Object.entries(schema2)) {
const result = await validator["~standard"].validate(env[key]);
if (result.issues) {
errors.push({ key, err: result });
continue;
}
variables.push({ key, value: result.value });
}
if (errors.length) {
throw new Error(errorReporter2(ui, errors));
}
return variables;
}
// src/index.ts
import { schema } from "@poppinss/validator-lite";
async function loadOptions(rootDir, inlineConfig) {
let source = "env";
if (inlineConfig && "configFile" in inlineConfig && inlineConfig.configFile) {
source = inlineConfig.configFile;
}
const loader = createLoader({
sources: [{ files: source, extensions: ["ts", "cts", "mts", "js", "cjs", "mjs"] }],
cwd: rootDir,
defaults: inlineConfig
});
const result = await loader.load();
const config = result.config;
if (!config) throw new Error("Missing configuration for vite-plugin-validate-env");
return config;
}
function getNormalizedOptions(options) {
let schema2;
let validator;
const isSchemaNested = "schema" in options && "validator" in options;
if (isSchemaNested) {
schema2 = options.schema;
validator = options.validator;
} else {
validator = "builtin";
schema2 = options;
}
return { schema: schema2, validator };
}
function logVariables(ui, variables) {
ui.logger.log(`${ui.colors.cyan("[vite-plugin-validate-env]")} debug process.env content`);
for (const { key, value } of variables) {
ui.logger.log(`${ui.icons.pointer} ${ui.colors.cyan(key)}: ${value}`);
}
}
function shouldLogVariables(options) {
return "debug" in options && options.debug === true;
}
async function validateEnv(ui, config, inlineOptions) {
const { normalizePath, loadEnv } = await import("vite");
const rootDir = config.root || cwd();
const resolvedRoot = normalizePath(config.root ? path.resolve(config.root) : process.cwd());
const envDir = config.envDir ? normalizePath(path.resolve(resolvedRoot, config.envDir)) : resolvedRoot;
const env = loadEnv(config.mode, envDir, config.envPrefix);
const options = await loadOptions(rootDir, inlineOptions);
const variables = await validateAndLog(ui, env, options);
return variables;
}
async function validateAndLog(ui, env, options) {
const { schema: schema2, validator } = getNormalizedOptions(options);
const showDebug = shouldLogVariables(options);
const validate = { builtin: builtinValidation, standard: standardValidation }[validator];
try {
const variables = await validate(ui, env, schema2);
if (showDebug) logVariables(ui, variables);
return variables;
} catch (error) {
if (showDebug) {
const variables = Object.entries(schema2).map(([key]) => ({ key, value: env[key] }));
logVariables(ui, variables);
}
throw error;
}
}
var ValidateEnv = (options) => {
const ui = initUi();
return {
// @ts-expect-error - only used for testing as we need to keep each instance of the plugin unique to a test
ui: process.env.NODE_ENV === "testing" ? ui : void 0,
name: "vite-plugin-validate-env",
config: async ({ envDir, envPrefix, root }, { mode }) => {
const env = await validateEnv(ui, { envDir, envPrefix, root, mode }, options);
const define = Object.fromEntries(
env.map(({ key, value }) => [`import.meta.env.${key}`, JSON.stringify(value)])
);
return { define };
}
};
};
var loadAndValidateEnv = async (config, options) => {
const ui = initUi();
const variables = await validateEnv(ui, config, options);
for (const { key, value } of variables) {
process.env[key] = value;
}
return Object.fromEntries(variables.map(({ key, value }) => [key, value]));
};
var defineConfig = (config) => config;
export {
schema as Schema,
ValidateEnv,
defineConfig,
loadAndValidateEnv
};
//# sourceMappingURL=index.js.map