Skip to content

Commit 9d2fdda

Browse files
committed
Merge branch 'next' of github.com:devforth/adminforth into dynamic-filter
2 parents 3f67dee + 0bcbabf commit 9d2fdda

File tree

139 files changed

+2813
-652
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

139 files changed

+2813
-652
lines changed

adapters/install-adapters.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env bash
2-
ADAPTERS="adminforth-completion-adapter-open-ai-chat-gpt adminforth-email-adapter-aws-ses adminforth-google-oauth-adapter adminforth-github-oauth-adapter adminforth-facebook-oauth-adapter adminforth-keycloak-oauth-adapter adminforth-microsoft-oauth-adapter adminforth-image-generation-adapter-openai adminforth-storage-adapter-amazon-s3 adminforth-storage-adapter-local"
2+
ADAPTERS="adminforth-completion-adapter-open-ai-chat-gpt adminforth-email-adapter-aws-ses adminforth-email-adapter-mailgun adminforth-google-oauth-adapter adminforth-github-oauth-adapter adminforth-facebook-oauth-adapter adminforth-keycloak-oauth-adapter adminforth-microsoft-oauth-adapter adminforth-twitch-oauth-adapter adminforth-image-generation-adapter-openai adminforth-storage-adapter-amazon-s3 adminforth-storage-adapter-local"
33

