@opprs/db-prisma 2.3.0 → 2.5.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.
package/dist/index.cjs CHANGED
@@ -20,31 +20,91 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ MAX_API_KEYS_PER_USER: () => MAX_API_KEYS_PER_USER,
24
+ applyRDDecayForInactivePlayers: () => applyRDDecayForInactivePlayers,
23
25
  connect: () => connect,
26
+ countBlogPosts: () => countBlogPosts,
27
+ countBlogTags: () => countBlogTags,
28
+ countEntries: () => countEntries,
29
+ countLocations: () => countLocations,
30
+ countMatches: () => countMatches,
31
+ countOpprPlayerRankings: () => countOpprPlayerRankings,
32
+ countOpprRankingHistory: () => countOpprRankingHistory,
24
33
  countPlayers: () => countPlayers,
25
- countResults: () => countResults,
34
+ countPublishedBlogPosts: () => countPublishedBlogPosts,
35
+ countRounds: () => countRounds,
36
+ countStandings: () => countStandings,
26
37
  countTournaments: () => countTournaments,
38
+ countUserApiKeys: () => countUserApiKeys,
27
39
  countUsers: () => countUsers,
28
- createManyResults: () => createManyResults,
40
+ createApiKey: () => createApiKey,
41
+ createBlogPost: () => createBlogPost,
42
+ createBlogTag: () => createBlogTag,
43
+ createEntry: () => createEntry,
44
+ createLocation: () => createLocation,
45
+ createManyEntries: () => createManyEntries,
46
+ createManyMatches: () => createManyMatches,
47
+ createManyRounds: () => createManyRounds,
48
+ createManyStandings: () => createManyStandings,
49
+ createMatch: () => createMatch,
50
+ createOpprPlayerRanking: () => createOpprPlayerRanking,
51
+ createOpprRankingHistory: () => createOpprRankingHistory,
29
52
  createPlayer: () => createPlayer,
30
- createResult: () => createResult,
53
+ createRound: () => createRound,
54
+ createStanding: () => createStanding,
31
55
  createTournament: () => createTournament,
32
56
  createUser: () => createUser,
33
57
  createUserWithPlayer: () => createUserWithPlayer,
58
+ deleteApiKey: () => deleteApiKey,
59
+ deleteBlogPost: () => deleteBlogPost,
60
+ deleteBlogTag: () => deleteBlogTag,
61
+ deleteEntriesByMatch: () => deleteEntriesByMatch,
62
+ deleteEntry: () => deleteEntry,
63
+ deleteLocation: () => deleteLocation,
64
+ deleteMatch: () => deleteMatch,
65
+ deleteMatchesByRound: () => deleteMatchesByRound,
66
+ deleteMatchesByTournament: () => deleteMatchesByTournament,
67
+ deleteOpprPlayerRanking: () => deleteOpprPlayerRanking,
34
68
  deletePlayer: () => deletePlayer,
35
- deleteResult: () => deleteResult,
36
- deleteResultsByTournament: () => deleteResultsByTournament,
69
+ deleteRound: () => deleteRound,
70
+ deleteRoundsByTournament: () => deleteRoundsByTournament,
71
+ deleteStanding: () => deleteStanding,
72
+ deleteStandingsByTournament: () => deleteStandingsByTournament,
37
73
  deleteTournament: () => deleteTournament,
38
74
  deleteUser: () => deleteUser,
75
+ deleteUserApiKey: () => deleteUserApiKey,
39
76
  disconnect: () => disconnect,
77
+ findApiKeyById: () => findApiKeyById,
78
+ findApiKeysByPrefix: () => findApiKeysByPrefix,
79
+ findBlogPostById: () => findBlogPostById,
80
+ findBlogPostBySlug: () => findBlogPostBySlug,
81
+ findBlogPosts: () => findBlogPosts,
82
+ findBlogTagById: () => findBlogTagById,
83
+ findBlogTagBySlug: () => findBlogTagBySlug,
84
+ findBlogTags: () => findBlogTags,
85
+ findEntries: () => findEntries,
86
+ findEntryById: () => findEntryById,
87
+ findEntryByMatchAndPlayer: () => findEntryByMatchAndPlayer,
88
+ findLocationByExternalId: () => findLocationByExternalId,
89
+ findLocationById: () => findLocationById,
90
+ findLocations: () => findLocations,
91
+ findMatchById: () => findMatchById,
92
+ findMatches: () => findMatches,
93
+ findOpprPlayerRankingById: () => findOpprPlayerRankingById,
94
+ findOpprPlayerRankingByPlayerId: () => findOpprPlayerRankingByPlayerId,
95
+ findOpprPlayerRankings: () => findOpprPlayerRankings,
40
96
  findPlayerByExternalId: () => findPlayerByExternalId,
41
97
  findPlayerById: () => findPlayerById,
42
98
  findPlayerByPlayerNumber: () => findPlayerByPlayerNumber,
43
99
  findPlayerByUserEmail: () => findPlayerByUserEmail,
44
100
  findPlayers: () => findPlayers,
45
- findResultById: () => findResultById,
46
- findResultByPlayerAndTournament: () => findResultByPlayerAndTournament,
47
- findResults: () => findResults,
101
+ findPublishedBlogPosts: () => findPublishedBlogPosts,
102
+ findRoundById: () => findRoundById,
103
+ findRoundByTournamentAndNumber: () => findRoundByTournamentAndNumber,
104
+ findRounds: () => findRounds,
105
+ findStandingById: () => findStandingById,
106
+ findStandingByPlayerAndTournament: () => findStandingByPlayerAndTournament,
107
+ findStandings: () => findStandings,
48
108
  findTournamentByExternalId: () => findTournamentByExternalId,
49
109
  findTournamentById: () => findTournamentById,
50
110
  findTournaments: () => findTournaments,
