npm package: @hero-dynamic-form/prisma-inspector
Description: Prisma entity inspector adapter for @hero-dynamic-form/core
Author: hero-truong
Latest version: 1.0.43

# @hero-dynamic-form/prisma-inspector

Prisma entity inspector adapter for `@hero-dynamic-form/core`. This package provides both a library for runtime entity inspection and a CLI tool for generating Prisma schemas from your PostgreSQL database.

## Installation

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

## CLI Usage

### Generate Prisma schema from database

```bash
# List all tables
npx prisma-inspector generate

# Generate schema from table
npx prisma-inspector generate users --output ./prisma/schema.prisma

# Append to existing schema
npx prisma-inspector generate posts --append

# Overwrite existing file
npx prisma-inspector generate users --force
```

Options:
- `--output, -o <path>` - Output file (default: `./prisma/schema.prisma`)
- `--force, -f` - Overwrite existing files
- `--append` - Append to existing schema file
- `--env <path>` - Path to .env file (default: `.env`)

### Environment Variables

```env
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASS=postgres
DB_NAME=your_database
```

## Library Usage

### Method 1: Using Prisma DMMF (Recommended)

```typescript
import { DynamicFormCore } from '@hero-dynamic-form/core';
import { PrismaEntityInspector } from '@hero-dynamic-form/prisma-inspector';
import { PrismaClient, Prisma } from '@prisma/client';

// Create inspector from Prisma DMMF (Data Model Meta Format)
const inspector = PrismaEntityInspector.fromDMMF(Prisma.dmmf);

const config = {
  entityInspector: inspector,
  resources: [
    {
      name: 'users',
      entity: 'User', // Prisma model name
    },
  ],
  // ... rest of config
};

const core = new DynamicFormCore(config);
await core.init();
await core.start();
```

### Method 2: Manual Model Registration

```typescript
import { PrismaEntityInspector } from '@hero-dynamic-form/prisma-inspector';

const inspector = new PrismaEntityInspector();

// Manually register model metadata
inspector.registerModel('User', {
  name: 'User',
  fields: [
    {
      name: 'id',
      type: 'Int',
      isRequired: true,
      isList: false,
      isId: true,
    },
    {
      name: 'email',
      type: 'String',
      isRequired: true,
      isList: false,
      isUnique: true,
    },
    {
      name: 'name',
      type: 'String',
      isRequired: false,
      isList: false,
    },
  ],
});

// Use inspector in config
const config = {
  entityInspector: inspector,
  // ...
};
```

## Features

- Extracts Prisma model metadata automatically from DMMF
- Generates validation rules based on field types and constraints
- Supports all Prisma field types:
  - String → text
  - Int → int
  - BigInt → bigint
  - Float → float
  - Decimal → decimal
  - Boolean → boolean
  - DateTime → timestamp
  - Json → json
  - Bytes → bytea
- Supports field modifiers:
  - `@id` - Primary key detection
  - `@unique` - Unique constraint
  - `@default` - Default values
  - `?` - Optional fields
  - `[]` - Array fields
- Automatic validation for:
  - Required fields
  - Email format (by field name)
  - URL format (by field name)
  - Phone format (by field name)
  - Enum values
  - JSON validation
  - DateTime validation
  - Numeric ranges

## Prisma Schema Example

```prisma
model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String?
  role      Role     @default(USER)
  posts     Post[]
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

enum Role {
  USER
  ADMIN
  MODERATOR
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  Int
}
```

## Full Example

```typescript
import { DynamicFormCore, defineConfig } from '@hero-dynamic-form/core';
import { PrismaEntityInspector } from '@hero-dynamic-form/prisma-inspector';
import { PrismaClient, Prisma } from '@prisma/client';

const prisma = new PrismaClient();
const inspector = PrismaEntityInspector.fromDMMF(Prisma.dmmf);

const config = defineConfig({
  dataSource: prisma, // Pass Prisma client as dataSource
  entityInspector: inspector,
  resources: [
    {
      name: 'users',
      entity: 'User',
      label: 'Users',
    },
    {
      name: 'posts',
      entity: 'Post',
      label: 'Posts',
    },
  ],
  auth: {
    enabled: true,
    adapter: myAuthAdapter,
  },
  backend: {
    port: 3030,
  },
});

const core = new DynamicFormCore(config);
await core.init();
await core.start();
```

## Type Mappings

| Prisma Type | Normalized Type |
|-------------|----------------|
| String      | text           |
| Int         | int            |
| BigInt      | bigint         |
| Float       | float          |
| Decimal     | decimal        |
| Boolean     | boolean        |
| DateTime    | timestamp      |
| Json        | json           |
| Bytes       | bytea          |

Arrays are represented with `[]` suffix (e.g., `text[]`).

## Validation Rules

The inspector automatically generates validation rules based on:

1. **Field Constraints**:
   - Required fields (no `?`)
   - Default values
   - Unique constraints

2. **Type-based Validation**:
   - Numeric types: min/max ranges
   - DateTime: valid date check
   - Boolean: boolean check
   - Json: valid JSON check
   - Arrays: array check

3. **Convention-based Validation**:
   - Fields named `email`: email pattern
   - Fields named `url`: URL pattern
   - Fields named `phone`/`tel`: phone pattern

## API

### PrismaEntityInspector

```typescript
class PrismaEntityInspector implements EntityInspector {
  // Create inspector from Prisma DMMF
  static fromDMMF(dmmf: any): PrismaEntityInspector;

  // Manually register a model
  registerModel(modelName: string, metadata: PrismaModelMetadata): void;

  // Inspect entity (required by EntityInspector interface)
  inspectEntity(entity: any): ResourceSchema;
}
```

## License

MIT