diff --git a/adminforth/commands/createCustomComponent/configLoader.js b/adminforth/commands/createCustomComponent/configLoader.js index 6fb8593e..a956a56e 100644 --- a/adminforth/commands/createCustomComponent/configLoader.js +++ b/adminforth/commands/createCustomComponent/configLoader.js @@ -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 { @@ -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({...});'`); } @@ -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); } diff --git a/adminforth/commands/generateModels.js b/adminforth/commands/generateModels.js index f6ad2637..c6437788 100755 --- a/adminforth/commands/generateModels.js +++ b/adminforth/commands/generateModels.js @@ -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"; @@ -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", "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;