44
# for each
55
install_adapter() {

adminforth/commands/callTsProxy.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,28 @@ import { spawn } from "child_process";
33
import path from "path";
44
import fs from "fs";
55
import chalk from "chalk";
6+
import dotenv from "dotenv";
67

78
const currentFilePath = import.meta.url;
89
const currentFileFolder = path.dirname(currentFilePath).replace("file:", "");
910

1011
export function callTsProxy(tsCode, silent=false) {
1112

13+
const currentDirectory = process.cwd();
14+
const envPath = path.resolve(currentDirectory, ".env");
15+
const envLocalPath = path.resolve(currentDirectory, ".env.local");
16+
if (fs.existsSync(envLocalPath)) {
17+
dotenv.config({ path: envLocalPath, override: true });
18+
}
19+
if (fs.existsSync(envPath)) {
20+
dotenv.config({ path: envPath, override: true });
21+
}
22+
1223
process.env.HEAVY_DEBUG && console.log("🌐 Calling tsproxy with code:", path.join(currentFileFolder, "proxy.ts"));
1324
return new Promise((resolve, reject) => {
14-
const child = spawn("tsx", [
15-
path.join(currentFileFolder, "proxy.ts")
16-
]);
17-
25+
const child = spawn("tsx", [path.join(currentFileFolder, "proxy.ts")], {
26+
env: process.env,
27+
});
1828
let stdout = "";
1929
let stderr = "";
2030

adminforth/commands/cli.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import createResource from "./createResource/main.js";
1212
import chalk from "chalk";
1313
import path from "path";
1414
import fs from "fs";
15+
import { fileURLToPath } from 'url';
1516

1617
function showHelp() {
1718
console.log(
@@ -20,23 +21,30 @@ function showHelp() {
2021
chalk.green(' create-plugin') + chalk.white(' Create a plugin for your AdminForth app\n') +
2122
chalk.green(' generate-models') + chalk.white(' Generate TypeScript models from your databases\n') +
2223
chalk.green(' bundle') + chalk.white(' Bundles your AdminForth app SPA for production\n') +
23-
chalk.green(' component') + chalk.white(' Scaffold a custom Vue component\n')
24+
chalk.green(' component') + chalk.white(' Scaffold a custom Vue component\n') +
25+
chalk.green(' resource') + chalk.white(' Scaffold a custom resource\n')
2426
);
2527
}
2628

27-
function currentFileDir(importMetaUrl) {
28-
const filePath = importMetaUrl.replace("file://", "");
29+
export function currentFileDir(importMetaUrl) {
30+
const filePath = fileURLToPath(importMetaUrl);
2931
const fileDir = path.dirname(filePath);
3032
return fileDir;
3133
}
3234

33-
function showVersion() {
35+
export function getVersion() {
3436
const ADMIN_FORTH_ABSOLUTE_PATH = path.join(currentFileDir(import.meta.url), '..');
3537

3638
const package_json = JSON.parse(fs.readFileSync(path.join(ADMIN_FORTH_ABSOLUTE_PATH, 'package.json'), 'utf8'));
3739

3840
const ADMINFORTH_VERSION = package_json.version;
3941

42+
return ADMINFORTH_VERSION;
43+
}
44+
45+
function showVersion() {
46+
const ADMINFORTH_VERSION = getVersion();
47+
4048
console.log(
4149
chalk.white('AdminForth CLI version: ') +
4250
chalk.cyan.bold(ADMINFORTH_VERSION)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
ADMINFORTH_SECRET=123
22
NODE_ENV=development
3-
DATABASE_URL={{dbUrl}}
3+
DATABASE_URL={{{dbUrl}}}
44
{{#if prismaDbUrl}}
5-
PRISMA_DATABASE_URL={{prismaDbUrl}}
5+
PRISMA_DATABASE_URL={{{prismaDbUrl}}}
66
{{/if}}

adminforth/commands/createApp/templates/custom/tsconfig.json.hbs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
"compilerOptions": {
33
"baseUrl": ".",
44
"paths": {
5-
"@/": "../node_modules/adminforth/dist/spa/src/",
6-
"": "../node_modules/adminforth/dist/spa/node_modules/",
7-
"@@/*": "."
5+
"@/*": ["../node_modules/adminforth/dist/spa/src/*"],
6+
"@@/*": ["./*"]
87
}
98
}
109
}

adminforth/commands/createApp/templates/index.ts.hbs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import express from 'express';
22
import AdminForth from 'adminforth';
33
import usersResource from "./resources/adminuser.js";
4-
4+
import { fileURLToPath } from 'url';
5+
import path from 'path';
6+
57
const ADMIN_BASE_URL = '';
68

79
export const admin = new AdminForth({
@@ -55,7 +57,7 @@ export const admin = new AdminForth({
5557
],
5658
});
5759

58-
if (import.meta.url === `file://${process.argv[1]}`) {
60+
if (fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) {
5961
const app = express();
6062
app.use(express.json());
6163

adminforth/commands/createApp/templates/package.json.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
},
2323
"dependencies": {
2424
"@dotenvx/dotenvx": "^1.34.0",
25-
"adminforth": "latest",
25+
"adminforth": "{{adminforthVersion}}",
2626
"express": "latest-4"
2727
},
2828
"devDependencies": {

adminforth/commands/createApp/utils.js

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,31 @@ import { exec } from 'child_process';
1111

1212
import Handlebars from 'handlebars';
1313
import { promisify } from 'util';
14+
import { getVersion } from '../cli.js';
1415

1516
const execAsync = promisify(exec);
1617

18+
function detectAdminforthVersion() {
19+
try {
20+
const version = getVersion();
21+
22+
if (typeof version !== 'string') {
23+
throw new Error('Invalid version format');
24+
}
25+
26+
if (version.includes('next')) {
27+
return 'next';
28+
}
29+
return 'latest';
30+
} catch (err) {
31+
console.warn('⚠️ Could not detect AdminForth version, defaulting to "latest".');
32+
return 'latest';
33+
}
34+
}
35+
36+
const adminforthVersion = detectAdminforthVersion();
37+
38+
1739
export function parseArgumentsIntoOptions(rawArgs) {
1840
const args = arg(
1941
{
@@ -203,7 +225,10 @@ async function writeTemplateFiles(dirname, cwd, options) {
203225
{
204226
src: 'package.json.hbs',
205227
dest: 'package.json',
206-
data: { appName },
228+
data: {
229+
appName,
230+
adminforthVersion: adminforthVersion,
231+
},
207232
},
208233
{
209234
src: 'index.ts.hbs',
@@ -284,14 +309,22 @@ async function writeTemplateFiles(dirname, cwd, options) {
284309
}
285310

286311
async function installDependencies(ctx, cwd) {
287-
const nodeBinary = process.execPath; // Path to the Node.js binary running this script
288-
const npmPath = path.join(path.dirname(nodeBinary), 'npm'); // Path to the npm executable
312+
const isWindows = process.platform === 'win32';
289313

314+
const nodeBinary = process.execPath;
315+
const npmPath = path.join(path.dirname(nodeBinary), isWindows ? 'npm.cmd' : 'npm');
290316
const customDir = ctx.customDir;
291-
const res = await Promise.all([
292-
await execAsync(`${nodeBinary} ${npmPath} install`, { cwd, env: { PATH: process.env.PATH } }),
293-
await execAsync(`${nodeBinary} ${npmPath} install`, { cwd: customDir, env: { PATH: process.env.PATH } }),
294-
]);
317+
if (isWindows) {
318+
const res = await Promise.all([
319+
await execAsync(`npm install`, { cwd, env: { PATH: process.env.PATH } }),
320+
await execAsync(`npm install`, { cwd: customDir, env: { PATH: process.env.PATH } }),
321+
]);
322+
} else {
323+
const res = await Promise.all([
324+
await execAsync(`${nodeBinary} ${npmPath} install`, { cwd, env: { PATH: process.env.PATH } }),
325+
await execAsync(`${nodeBinary} ${npmPath} install`, { cwd: customDir, env: { PATH: process.env.PATH } }),
326+
]);
327+
}
295328
// console.log(chalk.dim(`Dependencies installed in ${cwd} and ${customDir}: \n${res[0].stdout}${res[1].stdout}`));
296329
}
297330

adminforth/commands/createCustomComponent/configUpdater.js

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ export async function updateResourceConfig(resourceId, columnName, fieldType, co
254254
}
255255

256256

257-
export async function injectLoginComponent(indexFilePath, componentPath) {
257+
export async function injectLoginComponent(indexFilePath, componentPath, injectionType) {
258258
console.log(chalk.dim(`Reading file: ${indexFilePath}`));
259259
const content = await fs.readFile(indexFilePath, 'utf-8');
260260
const ast = recast.parse(content, {
@@ -263,6 +263,7 @@ export async function injectLoginComponent(indexFilePath, componentPath) {
263263

264264
let updated = false;
265265
let injectionLine = null;
266+
let targetProperty = null;
266267

267268
recast.visit(ast, {
268269
visitNewExpression(path) {
@@ -293,20 +294,23 @@ export async function injectLoginComponent(indexFilePath, componentPath) {
293294
const loginPageInjections = getOrCreateProp(customization, 'loginPageInjections');
294295
if (!n.ObjectExpression.check(loginPageInjections)) return false;
295296

296-
let underInputsProp = loginPageInjections.properties.find(
297-
p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === 'underInputs'
297+
// Determine target property based on injection type
298+
targetProperty = injectionType === 'beforeLogin' ? 'panelHeader' : 'underInputs';
299+
300+
let targetProp = loginPageInjections.properties.find(
301+
p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === targetProperty
298302
);
299303

300-
if (underInputsProp) {
301-
const currentVal = underInputsProp.value;
302-
injectionLine = underInputsProp.loc?.start.line ?? null;
304+
if (targetProp) {
305+
const currentVal = targetProp.value;
306+
injectionLine = targetProp.loc?.start.line ?? null;
303307
if (n.StringLiteral.check(currentVal)) {
304308
if (currentVal.value !== componentPath) {
305-
underInputsProp.value = b.arrayExpression([
309+
targetProp.value = b.arrayExpression([
306310
b.stringLiteral(currentVal.value),
307311
b.stringLiteral(componentPath),
308312
]);
309-
console.log(chalk.dim(`Converted 'underInputs' to array with existing + new path.`));
313+
console.log(chalk.dim(`Converted '${targetProperty}' to array with existing + new path.`));
310314
} else {
311315
console.log(chalk.dim(`Component path already present as string. Skipping.`));
312316
}
@@ -316,26 +320,26 @@ export async function injectLoginComponent(indexFilePath, componentPath) {
316320
);
317321
if (!exists) {
318322
currentVal.elements.push(b.stringLiteral(componentPath));
319-
console.log(chalk.dim(`Appended new component path to existing 'underInputs' array.`));
323+
console.log(chalk.dim(`Appended new component path to existing '${targetProperty}' array.`));
320324
} else {
321325
console.log(chalk.dim(`Component path already present in array. Skipping.`));
322326
}
323327
} else {
324-
console.warn(chalk.yellow(`⚠️ 'underInputs' is not a string or array. Skipping.`));
328+
console.warn(chalk.yellow(`⚠️ '${targetProperty}' is not a string or array. Skipping.`));
325329
return false;
326330
}
327331
} else {
328332
const newProperty = b.objectProperty(
329-
b.identifier('underInputs'),
330-
b.stringLiteral(componentPath)
331-
);
332-
333-
if (newProperty.loc) {
334-
console.log(chalk.dim(`Adding 'underInputs' at line: ${newProperty.loc.start.line}`));
335-
}
336-
337-
loginPageInjections.properties.push(newProperty);
338-
console.log(chalk.dim(`Added 'underInputs': ${componentPath}`));
333+
b.identifier(targetProperty),
334+
b.stringLiteral(componentPath)
335+
);
336+
337+
if (newProperty.loc) {
338+
console.log(chalk.dim(`Adding '${targetProperty}' at line: ${newProperty.loc.start.line}`));
339+
}
340+
341+
loginPageInjections.properties.push(newProperty);
342+
console.log(chalk.dim(`Added '${targetProperty}': ${componentPath}`));
339343
}
340344

341345
updated = true;
@@ -353,7 +357,7 @@ export async function injectLoginComponent(indexFilePath, componentPath) {
353357
await fs.writeFile(indexFilePath, outputCode, 'utf-8');
354358
console.log(
355359
chalk.green(
356-
`✅ Successfully updated CRUD injection in resource file: ${indexFilePath}` +
360+
`✅ Successfully updated login ${targetProperty} injection in: ${indexFilePath}` +
357361
(injectionLine !== null ? `:${injectionLine}` : '')
358362
)
359363
);

adminforth/commands/createCustomComponent/fileGenerator.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ export async function generateLoginOrGlobalComponentFile(componentFileName, inje
129129
const __filename = fileURLToPath(import.meta.url);
130130
const __dirname = path.dirname(__filename);
131131
let templatePath;
132-
if (injectionType === 'afterLogin') {
132+
if (injectionType === 'afterLogin' || injectionType === 'beforeLogin') {
133133
templatePath = path.join(__dirname, 'templates', 'login', `${injectionType}.vue.hbs`);
134134
} else {
135135
templatePath = path.join(__dirname, 'templates', 'global', `${injectionType}.vue.hbs`);

0 commit comments

Comments
 (0)