npm package: @hero-dynamic-form/core
Description: A plug-and-play dynamic admin panel that **auto-generates UI + CRUD API** from your Resource Config and ORM Entities.
Author: hero-truong
Latest version: 1.0.49

# @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-inspector` separately.
> See [MIGRATION_GUIDE.md](./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>/:id`
  - `DELETE /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

```bash
mkdir my-admin-panel
cd my-admin-panel
npm init -y
```

### Step 2: Install Dependencies

```bash
# 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 nodemon
```

### Step 3: Create tsconfig.json

```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.json
```

### Step 5: Create Entity

`src/entities/User.ts`

```typescript
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`

```typescript
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:**

```env
# Option 1: Connection string
DATABASE_URL=postgres://postgres:postgres@127.0.0.1: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_db
```

### Step 7: Create Main Entry

`src/index.ts`

```typescript
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

```json
{
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "dev": "ts-node src/index.ts"
  }
}
```

### Step 9: Create Database

```bash
# PostgreSQL
createdb my_admin_db

# Or using psql
psql -U postgres -c "CREATE DATABASE my_admin_db;"
```

### Step 10: Run the Server

```bash
# Development
npm run dev

# Or Production
npm run build
npm start
```

Server 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

```bash
npm install @hero-dynamic-form/core @hero-dynamic-form/typeorm-inspector typeorm reflect-metadata
```

### With Prisma

```bash
npm install @hero-dynamic-form/core @hero-dynamic-form/prisma-inspector @prisma/client
```

### With Sequelize

```bash
npm install @hero-dynamic-form/core @hero-dynamic-form/sequelize-inspector sequelize
```

---

## 🧩 Configuration Reference

### DynamicFormCoreConfig

```typescript
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

```typescript
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

```typescript
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:

```typescript
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