@addon24/eslint-config
Version:
ESLint configuration rules for WorldOfTextcraft projects - Centralized configuration for all project types
152 lines (140 loc) • 5.83 kB
JavaScript
export default {
meta: {
type: "problem",
docs: {
description: "Forbid direct usage of import.meta.env, use ConfigProvider instead",
category: "Best Practices",
recommended: true,
},
fixable: "code",
schema: [],
messages: {
noImportMetaEnv: "Direct usage of import.meta.env is forbidden. Use ConfigProvider methods instead to ensure proper validation and error handling.",
},
},
create (context) {
let hasConfigProviderImport = false;
return {
ImportDeclaration (node) {
// Check if ConfigProvider is already imported
if (node.source.value.includes("ConfigProvider")) {
hasConfigProviderImport = true;
}
},
MemberExpression (node) {
if (
node.object &&
node.object.type === "MetaProperty" &&
node.object.meta &&
node.object.meta.name === "import" &&
node.object.property &&
node.object.property.name === "meta" &&
node.property &&
node.property.name === "env"
) {
context.report({
node,
messageId: "noImportMetaEnv",
fix (fixer) {
const fixes = [];
// Add ConfigProvider import if not present
if (!hasConfigProviderImport) {
const program = context.getSourceCode().ast;
const lastImport = program.body.filter(n => n.type === "ImportDeclaration").slice(-1)[0] || null;
if (lastImport) {
fixes.push(
fixer.insertTextAfter(
lastImport,
'\nimport { ConfigProvider } from "@/config/ConfigProvider";'
)
);
} else {
fixes.push(
fixer.insertTextBeforeRange([0, 0], 'import { ConfigProvider } from "@/config/ConfigProvider";\n')
);
}
}
// Check if this is accessing a specific environment variable
const parent = node.parent;
if (parent && parent.type === "MemberExpression" && parent.property) {
const rawName = parent.property.name || parent.property.value;
const toCamel = (name) => {
const lower = String(name).toLowerCase();
if (lower === "node_env") return "NodeEnv";
if (lower === "db_host") return "DbHost";
if (lower === "db_port") return "DbPort";
if (lower === "db_timeout") return "DbTimeout";
if (lower === "database_url" || lower === "db_url") return "DatabaseUrl";
if (lower === "log_level") return "LogLevel";
if (lower === "api_url") return "ApiUrl";
if (lower === "secret_key") return "SecretKey";
if (lower === "primary_db_url") return "PrimaryDbUrl";
if (lower === "replica_db_url") return "ReplicaDbUrl";
if (lower === "redis_url") return "RedisUrl";
if (lower === "redis_ttl") return "RedisTtl";
const parts = String(name).split(/[_-]+/);
return parts.map((p, i) => i === 0 ? p.charAt(0).toUpperCase() + p.slice(1).toLowerCase() : p.charAt(0).toUpperCase() + p.slice(1).toLowerCase()).join("");
};
const envVarName = toCamel(rawName);
if (envVarName) {
// Convert to ConfigProvider method call
const methodName = `get${envVarName}`;
fixes.push(fixer.replaceText(parent, `ConfigProvider.${methodName}()`));
} else {
// Fallback: replace with generic ConfigProvider call
fixes.push(fixer.replaceText(node, "ConfigProvider"));
}
} else {
// Replace the entire import.meta.env with ConfigProvider
fixes.push(fixer.replaceText(node, "ConfigProvider"));
}
return fixes;
},
});
}
},
CallExpression (node) {
if (
node.callee &&
node.callee.type === "MemberExpression" &&
node.callee.object &&
node.callee.object.type === "MetaProperty" &&
node.callee.object.meta &&
node.callee.object.meta.name === "import" &&
node.callee.object.property &&
node.callee.object.property.name === "meta" &&
node.callee.property &&
node.callee.property.name === "env"
) {
context.report({
node,
messageId: "noImportMetaEnv",
fix (fixer) {
const fixes = [];
// Add ConfigProvider import if not present
if (!hasConfigProviderImport) {
const program = context.getSourceCode().ast;
const lastImport = program.body.filter(n => n.type === "ImportDeclaration").slice(-1)[0] || null;
if (lastImport) {
fixes.push(
fixer.insertTextAfter(
lastImport,
'\nimport { ConfigProvider } from "@/config/ConfigProvider";'
)
);
} else {
fixes.push(
fixer.insertTextBeforeRange([0, 0], 'import { ConfigProvider } from "@/config/ConfigProvider";\n')
);
}
}
// Replace the call with ConfigProvider
fixes.push(fixer.replaceText(node.callee, "ConfigProvider"));
return fixes;
},
});
}
},
};
},
};