@surv-co/prisma-typeorm-db-utils
Version:
Transform Prisma schemas to TypeORM entities with NestJS integration and fast pg-mem testing
429 lines (340 loc) โข 12.5 kB
Markdown
# @surv-co/prisma-typeorm-db-utils
**Transform Prisma schemas to TypeORM datasources with NestJS integration and testing support.**
[](https://www.npmjs.com/package/@surv-co/prisma-typeorm-db-utils)
[](https://www.typescriptlang.org/)
## Why use this library?
- ๐ **Prisma Schema โ TypeORM Datasource** - Complete transformation in one step
- ๐งช **Fast pg-mem testing** - In-memory PostgreSQL for lightning-fast tests
- ๐๏ธ **Ready-to-use NestJS modules** - Drop-in TypeORM and repository integration for both testing (pg-mem) and production (PostgreSQL)
- ๐ฏ **Type-safe throughout** - Full TypeScript support with proper error handling
- ๐ฆ **Simple API** - Just a few imports to get everything working
## Core Features
### 1. **Complete Testing Setup (pg-mem)** - Schema to TypeORM Datasource
Transform your Prisma schema directly into a working TypeORM datasource with pg-mem database:
```typescript
import { createPrismaToPgMemTypeormDatasourceGenerator } from '@surv-co/prisma-typeorm-db-utils';
// Your Prisma schema
const schema = `
model User {
id String @id @default(uuid())
email String @unique
name String?
posts Post[]
}
model Post {
id String @id @default(uuid())
title String
content String?
authorId String
author User @relation(fields: [authorId], references: [id])
}
`;
// Generate complete TypeORM datasource
const generator = createPrismaToPgMemTypeormDatasourceGenerator();
const result = await generator.generateDatasource({
schema,
entities: [User, Post] // Your TypeORM entity classes
});
if (result._tag === 'Right') {
const { datasource } = result.right;
// Use datasource for testing - fully configured with pg-mem database
const userRepository = datasource.getRepository(User);
const newUser = await userRepository.save({ email: 'test@example.com' });
}
```
### 2. **NestJS DataSource Integration (pg-mem)** - Injectable TYPEORM_DATASOURCE
Automatically provides a TypeORM datasource with pg-mem for fast testing:
```typescript
import { Module } from '@nestjs/common';
import { TypeORMPgMemModule } from '@surv-co/prisma-typeorm-db-utils';
import { User, Post } from './entities';
@Module({
imports: [
TypeORMPgMemModule.forRoot({
entities: [User, Post],
prismaSchema: `
model User {
id String @id @default(uuid())
email String @unique
name String?
posts Post[]
}
model Post {
id String @id @default(uuid())
title String
content String?
authorId String
author User @relation(fields: [authorId], references: [id])
}
`
}),
// Other modules can now inject TYPEORM_DATASOURCE
],
})
export class AppModule {}
```
> **Note:** The `synchronize` option is not supported for pg-mem. The schema is always created from the provided `prismaSchema`.
---
### 3. **Production/PostgreSQL Integration** - Real PostgreSQL Datasource
Use the `TypeORMPostgresModule` to connect to a real PostgreSQL database in production or staging environments:
```typescript
import { Module } from '@nestjs/common';
import { TypeORMPostgresModule } from '@surv-co/prisma-typeorm-db-utils';
import { User, Post } from './entities';
@Module({
imports: [
TypeORMPostgresModule.forRoot({
entities: [User, Post],
host: 'localhost',
port: 5432,
username: 'postgres',
password: 'password',
database: 'mydb',
// synchronize: false, // Not supported! See note below
logging: false,
ssl: false // or provide SSL config for production
}),
// Other modules can now inject TYPEORM_DATASOURCE
],
})
export class AppModule {}
```
- **Entities**: Register your TypeORM entity classes
- **Connection**: Provide all PostgreSQL connection details
- **SSL/Logging**: Configure as needed for your environment
> **Important:** The `synchronize` option is **not supported** for the real PostgreSQL datasource. You must run your database migrations before using the datasource. This module does not auto-sync or create the schema in PostgreSQL.
---
### 4. **Repository Factory Function** - createTypeORMRepositoryFactory
Create repository operations from any TypeORM datasource:
```typescript
import {
createPrismaToPgMemTypeormDatasourceGenerator,
createTypeORMRepositoryFactory
} from '@surv-co/prisma-typeorm-db-utils';
import { Entity, PrimaryColumn, Column } from 'typeorm';
@Entity()
class User {
@PrimaryColumn('uuid')
id: string;
@Column('varchar')
email: string;
@Column('varchar', { nullable: true })
name: string;
}
const schema = `
model User {
id String @id @default(uuid())
email String @unique
name String?
}
`;
// Complete setup in one step
const generator = createPrismaToPgMemTypeormDatasourceGenerator();
const result = await generator.generateDatasource({ schema, entities: [User] });
if (result._tag === 'Right') {
const { datasource } = result.right;
// Create repository factory from the datasource
const repositoryFactory = createTypeORMRepositoryFactory(datasource);
const userRepository = repositoryFactory(User);
// Use functional repository operations
const createResult = await userRepository.create({
email: 'test@example.com',
name: 'Test User'
})();
if (createResult._tag === 'Right') {
console.log('User created:', createResult.right);
}
}
```
### 5. **NestJS Repository Integration** - Injectable REPOSITORY_OPERATIONS
Provides a repository factory that works with any datasource:
```typescript
import { Injectable, Inject } from '@nestjs/common';
import { REPOSITORY_OPERATIONS } from '@surv-co/prisma-typeorm-db-utils';
import { User } from './entities/User';
@Injectable()
export class UserService {
private userRepository;
constructor(
@Inject(REPOSITORY_OPERATIONS) repositoryFactory: any
) {
this.userRepository = repositoryFactory(User);
}
async createUser(userData: Partial<User>) {
const result = await this.userRepository.create(userData)();
if (result._tag === 'Right') {
return result.right;
}
throw new Error(result.left.message);
}
}
```
### 6. **Entity Generator** - TypeORM Entities from Prisma Schema
Generate TypeORM entity classes from your Prisma schema:
```typescript
import { createPrismaToEntitiesGenerator } from '@surv-co/prisma-typeorm-db-utils';
const generator = createPrismaToEntitiesGenerator();
const result = await generator.generateEntities(schema)();
if (result._tag === 'Right') {
console.log('Generated TypeORM entities:');
result.right.forEach(entityCode => {
console.log(entityCode);
});
}
```
## Quick Start
### 1. Install
```bash
npm install @surv-co/prisma-typeorm-db-utils
```
### 2. Basic Usage
```typescript
import {
createPrismaToPgMemTypeormDatasourceGenerator,
TypeORMPgMemModule,
TypeORMPostgresModule, // <-- NEW: for real PostgreSQL
RepositoryModule,
REPOSITORY_OPERATIONS
} from '@surv-co/prisma-typeorm-db-utils';
```
### 3. Complete NestJS Setup (pg-mem and postgres)
```typescript
// app.module.ts
import { Module } from '@nestjs/common';
import { TypeORMPgMemModule, TypeORMPostgresModule, RepositoryModule } from '@surv-co/prisma-typeorm-db-utils';
import { User, Post } from './entities';
@Module({
imports: [
// For fast in-memory testing
TypeORMPgMemModule.forRoot({
entities: [User, Post],
prismaSchema: `...`
}),
// For production with real PostgreSQL
// TypeORMPostgresModule.forRoot({
// entities: [User, Post],
// host: 'localhost',
// port: 5432,
// username: 'postgres',
// password: 'password',
// database: 'mydb',
// // synchronize: false, // Not supported!
// logging: false,
// ssl: false
// }),
RepositoryModule,
],
})
export class AppModule {}
```
> **Note:** For pg-mem, schema is always created from the provided `prismaSchema`. For PostgreSQL, you must run your migrations before using the datasource. The module does not auto-sync or create the schema.
### 4. Testing Setup
```typescript
// user.service.spec.ts
import { Test } from '@nestjs/testing';
import { createPrismaToPgMemTypeormDatasourceGenerator } from '@surv-co/prisma-typeorm-db-utils';
import { UserService } from './user.service';
describe('UserService', () => {
let service: UserService;
let cleanup: () => Promise<void>;
beforeEach(async () => {
// Create complete testing environment from schema
const generator = createPrismaToPgMemTypeormDatasourceGenerator();
const result = await generator.generateDatasource({
schema: prismaSchemaString,
entities: [User, Post]
});
if (result._tag === 'Right') {
const { datasource, database } = result.right;
cleanup = database.cleanup;
const module = await Test.createTestingModule({
imports: [RepositoryModule],
providers: [UserService],
})
.overrideProvider('TYPEORM_DATASOURCE')
.useValue(datasource)
.compile();
service = module.get<UserService>(UserService);
}
});
afterEach(async () => {
await cleanup();
});
it('should create a user', async () => {
const user = await service.createUser({
email: 'test@example.com',
name: 'Test User'
});
expect(user.email).toBe('test@example.com');
});
});
```
## Core API
### Primary Functions
```typescript
// Complete schema to datasource transformation
createPrismaToPgMemTypeormDatasourceGenerator()
// NestJS modules
TypeORMPgMemModule.forRoot({ entities: [...], prismaSchema: '...' }) // Provides TYPEORM_DATASOURCE (pg-mem)
TypeORMPostgresModule.forRoot({ entities: [...], host, port, username, password, database, ... }) // Provides TYPEORM_DATASOURCE (PostgreSQL)
RepositoryModule // Provides REPOSITORY_OPERATIONS
// Repository factory function
createTypeORMRepositoryFactory(dataSource)
// Entity generation
createPrismaToEntitiesGenerator()
```
### Core Exports
```typescript
import {
// Main integration - Prisma schema to complete TypeORM datasource
createPrismaToPgMemTypeormDatasourceGenerator,
// NestJS modules
TypeORMPgMemModule, // Provides TYPEORM_DATASOURCE (pg-mem)
TypeORMPostgresModule, // Provides TYPEORM_DATASOURCE (PostgreSQL)
RepositoryModule, // Provides REPOSITORY_OPERATIONS
REPOSITORY_OPERATIONS, // Repository factory injection token
// Individual functions
createTypeORMRepositoryFactory, // Repository factory function
createPrismaToEntitiesGenerator, // Entity generator
// Testing utilities
createTestTypeORMClient, // Low-level pg-mem client
createPostgresTypeORMClient, // Low-level Postgres client
// Types
type RepositoryOperations,
type TableConfig,
type ColumnConfig
} from '@surv-co/prisma-typeorm-db-utils';
```
## Environment Configuration
### All Environments
- **pg-mem**: Uses in-memory database for fast testing and development. No external dependencies. The schema is always created from the provided `prismaSchema`.
- **PostgreSQL**: Uses real PostgreSQL connection for production/staging. You must run your migrations before using the datasource. The module does not auto-sync or create the schema.
## TypeORM Features Supported
- โ
**Complete datasource creation** from Prisma schema
- โ
**Entity generation** with proper decorators
- โ
**Relationships** (@ManyToOne, @OneToMany, @JoinColumn)
- โ
**UUID primary keys** with auto-generation
- โ
**Composite primary keys** with defaults
- โ
**Snake case naming** (camelCase โ snake_case)
- โ
**Unique constraints** and indexes
- โ
**Nullable fields** and default values
## Error Handling
All operations use functional error handling:
```typescript
const result = await someOperation();
if (result._tag === 'Right') {
const data = result.right; // Success case
} else {
const error = result.left; // Error case
console.error('Operation failed:', error.message);
}
```
## Requirements
- Node.js 18+
- TypeScript 4.9+
- NestJS 10+ (for NestJS features)
- TypeORM 0.3+
## License
MIT
---
**Need help?** Open an issue on GitHub for support.