@opprs/db-prisma 2.2.1-canary.b943669 → 2.2.1-canary.c3d513e
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 +542 -66
- package/dist/index.d.cts +408 -62
- package/dist/index.d.ts +408 -62
- package/dist/index.js +493 -61
- package/package.json +2 -2
- package/prisma/migrations/20260105000000_add_oppr_ranking_models/migration.sql +108 -0
- package/prisma/migrations/20260105010000_add_tournament_external_url/migration.sql +2 -0
- package/prisma/schema.prisma +163 -13
- package/prisma/seed.ts +22 -20
package/dist/index.cjs
CHANGED
|
@@ -20,15 +20,26 @@ 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,
|
|
24
28
|
countEntries: () => countEntries,
|
|
25
29
|
countLocations: () => countLocations,
|
|
26
30
|
countMatches: () => countMatches,
|
|
31
|
+
countOpprPlayerRankings: () => countOpprPlayerRankings,
|
|
32
|
+
countOpprRankingHistory: () => countOpprRankingHistory,
|
|
27
33
|
countPlayers: () => countPlayers,
|
|
34
|
+
countPublishedBlogPosts: () => countPublishedBlogPosts,
|
|
28
35
|
countRounds: () => countRounds,
|
|
29
36
|
countStandings: () => countStandings,
|
|
30
37
|
countTournaments: () => countTournaments,
|
|
38
|
+
countUserApiKeys: () => countUserApiKeys,
|
|
31
39
|
countUsers: () => countUsers,
|
|
40
|
+
createApiKey: () => createApiKey,
|
|
41
|
+
createBlogPost: () => createBlogPost,
|
|
42
|
+
createBlogTag: () => createBlogTag,
|
|
32
43
|
createEntry: () => createEntry,
|
|
33
44
|
createLocation: () => createLocation,
|
|
34
45
|
createManyEntries: () => createManyEntries,
|
|
@@ -36,18 +47,24 @@ __export(index_exports, {
|
|
|
36
47
|
createManyRounds: () => createManyRounds,
|
|
37
48
|
createManyStandings: () => createManyStandings,
|
|
38
49
|
createMatch: () => createMatch,
|
|
50
|
+
createOpprPlayerRanking: () => createOpprPlayerRanking,
|
|
51
|
+
createOpprRankingHistory: () => createOpprRankingHistory,
|
|
39
52
|
createPlayer: () => createPlayer,
|
|
40
53
|
createRound: () => createRound,
|
|
41
54
|
createStanding: () => createStanding,
|
|
42
55
|
createTournament: () => createTournament,
|
|
43
56
|
createUser: () => createUser,
|
|
44
57
|
createUserWithPlayer: () => createUserWithPlayer,
|
|
58
|
+
deleteApiKey: () => deleteApiKey,
|
|
59
|
+
deleteBlogPost: () => deleteBlogPost,
|
|
60
|
+
deleteBlogTag: () => deleteBlogTag,
|
|
45
61
|
deleteEntriesByMatch: () => deleteEntriesByMatch,
|
|
46
62
|
deleteEntry: () => deleteEntry,
|
|
47
63
|
deleteLocation: () => deleteLocation,
|
|
48
64
|
deleteMatch: () => deleteMatch,
|
|
49
65
|
deleteMatchesByRound: () => deleteMatchesByRound,
|
|
50
66
|
deleteMatchesByTournament: () => deleteMatchesByTournament,
|
|
67
|
+
deleteOpprPlayerRanking: () => deleteOpprPlayerRanking,
|
|
51
68
|
deletePlayer: () => deletePlayer,
|
|
52
69
|
deleteRound: () => deleteRound,
|
|
53
70
|
deleteRoundsByTournament: () => deleteRoundsByTournament,
|
|
@@ -55,7 +72,16 @@ __export(index_exports, {
|
|
|
55
72
|
deleteStandingsByTournament: () => deleteStandingsByTournament,
|
|
56
73
|
deleteTournament: () => deleteTournament,
|
|
57
74
|
deleteUser: () => deleteUser,
|
|
75
|
+
deleteUserApiKey: () => deleteUserApiKey,
|
|
58
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,
|
|
59
85
|
findEntries: () => findEntries,
|
|
60
86
|
findEntryById: () => findEntryById,
|
|
61
87
|
findEntryByMatchAndPlayer: () => findEntryByMatchAndPlayer,
|
|
@@ -64,11 +90,15 @@ __export(index_exports, {
|
|
|
64
90
|
findLocations: () => findLocations,
|
|
65
91
|
findMatchById: () => findMatchById,
|
|
66
92
|
findMatches: () => findMatches,
|
|
93
|
+
findOpprPlayerRankingById: () => findOpprPlayerRankingById,
|
|
94
|
+
findOpprPlayerRankingByPlayerId: () => findOpprPlayerRankingByPlayerId,
|
|
95
|
+
findOpprPlayerRankings: () => findOpprPlayerRankings,
|
|
67
96
|
findPlayerByExternalId: () => findPlayerByExternalId,
|
|
68
97
|
findPlayerById: () => findPlayerById,
|
|
69
98
|
findPlayerByPlayerNumber: () => findPlayerByPlayerNumber,
|
|
70
99
|
findPlayerByUserEmail: () => findPlayerByUserEmail,
|
|
71
100
|
findPlayers: () => findPlayers,
|
|
101
|
+
findPublishedBlogPosts: () => findPublishedBlogPosts,
|
|
72
102
|
findRoundById: () => findRoundById,
|
|
73
103
|
findRoundByTournamentAndNumber: () => findRoundByTournamentAndNumber,
|
|
74
104
|
findRounds: () => findRounds,
|
|
@@ -82,13 +112,19 @@ __export(index_exports, {
|
|
|
82
112
|
findUserById: () => findUserById,
|
|
83
113
|
findUsers: () => findUsers,
|
|
84
114
|
generateUniquePlayerNumber: () => generateUniquePlayerNumber,
|
|
115
|
+
getBlogTagWithPostCount: () => getBlogTagWithPostCount,
|
|
116
|
+
getBlogTagsWithPostCounts: () => getBlogTagsWithPostCounts,
|
|
85
117
|
getFinalsRounds: () => getFinalsRounds,
|
|
86
118
|
getFinalsStandings: () => getFinalsStandings,
|
|
119
|
+
getLatestOpprRankingHistory: () => getLatestOpprRankingHistory,
|
|
87
120
|
getLocationWithTournaments: () => getLocationWithTournaments,
|
|
88
121
|
getMajorTournaments: () => getMajorTournaments,
|
|
89
122
|
getMatchEntries: () => getMatchEntries,
|
|
90
123
|
getMatchWithEntries: () => getMatchWithEntries,
|
|
91
124
|
getMergedStandings: () => getMergedStandings,
|
|
125
|
+
getOpprRankingHistory: () => getOpprRankingHistory,
|
|
126
|
+
getOpprRankingHistoryByDateRange: () => getOpprRankingHistoryByDateRange,
|
|
127
|
+
getOrCreateOpprPlayerRanking: () => getOrCreateOpprPlayerRanking,
|
|
92
128
|
getPlayerEntries: () => getPlayerEntries,
|
|
93
129
|
getPlayerEntryStats: () => getPlayerEntryStats,
|
|
94
130
|
getPlayerStandings: () => getPlayerStandings,
|
|
@@ -99,12 +135,12 @@ __export(index_exports, {
|
|
|
99
135
|
getPlayerWithResults: () => getPlayerWithResults,
|
|
100
136
|
getQualifyingRounds: () => getQualifyingRounds,
|
|
101
137
|
getQualifyingStandings: () => getQualifyingStandings,
|
|
102
|
-
|
|
138
|
+
getRatedOpprPlayers: () => getRatedOpprPlayers,
|
|
103
139
|
getRecentTournaments: () => getRecentTournaments,
|
|
104
140
|
getRoundMatches: () => getRoundMatches,
|
|
105
141
|
getRoundWithMatches: () => getRoundWithMatches,
|
|
106
|
-
|
|
107
|
-
|
|
142
|
+
getTopPlayersByOpprRanking: () => getTopPlayersByOpprRanking,
|
|
143
|
+
getTopPlayersByOpprRating: () => getTopPlayersByOpprRating,
|
|
108
144
|
getTournamentMatches: () => getTournamentMatches,
|
|
109
145
|
getTournamentRounds: () => getTournamentRounds,
|
|
110
146
|
getTournamentStandings: () => getTournamentStandings,
|
|
@@ -113,27 +149,35 @@ __export(index_exports, {
|
|
|
113
149
|
getTournamentWithResults: () => getTournamentWithResults,
|
|
114
150
|
getTournamentsByBoosterType: () => getTournamentsByBoosterType,
|
|
115
151
|
getTournamentsByDateRange: () => getTournamentsByDateRange,
|
|
152
|
+
getUserApiKeys: () => getUserApiKeys,
|
|
116
153
|
getUserByEmailWithPlayer: () => getUserByEmailWithPlayer,
|
|
117
154
|
getUserWithPlayer: () => getUserWithPlayer,
|
|
118
155
|
isValidPlayerNumber: () => isValidPlayerNumber,
|
|
119
156
|
linkPlayerToUser: () => linkPlayerToUser,
|
|
120
157
|
prisma: () => prisma,
|
|
121
158
|
recalculateTimeDecay: () => recalculateTimeDecay,
|
|
159
|
+
searchBlogPosts: () => searchBlogPosts,
|
|
160
|
+
searchBlogTags: () => searchBlogTags,
|
|
122
161
|
searchLocations: () => searchLocations,
|
|
123
162
|
searchPlayers: () => searchPlayers,
|
|
124
163
|
searchTournaments: () => searchTournaments,
|
|
125
164
|
testConnection: () => testConnection,
|
|
165
|
+
updateApiKeyLastUsed: () => updateApiKeyLastUsed,
|
|
166
|
+
updateBlogPost: () => updateBlogPost,
|
|
167
|
+
updateBlogTag: () => updateBlogTag,
|
|
126
168
|
updateEntry: () => updateEntry,
|
|
127
169
|
updateLocation: () => updateLocation,
|
|
128
170
|
updateMatch: () => updateMatch,
|
|
171
|
+
updateOpprPlayerRanking: () => updateOpprPlayerRanking,
|
|
172
|
+
updateOpprRatingAfterTournament: () => updateOpprRatingAfterTournament,
|
|
129
173
|
updatePlayer: () => updatePlayer,
|
|
130
|
-
updatePlayerRating: () => updatePlayerRating,
|
|
131
174
|
updateRound: () => updateRound,
|
|
132
175
|
updateStanding: () => updateStanding,
|
|
133
176
|
updateStandingPoints: () => updateStandingPoints,
|
|
134
177
|
updateTournament: () => updateTournament,
|
|
135
178
|
updateUser: () => updateUser,
|
|
136
|
-
updateUserRefreshToken: () => updateUserRefreshToken
|
|
179
|
+
updateUserRefreshToken: () => updateUserRefreshToken,
|
|
180
|
+
updateWorldRankings: () => updateWorldRankings
|
|
137
181
|
});
|
|
138
182
|
module.exports = __toCommonJS(index_exports);
|
|
139
183
|
|
|
@@ -232,48 +276,12 @@ async function findPlayers(options = {}) {
|
|
|
232
276
|
include: options.include
|
|
233
277
|
});
|
|
234
278
|
}
|
|
235
|
-
async function getRatedPlayers(options = {}) {
|
|
236
|
-
return findPlayers({
|
|
237
|
-
...options,
|
|
238
|
-
where: { isRated: true }
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
async function getTopPlayersByRating(limit = 50) {
|
|
242
|
-
return findPlayers({
|
|
243
|
-
take: limit,
|
|
244
|
-
orderBy: { rating: "desc" },
|
|
245
|
-
where: { isRated: true }
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
async function getTopPlayersByRanking(limit = 50) {
|
|
249
|
-
return findPlayers({
|
|
250
|
-
take: limit,
|
|
251
|
-
orderBy: { ranking: "asc" },
|
|
252
|
-
where: {
|
|
253
|
-
isRated: true,
|
|
254
|
-
ranking: { not: null }
|
|
255
|
-
}
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
279
|
async function updatePlayer(id, data) {
|
|
259
280
|
return prisma.player.update({
|
|
260
281
|
where: { id },
|
|
261
282
|
data
|
|
262
283
|
});
|
|
263
284
|
}
|
|
264
|
-
async function updatePlayerRating(id, rating, ratingDeviation, eventCount) {
|
|
265
|
-
const updateData = {
|
|
266
|
-
rating,
|
|
267
|
-
ratingDeviation,
|
|
268
|
-
lastRatingUpdate: /* @__PURE__ */ new Date(),
|
|
269
|
-
lastEventDate: /* @__PURE__ */ new Date()
|
|
270
|
-
};
|
|
271
|
-
if (eventCount !== void 0) {
|
|
272
|
-
updateData.eventCount = eventCount;
|
|
273
|
-
updateData.isRated = eventCount >= 5;
|
|
274
|
-
}
|
|
275
|
-
return updatePlayer(id, updateData);
|
|
276
|
-
}
|
|
277
285
|
async function deletePlayer(id) {
|
|
278
286
|
return prisma.player.delete({
|
|
279
287
|
where: { id }
|
|
@@ -315,6 +323,212 @@ async function searchPlayers(query, limit = 20) {
|
|
|
315
323
|
});
|
|
316
324
|
}
|
|
317
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
|
+
|
|
318
532
|
// src/tournaments.ts
|
|
319
533
|
async function createTournament(data) {
|
|
320
534
|
return prisma.tournament.create({
|
|
@@ -1029,10 +1243,6 @@ async function createUserWithPlayer(userData, playerData) {
|
|
|
1029
1243
|
id: true,
|
|
1030
1244
|
playerNumber: true,
|
|
1031
1245
|
name: true,
|
|
1032
|
-
rating: true,
|
|
1033
|
-
ratingDeviation: true,
|
|
1034
|
-
ranking: true,
|
|
1035
|
-
isRated: true,
|
|
1036
1246
|
eventCount: true
|
|
1037
1247
|
}
|
|
1038
1248
|
}
|
|
@@ -1062,10 +1272,6 @@ async function getUserWithPlayer(id) {
|
|
|
1062
1272
|
id: true,
|
|
1063
1273
|
playerNumber: true,
|
|
1064
1274
|
name: true,
|
|
1065
|
-
rating: true,
|
|
1066
|
-
ratingDeviation: true,
|
|
1067
|
-
ranking: true,
|
|
1068
|
-
isRated: true,
|
|
1069
1275
|
eventCount: true
|
|
1070
1276
|
}
|
|
1071
1277
|
}
|
|
@@ -1085,10 +1291,6 @@ async function getUserByEmailWithPlayer(email) {
|
|
|
1085
1291
|
id: true,
|
|
1086
1292
|
playerNumber: true,
|
|
1087
1293
|
name: true,
|
|
1088
|
-
rating: true,
|
|
1089
|
-
ratingDeviation: true,
|
|
1090
|
-
ranking: true,
|
|
1091
|
-
isRated: true,
|
|
1092
1294
|
eventCount: true
|
|
1093
1295
|
}
|
|
1094
1296
|
}
|
|
@@ -1131,10 +1333,6 @@ async function findUsers(params) {
|
|
|
1131
1333
|
id: true,
|
|
1132
1334
|
playerNumber: true,
|
|
1133
1335
|
name: true,
|
|
1134
|
-
rating: true,
|
|
1135
|
-
ratingDeviation: true,
|
|
1136
|
-
ranking: true,
|
|
1137
|
-
isRated: true,
|
|
1138
1336
|
eventCount: true
|
|
1139
1337
|
}
|
|
1140
1338
|
}
|
|
@@ -1163,10 +1361,6 @@ async function linkPlayerToUser(userId, playerId) {
|
|
|
1163
1361
|
id: true,
|
|
1164
1362
|
playerNumber: true,
|
|
1165
1363
|
name: true,
|
|
1166
|
-
rating: true,
|
|
1167
|
-
ratingDeviation: true,
|
|
1168
|
-
ranking: true,
|
|
1169
|
-
isRated: true,
|
|
1170
1364
|
eventCount: true
|
|
1171
1365
|
}
|
|
1172
1366
|
}
|
|
@@ -1176,6 +1370,65 @@ async function linkPlayerToUser(userId, playerId) {
|
|
|
1176
1370
|
});
|
|
1177
1371
|
}
|
|
1178
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
|
+
|
|
1179
1432
|
// src/locations.ts
|
|
1180
1433
|
async function createLocation(data) {
|
|
1181
1434
|
return prisma.location.create({
|
|
@@ -1241,17 +1494,207 @@ async function getLocationWithTournaments(id) {
|
|
|
1241
1494
|
}
|
|
1242
1495
|
});
|
|
1243
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
|
+
}
|
|
1244
1676
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1245
1677
|
0 && (module.exports = {
|
|
1678
|
+
MAX_API_KEYS_PER_USER,
|
|
1679
|
+
applyRDDecayForInactivePlayers,
|
|
1246
1680
|
connect,
|
|
1681
|
+
countBlogPosts,
|
|
1682
|
+
countBlogTags,
|
|
1247
1683
|
countEntries,
|
|
1248
1684
|
countLocations,
|
|
1249
1685
|
countMatches,
|
|
1686
|
+
countOpprPlayerRankings,
|
|
1687
|
+
countOpprRankingHistory,
|
|
1250
1688
|
countPlayers,
|
|
1689
|
+
countPublishedBlogPosts,
|
|
1251
1690
|
countRounds,
|
|
1252
1691
|
countStandings,
|
|
1253
1692
|
countTournaments,
|
|
1693
|
+
countUserApiKeys,
|
|
1254
1694
|
countUsers,
|
|
1695
|
+
createApiKey,
|
|
1696
|
+
createBlogPost,
|
|
1697
|
+
createBlogTag,
|
|
1255
1698
|
createEntry,
|
|
1256
1699
|
createLocation,
|
|
1257
1700
|
createManyEntries,
|
|
@@ -1259,18 +1702,24 @@ async function getLocationWithTournaments(id) {
|
|
|
1259
1702
|
createManyRounds,
|
|
1260
1703
|
createManyStandings,
|
|
1261
1704
|
createMatch,
|
|
1705
|
+
createOpprPlayerRanking,
|
|
1706
|
+
createOpprRankingHistory,
|
|
1262
1707
|
createPlayer,
|
|
1263
1708
|
createRound,
|
|
1264
1709
|
createStanding,
|
|
1265
1710
|
createTournament,
|
|
1266
1711
|
createUser,
|
|
1267
1712
|
createUserWithPlayer,
|
|
1713
|
+
deleteApiKey,
|
|
1714
|
+
deleteBlogPost,
|
|
1715
|
+
deleteBlogTag,
|
|
1268
1716
|
deleteEntriesByMatch,
|
|
1269
1717
|
deleteEntry,
|
|
1270
1718
|
deleteLocation,
|
|
1271
1719
|
deleteMatch,
|
|
1272
1720
|
deleteMatchesByRound,
|
|
1273
1721
|
deleteMatchesByTournament,
|
|
1722
|
+
deleteOpprPlayerRanking,
|
|
1274
1723
|
deletePlayer,
|
|
1275
1724
|
deleteRound,
|
|
1276
1725
|
deleteRoundsByTournament,
|
|
@@ -1278,7 +1727,16 @@ async function getLocationWithTournaments(id) {
|
|
|
1278
1727
|
deleteStandingsByTournament,
|
|
1279
1728
|
deleteTournament,
|
|
1280
1729
|
deleteUser,
|
|
1730
|
+
deleteUserApiKey,
|
|
1281
1731
|
disconnect,
|
|
1732
|
+
findApiKeyById,
|
|
1733
|
+
findApiKeysByPrefix,
|
|
1734
|
+
findBlogPostById,
|
|
1735
|
+
findBlogPostBySlug,
|
|
1736
|
+
findBlogPosts,
|
|
1737
|
+
findBlogTagById,
|
|
1738
|
+
findBlogTagBySlug,
|
|
1739
|
+
findBlogTags,
|
|
1282
1740
|
findEntries,
|
|
1283
1741
|
findEntryById,
|
|
1284
1742
|
findEntryByMatchAndPlayer,
|
|
@@ -1287,11 +1745,15 @@ async function getLocationWithTournaments(id) {
|
|
|
1287
1745
|
findLocations,
|
|
1288
1746
|
findMatchById,
|
|
1289
1747
|
findMatches,
|
|
1748
|
+
findOpprPlayerRankingById,
|
|
1749
|
+
findOpprPlayerRankingByPlayerId,
|
|
1750
|
+
findOpprPlayerRankings,
|
|
1290
1751
|
findPlayerByExternalId,
|
|
1291
1752
|
findPlayerById,
|
|
1292
1753
|
findPlayerByPlayerNumber,
|
|
1293
1754
|
findPlayerByUserEmail,
|
|
1294
1755
|
findPlayers,
|
|
1756
|
+
findPublishedBlogPosts,
|
|
1295
1757
|
findRoundById,
|
|
1296
1758
|
findRoundByTournamentAndNumber,
|
|
1297
1759
|
findRounds,
|
|
@@ -1305,13 +1767,19 @@ async function getLocationWithTournaments(id) {
|
|
|
1305
1767
|
findUserById,
|
|
1306
1768
|
findUsers,
|
|
1307
1769
|
generateUniquePlayerNumber,
|
|
1770
|
+
getBlogTagWithPostCount,
|
|
1771
|
+
getBlogTagsWithPostCounts,
|
|
1308
1772
|
getFinalsRounds,
|
|
1309
1773
|
getFinalsStandings,
|
|
1774
|
+
getLatestOpprRankingHistory,
|
|
1310
1775
|
getLocationWithTournaments,
|
|
1311
1776
|
getMajorTournaments,
|
|
1312
1777
|
getMatchEntries,
|
|
1313
1778
|
getMatchWithEntries,
|
|
1314
1779
|
getMergedStandings,
|
|
1780
|
+
getOpprRankingHistory,
|
|
1781
|
+
getOpprRankingHistoryByDateRange,
|
|
1782
|
+
getOrCreateOpprPlayerRanking,
|
|
1315
1783
|
getPlayerEntries,
|
|
1316
1784
|
getPlayerEntryStats,
|
|
1317
1785
|
getPlayerStandings,
|
|
@@ -1322,12 +1790,12 @@ async function getLocationWithTournaments(id) {
|
|
|
1322
1790
|
getPlayerWithResults,
|
|
1323
1791
|
getQualifyingRounds,
|
|
1324
1792
|
getQualifyingStandings,
|
|
1325
|
-
|
|
1793
|
+
getRatedOpprPlayers,
|
|
1326
1794
|
getRecentTournaments,
|
|
1327
1795
|
getRoundMatches,
|
|
1328
1796
|
getRoundWithMatches,
|
|
1329
|
-
|
|
1330
|
-
|
|
1797
|
+
getTopPlayersByOpprRanking,
|
|
1798
|
+
getTopPlayersByOpprRating,
|
|
1331
1799
|
getTournamentMatches,
|
|
1332
1800
|
getTournamentRounds,
|
|
1333
1801
|
getTournamentStandings,
|
|
@@ -1336,25 +1804,33 @@ async function getLocationWithTournaments(id) {
|
|
|
1336
1804
|
getTournamentWithResults,
|
|
1337
1805
|
getTournamentsByBoosterType,
|
|
1338
1806
|
getTournamentsByDateRange,
|
|
1807
|
+
getUserApiKeys,
|
|
1339
1808
|
getUserByEmailWithPlayer,
|
|
1340
1809
|
getUserWithPlayer,
|
|
1341
1810
|
isValidPlayerNumber,
|
|
1342
1811
|
linkPlayerToUser,
|
|
1343
1812
|
prisma,
|
|
1344
1813
|
recalculateTimeDecay,
|
|
1814
|
+
searchBlogPosts,
|
|
1815
|
+
searchBlogTags,
|
|
1345
1816
|
searchLocations,
|
|
1346
1817
|
searchPlayers,
|
|
1347
1818
|
searchTournaments,
|
|
1348
1819
|
testConnection,
|
|
1820
|
+
updateApiKeyLastUsed,
|
|
1821
|
+
updateBlogPost,
|
|
1822
|
+
updateBlogTag,
|
|
1349
1823
|
updateEntry,
|
|
1350
1824
|
updateLocation,
|
|
1351
1825
|
updateMatch,
|
|
1826
|
+
updateOpprPlayerRanking,
|
|
1827
|
+
updateOpprRatingAfterTournament,
|
|
1352
1828
|
updatePlayer,
|
|
1353
|
-
updatePlayerRating,
|
|
1354
1829
|
updateRound,
|
|
1355
1830
|
updateStanding,
|
|
1356
1831
|
updateStandingPoints,
|
|
1357
1832
|
updateTournament,
|
|
1358
1833
|
updateUser,
|
|
1359
|
-
updateUserRefreshToken
|
|
1834
|
+
updateUserRefreshToken,
|
|
1835
|
+
updateWorldRankings
|
|
1360
1836
|
});
|