@@ -52,36 +112,72 @@ __export(index_exports, {
52
112
  findUserById: () => findUserById,
53
113
  findUsers: () => findUsers,
54
114
  generateUniquePlayerNumber: () => generateUniquePlayerNumber,
115
+ getBlogTagWithPostCount: () => getBlogTagWithPostCount,
116
+ getBlogTagsWithPostCounts: () => getBlogTagsWithPostCounts,
117
+ getFinalsRounds: () => getFinalsRounds,
118
+ getFinalsStandings: () => getFinalsStandings,
119
+ getLatestOpprRankingHistory: () => getLatestOpprRankingHistory,
120
+ getLocationWithTournaments: () => getLocationWithTournaments,
55
121
  getMajorTournaments: () => getMajorTournaments,
56
- getPlayerResults: () => getPlayerResults,
122
+ getMatchEntries: () => getMatchEntries,
123
+ getMatchWithEntries: () => getMatchWithEntries,
124
+ getMergedStandings: () => getMergedStandings,
125
+ getOpprRankingHistory: () => getOpprRankingHistory,
126
+ getOpprRankingHistoryByDateRange: () => getOpprRankingHistoryByDateRange,
127
+ getOrCreateOpprPlayerRanking: () => getOrCreateOpprPlayerRanking,
128
+ getPlayerEntries: () => getPlayerEntries,
129
+ getPlayerEntryStats: () => getPlayerEntryStats,
130
+ getPlayerStandings: () => getPlayerStandings,
57
131
  getPlayerStats: () => getPlayerStats,
58
132
  getPlayerTopFinishes: () => getPlayerTopFinishes,
133
+ getPlayerTournamentEntries: () => getPlayerTournamentEntries,
134
+ getPlayerTournamentMatches: () => getPlayerTournamentMatches,
59
135
  getPlayerWithResults: () => getPlayerWithResults,
60
- getRatedPlayers: () => getRatedPlayers,
136
+ getQualifyingRounds: () => getQualifyingRounds,
137
+ getQualifyingStandings: () => getQualifyingStandings,
138
+ getRatedOpprPlayers: () => getRatedOpprPlayers,
61
139
  getRecentTournaments: () => getRecentTournaments,
62
- getTopPlayersByRanking: () => getTopPlayersByRanking,
63
- getTopPlayersByRating: () => getTopPlayersByRating,
64
- getTournamentResults: () => getTournamentResults,
140
+ getRoundMatches: () => getRoundMatches,
141
+ getRoundWithMatches: () => getRoundWithMatches,
142
+ getTopPlayersByOpprRanking: () => getTopPlayersByOpprRanking,
143
+ getTopPlayersByOpprRating: () => getTopPlayersByOpprRating,
144
+ getTournamentMatches: () => getTournamentMatches,
145
+ getTournamentRounds: () => getTournamentRounds,
146
+ getTournamentStandings: () => getTournamentStandings,
65
147
  getTournamentStats: () => getTournamentStats,
148
+ getTournamentWithMatches: () => getTournamentWithMatches,
66
149
  getTournamentWithResults: () => getTournamentWithResults,
67
150
  getTournamentsByBoosterType: () => getTournamentsByBoosterType,
68
151
  getTournamentsByDateRange: () => getTournamentsByDateRange,
152
+ getUserApiKeys: () => getUserApiKeys,
69
153
  getUserByEmailWithPlayer: () => getUserByEmailWithPlayer,
70
154
  getUserWithPlayer: () => getUserWithPlayer,
71
155
  isValidPlayerNumber: () => isValidPlayerNumber,
72
156
  linkPlayerToUser: () => linkPlayerToUser,
73
157
  prisma: () => prisma,
74
158
  recalculateTimeDecay: () => recalculateTimeDecay,
159
+ searchBlogPosts: () => searchBlogPosts,
160
+ searchBlogTags: () => searchBlogTags,
161
+ searchLocations: () => searchLocations,
75
162
  searchPlayers: () => searchPlayers,
76
163
  searchTournaments: () => searchTournaments,
77
164
  testConnection: () => testConnection,
165
+ updateApiKeyLastUsed: () => updateApiKeyLastUsed,
166
+ updateBlogPost: () => updateBlogPost,
167
+ updateBlogTag: () => updateBlogTag,
168
+ updateEntry: () => updateEntry,
169
+ updateLocation: () => updateLocation,
170
+ updateMatch: () => updateMatch,
171
+ updateOpprPlayerRanking: () => updateOpprPlayerRanking,
172
+ updateOpprRatingAfterTournament: () => updateOpprRatingAfterTournament,
78
173
  updatePlayer: () => updatePlayer,
79
- updatePlayerRating: () => updatePlayerRating,
80
- updateResult: () => updateResult,
81
- updateResultPoints: () => updateResultPoints,
174
+ updateRound: () => updateRound,
175
+ updateStanding: () => updateStanding,
176
+ updateStandingPoints: () => updateStandingPoints,
82
177
  updateTournament: () => updateTournament,
83
178
  updateUser: () => updateUser,
84
- updateUserRefreshToken: () => updateUserRefreshToken
179
+ updateUserRefreshToken: () => updateUserRefreshToken,
180
+ updateWorldRankings: () => updateWorldRankings
85
181
  });
86
182
  module.exports = __toCommonJS(index_exports);
87
183
 
@@ -180,48 +276,12 @@ async function findPlayers(options = {}) {
180
276
  include: options.include
181
277
  });
182
278
  }
183
- async function getRatedPlayers(options = {}) {
184
- return findPlayers({
185
- ...options,
186
- where: { isRated: true }
187
- });
188
- }
189
- async function getTopPlayersByRating(limit = 50) {
190
- return findPlayers({
191
- take: limit,
192
- orderBy: { rating: "desc" },
193
- where: { isRated: true }
194
- });
195
- }
196
- async function getTopPlayersByRanking(limit = 50) {
197
- return findPlayers({
198
- take: limit,
199
- orderBy: { ranking: "asc" },
200
- where: {
201
- isRated: true,
202
- ranking: { not: null }
203
- }
204
- });
205
- }
206
279
  async function updatePlayer(id, data) {
207
280
  return prisma.player.update({
208
281
  where: { id },
209
282
  data
210
283
  });
211
284
  }
