@opprs/db-prisma 2.2.1-canary.ea6f686 → 2.2.1-canary.f877650

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
@@ -21,24 +21,31 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  connect: () => connect,
24
+ countLocations: () => countLocations,
24
25
  countPlayers: () => countPlayers,
25
26
  countResults: () => countResults,
26
27
  countTournaments: () => countTournaments,
27
28
  countUsers: () => countUsers,
29
+ createLocation: () => createLocation,
28
30
  createManyResults: () => createManyResults,
29
31
  createPlayer: () => createPlayer,
30
32
  createResult: () => createResult,
31
33
  createTournament: () => createTournament,
32
34
  createUser: () => createUser,
33
35
  createUserWithPlayer: () => createUserWithPlayer,
36
+ deleteLocation: () => deleteLocation,
34
37
  deletePlayer: () => deletePlayer,
35
38
  deleteResult: () => deleteResult,
36
39
  deleteResultsByTournament: () => deleteResultsByTournament,
37
40
  deleteTournament: () => deleteTournament,
38
41
  deleteUser: () => deleteUser,
39
42
  disconnect: () => disconnect,
43
+ findLocationByExternalId: () => findLocationByExternalId,
44
+ findLocationById: () => findLocationById,
45
+ findLocations: () => findLocations,
40
46
  findPlayerByExternalId: () => findPlayerByExternalId,
41
47
  findPlayerById: () => findPlayerById,
48
+ findPlayerByPlayerNumber: () => findPlayerByPlayerNumber,
42
49
  findPlayerByUserEmail: () => findPlayerByUserEmail,
43
50
  findPlayers: () => findPlayers,
44
51
  findResultById: () => findResultById,
