From 7b9dcd29d4de04c97b6293850076f0857e1cf5a6 Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Mon, 13 Oct 2025 09:31:58 +0300 Subject: [PATCH 1/3] fix: refactor model generation for generate-models command to use callTsProxy --- adminforth/commands/generateModels.js | 40 +++++++++++++++++---------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/adminforth/commands/generateModels.js b/adminforth/commands/generateModels.js index f6ad2637a..018c67cd2 100755 --- a/adminforth/commands/generateModels.js +++ b/adminforth/commands/generateModels.js @@ -2,6 +2,7 @@ import fs from "fs"; import path from "path"; import { toPascalCase, mapToTypeScriptType, getInstance } from "./utils.js"; import dotenv from "dotenv"; +import { callTsProxy } from "./callTsProxy.js"; const envFileArg = process.argv.find((arg) => arg.startsWith("--env-file=")); const envFilePath = envFileArg ? envFileArg.split("=")[1] : ".env"; @@ -25,28 +26,40 @@ 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) => { + for (const resource of instance.config.resources) { 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 typeName = toPascalCase(resource.resourceId); + + const tsCode = ` + export async function exec() { + const columns = ${JSON.stringify(resource.columns)}; + const typeName = "${typeName}"; + function mapToTypeScriptType(type) { + const map = { "int": "number", "varchar": "string", "boolean": "boolean" }; + 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\`; + } + } + typeStr += "}\\n\\n"; + return typeStr; } - }); - modelContent += `}\n\n`; + `; + + const result = await callTsProxy(tsCode); + modelContent += result; } - }); + }; } } } @@ -55,7 +68,6 @@ async function generateModels() { 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; From 28ed53f045c2cf82d92a3aa994fb55f803957cee Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Tue, 14 Oct 2025 18:13:54 +0300 Subject: [PATCH 2/3] fix: refactor config loading and model generation to use getAdminInstance --- .../createCustomComponent/configLoader.js | 16 ++++- adminforth/commands/generateModels.js | 60 +++++++++---------- 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/adminforth/commands/createCustomComponent/configLoader.js b/adminforth/commands/createCustomComponent/configLoader.js index 6fb8593e4..878b99edb 100644 --- a/adminforth/commands/createCustomComponent/configLoader.js +++ b/adminforth/commands/createCustomComponent/configLoader.js @@ -7,16 +7,16 @@ import dotenv 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,7 +29,17 @@ export async function loadAdminForthConfig() { const configModule = _require(configPath); const adminInstance = configModule.admin || configModule.default?.admin; + return adminInstance; + } catch (error) { + console.error(chalk.red(`\nError loading or parsing configuration file: ${configPath}`)); + console.error(error); + return null; + } +} +export async function loadAdminForthConfig() { + try { + const adminInstance = getAdminInstance(); 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({...});'`); diff --git a/adminforth/commands/generateModels.js b/adminforth/commands/generateModels.js index 018c67cd2..05603f4bb 100755 --- a/adminforth/commands/generateModels.js +++ b/adminforth/commands/generateModels.js @@ -3,6 +3,7 @@ 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"; @@ -24,44 +25,39 @@ 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; - for (const resource of instance.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 = { "int": "number", "varchar": "string", "boolean": "boolean" }; - return map[type] || "any"; - } + const instance = await getAdminInstance(); + if (instance) { + await instance.discoverDatabases(); + instanceFound = true; + for (const resource of instance.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\`; - } - } - typeStr += "}\\n\\n"; - return typeStr; + let typeStr = \`export type \${typeName} = {\\n\`; + for (const col of columns) { + if (col.name && col.type) { + typeStr += \` \${col.name}: \${mapToTypeScriptType(col.type)};\\n\`; } - `; - - const result = await callTsProxy(tsCode); - modelContent += result; + } + typeStr += "}\\n\\n"; + return typeStr; } - }; + `; + + const result = await callTsProxy(tsCode); + modelContent += result; } - } + }; } if (!instanceFound) { From bbccede7188495f33666305395701c81a3b1991b Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Wed, 15 Oct 2025 08:56:03 +0300 Subject: [PATCH 3/3] fix: fix "adminforth component" command --- .../commands/createCustomComponent/configLoader.js | 11 ++++++----- adminforth/commands/generateModels.js | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/adminforth/commands/createCustomComponent/configLoader.js b/adminforth/commands/createCustomComponent/configLoader.js index 878b99edb..a956a56ec 100644 --- a/adminforth/commands/createCustomComponent/configLoader.js +++ b/adminforth/commands/createCustomComponent/configLoader.js @@ -2,7 +2,7 @@ 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 }); @@ -29,7 +29,7 @@ export async function getAdminInstance() { const configModule = _require(configPath); const adminInstance = configModule.admin || configModule.default?.admin; - return adminInstance; + return { adminInstance, configPath, configFileName }; } catch (error) { console.error(chalk.red(`\nError loading or parsing configuration file: ${configPath}`)); console.error(error); @@ -38,9 +38,10 @@ export async function getAdminInstance() { } export async function loadAdminForthConfig() { - try { - const adminInstance = getAdminInstance(); + + 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({...});'`); } @@ -63,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 05603f4bb..c64377889 100755 --- a/adminforth/commands/generateModels.js +++ b/adminforth/commands/generateModels.js @@ -27,11 +27,11 @@ async function generateModels() { let modelContent = "// Generated model file\n\n"; let instanceFound = false; - const instance = await getAdminInstance(); - if (instance) { - await instance.discoverDatabases(); + const { adminInstance, configPath, configFileName } = await getAdminInstance(); + if (adminInstance) { + await adminInstance.discoverDatabases(); instanceFound = true; - for (const resource of instance.config.resources) { + for (const resource of adminInstance.config.resources) { if (resource.columns) { const typeName = toPascalCase(resource.resourceId); const tsCode = `