@opprs/db-prisma 2.1.0 → 2.2.1-canary.2db0cbb

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +5 -3
  2. package/prisma/seed.ts +186 -109
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opprs/db-prisma",
3
- "version": "2.1.0",
3
+ "version": "2.2.1-canary.2db0cbb",
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": "^1.1.4"
59
+ "@opprs/core": "^2.2.1-canary.2db0cbb"
58
60
  },
59
61
  "engines": {
60
- "node": ">=18.0.0"
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,258 @@
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 player1 = await prisma.player.create({
11
- data: {
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 sample tournaments
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 admin user
116
+ console.log('Creating admin user...');
117
+ const adminPassword = 'AdminPassword123!';
118
+ const adminPasswordHash = await bcrypt.hash(adminPassword, BCRYPT_SALT_ROUNDS);
119
+
120
+ await prisma.user.upsert({
121
+ where: { email: 'admin@example.com' },
122
+ update: {
123
+ passwordHash: adminPasswordHash,
124
+ role: 'ADMIN',
125
+ },
126
+ create: {
127
+ email: 'admin@example.com',
128
+ passwordHash: adminPasswordHash,
129
+ role: 'ADMIN',
130
+ },
131
+ });
132
+
133
+ console.log(`✓ Created admin user (admin@example.com / ${adminPassword})`);
134
+
135
+ // Create sample tournaments (using upsert for idempotency)
78
136
  console.log('Creating tournaments...');
79
137
 
80
- // Major Championship Tournament
81
- const tournament1 = await prisma.tournament.create({
82
- data: {
83
- externalId: 'tournament-1',
84
- name: 'World Pinball Championship 2024',
85
- location: 'Las Vegas, NV',
86
- date: new Date('2024-03-15'),
87
- eventBooster: EventBoosterType.MAJOR,
88
- allowsOptOut: false,
89
- tgpConfig: {
90
- qualifying: {
91
- type: 'limited',
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,
138
+ const tournament1Data = {
139
+ externalId: 'tournament-1',
140
+ name: 'World Pinball Championship 2024',
141
+ location: 'Las Vegas, NV',
142
+ date: new Date('2024-03-15'),
143
+ eventBooster: EventBoosterType.MAJOR,
144
+ allowsOptOut: false,
145
+ tgpConfig: {
146
+ qualifying: {
147
+ type: 'limited',
148
+ meaningfulGames: 12,
149
+ fourPlayerGroups: true,
102
150
  },
103
- baseValue: 32.0,
104
- tvaRating: 25.0,
105
- tvaRanking: 50.0,
106
- totalTVA: 75.0,
107
- tgp: 1.92,
108
- eventBoosterMultiplier: 2.0,
109
- firstPlaceValue: 411.84,
151
+ finals: {
152
+ formatType: 'match-play',
153
+ meaningfulGames: 20,
154
+ fourPlayerGroups: true,
155
+ finalistCount: 16,
156
+ },
157
+ ballCountAdjustment: 1.0,
110
158
  },
159
+ baseValue: 32.0,
160
+ tvaRating: 25.0,
161
+ tvaRanking: 50.0,
162
+ totalTVA: 75.0,
163
+ tgp: 1.92,
164
+ eventBoosterMultiplier: 2.0,
165
+ firstPlaceValue: 411.84,
166
+ };
167
+
168
+ const tournament1 = await prisma.tournament.upsert({
169
+ where: { externalId: 'tournament-1' },
170
+ update: tournament1Data,
171
+ create: tournament1Data,
111
172
  });
112
173
 
113
- // Certified Tournament
114
- const tournament2 = await prisma.tournament.create({
115
- data: {
116
- externalId: 'tournament-2',
117
- name: 'Spring Classics 2024',
118
- location: 'Portland, OR',
119
- date: new Date('2024-04-20'),
120
- eventBooster: EventBoosterType.CERTIFIED,
121
- allowsOptOut: true,
122
- tgpConfig: {
123
- qualifying: {
124
- type: 'limited',
125
- meaningfulGames: 7,
126
- },
127
- finals: {
128
- formatType: 'double-elimination',
129
- meaningfulGames: 15,
130
- fourPlayerGroups: false,
131
- finalistCount: 8,
132
- },
174
+ const tournament2Data = {
175
+ externalId: 'tournament-2',
176
+ name: 'Spring Classics 2024',
177
+ location: 'Portland, OR',
178
+ date: new Date('2024-04-20'),
179
+ eventBooster: EventBoosterType.CERTIFIED,
180
+ allowsOptOut: true,
181
+ tgpConfig: {
182
+ qualifying: {
183
+ type: 'limited',
184
+ meaningfulGames: 7,
185
+ },
186
+ finals: {
187
+ formatType: 'double-elimination',
188
+ meaningfulGames: 15,
189
+ fourPlayerGroups: false,
190
+ finalistCount: 8,
133
191
  },
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
192
  },
193
+ baseValue: 28.0,
194
+ tvaRating: 18.5,
195
+ tvaRanking: 32.0,
196
+ totalTVA: 50.5,
197
+ tgp: 0.88,
198
+ eventBoosterMultiplier: 1.25,
199
+ firstPlaceValue: 87.28,
200
+ };
201
+
202
+ const tournament2 = await prisma.tournament.upsert({
203
+ where: { externalId: 'tournament-2' },
204
+ update: tournament2Data,
205
+ create: tournament2Data,
142
206
  });
143
207
 
144
- // Local Tournament
145
- const tournament3 = await prisma.tournament.create({
146
- data: {
147
- externalId: 'tournament-3',
148
- name: 'Monthly League Finals',
149
- location: 'Seattle, WA',
150
- date: new Date('2024-05-10'),
151
- eventBooster: EventBoosterType.NONE,
152
- allowsOptOut: false,
153
- tgpConfig: {
154
- qualifying: {
155
- type: 'none',
156
- meaningfulGames: 0,
157
- },
158
- finals: {
159
- formatType: 'match-play',
160
- meaningfulGames: 10,
161
- fourPlayerGroups: true,
162
- finalistCount: 8,
163
- },
208
+ const tournament3Data = {
209
+ externalId: 'tournament-3',
210
+ name: 'Monthly League Finals',
211
+ location: 'Seattle, WA',
212
+ date: new Date('2024-05-10'),
213
+ eventBooster: EventBoosterType.NONE,
214
+ allowsOptOut: false,
215
+ tgpConfig: {
216
+ qualifying: {
217
+ type: 'none',
218
+ meaningfulGames: 0,
219
+ },
220
+ finals: {
221
+ formatType: 'match-play',
222
+ meaningfulGames: 10,
223
+ fourPlayerGroups: true,
224
+ finalistCount: 8,
164
225
  },
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
226
  },
227
+ baseValue: 15.0,
228
+ tvaRating: 8.5,
229
+ tvaRanking: 12.0,
230
+ totalTVA: 20.5,
231
+ tgp: 0.80,
232
+ eventBoosterMultiplier: 1.0,
233
+ firstPlaceValue: 28.4,
234
+ };
235
+
236
+ const tournament3 = await prisma.tournament.upsert({
237
+ where: { externalId: 'tournament-3' },
238
+ update: tournament3Data,
239
+ create: tournament3Data,
173
240
  });
174
241
 
175
242
  console.log(`✓ Created ${await prisma.tournament.count()} tournaments`);
176
243
 
177
- // Create tournament results
244
+ // Create tournament results (delete existing first for idempotency)
178
245
  console.log('Creating tournament results...');
179
246
 
247
+ // Delete existing results for seeded tournaments
248
+ await prisma.tournamentResult.deleteMany({
249
+ where: {
250
+ tournamentId: {
251
+ in: [tournament1.id, tournament2.id, tournament3.id],
252
+ },
253
+ },
254
+ });
255
+
180
256
  // World Championship results
181
257
  await prisma.tournamentResult.createMany({
182
258
  data: [
@@ -334,6 +410,7 @@ async function main() {
334
410
  console.log('');
335
411
  console.log('Summary:');
336
412
  console.log(` - ${await prisma.player.count()} players`);
413
+ console.log(` - ${await prisma.user.count()} users`);
337
414
  console.log(` - ${await prisma.tournament.count()} tournaments`);
338
415
  console.log(` - ${await prisma.tournamentResult.count()} tournament results`);
339
416
  }