prisma-flare 1.0.0

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.
Files changed (45) hide show
  1. package/dist/cli/db-create.cjs +240 -0
  2. package/dist/cli/db-create.d.cts +1 -0
  3. package/dist/cli/db-create.d.ts +1 -0
  4. package/dist/cli/db-create.js +217 -0
  5. package/dist/cli/db-drop.cjs +263 -0
  6. package/dist/cli/db-drop.d.cts +1 -0
  7. package/dist/cli/db-drop.d.ts +1 -0
  8. package/dist/cli/db-drop.js +240 -0
  9. package/dist/cli/db-migrate.cjs +318 -0
  10. package/dist/cli/db-migrate.d.cts +1 -0
  11. package/dist/cli/db-migrate.d.ts +1 -0
  12. package/dist/cli/db-migrate.js +295 -0
  13. package/dist/cli/db-reset.cjs +110 -0
  14. package/dist/cli/db-reset.d.cts +1 -0
  15. package/dist/cli/db-reset.d.ts +1 -0
  16. package/dist/cli/db-reset.js +87 -0
  17. package/dist/cli/db-seed.cjs +87 -0
  18. package/dist/cli/db-seed.d.cts +1 -0
  19. package/dist/cli/db-seed.d.ts +1 -0
  20. package/dist/cli/db-seed.js +64 -0
  21. package/dist/cli/index.cjs +352 -0
  22. package/dist/cli/index.d.cts +1 -0
  23. package/dist/cli/index.d.ts +1 -0
  24. package/dist/cli/index.js +328 -0
  25. package/dist/core/flareBuilder.cjs +681 -0
  26. package/dist/core/flareBuilder.d.cts +402 -0
  27. package/dist/core/flareBuilder.d.ts +402 -0
  28. package/dist/core/flareBuilder.js +658 -0
  29. package/dist/core/hooks.cjs +243 -0
  30. package/dist/core/hooks.d.cts +13 -0
  31. package/dist/core/hooks.d.ts +13 -0
  32. package/dist/core/hooks.js +209 -0
  33. package/dist/generated.cjs +31 -0
  34. package/dist/generated.d.cts +4 -0
  35. package/dist/generated.d.ts +4 -0
  36. package/dist/generated.js +6 -0
  37. package/dist/index.cjs +1315 -0
  38. package/dist/index.d.cts +237 -0
  39. package/dist/index.d.ts +237 -0
  40. package/dist/index.js +1261 -0
  41. package/dist/prisma.types-nGNe1CG8.d.cts +201 -0
  42. package/dist/prisma.types-nGNe1CG8.d.ts +201 -0
  43. package/license.md +21 -0
  44. package/package.json +115 -0
  45. package/readme.md +957 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,1315 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ ExtendedPrismaClient: () => ExtendedPrismaClient,
