@dataql/prisma-adapter
Version:
Prisma adapter for DataQL with zero API changes
356 lines (295 loc) • 7.8 kB
Markdown
# @dataql/prisma-adapter
Migrate from Prisma to DataQL with zero API changes. This adapter provides a Prisma Client-compatible API that uses DataQL under the hood.
## Installation
```bash
npm install @dataql/core @dataql/prisma-adapter
```
## Quick Start
```typescript
import { createPrismaClient } from "@dataql/prisma-adapter";
// Define your schema using DataQL format
const schemas = {
user: {
id: { type: "ID", required: true },
email: { type: "String", required: true, unique: true },
name: { type: "String" },
age: { type: "Int" },
createdAt: { type: "Date", default: "now" },
updatedAt: { type: "Date", default: "now" },
posts: { type: "array", items: { ref: "post" } },
},
post: {
id: { type: "ID", required: true },
title: { type: "String", required: true },
content: { type: "String" },
published: { type: "Boolean", default: false },
authorId: { type: "ID", required: true, ref: "user" },
createdAt: { type: "Date", default: "now" },
updatedAt: { type: "Date", default: "now" },
},
};
// Create Prisma client with DataQL backend
const prisma = createPrismaClient(
{
appToken: "your-app-token",
},
schemas
);
// Use familiar Prisma syntax
const user = await prisma.user.create({
data: {
email: "john@example.com",
name: "John Doe",
age: 30,
posts: {
create: [
{
title: "Hello World",
content: "This is my first post",
published: true,
},
],
},
},
include: {
posts: true,
},
});
// Query with filters and pagination
const users = await prisma.user.findMany({
where: {
age: {
gte: 18,
},
posts: {
some: {
published: true,
},
},
},
include: {
posts: {
where: {
published: true,
},
},
},
orderBy: {
createdAt: "desc",
},
take: 10,
skip: 0,
});
// Update data
const updatedUser = await prisma.user.update({
where: { id: user.id },
data: {
age: 31,
posts: {
update: {
where: { id: user.posts[0].id },
data: { title: "Updated Title" },
},
},
},
});
// Delete data
await prisma.post.deleteMany({
where: {
published: false,
},
});
```
## API Compatibility
### Supported Prisma Client Features
#### CRUD Operations
- ✅ `create()` - Create single record
- ✅ `createMany()` - Create multiple records
- ✅ `findUnique()` - Find single record by unique field
- ✅ `findFirst()` - Find first matching record
- ✅ `findMany()` - Find multiple records
- ✅ `update()` - Update single record
- ✅ `updateMany()` - Update multiple records
- ✅ `upsert()` - Insert or update record
- ✅ `delete()` - Delete single record
- ✅ `deleteMany()` - Delete multiple records
- ✅ `count()` - Count records
- ✅ `aggregate()` - Aggregate data (basic support)
#### Query Options
- ✅ `where` - Filter conditions
- ✅ `select` - Field selection
- ✅ `include` - Include relations (basic support)
- ✅ `orderBy` - Sorting
- ✅ `take` / `skip` - Pagination
- ✅ `distinct` - Distinct values
#### Filtering
- ✅ String filters: `equals`, `contains`, `startsWith`, `endsWith`, `in`, `notIn`
- ✅ Number filters: `equals`, `gt`, `gte`, `lt`, `lte`, `in`, `notIn`
- ✅ Boolean filters: `equals`
- ✅ Date filters: `equals`, `gt`, `gte`, `lt`, `lte`, `in`, `notIn`
- ✅ Logical operators: `AND`, `OR`, `NOT`
#### Advanced Features
- ✅ Transactions (`$transaction`)
- ✅ Connection management (`$connect`, `$disconnect`)
- ✅ Type safety with TypeScript
- ✅ Error handling (Prisma error classes)
### DataQL Enhancements
While maintaining Prisma compatibility, you also get DataQL's additional features:
- **Offline-first**: Automatic offline support and sync
- **Real-time**: Built-in real-time updates
- **Multi-region**: Global data distribution
- **Schema evolution**: Dynamic schema updates
- **WAL support**: Write-ahead logging for reliability
- **Unique document creation**: `createUnique()` method to prevent duplicates
## Migration Guide
### From Prisma
1. **Replace imports**:
```typescript
// Before
import { PrismaClient } from "@prisma/client";
// After
import { createPrismaClient } from "@dataql/prisma-adapter";
```
2. **Convert Prisma schema to DataQL format**:
```typescript
// Before (schema.prisma)
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
// After (TypeScript object)
const schemas = {
user: {
id: { type: 'ID', required: true },
email: { type: 'String', required: true, unique: true },
name: { type: 'String' },
posts: { type: 'array', items: { ref: 'post' } }
}
};
```
3. **Update client initialization**:
```typescript
// Before
const prisma = new PrismaClient();
// After
const prisma = createPrismaClient(
{
appToken: "your-app-token",
},
schemas
);
```
4. **Your queries work the same**:
```typescript
// This works exactly the same
const users = await prisma.user.findMany({
where: { email: { contains: "@gmail.com" } },
});
```
## Configuration
```typescript
const prisma = createPrismaClient(
{
appToken: "your-app-token", // Authentication token
env: "prod", // 'dev' or 'prod'
devPrefix: "dev_", // Prefix for dev tables
log: ["query", "error"], // Logging options
errorFormat: "pretty", // Error formatting
},
schemas
);
```
## TypeScript Support
Full TypeScript support with inferred types:
```typescript
interface User {
id: string;
email: string;
name?: string;
age?: number;
createdAt?: Date;
updatedAt?: Date;
}
interface Post {
id: string;
title: string;
content?: string;
published?: boolean;
authorId: string;
createdAt?: Date;
updatedAt?: Date;
}
const prisma = createPrismaClient<{
user: User;
post: Post;
}>(
{
appToken: "your-app-token",
},
schemas
);
// Type-safe operations
const user: User = await prisma.user.create({
data: {
email: "jane@example.com",
name: "Jane Doe",
},
});
```
## Transaction Support
Transactions work exactly like Prisma:
```typescript
// Interactive transactions
const result = await prisma.$transaction(async (tx) => {
const user = await tx.user.create({
data: { email: "john@example.com", name: "John" },
});
const post = await tx.post.create({
data: {
title: "Hello World",
authorId: user.id,
},
});
return { user, post };
});
// Batch transactions
const [user, post] = await prisma.$transaction([
prisma.user.create({ data: { email: "jane@example.com" } }),
prisma.post.create({ data: { title: "My Post", authorId: "1" } }),
]);
```
## Error Handling
Standard Prisma error types are supported:
```typescript
import {
PrismaClientKnownRequestError,
PrismaClientValidationError,
} from "@dataql/prisma-adapter";
try {
await prisma.user.create({
data: { email: "invalid-email" },
});
} catch (error) {
if (error instanceof PrismaClientKnownRequestError) {
if (error.code === "P2002") {
console.log("Unique constraint violation");
}
} else if (error instanceof PrismaClientValidationError) {
console.log("Validation error:", error.message);
}
}
```
## Limitations
Some advanced Prisma features are not yet supported:
- Raw SQL queries (`$queryRaw`, `$executeRaw`)
- Advanced aggregations (`groupBy`)
- Full-text search
- Complex nested writes
- Prisma schema migrations (use DataQL's schema evolution instead)
- Prisma Studio integration
- Database introspection
If you need these features, please [open an issue](https://github.com/dataql/dataql/issues).
## License
MIT