@@ -50,6 +57,8 @@ __export(index_exports, {
50
57
  findUserByEmail: () => findUserByEmail,
51
58
  findUserById: () => findUserById,
52
59
  findUsers: () => findUsers,
60
+ generateUniquePlayerNumber: () => generateUniquePlayerNumber,
61
+ getLocationWithTournaments: () => getLocationWithTournaments,
53
62
  getMajorTournaments: () => getMajorTournaments,
54
63
  getPlayerResults: () => getPlayerResults,
55
64
  getPlayerStats: () => getPlayerStats,
@@ -66,12 +75,15 @@ __export(index_exports, {
66
75
  getTournamentsByDateRange: () => getTournamentsByDateRange,
67
76
  getUserByEmailWithPlayer: () => getUserByEmailWithPlayer,
68
77
  getUserWithPlayer: () => getUserWithPlayer,
78
+ isValidPlayerNumber: () => isValidPlayerNumber,
69
79
  linkPlayerToUser: () => linkPlayerToUser,
70
80
  prisma: () => prisma,
71
81
  recalculateTimeDecay: () => recalculateTimeDecay,
82
+ searchLocations: () => searchLocations,
72
83
  searchPlayers: () => searchPlayers,
73
84
  searchTournaments: () => searchTournaments,
74
85
  testConnection: () => testConnection,
86
+ updateLocation: () => updateLocation,
75
87
  updatePlayer: () => updatePlayer,
76
88
  updatePlayerRating: () => updatePlayerRating,
77
89
  updateResult: () => updateResult,
@@ -107,10 +119,40 @@ async function testConnection() {
107
119
  }
108
120
  }
109
121
 
122
+ // src/player-number.ts
123
+ var MIN_PLAYER_NUMBER = 1e4;
124
+ var MAX_PLAYER_NUMBER = 99999;
125
+ var MAX_RETRIES = 10;
126
+ function generateRandomPlayerNumber() {
127
+ return Math.floor(Math.random() * (MAX_PLAYER_NUMBER - MIN_PLAYER_NUMBER + 1)) + MIN_PLAYER_NUMBER;
128
+ }
129
+ async function generateUniquePlayerNumber() {
130
+ for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
131
+ const candidate = generateRandomPlayerNumber();
132
+ const existing = await prisma.player.findUnique({
133
+ where: { playerNumber: candidate },
134
+ select: { id: true }
135
+ });
136
+ if (!existing) {
137
+ return candidate;
138
+ }
139
+ }
140
+ throw new Error(
141
+ `Failed to generate unique player number after ${MAX_RETRIES} attempts. Consider increasing the number range or implementing a different allocation strategy.`
142
+ );
143
+ }
144
+ function isValidPlayerNumber(playerNumber) {
145
+ return Number.isInteger(playerNumber) && playerNumber >= MIN_PLAYER_NUMBER && playerNumber <= MAX_PLAYER_NUMBER;
146
+ }
147
+
110
148
  // src/players.ts
111
149
  async function createPlayer(data) {
150
+ const playerNumber = data.playerNumber ?? await generateUniquePlayerNumber();
112
151
  return prisma.player.create({
113
- data
152
+ data: {
153
+ ...data,
154
+ playerNumber
155
+ }
114
156
  });
115
157
  }
116
158
  async function findPlayerById(id, include) {
@@ -125,6 +167,12 @@ async function findPlayerByExternalId(externalId, include) {
125
167
  include
126
168
  });
127
169
  }
170
+ async function findPlayerByPlayerNumber(playerNumber, include) {
171
+ return prisma.player.findUnique({
172
+ where: { playerNumber },
173
+ include
174
+ });
175
+ }
128
176
  async function findPlayerByUserEmail(email, include) {
129
177
  const user = await prisma.user.findUnique({
130
178
  where: { email },
@@ -320,7 +368,7 @@ async function searchTournaments(query, limit = 20) {
320
368
  where: {
321
369
  OR: [
322
370
  { name: { contains: query, mode: "insensitive" } },
323
- { location: { contains: query, mode: "insensitive" } }
371
+ { location: { name: { contains: query, mode: "insensitive" } } }
324
372
  ]
325
373
  },
326
374
  orderBy: { date: "desc" }
@@ -540,9 +588,11 @@ async function createUser(data) {
540
588
  }
541
589
  async function createUserWithPlayer(userData, playerData) {
542
590
  return prisma.$transaction(async (tx) => {
591
+ const playerNumber = await generateUniquePlayerNumber();
543
592
  const player = await tx.player.create({
544
593
  data: {
545
- name: playerData.name
594
+ name: playerData.name,
595
+ playerNumber
546
596
  }
547
597
  });
548
598
  const user = await tx.user.create({
@@ -554,6 +604,7 @@ async function createUserWithPlayer(userData, playerData) {
554
604
  player: {
555
605
  select: {
556
606
  id: true,
607
+ playerNumber: true,
557
608
  name: true,
558
609
  rating: true,
559
610
  ratingDeviation: true,
@@ -586,6 +637,7 @@ async function getUserWithPlayer(id) {
586
637
  player: {
587
638
  select: {
588
639
  id: true,
640
+ playerNumber: true,
589
641
  name: true,
590
642
  rating: true,
591
643
  ratingDeviation: true,
@@ -608,6 +660,7 @@ async function getUserByEmailWithPlayer(email) {
608
660
  player: {
609
661
  select: {
610
662
  id: true,
663
+ playerNumber: true,
611
664
  name: true,
612
665
  rating: true,
613
666
  ratingDeviation: true,
@@ -653,6 +706,7 @@ async function findUsers(params) {
653
706
  player: {
654
707
  select: {
655
708
  id: true,
709
+ playerNumber: true,
656
710
  name: true,
657
711
  rating: true,
658
712
  ratingDeviation: true,
@@ -684,6 +738,7 @@ async function linkPlayerToUser(userId, playerId) {
684
738
  player: {
685
739
  select: {
686
740
  id: true,
741
+ playerNumber: true,
687
742
  name: true,
688
743
  rating: true,
689
744
  ratingDeviation: true,
@@ -697,27 +752,100 @@ async function linkPlayerToUser(userId, playerId) {
697
752
  return user;
698
753
  });
699
754
  }
755
+
756
+ // src/locations.ts
757
+ async function createLocation(data) {
758
+ return prisma.location.create({
759
+ data
760
+ });
761
+ }
762
+ async function findLocationById(id, include) {
763
+ return prisma.location.findUnique({
764
+ where: { id },
765
+ include
766
+ });
767
+ }
768
+ async function findLocationByExternalId(externalId, include) {
769
+ return prisma.location.findUnique({
770
+ where: { externalId },
771
+ include
772
+ });
773
+ }
774
+ async function findLocations(options = {}) {
775
+ return prisma.location.findMany({
776
+ take: options.take,
777
+ skip: options.skip,
778
+ where: options.where,
779
+ orderBy: options.orderBy,
780
+ include: options.include
781
+ });
782
+ }
783
+ async function searchLocations(query, limit = 20) {
784
+ return findLocations({
785
+ take: limit,
786
+ where: {
787
+ OR: [
788
+ { name: { contains: query, mode: "insensitive" } },
789
+ { city: { contains: query, mode: "insensitive" } }
790
+ ]
791
+ },
792
+ orderBy: { name: "asc" }
793
+ });
794
+ }
795
+ async function updateLocation(id, data) {
796
+ return prisma.location.update({
797
+ where: { id },
798
+ data
799
+ });
800
+ }
801
+ async function deleteLocation(id) {
802
+ return prisma.location.delete({
803
+ where: { id }
804
+ });
805
+ }
806
+ async function countLocations(where) {
807
+ return prisma.location.count({ where });
808
+ }
809
+ async function getLocationWithTournaments(id) {
810
+ return prisma.location.findUnique({
811
+ where: { id },
812
+ include: {
813
+ tournaments: {
814
+ orderBy: {
815
+ date: "desc"
816
+ }
817
+ }
818
+ }
819
+ });
820
+ }
700
821
  // Annotate the CommonJS export names for ESM import in node:
701
822
  0 && (module.exports = {
702
823
  connect,
824
+ countLocations,
703
825
  countPlayers,
704
826
  countResults,
705
827
  countTournaments,
706
828
  countUsers,
829
+ createLocation,
707
830
  createManyResults,
708
831
  createPlayer,
709
832
  createResult,
710
833
  createTournament,
711
834
  createUser,
712
835
  createUserWithPlayer,
836
+ deleteLocation,
713
837
  deletePlayer,
714
838
  deleteResult,
715
839
  deleteResultsByTournament,
716
840
  deleteTournament,
717
841
  deleteUser,
718
842
  disconnect,
843
+ findLocationByExternalId,
844
+ findLocationById,
845
+ findLocations,
719
846
  findPlayerByExternalId,
720
847
  findPlayerById,
848
+ findPlayerByPlayerNumber,
721
849
  findPlayerByUserEmail,
722
850
  findPlayers,
723
851
  findResultById,
@@ -729,6 +857,8 @@ async function linkPlayerToUser(userId, playerId) {
729
857
  findUserByEmail,
730
858
  findUserById,
731
859
  findUsers,
860
+ generateUniquePlayerNumber,
861
+ getLocationWithTournaments,
732
862
  getMajorTournaments,
733
863
  getPlayerResults,
734
864
  getPlayerStats,
@@ -745,12 +875,15 @@ async function linkPlayerToUser(userId, playerId) {
745
875
  getTournamentsByDateRange,
746
876
  getUserByEmailWithPlayer,
747
877
  getUserWithPlayer,
878
+ isValidPlayerNumber,
748
879
  linkPlayerToUser,
749
880
  prisma,
750
881
  recalculateTimeDecay,
882
+ searchLocations,
751
883
  searchPlayers,
752
884
  searchTournaments,
753
885
  testConnection,
886
+ updateLocation,
754
887
  updatePlayer,
755
888
  updatePlayerRating,
756
889
  updateResult,
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _prisma_client_runtime_library from '@prisma/client/runtime/library';
2
2
  import * as _prisma_client from '@prisma/client';
3
- import { PrismaClient, Player, Prisma, EventBoosterType, Tournament, TournamentResult, User } from '@prisma/client';
4
- export { EventBoosterType, Player, Prisma, Role, Tournament, TournamentResult, User } from '@prisma/client';
3
+ import { PrismaClient, Player, Prisma, EventBoosterType, Tournament, TournamentResult, User, Location } from '@prisma/client';
4
+ export { EventBoosterType, Location, Player, Prisma, Role, Tournament, TournamentResult, User } from '@prisma/client';
5
5
 
6
6
  declare const prisma: PrismaClient<_prisma_client.Prisma.PrismaClientOptions, never, _prisma_client_runtime_library.DefaultArgs>;
7
7
  /**
@@ -25,6 +25,7 @@ declare function testConnection(): Promise<boolean>;
25
25
  */
26
26
  interface CreatePlayerInput {
27
27
  externalId?: string;
28
+ playerNumber?: number;
28
29
  name?: string;
29
30
  rating?: number;
30
31
  ratingDeviation?: number;
@@ -56,7 +57,7 @@ interface FindPlayersOptions {
56
57
  include?: Prisma.PlayerInclude;
57
58
  }
58
59
  /**
59
- * Creates a new player
60
+ * Creates a new player with auto-generated playerNumber
60
61
  */
61
62
  declare function createPlayer(data: CreatePlayerInput): Promise<Player>;
62
63
  /**
@@ -67,6 +68,10 @@ declare function findPlayerById(id: string, include?: Prisma.PlayerInclude): Pro
67
68
  * Finds a player by external ID
68
69
  */
69
70
  declare function findPlayerByExternalId(externalId: string, include?: Prisma.PlayerInclude): Promise<Player | null>;
71
+ /**
72
+ * Finds a player by player number
73
+ */
74
+ declare function findPlayerByPlayerNumber(playerNumber: number, include?: Prisma.PlayerInclude): Promise<Player | null>;
70
75
  /**
71
76
  * Finds a player through their linked User's email
72
77
  */
@@ -114,8 +119,10 @@ declare function getPlayerWithResults(id: string): Promise<{
114
119
  createdAt: Date;
115
120
  updatedAt: Date;
116
121
  externalId: string | null;
117
- location: string | null;
122
+ description: string | null;
118
123
  date: Date;
124
+ locationId: string | null;
125
+ organizerId: string | null;
119
126
  tgpConfig: Prisma.JsonValue | null;
120
127
  eventBooster: _prisma_client.$Enums.EventBoosterType;
121
128
  allowsOptOut: boolean;
@@ -150,8 +157,10 @@ declare function getPlayerWithResults(id: string): Promise<{
150
157
  createdAt: Date;
151
158
  updatedAt: Date;
152
159
  externalId: string | null;
153
- location: string | null;
160
+ description: string | null;
154
161
  date: Date;
162
+ locationId: string | null;
163
+ organizerId: string | null;
155
164
  tgpConfig: Prisma.JsonValue | null;
156
165
  eventBooster: _prisma_client.$Enums.EventBoosterType;
157
166
  allowsOptOut: boolean;
@@ -184,6 +193,7 @@ declare function getPlayerWithResults(id: string): Promise<{
184
193
  createdAt: Date;
185
194
  updatedAt: Date;
186
195
  externalId: string | null;
196
+ playerNumber: number;
187
197
  rating: number;
188
198
  ratingDeviation: number;
189
199
  ranking: number | null;
@@ -197,14 +207,28 @@ declare function getPlayerWithResults(id: string): Promise<{
197
207
  */
198
208
  declare function searchPlayers(query: string, limit?: number): Promise<Player[]>;
199
209
 
210
+ /**
211
+ * Generates a unique player number with collision handling.
212
+ * Retries up to MAX_RETRIES times if collision occurs.
213
+ *
214
+ * @throws Error if unable to generate unique number after max retries
215
+ */
216
+ declare function generateUniquePlayerNumber(): Promise<number>;
217
+ /**
218
+ * Validates that a player number is in the valid range
219
+ */
220
+ declare function isValidPlayerNumber(playerNumber: number): boolean;
221
+
200
222
  /**
201
223
  * Input for creating a new tournament
202
224
  */
203
225
  interface CreateTournamentInput {
204
226
  externalId?: string;
205
227
  name: string;
206
- location?: string;
228
+ description?: string;
207
229
  date: Date;
230
+ locationId?: string;
231
+ organizerId?: string;
208
232
  tgpConfig?: Prisma.InputJsonValue;
209
233
  eventBooster?: EventBoosterType;
210
234
  allowsOptOut?: boolean;
@@ -221,8 +245,10 @@ interface CreateTournamentInput {
221
245
  */
222
246
  interface UpdateTournamentInput {
223
247
  name?: string;
224
- location?: string;
248
+ description?: string | null;
225
249
  date?: Date;
250
+ locationId?: string | null;
251
+ organizerId?: string | null;
226
252
  tgpConfig?: Prisma.InputJsonValue;
227
253
  eventBooster?: EventBoosterType;
228
254
  allowsOptOut?: boolean;
@@ -299,6 +325,7 @@ declare function getTournamentWithResults(id: string): Promise<({
299
325
  createdAt: Date;
300
326
  updatedAt: Date;
301
327
  externalId: string | null;
328
+ playerNumber: number;
302
329
  rating: number;
303
330
  ratingDeviation: number;
304
331
  ranking: number | null;
@@ -329,8 +356,10 @@ declare function getTournamentWithResults(id: string): Promise<({
329
356
  createdAt: Date;
330
357
  updatedAt: Date;
331
358
  externalId: string | null;
332
- location: string | null;
359
+ description: string | null;
333
360
  date: Date;
361
+ locationId: string | null;
362
+ organizerId: string | null;
334
363
  tgpConfig: Prisma.JsonValue | null;
335
364
  eventBooster: _prisma_client.$Enums.EventBoosterType;
336
365
  allowsOptOut: boolean;
@@ -343,7 +372,7 @@ declare function getTournamentWithResults(id: string): Promise<({
343
372
  firstPlaceValue: number | null;
344
373
  }) | null>;
345
374
  /**
346
- * Searches tournaments by name or location
375
+ * Searches tournaments by name or location name
347
376
  */
348
377
  declare function searchTournaments(query: string, limit?: number): Promise<Tournament[]>;
349
378
  /**
@@ -358,6 +387,7 @@ declare function getTournamentStats(id: string): Promise<{
358
387
  createdAt: Date;
359
388
  updatedAt: Date;
360
389
  externalId: string | null;
390
+ playerNumber: number;
361
391
  rating: number;
362
392
  ratingDeviation: number;
363
393
  ranking: number | null;
@@ -388,8 +418,10 @@ declare function getTournamentStats(id: string): Promise<{
388
418
  createdAt: Date;
389
419
  updatedAt: Date;
390
420
  externalId: string | null;
391
- location: string | null;
421
+ description: string | null;
392
422
  date: Date;
423
+ locationId: string | null;
424
+ organizerId: string | null;
393
425
  tgpConfig: Prisma.JsonValue | null;
394
426
  eventBooster: _prisma_client.$Enums.EventBoosterType;
395
427
  allowsOptOut: boolean;
@@ -571,6 +603,7 @@ interface UserWithPlayer {
571
603
  updatedAt: Date;
572
604
  player: {
573
605
  id: string;
606
+ playerNumber: number;
574
607
  name: string | null;
575
608
  rating: number;
576
609
  ratingDeviation: number;
@@ -641,6 +674,106 @@ declare function findUsers(params: {
641
674
  */
642
675
  declare function linkPlayerToUser(userId: string, playerId: string | null): Promise<UserWithPlayer>;
643
676
 
677
+ /**
678
+ * Input for creating a new location
679
+ */
680
+ interface CreateLocationInput {
681
+ externalId?: string;
682
+ name: string;
683
+ address?: string;
684
+ city?: string;
685
+ state?: string;
686
+ country?: string;
687
+ }
688
+ /**
689
+ * Input for updating a location
690
+ */
691
+ interface UpdateLocationInput {
692
+ name?: string;
693
+ address?: string | null;
694
+ city?: string | null;
695
+ state?: string | null;
696
+ country?: string | null;
697
+ }
698
+ /**
699
+ * Options for querying locations
700
+ */
701
+ interface FindLocationsOptions {
702
+ take?: number;
703
+ skip?: number;
704
+ orderBy?: Prisma.LocationOrderByWithRelationInput;
705
+ where?: Prisma.LocationWhereInput;
706
+ include?: Prisma.LocationInclude;
707
+ }
708
+ /**
709
+ * Creates a new location
710
+ */
711
+ declare function createLocation(data: CreateLocationInput): Promise<Location>;
712
+ /**
713
+ * Finds a location by ID
714
+ */
715
+ declare function findLocationById(id: string, include?: Prisma.LocationInclude): Promise<Location | null>;
716
+ /**
717
+ * Finds a location by external ID
718
+ */
719
+ declare function findLocationByExternalId(externalId: string, include?: Prisma.LocationInclude): Promise<Location | null>;
720
+ /**
721
+ * Finds multiple locations with optional filters
722
+ */
723
+ declare function findLocations(options?: FindLocationsOptions): Promise<Location[]>;
724
+ /**
725
+ * Searches locations by name or city
726
+ */
727
+ declare function searchLocations(query: string, limit?: number): Promise<Location[]>;
728
+ /**
729
+ * Updates a location
730
+ */
731
+ declare function updateLocation(id: string, data: UpdateLocationInput): Promise<Location>;
732
+ /**
733
+ * Deletes a location
734
+ */
735
+ declare function deleteLocation(id: string): Promise<Location>;
736
+ /**
737
+ * Counts total locations
738
+ */
739
+ declare function countLocations(where?: Prisma.LocationWhereInput): Promise<number>;
740
+ /**
741
+ * Gets location with its tournaments
742
+ */
743
+ declare function getLocationWithTournaments(id: string): Promise<({
744
+ tournaments: {
745
+ name: string;
746
+ id: string;
747
+ createdAt: Date;
748
+ updatedAt: Date;
749
+ externalId: string | null;
750
+ description: string | null;
751
+ date: Date;
752
+ locationId: string | null;
753
+ organizerId: string | null;
754
+ tgpConfig: Prisma.JsonValue | null;
755
+ eventBooster: _prisma_client.$Enums.EventBoosterType;
756
+ allowsOptOut: boolean;
757
+ baseValue: number | null;
758
+ tvaRating: number | null;
759
+ tvaRanking: number | null;
760
+ totalTVA: number | null;
761
+ tgp: number | null;
762
+ eventBoosterMultiplier: number | null;
763
+ firstPlaceValue: number | null;
764
+ }[];
765
+ } & {
766
+ name: string;
767
+ id: string;
768
+ createdAt: Date;
769
+ updatedAt: Date;
770
+ externalId: string | null;
771
+ address: string | null;
772
+ city: string | null;
773
+ state: string | null;
774
+ country: string | null;
775
+ }) | null>;
776
+
644
777
  /**
645
778
  * Re-export Prisma generated types
646
779
  */
@@ -700,4 +833,4 @@ interface ConnectionStatus {
700
833
  error?: string;
701
834
  }
702
835
 
703
- export { type ConnectionStatus, type CreatePlayerInput, type CreateResultInput, type CreateTournamentInput, type CreateUserInput, type FindPlayersOptions, type FindResultsOptions, type FindTournamentsOptions, type PlayerStatistics, type PlayerWithResults, type TournamentResultWithTournament, type TournamentStatistics, type UpdatePlayerInput, type UpdateResultInput, type UpdateTournamentInput, type UpdateUserInput, type UserWithPlayer, connect, countPlayers, countResults, countTournaments, countUsers, createManyResults, createPlayer, createResult, createTournament, createUser, createUserWithPlayer, deletePlayer, deleteResult, deleteResultsByTournament, deleteTournament, deleteUser, disconnect, findPlayerByExternalId, findPlayerById, findPlayerByUserEmail, findPlayers, findResultById, findResultByPlayerAndTournament, findResults, findTournamentByExternalId, findTournamentById, findTournaments, findUserByEmail, findUserById, findUsers, getMajorTournaments, getPlayerResults, getPlayerStats, getPlayerTopFinishes, getPlayerWithResults, getRatedPlayers, getRecentTournaments, getTopPlayersByRanking, getTopPlayersByRating, getTournamentResults, getTournamentStats, getTournamentWithResults, getTournamentsByBoosterType, getTournamentsByDateRange, getUserByEmailWithPlayer, getUserWithPlayer, linkPlayerToUser, prisma, recalculateTimeDecay, searchPlayers, searchTournaments, testConnection, updatePlayer, updatePlayerRating, updateResult, updateResultPoints, updateTournament, updateUser, updateUserRefreshToken };
836
+ export { type ConnectionStatus, type CreateLocationInput, type CreatePlayerInput, type CreateResultInput, type CreateTournamentInput, type CreateUserInput, type FindLocationsOptions, type FindPlayersOptions, type FindResultsOptions, type FindTournamentsOptions, type PlayerStatistics, type PlayerWithResults, type TournamentResultWithTournament, type TournamentStatistics, type UpdateLocationInput, type UpdatePlayerInput, type UpdateResultInput, type UpdateTournamentInput, type UpdateUserInput, type UserWithPlayer, connect, countLocations, countPlayers, countResults, countTournaments, countUsers, createLocation, createManyResults, createPlayer, createResult, createTournament, createUser, createUserWithPlayer, deleteLocation, deletePlayer, deleteResult, deleteResultsByTournament, deleteTournament, deleteUser, disconnect, findLocationByExternalId, findLocationById, findLocations, findPlayerByExternalId, findPlayerById, findPlayerByPlayerNumber, findPlayerByUserEmail, findPlayers, findResultById, findResultByPlayerAndTournament, findResults, findTournamentByExternalId, findTournamentById, findTournaments, findUserByEmail, findUserById, findUsers, generateUniquePlayerNumber, getLocationWithTournaments, getMajorTournaments, getPlayerResults, getPlayerStats, getPlayerTopFinishes, getPlayerWithResults, getRatedPlayers, getRecentTournaments, getTopPlayersByRanking, getTopPlayersByRating, getTournamentResults, getTournamentStats, getTournamentWithResults, getTournamentsByBoosterType, getTournamentsByDateRange, getUserByEmailWithPlayer, getUserWithPlayer, isValidPlayerNumber, linkPlayerToUser, prisma, recalculateTimeDecay, searchLocations, searchPlayers, searchTournaments, testConnection, updateLocation, updatePlayer, updatePlayerRating, updateResult, updateResultPoints, updateTournament, updateUser, updateUserRefreshToken };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _prisma_client_runtime_library from '@prisma/client/runtime/library';
2
2
  import * as _prisma_client from '@prisma/client';
3
- import { PrismaClient, Player, Prisma, EventBoosterType, Tournament, TournamentResult, User } from '@prisma/client';
4
- export { EventBoosterType, Player, Prisma, Role, Tournament, TournamentResult, User } from '@prisma/client';
3
+ import { PrismaClient, Player, Prisma, EventBoosterType, Tournament, TournamentResult, User, Location } from '@prisma/client';
4
+ export { EventBoosterType, Location, Player, Prisma, Role, Tournament, TournamentResult, User } from '@prisma/client';
5
5
 
6
6
  declare const prisma: PrismaClient<_prisma_client.Prisma.PrismaClientOptions, never, _prisma_client_runtime_library.DefaultArgs>;
7
7
  /**
@@ -25,6 +25,7 @@ declare function testConnection(): Promise<boolean>;
25
25
  */
26
26
  interface CreatePlayerInput {
27
27
  externalId?: string;
28
+ playerNumber?: number;
28
29
  name?: string;
29
30
  rating?: number;
30
31
  ratingDeviation?: number;
@@ -56,7 +57,7 @@ interface FindPlayersOptions {
56
57
  include?: Prisma.PlayerInclude;
57
58
  }
58
59
  /**
59
- * Creates a new player
60
+ * Creates a new player with auto-generated playerNumber
60
61
  */
61
62
  declare function createPlayer(data: CreatePlayerInput): Promise<Player>;
62
63
  /**
@@ -67,6 +68,10 @@ declare function findPlayerById(id: string, include?: Prisma.PlayerInclude): Pro
67
68
  * Finds a player by external ID
68
69
  */
69
70
  declare function findPlayerByExternalId(externalId: string, include?: Prisma.PlayerInclude): Promise<Player | null>;
71
+ /**
72
+ * Finds a player by player number
73
+ */
74
+ declare function findPlayerByPlayerNumber(playerNumber: number, include?: Prisma.PlayerInclude): Promise<Player | null>;
70
75
  /**
71
76
  * Finds a player through their linked User's email
72
77
  */
@@ -114,8 +119,10 @@ declare function getPlayerWithResults(id: string): Promise<{
114
119
  createdAt: Date;
115
120
  updatedAt: Date;
116
121
  externalId: string | null;
117
- location: string | null;
122
+ description: string | null;
118
123
  date: Date;
124
+ locationId: string | null;
125
+ organizerId: string | null;
119
126
  tgpConfig: Prisma.JsonValue | null;
120
127
  eventBooster: _prisma_client.$Enums.EventBoosterType;
121
128
  allowsOptOut: boolean;
@@ -150,8 +157,10 @@ declare function getPlayerWithResults(id: string): Promise<{
150
157
  createdAt: Date;
151
158
  updatedAt: Date;
152
159
  externalId: string | null;
153
- location: string | null;
160
+ description: string | null;
154
161
  date: Date;
162
+ locationId: string | null;
163
+ organizerId: string | null;
155
164
  tgpConfig: Prisma.JsonValue | null;
156
165
  eventBooster: _prisma_client.$Enums.EventBoosterType;
157
166
  allowsOptOut: boolean;
@@ -184,6 +193,7 @@ declare function getPlayerWithResults(id: string): Promise<{
184
193
  createdAt: Date;
185
194
  updatedAt: Date;
186
195
  externalId: string | null;
196
+ playerNumber: number;
187
197
  rating: number;
188
198
  ratingDeviation: number;
189
199
  ranking: number | null;
@@ -197,14 +207,28 @@ declare function getPlayerWithResults(id: string): Promise<{
197
207
  */
198
208
  declare function searchPlayers(query: string, limit?: number): Promise<Player[]>;
199
209
 
210
+ /**
211
+ * Generates a unique player number with collision handling.
212
+ * Retries up to MAX_RETRIES times if collision occurs.
213
+ *
214
+ * @throws Error if unable to generate unique number after max retries
215
+ */
216
+ declare function generateUniquePlayerNumber(): Promise<number>;
217
+ /**
218
+ * Validates that a player number is in the valid range
219
+ */
220
+ declare function isValidPlayerNumber(playerNumber: number): boolean;
221
+
200
222
  /**
201
223
  * Input for creating a new tournament
202
224
  */
203
225
  interface CreateTournamentInput {
204
226
  externalId?: string;
205
227
  name: string;
206
- location?: string;
228
+ description?: string;
207
229
  date: Date;
230
+ locationId?: string;
231
+ organizerId?: string;
208
232
  tgpConfig?: Prisma.InputJsonValue;
209
233
  eventBooster?: EventBoosterType;
210
234
  allowsOptOut?: boolean;
@@ -221,8 +245,10 @@ interface CreateTournamentInput {
221
245
  */
222
246
  interface UpdateTournamentInput {
223
247
  name?: string;
224
- location?: string;
248
+ description?: string | null;
225
249
  date?: Date;
250
+ locationId?: string | null;
251
+ organizerId?: string | null;
226
252
  tgpConfig?: Prisma.InputJsonValue;
227
253
  eventBooster?: EventBoosterType;
228
254
  allowsOptOut?: boolean;
@@ -299,6 +325,7 @@ declare function getTournamentWithResults(id: string): Promise<({
299
325
  createdAt: Date;
300
326
  updatedAt: Date;
301
327
  externalId: string | null;
328
+ playerNumber: number;
302
329
  rating: number;
303
330
  ratingDeviation: number;
304
331
  ranking: number | null;
@@ -329,8 +356,10 @@ declare function getTournamentWithResults(id: string): Promise<({
329
356
  createdAt: Date;
330
357
  updatedAt: Date;
331
358
  externalId: string | null;
332
- location: string | null;
359
+ description: string | null;
333
360
  date: Date;
361
+ locationId: string | null;
362
+ organizerId: string | null;
334
363
  tgpConfig: Prisma.JsonValue | null;
335
364
  eventBooster: _prisma_client.$Enums.EventBoosterType;
336
365
  allowsOptOut: boolean;
@@ -343,7 +372,7 @@ declare function getTournamentWithResults(id: string): Promise<({
343
372
  firstPlaceValue: number | null;
344
373
  }) | null>;
345
374
  /**
346
- * Searches tournaments by name or location
375
+ * Searches tournaments by name or location name
347
376
  */
348
377
  declare function searchTournaments(query: string, limit?: number): Promise<Tournament[]>;
349
378
  /**
@@ -358,6 +387,7 @@ declare function getTournamentStats(id: string): Promise<{
358
387
  createdAt: Date;
359
388
  updatedAt: Date;
360
389
  externalId: string | null;
390
+ playerNumber: number;
361
391
  rating: number;
362
392
  ratingDeviation: number;
363
393
  ranking: number | null;
@@ -388,8 +418,10 @@ declare function getTournamentStats(id: string): Promise<{
388
418
  createdAt: Date;
389
419
  updatedAt: Date;
390
420
  externalId: string | null;
391
- location: string | null;
421
+ description: string | null;
392
422
  date: Date;
423
+ locationId: string | null;
424
+ organizerId: string | null;
393
425
  tgpConfig: Prisma.JsonValue | null;
394
426
  eventBooster: _prisma_client.$Enums.EventBoosterType;
395
427
  allowsOptOut: boolean;
@@ -571,6 +603,7 @@ interface UserWithPlayer {
571
603
  updatedAt: Date;
572
604
  player: {
573
605
  id: string;
606
+ playerNumber: number;
574
607
  name: string | null;
575
608
  rating: number;
576
609
  ratingDeviation: number;
@@ -641,6 +674,106 @@ declare function findUsers(params: {
641
674
  */
642
675
  declare function linkPlayerToUser(userId: string, playerId: string | null): Promise<UserWithPlayer>;
643
676
 
677
+ /**
678
+ * Input for creating a new location
679
+ */
680
+ interface CreateLocationInput {
681
+ externalId?: string;
682
+ name: string;
683
+ address?: string;
684
+ city?: string;
685
+ state?: string;
686
+ country?: string;
687
+ }
688
+ /**
689
+ * Input for updating a location
690
+ */
691
+ interface UpdateLocationInput {
692
+ name?: string;
693
+ address?: string | null;
694
+ city?: string | null;
695
+ state?: string | null;
696
+ country?: string | null;
697
+ }
698
+ /**
699
+ * Options for querying locations
700
+ */
701
+ interface FindLocationsOptions {
702
+ take?: number;
703
+ skip?: number;
704
+ orderBy?: Prisma.LocationOrderByWithRelationInput;
705
+ where?: Prisma.LocationWhereInput;
706
+ include?: Prisma.LocationInclude;
707
+ }
708
+ /**
709
+ * Creates a new location
710
+ */
711
+ declare function createLocation(data: CreateLocationInput): Promise<Location>;
712
+ /**
713
+ * Finds a location by ID
714
+ */
715
+ declare function findLocationById(id: string, include?: Prisma.LocationInclude): Promise<Location | null>;
716
+ /**
717
+ * Finds a location by external ID
718
+ */
719
+ declare function findLocationByExternalId(externalId: string, include?: Prisma.LocationInclude): Promise<Location | null>;
720
+ /**
721
+ * Finds multiple locations with optional filters
722
+ */
723
+ declare function findLocations(options?: FindLocationsOptions): Promise<Location[]>;
724
+ /**
725
+ * Searches locations by name or city
726
+ */
727
+ declare function searchLocations(query: string, limit?: number): Promise<Location[]>;
728
+ /**
729
+ * Updates a location
730
+ */
731
+ declare function updateLocation(id: string, data: UpdateLocationInput): Promise<Location>;
732
+ /**
733
+ * Deletes a location
734
+ */
735
+ declare function deleteLocation(id: string): Promise<Location>;
736
+ /**
737
+ * Counts total locations
738
+ */
739
+ declare function countLocations(where?: Prisma.LocationWhereInput): Promise<number>;
740
+ /**
741
+ * Gets location with its tournaments
742
+ */
743
+ declare function getLocationWithTournaments(id: string): Promise<({
744
+ tournaments: {
745
+ name: string;
746
+ id: string;
747
+ createdAt: Date;
748
+ updatedAt: Date;
749
+ externalId: string | null;
750
+ description: string | null;
751
+ date: Date;
752
+ locationId: string | null;
753
+ organizerId: string | null;
754
+ tgpConfig: Prisma.JsonValue | null;
755
+ eventBooster: _prisma_client.$Enums.EventBoosterType;
756
+ allowsOptOut: boolean;
757
+ baseValue: number | null;
758
+ tvaRating: number | null;
759
+ tvaRanking: number | null;
760
+ totalTVA: number | null;
761
+ tgp: number | null;
762
+ eventBoosterMultiplier: number | null;
763
+ firstPlaceValue: number | null;
764
+ }[];
765
+ } & {
766
+ name: string;
767
+ id: string;
768
+ createdAt: Date;
769
+ updatedAt: Date;
770
+ externalId: string | null;
771
+ address: string | null;
772
+ city: string | null;
773
+ state: string | null;
774
+ country: string | null;
775
+ }) | null>;
776
+
644
777
  /**
645
778
  * Re-export Prisma generated types
646
779
  */
@@ -700,4 +833,4 @@ interface ConnectionStatus {
700
833
  error?: string;
701
834
  }
702
835
 
703
- export { type ConnectionStatus, type CreatePlayerInput, type CreateResultInput, type CreateTournamentInput, type CreateUserInput, type FindPlayersOptions, type FindResultsOptions, type FindTournamentsOptions, type PlayerStatistics, type PlayerWithResults, type TournamentResultWithTournament, type TournamentStatistics, type UpdatePlayerInput, type UpdateResultInput, type UpdateTournamentInput, type UpdateUserInput, type UserWithPlayer, connect, countPlayers, countResults, countTournaments, countUsers, createManyResults, createPlayer, createResult, createTournament, createUser, createUserWithPlayer, deletePlayer, deleteResult, deleteResultsByTournament, deleteTournament, deleteUser, disconnect, findPlayerByExternalId, findPlayerById, findPlayerByUserEmail, findPlayers, findResultById, findResultByPlayerAndTournament, findResults, findTournamentByExternalId, findTournamentById, findTournaments, findUserByEmail, findUserById, findUsers, getMajorTournaments, getPlayerResults, getPlayerStats, getPlayerTopFinishes, getPlayerWithResults, getRatedPlayers, getRecentTournaments, getTopPlayersByRanking, getTopPlayersByRating, getTournamentResults, getTournamentStats, getTournamentWithResults, getTournamentsByBoosterType, getTournamentsByDateRange, getUserByEmailWithPlayer, getUserWithPlayer, linkPlayerToUser, prisma, recalculateTimeDecay, searchPlayers, searchTournaments, testConnection, updatePlayer, updatePlayerRating, updateResult, updateResultPoints, updateTournament, updateUser, updateUserRefreshToken };
836
+ export { type ConnectionStatus, type CreateLocationInput, type CreatePlayerInput, type CreateResultInput, type CreateTournamentInput, type CreateUserInput, type FindLocationsOptions, type FindPlayersOptions, type FindResultsOptions, type FindTournamentsOptions, type PlayerStatistics, type PlayerWithResults, type TournamentResultWithTournament, type TournamentStatistics, type UpdateLocationInput, type UpdatePlayerInput, type UpdateResultInput, type UpdateTournamentInput, type UpdateUserInput, type UserWithPlayer, connect, countLocations, countPlayers, countResults, countTournaments, countUsers, createLocation, createManyResults, createPlayer, createResult, createTournament, createUser, createUserWithPlayer, deleteLocation, deletePlayer, deleteResult, deleteResultsByTournament, deleteTournament, deleteUser, disconnect, findLocationByExternalId, findLocationById, findLocations, findPlayerByExternalId, findPlayerById, findPlayerByPlayerNumber, findPlayerByUserEmail, findPlayers, findResultById, findResultByPlayerAndTournament, findResults, findTournamentByExternalId, findTournamentById, findTournaments, findUserByEmail, findUserById, findUsers, generateUniquePlayerNumber, getLocationWithTournaments, getMajorTournaments, getPlayerResults, getPlayerStats, getPlayerTopFinishes, getPlayerWithResults, getRatedPlayers, getRecentTournaments, getTopPlayersByRanking, getTopPlayersByRating, getTournamentResults, getTournamentStats, getTournamentWithResults, getTournamentsByBoosterType, getTournamentsByDateRange, getUserByEmailWithPlayer, getUserWithPlayer, isValidPlayerNumber, linkPlayerToUser, prisma, recalculateTimeDecay, searchLocations, searchPlayers, searchTournaments, testConnection, updateLocation, updatePlayer, updatePlayerRating, updateResult, updateResultPoints, updateTournament, updateUser, updateUserRefreshToken };
package/dist/index.js CHANGED
@@ -23,10 +23,40 @@ async function testConnection() {
23
23
  }
24
24
  }
25
25
 
26
+ // src/player-number.ts
27
+ var MIN_PLAYER_NUMBER = 1e4;
28
+ var MAX_PLAYER_NUMBER = 99999;
29
+ var MAX_RETRIES = 10;
30
+ function generateRandomPlayerNumber() {
31
+ return Math.floor(Math.random() * (MAX_PLAYER_NUMBER - MIN_PLAYER_NUMBER + 1)) + MIN_PLAYER_NUMBER;
32
+ }
33
+ async function generateUniquePlayerNumber() {
34
+ for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
35
+ const candidate = generateRandomPlayerNumber();
36
+ const existing = await prisma.player.findUnique({
37
+ where: { playerNumber: candidate },
38
+ select: { id: true }
39
+ });
40
+ if (!existing) {
41
+ return candidate;
42
+ }
43
+ }
44
+ throw new Error(
45
+ `Failed to generate unique player number after ${MAX_RETRIES} attempts. Consider increasing the number range or implementing a different allocation strategy.`
46
+ );
47
+ }
48
+ function isValidPlayerNumber(playerNumber) {
49
+ return Number.isInteger(playerNumber) && playerNumber >= MIN_PLAYER_NUMBER && playerNumber <= MAX_PLAYER_NUMBER;
50
+ }
51
+
26
52
  // src/players.ts
27
53
  async function createPlayer(data) {
54
+ const playerNumber = data.playerNumber ?? await generateUniquePlayerNumber();
28
55
  return prisma.player.create({
29
- data
56
+ data: {
57
+ ...data,
58
+ playerNumber
59
+ }
30
60
  });
31
61
  }
32
62
  async function findPlayerById(id, include) {
@@ -41,6 +71,12 @@ async function findPlayerByExternalId(externalId, include) {
41
71
  include
42
72
  });
43
73
  }
74
+ async function findPlayerByPlayerNumber(playerNumber, include) {
75
+ return prisma.player.findUnique({
76
+ where: { playerNumber },
77
+ include
78
+ });
79
+ }
44
80
  async function findPlayerByUserEmail(email, include) {
45
81
  const user = await prisma.user.findUnique({
46
82
  where: { email },
@@ -236,7 +272,7 @@ async function searchTournaments(query, limit = 20) {
236
272
  where: {
237
273
  OR: [
238
274
  { name: { contains: query, mode: "insensitive" } },
239
- { location: { contains: query, mode: "insensitive" } }
275
+ { location: { name: { contains: query, mode: "insensitive" } } }
240
276
  ]
241
277
  },
242
278
  orderBy: { date: "desc" }
@@ -456,9 +492,11 @@ async function createUser(data) {
456
492
  }
457
493
  async function createUserWithPlayer(userData, playerData) {
458
494
  return prisma.$transaction(async (tx) => {
495
+ const playerNumber = await generateUniquePlayerNumber();
459
496
  const player = await tx.player.create({
460
497
  data: {
461
- name: playerData.name
498
+ name: playerData.name,
499
+ playerNumber
462
500
  }
463
501
  });
464
502
  const user = await tx.user.create({
@@ -470,6 +508,7 @@ async function createUserWithPlayer(userData, playerData) {
470
508
  player: {
471
509
  select: {
472
510
  id: true,
511
+ playerNumber: true,
473
512
  name: true,
474
513
  rating: true,
475
514
  ratingDeviation: true,
@@ -502,6 +541,7 @@ async function getUserWithPlayer(id) {
502
541
  player: {
503
542
  select: {
504
543
  id: true,
544
+ playerNumber: true,
505
545
  name: true,
506
546
  rating: true,
507
547
  ratingDeviation: true,
@@ -524,6 +564,7 @@ async function getUserByEmailWithPlayer(email) {
524
564
  player: {
525
565
  select: {
526
566
  id: true,
567
+ playerNumber: true,
527
568
  name: true,
528
569
  rating: true,
529
570
  ratingDeviation: true,
@@ -569,6 +610,7 @@ async function findUsers(params) {
569
610
  player: {
570
611
  select: {
571
612
  id: true,
613
+ playerNumber: true,
572
614
  name: true,
573
615
  rating: true,
574
616
  ratingDeviation: true,
@@ -600,6 +642,7 @@ async function linkPlayerToUser(userId, playerId) {
600
642
  player: {
601
643
  select: {
602
644
  id: true,
645
+ playerNumber: true,
603
646
  name: true,
604
647
  rating: true,
605
648
  ratingDeviation: true,
@@ -613,26 +656,99 @@ async function linkPlayerToUser(userId, playerId) {
613
656
  return user;
614
657
  });
615
658
  }
659
+
660
+ // src/locations.ts
661
+ async function createLocation(data) {
662
+ return prisma.location.create({
663
+ data
664
+ });
665
+ }
666
+ async function findLocationById(id, include) {
667
+ return prisma.location.findUnique({
668
+ where: { id },
669
+ include
670
+ });
671
+ }
672
+ async function findLocationByExternalId(externalId, include) {
673
+ return prisma.location.findUnique({
674
+ where: { externalId },
675
+ include
676
+ });
677
+ }
678
+ async function findLocations(options = {}) {
679
+ return prisma.location.findMany({
680
+ take: options.take,
681
+ skip: options.skip,
682
+ where: options.where,
683
+ orderBy: options.orderBy,
684
+ include: options.include
685
+ });
686
+ }
687
+ async function searchLocations(query, limit = 20) {
688
+ return findLocations({
689
+ take: limit,
690
+ where: {
691
+ OR: [
692
+ { name: { contains: query, mode: "insensitive" } },
693
+ { city: { contains: query, mode: "insensitive" } }
694
+ ]
695
+ },
696
+ orderBy: { name: "asc" }
697
+ });
698
+ }
699
+ async function updateLocation(id, data) {
700
+ return prisma.location.update({
701
+ where: { id },
702
+ data
703
+ });
704
+ }
705
+ async function deleteLocation(id) {
706
+ return prisma.location.delete({
707
+ where: { id }
708
+ });
709
+ }
710
+ async function countLocations(where) {
711
+ return prisma.location.count({ where });
712
+ }
713
+ async function getLocationWithTournaments(id) {
714
+ return prisma.location.findUnique({
715
+ where: { id },
716
+ include: {
717
+ tournaments: {
718
+ orderBy: {
719
+ date: "desc"
720
+ }
721
+ }
722
+ }
723
+ });
724
+ }
616
725
  export {
617
726
  connect,
727
+ countLocations,
618
728
  countPlayers,
619
729
  countResults,
620
730
  countTournaments,
621
731
  countUsers,
732
+ createLocation,
622
733
  createManyResults,
623
734
  createPlayer,
624
735
  createResult,
625
736
  createTournament,
626
737
  createUser,
627
738
  createUserWithPlayer,
739
+ deleteLocation,
628
740
  deletePlayer,
629
741
  deleteResult,
630
742
  deleteResultsByTournament,
631
743
  deleteTournament,
632
744
  deleteUser,
633
745
  disconnect,
746
+ findLocationByExternalId,
747
+ findLocationById,
748
+ findLocations,
634
749
  findPlayerByExternalId,
635
750
  findPlayerById,
751
+ findPlayerByPlayerNumber,
636
752
  findPlayerByUserEmail,
637
753
  findPlayers,
638
754
  findResultById,
@@ -644,6 +760,8 @@ export {
644
760
  findUserByEmail,
645
761
  findUserById,
646
762
  findUsers,
763
+ generateUniquePlayerNumber,
764
+ getLocationWithTournaments,
647
765
  getMajorTournaments,
648
766
  getPlayerResults,
649
767
  getPlayerStats,
@@ -660,12 +778,15 @@ export {
660
778
  getTournamentsByDateRange,
661
779
  getUserByEmailWithPlayer,
662
780
  getUserWithPlayer,
781
+ isValidPlayerNumber,
663
782
  linkPlayerToUser,
664
783
  prisma,
665
784
  recalculateTimeDecay,
785
+ searchLocations,
666
786
  searchPlayers,
667
787
  searchTournaments,
668
788
  testConnection,
789
+ updateLocation,
669
790
  updatePlayer,
670
791
  updatePlayerRating,
671
792
  updateResult,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opprs/db-prisma",
3
- "version": "2.2.1-canary.ea6f686",
3
+ "version": "2.2.1-canary.f877650",
4
4
  "description": "Database backend for OPPR (Open Pinball Player Ranking System) using Prisma and PostgreSQL",
5
5
  "keywords": [
6
6
  "oppr",
@@ -56,7 +56,7 @@
56
56
  "vitest": "^4.0.16"
57
57
  },
58
58
  "peerDependencies": {
59
- "@opprs/core": "^2.2.1-canary.ea6f686"
59
+ "@opprs/core": "^2.2.1-canary.f877650"
60
60
  },
61
61
  "engines": {
62
62
  "node": ">=20.9.0"
@@ -0,0 +1,23 @@
1
+ -- AlterTable
2
+ -- First add playerNumber as nullable, populate it, then make it required
3
+ ALTER TABLE "Player" ADD COLUMN "playerNumber" INTEGER;
4
+
5
+ -- Populate existing players with unique 5-digit player numbers
6
+ -- Use a sequence starting from 10000, incrementing for each existing row
7
+ WITH numbered_players AS (
8
+ SELECT id, ROW_NUMBER() OVER (ORDER BY "createdAt") + 9999 AS num
9
+ FROM "Player"
10
+ )
11
+ UPDATE "Player"
12
+ SET "playerNumber" = numbered_players.num::INTEGER
13
+ FROM numbered_players
14
+ WHERE "Player".id = numbered_players.id;
15
+
16
+ -- Make the column required and add unique constraint
17
+ ALTER TABLE "Player" ALTER COLUMN "playerNumber" SET NOT NULL;
18
+
19
+ -- CreateIndex
20
+ CREATE UNIQUE INDEX "Player_playerNumber_key" ON "Player"("playerNumber");
21
+
22
+ -- CreateIndex
23
+ CREATE INDEX "Player_playerNumber_idx" ON "Player"("playerNumber");
@@ -0,0 +1,45 @@
1
+ -- CreateTable
2
+ CREATE TABLE "Location" (
3
+ "id" TEXT NOT NULL,
4
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
5
+ "updatedAt" TIMESTAMP(3) NOT NULL,
6
+ "externalId" TEXT,
7
+ "name" TEXT NOT NULL,
8
+ "address" TEXT,
9
+ "city" TEXT,
10
+ "state" TEXT,
11
+ "country" TEXT,
12
+
13
+ CONSTRAINT "Location_pkey" PRIMARY KEY ("id")
14
+ );
15
+
16
+ -- CreateIndex
17
+ CREATE UNIQUE INDEX "Location_externalId_key" ON "Location"("externalId");
18
+
19
+ -- CreateIndex
20
+ CREATE INDEX "Location_externalId_idx" ON "Location"("externalId");
21
+
22
+ -- CreateIndex
23
+ CREATE INDEX "Location_name_idx" ON "Location"("name");
24
+
25
+ -- CreateIndex
26
+ CREATE INDEX "Location_city_idx" ON "Location"("city");
27
+
28
+ -- AlterTable: Add new columns to Tournament
29
+ ALTER TABLE "Tournament" ADD COLUMN "description" VARCHAR(2000);
30
+ ALTER TABLE "Tournament" ADD COLUMN "locationId" TEXT;
31
+ ALTER TABLE "Tournament" ADD COLUMN "organizerId" TEXT;
32
+
33
+ -- DropColumn: Remove old location string column (replaced by Location relation)
34
+ ALTER TABLE "Tournament" DROP COLUMN IF EXISTS "location";
35
+
36
+ -- CreateIndex for new Tournament columns
37
+ CREATE INDEX "Tournament_locationId_idx" ON "Tournament"("locationId");
38
+
39
+ CREATE INDEX "Tournament_organizerId_idx" ON "Tournament"("organizerId");
40
+
41
+ -- AddForeignKey: Tournament -> Location
42
+ ALTER TABLE "Tournament" ADD CONSTRAINT "Tournament_locationId_fkey" FOREIGN KEY ("locationId") REFERENCES "Location"("id") ON DELETE SET NULL ON UPDATE CASCADE;
43
+
44
+ -- AddForeignKey: Tournament -> Player (organizer)
45
+ ALTER TABLE "Tournament" ADD CONSTRAINT "Tournament_organizerId_fkey" FOREIGN KEY ("organizerId") REFERENCES "Player"("id") ON DELETE SET NULL ON UPDATE CASCADE;
@@ -18,6 +18,7 @@ model Player {
18
18
 
19
19
  // Player identification
20
20
  externalId String? @unique // External ID from OPPR or other systems
21
+ playerNumber Int @unique // 5-digit unique identifier (10000-99999)
21
22
  name String?
22
23
 
23
24
  // OPPR Rating fields
@@ -32,10 +33,12 @@ model Player {
32
33
  lastEventDate DateTime?
33
34
 
34
35
  // Relations
35
- tournamentResults TournamentResult[]
36
- user User?
36
+ tournamentResults TournamentResult[]
37
+ user User?
38
+ organizedTournaments Tournament[] @relation("OrganizedTournaments")
37
39
 
38
40
  @@index([externalId])
41
+ @@index([playerNumber])
39
42
  @@index([rating])
40
43
  @@index([ranking])
41
44
  }
@@ -49,9 +52,17 @@ model Tournament {
49
52
  // Tournament identification
50
53
  externalId String? @unique // External ID from OPPR or other systems
51
54
  name String
52
- location String?
55
+ description String? @db.VarChar(2000)
53
56
  date DateTime
54
57
 
58
+ // Location relation
59
+ locationId String?
60
+ location Location? @relation(fields: [locationId], references: [id], onDelete: SetNull)
61
+
62
+ // Organizer relation
63
+ organizerId String?
64
+ organizer Player? @relation("OrganizedTournaments", fields: [organizerId], references: [id], onDelete: SetNull)
65
+
55
66
  // Tournament configuration (stored as JSON)
56
67
  // Contains TGPConfig structure from OPPR
57
68
  tgpConfig Json?
@@ -75,6 +86,8 @@ model Tournament {
75
86
  @@index([date])
76
87
  @@index([eventBooster])
77
88
  @@index([externalId])
89
+ @@index([locationId])
90
+ @@index([organizerId])
78
91
  }
79
92
 
80
93
  // Tournament Result - junction table linking players to tournaments
@@ -149,3 +162,24 @@ model User {
149
162
 
150
163
  @@index([email])
151
164
  }
165
+
166
+ // Location model - represents a venue where tournaments are held
167
+ model Location {
168
+ id String @id @default(cuid())
169
+ createdAt DateTime @default(now())
170
+ updatedAt DateTime @updatedAt
171
+
172
+ externalId String? @unique
173
+ name String
174
+ address String?
175
+ city String?
176
+ state String?
177
+ country String?
178
+
179
+ // Relations
180
+ tournaments Tournament[]
181
+
182
+ @@index([externalId])
183
+ @@index([name])
184
+ @@index([city])
185
+ }
package/prisma/seed.ts CHANGED
@@ -13,6 +13,7 @@ async function main() {
13
13
  const playerData = [
14
14
  {
15
15
  externalId: 'player-1',
16
+ playerNumber: 10001,
16
17
  name: 'Alice Champion',
17
18
  rating: 1850,
18
19
  ratingDeviation: 50,
@@ -22,6 +23,7 @@ async function main() {
22
23
  },
23
24
  {
24
25
  externalId: 'player-2',
26
+ playerNumber: 10002,
25
27
  name: 'Bob Wizard',
26
28
  rating: 1750,
27
29
  ratingDeviation: 60,
@@ -31,6 +33,7 @@ async function main() {
31
33
  },
32
34
  {
33
35
  externalId: 'player-3',
36
+ playerNumber: 10003,
34
37
  name: 'Charlie Flipper',
35
38
  rating: 1650,
36
39
  ratingDeviation: 75,
@@ -40,6 +43,7 @@ async function main() {
40
43
  },
41
44
  {
42
45
  externalId: 'player-4',
46
+ playerNumber: 10004,
43
47
  name: 'Diana Tilt',
44
48
  rating: 1550,
45
49
  ratingDeviation: 100,
@@ -49,6 +53,7 @@ async function main() {
49
53
  },
50
54
  {
51
55
  externalId: 'player-5',
56
+ playerNumber: 10005,
52
57
  name: 'Eve Plunger',
53
58
  rating: 1300,
54
59
  ratingDeviation: 150,
@@ -144,13 +149,71 @@ async function main() {
144
149
 
145
150
  console.log(`✓ Created admin user (admin@example.com / ${adminPassword})`);
146
151
 
152
+ // Create sample locations (using upsert for idempotency)
153
+ console.log('Creating locations...');
154
+
155
+ const location1 = await prisma.location.upsert({
156
+ where: { externalId: 'location-1' },
157
+ update: {
158
+ name: 'Las Vegas Convention Center',
159
+ city: 'Las Vegas',
160
+ state: 'NV',
161
+ country: 'USA',
162
+ },
163
+ create: {
164
+ externalId: 'location-1',
165
+ name: 'Las Vegas Convention Center',
166
+ city: 'Las Vegas',
167
+ state: 'NV',
168
+ country: 'USA',
169
+ },
170
+ });
171
+
172
+ const location2 = await prisma.location.upsert({
173
+ where: { externalId: 'location-2' },
174
+ update: {
175
+ name: 'Ground Kontrol',
176
+ address: '115 NW 5th Ave',
177
+ city: 'Portland',
178
+ state: 'OR',
179
+ country: 'USA',
180
+ },
181
+ create: {
182
+ externalId: 'location-2',
183
+ name: 'Ground Kontrol',
184
+ address: '115 NW 5th Ave',
185
+ city: 'Portland',
186
+ state: 'OR',
187
+ country: 'USA',
188
+ },
189
+ });
190
+
191
+ const location3 = await prisma.location.upsert({
192
+ where: { externalId: 'location-3' },
193
+ update: {
194
+ name: 'Add-a-Ball Amusements',
195
+ city: 'Seattle',
196
+ state: 'WA',
197
+ country: 'USA',
198
+ },
199
+ create: {
200
+ externalId: 'location-3',
201
+ name: 'Add-a-Ball Amusements',
202
+ city: 'Seattle',
203
+ state: 'WA',
204
+ country: 'USA',
205
+ },
206
+ });
207
+
208
+ console.log(`✓ Created ${await prisma.location.count()} locations`);
209
+
147
210
  // Create sample tournaments (using upsert for idempotency)
148
211
  console.log('Creating tournaments...');
149
212
 
150
213
  const tournament1Data = {
151
214
  externalId: 'tournament-1',
152
215
  name: 'World Pinball Championship 2024',
153
- location: 'Las Vegas, NV',
216
+ locationId: location1.id,
154
217
  date: new Date('2024-03-15'),
155
218
  eventBooster: EventBoosterType.MAJOR,
156
219
  allowsOptOut: false,
@@ -186,7 +249,7 @@ async function main() {
186
249
  const tournament2Data = {
187
250
  externalId: 'tournament-2',
188
251
  name: 'Spring Classics 2024',
189
- location: 'Portland, OR',
252
+ locationId: location2.id,
190
253
  date: new Date('2024-04-20'),
191
254
  eventBooster: EventBoosterType.CERTIFIED,
192
255
  allowsOptOut: true,
@@ -220,7 +283,7 @@ async function main() {
220
283
  const tournament3Data = {
221
284
  externalId: 'tournament-3',
222
285
  name: 'Monthly League Finals',
223
- location: 'Seattle, WA',
286
+ locationId: location3.id,
224
287
  date: new Date('2024-05-10'),
225
288
  eventBooster: EventBoosterType.NONE,
226
289
  allowsOptOut: false,
@@ -423,6 +486,7 @@ async function main() {
423
486
  console.log('Summary:');
424
487
  console.log(` - ${await prisma.player.count()} players`);
425
488
  console.log(` - ${await prisma.user.count()} users`);
489
+ console.log(` - ${await prisma.location.count()} locations`);
426
490
  console.log(` - ${await prisma.tournament.count()} tournaments`);
427
491
  console.log(` - ${await prisma.tournamentResult.count()} tournament results`);
428
492
  }