34
+ FlareBuilder: () => FlareBuilder,
35
+ FlareClient: () => FlareClient,
36
+ afterChange: () => afterChange,
37
+ afterCreate: () => afterCreate,
38
+ afterDelete: () => afterDelete,
39
+ afterUpdate: () => afterUpdate,
40
+ afterUpsert: () => afterUpsert,
41
+ beforeCreate: () => beforeCreate,
42
+ beforeDelete: () => beforeDelete,
43
+ beforeUpdate: () => beforeUpdate,
44
+ createHooksExtension: () => createHooksExtension,
45
+ dbAdapterRegistry: () => registry,
46
+ hookRegistry: () => hookRegistry_default,
47
+ loadCallbacks: () => loadCallbacks,
48
+ modelRegistry: () => modelRegistry,
49
+ registerHooks: () => registerHooks,
50
+ registerHooksLegacy: () => registerHooksLegacy
51
+ });
52
+ module.exports = __toCommonJS(index_exports);
53
+
54
+ // src/core/extendedPrismaClient.ts
55
+ var import_client = require("@prisma/client");
56
+
57
+ // src/core/modelRegistry.ts
58
+ var ModelRegistry = class {
59
+ constructor() {
60
+ this.models = /* @__PURE__ */ new Map();
61
+ }
62
+ /**
63
+ * Register a custom model class for a given model name.
64
+ * The model name should match the Prisma model name (e.g., 'user', 'post', 'enrollment')
65
+ * @param modelName - The lowercase model name (matching Prisma delegate name)
66
+ * @param modelClass - The custom class that extends FlareBuilder
67
+ */
68
+ register(modelName, modelClass) {
69
+ this.models.set(modelName.toLowerCase(), modelClass);
70
+ }
71
+ /**
72
+ * Register multiple models at once
73
+ * @param models - Object mapping model names to their classes
74
+ */
75
+ registerMany(models) {
76
+ for (const [name, modelClass] of Object.entries(models)) {
77
+ this.register(name, modelClass);
78
+ }
79
+ }
80
+ /**
81
+ * Get a custom model class by name
82
+ * @param modelName - The model name to look up
83
+ * @returns The model class or undefined if not registered
84
+ */
85
+ get(modelName) {
86
+ return this.models.get(modelName.toLowerCase());
87
+ }
88
+ /**
89
+ * Check if a model is registered
90
+ * @param modelName - The model name to check
91
+ */
92
+ has(modelName) {
93
+ return this.models.has(modelName.toLowerCase());
94
+ }
95
+ /**
96
+ * Create an instance of a registered model
97
+ * @param modelName - The model name to instantiate
98
+ * @returns A new instance of the custom model class, or undefined if not registered
99
+ */
100
+ create(modelName) {
101
+ const ModelClass = this.get(modelName);
102
+ if (ModelClass) {
103
+ return new ModelClass();
104
+ }
105
+ return void 0;
106
+ }
107
+ /**
108
+ * Clear all registered models (useful for testing)
109
+ */
110
+ clear() {
111
+ this.models.clear();
112
+ }
113
+ /**
114
+ * Get all registered model names
115
+ */
116
+ getRegisteredModels() {
117
+ return Array.from(this.models.keys());
118
+ }
119
+ };
120
+ var modelRegistry = new ModelRegistry();
121
+
122
+ // src/core/flareBuilder.ts
123
+ function deepClone(obj) {
124
+ if (obj === null || typeof obj !== "object") {
125
+ return obj;
126
+ }
127
+ if (typeof obj === "bigint") {
128
+ return obj;
129
+ }
130
+ if (typeof structuredClone === "function") {
131
+ try {
132
+ return structuredClone(obj);
133
+ } catch {
134
+ }
135
+ }
136
+ if (obj instanceof Date) {
137
+ return new Date(obj.getTime());
138
+ }
139
+ if (obj instanceof RegExp) {
140
+ return new RegExp(obj.source, obj.flags);
141
+ }
142
+ if (typeof Buffer !== "undefined" && Buffer.isBuffer(obj)) {
143
+ return Buffer.from(obj);
144
+ }
145
+ if (obj instanceof ArrayBuffer) {
146
+ return obj.slice(0);
147
+ }
148
+ if (ArrayBuffer.isView(obj) && !(obj instanceof DataView)) {
149
+ const TypedArrayConstructor = obj.constructor;
150
+ const buffer = obj.buffer instanceof ArrayBuffer ? obj.buffer.slice(0) : obj.buffer;
151
+ return new TypedArrayConstructor(buffer);
152
+ }
153
+ if (obj instanceof Map) {
154
+ const clonedMap = /* @__PURE__ */ new Map();
155
+ obj.forEach((value, key) => {
156
+ clonedMap.set(deepClone(key), deepClone(value));
157
+ });
158
+ return clonedMap;
159
+ }
160
+ if (obj instanceof Set) {
161
+ const clonedSet = /* @__PURE__ */ new Set();
162
+ obj.forEach((value) => {
163
+ clonedSet.add(deepClone(value));
164
+ });
165
+ return clonedSet;
166
+ }
167
+ if (Array.isArray(obj)) {
168
+ return obj.map((item) => deepClone(item));
169
+ }
170
+ if (typeof obj.toDecimalPlaces === "function") {
171
+ return obj;
172
+ }
173
+ const prototype = Object.getPrototypeOf(obj);
174
+ const cloned = Object.create(prototype);
175
+ for (const key in obj) {
176
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
177
+ cloned[key] = deepClone(obj[key]);
178
+ }
179
+ }
180
+ return cloned;
181
+ }
182
+ var FlareBuilder = class _FlareBuilder {
183
+ constructor(model, query = {}) {
184
+ this.model = model;
185
+ this.query = query;
186
+ }
187
+ /**
188
+ * Adds a where condition to the query with type safety from Prisma.
189
+ * Multiple where() calls are composed using AND logic to avoid silent overwrites.
190
+ * @param condition - Where filter matching your Prisma model
191
+ *
192
+ * @example
193
+ * // These conditions are AND-ed together:
194
+ * DB.posts
195
+ * .where({ published: true })
196
+ * .where({ authorId: 1 })
197
+ * .findMany()
198
+ * // Equivalent to: { AND: [{ published: true }, { authorId: 1 }] }
199
+ */
200
+ where(condition) {
201
+ if (!this.query.where || Object.keys(this.query.where).length === 0) {
202
+ this.query.where = condition;
203
+ } else {
204
+ const prevWhere = this.query.where;
205
+ this.query.where = { AND: [prevWhere, condition] };
206
+ }
207
+ return this;
208
+ }
209
+ /**
210
+ * Adds a where condition using AND logic (explicit alias for where())
211
+ * @param condition - Where filter matching your Prisma model
212
+ *
213
+ * @example
214
+ * DB.posts
215
+ * .where({ published: true })
216
+ * .andWhere({ createdAt: { gte: new Date('2024-01-01') } })
217
+ * .findMany()
218
+ */
219
+ andWhere(condition) {
220
+ return this.where(condition);
221
+ }
222
+ /**
223
+ * Adds a where condition using OR logic.
224
+ *
225
+ * ⚠️ **IMPORTANT**: `orWhere()` wraps the *entire* accumulated where clause:
226
+ * `OR([prevWhere, condition])`. This means:
227
+ *
228
+ * ```ts
229
+ * .where(A).orWhere(B).where(C) // becomes: (A OR B) AND C
230
+ * ```
231
+ *
232
+ * For complex boolean logic, prefer `whereGroup()` / `orWhereGroup()` for explicit control.
233
+ *
234
+ * @param condition - Where filter matching your Prisma model
235
+ *
236
+ * @example
237
+ * // Simple case - OK:
238
+ * DB.posts
239
+ * .where({ published: true })
240
+ * .orWhere({ featured: true })
241
+ * .findMany()
242
+ * // Result: published OR featured
243
+ *
244
+ * @example
245
+ * // For complex logic, use whereGroup instead:
246
+ * DB.posts
247
+ * .where({ published: true })
248
+ * .whereGroup(qb => qb
249
+ * .where({ category: 'news' })
250
+ * .orWhere({ category: 'tech' })
251
+ * )
252
+ * .findMany()
253
+ * // Result: published AND (category='news' OR category='tech')
254
+ */
255
+ orWhere(condition) {
256
+ if (!this.query.where || Object.keys(this.query.where).length === 0) {
257
+ this.query.where = condition;
258
+ } else {
259
+ const prevWhere = this.query.where;
260
+ this.query.where = { OR: [prevWhere, condition] };
261
+ }
262
+ return this;
263
+ }
264
+ /**
265
+ * Creates a grouped where condition using a callback.
266
+ * Use this for explicit control over boolean logic grouping.
267
+ * The callback receives a fresh builder - its accumulated where becomes a single group.
268
+ *
269
+ * @param callback - Function that builds the grouped condition
270
+ * @param mode - How to combine with existing where: 'AND' (default) or 'OR'
271
+ *
272
+ * @example
273
+ * // (status = 'active') AND (name LIKE 'A%' OR name LIKE 'B%')
274
+ * DB.users
275
+ * .where({ status: 'active' })
276
+ * .whereGroup(qb => qb
277
+ * .where({ name: { startsWith: 'A' } })
278
+ * .orWhere({ name: { startsWith: 'B' } })
279
+ * )
280
+ * .findMany()
281
+ *
282
+ * @example
283
+ * // (status = 'active') OR (role = 'admin' AND verified = true)
284
+ * DB.users
285
+ * .where({ status: 'active' })
286
+ * .whereGroup(qb => qb
287
+ * .where({ role: 'admin' })
288
+ * .where({ verified: true })
289
+ * , 'OR')
290
+ * .findMany()
291
+ */
292
+ whereGroup(callback, mode = "AND") {
293
+ const groupBuilder = new _FlareBuilder(this.model, {});
294
+ callback(groupBuilder);
295
+ const groupWhere = groupBuilder.getQuery().where;
296
+ if (!groupWhere || Object.keys(groupWhere).length === 0) {
297
+ return this;
298
+ }
299
+ if (!this.query.where || Object.keys(this.query.where).length === 0) {
300
+ this.query.where = groupWhere;
301
+ } else {
302
+ const prevWhere = this.query.where;
303
+ this.query.where = { [mode]: [prevWhere, groupWhere] };
304
+ }
305
+ return this;
306
+ }
307
+ /**
308
+ * Alias for whereGroup with OR mode.
309
+ * Creates a grouped condition that's OR-ed with existing where.
310
+ *
311
+ * @param callback - Function that builds the grouped condition
312
+ *
313
+ * @example
314
+ * // (published = true) OR (authorId = 1 AND draft = true)
315
+ * DB.posts
316
+ * .where({ published: true })
317
+ * .orWhereGroup(qb => qb
318
+ * .where({ authorId: 1 })
319
+ * .where({ draft: true })
320
+ * )
321
+ * .findMany()
322
+ */
323
+ orWhereGroup(callback) {
324
+ return this.whereGroup(callback, "OR");
325
+ }
326
+ /**
327
+ * Adds a where condition to the query for the specified id.
328
+ * Uses the same AND composition as where() for consistency.
329
+ * @param id - The id to search for
330
+ */
331
+ withId(id) {
332
+ if (!id) {
333
+ throw new Error("Id is required");
334
+ }
335
+ if (!this.query.where || Object.keys(this.query.where).length === 0) {
336
+ this.query.where = { id };
337
+ } else {
338
+ const prevWhere = this.query.where;
339
+ this.query.where = { AND: [prevWhere, { id }] };
340
+ }
341
+ return this;
342
+ }
343
+ /**
344
+ * Adds an order by condition to the query
345
+ * @param orderBy - OrderBy object matching your Prisma model
346
+ */
347
+ order(orderBy) {
348
+ this.query.orderBy = orderBy;
349
+ return this;
350
+ }
351
+ /**
352
+ * Gets the last record sorted by the specified field
353
+ * @param key - Field to sort by (defaults to 'createdAt')
354
+ */
355
+ last(key = "createdAt") {
356
+ return this.order({ [key]: "desc" }).limit(1);
357
+ }
358
+ /**
359
+ * Gets the first record sorted by the specified field
360
+ * @param key - Field to sort by (defaults to 'createdAt')
361
+ */
362
+ first(key = "createdAt") {
363
+ return this.order({ [key]: "asc" }).limit(1);
364
+ }
365
+ /**
366
+ * Sets a limit on the number of records to retrieve
367
+ * @param limit - Maximum number of records
368
+ */
369
+ limit(limit) {
370
+ this.query.take = limit;
371
+ return this;
372
+ }
373
+ /**
374
+ * Sets distinct fields for the query
375
+ * @param distinct - Fields to be distinct
376
+ */
377
+ distinct(distinct) {
378
+ this.query.distinct = distinct;
379
+ return this;
380
+ }
381
+ /**
382
+ * Selects specific fields to retrieve
383
+ * @param fields - Select object matching your Prisma model
384
+ */
385
+ select(fields) {
386
+ this.query.select = fields;
387
+ return this;
388
+ }
389
+ /**
390
+ * Selects only the specified field and returns its value
391
+ * @param field - Field name to retrieve
392
+ */
393
+ async only(field) {
394
+ this.query.select = { [field]: true };
395
+ const result = await this.model.findFirst(this.query);
396
+ if (!result) {
397
+ return null;
398
+ }
399
+ return result[field];
400
+ }
401
+ /**
402
+ * Returns the current query object
403
+ */
404
+ getQuery() {
405
+ return this.query;
406
+ }
407
+ include(relation, callback) {
408
+ let relationQuery = true;
409
+ if (callback) {
410
+ const builder = modelRegistry.create(relation) ?? new _FlareBuilder(null);
411
+ callback(builder);
412
+ relationQuery = builder.getQuery();
413
+ if (Object.keys(relationQuery).length === 0) {
414
+ relationQuery = true;
415
+ }
416
+ }
417
+ this.query.include = {
418
+ ...this.query.include,
419
+ [relation]: relationQuery
420
+ };
421
+ return this;
422
+ }
423
+ /**
424
+ * Groups results by specified fields
425
+ * @param groupBy - Fields to group by
426
+ */
427
+ groupBy(groupBy) {
428
+ this.query.by = groupBy;
429
+ return this;
430
+ }
431
+ /**
432
+ * Adds a having condition to the query
433
+ * @param condition - Having condition
434
+ */
435
+ having(condition) {
436
+ this.query.having = condition;
437
+ return this;
438
+ }
439
+ /**
440
+ * Skips the specified number of records
441
+ * @param offset - Number of records to skip
442
+ */
443
+ skip(offset) {
444
+ this.query.skip = offset;
445
+ return this;
446
+ }
447
+ /**
448
+ * Checks if any record exists matching the current query
449
+ * @param existenceKey - Key to check for existence (defaults to 'id')
450
+ */
451
+ async exists(existenceKey = "id") {
452
+ const result = await this.model.findFirst({
453
+ where: this.query.where,
454
+ select: { [existenceKey]: true }
455
+ });
456
+ return Boolean(result);
457
+ }
458
+ /**
459
+ * Paginates the results
460
+ * @param page - Page number (1-based)
461
+ * @param perPage - Number of records per page
462
+ */
463
+ async paginate(page = 1, perPage = 15) {
464
+ const skip = (page - 1) * perPage;
465
+ const take = perPage;
466
+ this.query.skip = skip;
467
+ this.query.take = take;
468
+ const [data, total] = await Promise.all([
469
+ this.model.findMany(this.query),
470
+ this.model.count({ where: this.query.where })
471
+ ]);
472
+ const lastPage = Math.ceil(total / perPage);
473
+ return {
474
+ data,
475
+ meta: {
476
+ total,
477
+ lastPage,
478
+ currentPage: page,
479
+ perPage,
480
+ prev: page > 1 ? page - 1 : null,
481
+ next: page < lastPage ? page + 1 : null
482
+ }
483
+ };
484
+ }
485
+ /**
486
+ * Conditionally executes a callback on the query builder
487
+ * @param condition - Boolean or function returning boolean
488
+ * @param callback - Function to execute if condition is true
489
+ */
490
+ when(condition, callback) {
491
+ const isTrue = typeof condition === "function" ? condition() : condition;
492
+ if (isTrue) {
493
+ callback(this);
494
+ }
495
+ return this;
496
+ }
497
+ /**
498
+ * Processes results in chunks to avoid memory issues
499
+ * @param size - Size of each chunk
500
+ * @param callback - Function to process each chunk
501
+ */
502
+ async chunk(size, callback) {
503
+ let page = 1;
504
+ let hasMore = true;
505
+ const originalSkip = this.query.skip;
506
+ const originalTake = this.query.take;
507
+ while (hasMore) {
508
+ this.query.skip = (page - 1) * size;
509
+ this.query.take = size;
510
+ const results = await this.model.findMany(this.query);
511
+ if (results.length > 0) {
512
+ await callback(results);
513
+ page++;
514
+ if (results.length < size) {
515
+ hasMore = false;
516
+ }
517
+ } else {
518
+ hasMore = false;
519
+ }
520
+ }
521
+ this.query.skip = originalSkip;
522
+ this.query.take = originalTake;
523
+ }
524
+ /**
525
+ * Clones the current query builder instance.
526
+ * Uses structuredClone for proper handling of Date, BigInt, etc.
527
+ */
528
+ clone() {
529
+ const queryCopy = deepClone(this.query);
530
+ return new _FlareBuilder(this.model, queryCopy);
531
+ }
532
+ /**
533
+ * Finds the first record matching the query or throws an error if none found
534
+ * Throws a Prisma NotFoundError if no record matches the query
535
+ * @throws {Prisma.NotFoundError} When no record matches the query
536
+ * @returns Promise resolving to the found record
537
+ */
538
+ async findFirstOrThrow() {
539
+ return this.model.findFirstOrThrow(this.query);
540
+ }
541
+ /**
542
+ * Finds a unique record by primary key or throws an error if not found
543
+ * Requires a unique constraint (typically the id field)
544
+ * Throws a Prisma NotFoundError if no record matches
545
+ * @throws {Prisma.NotFoundError} When no record is found
546
+ * @returns Promise resolving to the found record
547
+ */
548
+ async findUniqueOrThrow() {
549
+ return this.model.findUniqueOrThrow(this.query);
550
+ }
551
+ /**
552
+ * Finds all records matching the query
553
+ * Respects all previously set query conditions (where, orderBy, take, skip, include, select, distinct)
554
+ * @returns Promise resolving to an array of records matching the query
555
+ */
556
+ async findMany() {
557
+ return this.model.findMany(this.query);
558
+ }
559
+ /**
560
+ * Finds the first record matching the query
561
+ * Returns null if no record matches. To throw an error instead, use findFirstOrThrow()
562
+ * @returns Promise resolving to the first matching record or null
563
+ */
564
+ async findFirst() {
565
+ return this.model.findFirst(this.query);
566
+ }
567
+ /**
568
+ * Finds a unique record by primary key
569
+ * Returns null if no record is found. To throw an error instead, use findUniqueOrThrow()
570
+ * Requires a unique constraint in the where condition (typically the id field)
571
+ * @returns Promise resolving to the found record or null
572
+ */
573
+ async findUnique() {
574
+ return this.model.findUnique(this.query);
575
+ }
576
+ /**
577
+ * Creates a new record with the provided data
578
+ * Any hooks registered for 'create' operations will be triggered
579
+ * @param data - Data matching your Prisma model's create input
580
+ * @returns Promise resolving to the newly created record
581
+ */
582
+ async create(data) {
583
+ const query = { ...this.query, data };
584
+ return this.model.create(query);
585
+ }
586
+ /**
587
+ * Creates multiple records in a single operation
588
+ * More efficient than creating records individually
589
+ * Any hooks registered for 'create' operations will be triggered for each record
590
+ * @param data - Array of data objects matching your Prisma model's create input
591
+ * @returns Promise resolving to the count of created records
592
+ */
593
+ async createMany(data) {
594
+ const query = { ...this.query, data };
595
+ return this.model.createMany(query);
596
+ }
597
+ /**
598
+ * Deletes a single record matching the current query conditions
599
+ * Requires at least one unique constraint in the where condition (typically id)
600
+ * Any hooks registered for 'delete' operations will be triggered
601
+ * @param args - Optional additional delete arguments to override query conditions
602
+ * @returns Promise resolving to the deleted record
603
+ */
604
+ async delete(args) {
605
+ const query = args ? { ...this.query, ...args } : this.query;
606
+ return this.model.delete(query);
607
+ }
608
+ /**
609
+ * Deletes multiple records matching the current query conditions
610
+ * More efficient than deleting records individually
611
+ * Any hooks registered for 'delete' operations will be triggered for each record
612
+ * @param args - Optional additional delete arguments to override query conditions
613
+ * @returns Promise resolving to the count of deleted records
614
+ */
615
+ async deleteMany(args) {
616
+ const query = args ? { ...this.query, ...args } : this.query;
617
+ return this.model.deleteMany(query);
618
+ }
619
+ /**
620
+ * Updates a single record matching the current query conditions
621
+ * Requires at least one unique constraint in the where condition (typically id)
622
+ * Any hooks registered for 'update' operations will be triggered
623
+ * @param data - Data to update, matching your Prisma model's update input
624
+ * @returns Promise resolving to the updated record
625
+ */
626
+ async update(data) {
627
+ const query = { ...this.query, data };
628
+ return this.model.update(query);
629
+ }
630
+ /**
631
+ * Updates multiple records matching the current query conditions
632
+ * More efficient than updating records individually
633
+ * Any hooks registered for 'update' operations will be triggered for each record
634
+ * @param data - Data to update, matching your Prisma model's update input
635
+ * @returns Promise resolving to the count of updated records
636
+ */
637
+ async updateMany(data) {
638
+ const query = { ...this.query, data };
639
+ return this.model.updateMany(query);
640
+ }
641
+ /**
642
+ * Updates a record if it exists, otherwise creates a new record
643
+ * The record is uniquely identified by the where condition (typically id)
644
+ * Any hooks registered for 'update' or 'create' operations will be triggered accordingly
645
+ * @param args - Optional upsert arguments including where, update, and create data
646
+ * @returns Promise resolving to the upserted record
647
+ */
648
+ async upsert(args) {
649
+ const query = args ? { ...this.query, ...args } : this.query;
650
+ return this.model.upsert(query);
651
+ }
652
+ /**
653
+ * Counts the number of records matching the query
654
+ */
655
+ async count() {
656
+ return this.model.count(this.query);
657
+ }
658
+ /**
659
+ * Sums the specified numeric field
660
+ * @param field - Field name to sum
661
+ */
662
+ async sum(field) {
663
+ const result = await this.model.aggregate({
664
+ _sum: { [field]: true },
665
+ where: this.query.where
666
+ });
667
+ return result._sum[field];
668
+ }
669
+ /**
670
+ * Calculates the average of the specified numeric field
671
+ * @param field - Field name to average
672
+ */
673
+ async avg(field) {
674
+ const result = await this.model.aggregate({
675
+ _avg: { [field]: true },
676
+ where: this.query.where
677
+ });
678
+ return result._avg[field];
679
+ }
680
+ /**
681
+ * Finds the minimum value of the specified field
682
+ * @param field - Field name to find minimum
683
+ */
684
+ async min(field) {
685
+ const result = await this.model.aggregate({
686
+ _min: { [field]: true },
687
+ where: this.query.where
688
+ });
689
+ return result._min[field];
690
+ }
691
+ /**
692
+ * Finds the maximum value of the specified field
693
+ * @param field - Field name to find maximum
694
+ */
695
+ async max(field) {
696
+ const result = await this.model.aggregate({
697
+ _max: { [field]: true },
698
+ where: this.query.where
699
+ });
700
+ return result._max[field];
701
+ }
702
+ /**
703
+ * Plucks the specified field from all results
704
+ * @param field - Field name to pluck
705
+ */
706
+ async pluck(field) {
707
+ this.query.select = { [field]: true };
708
+ const results = await this.model.findMany(this.query);
709
+ return results.map((result) => result[field]);
710
+ }
711
+ };
712
+
713
+ // src/core/extendedPrismaClient.ts
714
+ var FlareClient = class extends import_client.PrismaClient {
715
+ constructor(options = {}) {
716
+ super(options);
717
+ }
718
+ /**
719
+ * Creates a new FlareBuilder instance for the specified model.
720
+ * @param modelName - The name of the model.
721
+ * @returns FlareBuilder instance
722
+ */
723
+ from(modelName) {
724
+ const key = modelName.charAt(0).toLowerCase() + modelName.slice(1);
725
+ const model = this[key];
726
+ if (!model) {
727
+ throw new Error(`Model ${modelName} does not exist on PrismaClient.`);
728
+ }
729
+ return new FlareBuilder(model);
730
+ }
731
+ /**
732
+ * Executes a transaction with the FlareClient capabilities.
733
+ * @param fn - The transaction function.
734
+ * @param options - Transaction options.
735
+ * @returns The result of the transaction.
736
+ */
737
+ async transaction(fn, options) {
738
+ return super.$transaction(async (tx) => {
739
+ const extendedTx = new Proxy(tx, {
740
+ get: (target, prop, receiver) => {
741
+ if (prop === "from") {
742
+ return (modelName) => {
743
+ const key = modelName.charAt(0).toLowerCase() + modelName.slice(1);
744
+ const model = target[key];
745
+ if (!model) {
746
+ throw new Error(`Model ${modelName} does not exist on TransactionClient.`);
747
+ }
748
+ return new FlareBuilder(model);
749
+ };
750
+ }
751
+ return Reflect.get(target, prop, receiver);
752
+ }
753
+ });
754
+ return fn(extendedTx);
755
+ }, options);
756
+ }
757
+ };
758
+ var ExtendedPrismaClient = FlareClient;
759
+
760
+ // src/core/hookRegistry.ts
761
+ function valuesEqual(a, b) {
762
+ if (a == null && b == null) return true;
763
+ if (a == null || b == null) return false;
764
+ if (a === b) return true;
765
+ if (a instanceof Date && b instanceof Date) {
766
+ return a.getTime() === b.getTime();
767
+ }
768
+ if (typeof a.toDecimalPlaces === "function" && typeof b.toDecimalPlaces === "function") {
769
+ return a.toString() === b.toString();
770
+ }
771
+ if (typeof a === "bigint" && typeof b === "bigint") {
772
+ return a === b;
773
+ }
774
+ if (typeof a === "object" && typeof b === "object") {
775
+ try {
776
+ return JSON.stringify(a) === JSON.stringify(b);
777
+ } catch {
778
+ return false;
779
+ }
780
+ }
781
+ return a === b;
782
+ }
783
+ var DEFAULT_CONFIG = {
784
+ enableColumnHooks: true,
785
+ maxRefetch: 1e3,
786
+ warnOnSkip: true
787
+ };
788
+ var HookRegistry = class {
789
+ constructor() {
790
+ this.hooks = {
791
+ before: {},
792
+ after: {}
793
+ };
794
+ this.columnHooks = {
795
+ afterChange: {}
796
+ };
797
+ this.fieldCache = {};
798
+ this.modelsWithColumnHooks = /* @__PURE__ */ new Set();
799
+ this.config = { ...DEFAULT_CONFIG };
800
+ }
801
+ /**
802
+ * Configure the hook system.
803
+ * @param config - Partial configuration to merge with defaults
804
+ *
805
+ * @example
806
+ * // Disable column hooks globally for performance
807
+ * hookRegistry.configure({ enableColumnHooks: false });
808
+ *
809
+ * @example
810
+ * // Increase maxRefetch limit
811
+ * hookRegistry.configure({ maxRefetch: 5000 });
812
+ *
813
+ * @example
814
+ * // Disable limit entirely (use with caution)
815
+ * hookRegistry.configure({ maxRefetch: Infinity });
816
+ */
817
+ configure(config) {
818
+ this.config = { ...this.config, ...config };
819
+ }
820
+ /**
821
+ * Get current configuration.
822
+ */
823
+ getConfig() {
824
+ return this.config;
825
+ }
826
+ addHook(model, action, timing, fn) {
827
+ const key = `${model}:${action}`;
828
+ if (!this.hooks[timing][key]) {
829
+ this.hooks[timing][key] = [];
830
+ }
831
+ this.hooks[timing][key].push(fn);
832
+ }
833
+ addColumnHook(model, column, fn) {
834
+ const key = `${model}:${column}`;
835
+ if (!this.columnHooks.afterChange[key]) {
836
+ this.columnHooks.afterChange[key] = [];
837
+ }
838
+ this.columnHooks.afterChange[key].push(fn);
839
+ this.modelsWithColumnHooks.add(model);
840
+ }
841
+ async runHooks(timing, model, action, args, prisma) {
842
+ const key = `${model}:${action}`;
843
+ const hooks = this.hooks[timing]?.[key] ?? [];
844
+ if (timing === "after") {
845
+ await Promise.all(hooks.map((hook) => hook(...args, prisma)));
846
+ } else {
847
+ for (const hook of hooks) {
848
+ await hook(...args, prisma);
849
+ }
850
+ }
851
+ }
852
+ async runColumnHooks(model, newData, prevData, prisma) {
853
+ const promises = [];
854
+ for (const column in newData) {
855
+ const key = `${model}:${column}`;
856
+ const hooks = this.columnHooks.afterChange[key];
857
+ if (hooks && !valuesEqual(newData[column], prevData[column])) {
858
+ for (const hook of hooks) {
859
+ promises.push(hook(prevData[column], newData[column], newData, prisma));
860
+ }
861
+ }
862
+ }
863
+ await Promise.all(promises);
864
+ }
865
+ hasColumnHooks(model) {
866
+ return this.modelsWithColumnHooks.has(model);
867
+ }
868
+ /**
869
+ * Check if column hooks should run for an operation.
870
+ * Takes into account global config, record count limits, and per-call options.
871
+ *
872
+ * @param model - The model name
873
+ * @param recordCount - Number of records affected (for maxRefetch check)
874
+ * @param args - The operation args (to check for __flare skip option)
875
+ * @returns Whether column hooks should execute
876
+ */
877
+ shouldRunColumnHooks(model, recordCount, args) {
878
+ if (args?.__flare?.skipColumnHooks === true) {
879
+ return false;
880
+ }
881
+ if (!this.config.enableColumnHooks) {
882
+ return false;
883
+ }
884
+ if (!this.modelsWithColumnHooks.has(model)) {
885
+ return false;
886
+ }
887
+ if (this.config.maxRefetch > 0 && recordCount > this.config.maxRefetch) {
888
+ if (this.config.warnOnSkip) {
889
+ console.warn(
890
+ `[prisma-flare] Skipping column hooks for ${model}: ${recordCount} records exceeds maxRefetch limit of ${this.config.maxRefetch}. Configure via hookRegistry.configure({ maxRefetch: ... })`
891
+ );
892
+ }
893
+ return false;
894
+ }
895
+ return true;
896
+ }
897
+ getRelevantFields(model) {
898
+ if (this.fieldCache[model]) {
899
+ return this.fieldCache[model];
900
+ }
901
+ const fields = /* @__PURE__ */ new Set();
902
+ for (const key of Object.keys(this.columnHooks.afterChange)) {
903
+ if (key.startsWith(`${model}:`)) {
904
+ const [, column] = key.split(":");
905
+ fields.add(column);
906
+ }
907
+ }
908
+ fields.add("id");
909
+ const result = Array.from(fields).reduce((acc, field) => {
910
+ acc[field] = true;
911
+ return acc;
912
+ }, {});
913
+ this.fieldCache[model] = result;
914
+ return result;
915
+ }
916
+ /**
917
+ * Clear all registered hooks (useful for testing)
918
+ */
919
+ clearAll() {
920
+ this.hooks.before = {};
921
+ this.hooks.after = {};
922
+ this.columnHooks.afterChange = {};
923
+ this.fieldCache = {};
924
+ this.modelsWithColumnHooks.clear();
925
+ this.config = { ...DEFAULT_CONFIG };
926
+ }
927
+ };
928
+ var hookRegistry = new HookRegistry();
929
+ var hookRegistry_default = hookRegistry;
930
+
931
+ // src/core/hooks.ts
932
+ function normalizeModelName(model) {
933
+ return model.toLowerCase();
934
+ }
935
+ function beforeCreate(model, callback) {
936
+ hookRegistry_default.addHook(normalizeModelName(model), "create", "before", callback);
937
+ }
938
+ function beforeDelete(model, callback) {
939
+ hookRegistry_default.addHook(normalizeModelName(model), "delete", "before", callback);
940
+ }
941
+ function afterCreate(model, callback) {
942
+ hookRegistry_default.addHook(normalizeModelName(model), "create", "after", callback);
943
+ }
944
+ function afterDelete(model, callback) {
945
+ hookRegistry_default.addHook(normalizeModelName(model), "delete", "after", callback);
946
+ }
947
+ function beforeUpdate(model, callback) {
948
+ hookRegistry_default.addHook(normalizeModelName(model), "update", "before", callback);
949
+ }
950
+ function afterUpdate(model, callback) {
951
+ hookRegistry_default.addHook(normalizeModelName(model), "update", "after", callback);
952
+ }
953
+ function afterChange(model, column, callback) {
954
+ hookRegistry_default.addColumnHook(normalizeModelName(model), column, callback);
955
+ }
956
+ function afterUpsert(model, callback) {
957
+ hookRegistry_default.addHook(normalizeModelName(model), "upsert", "after", callback);
958
+ }
959
+
960
+ // src/core/hookMiddleware.ts
961
+ var import_client2 = require("@prisma/client");
962
+
963
+ // src/cli/config.ts
964
+ var fs = __toESM(require("fs"), 1);
965
+ var path = __toESM(require("path"), 1);
966
+ function findProjectRoot(currentDir) {
967
+ if (fs.existsSync(path.join(currentDir, "package.json"))) {
968
+ return currentDir;
969
+ }
970
+ const parentDir = path.dirname(currentDir);
971
+ if (parentDir === currentDir) {
972
+ throw new Error("Could not find package.json");
973
+ }
974
+ return findProjectRoot(parentDir);
975
+ }
976
+ function loadConfig(rootDir) {
977
+ const projectRoot = rootDir || findProjectRoot(process.cwd());
978
+ const configPath = path.join(projectRoot, "prisma-flare.config.json");
979
+ let config = {
980
+ modelsPath: "prisma/models",
981
+ dbPath: "prisma/db",
982
+ callbacksPath: "prisma/callbacks"
983
+ };
984
+ if (fs.existsSync(configPath)) {
985
+ try {
986
+ const configFile = fs.readFileSync(configPath, "utf-8");
987
+ const userConfig = JSON.parse(configFile);
988
+ config = { ...config, ...userConfig };
989
+ } catch {
990
+ console.warn("\u26A0\uFE0F Could not read prisma-flare.config.json, using defaults.");
991
+ }
992
+ }
993
+ return {
994
+ ...config
995
+ };
996
+ }
997
+
998
+ // src/core/hookMiddleware.ts
999
+ var import_fs = __toESM(require("fs"), 1);
1000
+ var import_path = __toESM(require("path"), 1);
1001
+ function supportsTypeScriptImports() {
1002
+ if (process.env.TS_NODE || /* @__PURE__ */ Symbol.for("ts-node.register.instance") in process) {
1003
+ return true;
1004
+ }
1005
+ if (process.env.TSX) {
1006
+ return true;
1007
+ }
1008
+ if (typeof globalThis.Bun !== "undefined") {
1009
+ return true;
1010
+ }
1011
+ if (process.env.VITEST) {
1012
+ return true;
1013
+ }
1014
+ return false;
1015
+ }
1016
+ async function loadCallbacks(callbacksDir) {
1017
+ if (!callbacksDir) {
1018
+ callbacksDir = import_path.default.join(process.cwd(), "prisma", "callbacks");
1019
+ }
1020
+ if (!import_fs.default.existsSync(callbacksDir)) {
1021
+ console.warn(`Callbacks directory not found: ${callbacksDir}`);
1022
+ return;
1023
+ }
1024
+ const canImportTs = supportsTypeScriptImports();
1025
+ const files = import_fs.default.readdirSync(callbacksDir);
1026
+ for (const file of files) {
1027
+ const filePath = import_path.default.join(callbacksDir, file);
1028
+ if (file.endsWith(".js")) {
1029
+ await import(filePath);
1030
+ } else if (file.endsWith(".ts") && canImportTs) {
1031
+ await import(filePath);
1032
+ } else if (file.endsWith(".ts") && !canImportTs) {
1033
+ console.warn(
1034
+ `Skipping TypeScript callback file: ${file}. TypeScript imports require ts-node, tsx, or Bun. Compile to JavaScript for production use.`
1035
+ );
1036
+ }
1037
+ }
1038
+ }
1039
+ async function fetchAffectedRecords(db, model, where, fields) {
1040
+ const key = model.charAt(0).toLowerCase() + model.slice(1);
1041
+ const delegate = db[key];
1042
+ const select = fields ? { ...fields, id: true } : void 0;
1043
+ const records = await delegate.findMany({
1044
+ where,
1045
+ ...select && { select }
1046
+ });
1047
+ return records;
1048
+ }
1049
+ async function executeHookLogic(prisma, model, action, args, next) {
1050
+ if (!model) {
1051
+ return next();
1052
+ }
1053
+ let flareOptions = args?.__flare;
1054
+ if (args?.__flare) {
1055
+ delete args.__flare;
1056
+ }
1057
+ if (args?.data?.__flare) {
1058
+ flareOptions = args.data.__flare;
1059
+ delete args.data.__flare;
1060
+ }
1061
+ const modelName = model.toLowerCase();
1062
+ const hasColumnHooks = hookRegistry_default.hasColumnHooks(modelName);
1063
+ let prevData = [];
1064
+ let fields;
1065
+ let shouldRunColumnHooks = false;
1066
+ const isUpdateAction = action === "update" || action === "updateMany";
1067
+ if (hasColumnHooks && isUpdateAction) {
1068
+ fields = hookRegistry_default.getRelevantFields(modelName);
1069
+ prevData = await fetchAffectedRecords(prisma, modelName, args.where, fields);
1070
+ shouldRunColumnHooks = hookRegistry_default.shouldRunColumnHooks(modelName, prevData.length, { __flare: flareOptions });
1071
+ }
1072
+ await hookRegistry_default.runHooks("before", modelName, action, [args], prisma);
1073
+ const result = await next();
1074
+ if (shouldRunColumnHooks && prevData.length > 0) {
1075
+ let newData = [];
1076
+ const ids = prevData.map((r) => r.id);
1077
+ newData = await fetchAffectedRecords(prisma, modelName, { id: { in: ids } }, fields);
1078
+ for (let i = 0; i < prevData.length; i++) {
1079
+ const prevRecord = prevData[i];
1080
+ const newRecord = newData.find((record) => record.id === prevRecord.id);
1081
+ if (newRecord) {
1082
+ hookRegistry_default.runColumnHooks(modelName, newRecord, prevRecord, prisma).catch((error) => {
1083
+ console.error("Column hook error:", error);
1084
+ });
1085
+ }
1086
+ }
1087
+ }
1088
+ hookRegistry_default.runHooks("after", modelName, action, [args, result], prisma).catch((error) => {
1089
+ console.error("After hook error:", error);
1090
+ });
1091
+ return result;
1092
+ }
1093
+ function supportsPrisma6Middleware(prisma) {
1094
+ return typeof prisma.$use === "function";
1095
+ }
1096
+ function createHooksExtension(basePrisma) {
1097
+ return import_client2.Prisma.defineExtension({
1098
+ name: "prisma-flare-hooks",
1099
+ query: {
1100
+ $allModels: {
1101
+ async $allOperations({ model, operation, args, query }) {
1102
+ return executeHookLogic(
1103
+ basePrisma,
1104
+ model,
1105
+ operation,
1106
+ args,
1107
+ () => query(args)
1108
+ );
1109
+ }
1110
+ }
1111
+ }
1112
+ });
1113
+ }
1114
+ function registerHooksLegacy(prisma) {
1115
+ prisma.$use(async (params, next) => {
1116
+ const { model, action, args } = params;
1117
+ return executeHookLogic(prisma, model, action, args, () => next(params));
1118
+ });
1119
+ }
1120
+ async function registerHooks(prisma) {
1121
+ let client;
1122
+ if (supportsPrisma6Middleware(prisma)) {
1123
+ registerHooksLegacy(prisma);
1124
+ client = prisma;
1125
+ } else {
1126
+ const extension = createHooksExtension(prisma);
1127
+ client = prisma.$extends(extension);
1128
+ }
1129
+ try {
1130
+ const config = loadConfig();
1131
+ const projectRoot = findProjectRoot(process.cwd());
1132
+ const callbacksPath = import_path.default.join(projectRoot, config.callbacksPath);
1133
+ await loadCallbacks(callbacksPath);
1134
+ } catch {
1135
+ }
1136
+ return client;
1137
+ }
1138
+
1139
+ // src/core/adapters/postgres.ts
1140
+ var PostgresAdapter = {
1141
+ name: "postgres",
1142
+ matches(url) {
1143
+ return url.startsWith("postgresql://") || url.startsWith("postgres://");
1144
+ },
1145
+ async create(url) {
1146
+ const config = parseDatabaseUrl(url);
1147
+ const { Client } = await import("pg");
1148
+ const client = new Client({
1149
+ user: config.user,
1150
+ password: config.password,
1151
+ host: config.host,
1152
+ port: config.port,
1153
+ database: "postgres"
1154
+ });
1155
+ try {
1156
+ await client.connect();
1157
+ const checkRes = await client.query(
1158
+ `SELECT 1 FROM pg_database WHERE datname = $1`,
1159
+ [config.database]
1160
+ );
1161
+ if (checkRes.rowCount === 0) {
1162
+ await client.query(`CREATE DATABASE "${config.database}"`);
1163
+ console.log(`\u2705 Database "${config.database}" created successfully.`);
1164
+ } else {
1165
+ console.log(`\u26A0\uFE0F Database "${config.database}" already exists.`);
1166
+ }
1167
+ } catch (error) {
1168
+ console.error("\u274C Error creating database:", error);
1169
+ throw error;
1170
+ } finally {
1171
+ await client.end();
1172
+ }
1173
+ },
1174
+ async drop(url) {
1175
+ const config = parseDatabaseUrl(url);
1176
+ const { Client } = await import("pg");
1177
+ const client = new Client({
1178
+ user: config.user,
1179
+ password: config.password,
1180
+ host: config.host,
1181
+ port: config.port,
1182
+ database: "postgres"
1183
+ });
1184
+ try {
1185
+ await client.connect();
1186
+ await client.query(
1187
+ `SELECT pg_terminate_backend(pg_stat_activity.pid)
1188
+ FROM pg_stat_activity
1189
+ WHERE pg_stat_activity.datname = $1
1190
+ AND pid <> pg_backend_pid()`,
1191
+ [config.database]
1192
+ );
1193
+ await client.query(`DROP DATABASE IF EXISTS "${config.database}"`);
1194
+ console.log(`\u2705 Database "${config.database}" dropped successfully.`);
1195
+ } catch (error) {
1196
+ console.error("\u274C Error dropping database:", error);
1197
+ throw error;
1198
+ } finally {
1199
+ await client.end();
1200
+ }
1201
+ }
1202
+ };
1203
+ function parseDatabaseUrl(url) {
1204
+ const regex = /postgres(?:ql)?:\/\/([^:]+):([^@]+)@([^:]+):(\d+)\/([^?]+)(\?.*)?/;
1205
+ const match = url.match(regex);
1206
+ if (!match) {
1207
+ throw new Error("Invalid PostgreSQL connection string");
1208
+ }
1209
+ return {
1210
+ user: decodeURIComponent(match[1]),
1211
+ password: decodeURIComponent(match[2]),
1212
+ host: match[3],
1213
+ port: parseInt(match[4], 10),
1214
+ database: match[5]
1215
+ };
1216
+ }
1217
+
1218
+ // src/core/adapters/sqlite.ts
1219
+ var fs3 = __toESM(require("fs"), 1);
1220
+ var path3 = __toESM(require("path"), 1);
1221
+ var SqliteAdapter = {
1222
+ name: "sqlite",
1223
+ matches(url) {
1224
+ return url.startsWith("file:");
1225
+ },
1226
+ async create(url) {
1227
+ const filePath = parseSqliteUrl(url);
1228
+ const dir = path3.dirname(filePath);
1229
+ try {
1230
+ if (!fs3.existsSync(dir)) {
1231
+ fs3.mkdirSync(dir, { recursive: true });
1232
+ }
1233
+ if (!fs3.existsSync(filePath)) {
1234
+ fs3.writeFileSync(filePath, "");
1235
+ console.log(`\u2705 SQLite database created at "${filePath}"`);
1236
+ } else {
1237
+ console.log(`\u26A0\uFE0F SQLite database already exists at "${filePath}"`);
1238
+ }
1239
+ } catch (error) {
1240
+ console.error("\u274C Error creating SQLite database:", error);
1241
+ throw error;
1242
+ }
1243
+ },
1244
+ async drop(url) {
1245
+ const filePath = parseSqliteUrl(url);
1246
+ try {
1247
+ if (fs3.existsSync(filePath)) {
1248
+ fs3.unlinkSync(filePath);
1249
+ console.log(`\u2705 SQLite database at "${filePath}" dropped successfully.`);
1250
+ } else {
1251
+ console.log(`\u26A0\uFE0F SQLite database does not exist at "${filePath}"`);
1252
+ }
1253
+ if (fs3.existsSync(`${filePath}-journal`)) {
1254
+ fs3.unlinkSync(`${filePath}-journal`);
1255
+ }
1256
+ if (fs3.existsSync(`${filePath}-wal`)) {
1257
+ fs3.unlinkSync(`${filePath}-wal`);
1258
+ }
1259
+ if (fs3.existsSync(`${filePath}-shm`)) {
1260
+ fs3.unlinkSync(`${filePath}-shm`);
1261
+ }
1262
+ } catch (error) {
1263
+ console.error("\u274C Error dropping SQLite database:", error);
1264
+ throw error;
1265
+ }
1266
+ }
1267
+ };
1268
+ function parseSqliteUrl(url) {
1269
+ let cleanPath = url.replace(/^file:/, "");
1270
+ if (!path3.isAbsolute(cleanPath)) {
1271
+ cleanPath = path3.resolve(process.cwd(), cleanPath);
1272
+ }
1273
+ return cleanPath;
1274
+ }
1275
+
1276
+ // src/core/adapters/index.ts
1277
+ var AdapterRegistry = class {
1278
+ constructor() {
1279
+ this.adapters = [];
1280
+ }
1281
+ register(adapter) {
1282
+ this.adapters.push(adapter);
1283
+ }
1284
+ getAdapter(url) {
1285
+ const adapter = this.adapters.find((a) => a.matches(url));
1286
+ if (!adapter) {
1287
+ throw new Error(`No database adapter found for URL: ${url}`);
1288
+ }
1289
+ return adapter;
1290
+ }
1291
+ };
1292
+ var registry = new AdapterRegistry();
1293
+ registry.register(PostgresAdapter);
1294
+ registry.register(SqliteAdapter);
1295
+ // Annotate the CommonJS export names for ESM import in node:
1296
+ 0 && (module.exports = {
1297
+ ExtendedPrismaClient,
1298
+ FlareBuilder,
1299
+ FlareClient,
1300
+ afterChange,
1301
+ afterCreate,
1302
+ afterDelete,
1303
+ afterUpdate,
1304
+ afterUpsert,
1305
+ beforeCreate,
1306
+ beforeDelete,
1307
+ beforeUpdate,
1308
+ createHooksExtension,
1309
+ dbAdapterRegistry,
1310
+ hookRegistry,
1311
+ loadCallbacks,
1312
+ modelRegistry,
1313
+ registerHooks,
1314
+ registerHooksLegacy
1315
+ });