212
- async function updatePlayerRating(id, rating, ratingDeviation, eventCount) {
213
- const updateData = {
214
- rating,
215
- ratingDeviation,
216
- lastRatingUpdate: /* @__PURE__ */ new Date(),
217
- lastEventDate: /* @__PURE__ */ new Date()
218
- };
219
- if (eventCount !== void 0) {
220
- updateData.eventCount = eventCount;
221
- updateData.isRated = eventCount >= 5;
222
- }
223
- return updatePlayer(id, updateData);
224
- }
225
285
  async function deletePlayer(id) {
226
286
  return prisma.player.delete({
227
287
  where: { id }
@@ -234,7 +294,7 @@ async function getPlayerWithResults(id) {
234
294
  const player = await prisma.player.findUnique({
235
295
  where: { id },
236
296
  include: {
237
- tournamentResults: {
297
+ standings: {
238
298
  include: {
239
299
  tournament: true
240
300
  },
@@ -251,7 +311,7 @@ async function getPlayerWithResults(id) {
251
311
  }
252
312
  return {
253
313
  ...player,
254
- results: player.tournamentResults
314
+ results: player.standings
255
315
  };
256
316
  }
257
317
  async function searchPlayers(query, limit = 20) {
@@ -263,6 +323,212 @@ async function searchPlayers(query, limit = 20) {
263
323
  });
264
324
  }
265
325
 
326
+ // src/oppr-rankings.ts
327
+ async function getOrCreateOpprPlayerRanking(playerId) {
328
+ const existing = await prisma.opprPlayerRanking.findUnique({
329
+ where: { playerId }
330
+ });
331
+ if (existing) return existing;
332
+ return prisma.opprPlayerRanking.create({
333
+ data: { playerId }
334
+ });
335
+ }
336
+ async function createOpprPlayerRanking(data) {
337
+ return prisma.opprPlayerRanking.create({
338
+ data
339
+ });
340
+ }
341
+ async function findOpprPlayerRankingById(id, include) {
342
+ return prisma.opprPlayerRanking.findUnique({
343
+ where: { id },
344
+ include
345
+ });
346
+ }
347
+ async function findOpprPlayerRankingByPlayerId(playerId, include) {
348
+ return prisma.opprPlayerRanking.findUnique({
349
+ where: { playerId },
350
+ include
351
+ });
352
+ }
353
+ async function findOpprPlayerRankings(options = {}) {
354
+ return prisma.opprPlayerRanking.findMany({
355
+ take: options.take,
356
+ skip: options.skip,
357
+ where: options.where,
358
+ orderBy: options.orderBy,
359
+ include: options.include
360
+ });
361
+ }
362
+ async function getTopPlayersByOpprRating(limit = 50) {
363
+ return prisma.opprPlayerRanking.findMany({
364
+ take: limit,
365
+ where: { isRated: true },
366
+ orderBy: { rating: "desc" },
367
+ include: { player: true }
368
+ });
369
+ }
370
+ async function getTopPlayersByOpprRanking(limit = 50) {
371
+ return prisma.opprPlayerRanking.findMany({
372
+ take: limit,
373
+ where: {
374
+ isRated: true,
375
+ ranking: { not: null }
376
+ },
377
+ orderBy: { ranking: "asc" },
378
+ include: { player: true }
379
+ });
380
+ }
381
+ async function getRatedOpprPlayers(options = {}) {
382
+ return prisma.opprPlayerRanking.findMany({
383
+ ...options,
384
+ where: { isRated: true },
385
+ include: { player: true, ...options.include }
386
+ });
387
+ }
388
+ async function updateOpprPlayerRanking(playerId, data) {
389
+ return prisma.opprPlayerRanking.update({
390
+ where: { playerId },
391
+ data: {
392
+ ...data,
393
+ lastRatingUpdate: data.lastRatingUpdate ?? /* @__PURE__ */ new Date()
394
+ }
395
+ });
396
+ }
397
+ async function updateOpprRatingAfterTournament(playerId, newRating, newRD, tournamentId, eventCount) {
398
+ const ranking = await getOrCreateOpprPlayerRanking(playerId);
399
+ const isRated = eventCount !== void 0 ? eventCount >= 5 : ranking.isRated;
400
+ const updated = await prisma.opprPlayerRanking.update({
401
+ where: { playerId },
402
+ data: {
403
+ rating: newRating,
404
+ ratingDeviation: newRD,
405
+ lastRatingUpdate: /* @__PURE__ */ new Date(),
406
+ isRated
407
+ }
408
+ });
409
+ await createOpprRankingHistory({
410
+ opprPlayerRankingId: ranking.id,
411
+ rating: newRating,
412
+ ratingDeviation: newRD,
413
+ ranking: updated.ranking ?? void 0,
414
+ isRated,
415
+ changeType: "TOURNAMENT_RESULT",
416
+ tournamentId
417
+ });
418
+ return updated;
419
+ }
420
+ async function updateWorldRankings(rankings) {
421
+ await prisma.$transaction(async (tx) => {
422
+ for (const { playerId, ranking } of rankings) {
423
+ const opprRanking = await tx.opprPlayerRanking.findUnique({
424
+ where: { playerId }
425
+ });
426
+ if (opprRanking) {
427
+ await tx.opprPlayerRanking.update({
428
+ where: { playerId },
429
+ data: { ranking }
430
+ });
431
+ await tx.opprRankingHistory.create({
432
+ data: {
433
+ opprPlayerRankingId: opprRanking.id,
434
+ rating: opprRanking.rating,
435
+ ratingDeviation: opprRanking.ratingDeviation,
436
+ ranking,
437
+ isRated: opprRanking.isRated,
438
+ changeType: "RANKING_REFRESH"
439
+ }
440
+ });
441
+ }
442
+ }
443
+ });
444
+ }
445
+ async function applyRDDecayForInactivePlayers(thresholdDays = 30, decayPerDay = 0.3, maxRD = 200) {
446
+ const cutoffDate = /* @__PURE__ */ new Date();
447
+ cutoffDate.setDate(cutoffDate.getDate() - thresholdDays);
448
+ const inactivePlayers = await prisma.opprPlayerRanking.findMany({
449
+ where: {
450
+ lastRatingUpdate: { lt: cutoffDate },
451
+ ratingDeviation: { lt: maxRD }
452
+ }
453
+ });
454
+ let updatedCount = 0;
455
+ await prisma.$transaction(async (tx) => {
456
+ for (const ranking of inactivePlayers) {
457
+ const daysSinceUpdate = Math.floor(
458
+ (Date.now() - ranking.lastRatingUpdate.getTime()) / (1e3 * 60 * 60 * 24)
459
+ );
460
+ const newRD = Math.min(ranking.ratingDeviation + daysSinceUpdate * decayPerDay, maxRD);
461
+ await tx.opprPlayerRanking.update({
462
+ where: { id: ranking.id },
463
+ data: { ratingDeviation: newRD }
464
+ });
465
+ await tx.opprRankingHistory.create({
466
+ data: {
467
+ opprPlayerRankingId: ranking.id,
468
+ rating: ranking.rating,
469
+ ratingDeviation: newRD,
470
+ ranking: ranking.ranking,
471
+ isRated: ranking.isRated,
472
+ changeType: "RD_DECAY",
473
+ notes: `RD increased from ${ranking.ratingDeviation.toFixed(1)} to ${newRD.toFixed(1)} due to ${daysSinceUpdate} days of inactivity`
474
+ }
475
+ });
476
+ updatedCount++;
477
+ }
478
+ });
479
+ return updatedCount;
480
+ }
481
+ async function deleteOpprPlayerRanking(playerId) {
482
+ return prisma.opprPlayerRanking.delete({
483
+ where: { playerId }
484
+ });
485
+ }
486
+ async function countOpprPlayerRankings(where) {
487
+ return prisma.opprPlayerRanking.count({ where });
488
+ }
489
+ async function createOpprRankingHistory(data) {
490
+ return prisma.opprRankingHistory.create({
491
+ data
492
+ });
493
+ }
494
+ async function getOpprRankingHistory(playerId, limit) {
495
+ const ranking = await findOpprPlayerRankingByPlayerId(playerId);
496
+ if (!ranking) return [];
497
+ return prisma.opprRankingHistory.findMany({
498
+ where: { opprPlayerRankingId: ranking.id },
499
+ orderBy: { createdAt: "desc" },
500
+ take: limit,
501
+ include: { tournament: true }
502
+ });
503
+ }
504
+ async function getOpprRankingHistoryByDateRange(playerId, startDate, endDate) {
505
+ const ranking = await findOpprPlayerRankingByPlayerId(playerId);
506
+ if (!ranking) return [];
507
+ return prisma.opprRankingHistory.findMany({
508
+ where: {
509
+ opprPlayerRankingId: ranking.id,
510
+ createdAt: {
511
+ gte: startDate,
512
+ lte: endDate
513
+ }
514
+ },
515
+ orderBy: { createdAt: "asc" },
516
+ include: { tournament: true }
517
+ });
518
+ }
519
+ async function getLatestOpprRankingHistory(playerId) {
520
+ const ranking = await findOpprPlayerRankingByPlayerId(playerId);
521
+ if (!ranking) return null;
522
+ return prisma.opprRankingHistory.findFirst({
523
+ where: { opprPlayerRankingId: ranking.id },
524
+ orderBy: { createdAt: "desc" },
525
+ include: { tournament: true }
526
+ });
527
+ }
528
+ async function countOpprRankingHistory(where) {
529
+ return prisma.opprRankingHistory.count({ where });
530
+ }
531
+
266
532
  // src/tournaments.ts
267
533
  async function createTournament(data) {
268
534
  return prisma.tournament.create({
@@ -342,13 +608,33 @@ async function getTournamentWithResults(id) {
342
608
  return prisma.tournament.findUnique({
343
609
  where: { id },
344
610
  include: {
345
- results: {
611
+ standings: {
346
612
  include: {
347
613
  player: true
348
614
  },
349
- orderBy: {
350
- position: "asc"
351
- }
615
+ orderBy: [{ isFinals: "desc" }, { position: "asc" }]
616
+ }
617
+ }
618
+ });
619
+ }
620
+ async function getTournamentWithMatches(id) {
621
+ return prisma.tournament.findUnique({
622
+ where: { id },
623
+ include: {
624
+ rounds: {
625
+ include: {
626
+ matches: {
627
+ include: {
628
+ entries: {
629
+ include: {
630
+ player: true
631
+ }
632
+ }
633
+ },
634
+ orderBy: { number: "asc" }
635
+ }
636
+ },
637
+ orderBy: [{ isFinals: "asc" }, { number: "asc" }]
352
638
  }
353
639
  }
354
640
  });
@@ -359,7 +645,7 @@ async function searchTournaments(query, limit = 20) {
359
645
  where: {
360
646
  OR: [
361
647
  { name: { contains: query, mode: "insensitive" } },
362
- { location: { contains: query, mode: "insensitive" } }
648
+ { location: { name: { contains: query, mode: "insensitive" } } }
363
649
  ]
364
650
  },
365
651
  orderBy: { date: "desc" }
@@ -370,7 +656,7 @@ async function getTournamentStats(id) {
370
656
  if (!tournament) {
371
657
  return null;
372
658
  }
373
- const playerCount = tournament.results.length;
659
+ const playerCount = tournament.standings.length;
374
660
  if (playerCount === 0) {
375
661
  return {
376
662
  tournament,
@@ -381,9 +667,9 @@ async function getTournamentStats(id) {
381
667
  lowestPoints: 0
382
668
  };
383
669
  }
384
- const totalPoints = tournament.results.reduce((sum, r) => sum + (r.totalPoints || 0), 0);
385
- const totalEfficiency = tournament.results.reduce((sum, r) => sum + (r.efficiency || 0), 0);
386
- const allPoints = tournament.results.map((r) => r.totalPoints || 0);
670
+ const totalPoints = tournament.standings.reduce((sum, s) => sum + (s.totalPoints || 0), 0);
671
+ const totalEfficiency = tournament.standings.reduce((sum, s) => sum + (s.efficiency || 0), 0);
672
+ const allPoints = tournament.standings.map((s) => s.totalPoints || 0);
387
673
  return {
388
674
  tournament,
389
675
  playerCount,
@@ -394,44 +680,364 @@ async function getTournamentStats(id) {
394
680
  };
395
681
  }
396
682
 
397
- // src/results.ts
398
- async function createResult(data) {
399
- const resultData = {
683
+ // src/rounds.ts
684
+ async function createRound(data) {
685
+ return prisma.round.create({
686
+ data: {
687
+ ...data,
688
+ isFinals: data.isFinals ?? false
689
+ }
690
+ });
691
+ }
692
+ async function createManyRounds(data) {
693
+ const roundsData = data.map((item) => ({
694
+ ...item,
695
+ isFinals: item.isFinals ?? false
696
+ }));
697
+ return prisma.round.createMany({
698
+ data: roundsData
699
+ });
700
+ }
701
+ async function findRoundById(id, include) {
702
+ return prisma.round.findUnique({
703
+ where: { id },
704
+ include
705
+ });
706
+ }
707
+ async function findRoundByTournamentAndNumber(tournamentId, number, isFinals, include) {
708
+ return prisma.round.findUnique({
709
+ where: {
710
+ tournamentId_number_isFinals: {
711
+ tournamentId,
712
+ number,
713
+ isFinals
714
+ }
715
+ },
716
+ include
717
+ });
718
+ }
719
+ async function findRounds(options = {}) {
720
+ return prisma.round.findMany({
721
+ take: options.take,
722
+ skip: options.skip,
723
+ where: options.where,
724
+ orderBy: options.orderBy,
725
+ include: options.include
726
+ });
727
+ }
728
+ async function getTournamentRounds(tournamentId, options = {}) {
729
+ return findRounds({
730
+ ...options,
731
+ where: { tournamentId },
732
+ orderBy: options.orderBy ?? [{ isFinals: "asc" }, { number: "asc" }]
733
+ });
734
+ }
735
+ async function getQualifyingRounds(tournamentId, options = {}) {
736
+ return findRounds({
737
+ ...options,
738
+ where: { tournamentId, isFinals: false },
739
+ orderBy: options.orderBy ?? { number: "asc" }
740
+ });
741
+ }
742
+ async function getFinalsRounds(tournamentId, options = {}) {
743
+ return findRounds({
744
+ ...options,
745
+ where: { tournamentId, isFinals: true },
746
+ orderBy: options.orderBy ?? { number: "asc" }
747
+ });
748
+ }
749
+ async function updateRound(id, data) {
750
+ return prisma.round.update({
751
+ where: { id },
752
+ data
753
+ });
754
+ }
755
+ async function deleteRound(id) {
756
+ return prisma.round.delete({
757
+ where: { id }
758
+ });
759
+ }
760
+ async function deleteRoundsByTournament(tournamentId) {
761
+ return prisma.round.deleteMany({
762
+ where: { tournamentId }
763
+ });
764
+ }
765
+ async function countRounds(where) {
766
+ return prisma.round.count({ where });
767
+ }
768
+ async function getRoundWithMatches(id) {
769
+ return prisma.round.findUnique({
770
+ where: { id },
771
+ include: {
772
+ matches: {
773
+ include: {
774
+ entries: {
775
+ include: {
776
+ player: true
777
+ }
778
+ }
779
+ },
780
+ orderBy: {
781
+ number: "asc"
782
+ }
783
+ }
784
+ }
785
+ });
786
+ }
787
+
788
+ // src/matches.ts
789
+ async function createMatch(data) {
790
+ return prisma.match.create({
791
+ data
792
+ });
793
+ }
794
+ async function createManyMatches(data) {
795
+ return prisma.match.createMany({
796
+ data
797
+ });
798
+ }
799
+ async function findMatchById(id, include) {
800
+ return prisma.match.findUnique({
801
+ where: { id },
802
+ include
803
+ });
804
+ }
805
+ async function findMatches(options = {}) {
806
+ return prisma.match.findMany({
807
+ take: options.take,
808
+ skip: options.skip,
809
+ where: options.where,
810
+ orderBy: options.orderBy,
811
+ include: options.include
812
+ });
813
+ }
814
+ async function getTournamentMatches(tournamentId, options = {}) {
815
+ return findMatches({
816
+ ...options,
817
+ where: { tournamentId },
818
+ orderBy: options.orderBy ?? { number: "asc" }
819
+ });
820
+ }
821
+ async function getRoundMatches(roundId, options = {}) {
822
+ return findMatches({
823
+ ...options,
824
+ where: { roundId },
825
+ orderBy: options.orderBy ?? { number: "asc" }
826
+ });
827
+ }
828
+ async function updateMatch(id, data) {
829
+ return prisma.match.update({
830
+ where: { id },
831
+ data
832
+ });
833
+ }
834
+ async function deleteMatch(id) {
835
+ return prisma.match.delete({
836
+ where: { id }
837
+ });
838
+ }
839
+ async function deleteMatchesByTournament(tournamentId) {
840
+ return prisma.match.deleteMany({
841
+ where: { tournamentId }
842
+ });
843
+ }
844
+ async function deleteMatchesByRound(roundId) {
845
+ return prisma.match.deleteMany({
846
+ where: { roundId }
847
+ });
848
+ }
849
+ async function countMatches(where) {
850
+ return prisma.match.count({ where });
851
+ }
852
+ async function getMatchWithEntries(id) {
853
+ return prisma.match.findUnique({
854
+ where: { id },
855
+ include: {
856
+ entries: {
857
+ include: {
858
+ player: true
859
+ },
860
+ orderBy: {
861
+ position: "asc"
862
+ }
863
+ },
864
+ round: true
865
+ }
866
+ });
867
+ }
868
+ async function getPlayerTournamentMatches(playerId, tournamentId, include) {
869
+ return findMatches({
870
+ where: {
871
+ tournamentId,
872
+ entries: {
873
+ some: {
874
+ playerId
875
+ }
876
+ }
877
+ },
878
+ include: include ?? {
879
+ entries: {
880
+ include: {
881
+ player: true
882
+ }
883
+ },
884
+ round: true
885
+ },
886
+ orderBy: [{ round: { number: "asc" } }, { number: "asc" }]
887
+ });
888
+ }
889
+
890
+ // src/entries.ts
891
+ async function createEntry(data) {
892
+ return prisma.entry.create({
893
+ data
894
+ });
895
+ }
896
+ async function createManyEntries(data) {
897
+ return prisma.entry.createMany({
898
+ data
899
+ });
900
+ }
901
+ async function findEntryById(id, include) {
902
+ return prisma.entry.findUnique({
903
+ where: { id },
904
+ include
905
+ });
906
+ }
907
+ async function findEntryByMatchAndPlayer(matchId, playerId, include) {
908
+ return prisma.entry.findUnique({
909
+ where: {
910
+ matchId_playerId: {
911
+ matchId,
912
+ playerId
913
+ }
914
+ },
915
+ include
916
+ });
917
+ }
918
+ async function findEntries(options = {}) {
919
+ return prisma.entry.findMany({
920
+ take: options.take,
921
+ skip: options.skip,
922
+ where: options.where,
923
+ orderBy: options.orderBy,
924
+ include: options.include
925
+ });
926
+ }
927
+ async function getMatchEntries(matchId, options = {}) {
928
+ return findEntries({
929
+ ...options,
930
+ where: { matchId },
931
+ include: options.include ?? { player: true },
932
+ orderBy: options.orderBy ?? { position: "asc" }
933
+ });
934
+ }
935
+ async function getPlayerEntries(playerId, options = {}) {
936
+ return findEntries({
937
+ ...options,
938
+ where: { playerId },
939
+ include: options.include ?? { match: { include: { round: true, tournament: true } } }
940
+ });
941
+ }
942
+ async function getPlayerTournamentEntries(playerId, tournamentId, include) {
943
+ return findEntries({
944
+ where: {
945
+ playerId,
946
+ match: {
947
+ tournamentId
948
+ }
949
+ },
950
+ include: include ?? {
951
+ match: {
952
+ include: {
953
+ round: true,
954
+ entries: {
955
+ include: {
956
+ player: true
957
+ }
958
+ }
959
+ }
960
+ }
961
+ }
962
+ });
963
+ }
964
+ async function updateEntry(id, data) {
965
+ return prisma.entry.update({
966
+ where: { id },
967
+ data
968
+ });
969
+ }
970
+ async function deleteEntry(id) {
971
+ return prisma.entry.delete({
972
+ where: { id }
973
+ });
974
+ }
975
+ async function deleteEntriesByMatch(matchId) {
976
+ return prisma.entry.deleteMany({
977
+ where: { matchId }
978
+ });
979
+ }
980
+ async function countEntries(where) {
981
+ return prisma.entry.count({ where });
982
+ }
983
+ async function getPlayerEntryStats(playerId) {
984
+ const entries = await getPlayerEntries(playerId);
985
+ if (entries.length === 0) {
986
+ return null;
987
+ }
988
+ const wins = entries.filter((e) => e.result === "WIN").length;
989
+ const losses = entries.filter((e) => e.result === "LOSS").length;
990
+ const ties = entries.filter((e) => e.result === "TIE").length;
991
+ return {
992
+ totalMatches: entries.length,
993
+ wins,
994
+ losses,
995
+ ties,
996
+ winRate: wins / entries.length
997
+ };
998
+ }
999
+
1000
+ // src/standings.ts
1001
+ async function createStanding(data) {
1002
+ const standingData = {
400
1003
  ...data,
1004
+ isFinals: data.isFinals ?? false,
401
1005
  decayedPoints: data.decayedPoints ?? data.totalPoints ?? 0
402
1006
  };
403
- return prisma.tournamentResult.create({
404
- data: resultData
1007
+ return prisma.standing.create({
1008
+ data: standingData
405
1009
  });
406
1010
  }
407
- async function createManyResults(data) {
408
- const resultsData = data.map((item) => ({
1011
+ async function createManyStandings(data) {
1012
+ const standingsData = data.map((item) => ({
409
1013
  ...item,
1014
+ isFinals: item.isFinals ?? false,
410
1015
  decayedPoints: item.decayedPoints ?? item.totalPoints ?? 0
411
1016
  }));
412
- return prisma.tournamentResult.createMany({
413
- data: resultsData
1017
+ return prisma.standing.createMany({
1018
+ data: standingsData
414
1019
  });
415
1020
  }
416
- async function findResultById(id, include) {
417
- return prisma.tournamentResult.findUnique({
1021
+ async function findStandingById(id, include) {
1022
+ return prisma.standing.findUnique({
418
1023
  where: { id },
419
1024
  include
420
1025
  });
421
1026
  }
422
- async function findResultByPlayerAndTournament(playerId, tournamentId, include) {
423
- return prisma.tournamentResult.findUnique({
1027
+ async function findStandingByPlayerAndTournament(playerId, tournamentId, isFinals, include) {
1028
+ return prisma.standing.findUnique({
424
1029
  where: {
425
- playerId_tournamentId: {
1030
+ playerId_tournamentId_isFinals: {
426
1031
  playerId,
427
- tournamentId
1032
+ tournamentId,
1033
+ isFinals
428
1034
  }
429
1035
  },
430
1036
  include
431
1037
  });
432
1038
  }
433
- async function findResults(options = {}) {
434
- return prisma.tournamentResult.findMany({
1039
+ async function findStandings(options = {}) {
1040
+ return prisma.standing.findMany({
435
1041
  take: options.take,
436
1042
  skip: options.skip,
437
1043
  where: options.where,
@@ -439,45 +1045,85 @@ async function findResults(options = {}) {
439
1045
  include: options.include
440
1046
  });
441
1047
  }
442
- async function getPlayerResults(playerId, options = {}) {
443
- return findResults({
1048
+ async function getPlayerStandings(playerId, options = {}) {
1049
+ return findStandings({
444
1050
  ...options,
445
1051
  where: { playerId },
446
1052
  include: { tournament: true, ...options.include },
447
1053
  orderBy: { tournament: { date: "desc" } }
448
1054
  });
449
1055
  }
450
- async function getTournamentResults(tournamentId, options = {}) {
451
- return findResults({
1056
+ async function getTournamentStandings(tournamentId, options = {}) {
1057
+ return findStandings({
452
1058
  ...options,
453
1059
  where: { tournamentId },
454
1060
  include: { player: true, ...options.include },
455
- orderBy: { position: "asc" }
1061
+ orderBy: options.orderBy ?? { position: "asc" }
456
1062
  });
457
1063
  }
1064
+ async function getQualifyingStandings(tournamentId, options = {}) {
1065
+ return findStandings({
1066
+ ...options,
1067
+ where: { tournamentId, isFinals: false },
1068
+ include: { player: true, ...options.include },
1069
+ orderBy: options.orderBy ?? { position: "asc" }
1070
+ });
1071
+ }
1072
+ async function getFinalsStandings(tournamentId, options = {}) {
1073
+ return findStandings({
1074
+ ...options,
1075
+ where: { tournamentId, isFinals: true },
1076
+ include: { player: true, ...options.include },
1077
+ orderBy: options.orderBy ?? { position: "asc" }
1078
+ });
1079
+ }
1080
+ async function getMergedStandings(tournamentId) {
1081
+ const [finals, qualifying] = await Promise.all([
1082
+ findStandings({
1083
+ where: { tournamentId, isFinals: true },
1084
+ orderBy: { position: "asc" },
1085
+ include: { player: true }
1086
+ }),
1087
+ findStandings({
1088
+ where: { tournamentId, isFinals: false },
1089
+ orderBy: { position: "asc" },
1090
+ include: { player: true }
1091
+ })
1092
+ ]);
1093
+ const finalistIds = new Set(finals.map((s) => s.playerId));
1094
+ const nonFinalists = qualifying.filter((s) => !finalistIds.has(s.playerId));
1095
+ return [
1096
+ ...finals.map((s) => ({ ...s, mergedPosition: s.position, isFinalist: true })),
1097
+ ...nonFinalists.map((s, i) => ({
1098
+ ...s,
1099
+ mergedPosition: finals.length + i + 1,
1100
+ isFinalist: false
1101
+ }))
1102
+ ];
1103
+ }
458
1104
  async function getPlayerTopFinishes(playerId, limit = 15) {
459
- return findResults({
1105
+ return findStandings({
460
1106
  where: { playerId },
461
1107
  take: limit,
462
1108
  include: { tournament: true },
463
1109
  orderBy: { decayedPoints: "desc" }
464
1110
  });
465
1111
  }
466
- async function updateResult(id, data) {
467
- return prisma.tournamentResult.update({
1112
+ async function updateStanding(id, data) {
1113
+ return prisma.standing.update({
468
1114
  where: { id },
469
1115
  data
470
1116
  });
471
1117
  }
472
- async function updateResultPoints(id, linearPoints, dynamicPoints, totalPoints) {
473
- const result = await findResultById(id, {
1118
+ async function updateStandingPoints(id, linearPoints, dynamicPoints, totalPoints) {
1119
+ const standing = await findStandingById(id, {
474
1120
  tournament: true
475
1121
  });
476
- if (!result) {
477
- throw new Error(`Result with id ${id} not found`);
1122
+ if (!standing) {
1123
+ throw new Error(`Standing with id ${id} not found`);
478
1124
  }
479
1125
  const now = /* @__PURE__ */ new Date();
480
- const tournamentDate = result.tournament.date;
1126
+ const tournamentDate = standing.tournament.date;
481
1127
  const ageInDays = Math.floor((now.getTime() - tournamentDate.getTime()) / (1e3 * 60 * 60 * 24));
482
1128
  const ageInYears = ageInDays / 365;
483
1129
  let decayMultiplier = 0;
@@ -491,7 +1137,7 @@ async function updateResultPoints(id, linearPoints, dynamicPoints, totalPoints)
491
1137
  decayMultiplier = 0;
492
1138
  }
493
1139
  const decayedPoints = totalPoints * decayMultiplier;
494
- return updateResult(id, {
1140
+ return updateStanding(id, {
495
1141
  linearPoints,
496
1142
  dynamicPoints,
497
1143
  totalPoints,
@@ -500,50 +1146,50 @@ async function updateResultPoints(id, linearPoints, dynamicPoints, totalPoints)
500
1146
  decayedPoints
501
1147
  });
502
1148
  }
503
- async function deleteResult(id) {
504
- return prisma.tournamentResult.delete({
1149
+ async function deleteStanding(id) {
1150
+ return prisma.standing.delete({
505
1151
  where: { id }
506
1152
  });
507
1153
  }
508
- async function deleteResultsByTournament(tournamentId) {
509
- return prisma.tournamentResult.deleteMany({
1154
+ async function deleteStandingsByTournament(tournamentId) {
1155
+ return prisma.standing.deleteMany({
510
1156
  where: { tournamentId }
511
1157
  });
512
1158
  }
513
- async function countResults(where) {
514
- return prisma.tournamentResult.count({ where });
1159
+ async function countStandings(where) {
1160
+ return prisma.standing.count({ where });
515
1161
  }
516
1162
  async function getPlayerStats(playerId) {
517
- const results = await getPlayerResults(playerId);
518
- if (results.length === 0) {
1163
+ const standings = await getPlayerStandings(playerId);
1164
+ if (standings.length === 0) {
519
1165
  return null;
520
1166
  }
521
- const totalPoints = results.reduce((sum, r) => sum + (r.totalPoints || 0), 0);
522
- const totalDecayedPoints = results.reduce((sum, r) => sum + (r.decayedPoints || 0), 0);
523
- const averagePosition = results.reduce((sum, r) => sum + r.position, 0) / results.length;
524
- const averageEfficiency = results.reduce((sum, r) => sum + (r.efficiency || 0), 0) / results.length;
525
- const firstPlaceFinishes = results.filter((r) => r.position === 1).length;
526
- const topThreeFinishes = results.filter((r) => r.position <= 3).length;
1167
+ const totalPoints = standings.reduce((sum, s) => sum + (s.totalPoints || 0), 0);
1168
+ const totalDecayedPoints = standings.reduce((sum, s) => sum + (s.decayedPoints || 0), 0);
1169
+ const averagePosition = standings.reduce((sum, s) => sum + s.position, 0) / standings.length;
1170
+ const averageEfficiency = standings.reduce((sum, s) => sum + (s.efficiency || 0), 0) / standings.length;
1171
+ const firstPlaceFinishes = standings.filter((s) => s.position === 1).length;
1172
+ const topThreeFinishes = standings.filter((s) => s.position <= 3).length;
527
1173
  return {
528
- totalEvents: results.length,
1174
+ totalEvents: standings.length,
529
1175
  totalPoints,
530
1176
  totalDecayedPoints,
531
- averagePoints: totalPoints / results.length,
1177
+ averagePoints: totalPoints / standings.length,
532
1178
  averagePosition,
533
1179
  averageFinish: averagePosition,
534
1180
  averageEfficiency,
535
1181
  firstPlaceFinishes,
536
1182
  topThreeFinishes,
537
- bestFinish: Math.min(...results.map((r) => r.position)),
538
- highestPoints: Math.max(...results.map((r) => r.totalPoints || 0))
1183
+ bestFinish: Math.min(...standings.map((s) => s.position)),
1184
+ highestPoints: Math.max(...standings.map((s) => s.totalPoints || 0))
539
1185
  };
540
1186
  }
541
1187
  async function recalculateTimeDecay(referenceDate = /* @__PURE__ */ new Date()) {
542
- const results = await findResults({
1188
+ const standings = await findStandings({
543
1189
  include: { tournament: true }
544
1190
  });
545
- const updates = results.map((result) => {
546
- const tournamentDate = result.tournament.date;
1191
+ const updates = standings.map((standing) => {
1192
+ const tournamentDate = standing.tournament.date;
547
1193
  const ageInDays = Math.floor(
548
1194
  (referenceDate.getTime() - tournamentDate.getTime()) / (1e3 * 60 * 60 * 24)
549
1195
  );
@@ -558,9 +1204,9 @@ async function recalculateTimeDecay(referenceDate = /* @__PURE__ */ new Date())
558
1204
  } else {
559
1205
  decayMultiplier = 0;
560
1206
  }
561
- const decayedPoints = (result.totalPoints || 0) * decayMultiplier;
562
- return prisma.tournamentResult.update({
563
- where: { id: result.id },
1207
+ const decayedPoints = (standing.totalPoints || 0) * decayMultiplier;
1208
+ return prisma.standing.update({
1209
+ where: { id: standing.id },
564
1210
  data: {
565
1211
  ageInDays,
566
1212
  decayMultiplier,
@@ -597,10 +1243,6 @@ async function createUserWithPlayer(userData, playerData) {
597
1243
  id: true,
598
1244
  playerNumber: true,
599
1245
  name: true,
600
- rating: true,
601
- ratingDeviation: true,
602
- ranking: true,
603
- isRated: true,
604
1246
  eventCount: true
605
1247
  }
606
1248
  }
@@ -630,10 +1272,6 @@ async function getUserWithPlayer(id) {
630
1272
  id: true,
631
1273
  playerNumber: true,
632
1274
  name: true,
633
- rating: true,
634
- ratingDeviation: true,
635
- ranking: true,
636
- isRated: true,
637
1275
  eventCount: true
638
1276
  }
639
1277
  }
@@ -653,10 +1291,6 @@ async function getUserByEmailWithPlayer(email) {
653
1291
  id: true,
654
1292
  playerNumber: true,
655
1293
  name: true,
656
- rating: true,
657
- ratingDeviation: true,
658
- ranking: true,
659
- isRated: true,
660
1294
  eventCount: true
661
1295
  }
662
1296
  }
@@ -699,10 +1333,6 @@ async function findUsers(params) {
699
1333
  id: true,
700
1334
  playerNumber: true,
701
1335
  name: true,
702
- rating: true,
703
- ratingDeviation: true,
704
- ranking: true,
705
- isRated: true,
706
1336
  eventCount: true
707
1337
  }
708
1338
  }
@@ -731,10 +1361,6 @@ async function linkPlayerToUser(userId, playerId) {
731
1361
  id: true,
732
1362
  playerNumber: true,
733
1363
  name: true,
734
- rating: true,
735
- ratingDeviation: true,
736
- ranking: true,
737
- isRated: true,
738
1364
  eventCount: true
739
1365
  }
740
1366
  }
@@ -743,33 +1369,397 @@ async function linkPlayerToUser(userId, playerId) {
743
1369
  return user;
744
1370
  });
745
1371
  }
1372
+
1373
+ // src/api-keys.ts
1374
+ var MAX_API_KEYS_PER_USER = 5;
1375
+ async function createApiKey(data) {
1376
+ return prisma.apiKey.create({ data });
1377
+ }
1378
+ async function findApiKeyById(id) {
1379
+ return prisma.apiKey.findUnique({ where: { id } });
1380
+ }
1381
+ async function findApiKeysByPrefix(keyPrefix) {
1382
+ const keys = await prisma.apiKey.findMany({
1383
+ where: { keyPrefix },
1384
+ include: {
1385
+ user: {
1386
+ select: {
1387
+ id: true,
1388
+ email: true,
1389
+ role: true
1390
+ }
1391
+ }
1392
+ }
1393
+ });
1394
+ return keys;
1395
+ }
1396
+ async function getUserApiKeys(userId) {
1397
+ return prisma.apiKey.findMany({
1398
+ where: { userId },
1399
+ select: {
1400
+ id: true,
1401
+ name: true,
1402
+ keyPrefix: true,
1403
+ expiresAt: true,
1404
+ lastUsedAt: true,
1405
+ createdAt: true
1406
+ },
1407
+ orderBy: { createdAt: "desc" }
1408
+ });
1409
+ }
1410
+ async function countUserApiKeys(userId) {
1411
+ return prisma.apiKey.count({ where: { userId } });
1412
+ }
1413
+ async function updateApiKeyLastUsed(id) {
1414
+ await prisma.apiKey.update({
1415
+ where: { id },
1416
+ data: { lastUsedAt: /* @__PURE__ */ new Date() }
1417
+ });
1418
+ }
1419
+ async function deleteApiKey(id) {
1420
+ return prisma.apiKey.delete({ where: { id } });
1421
+ }
1422
+ async function deleteUserApiKey(id, userId) {
1423
+ const key = await prisma.apiKey.findFirst({
1424
+ where: { id, userId }
1425
+ });
1426
+ if (!key) {
1427
+ return null;
1428
+ }
1429
+ return prisma.apiKey.delete({ where: { id } });
1430
+ }
1431
+
1432
+ // src/locations.ts
1433
+ async function createLocation(data) {
1434
+ return prisma.location.create({
1435
+ data
1436
+ });
1437
+ }
1438
+ async function findLocationById(id, include) {
1439
+ return prisma.location.findUnique({
1440
+ where: { id },
1441
+ include
1442
+ });
1443
+ }
1444
+ async function findLocationByExternalId(externalId, include) {
1445
+ return prisma.location.findUnique({
1446
+ where: { externalId },
1447
+ include
1448
+ });
1449
+ }
1450
+ async function findLocations(options = {}) {
1451
+ return prisma.location.findMany({
1452
+ take: options.take,
1453
+ skip: options.skip,
1454
+ where: options.where,
1455
+ orderBy: options.orderBy,
1456
+ include: options.include
1457
+ });
1458
+ }
1459
+ async function searchLocations(query, limit = 20) {
1460
+ return findLocations({
1461
+ take: limit,
1462
+ where: {
1463
+ OR: [
1464
+ { name: { contains: query, mode: "insensitive" } },
1465
+ { city: { contains: query, mode: "insensitive" } }
1466
+ ]
1467
+ },
1468
+ orderBy: { name: "asc" }
1469
+ });
1470
+ }
1471
+ async function updateLocation(id, data) {
1472
+ return prisma.location.update({
1473
+ where: { id },
1474
+ data
1475
+ });
1476
+ }
1477
+ async function deleteLocation(id) {
1478
+ return prisma.location.delete({
1479
+ where: { id }
1480
+ });
1481
+ }
1482
+ async function countLocations(where) {
1483
+ return prisma.location.count({ where });
1484
+ }
1485
+ async function getLocationWithTournaments(id) {
1486
+ return prisma.location.findUnique({
1487
+ where: { id },
1488
+ include: {
1489
+ tournaments: {
1490
+ orderBy: {
1491
+ date: "desc"
1492
+ }
1493
+ }
1494
+ }
1495
+ });
1496
+ }
1497
+
1498
+ // src/blog-posts.ts
1499
+ var defaultInclude = {
1500
+ author: {
1501
+ select: { id: true, email: true }
1502
+ },
1503
+ tags: {
1504
+ select: { id: true, name: true, slug: true }
1505
+ }
1506
+ };
1507
+ async function createBlogPost(data) {
1508
+ const { tagIds, ...postData } = data;
1509
+ return prisma.blogPost.create({
1510
+ data: {
1511
+ ...postData,
1512
+ tags: tagIds?.length ? { connect: tagIds.map((id) => ({ id })) } : void 0
1513
+ },
1514
+ include: defaultInclude
1515
+ });
1516
+ }
1517
+ async function findBlogPostById(id) {
1518
+ return prisma.blogPost.findUnique({
1519
+ where: { id },
1520
+ include: defaultInclude
1521
+ });
1522
+ }
1523
+ async function findBlogPostBySlug(slug) {
1524
+ return prisma.blogPost.findUnique({
1525
+ where: { slug },
1526
+ include: defaultInclude
1527
+ });
1528
+ }
1529
+ async function findBlogPosts(options = {}) {
1530
+ return prisma.blogPost.findMany({
1531
+ take: options.take,
1532
+ skip: options.skip,
1533
+ where: options.where,
1534
+ orderBy: options.orderBy ?? { createdAt: "desc" },
1535
+ include: options.include ?? defaultInclude
1536
+ });
1537
+ }
1538
+ async function findPublishedBlogPosts(options = {}) {
1539
+ const { tagSlug, ...restOptions } = options;
1540
+ const where = {
1541
+ status: "PUBLISHED",
1542
+ publishedAt: { not: null },
1543
+ ...tagSlug && {
1544
+ tags: {
1545
+ some: { slug: tagSlug }
1546
+ }
1547
+ }
1548
+ };
1549
+ return findBlogPosts({
1550
+ ...restOptions,
1551
+ where,
1552
+ orderBy: options.orderBy ?? { publishedAt: "desc" }
1553
+ });
1554
+ }
1555
+ async function searchBlogPosts(query, limit = 20, publishedOnly = true) {
1556
+ const where = {
1557
+ OR: [
1558
+ { title: { contains: query, mode: "insensitive" } },
1559
+ { excerpt: { contains: query, mode: "insensitive" } }
1560
+ ],
1561
+ ...publishedOnly && {
1562
+ status: "PUBLISHED",
1563
+ publishedAt: { not: null }
1564
+ }
1565
+ };
1566
+ return findBlogPosts({
1567
+ take: limit,
1568
+ where,
1569
+ orderBy: { publishedAt: "desc" }
1570
+ });
1571
+ }
1572
+ async function updateBlogPost(id, data) {
1573
+ const { tagIds, ...postData } = data;
1574
+ return prisma.blogPost.update({
1575
+ where: { id },
1576
+ data: {
1577
+ ...postData,
1578
+ // If tagIds is provided, replace all tags
1579
+ ...tagIds !== void 0 && {
1580
+ tags: {
1581
+ set: tagIds.map((tagId) => ({ id: tagId }))
1582
+ }
1583
+ }
1584
+ },
1585
+ include: defaultInclude
1586
+ });
1587
+ }
1588
+ async function deleteBlogPost(id) {
1589
+ return prisma.blogPost.delete({
1590
+ where: { id }
1591
+ });
1592
+ }
1593
+ async function countBlogPosts(where) {
1594
+ return prisma.blogPost.count({ where });
1595
+ }
1596
+ async function countPublishedBlogPosts(tagSlug) {
1597
+ return countBlogPosts({
1598
+ status: "PUBLISHED",
1599
+ publishedAt: { not: null },
1600
+ ...tagSlug && {
1601
+ tags: {
1602
+ some: { slug: tagSlug }
1603
+ }
1604
+ }
1605
+ });
1606
+ }
1607
+
1608
+ // src/blog-tags.ts
1609
+ async function createBlogTag(data) {
1610
+ return prisma.blogTag.create({
1611
+ data
1612
+ });
1613
+ }
1614
+ async function findBlogTagById(id) {
1615
+ return prisma.blogTag.findUnique({
1616
+ where: { id }
1617
+ });
1618
+ }
1619
+ async function findBlogTagBySlug(slug) {
1620
+ return prisma.blogTag.findUnique({
1621
+ where: { slug }
1622
+ });
1623
+ }
1624
+ async function findBlogTags(options = {}) {
1625
+ return prisma.blogTag.findMany({
1626
+ take: options.take,
1627
+ skip: options.skip,
1628
+ where: options.where,
1629
+ orderBy: options.orderBy ?? { name: "asc" },
1630
+ include: options.include
1631
+ });
1632
+ }
1633
+ async function searchBlogTags(query, limit = 20) {
1634
+ return findBlogTags({
1635
+ take: limit,
1636
+ where: {
1637
+ name: { contains: query, mode: "insensitive" }
1638
+ },
1639
+ orderBy: { name: "asc" }
1640
+ });
1641
+ }
1642
+ async function updateBlogTag(id, data) {
1643
+ return prisma.blogTag.update({
1644
+ where: { id },
1645
+ data
1646
+ });
1647
+ }
1648
+ async function deleteBlogTag(id) {
1649
+ return prisma.blogTag.delete({
1650
+ where: { id }
1651
+ });
1652
+ }
1653
+ async function countBlogTags(where) {
1654
+ return prisma.blogTag.count({ where });
1655
+ }
1656
+ async function getBlogTagWithPostCount(id) {
1657
+ return prisma.blogTag.findUnique({
1658
+ where: { id },
1659
+ include: {
1660
+ _count: {
1661
+ select: { posts: true }
1662
+ }
1663
+ }
1664
+ });
1665
+ }
1666
+ async function getBlogTagsWithPostCounts() {
1667
+ return prisma.blogTag.findMany({
1668
+ include: {
1669
+ _count: {
1670
+ select: { posts: true }
1671
+ }
1672
+ },
1673
+ orderBy: { name: "asc" }
1674
+ });
1675
+ }
746
1676
  // Annotate the CommonJS export names for ESM import in node:
747
1677
  0 && (module.exports = {
1678
+ MAX_API_KEYS_PER_USER,
1679
+ applyRDDecayForInactivePlayers,
748
1680
  connect,
1681
+ countBlogPosts,
1682
+ countBlogTags,
1683
+ countEntries,
1684
+ countLocations,
1685
+ countMatches,
1686
+ countOpprPlayerRankings,
1687
+ countOpprRankingHistory,
749
1688
  countPlayers,
750
- countResults,
1689
+ countPublishedBlogPosts,
1690
+ countRounds,
1691
+ countStandings,
751
1692
  countTournaments,
1693
+ countUserApiKeys,
752
1694
  countUsers,
753
- createManyResults,
1695
+ createApiKey,
1696
+ createBlogPost,
1697
+ createBlogTag,
1698
+ createEntry,
1699
+ createLocation,
1700
+ createManyEntries,
1701
+ createManyMatches,
1702
+ createManyRounds,
1703
+ createManyStandings,
1704
+ createMatch,
1705
+ createOpprPlayerRanking,
1706
+ createOpprRankingHistory,
754
1707
  createPlayer,
755
- createResult,
1708
+ createRound,
1709
+ createStanding,
756
1710
  createTournament,
757
1711
  createUser,
758
1712
  createUserWithPlayer,
1713
+ deleteApiKey,
1714
+ deleteBlogPost,
1715
+ deleteBlogTag,
1716
+ deleteEntriesByMatch,
1717
+ deleteEntry,
1718
+ deleteLocation,
1719
+ deleteMatch,
1720
+ deleteMatchesByRound,
1721
+ deleteMatchesByTournament,
1722
+ deleteOpprPlayerRanking,
759
1723
  deletePlayer,
760
- deleteResult,
761
- deleteResultsByTournament,
1724
+ deleteRound,
1725
+ deleteRoundsByTournament,
1726
+ deleteStanding,
1727
+ deleteStandingsByTournament,
762
1728
  deleteTournament,
763
1729
  deleteUser,
1730
+ deleteUserApiKey,
764
1731
  disconnect,
1732
+ findApiKeyById,
1733
+ findApiKeysByPrefix,
1734
+ findBlogPostById,
1735
+ findBlogPostBySlug,
1736
+ findBlogPosts,
1737
+ findBlogTagById,
1738
+ findBlogTagBySlug,
1739
+ findBlogTags,
1740
+ findEntries,
1741
+ findEntryById,
1742
+ findEntryByMatchAndPlayer,
1743
+ findLocationByExternalId,
1744
+ findLocationById,
1745
+ findLocations,
1746
+ findMatchById,
1747
+ findMatches,
1748
+ findOpprPlayerRankingById,
1749
+ findOpprPlayerRankingByPlayerId,
1750
+ findOpprPlayerRankings,
765
1751
  findPlayerByExternalId,
766
1752
  findPlayerById,
767
1753
  findPlayerByPlayerNumber,
768
1754
  findPlayerByUserEmail,
769
1755
  findPlayers,
770
- findResultById,
771
- findResultByPlayerAndTournament,
772
- findResults,
1756
+ findPublishedBlogPosts,
1757
+ findRoundById,
1758
+ findRoundByTournamentAndNumber,
1759
+ findRounds,
1760
+ findStandingById,
1761
+ findStandingByPlayerAndTournament,
1762
+ findStandings,
773
1763
  findTournamentByExternalId,
774
1764
  findTournamentById,
775
1765
  findTournaments,
@@ -777,34 +1767,70 @@ async function linkPlayerToUser(userId, playerId) {
777
1767
  findUserById,
778
1768
  findUsers,
779
1769
  generateUniquePlayerNumber,
1770
+ getBlogTagWithPostCount,
1771
+ getBlogTagsWithPostCounts,
1772
+ getFinalsRounds,
1773
+ getFinalsStandings,
1774
+ getLatestOpprRankingHistory,
1775
+ getLocationWithTournaments,
780
1776
  getMajorTournaments,
781
- getPlayerResults,
1777
+ getMatchEntries,
1778
+ getMatchWithEntries,
1779
+ getMergedStandings,
1780
+ getOpprRankingHistory,
1781
+ getOpprRankingHistoryByDateRange,
1782
+ getOrCreateOpprPlayerRanking,
1783
+ getPlayerEntries,
1784
+ getPlayerEntryStats,
1785
+ getPlayerStandings,
782
1786
  getPlayerStats,
783
1787
  getPlayerTopFinishes,
1788
+ getPlayerTournamentEntries,
1789
+ getPlayerTournamentMatches,
784
1790
  getPlayerWithResults,
785
- getRatedPlayers,
1791
+ getQualifyingRounds,
1792
+ getQualifyingStandings,
1793
+ getRatedOpprPlayers,
786
1794
  getRecentTournaments,
787
- getTopPlayersByRanking,
788
- getTopPlayersByRating,
789
- getTournamentResults,
1795
+ getRoundMatches,
1796
+ getRoundWithMatches,
1797
+ getTopPlayersByOpprRanking,
1798
+ getTopPlayersByOpprRating,
1799
+ getTournamentMatches,
1800
+ getTournamentRounds,
1801
+ getTournamentStandings,
790
1802
  getTournamentStats,
1803
+ getTournamentWithMatches,
791
1804
  getTournamentWithResults,
792
1805
  getTournamentsByBoosterType,
793
1806
  getTournamentsByDateRange,
1807
+ getUserApiKeys,
794
1808
  getUserByEmailWithPlayer,
795
1809
  getUserWithPlayer,
796
1810
  isValidPlayerNumber,
797
1811
  linkPlayerToUser,
798
1812
  prisma,
799
1813
  recalculateTimeDecay,
1814
+ searchBlogPosts,
1815
+ searchBlogTags,
1816
+ searchLocations,
800
1817
  searchPlayers,
801
1818
  searchTournaments,
802
1819
  testConnection,
1820
+ updateApiKeyLastUsed,
1821
+ updateBlogPost,
1822
+ updateBlogTag,
1823
+ updateEntry,
1824
+ updateLocation,
1825
+ updateMatch,
1826
+ updateOpprPlayerRanking,
1827
+ updateOpprRatingAfterTournament,
803
1828
  updatePlayer,
804
- updatePlayerRating,
805
- updateResult,
806
- updateResultPoints,
1829
+ updateRound,
1830
+ updateStanding,
1831
+ updateStandingPoints,
807
1832
  updateTournament,
808
1833
  updateUser,
809
- updateUserRefreshToken
1834
+ updateUserRefreshToken,
1835
+ updateWorldRankings
810
1836
  });