Skip to content

Commit c1e2c3d

Browse files
authored
Merge pull request #35 from devforth/cli
improved imports
2 parents ae92372 + 5aabdee commit c1e2c3d

File tree

11 files changed

+421
-134
lines changed

11 files changed

+421
-134
lines changed

adminforth/commands/utils.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export const findInstance = (fileContent) => {
5858

5959
export async function getInstance(file, currentDirectory) {
6060
const initialFilePath = path.join(currentDirectory, file);
61-
let filePath = path.join(currentDirectory, file);
61+
let filePath = initialFilePath;
6262

6363
if (file.endsWith(".ts")) {
6464
console.log(`Compiling TypeScript file: ${file}`);
@@ -76,11 +76,26 @@ export async function getInstance(file, currentDirectory) {
7676
filePath = filePath
7777
.replace(".ts", ".js")
7878
.replace(currentDirectory, path.join(currentDirectory, "dist"));
79+
80+
try {
81+
const compiledContent = fs.readFileSync(filePath, "utf-8");
82+
const updatedContent = compiledContent.replace(
83+
/import (.+?) from ["'](.+?)["'];/g,
84+
(match, imports, modulePath) => {
85+
if (!modulePath.endsWith(".js") && (modulePath.startsWith("./") || modulePath.startsWith("../"))) {
86+
return `import ${imports} from "${modulePath}.js";`; // Append .js to local imports
87+
}
88+
return match;
89+
}
90+
);
91+
fs.writeFileSync(filePath, updatedContent, "utf-8");
92+
} catch (error) {
93+
console.error("Error during post-processing:", error);
94+
}
7995
}
8096

8197
const fileContent = fs.readFileSync(initialFilePath, "utf-8");
8298
const instanceName = findInstance(fileContent);
83-
8499
if (instanceName) {
85100
try {
86101
const module = await import(`file://${filePath}`);

cli-demo/index.ts

Lines changed: 60 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,36 @@
11
import express from 'express';
2-
import AdminForth, { AdminForthDataTypes, AdminUser, Filters } from 'adminforth';
2+
import AdminForth, { Filters } from 'adminforth';
3+
import usersResource from "./resources/users";
4+
import apartmentsResource from "./resources/apartments";
5+
import auditLogsResource from "./resources/auditLogs"
6+
7+
8+
const ADMIN_BASE_URL = '';
39

410
export const admin = new AdminForth({
5-
baseUrl: '',
11+
baseUrl : ADMIN_BASE_URL,
612
auth: {
713
usersResourceId: 'users', // resource to get user during login
814
usernameField: 'email', // field where username is stored, should exist in resource
9-
passwordHashField: 'passwordHash',
15+
passwordHashField: 'password_hash',
16+
rememberMeDays: 30, // users who will check "remember me" will stay logged in for 30 days
1017
},
1118
customization: {
1219
brandName: 'My Admin',
1320
datesFormat: 'D MMM YY',
1421
timeFormat: 'HH:mm:ss',
1522
emptyFieldPlaceholder: '-',
1623
},
17-
dataSources: [{
18-
id: 'maindb',
19-
url: `sqlite://${process.env.DATABASE_FILE}`,
20-
}],
21-
resources: [
24+
dataSources: [
2225
{
23-
dataSource: 'maindb',
24-
table: 'user',
25-
resourceId: 'users',
26-
label: 'Users',
27-
recordLabel: (r: any) => `👤 ${r.email}`,
28-
columns: [
29-
{
30-
name: 'id',
31-
primaryKey: true,
32-
fillOnCreate: () => Math.random().toString(36).substring(7),
33-
showIn: ['list', 'filter', 'show'],
34-
},
35-
{
36-
name: 'email',
37-
required: true,
38-
isUnique: true,
39-
enforceLowerCase: true,
40-
validation: [
41-
AdminForth.Utils.EMAIL_VALIDATOR,
42-
]
43-
},
44-
{
45-
name: 'createdAt',
46-
type: AdminForthDataTypes.DATETIME,
47-
showIn: ['list', 'filter', 'show'],
48-
fillOnCreate: () => (new Date()).toISOString(),
49-
},
50-
{
51-
name: 'role',
52-
enum: [
53-
{ value: 'superadmin', label: 'Super Admin' },
54-
{ value: 'user', label: 'User' },
55-
]
56-
},
57-
{
58-
name: 'password',
59-
virtual: true,
60-
required: { create: true },
61-
editingNote: { edit: 'Leave empty to keep password unchanged' },
62-
minLength: 8,
63-
type: AdminForthDataTypes.STRING,
64-
showIn: ['create', 'edit'],
65-
masked: true,
66-
},
67-
{ name: 'passwordHash', backendOnly: true, showIn: [] }
68-
],
26+
id: 'maindb',
27+
url: `sqlite://${process.env.DATABASE_FILE}`
6928
},
70-
{
71-
table: 'post',
72-
resourceId: 'posts',
73-
dataSource: 'maindb',
74-
label: 'Posts',
75-
recordLabel: (r: any) => `📝 ${r.title}`,
76-
columns: [
77-
{
78-
name: 'id',
79-
primaryKey: true,
80-
fillOnCreate: () => Math.random().toString(36).substring(7),
81-
showIn: ['list', 'filter', 'show'],
82-
},
83-
{
84-
name: 'title',
85-
type: AdminForthDataTypes.STRING,
86-
required: true,
87-
showIn: ['list', 'create', 'edit', 'filter', 'show'],
88-
maxLength: 255,
89-
minLength: 3,
90-
},
91-
{
92-
name: 'content',
93-
showIn: ['list', 'create', 'edit', 'filter', 'show'],
94-
},
95-
{
96-
name: 'createdAt',
97-
showIn: ['list', 'filter', 'show',],
98-
fillOnCreate: () => (new Date()).toISOString(),
99-
},
100-
{
101-
name: 'published',
102-
required: true,
103-
},
104-
{
105-
name: 'authorId',
106-
foreignResource: {
107-
resourceId: 'users',
108-
},
109-
showIn: ['list', 'filter', 'show'],
110-
fillOnCreate: ({ adminUser }: { adminUser: AdminUser }) => {
111-
return adminUser.dbUser.id;
112-
}
113-
}
114-
],
115-
}
29+
],
30+
resources: [
31+
apartmentsResource,
32+
usersResource,
33+
auditLogsResource
11634
],
11735
menu: [
11836
{
@@ -122,15 +40,27 @@ export const admin = new AdminForth({
12240
children: [
12341
{
12442
homepage: true,
125-
label: 'Posts',
43+
label: 'Apartments',
12644
icon: 'flowbite:home-solid',
127-
resourceId: 'posts',
45+
resourceId: 'aparts',
12846
},
47+
{
48+
label: 'Audit Logs',
49+
icon: 'flowbite:search-outline',
50+
resourceId: 'audit_logs',
51+
}
12952
]
13053
},
131-
{ type: 'gap' },
132-
{ type: 'divider' },
133-
{ type: 'heading', label: 'SYSTEM' },
54+
{
55+
type: 'gap'
56+
},
57+
{
58+
type: 'divider'
59+
},
60+
{
61+
type: 'heading',
62+
label: 'SYSTEM',
63+
},
13464
{
13565
label: 'Users',
13666
icon: 'flowbite:user-solid',
@@ -139,32 +69,53 @@ export const admin = new AdminForth({
13969
],
14070
});
14171

72+
async function seedDatabase() {
73+
if (await admin.resource('aparts').count() > 0) {
74+
return
75+
}
76+
for (let i = 0; i <= 50; i++) {
77+
await admin.resource('aparts').create({
78+
id: `${i}`,
79+
title: `Apartment ${i}`,
80+
square_meter: (Math.random() * 100).toFixed(1),
81+
price: (Math.random() * 10000).toFixed(2),
82+
number_of_rooms: Math.floor(Math.random() * 4) + 1,
83+
description: 'Next gen apartments',
84+
created_at: (new Date(Date.now() - Math.random() * 60 * 60 * 24 * 14 * 1000)).toISOString(),
85+
listed: i % 2 == 0,
86+
country: `${['US', 'DE', 'FR', 'GB', 'NL', 'IT', 'ES', 'DK', 'PL', 'UA'][Math.floor(Math.random() * 10)]}`
87+
});
88+
};
89+
};
14290

14391
if (import.meta.url === `file://${process.argv[1]}`) {
14492
// if script is executed directly e.g. node index.ts or npm start
14593

94+
14695
const app = express()
14796
app.use(express.json());
14897
const port = 3500;
14998

15099
// needed to compile SPA. Call it here or from a build script e.g. in Docker build time to reduce downtime
151-
await admin.bundleNow({ hotReload: process.env.NODE_ENV === 'development' });
100+
await admin.bundleNow({ hotReload: process.env.NODE_ENV === 'development'});
152101
console.log('Bundling AdminForth done. For faster serving consider calling bundleNow() from a build script.');
153102

103+
154104
// serve after you added all api
155105
admin.express.serve(app)
156106

157107
admin.discoverDatabases().then(async () => {
158108
if (!await admin.resource('users').get([Filters.EQ('email', 'adminforth')])) {
159109
await admin.resource('users').create({
160110
email: 'adminforth',
161-
passwordHash: await AdminForth.Utils.generatePasswordHash('adminforth'),
111+
password_hash: await AdminForth.Utils.generatePasswordHash('adminforth'),
162112
role: 'superadmin',
163113
});
164114
}
115+
await seedDatabase();
165116
});
166117

167-
admin.express.listen(port, () => {
168-
console.log(`\n⚡ AdminForth is available at http://localhost:${port}\n`)
118+
admin.express.expressApp.listen(port, () => {
119+
console.log(`\n⚡ AdminForth is available at http://localhost:${port}${ADMIN_BASE_URL}\n`)
169120
});
170121
}
File renamed without changes.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
Warnings:
3+
4+
- You are about to drop the `Post` table. If the table is not empty, all the data it contains will be lost.
5+
- You are about to drop the `User` table. If the table is not empty, all the data it contains will be lost.
6+
7+
*/
8+
-- DropTable
9+
PRAGMA foreign_keys=off;
10+
DROP TABLE "Post";
11+
PRAGMA foreign_keys=on;
12+
13+
-- DropTable
14+
PRAGMA foreign_keys=off;
15+
DROP TABLE "User";
16+
PRAGMA foreign_keys=on;
17+
18+
-- CreateTable
19+
CREATE TABLE "users" (
20+
"id" TEXT NOT NULL PRIMARY KEY,
21+
"created_at" DATETIME NOT NULL,
22+
"email" TEXT NOT NULL,
23+
"role" TEXT NOT NULL,
24+
"password_hash" TEXT NOT NULL
25+
);
26+
27+
-- CreateTable
28+
CREATE TABLE "apartments" (
29+
"id" TEXT NOT NULL PRIMARY KEY,
30+
"created_at" DATETIME,
31+
"title" TEXT NOT NULL,
32+
"square_meter" REAL,
33+
"price" DECIMAL NOT NULL,
34+
"number_of_rooms" INTEGER,
35+
"description" TEXT,
36+
"country" TEXT,
37+
"listed" BOOLEAN NOT NULL,
38+
"realtor_id" TEXT
39+
);
40+
41+
-- CreateIndex
42+
CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-- CreateTable
2+
CREATE TABLE "audit_logs" (
3+
"id" TEXT NOT NULL PRIMARY KEY,
4+
"created_at" DATETIME NOT NULL,
5+
"resource_id" TEXT NOT NULL,
6+
"user_id" TEXT NOT NULL,
7+
"action" TEXT NOT NULL,
8+
"diff" TEXT,
9+
"record_id" TEXT
10+
);

cli-demo/package-lock.json

Lines changed: 30 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)