dotenv-constraint
Version:
A lightweight package to enforce constraints on environment variables in JavaScript, ensuring required variables are defined and match expected types.
148 lines • 3.82 kB
JavaScript
// src/index.ts
import fs from "fs";
import path from "path";
var validateEnv = (config) => {
var _a, _b;
const appRoot = process.cwd();
let envFile;
let envSchemaFile;
try {
envFile = fs.readFileSync(
path.join(appRoot, (_a = config == null ? void 0 : config.dotenvPath) != null ? _a : ".env"),
"utf8"
);
envSchemaFile = fs.readFileSync(
path.join(appRoot, (_b = config == null ? void 0 : config.schemaPath) != null ? _b : ".env.schema"),
"utf8"
);
} catch (error) {
return {
errors: [
{
code: "file_not_found"
}
],
success: false
};
}
const envVariables = extractEnvVariables(envFile);
const envSchema = extractEnvSchema(envSchemaFile);
const duplicateErrors = checkDuplicates(envVariables);
const undeclaredErrors = checkUndeclared(envVariables, envSchema);
const constraintErrors = checkConstraints(envVariables, envSchema);
const allErrors = [...duplicateErrors, ...undeclaredErrors, ...constraintErrors];
return {
errors: allErrors,
success: allErrors.length === 0
};
};
var extractEnvVariables = (dotenvFile) => {
const envVariables = [];
for (const line of dotenvFile.split("\n")) {
const trimmedLine = line.trim();
if (!trimmedLine || trimmedLine.startsWith("#")) {
continue;
}
if (line.includes("=")) {
const [name, value] = line.split("=");
envVariables.push({ name, value });
}
}
return envVariables;
};
var extractEnvSchema = (schemaFile) => {
const schema = [];
for (const line of schemaFile.split("\n")) {
if (line.includes("=")) {
const name = line.split("=")[0];
const optional = line.includes("#optional");
const number = line.includes("#number");
schema.push({ name, constraints: { optional, number } });
}
}
return schema;
};
var checkDuplicates = (envVariables) => {
const errors = [];
const seen = /* @__PURE__ */ new Set();
const duplicates = /* @__PURE__ */ new Set();
for (const { name } of envVariables) {
if (seen.has(name)) {
duplicates.add(name);
}
seen.add(name);
}
for (const name of duplicates) {
errors.push({
variable: name,
code: "duplicate"
});
}
return errors;
};
var checkUndeclared = (envVariables, envSchema) => {
const errors = [];
const schemaVariables = new Set(envSchema.map((s) => s.name));
for (const { name } of envVariables) {
if (!schemaVariables.has(name)) {
errors.push({
variable: name,
code: "not_in_schema"
});
}
}
return errors;
};
var checkConstraints = (envVariables, envSchema) => {
const errors = [];
for (const { name, constraints } of envSchema) {
const envVariable = envVariables.find((v) => v.name === name);
if (!envVariable && !constraints.optional) {
errors.push({
variable: name,
code: "missing"
});
} else if (envVariable) {
if (constraints.number) {
const result = isNumber(envVariable);
if (result !== true) {
errors.push(result);
}
}
if (!constraints.optional) {
const result = isRequired(envVariable);
if (result !== true) {
errors.push(result);
}
}
}
}
return errors;
};
var isRequired = (envVariable) => {
if (!envVariable.value) {
return {
variable: envVariable.name,
code: "empty"
};
}
return true;
};
var isNumber = (envVariable) => {
if (envVariable.value && isNaN(Number(envVariable.value))) {
return {
variable: envVariable.name,
code: "invalid_type",
expected: "number"
};
}
return true;
};
var index_default = {
validateEnv
};
export {
index_default as default,
validateEnv
};
//# sourceMappingURL=index.mjs.map