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
@@ -0,0 +1,658 @@
1
+ // src/core/modelRegistry.ts
2
+ var ModelRegistry = class {
3
+ constructor() {
4
+ this.models = /* @__PURE__ */ new Map();
5
+ }
6
+ /**
7
+ * Register a custom model class for a given model name.
8
+ * The model name should match the Prisma model name (e.g., 'user', 'post', 'enrollment')
9
+ * @param modelName - The lowercase model name (matching Prisma delegate name)
10
+ * @param modelClass - The custom class that extends FlareBuilder
11
+ */
12
+ register(modelName, modelClass) {
13
+ this.models.set(modelName.toLowerCase(), modelClass);
14
+ }
15
+ /**
16
+ * Register multiple models at once
17
+ * @param models - Object mapping model names to their classes
18
+ */
19
+ registerMany(models) {
20
+ for (const [name, modelClass] of Object.entries(models)) {
21
+ this.register(name, modelClass);
22
+ }
23
+ }
24
+ /**
25
+ * Get a custom model class by name
26
+ * @param modelName - The model name to look up
27
+ * @returns The model class or undefined if not registered
28
+ */
29
+ get(modelName) {
30
+ return this.models.get(modelName.toLowerCase());
31
+ }
32
+ /**
33
+ * Check if a model is registered
34
+ * @param modelName - The model name to check
35
+ */
36
+ has(modelName) {
37
+ return this.models.has(modelName.toLowerCase());
38
+ }
39
+ /**
40
+ * Create an instance of a registered model
41
+ * @param modelName - The model name to instantiate
42
+ * @returns A new instance of the custom model class, or undefined if not registered
43
+ */
44
+ create(modelName) {
45
+ const ModelClass = this.get(modelName);
46
+ if (ModelClass) {
47
+ return new ModelClass();
48
+ }
49
+ return void 0;
50
+ }
51
+ /**
52
+ * Clear all registered models (useful for testing)
53
+ */
54
+ clear() {
55
+ this.models.clear();
56
+ }
57
+ /**
58
+ * Get all registered model names
59
+ */
60
+ getRegisteredModels() {
61
+ return Array.from(this.models.keys());
62
+ }
63
+ };
64
+ var modelRegistry = new ModelRegistry();
65
+
66
+ // src/core/flareBuilder.ts
67
+ function deepClone(obj) {
68
+ if (obj === null || typeof obj !== "object") {
69
+ return obj;
70
+ }
71
+ if (typeof obj === "bigint") {
72
+ return obj;
73
+ }
74
+ if (typeof structuredClone === "function") {
75
+ try {
76
+ return structuredClone(obj);
77
+ } catch {
78
+ }
79
+ }
80
+ if (obj instanceof Date) {
81
+ return new Date(obj.getTime());
82
+ }
83
+ if (obj instanceof RegExp) {
84
+ return new RegExp(obj.source, obj.flags);
85
+ }
86
+ if (typeof Buffer !== "undefined" && Buffer.isBuffer(obj)) {
87
+ return Buffer.from(obj);
88
+ }
89
+ if (obj instanceof ArrayBuffer) {
90
+ return obj.slice(0);
91
+ }
92
+ if (ArrayBuffer.isView(obj) && !(obj instanceof DataView)) {
93
+ const TypedArrayConstructor = obj.constructor;
94
+ const buffer = obj.buffer instanceof ArrayBuffer ? obj.buffer.slice(0) : obj.buffer;
95
+ return new TypedArrayConstructor(buffer);
96
+ }
97
+ if (obj instanceof Map) {
98
+ const clonedMap = /* @__PURE__ */ new Map();
99
+ obj.forEach((value, key) => {
100
+ clonedMap.set(deepClone(key), deepClone(value));
101
+ });
102
+ return clonedMap;
103
+ }
104
+ if (obj instanceof Set) {
105
+ const clonedSet = /* @__PURE__ */ new Set();
106
+ obj.forEach((value) => {
107
+ clonedSet.add(deepClone(value));
108
+ });
109
+ return clonedSet;
110
+ }
111
+ if (Array.isArray(obj)) {
112
+ return obj.map((item) => deepClone(item));
113
+ }
114
+ if (typeof obj.toDecimalPlaces === "function") {
115
+ return obj;
116
+ }
117
+ const prototype = Object.getPrototypeOf(obj);
118
+ const cloned = Object.create(prototype);
119
+ for (const key in obj) {
120
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
121
+ cloned[key] = deepClone(obj[key]);
122
+ }
123
+ }
124
+ return cloned;
125
+ }
126
+ var FlareBuilder = class _FlareBuilder {
127
+ constructor(model, query = {}) {
128
+ this.model = model;
129
+ this.query = query;
130
+ }
131
+ /**
132
+ * Adds a where condition to the query with type safety from Prisma.
133
+ * Multiple where() calls are composed using AND logic to avoid silent overwrites.
134
+ * @param condition - Where filter matching your Prisma model
135
+ *
136
+ * @example
137
+ * // These conditions are AND-ed together:
138
+ * DB.posts
139
+ * .where({ published: true })
140
+ * .where({ authorId: 1 })
141
+ * .findMany()
142
+ * // Equivalent to: { AND: [{ published: true }, { authorId: 1 }] }
143
+ */
144
+ where(condition) {
145
+ if (!this.query.where || Object.keys(this.query.where).length === 0) {
146
+ this.query.where = condition;
147
+ } else {
148
+ const prevWhere = this.query.where;
149
+ this.query.where = { AND: [prevWhere, condition] };
150
+ }
151
+ return this;
152
+ }
153
+ /**
154
+ * Adds a where condition using AND logic (explicit alias for where())
155
+ * @param condition - Where filter matching your Prisma model
156
+ *
157
+ * @example
158
+ * DB.posts
159
+ * .where({ published: true })
160
+ * .andWhere({ createdAt: { gte: new Date('2024-01-01') } })
161
+ * .findMany()
162
+ */
163
+ andWhere(condition) {
164
+ return this.where(condition);
165
+ }
166
+ /**
167
+ * Adds a where condition using OR logic.
168
+ *
169
+ * ⚠️ **IMPORTANT**: `orWhere()` wraps the *entire* accumulated where clause:
170
+ * `OR([prevWhere, condition])`. This means:
171
+ *
172
+ * ```ts
173
+ * .where(A).orWhere(B).where(C) // becomes: (A OR B) AND C
174
+ * ```
175
+ *
176
+ * For complex boolean logic, prefer `whereGroup()` / `orWhereGroup()` for explicit control.
177
+ *
178
+ * @param condition - Where filter matching your Prisma model
179
+ *
180
+ * @example
181
+ * // Simple case - OK:
182
+ * DB.posts
183
+ * .where({ published: true })
184
+ * .orWhere({ featured: true })
185
+ * .findMany()
186
+ * // Result: published OR featured
187
+ *
188
+ * @example
189
+ * // For complex logic, use whereGroup instead:
190
+ * DB.posts
191
+ * .where({ published: true })
192
+ * .whereGroup(qb => qb
193
+ * .where({ category: 'news' })
194
+ * .orWhere({ category: 'tech' })
195
+ * )
196
+ * .findMany()
197
+ * // Result: published AND (category='news' OR category='tech')
198
+ */
199
+ orWhere(condition) {
200
+ if (!this.query.where || Object.keys(this.query.where).length === 0) {
201
+ this.query.where = condition;
202
+ } else {
203
+ const prevWhere = this.query.where;
204
+ this.query.where = { OR: [prevWhere, condition] };
205
+ }
206
+ return this;
207
+ }
208
+ /**
209
+ * Creates a grouped where condition using a callback.
210
+ * Use this for explicit control over boolean logic grouping.
211
+ * The callback receives a fresh builder - its accumulated where becomes a single group.
212
+ *
213
+ * @param callback - Function that builds the grouped condition
214
+ * @param mode - How to combine with existing where: 'AND' (default) or 'OR'
215
+ *
216
+ * @example
217
+ * // (status = 'active') AND (name LIKE 'A%' OR name LIKE 'B%')
218
+ * DB.users
219
+ * .where({ status: 'active' })
220
+ * .whereGroup(qb => qb
221
+ * .where({ name: { startsWith: 'A' } })
222
+ * .orWhere({ name: { startsWith: 'B' } })
223
+ * )
224
+ * .findMany()
225
+ *
226
+ * @example
227
+ * // (status = 'active') OR (role = 'admin' AND verified = true)
228
+ * DB.users
229
+ * .where({ status: 'active' })
230
+ * .whereGroup(qb => qb
231
+ * .where({ role: 'admin' })
232
+ * .where({ verified: true })
233
+ * , 'OR')
234
+ * .findMany()
235
+ */
236
+ whereGroup(callback, mode = "AND") {
237
+ const groupBuilder = new _FlareBuilder(this.model, {});
238
+ callback(groupBuilder);
239
+ const groupWhere = groupBuilder.getQuery().where;
240
+ if (!groupWhere || Object.keys(groupWhere).length === 0) {
241
+ return this;
242
+ }
243
+ if (!this.query.where || Object.keys(this.query.where).length === 0) {
244
+ this.query.where = groupWhere;
245
+ } else {
246
+ const prevWhere = this.query.where;
247
+ this.query.where = { [mode]: [prevWhere, groupWhere] };
248
+ }
249
+ return this;
250
+ }
251
+ /**
252
+ * Alias for whereGroup with OR mode.
253
+ * Creates a grouped condition that's OR-ed with existing where.
254
+ *
255
+ * @param callback - Function that builds the grouped condition
256
+ *
257
+ * @example
258
+ * // (published = true) OR (authorId = 1 AND draft = true)
259
+ * DB.posts
260
+ * .where({ published: true })
261
+ * .orWhereGroup(qb => qb
262
+ * .where({ authorId: 1 })
263
+ * .where({ draft: true })
264
+ * )
265
+ * .findMany()
266
+ */
267
+ orWhereGroup(callback) {
268
+ return this.whereGroup(callback, "OR");
269
+ }
270
+ /**
271
+ * Adds a where condition to the query for the specified id.
272
+ * Uses the same AND composition as where() for consistency.
273
+ * @param id - The id to search for
274
+ */
275
+ withId(id) {
276
+ if (!id) {
277
+ throw new Error("Id is required");
278
+ }
279
+ if (!this.query.where || Object.keys(this.query.where).length === 0) {
280
+ this.query.where = { id };
281
+ } else {
282
+ const prevWhere = this.query.where;
283
+ this.query.where = { AND: [prevWhere, { id }] };
284
+ }
285
+ return this;
286
+ }
287
+ /**
288
+ * Adds an order by condition to the query
289
+ * @param orderBy - OrderBy object matching your Prisma model
290
+ */
291
+ order(orderBy) {
292
+ this.query.orderBy = orderBy;
293
+ return this;
294
+ }
295
+ /**
296
+ * Gets the last record sorted by the specified field
297
+ * @param key - Field to sort by (defaults to 'createdAt')
298
+ */
299
+ last(key = "createdAt") {
300
+ return this.order({ [key]: "desc" }).limit(1);
301
+ }
302
+ /**
303
+ * Gets the first record sorted by the specified field
304
+ * @param key - Field to sort by (defaults to 'createdAt')
305
+ */
306
+ first(key = "createdAt") {
307
+ return this.order({ [key]: "asc" }).limit(1);
308
+ }
309
+ /**
310
+ * Sets a limit on the number of records to retrieve
311
+ * @param limit - Maximum number of records
312
+ */
313
+ limit(limit) {
314
+ this.query.take = limit;
315
+ return this;
316
+ }
317
+ /**
318
+ * Sets distinct fields for the query
319
+ * @param distinct - Fields to be distinct
320
+ */
321
+ distinct(distinct) {
322
+ this.query.distinct = distinct;
323
+ return this;
324
+ }
325
+ /**
326
+ * Selects specific fields to retrieve
327
+ * @param fields - Select object matching your Prisma model
328
+ */
329
+ select(fields) {
330
+ this.query.select = fields;
331
+ return this;
332
+ }
333
+ /**
334
+ * Selects only the specified field and returns its value
335
+ * @param field - Field name to retrieve
336
+ */
337
+ async only(field) {
338
+ this.query.select = { [field]: true };
339
+ const result = await this.model.findFirst(this.query);
340
+ if (!result) {
341
+ return null;
342
+ }
343
+ return result[field];
344
+ }
345
+ /**
346
+ * Returns the current query object
347
+ */
348
+ getQuery() {
349
+ return this.query;
350
+ }
351
+ include(relation, callback) {
352
+ let relationQuery = true;
353
+ if (callback) {
354
+ const builder = modelRegistry.create(relation) ?? new _FlareBuilder(null);
355
+ callback(builder);
356
+ relationQuery = builder.getQuery();
357
+ if (Object.keys(relationQuery).length === 0) {
358
+ relationQuery = true;
359
+ }
360
+ }
361
+ this.query.include = {
362
+ ...this.query.include,
363
+ [relation]: relationQuery
364
+ };
365
+ return this;
366
+ }
367
+ /**
368
+ * Groups results by specified fields
369
+ * @param groupBy - Fields to group by
370
+ */
371
+ groupBy(groupBy) {
372
+ this.query.by = groupBy;
373
+ return this;
374
+ }
375
+ /**
376
+ * Adds a having condition to the query
377
+ * @param condition - Having condition
378
+ */
379
+ having(condition) {
380
+ this.query.having = condition;
381
+ return this;
382
+ }
383
+ /**
384
+ * Skips the specified number of records
385
+ * @param offset - Number of records to skip
386
+ */
387
+ skip(offset) {
388
+ this.query.skip = offset;
389
+ return this;
390
+ }
391
+ /**
392
+ * Checks if any record exists matching the current query
393
+ * @param existenceKey - Key to check for existence (defaults to 'id')
394
+ */
395
+ async exists(existenceKey = "id") {
396
+ const result = await this.model.findFirst({
397
+ where: this.query.where,
398
+ select: { [existenceKey]: true }
399
+ });
400
+ return Boolean(result);
401
+ }
402
+ /**
403
+ * Paginates the results
404
+ * @param page - Page number (1-based)
405
+ * @param perPage - Number of records per page
406
+ */
407
+ async paginate(page = 1, perPage = 15) {
408
+ const skip = (page - 1) * perPage;
409
+ const take = perPage;
410
+ this.query.skip = skip;
411
+ this.query.take = take;
412
+ const [data, total] = await Promise.all([
413
+ this.model.findMany(this.query),
414
+ this.model.count({ where: this.query.where })
415
+ ]);
416
+ const lastPage = Math.ceil(total / perPage);
417
+ return {
418
+ data,
419
+ meta: {
420
+ total,
421
+ lastPage,
422
+ currentPage: page,
423
+ perPage,
424
+ prev: page > 1 ? page - 1 : null,
425
+ next: page < lastPage ? page + 1 : null
426
+ }
427
+ };
428
+ }
429
+ /**
430
+ * Conditionally executes a callback on the query builder
431
+ * @param condition - Boolean or function returning boolean
432
+ * @param callback - Function to execute if condition is true
433
+ */
434
+ when(condition, callback) {
435
+ const isTrue = typeof condition === "function" ? condition() : condition;
436
+ if (isTrue) {
437
+ callback(this);
438
+ }
439
+ return this;
440
+ }
441
+ /**
442
+ * Processes results in chunks to avoid memory issues
443
+ * @param size - Size of each chunk
444
+ * @param callback - Function to process each chunk
445
+ */
446
+ async chunk(size, callback) {
447
+ let page = 1;
448
+ let hasMore = true;
449
+ const originalSkip = this.query.skip;
450
+ const originalTake = this.query.take;
451
+ while (hasMore) {
452
+ this.query.skip = (page - 1) * size;
453
+ this.query.take = size;
454
+ const results = await this.model.findMany(this.query);
455
+ if (results.length > 0) {
456
+ await callback(results);
457
+ page++;
458
+ if (results.length < size) {
459
+ hasMore = false;
460
+ }
461
+ } else {
462
+ hasMore = false;
463
+ }
464
+ }
465
+ this.query.skip = originalSkip;
466
+ this.query.take = originalTake;
467
+ }
468
+ /**
469
+ * Clones the current query builder instance.
470
+ * Uses structuredClone for proper handling of Date, BigInt, etc.
471
+ */
472
+ clone() {
473
+ const queryCopy = deepClone(this.query);
474
+ return new _FlareBuilder(this.model, queryCopy);
475
+ }
476
+ /**
477
+ * Finds the first record matching the query or throws an error if none found
478
+ * Throws a Prisma NotFoundError if no record matches the query
479
+ * @throws {Prisma.NotFoundError} When no record matches the query
480
+ * @returns Promise resolving to the found record
481
+ */
482
+ async findFirstOrThrow() {
483
+ return this.model.findFirstOrThrow(this.query);
484
+ }
485
+ /**
486
+ * Finds a unique record by primary key or throws an error if not found
487
+ * Requires a unique constraint (typically the id field)
488
+ * Throws a Prisma NotFoundError if no record matches
489
+ * @throws {Prisma.NotFoundError} When no record is found
490
+ * @returns Promise resolving to the found record
491
+ */
492
+ async findUniqueOrThrow() {
493
+ return this.model.findUniqueOrThrow(this.query);
494
+ }
495
+ /**
496
+ * Finds all records matching the query
497
+ * Respects all previously set query conditions (where, orderBy, take, skip, include, select, distinct)
498
+ * @returns Promise resolving to an array of records matching the query
499
+ */
500
+ async findMany() {
501
+ return this.model.findMany(this.query);
502
+ }
503
+ /**
504
+ * Finds the first record matching the query
505
+ * Returns null if no record matches. To throw an error instead, use findFirstOrThrow()
506
+ * @returns Promise resolving to the first matching record or null
507
+ */
508
+ async findFirst() {
509
+ return this.model.findFirst(this.query);
510
+ }
511
+ /**
512
+ * Finds a unique record by primary key
513
+ * Returns null if no record is found. To throw an error instead, use findUniqueOrThrow()
514
+ * Requires a unique constraint in the where condition (typically the id field)
515
+ * @returns Promise resolving to the found record or null
516
+ */
517
+ async findUnique() {
518
+ return this.model.findUnique(this.query);
519
+ }
520
+ /**
521
+ * Creates a new record with the provided data
522
+ * Any hooks registered for 'create' operations will be triggered
523
+ * @param data - Data matching your Prisma model's create input
524
+ * @returns Promise resolving to the newly created record
525
+ */
526
+ async create(data) {
527
+ const query = { ...this.query, data };
528
+ return this.model.create(query);
529
+ }
530
+ /**
531
+ * Creates multiple records in a single operation
532
+ * More efficient than creating records individually
533
+ * Any hooks registered for 'create' operations will be triggered for each record
534
+ * @param data - Array of data objects matching your Prisma model's create input
535
+ * @returns Promise resolving to the count of created records
536
+ */
537
+ async createMany(data) {
538
+ const query = { ...this.query, data };
539
+ return this.model.createMany(query);
540
+ }
541
+ /**
542
+ * Deletes a single record matching the current query conditions
543
+ * Requires at least one unique constraint in the where condition (typically id)
544
+ * Any hooks registered for 'delete' operations will be triggered
545
+ * @param args - Optional additional delete arguments to override query conditions
546
+ * @returns Promise resolving to the deleted record
547
+ */
548
+ async delete(args) {
549
+ const query = args ? { ...this.query, ...args } : this.query;
550
+ return this.model.delete(query);
551
+ }
552
+ /**
553
+ * Deletes multiple records matching the current query conditions
554
+ * More efficient than deleting records individually
555
+ * Any hooks registered for 'delete' operations will be triggered for each record
556
+ * @param args - Optional additional delete arguments to override query conditions
557
+ * @returns Promise resolving to the count of deleted records
558
+ */
559
+ async deleteMany(args) {
560
+ const query = args ? { ...this.query, ...args } : this.query;
561
+ return this.model.deleteMany(query);
562
+ }
563
+ /**
564
+ * Updates a single record matching the current query conditions
565
+ * Requires at least one unique constraint in the where condition (typically id)
566
+ * Any hooks registered for 'update' operations will be triggered
567
+ * @param data - Data to update, matching your Prisma model's update input
568
+ * @returns Promise resolving to the updated record
569
+ */
570
+ async update(data) {
571
+ const query = { ...this.query, data };
572
+ return this.model.update(query);
573
+ }
574
+ /**
575
+ * Updates multiple records matching the current query conditions
576
+ * More efficient than updating records individually
577
+ * Any hooks registered for 'update' operations will be triggered for each record
578
+ * @param data - Data to update, matching your Prisma model's update input
579
+ * @returns Promise resolving to the count of updated records
580
+ */
581
+ async updateMany(data) {
582
+ const query = { ...this.query, data };
583
+ return this.model.updateMany(query);
584
+ }
585
+ /**
586
+ * Updates a record if it exists, otherwise creates a new record
587
+ * The record is uniquely identified by the where condition (typically id)
588
+ * Any hooks registered for 'update' or 'create' operations will be triggered accordingly
589
+ * @param args - Optional upsert arguments including where, update, and create data
590
+ * @returns Promise resolving to the upserted record
591
+ */
592
+ async upsert(args) {
593
+ const query = args ? { ...this.query, ...args } : this.query;
594
+ return this.model.upsert(query);
595
+ }
596
+ /**
597
+ * Counts the number of records matching the query
598
+ */
599
+ async count() {
600
+ return this.model.count(this.query);
601
+ }
602
+ /**
603
+ * Sums the specified numeric field
604
+ * @param field - Field name to sum
605
+ */
606
+ async sum(field) {
607
+ const result = await this.model.aggregate({
608
+ _sum: { [field]: true },
609
+ where: this.query.where
610
+ });
611
+ return result._sum[field];
612
+ }
613
+ /**
614
+ * Calculates the average of the specified numeric field
615
+ * @param field - Field name to average
616
+ */
617
+ async avg(field) {
618
+ const result = await this.model.aggregate({
619
+ _avg: { [field]: true },
620
+ where: this.query.where
621
+ });
622
+ return result._avg[field];
623
+ }
624
+ /**
625
+ * Finds the minimum value of the specified field
626
+ * @param field - Field name to find minimum
627
+ */
628
+ async min(field) {
629
+ const result = await this.model.aggregate({
630
+ _min: { [field]: true },
631
+ where: this.query.where
632
+ });
633
+ return result._min[field];
634
+ }
635
+ /**
636
+ * Finds the maximum value of the specified field
637
+ * @param field - Field name to find maximum
638
+ */
639
+ async max(field) {
640
+ const result = await this.model.aggregate({
641
+ _max: { [field]: true },
642
+ where: this.query.where
643
+ });
644
+ return result._max[field];
645
+ }
646
+ /**
647
+ * Plucks the specified field from all results
648
+ * @param field - Field name to pluck
649
+ */
650
+ async pluck(field) {
651
+ this.query.select = { [field]: true };
652
+ const results = await this.model.findMany(this.query);
653
+ return results.map((result) => result[field]);
654
+ }
655
+ };
656
+ export {
657
+ FlareBuilder as default
658
+ };