@opprs/db-prisma 2.1.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -3
- package/prisma/seed.ts +166 -109
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opprs/db-prisma",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "Database backend for OPPR (Open Pinball Player Ranking System) using Prisma and PostgreSQL",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"oppr",
|
|
@@ -40,7 +40,9 @@
|
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@testcontainers/postgresql": "^11.11.0",
|
|
43
|
+
"@types/bcrypt": "^6.0.0",
|
|
43
44
|
"@types/node": "^22.10.5",
|
|
45
|
+
"bcrypt": "^6.0.0",
|
|
44
46
|
"@typescript-eslint/eslint-plugin": "^8.19.1",
|
|
45
47
|
"@typescript-eslint/parser": "^8.19.1",
|
|
46
48
|
"@vitest/coverage-v8": "^4.0.16",
|
|
@@ -54,10 +56,10 @@
|
|
|
54
56
|
"vitest": "^4.0.16"
|
|
55
57
|
},
|
|
56
58
|
"peerDependencies": {
|
|
57
|
-
"@opprs/core": "^
|
|
59
|
+
"@opprs/core": "^2.2.1"
|
|
58
60
|
},
|
|
59
61
|
"engines": {
|
|
60
|
-
"node": ">=
|
|
62
|
+
"node": ">=20.9.0"
|
|
61
63
|
},
|
|
62
64
|
"prisma": {
|
|
63
65
|
"seed": "tsx prisma/seed.ts"
|
package/prisma/seed.ts
CHANGED
|
@@ -1,182 +1,238 @@
|
|
|
1
1
|
import { PrismaClient, EventBoosterType } from '@prisma/client';
|
|
2
|
+
import bcrypt from 'bcrypt';
|
|
2
3
|
|
|
3
4
|
const prisma = new PrismaClient();
|
|
4
5
|
|
|
6
|
+
const BCRYPT_SALT_ROUNDS = 12;
|
|
7
|
+
|
|
5
8
|
async function main() {
|
|
6
9
|
console.log('🌱 Seeding database...');
|
|
7
10
|
|
|
8
|
-
// Create sample players
|
|
11
|
+
// Create sample players (using upsert for idempotency)
|
|
9
12
|
console.log('Creating players...');
|
|
10
|
-
const
|
|
11
|
-
|
|
13
|
+
const playerData = [
|
|
14
|
+
{
|
|
12
15
|
externalId: 'player-1',
|
|
13
16
|
name: 'Alice Champion',
|
|
14
|
-
email: 'alice@example.com',
|
|
15
17
|
rating: 1850,
|
|
16
18
|
ratingDeviation: 50,
|
|
17
19
|
ranking: 5,
|
|
18
20
|
isRated: true,
|
|
19
21
|
eventCount: 25,
|
|
20
22
|
},
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const player2 = await prisma.player.create({
|
|
24
|
-
data: {
|
|
23
|
+
{
|
|
25
24
|
externalId: 'player-2',
|
|
26
25
|
name: 'Bob Wizard',
|
|
27
|
-
email: 'bob@example.com',
|
|
28
26
|
rating: 1750,
|
|
29
27
|
ratingDeviation: 60,
|
|
30
28
|
ranking: 12,
|
|
31
29
|
isRated: true,
|
|
32
30
|
eventCount: 18,
|
|
33
31
|
},
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const player3 = await prisma.player.create({
|
|
37
|
-
data: {
|
|
32
|
+
{
|
|
38
33
|
externalId: 'player-3',
|
|
39
34
|
name: 'Charlie Flipper',
|
|
40
|
-
email: 'charlie@example.com',
|
|
41
35
|
rating: 1650,
|
|
42
36
|
ratingDeviation: 75,
|
|
43
37
|
ranking: 28,
|
|
44
38
|
isRated: true,
|
|
45
39
|
eventCount: 12,
|
|
46
40
|
},
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const player4 = await prisma.player.create({
|
|
50
|
-
data: {
|
|
41
|
+
{
|
|
51
42
|
externalId: 'player-4',
|
|
52
43
|
name: 'Diana Tilt',
|
|
53
|
-
email: 'diana@example.com',
|
|
54
44
|
rating: 1550,
|
|
55
45
|
ratingDeviation: 100,
|
|
56
46
|
ranking: 45,
|
|
57
47
|
isRated: true,
|
|
58
48
|
eventCount: 8,
|
|
59
49
|
},
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const player5 = await prisma.player.create({
|
|
63
|
-
data: {
|
|
50
|
+
{
|
|
64
51
|
externalId: 'player-5',
|
|
65
52
|
name: 'Eve Plunger',
|
|
66
|
-
email: 'eve@example.com',
|
|
67
53
|
rating: 1300,
|
|
68
54
|
ratingDeviation: 150,
|
|
69
55
|
ranking: null,
|
|
70
56
|
isRated: false,
|
|
71
57
|
eventCount: 3,
|
|
72
58
|
},
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
const player1 = await prisma.player.upsert({
|
|
62
|
+
where: { externalId: 'player-1' },
|
|
63
|
+
update: playerData[0],
|
|
64
|
+
create: playerData[0],
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const player2 = await prisma.player.upsert({
|
|
68
|
+
where: { externalId: 'player-2' },
|
|
69
|
+
update: playerData[1],
|
|
70
|
+
create: playerData[1],
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const player3 = await prisma.player.upsert({
|
|
74
|
+
where: { externalId: 'player-3' },
|
|
75
|
+
update: playerData[2],
|
|
76
|
+
create: playerData[2],
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const player4 = await prisma.player.upsert({
|
|
80
|
+
where: { externalId: 'player-4' },
|
|
81
|
+
update: playerData[3],
|
|
82
|
+
create: playerData[3],
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const player5 = await prisma.player.upsert({
|
|
86
|
+
where: { externalId: 'player-5' },
|
|
87
|
+
update: playerData[4],
|
|
88
|
+
create: playerData[4],
|
|
73
89
|
});
|
|
74
90
|
|
|
75
91
|
console.log(`✓ Created ${await prisma.player.count()} players`);
|
|
76
92
|
|
|
77
|
-
// Create
|
|
93
|
+
// Create test user for e2e tests (linked to Alice Champion)
|
|
94
|
+
console.log('Creating test user...');
|
|
95
|
+
const testPassword = 'TestPassword123!';
|
|
96
|
+
const passwordHash = await bcrypt.hash(testPassword, BCRYPT_SALT_ROUNDS);
|
|
97
|
+
|
|
98
|
+
await prisma.user.upsert({
|
|
99
|
+
where: { email: 'e2e-test@example.com' },
|
|
100
|
+
update: {
|
|
101
|
+
passwordHash,
|
|
102
|
+
role: 'USER',
|
|
103
|
+
playerId: player1.id,
|
|
104
|
+
},
|
|
105
|
+
create: {
|
|
106
|
+
email: 'e2e-test@example.com',
|
|
107
|
+
passwordHash,
|
|
108
|
+
role: 'USER',
|
|
109
|
+
playerId: player1.id,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
console.log(`✓ Created test user (e2e-test@example.com / ${testPassword})`);
|
|
114
|
+
|
|
115
|
+
// Create sample tournaments (using upsert for idempotency)
|
|
78
116
|
console.log('Creating tournaments...');
|
|
79
117
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
meaningfulGames: 12,
|
|
93
|
-
fourPlayerGroups: true,
|
|
94
|
-
},
|
|
95
|
-
finals: {
|
|
96
|
-
formatType: 'match-play',
|
|
97
|
-
meaningfulGames: 20,
|
|
98
|
-
fourPlayerGroups: true,
|
|
99
|
-
finalistCount: 16,
|
|
100
|
-
},
|
|
101
|
-
ballCountAdjustment: 1.0,
|
|
118
|
+
const tournament1Data = {
|
|
119
|
+
externalId: 'tournament-1',
|
|
120
|
+
name: 'World Pinball Championship 2024',
|
|
121
|
+
location: 'Las Vegas, NV',
|
|
122
|
+
date: new Date('2024-03-15'),
|
|
123
|
+
eventBooster: EventBoosterType.MAJOR,
|
|
124
|
+
allowsOptOut: false,
|
|
125
|
+
tgpConfig: {
|
|
126
|
+
qualifying: {
|
|
127
|
+
type: 'limited',
|
|
128
|
+
meaningfulGames: 12,
|
|
129
|
+
fourPlayerGroups: true,
|
|
102
130
|
},
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
131
|
+
finals: {
|
|
132
|
+
formatType: 'match-play',
|
|
133
|
+
meaningfulGames: 20,
|
|
134
|
+
fourPlayerGroups: true,
|
|
135
|
+
finalistCount: 16,
|
|
136
|
+
},
|
|
137
|
+
ballCountAdjustment: 1.0,
|
|
110
138
|
},
|
|
139
|
+
baseValue: 32.0,
|
|
140
|
+
tvaRating: 25.0,
|
|
141
|
+
tvaRanking: 50.0,
|
|
142
|
+
totalTVA: 75.0,
|
|
143
|
+
tgp: 1.92,
|
|
144
|
+
eventBoosterMultiplier: 2.0,
|
|
145
|
+
firstPlaceValue: 411.84,
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const tournament1 = await prisma.tournament.upsert({
|
|
149
|
+
where: { externalId: 'tournament-1' },
|
|
150
|
+
update: tournament1Data,
|
|
151
|
+
create: tournament1Data,
|
|
111
152
|
});
|
|
112
153
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
fourPlayerGroups: false,
|
|
131
|
-
finalistCount: 8,
|
|
132
|
-
},
|
|
154
|
+
const tournament2Data = {
|
|
155
|
+
externalId: 'tournament-2',
|
|
156
|
+
name: 'Spring Classics 2024',
|
|
157
|
+
location: 'Portland, OR',
|
|
158
|
+
date: new Date('2024-04-20'),
|
|
159
|
+
eventBooster: EventBoosterType.CERTIFIED,
|
|
160
|
+
allowsOptOut: true,
|
|
161
|
+
tgpConfig: {
|
|
162
|
+
qualifying: {
|
|
163
|
+
type: 'limited',
|
|
164
|
+
meaningfulGames: 7,
|
|
165
|
+
},
|
|
166
|
+
finals: {
|
|
167
|
+
formatType: 'double-elimination',
|
|
168
|
+
meaningfulGames: 15,
|
|
169
|
+
fourPlayerGroups: false,
|
|
170
|
+
finalistCount: 8,
|
|
133
171
|
},
|
|
134
|
-
baseValue: 28.0,
|
|
135
|
-
tvaRating: 18.5,
|
|
136
|
-
tvaRanking: 32.0,
|
|
137
|
-
totalTVA: 50.5,
|
|
138
|
-
tgp: 0.88,
|
|
139
|
-
eventBoosterMultiplier: 1.25,
|
|
140
|
-
firstPlaceValue: 87.28,
|
|
141
172
|
},
|
|
173
|
+
baseValue: 28.0,
|
|
174
|
+
tvaRating: 18.5,
|
|
175
|
+
tvaRanking: 32.0,
|
|
176
|
+
totalTVA: 50.5,
|
|
177
|
+
tgp: 0.88,
|
|
178
|
+
eventBoosterMultiplier: 1.25,
|
|
179
|
+
firstPlaceValue: 87.28,
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const tournament2 = await prisma.tournament.upsert({
|
|
183
|
+
where: { externalId: 'tournament-2' },
|
|
184
|
+
update: tournament2Data,
|
|
185
|
+
create: tournament2Data,
|
|
142
186
|
});
|
|
143
187
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
fourPlayerGroups: true,
|
|
162
|
-
finalistCount: 8,
|
|
163
|
-
},
|
|
188
|
+
const tournament3Data = {
|
|
189
|
+
externalId: 'tournament-3',
|
|
190
|
+
name: 'Monthly League Finals',
|
|
191
|
+
location: 'Seattle, WA',
|
|
192
|
+
date: new Date('2024-05-10'),
|
|
193
|
+
eventBooster: EventBoosterType.NONE,
|
|
194
|
+
allowsOptOut: false,
|
|
195
|
+
tgpConfig: {
|
|
196
|
+
qualifying: {
|
|
197
|
+
type: 'none',
|
|
198
|
+
meaningfulGames: 0,
|
|
199
|
+
},
|
|
200
|
+
finals: {
|
|
201
|
+
formatType: 'match-play',
|
|
202
|
+
meaningfulGames: 10,
|
|
203
|
+
fourPlayerGroups: true,
|
|
204
|
+
finalistCount: 8,
|
|
164
205
|
},
|
|
165
|
-
baseValue: 15.0,
|
|
166
|
-
tvaRating: 8.5,
|
|
167
|
-
tvaRanking: 12.0,
|
|
168
|
-
totalTVA: 20.5,
|
|
169
|
-
tgp: 0.80,
|
|
170
|
-
eventBoosterMultiplier: 1.0,
|
|
171
|
-
firstPlaceValue: 28.4,
|
|
172
206
|
},
|
|
207
|
+
baseValue: 15.0,
|
|
208
|
+
tvaRating: 8.5,
|
|
209
|
+
tvaRanking: 12.0,
|
|
210
|
+
totalTVA: 20.5,
|
|
211
|
+
tgp: 0.80,
|
|
212
|
+
eventBoosterMultiplier: 1.0,
|
|
213
|
+
firstPlaceValue: 28.4,
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const tournament3 = await prisma.tournament.upsert({
|
|
217
|
+
where: { externalId: 'tournament-3' },
|
|
218
|
+
update: tournament3Data,
|
|
219
|
+
create: tournament3Data,
|
|
173
220
|
});
|
|
174
221
|
|
|
175
222
|
console.log(`✓ Created ${await prisma.tournament.count()} tournaments`);
|
|
176
223
|
|
|
177
|
-
// Create tournament results
|
|
224
|
+
// Create tournament results (delete existing first for idempotency)
|
|
178
225
|
console.log('Creating tournament results...');
|
|
179
226
|
|
|
227
|
+
// Delete existing results for seeded tournaments
|
|
228
|
+
await prisma.tournamentResult.deleteMany({
|
|
229
|
+
where: {
|
|
230
|
+
tournamentId: {
|
|
231
|
+
in: [tournament1.id, tournament2.id, tournament3.id],
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
|
|
180
236
|
// World Championship results
|
|
181
237
|
await prisma.tournamentResult.createMany({
|
|
182
238
|
data: [
|
|
@@ -334,6 +390,7 @@ async function main() {
|
|
|
334
390
|
console.log('');
|
|
335
391
|
console.log('Summary:');
|
|
336
392
|
console.log(` - ${await prisma.player.count()} players`);
|
|
393
|
+
console.log(` - ${await prisma.user.count()} users`);
|
|
337
394
|
console.log(` - ${await prisma.tournament.count()} tournaments`);
|
|
338
395
|
console.log(` - ${await prisma.tournamentResult.count()} tournament results`);
|
|
339
396
|
}
|