npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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.

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-inspector separately. 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>/: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

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

Step 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 nodemon

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

Step 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_db

Step 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 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

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

With Prisma

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

With 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