@hazeljs/prisma 0.2.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +576 -0
- package/dist/base.repository.d.ts +45 -0
- package/dist/base.repository.d.ts.map +1 -0
- package/dist/base.repository.js +82 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/prisma.module.d.ts +3 -0
- package/dist/prisma.module.d.ts.map +1 -0
- package/dist/prisma.module.js +20 -0
- package/dist/prisma.service.d.ts +7 -0
- package/dist/prisma.service.d.ts.map +1 -0
- package/dist/prisma.service.js +77 -0
- package/dist/repository.decorator.d.ts +5 -0
- package/dist/repository.decorator.d.ts.map +1 -0
- package/dist/repository.decorator.js +28 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
# @hazeljs/prisma
|
|
2
|
+
|
|
3
|
+
**Prisma ORM Integration for HazelJS**
|
|
4
|
+
|
|
5
|
+
First-class Prisma support with repository pattern, automatic migrations, and type-safe database access.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@hazeljs/prisma)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- ๐ฏ **Type-Safe Queries** - Full TypeScript support with Prisma
|
|
13
|
+
- ๐๏ธ **Repository Pattern** - Clean data access layer
|
|
14
|
+
- ๐จ **Decorator Support** - `@PrismaModel` decorator
|
|
15
|
+
- ๐ **Transaction Support** - Built-in transaction management
|
|
16
|
+
- ๐ **Query Builder** - Fluent query interface
|
|
17
|
+
- ๐ **Dependency Injection** - Seamless DI integration
|
|
18
|
+
- ๐งช **Testing Utilities** - Mock Prisma for testing
|
|
19
|
+
- ๐ **Connection Pooling** - Automatic connection management
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @hazeljs/prisma @prisma/client
|
|
25
|
+
npm install -D prisma
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
### 1. Initialize Prisma
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx prisma init
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 2. Define Schema
|
|
37
|
+
|
|
38
|
+
```prisma
|
|
39
|
+
// prisma/schema.prisma
|
|
40
|
+
generator client {
|
|
41
|
+
provider = "prisma-client-js"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
datasource db {
|
|
45
|
+
provider = "postgresql"
|
|
46
|
+
url = env("DATABASE_URL")
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
model User {
|
|
50
|
+
id String @id @default(uuid())
|
|
51
|
+
email String @unique
|
|
52
|
+
name String
|
|
53
|
+
posts Post[]
|
|
54
|
+
createdAt DateTime @default(now())
|
|
55
|
+
updatedAt DateTime @updatedAt
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
model Post {
|
|
59
|
+
id String @id @default(uuid())
|
|
60
|
+
title String
|
|
61
|
+
content String?
|
|
62
|
+
published Boolean @default(false)
|
|
63
|
+
authorId String
|
|
64
|
+
author User @relation(fields: [authorId], references: [id])
|
|
65
|
+
createdAt DateTime @default(now())
|
|
66
|
+
updatedAt DateTime @updatedAt
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 3. Generate Prisma Client
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npx prisma generate
|
|
74
|
+
npx prisma migrate dev --name init
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 4. Configure Module
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { HazelModule } from '@hazeljs/core';
|
|
81
|
+
import { PrismaModule } from '@hazeljs/prisma';
|
|
82
|
+
|
|
83
|
+
@HazelModule({
|
|
84
|
+
imports: [
|
|
85
|
+
PrismaModule.forRoot({
|
|
86
|
+
connectionString: process.env.DATABASE_URL,
|
|
87
|
+
}),
|
|
88
|
+
],
|
|
89
|
+
})
|
|
90
|
+
export class AppModule {}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 5. Create Repository
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { Injectable } from '@hazeljs/core';
|
|
97
|
+
import { PrismaService, BaseRepository, PrismaModel } from '@hazeljs/prisma';
|
|
98
|
+
|
|
99
|
+
@Injectable()
|
|
100
|
+
@PrismaModel('User')
|
|
101
|
+
export class UserRepository extends BaseRepository {
|
|
102
|
+
constructor(prisma: PrismaService) {
|
|
103
|
+
super(prisma);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Custom methods
|
|
107
|
+
async findByEmail(email: string) {
|
|
108
|
+
return this.prisma.user.findUnique({ where: { email } });
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async findWithPosts(id: string) {
|
|
112
|
+
return this.prisma.user.findUnique({
|
|
113
|
+
where: { id },
|
|
114
|
+
include: { posts: true },
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 6. Use in Service
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { Injectable } from '@hazeljs/core';
|
|
124
|
+
|
|
125
|
+
@Injectable()
|
|
126
|
+
export class UserService {
|
|
127
|
+
constructor(private userRepository: UserRepository) {}
|
|
128
|
+
|
|
129
|
+
async create(data: { email: string; name: string }) {
|
|
130
|
+
return this.userRepository.create({ data });
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async findAll() {
|
|
134
|
+
return this.userRepository.findMany();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async findOne(id: string) {
|
|
138
|
+
return this.userRepository.findUnique({ where: { id } });
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async update(id: string, data: any) {
|
|
142
|
+
return this.userRepository.update({
|
|
143
|
+
where: { id },
|
|
144
|
+
data,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async delete(id: string) {
|
|
149
|
+
return this.userRepository.delete({ where: { id } });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Base Repository
|
|
155
|
+
|
|
156
|
+
The `BaseRepository` provides common CRUD operations:
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
class BaseRepository {
|
|
160
|
+
// Create
|
|
161
|
+
create(args: Prisma.UserCreateArgs): Promise<User>;
|
|
162
|
+
createMany(args: Prisma.UserCreateManyArgs): Promise<Prisma.BatchPayload>;
|
|
163
|
+
|
|
164
|
+
// Read
|
|
165
|
+
findUnique(args: Prisma.UserFindUniqueArgs): Promise<User | null>;
|
|
166
|
+
findFirst(args: Prisma.UserFindFirstArgs): Promise<User | null>;
|
|
167
|
+
findMany(args?: Prisma.UserFindManyArgs): Promise<User[]>;
|
|
168
|
+
count(args?: Prisma.UserCountArgs): Promise<number>;
|
|
169
|
+
|
|
170
|
+
// Update
|
|
171
|
+
update(args: Prisma.UserUpdateArgs): Promise<User>;
|
|
172
|
+
updateMany(args: Prisma.UserUpdateManyArgs): Promise<Prisma.BatchPayload>;
|
|
173
|
+
upsert(args: Prisma.UserUpsertArgs): Promise<User>;
|
|
174
|
+
|
|
175
|
+
// Delete
|
|
176
|
+
delete(args: Prisma.UserDeleteArgs): Promise<User>;
|
|
177
|
+
deleteMany(args?: Prisma.UserDeleteManyArgs): Promise<Prisma.BatchPayload>;
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Transactions
|
|
182
|
+
|
|
183
|
+
### Using PrismaService
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
@Injectable()
|
|
187
|
+
export class TransferService {
|
|
188
|
+
constructor(private prisma: PrismaService) {}
|
|
189
|
+
|
|
190
|
+
async transfer(fromId: string, toId: string, amount: number) {
|
|
191
|
+
return this.prisma.$transaction(async (tx) => {
|
|
192
|
+
// Deduct from sender
|
|
193
|
+
await tx.account.update({
|
|
194
|
+
where: { id: fromId },
|
|
195
|
+
data: { balance: { decrement: amount } },
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Add to receiver
|
|
199
|
+
await tx.account.update({
|
|
200
|
+
where: { id: toId },
|
|
201
|
+
data: { balance: { increment: amount } },
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Create transaction record
|
|
205
|
+
return tx.transaction.create({
|
|
206
|
+
data: { fromId, toId, amount },
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Using Repository
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
@Injectable()
|
|
217
|
+
export class OrderService {
|
|
218
|
+
constructor(
|
|
219
|
+
private orderRepository: OrderRepository,
|
|
220
|
+
private inventoryRepository: InventoryRepository,
|
|
221
|
+
private prisma: PrismaService
|
|
222
|
+
) {}
|
|
223
|
+
|
|
224
|
+
async createOrder(userId: string, items: OrderItem[]) {
|
|
225
|
+
return this.prisma.$transaction(async (tx) => {
|
|
226
|
+
// Create order
|
|
227
|
+
const order = await tx.order.create({
|
|
228
|
+
data: {
|
|
229
|
+
userId,
|
|
230
|
+
items: { create: items },
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// Update inventory
|
|
235
|
+
for (const item of items) {
|
|
236
|
+
await tx.inventory.update({
|
|
237
|
+
where: { productId: item.productId },
|
|
238
|
+
data: { quantity: { decrement: item.quantity } },
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return order;
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Advanced Queries
|
|
249
|
+
|
|
250
|
+
### Relations
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
@Injectable()
|
|
254
|
+
export class UserRepository extends BaseRepository {
|
|
255
|
+
async findWithRelations(id: string) {
|
|
256
|
+
return this.prisma.user.findUnique({
|
|
257
|
+
where: { id },
|
|
258
|
+
include: {
|
|
259
|
+
posts: {
|
|
260
|
+
where: { published: true },
|
|
261
|
+
orderBy: { createdAt: 'desc' },
|
|
262
|
+
},
|
|
263
|
+
profile: true,
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Pagination
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
@Injectable()
|
|
274
|
+
export class PostRepository extends BaseRepository {
|
|
275
|
+
async findPaginated(page: number, limit: number) {
|
|
276
|
+
const skip = (page - 1) * limit;
|
|
277
|
+
|
|
278
|
+
const [posts, total] = await Promise.all([
|
|
279
|
+
this.prisma.post.findMany({
|
|
280
|
+
skip,
|
|
281
|
+
take: limit,
|
|
282
|
+
orderBy: { createdAt: 'desc' },
|
|
283
|
+
}),
|
|
284
|
+
this.prisma.post.count(),
|
|
285
|
+
]);
|
|
286
|
+
|
|
287
|
+
return {
|
|
288
|
+
data: posts,
|
|
289
|
+
meta: {
|
|
290
|
+
page,
|
|
291
|
+
limit,
|
|
292
|
+
total,
|
|
293
|
+
totalPages: Math.ceil(total / limit),
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Filtering
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
@Injectable()
|
|
304
|
+
export class ProductRepository extends BaseRepository {
|
|
305
|
+
async search(query: string, filters: {
|
|
306
|
+
category?: string;
|
|
307
|
+
minPrice?: number;
|
|
308
|
+
maxPrice?: number;
|
|
309
|
+
inStock?: boolean;
|
|
310
|
+
}) {
|
|
311
|
+
return this.prisma.product.findMany({
|
|
312
|
+
where: {
|
|
313
|
+
AND: [
|
|
314
|
+
{
|
|
315
|
+
OR: [
|
|
316
|
+
{ name: { contains: query, mode: 'insensitive' } },
|
|
317
|
+
{ description: { contains: query, mode: 'insensitive' } },
|
|
318
|
+
],
|
|
319
|
+
},
|
|
320
|
+
filters.category ? { category: filters.category } : {},
|
|
321
|
+
filters.minPrice ? { price: { gte: filters.minPrice } } : {},
|
|
322
|
+
filters.maxPrice ? { price: { lte: filters.maxPrice } } : {},
|
|
323
|
+
filters.inStock ? { stock: { gt: 0 } } : {},
|
|
324
|
+
],
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Aggregations
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
@Injectable()
|
|
335
|
+
export class AnalyticsRepository {
|
|
336
|
+
constructor(private prisma: PrismaService) {}
|
|
337
|
+
|
|
338
|
+
async getOrderStats() {
|
|
339
|
+
return this.prisma.order.aggregate({
|
|
340
|
+
_sum: { total: true },
|
|
341
|
+
_avg: { total: true },
|
|
342
|
+
_count: true,
|
|
343
|
+
_max: { total: true },
|
|
344
|
+
_min: { total: true },
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
async getRevenueByMonth() {
|
|
349
|
+
return this.prisma.$queryRaw`
|
|
350
|
+
SELECT
|
|
351
|
+
DATE_TRUNC('month', "createdAt") as month,
|
|
352
|
+
SUM(total) as revenue,
|
|
353
|
+
COUNT(*) as orders
|
|
354
|
+
FROM "Order"
|
|
355
|
+
GROUP BY month
|
|
356
|
+
ORDER BY month DESC
|
|
357
|
+
`;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## Middleware
|
|
363
|
+
|
|
364
|
+
Add Prisma middleware for logging, soft deletes, etc:
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
@Injectable()
|
|
368
|
+
export class PrismaService extends PrismaClient {
|
|
369
|
+
constructor() {
|
|
370
|
+
super();
|
|
371
|
+
|
|
372
|
+
// Logging middleware
|
|
373
|
+
this.$use(async (params, next) => {
|
|
374
|
+
const before = Date.now();
|
|
375
|
+
const result = await next(params);
|
|
376
|
+
const after = Date.now();
|
|
377
|
+
|
|
378
|
+
console.log(`Query ${params.model}.${params.action} took ${after - before}ms`);
|
|
379
|
+
return result;
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
// Soft delete middleware
|
|
383
|
+
this.$use(async (params, next) => {
|
|
384
|
+
if (params.action === 'delete') {
|
|
385
|
+
params.action = 'update';
|
|
386
|
+
params.args['data'] = { deletedAt: new Date() };
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (params.action === 'deleteMany') {
|
|
390
|
+
params.action = 'updateMany';
|
|
391
|
+
if (params.args.data != undefined) {
|
|
392
|
+
params.args.data['deletedAt'] = new Date();
|
|
393
|
+
} else {
|
|
394
|
+
params.args['data'] = { deletedAt: new Date() };
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return next(params);
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Seeding
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
// prisma/seed.ts
|
|
408
|
+
import { PrismaClient } from '@prisma/client';
|
|
409
|
+
|
|
410
|
+
const prisma = new PrismaClient();
|
|
411
|
+
|
|
412
|
+
async function main() {
|
|
413
|
+
// Create users
|
|
414
|
+
const alice = await prisma.user.create({
|
|
415
|
+
data: {
|
|
416
|
+
email: 'alice@example.com',
|
|
417
|
+
name: 'Alice',
|
|
418
|
+
posts: {
|
|
419
|
+
create: [
|
|
420
|
+
{
|
|
421
|
+
title: 'First Post',
|
|
422
|
+
content: 'Hello World!',
|
|
423
|
+
published: true,
|
|
424
|
+
},
|
|
425
|
+
],
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
const bob = await prisma.user.create({
|
|
431
|
+
data: {
|
|
432
|
+
email: 'bob@example.com',
|
|
433
|
+
name: 'Bob',
|
|
434
|
+
},
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
console.log({ alice, bob });
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
main()
|
|
441
|
+
.catch((e) => {
|
|
442
|
+
console.error(e);
|
|
443
|
+
process.exit(1);
|
|
444
|
+
})
|
|
445
|
+
.finally(async () => {
|
|
446
|
+
await prisma.$disconnect();
|
|
447
|
+
});
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Add to `package.json`:
|
|
451
|
+
|
|
452
|
+
```json
|
|
453
|
+
{
|
|
454
|
+
"prisma": {
|
|
455
|
+
"seed": "ts-node prisma/seed.ts"
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
Run seed:
|
|
461
|
+
|
|
462
|
+
```bash
|
|
463
|
+
npx prisma db seed
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
## Testing
|
|
467
|
+
|
|
468
|
+
### Mock Prisma Service
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
import { TestingModule } from '@hazeljs/core';
|
|
472
|
+
import { UserService } from './user.service';
|
|
473
|
+
import { UserRepository } from './user.repository';
|
|
474
|
+
|
|
475
|
+
describe('UserService', () => {
|
|
476
|
+
let service: UserService;
|
|
477
|
+
let repository: UserRepository;
|
|
478
|
+
|
|
479
|
+
const mockPrisma = {
|
|
480
|
+
user: {
|
|
481
|
+
create: jest.fn(),
|
|
482
|
+
findMany: jest.fn(),
|
|
483
|
+
findUnique: jest.fn(),
|
|
484
|
+
update: jest.fn(),
|
|
485
|
+
delete: jest.fn(),
|
|
486
|
+
},
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
beforeEach(async () => {
|
|
490
|
+
const module = await TestingModule.create({
|
|
491
|
+
providers: [
|
|
492
|
+
UserService,
|
|
493
|
+
{
|
|
494
|
+
provide: UserRepository,
|
|
495
|
+
useValue: {
|
|
496
|
+
create: mockPrisma.user.create,
|
|
497
|
+
findMany: mockPrisma.user.findMany,
|
|
498
|
+
findUnique: mockPrisma.user.findUnique,
|
|
499
|
+
update: mockPrisma.user.update,
|
|
500
|
+
delete: mockPrisma.user.delete,
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
],
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
service = module.get(UserService);
|
|
507
|
+
repository = module.get(UserRepository);
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
it('should create a user', async () => {
|
|
511
|
+
const userData = { email: 'test@example.com', name: 'Test' };
|
|
512
|
+
mockPrisma.user.create.mockResolvedValue({ id: '1', ...userData });
|
|
513
|
+
|
|
514
|
+
const result = await service.create(userData);
|
|
515
|
+
|
|
516
|
+
expect(result).toEqual({ id: '1', ...userData });
|
|
517
|
+
expect(mockPrisma.user.create).toHaveBeenCalledWith({ data: userData });
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
## Best Practices
|
|
523
|
+
|
|
524
|
+
1. **Use Repositories** - Encapsulate data access logic
|
|
525
|
+
2. **Type Safety** - Leverage Prisma's generated types
|
|
526
|
+
3. **Transactions** - Use transactions for related operations
|
|
527
|
+
4. **Indexes** - Add indexes for frequently queried fields
|
|
528
|
+
5. **Migrations** - Always use migrations, never modify schema directly
|
|
529
|
+
6. **Connection Pooling** - Configure appropriate pool size
|
|
530
|
+
7. **Error Handling** - Handle Prisma errors gracefully
|
|
531
|
+
8. **Soft Deletes** - Implement soft deletes with middleware
|
|
532
|
+
|
|
533
|
+
## Migration Commands
|
|
534
|
+
|
|
535
|
+
```bash
|
|
536
|
+
# Create migration
|
|
537
|
+
npx prisma migrate dev --name add_user_role
|
|
538
|
+
|
|
539
|
+
# Apply migrations
|
|
540
|
+
npx prisma migrate deploy
|
|
541
|
+
|
|
542
|
+
# Reset database
|
|
543
|
+
npx prisma migrate reset
|
|
544
|
+
|
|
545
|
+
# Generate client
|
|
546
|
+
npx prisma generate
|
|
547
|
+
|
|
548
|
+
# Open Prisma Studio
|
|
549
|
+
npx prisma studio
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
## Examples
|
|
553
|
+
|
|
554
|
+
See the [examples](../../example/src/prisma) directory for complete working examples.
|
|
555
|
+
|
|
556
|
+
## Testing
|
|
557
|
+
|
|
558
|
+
```bash
|
|
559
|
+
npm test
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
## Contributing
|
|
563
|
+
|
|
564
|
+
Contributions are welcome! Please read our [Contributing Guide](../../CONTRIBUTING.md) for details.
|
|
565
|
+
|
|
566
|
+
## License
|
|
567
|
+
|
|
568
|
+
MIT ยฉ [HazelJS](https://hazeljs.com)
|
|
569
|
+
|
|
570
|
+
## Links
|
|
571
|
+
|
|
572
|
+
- [Documentation](https://hazeljs.com/docs/packages/prisma)
|
|
573
|
+
- [Prisma Docs](https://www.prisma.io/docs)
|
|
574
|
+
- [GitHub](https://github.com/hazel-js/hazeljs)
|
|
575
|
+
- [Issues](https://github.com/hazeljs/hazel-js/issues)
|
|
576
|
+
- [Discord](https://discord.gg/hazeljs)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { PrismaService } from './prisma.service';
|
|
2
|
+
export type PrismaModel = {
|
|
3
|
+
id: number;
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
};
|
|
6
|
+
export type WhereUniqueInput = {
|
|
7
|
+
id?: number;
|
|
8
|
+
[key: string]: unknown;
|
|
9
|
+
};
|
|
10
|
+
export type UpdateInput = {
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
};
|
|
13
|
+
type PrismaModelDelegate = {
|
|
14
|
+
findMany: () => Promise<unknown[]>;
|
|
15
|
+
findUnique: (args: {
|
|
16
|
+
where: WhereUniqueInput;
|
|
17
|
+
}) => Promise<unknown | null>;
|
|
18
|
+
create: (args: {
|
|
19
|
+
data: unknown;
|
|
20
|
+
}) => Promise<unknown>;
|
|
21
|
+
update: (args: {
|
|
22
|
+
where: WhereUniqueInput;
|
|
23
|
+
data: UpdateInput;
|
|
24
|
+
}) => Promise<unknown>;
|
|
25
|
+
delete: (args: {
|
|
26
|
+
where: WhereUniqueInput;
|
|
27
|
+
}) => Promise<unknown>;
|
|
28
|
+
count: (args?: unknown) => Promise<number>;
|
|
29
|
+
};
|
|
30
|
+
export declare abstract class BaseRepository<T extends PrismaModel> {
|
|
31
|
+
protected readonly prisma: PrismaService;
|
|
32
|
+
protected readonly model: string;
|
|
33
|
+
constructor(prisma: PrismaService, model: string);
|
|
34
|
+
protected get prismaClient(): PrismaService;
|
|
35
|
+
protected get modelDelegate(): PrismaModelDelegate;
|
|
36
|
+
protected handleError(error: unknown): never;
|
|
37
|
+
findMany(): Promise<T[]>;
|
|
38
|
+
findOne(where: WhereUniqueInput): Promise<T | null>;
|
|
39
|
+
create(data: Omit<T, 'id'>): Promise<T>;
|
|
40
|
+
update(where: WhereUniqueInput, data: UpdateInput): Promise<T>;
|
|
41
|
+
delete(where: WhereUniqueInput): Promise<T>;
|
|
42
|
+
count(args?: unknown): Promise<number>;
|
|
43
|
+
}
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=base.repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.repository.d.ts","sourceRoot":"","sources":["../src/base.repository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAKjD,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACnC,UAAU,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,gBAAgB,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC3E,MAAM,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,MAAM,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,gBAAgB,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnF,MAAM,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,gBAAgB,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAChE,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC5C,CAAC;AAEF,8BACsB,cAAc,CAAC,CAAC,SAAS,WAAW;IAItD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,aAAa;IAH1C,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAGZ,MAAM,EAAE,aAAa,EACxC,KAAK,EAAE,MAAM;IAKf,SAAS,KAAK,YAAY,IAAI,aAAa,CAE1C;IAED,SAAS,KAAK,aAAa,IAAI,mBAAmB,CAEjD;IAED,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK;IA4BtC,QAAQ,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC;IAKxB,OAAO,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAKnD,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAKvC,MAAM,CAAC,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IAK9D,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;IAK3C,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;CAG7C"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.BaseRepository = void 0;
|
|
16
|
+
const core_1 = require("@hazeljs/core");
|
|
17
|
+
const prisma_service_1 = require("./prisma.service");
|
|
18
|
+
const library_1 = require("@prisma/client/runtime/library");
|
|
19
|
+
const core_2 = __importDefault(require("@hazeljs/core"));
|
|
20
|
+
let BaseRepository = class BaseRepository {
|
|
21
|
+
constructor(prisma, model) {
|
|
22
|
+
this.prisma = prisma;
|
|
23
|
+
this.model = model;
|
|
24
|
+
}
|
|
25
|
+
get prismaClient() {
|
|
26
|
+
return this.prisma;
|
|
27
|
+
}
|
|
28
|
+
get modelDelegate() {
|
|
29
|
+
return this.prismaClient[this.model];
|
|
30
|
+
}
|
|
31
|
+
handleError(error) {
|
|
32
|
+
core_2.default.error('Database error:', error);
|
|
33
|
+
if (error instanceof library_1.PrismaClientKnownRequestError) {
|
|
34
|
+
let errorMessage;
|
|
35
|
+
let target;
|
|
36
|
+
switch (error.code) {
|
|
37
|
+
case 'P2002':
|
|
38
|
+
target = error.meta?.target;
|
|
39
|
+
errorMessage = `Unique constraint violation on field${target ? `s: ${target.join(', ')}` : ''}`;
|
|
40
|
+
break;
|
|
41
|
+
case 'P2025':
|
|
42
|
+
errorMessage = 'Record not found';
|
|
43
|
+
break;
|
|
44
|
+
case 'P2003':
|
|
45
|
+
errorMessage = 'Foreign key constraint violation';
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
errorMessage = `Database error: ${error.message}`;
|
|
49
|
+
}
|
|
50
|
+
throw new Error(errorMessage);
|
|
51
|
+
}
|
|
52
|
+
throw new Error(`Database error: ${error.message}`);
|
|
53
|
+
}
|
|
54
|
+
async findMany() {
|
|
55
|
+
const result = await this.modelDelegate.findMany();
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
async findOne(where) {
|
|
59
|
+
const result = await this.modelDelegate.findUnique({ where });
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
async create(data) {
|
|
63
|
+
const result = await this.modelDelegate.create({ data });
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
async update(where, data) {
|
|
67
|
+
const result = await this.modelDelegate.update({ where, data });
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
async delete(where) {
|
|
71
|
+
const result = await this.modelDelegate.delete({ where });
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
async count(args) {
|
|
75
|
+
return this.modelDelegate.count(args);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
exports.BaseRepository = BaseRepository;
|
|
79
|
+
exports.BaseRepository = BaseRepository = __decorate([
|
|
80
|
+
(0, core_1.Injectable)(),
|
|
81
|
+
__metadata("design:paramtypes", [prisma_service_1.PrismaService, String])
|
|
82
|
+
], BaseRepository);
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hazeljs/prisma - Prisma integration for HazelJS
|
|
3
|
+
*/
|
|
4
|
+
export { PrismaModule } from './prisma.module';
|
|
5
|
+
export { PrismaService } from './prisma.service';
|
|
6
|
+
export { BaseRepository, type PrismaModel, type WhereUniqueInput, type UpdateInput, } from './base.repository';
|
|
7
|
+
export { Repository } from './repository.decorator';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EACL,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,WAAW,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @hazeljs/prisma - Prisma integration for HazelJS
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Repository = exports.BaseRepository = exports.PrismaService = exports.PrismaModule = void 0;
|
|
7
|
+
var prisma_module_1 = require("./prisma.module");
|
|
8
|
+
Object.defineProperty(exports, "PrismaModule", { enumerable: true, get: function () { return prisma_module_1.PrismaModule; } });
|
|
9
|
+
var prisma_service_1 = require("./prisma.service");
|
|
10
|
+
Object.defineProperty(exports, "PrismaService", { enumerable: true, get: function () { return prisma_service_1.PrismaService; } });
|
|
11
|
+
var base_repository_1 = require("./base.repository");
|
|
12
|
+
Object.defineProperty(exports, "BaseRepository", { enumerable: true, get: function () { return base_repository_1.BaseRepository; } });
|
|
13
|
+
var repository_decorator_1 = require("./repository.decorator");
|
|
14
|
+
Object.defineProperty(exports, "Repository", { enumerable: true, get: function () { return repository_decorator_1.Repository; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prisma.module.d.ts","sourceRoot":"","sources":["../src/prisma.module.ts"],"names":[],"mappings":"AAGA,qBAIa,YAAY;CAAG"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.PrismaModule = void 0;
|
|
10
|
+
const core_1 = require("@hazeljs/core");
|
|
11
|
+
const prisma_service_1 = require("./prisma.service");
|
|
12
|
+
let PrismaModule = class PrismaModule {
|
|
13
|
+
};
|
|
14
|
+
exports.PrismaModule = PrismaModule;
|
|
15
|
+
exports.PrismaModule = PrismaModule = __decorate([
|
|
16
|
+
(0, core_1.Module)({
|
|
17
|
+
providers: [prisma_service_1.PrismaService],
|
|
18
|
+
exports: [prisma_service_1.PrismaService],
|
|
19
|
+
})
|
|
20
|
+
], PrismaModule);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prisma.service.d.ts","sourceRoot":"","sources":["../src/prisma.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAwB9C,qBACa,aAAc,SAAQ,YAAY;;IAoCvC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAU7B,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;CASvC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.PrismaService = void 0;
|
|
16
|
+
const core_1 = require("@hazeljs/core");
|
|
17
|
+
const client_1 = require("@prisma/client");
|
|
18
|
+
const core_2 = __importDefault(require("@hazeljs/core"));
|
|
19
|
+
function isQueryEvent(event) {
|
|
20
|
+
return 'query' in event && 'params' in event && 'duration' in event;
|
|
21
|
+
}
|
|
22
|
+
function isErrorEvent(event) {
|
|
23
|
+
return 'message' in event;
|
|
24
|
+
}
|
|
25
|
+
let PrismaService = class PrismaService extends client_1.PrismaClient {
|
|
26
|
+
constructor() {
|
|
27
|
+
super({
|
|
28
|
+
log: [
|
|
29
|
+
{
|
|
30
|
+
emit: 'event',
|
|
31
|
+
level: 'query',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
emit: 'event',
|
|
35
|
+
level: 'error',
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
this.$on('query', (e) => {
|
|
40
|
+
if (isQueryEvent(e)) {
|
|
41
|
+
core_2.default.debug(`Query: ${e.query}`);
|
|
42
|
+
core_2.default.debug(`Params: ${e.params}`);
|
|
43
|
+
core_2.default.debug(`Duration: ${e.duration}ms`);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
this.$on('error', (e) => {
|
|
47
|
+
if (isErrorEvent(e)) {
|
|
48
|
+
core_2.default.error('Prisma Error:', e);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async onModuleInit() {
|
|
53
|
+
try {
|
|
54
|
+
await this.$connect();
|
|
55
|
+
core_2.default.info('Connected to database');
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
core_2.default.error('Failed to connect to database:', error);
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async onModuleDestroy() {
|
|
63
|
+
try {
|
|
64
|
+
await this.$disconnect();
|
|
65
|
+
core_2.default.info('Disconnected from database');
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
core_2.default.error('Error disconnecting from database:', error);
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
exports.PrismaService = PrismaService;
|
|
74
|
+
exports.PrismaService = PrismaService = __decorate([
|
|
75
|
+
(0, core_1.Injectable)(),
|
|
76
|
+
__metadata("design:paramtypes", [])
|
|
77
|
+
], PrismaService);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { RepositoryOptions } from '@hazeljs/core';
|
|
2
|
+
import 'reflect-metadata';
|
|
3
|
+
export declare function Repository(options: RepositoryOptions): ClassDecorator;
|
|
4
|
+
export declare function InjectRepository(): ParameterDecorator;
|
|
5
|
+
//# sourceMappingURL=repository.decorator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.decorator.d.ts","sourceRoot":"","sources":["../src/repository.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,kBAAkB,CAAC;AAE1B,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAIrE;AAED,wBAAgB,gBAAgB,IAAI,kBAAkB,CA0BrD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Repository = Repository;
|
|
4
|
+
exports.InjectRepository = InjectRepository;
|
|
5
|
+
require("reflect-metadata");
|
|
6
|
+
function Repository(options) {
|
|
7
|
+
return function (target) {
|
|
8
|
+
Reflect.defineMetadata('hazel:repository', options, target);
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
function InjectRepository() {
|
|
12
|
+
return function (target, propertyKey, parameterIndex) {
|
|
13
|
+
if (!propertyKey) {
|
|
14
|
+
throw new Error('InjectRepository decorator must be used on a method parameter');
|
|
15
|
+
}
|
|
16
|
+
const repositoryType = Reflect.getMetadata('design:paramtypes', target, propertyKey)[parameterIndex];
|
|
17
|
+
const model = Reflect.getMetadata('hazel:repository:model', repositoryType);
|
|
18
|
+
if (!model) {
|
|
19
|
+
throw new Error(`Repository ${repositoryType.name} is not decorated with @Repository`);
|
|
20
|
+
}
|
|
21
|
+
const repositories = Reflect.getMetadata('hazel:repositories', target) || [];
|
|
22
|
+
repositories.push({
|
|
23
|
+
index: parameterIndex,
|
|
24
|
+
model,
|
|
25
|
+
});
|
|
26
|
+
Reflect.defineMetadata('hazel:repositories', repositories, target);
|
|
27
|
+
};
|
|
28
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hazeljs/prisma",
|
|
3
|
+
"version": "0.2.0-beta.1",
|
|
4
|
+
"description": "Prisma ORM integration for HazelJS framework",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"test": "jest --coverage --passWithNoTests",
|
|
13
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
14
|
+
"lint:fix": "eslint \"src/**/*.ts\" --fix",
|
|
15
|
+
"clean": "rm -rf dist"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@hazeljs/core": "file:../core",
|
|
19
|
+
"@prisma/client": "^6.8.2"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^20.17.50",
|
|
23
|
+
"@typescript-eslint/eslint-plugin": "^8.18.2",
|
|
24
|
+
"@typescript-eslint/parser": "^8.18.2",
|
|
25
|
+
"eslint": "^8.56.0",
|
|
26
|
+
"jest": "^29.7.0",
|
|
27
|
+
"prisma": "^6.8.2",
|
|
28
|
+
"ts-jest": "^29.1.2",
|
|
29
|
+
"typescript": "^5.3.3"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/hazel-js/hazeljs.git",
|
|
37
|
+
"directory": "packages/prisma"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"hazeljs",
|
|
41
|
+
"prisma",
|
|
42
|
+
"orm",
|
|
43
|
+
"database"
|
|
44
|
+
],
|
|
45
|
+
"author": "Muhammad Arslan <marslan@hazeljs.com>",
|
|
46
|
+
"license": "MIT"
|
|
47
|
+
}
|