@hero-dynamic-form/core
v1.0.49
Published
A plug-and-play dynamic admin panel that **auto-generates UI + CRUD API** from your Resource Config and ORM Entities.
Maintainers
Readme
@hero-dynamic-form/core
A plug-and-play dynamic admin panel that auto-generates UI + CRUD API from your Resource Config and ORM Entities.
🔌 ORM-Agnostic: Works with TypeORM, Prisma, Sequelize, or any ORM through adapters.
No Express setup. No Webpack setup. No frontend code. No backend code. Install → Config → Start → Use.
🚨 IMPORTANT v2.0 Breaking Changes TypeORM is no longer bundled. Install
@hero-dynamic-form/typeorm-inspectorseparately. See MIGRATION_GUIDE.md for upgrade instructions.
✨ Features
Zero-Config Backend
Just declare a TypeORM entity. The backend will:
- Read metadata (columns, types, required…)
- Auto-generate CRUD API (list/get/create/update/delete)
- Validate incoming data automatically
- Expose REST API:
GET /api/<resource>POST /api/<resource>PUT /api/<resource>/:idDELETE /api/<resource>/:id
Zero-Config Frontend
The package includes a full React frontend + Webpack setup:
- Auto-render list table and forms based on metadata
- Auto-generate create/update UI
- Export static HTML/JS → served by backend
No React code needed.
🚀 Quick Start - Create New Project from Scratch
Prerequisites
- Node.js >= 18
- PostgreSQL (or MySQL/SQLite)
- pnpm / npm / yarn
Step 1: Create Project
mkdir my-admin-panel
cd my-admin-panel
npm init -yStep 2: Install Dependencies
# Core packages
npm install @hero-dynamic-form/core @hero-dynamic-form/typeorm-inspector
# TypeORM + Database driver
npm install typeorm reflect-metadata pg
# Dev dependencies
npm install -D typescript @types/node ts-node nodemonStep 3: Create tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "commonjs",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": ["src/**/*"]
}Step 4: Create Project Structure
my-admin-panel/
├── src/
│ ├── entities/
│ │ └── User.ts
│ ├── datasource.ts
│ └── index.ts
├── package.json
└── tsconfig.jsonStep 5: Create Entity
src/entities/User.ts
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
@Entity({ name: 'users' })
export class User {
@PrimaryGeneratedColumn()
id!: number;
@Column({ type: 'varchar', length: 255 })
username!: string;
@Column({ type: 'varchar', length: 255 })
password!: string;
@Column({ type: 'text', default: 'user' })
role!: string;
@Column({ type: 'boolean', default: true })
isActive!: boolean;
@Column({ type: 'text', nullable: true })
description?: string;
@CreateDateColumn()
createdAt!: Date;
@UpdateDateColumn()
updatedAt!: Date;
}Step 6: Create DataSource
src/datasource.ts
import { DataSource } from 'typeorm';
import { User } from './entities/User';
// Supports both DATABASE_URL and individual DB_* env vars
const getDataSourceConfig = () => {
const baseConfig = {
type: 'postgres' as const,
synchronize: true, // Auto-create tables (dev only!)
logging: false,
entities: [User],
};
// Option 1: Use DATABASE_URL (connection string)
if (process.env.DATABASE_URL) {
return { ...baseConfig, url: process.env.DATABASE_URL };
}
// Option 2: Use individual env vars
return {
...baseConfig,
host: process.env.DB_HOST || 'localhost',
port: Number(process.env.DB_PORT) || 5432,
username: process.env.DB_USER || 'postgres',
password: process.env.DB_PASS || 'postgres',
database: process.env.DB_NAME || 'my_admin_db',
};
};
export const datasource = new DataSource(getDataSourceConfig());Environment Variables:
# Option 1: Connection string
DATABASE_URL=postgres://postgres:[email protected]:5432/my_admin_db
# Option 2: Individual variables (if DATABASE_URL is not set)
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASS=postgres
DB_NAME=my_admin_dbStep 7: Create Main Entry
src/index.ts
import 'reflect-metadata';
import { datasource } from './datasource';
import { User } from './entities/User';
import { DynamicFormCore, DynamicFormCoreConfig } from '@hero-dynamic-form/core';
import { TypeORMEntityInspector } from '@hero-dynamic-form/typeorm-inspector';
const PORT = Number(process.env.PORT) || 4000;
const main = async () => {
// 1. Initialize database connection
await datasource.initialize();
console.log('Database connected');
// 2. Configure Dynamic Form
const config: DynamicFormCoreConfig = {
dataSource: datasource as any,
entityInspector: new TypeORMEntityInspector(),
resources: [
{
name: 'user',
entity: User,
},
// Add more resources here...
],
backend: {
port: PORT,
},
cors: {
origin: ['http://localhost:3000'],
credentials: true,
},
};
// 3. Initialize and start
const app = new DynamicFormCore(config);
await app.init();
app.start();
};
main().catch((error) => {
console.error('Error:', error);
process.exit(1);
});Step 8: Add Scripts to package.json
{
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "ts-node src/index.ts"
}
}Step 9: Create Database
# PostgreSQL
createdb my_admin_db
# Or using psql
psql -U postgres -c "CREATE DATABASE my_admin_db;"Step 10: Run the Server
# Development
npm run dev
# Or Production
npm run build
npm startServer will start at http://localhost:4000
Auto-Generated API Endpoints
| Method | Endpoint | Description |
| ------ | --------------- | ------------------- |
| GET | /api/user | List all users |
| GET | /api/user/:id | Get user by ID |
| POST | /api/user | Create new user |
| PUT | /api/user/:id | Update user |
| DELETE | /api/user/:id | Delete user |
| GET | /schema | Get schema metadata |
| GET | /health | Health check |
📦 Installation
With TypeORM
npm install @hero-dynamic-form/core @hero-dynamic-form/typeorm-inspector typeorm reflect-metadataWith Prisma
npm install @hero-dynamic-form/core @hero-dynamic-form/prisma-inspector @prisma/clientWith Sequelize
npm install @hero-dynamic-form/core @hero-dynamic-form/sequelize-inspector sequelize🧩 Configuration Reference
DynamicFormCoreConfig
interface DynamicFormCoreConfig {
// Required: TypeORM DataSource instance
dataSource: DataSource;
// Required: ORM inspector (TypeORM, Prisma, or Sequelize)
entityInspector: EntityInspector;
// Required: Resources to expose
resources: DynamicFormResourceConfig[];
// Optional: Backend settings
backend?: {
port?: number; // Default: 3030
apiKey?: string; // API key protection
};
// Optional: Authentication
auth?: AuthConfig;
// Optional: CORS settings
cors?: CorsConfig | boolean;
// Optional: Schema codegen
codegen?: SchemaCodegenConfig;
}Resource Config
interface DynamicFormResourceConfig {
name: string; // API route name (e.g., "user" → /api/user)
entity: Function; // Entity class
label?: string; // Display label
description?: string; // Description
actions?: {
// Custom action handlers
list?: ResourceActionConfig;
detail?: ResourceActionConfig;
create?: ResourceActionConfig;
update?: ResourceActionConfig;
delete?: ResourceActionConfig;
};
}Multiple Resources Example
const config: DynamicFormCoreConfig = {
dataSource: datasource as any,
entityInspector: new TypeORMEntityInspector(),
resources: [
{ name: 'user', entity: User },
{ name: 'product', entity: Product },
{ name: 'order', entity: Order },
{ name: 'category', entity: Category },
],
backend: { port: 4000 },
};🛣 Roadmap
v1
✔ TypeORM auto CRUD
✔ Auto UI form/table
✔ CLI backend + frontend
✔ Built-in Webpack
v2
✔ ORM Adapter Pattern - Support for multiple ORMs ✔ TypeORM inspector package ✔ Prisma inspector package ✔ Sequelize inspector package ⬜ Relations UI ⬜ Hooks (beforeSave, afterDelete…) ⬜ RBAC permissions ⬜ Custom themes ⬜ Multi-admin support
⚙️ Advanced Configuration
CORS Configuration
CORS is enabled by default. You can customize it using the cors option:
const config: DynamicFormCoreConfig = {
// ... other config
// Enable CORS with defaults (allows all origins)
cors: true,
// Or customize CORS settings
cors: {
origin: ['http://localhost:3000', 'http://example.com'],
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
},
// Or disable CORS entirely
cors: false,
};CORS Options
| Option | Type | Default | Description |
| ---------------- | ------------------------------- | ------------------------------------------------------ | -------------------------------------------------- |
| origin | string \| string[] \| boolean | true | Allowed origins. true allows all origins |
| credentials | boolean | true | Allow credentials (cookies, authorization headers) |
| methods | string[] | ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'] | Allowed HTTP methods |
| allowedHeaders | string[] | ['Content-Type', 'Authorization'] | Allowed request headers |
🤝 Contributing
PRs welcome.
📄 License
MIT License
