4bnode
Version:
4bnode is a CLI-powered backend development platform with a built-in visual dashboard to generate, manage, and test Node.js/Express APIs faster.
123 lines (109 loc) • 3.42 kB
JavaScript
import fs from "fs";
import path from "path";
export function getProjectRoot() {
return process.cwd();
}
export function listRoutes() {
const routesDir = path.join(getProjectRoot(), "src", "routes");
if (!fs.existsSync(routesDir)) {
return [];
}
return fs.readdirSync(routesDir).filter((f) => f.endsWith(".js"));
}
export function listModels() {
const modelsDir = path.join(getProjectRoot(), "src", "models");
if (!fs.existsSync(modelsDir)) {
return [];
}
return fs.readdirSync(modelsDir).filter((f) => f.endsWith(".js"));
}
function extractSchemaBlock(content) {
const marker = "new mongoose.Schema(";
const idx = content.indexOf(marker);
if (idx === -1) return null;
// Find the opening { after the marker
const braceStart = content.indexOf("{", idx + marker.length);
if (braceStart === -1) return null;
// Match balanced braces to find the outer schema object
let depth = 0;
for (let i = braceStart; i < content.length; i++) {
if (content[i] === "{") depth++;
else if (content[i] === "}") {
depth--;
if (depth === 0) return content.slice(braceStart + 1, i);
}
}
return null;
}
export function getModelSchema(modelName, { includeId = false } = {}) {
const modelFilePath = path.join(
getProjectRoot(),
"src",
"models",
modelName + ".js"
);
if (!fs.existsSync(modelFilePath)) {
return [];
}
const content = fs.readFileSync(modelFilePath, "utf8");
const schemaContent = extractSchemaBlock(content);
if (!schemaContent) {
return [];
}
const fieldRegex = /(\w+)\s*:\s*\{/g;
const fields = includeId ? ["_id"] : [];
let fieldMatch;
while ((fieldMatch = fieldRegex.exec(schemaContent)) !== null) {
fields.push(fieldMatch[1]);
}
return fields;
}
export function getModelSchemaDetailed(modelName) {
const modelFilePath = path.join(
getProjectRoot(),
"src",
"models",
modelName + ".js"
);
if (!fs.existsSync(modelFilePath)) {
return [];
}
const content = fs.readFileSync(modelFilePath, "utf8");
const schemaContent = extractSchemaBlock(content);
if (!schemaContent) return [];
const fields = [];
// Match each field block: fieldName: { type: ..., required: ..., unique: ..., default: ... }
const fieldRegex = /(\w+)\s*:\s*\{([^}]*)\}/g;
let fm;
while ((fm = fieldRegex.exec(schemaContent)) !== null) {
const name = fm[1];
const props = fm[2];
const typeMatch = props.match(/type:\s*([\w.]+)/);
const type = typeMatch
? typeMatch[1].replace("mongoose.Schema.Types.", "")
: "String";
const required = /required:\s*true/.test(props);
const unique = /unique:\s*true/.test(props);
const defaultMatch = props.match(/default:\s*(.+?)(?:,\s*\w+:|$)/);
const field = { name, type, required, unique };
if (defaultMatch) {
field.default = defaultMatch[1].trim();
}
fields.push(field);
}
return fields;
}
export function checkMongoConfig() {
const envPath = path.join(getProjectRoot(), ".env");
return (
fs.existsSync(envPath) &&
fs.readFileSync(envPath, "utf8").includes("MONGO_URI")
);
}
export function checkRoutesDir() {
return fs.existsSync(path.join(getProjectRoot(), "src", "routes"));
}
export function checkModelsExist() {
const modelsDir = path.join(getProjectRoot(), "src", "models");
return fs.existsSync(modelsDir) && fs.readdirSync(modelsDir).length > 0;
}