Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions adminforth/commands/createCustomComponent/configLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ import fs from 'fs/promises';
import path from 'path';
import chalk from 'chalk';
import jiti from 'jiti';
import dotenv from "dotenv";
import dotenv, { config } from "dotenv";

dotenv.config({ path: '.env.local', override: true });
dotenv.config({ path: '.env', override: true });

export async function loadAdminForthConfig() {
export async function getAdminInstance() {
const configFileName = 'index.ts';
const configPath = path.resolve(process.cwd(), configFileName);

console.log('Loading config from', configPath);
try {
await fs.access(configPath);
} catch (error) {
console.error(chalk.red(`\nError: Configuration file not found at ${configPath}`));
console.error(chalk.yellow(`Please ensure you are running this command from your project's root directory and the '${configFileName}' file exists.`));
process.exit(1);
return null;
}

try {
Expand All @@ -29,8 +29,19 @@ export async function loadAdminForthConfig() {
const configModule = _require(configPath);

const adminInstance = configModule.admin || configModule.default?.admin;
return { adminInstance, configPath, configFileName };
} catch (error) {
console.error(chalk.red(`\nError loading or parsing configuration file: ${configPath}`));
console.error(error);
return null;
}
}

export async function loadAdminForthConfig() {

const { adminInstance, configPath, configFileName } = await getAdminInstance();

try {
if (!adminInstance) {
throw new Error(`Could not find 'admin' export in ${configFileName}. Please ensure your config file exports the AdminForth instance like: 'export const admin = new AdminForth({...});'`);
}
Expand All @@ -53,7 +64,7 @@ export async function loadAdminForthConfig() {
return config;

} catch (error) {
console.error(chalk.red(`\nError loading or parsing configuration file: ${configPath}`));
console.error(chalk.red(`\nError loading or parsing configuration file: ${configPath}, error: ${error}`));
console.error(error);
process.exit(1);
}
Expand Down
52 changes: 30 additions & 22 deletions adminforth/commands/generateModels.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import fs from "fs";
import path from "path";
import { toPascalCase, mapToTypeScriptType, getInstance } from "./utils.js";
import dotenv from "dotenv";
import { callTsProxy } from "./callTsProxy.js";
import { getAdminInstance } from "../commands/createCustomComponent/configLoader.js";

const envFileArg = process.argv.find((arg) => arg.startsWith("--env-file="));
const envFilePath = envFileArg ? envFileArg.split("=")[1] : ".env";
Expand All @@ -23,39 +25,45 @@ async function generateModels() {
}

let modelContent = "// Generated model file\n\n";
const files = fs.readdirSync(currentDirectory);
let instanceFound = false;

for (const file of files) {
if (file.endsWith(".js") || file.endsWith(".ts")) {
const instance = await getInstance(file, currentDirectory);
if (instance) {
await instance.discoverDatabases();
instanceFound = true;
instance.config.resources.forEach((resource) => {
if (resource.columns) {
modelContent += `export type ${toPascalCase(
resource.resourceId
)} = {\n`;
resource.columns.forEach((column) => {
if (column.name && column.type) {
modelContent += ` ${column.name}: ${mapToTypeScriptType(
column.type
)};\n`;
const { adminInstance, configPath, configFileName } = await getAdminInstance();
if (adminInstance) {
await adminInstance.discoverDatabases();
instanceFound = true;
for (const resource of adminInstance.config.resources) {
if (resource.columns) {
const typeName = toPascalCase(resource.resourceId);
const tsCode = `
export async function exec() {
const columns = ${JSON.stringify(resource.columns)};
const typeName = "${typeName}";
function mapToTypeScriptType(type) {
const map = { "integer": "number", "varchar": "string", "boolean": "boolean", "date": "string", "datetime": "string", "decimal": "number", "float": "number", "json": "Record<string, any>", "text": "string", "string": "string", "time": "string" };
return map[type] || "any";
}

let typeStr = \`export type \${typeName} = {\\n\`;
for (const col of columns) {
if (col.name && col.type) {
typeStr += \` \${col.name}: \${mapToTypeScriptType(col.type)};\\n\`;
}
});
modelContent += `}\n\n`;
}
typeStr += "}\\n\\n";
return typeStr;
}
});
`;

const result = await callTsProxy(tsCode);
modelContent += result;
}
}
};
}

if (!instanceFound) {
console.error("Error: No valid instance found to generate models.");
return;
}

fs.writeFileSync(modelFilePath, modelContent, "utf-8");
console.log(`Generated TypeScript model file: ${modelFilePath}`);
return true;
Expand Down